Bladeren bron

update(mobile): 完成箭头注释的适配

gavin.chen 2 jaren geleden
bovenliggende
commit
9fea68893e

+ 47 - 2
lib/process/annotations/arrow_annotation.dart

@@ -39,10 +39,55 @@ class ArrowAnnotation extends AnnotationItem<ArrowAnnotationItemFeature> {
     return true;
   }
 
+  PointInfo? startPoint;
   @override
   bool onExecuteTouch(PointInfo args) {
-    // TODO: implement onExecuteTouch
-    throw UnimplementedError();
+    print("【${args.pointType}】");
+    if (state == AnnotationStates.finish) {
+      if (args.pointType == PointInfoType.touchDown) {
+        state = AnnotationStates.waiting;
+      }
+    }
+    if (state == AnnotationStates.waiting) {
+      switch (args.pointType) {
+        case PointInfoType.touchDown:
+          startPoint = args; // 设置线段起点
+          break;
+        case PointInfoType.touchUp:
+          break; // 按下立即抬起无事发生
+        case PointInfoType.touchMove:
+          feature = ArrowAnnotationItemFeature(this, startPoint as DPoint);
+          state = AnnotationStates.running; // 通过设置的起点开始一个绘制事件
+          break;
+        default:
+          break;
+      }
+    } else if (state == AnnotationStates.running) {
+      if (args.pointType == PointInfoType.touchUp) {
+        doFeatureFinish();
+      }
+      if (args.pointType == PointInfoType.touchMove) {
+        feature?.endPoint = args;
+      }
+    }
+    // if (state == AnnotationStates.waiting) {
+    //   if (args.pointType == PointInfoType.mouseDown) {
+    //     feature = ArrowAnnotationItemFeature(this, args);
+    //     state = AnnotationStates.running;
+    //     return true;
+    //   } else {
+    //     return false;
+    //   }
+    // } else {
+    //   if (args.pointType == PointInfoType.mouseUp) return false;
+
+    //   feature?.endPoint = args;
+    //   if (args.pointType == PointInfoType.mouseDown) {
+    //     doFeatureFinish();
+    //   }
+    // }
+
+    return true;
   }
 }
 

+ 48 - 0
lib/view/gesture/mobile_annotation/arrow_gesture_panel.dart

@@ -0,0 +1,48 @@
+import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+import '../positioned_cursor.dart';
+
+/// 箭头注释手势面板
+class AnnotationArrowGesturePanel extends StatefulWidget {
+  const AnnotationArrowGesturePanel({Key? key}) : super(key: key);
+
+  @override
+  State<AnnotationArrowGesturePanel> createState() => _PanelState();
+}
+
+class _PanelState extends State<AnnotationArrowGesturePanel> {
+  late final application = Get.find<IApplication>();
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(onTapDown: (details) {
+      application.createPointInfo(
+        details.localPosition,
+        PointInfoType.touchDown,
+      );
+    }, onPanDown: (details) {
+      application.createPointInfo(
+        details.localPosition,
+        PointInfoType.touchDown,
+      );
+    }, onPanUpdate: (details) {
+      application.createPointInfo(
+        details.localPosition,
+        PointInfoType.touchMove,
+      );
+    }, onTapUp: (details) {
+      application.createPointInfo(
+        details.localPosition,
+        PointInfoType.touchUp,
+      );
+    }, onPanEnd: (details) {
+      application.createPointInfo(
+        Offset.zero,
+        PointInfoType.touchUp,
+      );
+    });
+  }
+}

+ 113 - 0
lib/view/gesture/mobile_annotation/input_position_panel.dart

