Преглед изворни кода

update(measure): 完成测量、注释开关按钮 #0009381 Review by baka

gavin.chen пре 2 година
родитељ
комит
7883ce4e28

+ 112 - 44
lib/view/measure/operate_type_change_button.dart

@@ -8,14 +8,15 @@ import 'package:fis_measure/process/workspace/measure_controller.dart';
 import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
 import 'package:fis_measure/view/measure/measure_view_controller.dart';
+import 'package:fis_measure/view/menu_button_group/menu_button_group.dart';
 import 'package:fis_measure/view/player/controller.dart';
-import 'package:fis_theme/theme.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
+import 'package:get/get_connect/http/src/utils/utils.dart';
 import 'package:vid/us/vid_us_image.dart';
 
-/// 测量工具 注释工具Tab
+/// 测量工具 注释工具 切换按钮
 class OperateTypeChangeButton extends StatefulWidget implements FWidget {
   const OperateTypeChangeButton({super.key});
 
@@ -24,13 +25,16 @@ class OperateTypeChangeButton extends StatefulWidget implements FWidget {
       OperateTypeChangeButtonState();
 }
 
+// 两个按钮共有三种状态
+enum OperateButtonState { isMeasure, isAnnotation, allClose }
+
 class OperateTypeChangeButtonState extends State<OperateTypeChangeButton>
     with TickerProviderStateMixin {
   late final measureHandler = Get.find<MeasureHandler>();
-  late TabController tabController;
+  // late TabController tabController;
   late final measureData = Get.find<MeasureDataController>();
-  // List<Center> tabs = [];
   bool isShowMeasureButton = true;
+  OperateButtonState operateButtonState = OperateButtonState.isMeasure;
 
   /// 全部图片list
   final measureController = Get.find<MeasureController>();
@@ -49,7 +53,7 @@ class OperateTypeChangeButtonState extends State<OperateTypeChangeButton>
     super.dispose();
     measureHandler.annotationsLoaded.removeListener(onAnnotationsLoaded);
     measureController.imageLoaded.removeListener(_onImageLoaded);
-    tabController.dispose();
+    // tabController.dispose();
   }
 
   void initTab() {
@@ -60,23 +64,18 @@ class OperateTypeChangeButtonState extends State<OperateTypeChangeButton>
     ///比较妥协的临时解决方案是,触发切换注释时加上 500ms 延时【line 178:180】
     if (application.isSingleFrame && application.visuals.length > 1) {
       //多幅vid
-      // tabs = [i18nBook.measure.annotationTool.t]
-      //     .map((e) => Center(child: Tab(text: e)))
-      //     .toList();
+      changeTypeTo(MeasureOperateType.annotation);
       setState(() {
         isShowMeasureButton = false;
+        operateButtonState = OperateButtonState.isAnnotation;
       });
-      changeTypeTo(MeasureOperateType.annotation);
     } else {
-      // tabs = [i18nBook.measure.measureTool.t, i18nBook.measure.annotationTool.t]
-      //     .map((e) => Center(child: Tab(text: e)))
-      //     .toList();
+      changeTypeTo(MeasureOperateType.measure);
       setState(() {
         isShowMeasureButton = true;
+        operateButtonState = OperateButtonState.isMeasure;
       });
-      changeTypeTo(MeasureOperateType.measure);
     }
-    // setState(() {});
   }
 
   void changeTypeTo(e) {
@@ -84,8 +83,7 @@ class OperateTypeChangeButtonState extends State<OperateTypeChangeButton>
     if (e == MeasureOperateType.measure) {
       final measureMetaController = Get.find<MeasureMetaController>();
       measureMetaController.setAvailableModes(measureData.currentMode);
-
-      /// 用于切换到第一个测量项
+      // 用于切换到第一个测量项
       measureMetaController.updateItemList();
     } else {
       final application = Get.find<IApplication>();
@@ -117,35 +115,105 @@ class OperateTypeChangeButtonState extends State<OperateTypeChangeButton>
     super.didUpdateWidget(oldWidget);
   }
 
+  onTapMeasure() {
+    if (operateButtonState == OperateButtonState.isMeasure) {
+      measureHandler.toolPanelState = false;
+      setState(() {
+        operateButtonState = OperateButtonState.allClose;
+      });
+    } else {
+      measureHandler.toolPanelState = true;
+      changeTypeTo(MeasureOperateType.measure);
+      setState(() {
+        operateButtonState = OperateButtonState.isMeasure;
+      });
+    }
+  }
+
+  onTapAnnotation() {
+    if (operateButtonState == OperateButtonState.isAnnotation) {
+      measureHandler.toolPanelState = false;
+      setState(() {
+        operateButtonState = OperateButtonState.allClose;
+      });
+    } else {
+      measureHandler.toolPanelState = true;
+      changeTypeTo(MeasureOperateType.annotation);
+      setState(() {
+        operateButtonState = OperateButtonState.isAnnotation;
+      });
+    }
+  }
+
+  bool get isCurrMeasure => operateButtonState == OperateButtonState.isMeasure;
+  bool get isCurrAnnotation =>
+      operateButtonState == OperateButtonState.isAnnotation;
+
   @override
   FWidget build(BuildContext context) {
-    tabController = TabController(
-      vsync: this,
-      length: isShowMeasureButton ? 2 : 1,
-      initialIndex: 0,
-    );
-    final _colorScheme = FTheme.ins.colorScheme;
-
-    return FTabBar(
-      indicatorWeight: 2,
-      indicatorColor: _colorScheme.primary,
-      labelColor: _colorScheme.primary,
-      indicatorSize: TabBarIndicatorSize.label,
-      unselectedLabelColor: Colors.white,
-      onTap: (int index) {
-        try {
-          changeTypeTo(MeasureOperateType.values[index]);
-        } catch (e) {
-          debugPrint(e.toString());
-        }
-      },
-      tabs: isShowMeasureButton
-          ? [
-              Center(child: Tab(text: i18nBook.measure.measureTool.t)),
-              Center(child: Tab(text: i18nBook.measure.annotationTool.t))
-            ]
-          : [Center(child: Tab(text: i18nBook.measure.annotationTool.t))],
-      controller: tabController,
-    );
+    return FSizedBox(
+        width: 60,
+        child: FColumn(children: [
+          if (isShowMeasureButton)
+            FCustomLeftTooltip(
+              textStyle: const TextStyle(fontSize: 16, color: Colors.white),
+              height: 36,
+              message: i18nBook.measure.measureTool.t,
+              verticalOffset: 0,
+              margin: const EdgeInsets.only(right: 10),
+              decoration: BoxDecoration(
+                color: Colors.black.withOpacity(1.0),
+                borderRadius: BorderRadius.circular(4),
+              ),
+              child: FContainer(
+                height: 34,
+                margin: const EdgeInsets.only(
+                  top: 5,
+                ),
+                padding:
+                    const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
+                decoration: BoxDecoration(
+                  color: isCurrMeasure ? Colors.grey : Colors.transparent,
+                  borderRadius: BorderRadius.circular(5),
+                ),
+                child: FInkWell(
+                  onTap: onTapMeasure,
+                  child: Icon(
+                    Icons.straighten,
+                    color: isCurrMeasure ? Colors.white : Colors.white,
+                  ),
+                ),
+              ),
+            ),
+          FCustomLeftTooltip(
+            textStyle: const TextStyle(fontSize: 16, color: Colors.white),
+            height: 36,
+            message: i18nBook.measure.annotationTool.t,
+            verticalOffset: 0,
+            margin: const EdgeInsets.only(right: 10),
+            decoration: BoxDecoration(
+              color: Colors.black.withOpacity(1.0),
+              borderRadius: BorderRadius.circular(4),
+            ),
+            child: FContainer(
+              height: 34,
+              margin: const EdgeInsets.only(
+                top: 5,
+              ),
+              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
+              decoration: BoxDecoration(
+                color: isCurrAnnotation ? Colors.grey : Colors.transparent,
+                borderRadius: BorderRadius.circular(5),
+              ),
+              child: FInkWell(
+                onTap: onTapAnnotation,
+                child: Icon(
+                  Icons.font_download,
+                  color: isCurrAnnotation ? Colors.white : Colors.white,
+                ),
+              ),
+            ),
+          )
+        ]));
   }
 }

+ 0 - 1
lib/view/measure/tool_chest_title.dart

@@ -51,7 +51,6 @@ class LeftSiderHold extends StatelessWidget implements FWidget {
               LeftSiderHoldAllStyleConfig(ifHideConfig: ifHideConfig),
             ],
           ),
