input_position_panel.dart 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // ignore_for_file: constant_identifier_names
  2. import 'package:fis_measure/interfaces/enums/annotation.dart';
  3. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  4. import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
  5. import 'package:fis_measure/process/annotations/input_annotation.dart';
  6. import 'package:fis_measure/values/colors.dart';
  7. import 'package:fis_measure/view/gesture/mouse_gesture.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:get/get.dart';
  10. import '../positioned_cursor.dart';
  11. /// 自定义注释文本框定位面板
  12. class AnnotationInputPositionPanel extends StatefulWidget {
  13. const AnnotationInputPositionPanel({Key? key}) : super(key: key);
  14. @override
  15. State<AnnotationInputPositionPanel> createState() => _PanelState();
  16. }
  17. class _PanelState extends State<AnnotationInputPositionPanel> {
  18. late final application = Get.find<IApplication>();
  19. final mouseState = Get.find<IMouseState>();
  20. CursorDisplayType displayType = CursorDisplayType.none;
  21. Offset? position;
  22. @override
  23. Widget build(BuildContext context) {
  24. return GestureDetector(
  25. onPanDown: (details) {
  26. setState(() {
  27. position = details.localPosition -
  28. const Offset(
  29. _InputWidget.C_MIN_WIDTH / 2,
  30. _InputWidget.C_MAX_HEIGHT / 2,
  31. );
  32. application.createPointInfo(position!, PointInfoType.mouseDown);
  33. });
  34. },
  35. child: MouseRegion(
  36. cursor: SystemMouseCursors.none,
  37. onHover: (event) {
  38. mouseState.mousePosition = event.localPosition;
  39. },
  40. onEnter: (e) {
  41. setState(() {
  42. displayType = CursorDisplayType.normal;
  43. });
  44. },
  45. onExit: (e) {
  46. if (application.activeAnnotationItem != null &&
  47. application.activeAnnotationItem is InputAnnotation) {
  48. application.switchAnnotation(AnnotationType.label);
  49. }
  50. setState(() {
  51. position = null;
  52. displayType = CursorDisplayType.none;
  53. });
  54. },
  55. child: Stack(
  56. children: [
  57. if (position != null)
  58. Positioned(
  59. child: _InputWidget(
  60. key: UniqueKey(),
  61. onChanged: (value) {
  62. application.activeAnnotationItem?.text = value;
  63. },
  64. ),
  65. left: position!.dx,
  66. top: position!.dy,
  67. ),
  68. _buildCursor(),
  69. ],
  70. ),
  71. ),
  72. );
  73. }
  74. Widget _buildCursor() {
  75. switch (displayType) {
  76. case CursorDisplayType.none:
  77. return Container();
  78. case CursorDisplayType.normal:
  79. return const PositionedCursor();
  80. default:
  81. return const PositionedCursor();
  82. }
  83. }
  84. }
  85. typedef _InputValueChanged = void Function(String value);
  86. class _InputWidget extends StatelessWidget {
  87. static const C_BG_COLOR = Color.fromARGB(255, 121, 135, 151);
  88. static const C_MIN_WIDTH = 40.0;
  89. static const C_MAX_HEIGHT = 28.0;
  90. final FocusNode? focusNode;
  91. final _InputValueChanged onChanged;
  92. const _InputWidget({
  93. required this.onChanged,
  94. Key? key,
  95. this.focusNode,
  96. }) : super(key: key);
  97. @override
  98. Widget build(BuildContext context) {
  99. const border = OutlineInputBorder(
  100. borderSide: BorderSide(color: C_BG_COLOR),
  101. borderRadius: BorderRadius.all(Radius.circular(4.0)),
  102. );
  103. final input = TextField(
  104. expands: false,
  105. autofocus: true,
  106. focusNode: focusNode,
  107. style: const TextStyle(color: MeasureColors.Primary),
  108. cursorColor: MeasureColors.Primary,
  109. cursorWidth: 1.0,
  110. onChanged: onChanged,
  111. decoration: const InputDecoration(
  112. border: border,
  113. enabledBorder: border,
  114. focusedBorder: border,
  115. counterText: '',
  116. filled: true,
  117. fillColor: C_BG_COLOR,
  118. isCollapsed: false,
  119. contentPadding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
  120. constraints:
  121. BoxConstraints(minWidth: C_MIN_WIDTH, maxHeight: C_MAX_HEIGHT),
  122. ),
  123. );
  124. return Container(
  125. padding: const EdgeInsets.symmetric(horizontal: 1),
  126. alignment: Alignment.topLeft,
  127. child: IntrinsicWidth(child: input),
  128. );
  129. }
  130. }