@@ -0,0 +1,113 @@
+// ignore_for_file: constant_identifier_names
+
+import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:fis_measure/values/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+import '../positioned_cursor.dart';
+
+/// 自定义注释文本框定位面板
+class AnnotationInputPositionPanel extends StatefulWidget {
+  const AnnotationInputPositionPanel({Key? key}) : super(key: key);
+
+  @override
+  State<AnnotationInputPositionPanel> createState() => _PanelState();
+}
+
+class _PanelState extends State<AnnotationInputPositionPanel> {
+  late final application = Get.find<IApplication>();
+  final mouseState = Get.find<IMouseState>();
+
+  Offset? position;
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onPanDown: (details) {
+        setState(() {
+          position = details.localPosition;
+          application.createPointInfo(position!, PointInfoType.mouseDown);
+        });
+      },
+      child: MouseRegion(
+        cursor: SystemMouseCursors.none,
+        onHover: (event) {
+          mouseState.mousePosition = event.localPosition +
+              const Offset(
+                _InputWidget.C_MIN_WIDTH / 2,
+                _InputWidget.C_MAX_HEIGHT / 2,
+              );
+        },
+        child: Stack(
+          children: [
+            if (position != null)
+              Positioned(
+                child: _InputWidget(
+                  key: UniqueKey(),
+                  onChanged: (value) {
+                    application.activeAnnotationItem?.text = value;
+                  },
+                ),
+                left: position!.dx,
+                top: position!.dy,
+              ),
+            const PositionedCursor(),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+typedef _InputValueChanged = void Function(String value);
+
+class _InputWidget extends StatelessWidget {
+  static const C_BG_COLOR = Color.fromARGB(255, 121, 135, 151);
+  static const C_MIN_WIDTH = 40.0;
+  static const C_MAX_HEIGHT = 28.0;
+
+  final FocusNode? focusNode;
+  final _InputValueChanged onChanged;
+
+  const _InputWidget({
+    required this.onChanged,
+    Key? key,
+    this.focusNode,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    const border = OutlineInputBorder(
+      borderSide: BorderSide(color: C_BG_COLOR),
+      borderRadius: BorderRadius.all(Radius.circular(4.0)),
+    );
+    final input = TextField(
+      expands: false,
+      autofocus: true,
+      focusNode: focusNode,
+      style: const TextStyle(color: MeasureColors.Primary),
+      cursorColor: MeasureColors.Primary,
+      cursorWidth: 1.0,
+      onChanged: onChanged,
+      decoration: const InputDecoration(
+        border: border,
+        enabledBorder: border,
+        focusedBorder: border,
+        counterText: '',
+        filled: true,
+        fillColor: C_BG_COLOR,
+        isCollapsed: false,
+        contentPadding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
+        constraints:
+            BoxConstraints(minWidth: C_MIN_WIDTH, maxHeight: C_MAX_HEIGHT),
+      ),
+    );
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 1),
+      alignment: Alignment.topLeft,
+      child: IntrinsicWidth(child: input),
+    );
+  }
+}

+ 85 - 0
lib/view/gesture/mobile_annotation/label_drag_target_pannel.dart

@@ -0,0 +1,85 @@
+import 'package:fis_measure/interfaces/enums/annotation.dart';
+import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+import '../positioned_cursor.dart';
+
+/// 文本注释拖拽目标面板
+class AnnotationLabelDragTargetPanel extends StatefulWidget {
+  const AnnotationLabelDragTargetPanel({Key? key}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() => _PanelState();
+}
+
+class _PanelState extends State<AnnotationLabelDragTargetPanel> {
+  late final application = Get.find<IApplication>();
+  final mouseState = Get.find<IMouseState>();
+
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      // color: Colors.green,
+      child: DragTarget<String>(
+        builder: (context, candidateData, rejectedData) {
+          return GestureDetector(
+            onPanDown: (details) {
+              application.createPointInfo(
+                details.localPosition,
+                PointInfoType.mouseDown,
+              );
+              application.switchAnnotation(AnnotationType.input);
+            },
+            child: MouseRegion(
+              cursor: SystemMouseCursors.none,
+              onHover: (event) {
+                mouseState.mousePosition = event.localPosition;
+              },
+              child: Stack(
+                children: const [
+                  PositionedCursor(),
+                ],
+              ),
+            ),
+          );
+        },
+        onMove: (details) {
+          _notifyPosition(context, details.offset, PointInfoType.mouseMove);
+        },
+        onAcceptWithDetails: (details) {
+          _notifyPosition(context, details.offset, PointInfoType.mouseUp);
+        },
+      ),
+    );
+  }
+
+  void _notifyPosition(
+    BuildContext context,
+    Offset offset,
+    PointInfoType type,
+  ) {
+    final localOffset = _findLocalPosition(context, offset);
+    mouseState.mousePosition = localOffset;
+    application.createPointInfo(localOffset, type);
+  }
+
+  Offset _findLocalPosition(BuildContext context, Offset globalPosition) {
+    final renderBox = context.findRenderObject() as RenderBox?;
+    if (renderBox == null) return globalPosition;
+    return renderBox.globalToLocal(globalPosition);
+  }
+
+  @override
+  void dispose() {
+    // TODO: implement dispose
+    super.dispose();
+  }
+}

+ 97 - 0
lib/view/gesture/mobile_annotation/mobile_annotation_gesture.dart

@@ -0,0 +1,97 @@
+import 'package:fis_measure/interfaces/enums/annotation.dart';
+import 'package:fis_measure/interfaces/process/annotations/annotation.dart';
+import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+import '../positioned_cursor.dart';
+import 'arrow_gesture_panel.dart';
+import 'input_position_panel.dart';
+import 'label_drag_target_pannel.dart';
+
+/// 移动端注释手势层
+class AnnotationTouchLayer extends StatefulWidget {
+  const AnnotationTouchLayer({Key? key}) : super(key: key);
+
+  @override
+  State<AnnotationTouchLayer> createState() => _AnnotationTouchLayerState();
+}
+
+class _AnnotationTouchLayerState extends State<AnnotationTouchLayer> {
+  late final application = Get.find<IApplication>();
+
+  final mouseState = Get.put<IMouseState>(MouseState());
+
+  IAnnotationItem? currentItem;
+
+  @override
+  void initState() {
+    currentItem = application.activeAnnotationItem;
+    application.activeAnnotationItemChanged.addListener(_onItemChanged);
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    application.activeAnnotationItemChanged.removeListener(_onItemChanged);
+    super.dispose();
+  }
+
+  void _onItemChanged(Object sender, IAnnotationItem? item) {
+    if (!mounted) return;
+
+    if (item?.type != currentItem?.type) {
+      setState(() {
+        currentItem = item;
+      });
+    } else {
+      currentItem = item;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return _buildItemPanel();
+    // // TODO: melon - optimize with handlers
+    // return Stack(
+    //   children: [
+    //     _buildItemPanel(),
+    //     _buildTopGesture(),
+    //   ],
+    // );
+  }
+
+  // Widget _buildTopGesture() {
+  //   return GestureDetector(
+  //     onPanUpdate: (details) {
+  //       mouseState.mousePosition = details.localPosition;
+  //     },
+  //     child: MouseRegion(
+  //       cursor: SystemMouseCursors.none,
+  //       onHover: (details) {
+  //         mouseState.mousePosition = details.localPosition;
+  //       },
+  //       child: Stack(
+  //         children: const [
+  //           PositionedCursor(),
+  //         ],
+  //       ),
+  //     ),
+  //   );
+  // }
+
+  Widget _buildItemPanel() {
+    if (currentItem == null) {
+      return const SizedBox();
+    }
+    final type = currentItem!.type;
+    switch (type) {
+      case AnnotationType.label:
+        return const AnnotationLabelDragTargetPanel();
+      case AnnotationType.input:
+        return const AnnotationInputPositionPanel();
+      case AnnotationType.arrow:
+        return const AnnotationArrowGesturePanel();
+    }
+  }
+}

+ 0 - 2
lib/view/gesture/touch_gesture.dart

@@ -3,8 +3,6 @@ import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 
-import 'positioned_cursor.dart';
-
 class MeasureTouchGesturePanel extends StatefulWidget {
   const MeasureTouchGesturePanel({Key? key}) : super(key: key);
 

+ 2 - 1
lib/view/mobile_view/mobile_measure_main_view.dart

@@ -18,6 +18,7 @@ import 'package:fis_measure/utils/prompt_box.dart';
 import 'package:fis_measure/values/colors.dart';
 import 'package:fis_measure/view/button_group/button_group.dart';
 import 'package:fis_measure/view/gesture/annotation/annotation_gesture.dart';
+import 'package:fis_measure/view/gesture/mobile_annotation/mobile_annotation_gesture.dart';
 import 'package:fis_measure/view/gesture/touch_gesture.dart';
 import 'package:fis_measure/view/measure/capture_image.dart';
 import 'package:fis_measure/view/measure/measure_result.dart';
@@ -422,7 +423,7 @@ class _MobileMeasureMainViewState extends State<MobileMeasureMainView> {
       }
     }
     return inAnnotation
-        ? const AnnotationGestureLayer()
+        ? const AnnotationTouchLayer()
         : const MeasureTouchGesturePanel();
   }
 }

+ 1 - 74
lib/view/mobile_view/mobile_measure_view.dart

@@ -349,7 +349,7 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
               child: const MeasureLeftAnnotation(),
             ),
           ),