-          const OperateTypeChangeButton(),
           // const _LeftSiderTabBar(),
           // _LeftSelectInput(),
           // _LeftPulldown(),

+ 150 - 61
lib/view/menu_button_group/menu_button_group.dart

@@ -10,6 +10,7 @@ import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
 import 'package:fis_measure/utils/prompt_box.dart';
 import 'package:fis_measure/view/loadding/loadding.dart';
+import 'package:fis_measure/view/measure/operate_type_change_button.dart';
 import 'package:fis_measure/view/paint/ai_patint_controller.dart';
 import 'package:fis_measure/view/player/controller.dart';
 import 'package:fis_ui/index.dart';
@@ -31,19 +32,18 @@ class FMenuButtonGroup extends FStatefulWidget {
 
 class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
   // 单个按钮高度
-  static const double buttonHeight = 42;
+  static const double buttonHeight = 30;
   // 按钮外边距
   static const double buttonMargin = 10;
   // 单个按钮总高度 = Content(42)+Margin(10)
-  static const double singleButtonHeight = 52;
+  // static const double singleButtonHeight = buttonHeight + buttonMargin;
   // 按钮组宽度
   static const double buttonGroupWidth = 60;
   // 按钮组容器底部内边距 30 + 30
   static const double groupContainerPadding = buttonGroupWidth / 2;
-  // 按钮组容器展开的高度
-  get countGroupHeight =>
-      buildTitleButtonList().length * singleButtonHeight +
-      groupContainerPadding * 2;
+
+  /// 获取当前组件最大高度
+  get maxGroupHeight => Get.height - 200;
   final application = Get.find<IApplication>();
 
   /// 数据
@@ -68,7 +68,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
   @override
   void initState() {
     super.initState();
-    groupHeight = countGroupHeight;
+    groupHeight = maxGroupHeight;
     measure3DViewController.updatePlayerMode.addListener(_onModeChanged);
   }
 
@@ -85,7 +85,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
         setState(() {
           ifShowModeButton = false;
           ifShowVidModeButton = true;
-          groupHeight = countGroupHeight;
+          groupHeight = maxGroupHeight;
           isExpanded = true;
         });
         break;
@@ -93,7 +93,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
         setState(() {
           ifShowModeButton = true;
           ifShowVidModeButton = false;
-          groupHeight = countGroupHeight;
+          groupHeight = maxGroupHeight;
           isExpanded = true;
         });
         break;
@@ -118,6 +118,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
         i18nBook.measure.clear.t,
         () => application.clearRecords(),
       ),
