results_panel.dart 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import 'dart:ui' as ui;
  2. import 'package:fis_measure/interfaces/process/items/item_feature.dart';
  3. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  4. import 'package:fis_measure/process/workspace/measure_data_controller.dart';
  5. import 'package:fis_measure/values/colors.dart';
  6. import 'package:fis_ui/index.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:get/get.dart';
  9. import 'converter.dart';
  10. class MeasureResultPanel extends StatefulWidget {
  11. const MeasureResultPanel({Key? key}) : super(key: key);
  12. @override
  13. State<StatefulWidget> createState() => _MeasureResultPanelState();
  14. }
  15. class _MeasureResultPanelState extends State<MeasureResultPanel> {
  16. final _scrollController = ScrollController();
  17. final application = Get.find<IApplication>();
  18. final measureData = Get.find<MeasureDataController>();
  19. final List<ResultLine> lines = [];
  20. bool get hasOutputs => lines.isNotEmpty;
  21. @override
  22. Widget build(BuildContext context) {
  23. if (!hasOutputs || !measureData.measureSystemSetting.showResultWindow) {
  24. return const SizedBox();
  25. }
  26. return Align(
  27. alignment: _getAlignmentFromLocation(
  28. measureData.measureSystemSetting.showResultLocation),
  29. child: Container(
  30. margin: const EdgeInsets.only(left: 2, top: 2, right: 2, bottom: 2),
  31. constraints: const BoxConstraints(
  32. maxWidth: 600,
  33. minWidth: 150,
  34. maxHeight: 400,
  35. ),
  36. decoration: BoxDecoration(
  37. border: Border.all(
  38. color: MeasureColors.ResultBorder,
  39. width: 2,
  40. ),
  41. borderRadius: BorderRadius.circular(4),
  42. color: Colors.black.withOpacity(0.7),
  43. ),
  44. // padding: const EdgeInsets.only(left: 2),
  45. child: FThemeWidget(
  46. data: Theme.of(context).copyWith(
  47. scrollbarTheme: ScrollbarThemeData(
  48. thumbColor: MaterialStateProperty.all(
  49. MeasureColors.ResultScrollbar,
  50. ),
  51. crossAxisMargin: 1,
  52. ),
  53. ),
  54. child: FScrollbar(
  55. isAlwaysShown: false,
  56. controller: _scrollController,
  57. radius: ui.Radius.zero,
  58. child: FSingleChildScrollView(
  59. controller: _scrollController,
  60. child: FRepaintBoundary(
  61. child: FIntrinsicHeight(
  62. child: FIntrinsicWidth(
  63. child: FContainer(
  64. margin: const EdgeInsets.fromLTRB(5, 1, 5, 5),
  65. child: FColumn(
  66. mainAxisSize: MainAxisSize.min,
  67. crossAxisAlignment: CrossAxisAlignment.start,
  68. children: _buildMainList(),
  69. ),
  70. ),
  71. ),
  72. ),
  73. ),
  74. ),
  75. ),
  76. ),
  77. ),
  78. );
  79. }
  80. @override
  81. void initState() {
  82. _updateOutputs();
  83. application.updateRenderReady.addListener(_onMeasureRerenderReady);
  84. measureData.measureSystemSettingChanged
  85. .addListener(_onMeasureSystemSettingChanged);
  86. super.initState();
  87. }
  88. @override
  89. void dispose() {
  90. application.updateRenderReady.removeListener(_onMeasureRerenderReady);
  91. measureData.measureSystemSettingChanged
  92. .removeListener(_onMeasureSystemSettingChanged);
  93. super.dispose();
  94. }
  95. /// 样式更新事件监听
  96. void _onMeasureSystemSettingChanged(_, e) {
  97. _updateOutputs();
  98. setState(() {});
  99. }
  100. /// 面板对齐方式
  101. Alignment _getAlignmentFromLocation(int locationNum) {
  102. switch (locationNum) {
  103. case 0:
  104. return Alignment.topLeft;
  105. case 1:
  106. return Alignment.bottomLeft;
  107. case 2:
  108. return Alignment.topRight;
  109. case 3:
  110. return Alignment.bottomRight;
  111. default:
  112. return Alignment.topLeft;
  113. }
  114. }
  115. List<FWidget> _buildMainList() {
  116. final list = <FWidget>[
  117. _buildTitle(application.applicationName),
  118. _buildTitleDivider(),
  119. ];
  120. for (var line in lines) {
  121. list.add(_buildLine(line));
  122. }
  123. return list;
  124. }
  125. FWidget _buildLine(ResultLine result) {
  126. return FRow(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
  127. FText(
  128. result.label,
  129. style: TextStyle(
  130. fontSize: measureData.measureSystemSetting.fontSize.toDouble(),
  131. color: MeasureColors.Primary,
  132. ),
  133. ),
  134. const FSizedBox(width: 8),
  135. FText(
  136. result.value ?? '',
  137. style: TextStyle(
  138. fontSize: measureData.measureSystemSetting.fontSize.toDouble(),
  139. color: MeasureColors.Primary,
  140. ),
  141. ),
  142. ]);
  143. }
  144. FWidget _buildTitle(String title) {
  145. return FText(
  146. title,
  147. style: TextStyle(
  148. fontSize: measureData.measureSystemSetting.fontSize.toDouble() - 2,
  149. color: MeasureColors.Primary,
  150. ),
  151. );
  152. }
  153. FWidget _buildTitleDivider() {
  154. return const FDivider(
  155. color: Colors.white,
  156. height: 0.5,
  157. endIndent: 2,
  158. );
  159. }
  160. void _onMeasureRerenderReady(Object sender, void e) {
  161. if (mounted) {
  162. setState(() {
  163. _updateOutputs();
  164. _autoScrollToBottom();
  165. });
  166. }
  167. }
  168. void _updateOutputs() {
  169. lines.clear();
  170. final features = <IMeasureItemFeature>[];
  171. for (var item in application.measureItems) {
  172. if (item.measuredFeatures.isNotEmpty) {
  173. features.addAll(item.measuredFeatures);
  174. }
  175. if (item.feature != null) {
  176. features.add(item.feature!);
  177. }
  178. }
  179. final idLength = features.length.toString().length;
  180. for (var feature in features) {
  181. final strList = FeatureValueDescConverter(feature).generate(idLength);
  182. lines.addAll(strList);
  183. }
  184. }
  185. void _autoScrollToBottom() {
  186. if (lines.isEmpty) return;
  187. Future.delayed(const Duration(milliseconds: 200), () {
  188. if (_scrollController.hasClients) {
  189. _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
  190. }
  191. });
  192. }
  193. }
  194. class ResultLine {
  195. ResultLine({required this.label, this.value});
  196. String label;
  197. String? value;
  198. bool get isNotEmpty => value != null && value!.isNotEmpty && label.isNotEmpty;
  199. @override
  200. String toString() => '$label $value';
  201. }