-          _MeasureArrow(),
+          // _MeasureArrow(),
         ] else ...[
           FExpanded(
             child: showMeasureItems
@@ -368,76 +368,3 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
     );
   }
 }
-
-class _MeasureArrow extends FStatefulWidget {
-  @override
-  FState<_MeasureArrow> createState() => _MeasureArrowState();
-}
-
-class _MeasureArrowState extends FState<_MeasureArrow> {
-  final measureHandler = Get.find<MeasureHandler>();
-
-  final application = Get.find<IApplication>();
-  bool get isArrowMeasureAnnotationType =>
-      measureHandler.changedAnnotationType == AnnotationType.arrow;
-
-  void onChangedAnnotationType(
-    Object sender,
-    AnnotationType? e,
-  ) {
-    setState(() {});
-  }
-
-  @override
-  void initState() {
-    measureHandler.onChangedAnnotationType.addListener(onChangedAnnotationType);
-    super.initState();
-  }
-
-  @override
-  void dispose() {
-    measureHandler.onChangedAnnotationType
-        .removeListener(onChangedAnnotationType);
-    super.dispose();
-  }
-
-  @override
-  FWidget build(BuildContext context) {
-    return FContainer(
-      height: 100,
-      width: 300,
-      child: FCenter(
-        child: FColumn(
-          children: [
-            FInk(
-              child: FInkWell(
-                onTap: () {
-                  measureHandler.changedAnnotationType = AnnotationType.arrow;
-                  application.switchAnnotation(AnnotationType.arrow);
-                },
-                child: FIcon(
-                  Icons.call_made_rounded,
-                  color:
-                      isArrowMeasureAnnotationType ? Colors.blue : Colors.white,
-                  size: 30,
-                ),
-              ),
-            ),
-            FText(
-              i18nBook.measure.arrow.t,
-              style: isArrowMeasureAnnotationType
-                  ? const TextStyle(
-                      color: Colors.blue,
-                      fontSize: 14,
-                    )
-                  : const TextStyle(
-                      color: Colors.white,
-                      fontSize: 14,
-                    ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}

+ 4 - 3
lib/view/mobile_view/mobile_right_panel.dart

@@ -77,10 +77,11 @@ class _MobileRightPanelState extends State<MobileRightPanel> {
         return const MobileMeasureSelector();
       case MobileMeasureMode.annotationMode:
         return Container(
-          height: 300,
-          width: 300,
+          height: 100,
+          width: 100,
+          color: Color.fromARGB(10, 190, 190, 190),
           key: UniqueKey(),
-          child: const MeasureLeftAnnotation(),
+          // child: const MeasureLeftAnnotation(),
         );
       default:
         return Container();

+ 7 - 0
lib/view/mobile_view/mobile_top_menu.dart

@@ -1,3 +1,4 @@
+import 'package:fis_measure/interfaces/enums/annotation.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
 import 'package:fis_measure/interfaces/process/workspace/mobile_measure_view_state_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
@@ -161,10 +162,16 @@ class _MobileTopMenuState extends State<MobileTopMenu> {
   }
 
   Widget _arrowBtn() {
+    // bool get isArrowMeasureAnnotationType =>
+    //   measureHandler.changedAnnotationType == AnnotationType.arrow;
+    // TODO 原本是用于判断当前是否为箭头模式
     return SingleIconButton(
       icon: Icons.compare_arrows_rounded,
       onPressed: () {
         print("call 箭头模式");
+        measureHandler.changedAnnotationType =
+            AnnotationType.arrow; // TODO 原本是用于判断当前是否为箭头模式
+        application.switchAnnotation(AnnotationType.arrow);
       },
     );
   }