+      const OperateTypeChangeButton(),
       _buildTitleButton(
         measureHandler.fullScreenState
             ? FIcons.fis_full_screen_reduction
@@ -130,16 +131,6 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
           setState(() {});
         },
       ),
-      _buildTitleButton(
-        measureHandler.toolPanelState
-            ? Icons.cancel_presentation
-            : Icons.present_to_all,
-        measureHandler.toolPanelState ? "关闭测量" : "打开测量",
-        () {
-          measureHandler.toolPanelState = !measureHandler.toolPanelState;
-          setState(() {});
-        },
-      ),
       _buildTitleButton(
         FIcons.fis_save,
         i18nBook.common.save.t,
@@ -221,27 +212,33 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
           verticalDirection: VerticalDirection.up,
           mainAxisAlignment: MainAxisAlignment.end,
           children: [
-            QuickFWidget(Transform.translate(
-                offset: const Offset(0, -buttonGroupWidth / 2),
-                child: FAnimatedContainer(
-                    duration: const Duration(milliseconds: 300),
-                    padding: const EdgeInsets.only(
-                      top: groupContainerPadding,
-                      bottom: groupContainerPadding / 2,
-                    ),
-                    decoration: BoxDecoration(
-                      borderRadius: const BorderRadius.only(
-                        bottomLeft: Radius.circular(buttonGroupWidth / 2),
-                        bottomRight: Radius.circular(buttonGroupWidth / 2),
+            QuickFWidget(
+              Transform.translate(
+                  offset: const Offset(0, -buttonGroupWidth / 2),
+                  child: FAnimatedContainer(
+                      duration: const Duration(milliseconds: 300),
+                      padding: const EdgeInsets.only(
+                        top: groupContainerPadding,
+                        bottom: groupContainerPadding / 2,
                       ),
-                      color: Colors.grey.withOpacity(0.6),
-                    ),
-                    clipBehavior: Clip.hardEdge,
-                    width: buttonGroupWidth,
-                    height: groupHeight,
-                    child: FColumn(
-                      children: buildTitleButtonList(),
-                    )))),
+                      decoration: BoxDecoration(
+                        borderRadius: const BorderRadius.only(
+                          bottomLeft: Radius.circular(buttonGroupWidth / 2),
+                          bottomRight: Radius.circular(buttonGroupWidth / 2),
+                        ),
+                        color: Colors.grey.withOpacity(0.6),
+                      ),
+                      clipBehavior: Clip.antiAlias,
+                      width: buttonGroupWidth,
+                      // height: groupHeight,
+                      constraints: BoxConstraints(
+                        maxHeight: groupHeight,
+                      ),
+                      child: FListView(
+                        shrinkWrap: true,
+                        children: buildTitleButtonList(),
+                      ))),
+            ),
             _buildDropDownButton(),
             const FSizedBox(height: 10),
           ],
@@ -251,27 +248,27 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
   }
 
   FWidget _buildTitleButton(IconData icon, String title, Function onClick) {
-    return FContainer(
-      height: buttonHeight,
-      margin: const EdgeInsets.only(
-        top: buttonMargin,
+    return FCustomLeftTooltip(
+      textStyle: const TextStyle(fontSize: 16, color: Colors.white),
+      height: 36,
+      message: title,
+      verticalOffset: 0,
+      margin: const EdgeInsets.all(0),
+      decoration: BoxDecoration(
+        color: Colors.black.withOpacity(1.0),
+        borderRadius: BorderRadius.circular(4),
       ),
-      child: FInkWell(
-        onTap: () => onClick.call(),
-        child: Column(
-          children: [
-            Icon(
-              icon,
-              color: Colors.white,
-            ),
-            Text(
-              title,
-              style: const TextStyle(
-                color: Colors.white,
-                fontSize: 14,
-              ),
-            )
-          ],
+      child: FContainer(
+        height: buttonHeight,
+        margin: const EdgeInsets.only(
+          top: buttonMargin,
+        ),
+        child: FInkWell(
+          onTap: () => onClick.call(),
+          child: Icon(
+            icon,
+            color: Colors.white,
+          ),
         ),
       ),
     );
@@ -282,7 +279,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
         onHover: (isHover) {
           if (isHover && !isExpanded) {
             setState(() {
-              groupHeight = countGroupHeight;
+              groupHeight = maxGroupHeight;
               isExpanded = true;
             });
           }
@@ -295,7 +292,7 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
             });
           } else {
             setState(() {
-              groupHeight = countGroupHeight;
+              groupHeight = maxGroupHeight;
               isExpanded = true;
             });
           }
@@ -351,3 +348,95 @@ class _FMenuButtonGroupState extends FState<FMenuButtonGroup> {
     );
   }
 }
+
+/// TODO:[Gavin] 定制组件,可与主项目的 FCustomRightTooltip 合并整合进 ui lib
+class FCustomLeftTooltip extends FStatefulWidget {
+  const FCustomLeftTooltip({
+    super.key,
+    this.message,
+    this.height,
+    this.padding,
+    this.margin,
+    this.verticalOffset,
+    this.decoration,
+    this.textStyle,
+    this.child,
+  }) : super();
+  final String? message;
+  final double? height;
+  final EdgeInsetsGeometry? padding;
+  final EdgeInsetsGeometry? margin;
+  final double? verticalOffset;
+  final Decoration? decoration;
+  final TextStyle? textStyle;
+  final FWidget? child;
+
+  @override
+  FState<FCustomLeftTooltip> createState() => FCustomRightTooltipState();
+}
+
+class FCustomRightTooltipState extends FState<FCustomLeftTooltip> {
+  OverlayEntry? _entry;
+
+  void _showTooltip() {
+    _createNewEntry();
+  }
+
+  void _createNewEntry() {
+    final OverlayState overlayState = Overlay.of(
+      context,
+      debugRequiredFor: widget,
+    );
+
+    final RenderBox box = context.findRenderObject()! as RenderBox;
+    final RenderBox boxConatiner =
+        overlayState.context.findRenderObject() as RenderBox;
+    final Offset target = box.localToGlobal(
+      box.size.center(Offset.zero),
+      ancestor: overlayState.context.findRenderObject(),
+    );
+    final Offset leftSide = Offset(
+      boxConatiner.size.width - (target.dx - box.size.width / 2),
+      target.dy - (widget.height ?? 26) / 2,
+    );
+    final Widget overlay = Directionality(
+      textDirection: Directionality.of(context),
+      child: Positioned(
+        right: leftSide.dx,
+        top: leftSide.dy,
+        child: Container(
+          decoration: widget.decoration ??
+              BoxDecoration(
+                color: Colors.black.withOpacity(0.7),
+                borderRadius: BorderRadius.circular(4),
+              ),
+          height: widget.height ?? 26,
+          padding: widget.padding ?? const EdgeInsets.symmetric(horizontal: 8),
+          margin: widget.margin ?? const EdgeInsets.only(left: 10),
+          child: Center(
+            child: Text(
+              widget.message ?? '',
+              style: widget.textStyle,
+            ),
+          ),
+        ),
+      ),
+    );
+    _entry = OverlayEntry(builder: (BuildContext context) => overlay);
+
+    overlayState.insert(_entry!);
+  }
+
+  @override
+  FWidget build(BuildContext context) {
+    return FMouseRegion(
+      onEnter: (event) {
+        _showTooltip();
+      },
+      onExit: (event) => _entry?.remove(),
+      child: FContainer(
+        child: widget.child,
+      ),
+    );
+  }
+}