results_panel.dart 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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: 20, top: 2, right: 20, 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.all(8),
  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. const FSizedBox(height: 6),
  118. _buildTitle(application.applicationName),
  119. _buildTitleDivider(),
  120. ];
  121. for (var line in lines) {
  122. list.add(_buildLine(line));
  123. }
  124. return list;
  125. }
  126. FWidget _buildLine(ResultLine result) {
  127. return FRow(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
  128. FText(
  129. result.label,
  130. style: TextStyle(
  131. fontSize: measureData.measureSystemSetting.fontSize.toDouble(),
  132. color: MeasureColors.Primary,
  133. ),
  134. ),
  135. const FSizedBox(width: 8),
  136. FText(
  137. result.value ?? '',
  138. style: TextStyle(
  139. fontSize: measureData.measureSystemSetting.fontSize.toDouble(),
  140. color: MeasureColors.Primary,
  141. ),
  142. ),
  143. ]);
  144. }
  145. FWidget _buildTitle(String title) {
  146. return FText(
  147. title,
  148. style: TextStyle(
  149. fontSize: measureData.measureSystemSetting.fontSize.toDouble() - 2,
  150. color: MeasureColors.Primary,
  151. ),
  152. );
  153. }
  154. FWidget _buildTitleDivider() {
  155. return const FDivider(
  156. color: Colors.white,
  157. height: 0.5,
  158. endIndent: 2,
  159. );
  160. }
  161. void _onMeasureRerenderReady(Object sender, void e) {
  162. if (mounted) {
  163. setState(() {
  164. _updateOutputs();
  165. _autoScrollToBottom();
  166. });
  167. }
  168. }
  169. void _updateOutputs() {
  170. lines.clear();
  171. final features = <IMeasureItemFeature>[];
  172. for (var item in application.measureItems) {
  173. if (item.measuredFeatures.isNotEmpty) {
  174. features.addAll(item.measuredFeatures);
  175. }
  176. if (item.feature != null) {
  177. features.add(item.feature!);
  178. }
  179. }
  180. final idLength = features.length.toString().length;
  181. for (var feature in features) {
  182. final strList = FeatureValueDescConverter(feature).generate(idLength);
  183. lines.addAll(strList);
  184. }
  185. }
  186. void _autoScrollToBottom() {
  187. if (lines.isEmpty) return;
  188. Future.delayed(const Duration(milliseconds: 200), () {
  189. if (_scrollController.hasClients) {
  190. _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
  191. }
  192. });
  193. }
  194. }
  195. class ResultLine {
  196. ResultLine({required this.label, this.value});
  197. String label;
  198. String? value;
  199. bool get isNotEmpty => value != null && value!.isNotEmpty && label.isNotEmpty;
  200. @override
  201. String toString() => '$label $value';
  202. }