mouse_gesture.dart 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import 'package:fis_i18n/i18n.dart';
  2. import 'package:fis_measure/interfaces/date_types/point.dart';
  3. import 'package:fis_measure/interfaces/date_types/rect.dart';
  4. import 'package:fis_measure/interfaces/date_types/rect_region.dart';
  5. import 'package:fis_measure/interfaces/enums/items.dart';
  6. import 'package:fis_measure/interfaces/process/items/item.dart';
  7. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  8. import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
  9. import 'package:fis_measure/process/items/top_item.dart';
  10. import 'package:fis_measure/process/workspace/measure_handler.dart';
  11. import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
  12. import 'package:fis_ui/index.dart';
  13. import 'package:flutter/gestures.dart';
  14. import 'package:flutter/material.dart';
  15. import 'package:get/get.dart';
  16. import 'package:vid/us/vid_us_visual_area_type.dart';
  17. import 'positioned_cursor.dart';
  18. class MeasureMouseGesturePanel extends StatefulWidget {
  19. const MeasureMouseGesturePanel({Key? key}) : super(key: key);
  20. @override
  21. State<StatefulWidget> createState() => _MeasureMouseGesturePanelState();
  22. }
  23. class _MeasureMouseGesturePanelState extends State<MeasureMouseGesturePanel> {
  24. Offset? mousePosition;
  25. Offset? cursorPosition;
  26. final mouseState = Get.find<IMouseState>();
  27. late final application = Get.find<IApplication>();
  28. late final measureHandler = Get.find<MeasureHandler>();
  29. bool ifContainerTissueTM = false;
  30. CursorDisplayType displayType = CursorDisplayType.none;
  31. RectRegion tissueTMPixelRegion = RectRegion();
  32. bool isShowRightClickTip = false;
  33. late IMeasureItem? currMeasureItem;
  34. @override
  35. void initState() {
  36. _findMultiRegions();
  37. application.displaySizeChanged.addListener(_onResize);
  38. application.activeMeasureItemChanged
  39. .addListener(_onActiveMeasureItemChanged);
  40. currMeasureItem = application.activeMeasureItem;
  41. if (currMeasureItem != null) {
  42. currMeasureItem!.onItemStatesChanged.addListener(_onItemStatesChanged);
  43. }
  44. super.initState();
  45. }
  46. @override
  47. void dispose() {
  48. application.displaySizeChanged.removeListener(_onResize);
  49. application.activeMeasureItemChanged
  50. .removeListener(_onActiveMeasureItemChanged);
  51. if (currMeasureItem != null) {
  52. currMeasureItem!.onItemStatesChanged.removeListener(_onItemStatesChanged);
  53. }
  54. super.dispose();
  55. }
  56. @override
  57. Widget build(BuildContext context) {
  58. return Listener(
  59. onPointerDown: _rightClickListener,
  60. child: GestureDetector(
  61. onTapDown: (details) {
  62. application.createPointInfo(
  63. details.localPosition,
  64. PointInfoType.mouseDown,
  65. );
  66. },
  67. onPanDown: (details) {
  68. // application.createPointInfo(
  69. // details.localPosition,
  70. // PointInfoType.mouseDown,
  71. // );
  72. },
  73. onPanUpdate: (details) {
  74. mouseState.mousePosition = details.localPosition;
  75. application.createPointInfo(
  76. details.localPosition,
  77. PointInfoType.mouseMove,
  78. );
  79. },
  80. child: MouseRegion(
  81. cursor: SystemMouseCursors.none,
  82. onHover: (event) {
  83. mouseState.mousePosition = event.localPosition;
  84. application.createPointInfo(
  85. event.localPosition,
  86. PointInfoType.mouseMove,
  87. );
  88. _handleAreaChange(event.localPosition);
  89. },
  90. onEnter: (e) {
  91. setState(() {
  92. displayType = CursorDisplayType.normal;
  93. });
  94. },
  95. onExit: (e) {
  96. setState(() {
  97. displayType = CursorDisplayType.none;
  98. });
  99. },
  100. child: Stack(
  101. children: [
  102. _buildCursor(),
  103. if (isShowRightClickTip && displayType != CursorDisplayType.none)
  104. _buildTip(),
  105. ],
  106. ),
  107. ),
  108. ),
  109. );
  110. }
  111. Widget _buildCursor() {
  112. switch (displayType) {
  113. case CursorDisplayType.none:
  114. return Container();
  115. case CursorDisplayType.normal:
  116. return const PositionedCursor();
  117. case CursorDisplayType.cross:
  118. return CrossIndicator(
  119. areaRegion: Rect.fromLTRB(
  120. tissueTMPixelRegion.left,
  121. tissueTMPixelRegion.top,
  122. tissueTMPixelRegion.right,
  123. tissueTMPixelRegion.bottom),
  124. );
  125. }
  126. }
  127. /// 右键右上角角标
  128. FWidget _buildTip() {
  129. return FPositioned(
  130. top: 0,
  131. right: 100,
  132. child: FContainer(
  133. height: 24,
  134. margin: const EdgeInsets.all(5),
  135. padding: const EdgeInsets.all(5),
  136. decoration: const BoxDecoration(
  137. color: Color.fromRGBO(71, 71, 71, 1),
  138. borderRadius: BorderRadius.all(Radius.circular(5)),
  139. ),
  140. child: FRow(children: [
  141. const FIcon(
  142. Icons.error_outline,
  143. color: Colors.white,
  144. size: 14,
  145. ),
  146. const FSizedBox(width: 5),
  147. FFittedBox(
  148. fit: BoxFit.fitHeight,
  149. child: FText(
  150. i18nBook.measure.rightClickToCancel.t,
  151. style: const TextStyle(
  152. height: 1,
  153. fontSize: 20,
  154. color: Color.fromRGBO(213, 213, 213, 1)),
  155. ),
  156. ),
  157. ]),
  158. ),
  159. );
  160. }
  161. void _onResize(_, e) {
  162. _findMultiRegions();
  163. WidgetsBinding.instance.addPostFrameCallback((_) {
  164. _setScaleRatio();
  165. });
  166. }
  167. /// 同步缩放比
  168. void _setScaleRatio() {
  169. mouseState.cursorScaleRatio = application.displayScaleRatio;
  170. }
  171. void _onActiveMeasureItemChanged(_, IMeasureItem? e) {
  172. if (e == null) return;
  173. if (currMeasureItem != null) {
  174. currMeasureItem!.onItemStatesChanged.removeListener(_onItemStatesChanged);
  175. }
  176. /// 组合测量项看成一个整体
  177. if (e is TopMeasureItem) {
  178. setState(() {
  179. isShowRightClickTip = true;
  180. });
  181. }
  182. currMeasureItem = e;
  183. currMeasureItem!.onItemStatesChanged.addListener(_onItemStatesChanged);
  184. }
  185. void _onItemStatesChanged(_, ItemStates? e) {
  186. if (e == ItemStates.running) {
  187. setState(() {
  188. isShowRightClickTip = true;
  189. });
  190. } else {
  191. setState(() {
  192. isShowRightClickTip = false;
  193. });
  194. }
  195. }
  196. void _handleAreaChange(Offset pointerOffset) {
  197. if (ifContainerTissueTM) {
  198. if (tissueTMPixelRegion
  199. .containsPoint(DPoint.parseOffset(pointerOffset))) {
  200. if (displayType != CursorDisplayType.cross) {
  201. setState(() {
  202. displayType = CursorDisplayType.cross;
  203. });
  204. }
  205. } else {
  206. if (displayType != CursorDisplayType.normal) {
  207. setState(() {
  208. displayType = CursorDisplayType.normal;
  209. });
  210. }
  211. }
  212. }
  213. }
  214. void _findMultiRegions() {
  215. final displaySize = application.displaySize;
  216. for (var visual in application.visuals) {
  217. for (var area in visual.visualAreas) {
  218. if (area.visualAreaType == VidUsVisualAreaType.TissueTimeMotion ||
  219. area.visualAreaType == VidUsVisualAreaType.Doppler) {
  220. ifContainerTissueTM = true;
  221. ///TODO 由于布局问题 Left 定位给不准,这里放宽到边界
  222. tissueTMPixelRegion = RectRegion.rect(DRect(
  223. // area.displayRegion.left * displaySize.width,
  224. 0,
  225. area.displayRegion.top * displaySize.height,
  226. // area.displayRegion.width * displaySize.width,
  227. displaySize.width,
  228. area.displayRegion.height * displaySize.height,
  229. ));
  230. }
  231. }
  232. }
  233. }
  234. /// 鼠标右键监听
  235. void _rightClickListener(PointerDownEvent event) {
  236. if (event.kind == PointerDeviceKind.mouse &&
  237. event.buttons == kSecondaryMouseButton) {
  238. measureHandler.onRightClickFinishMeasure.emit(this, true);
  239. setState(() {
  240. isShowRightClickTip = false;
  241. });
  242. }
  243. }
  244. }
  245. enum CursorDisplayType {
  246. none,
  247. cross,
  248. normal,
  249. }