123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- import 'package:fis_common/logger/logger.dart';
- import 'package:fis_i18n/i18n.dart';
- import 'package:fis_jsonrpc/rpc.dart';
- import 'package:fis_measure/define.dart';
- import 'package:fis_measure/interfaces/process/items/item.dart';
- import 'package:fis_measure/interfaces/process/items/item_metas.dart';
- import 'package:fis_measure/interfaces/process/items/terms.dart';
- import 'package:fis_measure/interfaces/process/items/types.dart';
- import 'package:fis_measure/interfaces/process/player/play_controller.dart';
- import 'package:fis_measure/interfaces/process/workspace/application.dart';
- import 'package:fis_measure/process/language/measure_language.dart';
- import 'package:fis_measure/process/workspace/measure_data_controller.dart';
- import 'package:fis_measure/process/workspace/measure_data_helper.dart';
- import 'package:fis_measure/process/workspace/measure_handler.dart';
- import 'package:fis_measure/view/measure/combo_widget.dart';
- import 'package:fis_measure/view/measure/measure_view_controller.dart';
- import 'package:fis_measure/view/player/controller.dart';
- import 'package:fis_ui/index.dart';
- import 'package:fis_ui/interface/interactive_container.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:vid/us/vid_us_image.dart';
- import 'custom_item_buttons/combo.dart';
- /// 测量项页面
- class LeftSiderSelectMeasure extends FStatefulWidget
- implements FInteractiveContainer {
- const LeftSiderSelectMeasure({Key? key}) : super(key: key);
- @override
- final String pageName = 'LeftSiderSelectMeasure';
- @override
- FState<LeftSiderSelectMeasure> createState() => LeftSiderSelectMeasureState();
- }
- class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
- /// 数据
- IApplication get application => Get.find<IApplication>();
- VidPlayerController get playerController =>
- Get.find<IPlayerController>() as VidPlayerController;
- final measureHandler = Get.find<MeasureHandler>();
- final measureData = Get.find<MeasureDataController>();
- final measureMetaController = Get.find<MeasureMetaController>();
- /// 测量语言包
- final measureLanguage = MeasureLanguage();
- /// 当前选中的测量项下标
- int activeItemIndex = 0;
- /// 当前选中的子测量项下标
- int activeChildItemIndex = 0;
- /// 上一个测量项
- int lastActiveItemIndex = 0;
- /// 【TODO】 翻译
- String selectedType = "手动";
- String selectedLocation = "上";
- /// Styles
- late String fontFamily;
- static const Color buttonBackgroundColor = Color.fromRGBO(70, 70, 70, 1);
- static const Color buttonBorderColor = Color.fromRGBO(124, 124, 124, 1);
- static const Color buttonBorderHighlight = Color.fromRGBO(124, 124, 124, 1);
- static const Color buttonTextColor = Colors.white;
- static const Color childButtonHighlight = Color.fromRGBO(84, 144, 249, 1);
- static const Color childContainerBackground = Color.fromRGBO(60, 60, 60, 1);
- static const double buttonBorderHighlightWidth = 1.0;
- /// 触发测量项选中事件
- void selectItem(int selectIndex) {
- if (selectIndex == activeItemIndex) return;
- final itemMeta = measureData.curItemMetaList[selectIndex];
- /// 【TODO】 暂时屏蔽 buyStatus
- // if (itemMeta.buyStatus == WorkingItemStatusEnum.Unpaid) {
- // PromptBox.toast("如需继续使用该测量项,请联系Vinno申请试用或购买。");
- // return;
- // }
- changeItem(itemMeta);
- // setState(() {
- // activeItemIndex = selectIndex;
- // activeChildItemIndex = 0;
- // });
- }
- /// 触发子测量项选中事件
- void selectChildItem(int selectIndex) {
- if (selectIndex == activeChildItemIndex) return;
- final item = application.activeMeasureItem!;
- if (item is ITopMeasureItem) {
- item.switchChild(selectIndex);
- activeChildItemIndex = selectIndex;
- }
- setState(() {});
- }
- /// 切换测量项
- void changeItem(ItemMeta itemMeta) {
- int itemIndex =
- measureData.curItemMetaList.indexWhere((e) => e.name == itemMeta.name);
- int childItemIndex = activeChildItemIndex;
- try {
- // IMeasureItem? item = application.activeMeasureItem;
- // if (item != null &&
- // item.meta.name == itemMeta.name &&
- // item is ITopMeasureItem &&
- // item.isCrossFrameMode) {
- // // 跨帧测量,测量项无变化时,自动切到下一个子项
- // childItemIndex = item.workingChildIndex + 1;
- // if (childItemIndex < item.childItems.length) {
- // item.switchChild(childItemIndex);
- // item.workingChildChanged.addListener(_onWorkingChildChanged);
- // if (mounted) {
- // setState(() {
- // activeChildItemIndex = childItemIndex;
- // });
- // }
- // return;
- // }
- // }
- application.switchItem(itemMeta);
- final item = application.activeMeasureItem!;
- if (item is ITopMeasureItem) {
- item.switchChild(0);
- item.workingChildChanged.addListener(_onWorkingChildChanged);
- }
- } catch (e) {
- logger.e("changeItem failed", e);
- }
- if (mounted) {
- setState(() {
- activeItemIndex = itemIndex;
- activeChildItemIndex = childItemIndex;
- });
- }
- }
- /// 子测量项变化事件监听
- void _onWorkingChildChanged(sender, int e) {
- setState(() {
- activeChildItemIndex = e;
- });
- }
- void _onItemMetaListChanged(Object s, dynamic e) {
- try {
- if (e != null) {
- setState(() {});
- }
- } catch (e) {
- debugPrint("ItemMetaListChanged fail " + e.toString());
- }
- }
- /// 首帧加载完成事件监听: 获取当前图像的测量项,从第一帧取
- void _onFirstFrameLoaded(Object sender, VidUsImage e) async {
- if (!mounted) return;
- _getMeasureItemsList(e);
- _getAnnotationList();
- }
- //初始化时尝试加载第一项测量项(如果有的话)
- void _loadFirstItem() {
- if (measureData.curItemMetaList.isNotEmpty) {
- if (_checkAndHostCrossFrameMeasureItem()) {
- return;
- }
- final itemMeta = measureData.curItemMetaList.first;
- changeItem(itemMeta);
- // setState(() {
- // activeItemIndex = 0;
- // activeChildItemIndex = 0;
- // });
- }
- }
- /// 注释获取
- void _getAnnotationList() async {
- List<String> annotationList = [];
- var measureCommentItemResult =
- await MeasureDataHelper.getCommentsByApplicationAsync(
- application.applicationName,
- application.categoryName,
- );
- measureData.measureCommentItemResult =
- measureCommentItemResult?.commentItems ?? [];
- measureCommentItemResult?.commentItems?.forEach((element) {
- annotationList.add(element.text ?? '');
- });
- measureData.annotationList = annotationList;
- measureHandler.onAnnotationsLoaded();
- }
- void _getMeasureItemsList(VidUsImage e) async {
- List<String> getModes = [];
- for (var element in e.visuals[0].modes) {
- getModes.add(element.type.toString().split('.')[1]);
- }
- measureData.applicationModes = e.visuals[0].modes;
- measureData.currentMode = e.visuals[0].modes.first.type.name;
- var measureModeSelection = MeasureModeSelection(
- application.applicationName,
- application.categoryName,
- application.isThirdPart ? ['TPPTissue'] : getModes,
- );
- measureHandler.measureModeChanged = measureModeSelection;
- var measureApplicationDTO =
- await MeasureDataHelper.getMeasureApplication(measureModeSelection);
- if (measureApplicationDTO != null) {
- measureData.measureApplicationVersion =
- measureApplicationDTO.version ?? '';
- measureData.availableModes = measureApplicationDTO.availableModes ?? [];
- if (application.isThirdPart) {
- measureData.currentMode = 'TPPTissue';
- }
- measureMetaController.setAvailableModes(measureData.currentMode);
- setState(() {});
- }
- }
- /// 测量项列表变化事件监听
- void _onCurItemMetaListChanged(sender, e) {
- if (measureData.curItemMetaList.isNotEmpty) {
- if (_checkAndHostCrossFrameMeasureItem()) {
- return;
- }
- changeItem(measureData.curItemMetaList[0]);
- }
- // setState(() {
- // activeItemIndex = 0;
- // activeChildItemIndex = 0;
- // });
- }
- bool _checkAndHostCrossFrameMeasureItem() {
- final crossCxt = application.crossFrameContext;
- if (crossCxt != null && !crossCxt.isOver) {
- final activeItem = application.activeMeasureItem;
- if (activeItem != null &&
- activeItem is ITopMeasureItem &&
- activeItem.isCrossFrameMode) {
- // 跨帧时&当前是跨帧测量项,则保持此测量项
- changeItem(activeItem.meta);
- return true;
- }
- }
- return false;
- }
- /// 是否显示测量项翻译事件变化
- void _onShowItemTransStateChanged(_, e) {
- setState(() {});
- }
- /// 鼠标右键结束测量事件【即切换到空测量项】,此时缓存被结束的测量项,如果再次收到右击事件,恢复被结束的测量项
- void _onRightClickFinishMeasure(_, e) {
- if (activeItemIndex == -1) {
- changeItem(measureData.curItemMetaList[lastActiveItemIndex]);
- setState(() {
- activeItemIndex = lastActiveItemIndex;
- activeChildItemIndex = 0;
- });
- } else {
- lastActiveItemIndex = activeItemIndex;
- final emptyItem = ItemMeta(
- "EmptyItem",
- measureType: MeasureTypes.Empty,
- description: "",
- outputs: [],
- );
- changeItem(emptyItem);
- setState(() {
- activeItemIndex = -1;
- activeChildItemIndex = 0;
- });
- }
- }
- @override
- void initState() {
- measureData.curItemMetaListChanged.addListener(_onCurItemMetaListChanged);
- measureData.itemMetaListChanged.addListener(_onItemMetaListChanged);
- measureData.showItemTransStateChanged
- .addListener(_onShowItemTransStateChanged);
- measureHandler.onRightClickFinishMeasure
- .addListener(_onRightClickFinishMeasure);
- WidgetsBinding.instance.addPostFrameCallback((call) {
- _loadFirstItem();
- playerController.firstFrameLoaded.addListener(_onFirstFrameLoaded);
- });
- super.initState();
- }
- @override
- dispose() {
- super.dispose();
- playerController.firstFrameLoaded.removeListener(_onFirstFrameLoaded);
- measureData.curItemMetaListChanged
- .removeListener(_onCurItemMetaListChanged);
- measureData.itemMetaListChanged.removeListener(_onItemMetaListChanged);
- measureData.showItemTransStateChanged
- .removeListener(_onShowItemTransStateChanged);
- measureHandler.onRightClickFinishMeasure
- .removeListener(_onRightClickFinishMeasure);
- final item = application.activeMeasureItem;
- if (item != null && item is ITopMeasureItem) {
- item.workingChildChanged.removeListener(_onWorkingChildChanged);
- }
- }
- @override
- FWidget build(BuildContext context) {
- fontFamily = Theme.of(context).textTheme.labelLarge!.fontFamily!;
- return buildItemsListView(measureData.curItemMetaList);
- }
- /// 构建测量项列表
- FWidget buildItemsListView(List<ItemMeta> itemMetaList) {
- return FListView(
- shrinkWrap: true,
- controller: ScrollController(),
- children: List.generate(itemMetaList.length, (i) {
- return _buildItemContainer(i);
- }));
- }
- /// 构建测量项容器
- FWidget _buildItemContainer(int itemMetaIndex) {
- final itemMeta = measureData.curItemMetaList[itemMetaIndex];
- final isActived = itemMetaIndex == activeItemIndex; // 是否选中
- final hasChildItem = itemMeta.childItems.isNotEmpty; //是否为组合测量项
- return FContainer(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(5),
- border: isActived && hasChildItem
- ? Border.all(
- color: buttonBorderHighlight,
- width: buttonBorderHighlightWidth)
- : null,
- ),
- margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
- child: FStack(
- children: [
- FColumn(children: [
- if (isActived && hasChildItem) ...[
- _buildItemTitle(itemMetaIndex),
- _buildChildItemContainer(itemMeta),
- ] else
- FContainer(
- width: double.infinity,
- child: _buildItemButton(itemMetaIndex),
- ),
- ]),
- // if (itemMeta.buyStatus != null)
- // FPositioned(
- // top: 0,
- // right: 0,
- // child: _buildItemBuyStatusName(
- // itemMeta.buyStatus ?? WorkingItemStatusEnum.Free,
- // ),
- // )
- ],
- ));
- }
- // 构建测量项是否需要购买
- FWidget _buildItemBuyStatusName(WorkingItemStatusEnum buyStatus) {
- String name = "";
- Color textColor = Colors.white;
- switch (buyStatus) {
- case WorkingItemStatusEnum.Probation:
- name = i18nBook.measure.probation.t;
- textColor = Colors.yellow;
- break;
- case WorkingItemStatusEnum.Unpaid:
- name = i18nBook.measure.unpaid.t;
- textColor = Colors.red;
- break;
- case WorkingItemStatusEnum.Purchased:
- name = i18nBook.measure.purchased.t;
- textColor = childButtonHighlight;
- break;
- case WorkingItemStatusEnum.Expired:
- name = i18nBook.measure.expired.t;
- textColor = Colors.red;
- break;
- default:
- break;
- }
- if (name.isNotEmpty) {
- return QuickFWidget(
- RawChip(
- backgroundColor: textColor.withOpacity(0.8),
- label: FText(
- name,
- style: TextStyle(
- color: Colors.white,
- fontFamily: fontFamily,
- fontSize: 12,
- ),
- ),
- // isEnabled: false,//禁止点选状态
- labelPadding: const EdgeInsets.symmetric(horizontal: 4),
- shape: OutlinedBorder.lerp(
- RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(4),
- ),
- RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(4),
- ),
- 0,
- )
- // padding: EdgeInsets.only(left: 10, right: 10, top: 5),
- ),
- );
- }
- return const FSizedBox();
- }
- // 构建测量项按钮
- FWidget _buildItemButton(int itemIndex) {
- final itemMeta = measureData.curItemMetaList[itemIndex];
- final transValue = measureLanguage.t('measure', itemMeta.description);
- // 非英文环境下显示中英文,否则只显示英文
- final ifShowCN = !i18nBook.isCurrentEnglish &&
- transValue != itemMeta.description &&
- measureData.measureSystemSetting.showAnnotation;
- final isActived = itemIndex == activeItemIndex;
- if (AutomaticMeasureSupportedTerms.items.contains(itemMeta.description)) {
- return _buildItemAutomaticMeasure(
- itemIndex,
- itemMeta,
- ifShowCN,
- transValue,
- isActived,
- );
- }
- return FElevatedButton(
- name: itemMeta.name,
- businessParent: widget,
- onPressed: () => selectItem(itemIndex),
- child: FColumn(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- if (ifShowCN)
- FText(
- transValue,
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- color: isActived ? null : buttonTextColor,
- fontFamily: fontFamily,
- fontSize: 12,
- ),
- ),
- FText(
- itemMeta.description,
- style: TextStyle(
- color: isActived ? null : buttonTextColor,
- ),
- ),
- ],
- ),
- style: ElevatedButton.styleFrom(
- backgroundColor: isActived ? null : buttonBackgroundColor,
- fixedSize: const Size.fromHeight(
- 50,
- ),
- side: BorderSide(
- color: isActived ? Colors.transparent : buttonBorderColor,
- ),
- ),
- );
- }
- /// 构建特殊的自动测量项
- FWidget _buildItemAutomaticMeasure(
- int itemIndex,
- ItemMeta itemMeta,
- bool ifShowCN,
- String transValue,
- bool isActived,
- ) {
- return FColumn(
- children: [
- FRow(
- mainAxisSize: MainAxisSize.max,
- children: [
- FExpanded(
- child: FElevatedButton(
- name: itemMeta.name,
- businessParent: widget,
- onPressed: () => selectItem(itemIndex),
- child: FColumn(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- if (ifShowCN)
- FText(
- transValue + "($selectedType)",
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- color: isActived ? null : buttonTextColor,
- fontFamily: fontFamily,
- fontSize: 12,
- ),
- ),
- FText(
- itemMeta.description,
- style: TextStyle(
- color: isActived ? null : buttonTextColor,
- ),
- ),
- ],
- ),
- style: ElevatedButton.styleFrom(
- backgroundColor: isActived ? null : buttonBackgroundColor,
- fixedSize: const Size.fromHeight(
- 50,
- ),
- side: BorderSide(
- color: isActived ? Colors.transparent : buttonBorderColor,
- ),
- ),
- ),
- ),
- ],
- ),
- if (isActived) ...[
- FContainer(
- width: double.maxFinite,
- decoration: const BoxDecoration(
- color: childContainerBackground,
- borderRadius: BorderRadius.only(
- bottomLeft: Radius.circular(5),
- bottomRight: Radius.circular(5),
- ),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 5),
- child: FColumn(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- /// 【TODO】 翻译 测量方式
- FContainer(
- margin:
- const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
- child: const FText(
- '测量方式',
- style: TextStyle(
- fontSize: 12,
- color: buttonTextColor,
- ),
- ),
- ),
- FRow(
- children: ["自动", "半自动", "手动"]
- .map((e) => _buildMeasureButton(e, true))
- .toList(),
- ),
- if (selectedType == "自动") ...[
- FContainer(
- margin:
- const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
- child: const FText(
- '跟踪方向',
- style: TextStyle(
- fontSize: 12,
- color: buttonTextColor,
- ),
- ),
- ),
- FRow(
- children: ["上", "下", "全部"]
- .map((e) => _buildMeasureButton(e, false))
- .toList(),
- ),
- ]
- ],
- ),
- ),
- ]
- ],
- );
- }
- FWidget _buildMeasureButton(String type, bool isType) {
- return FExpanded(
- child: FInkWell(
- onTap: () {
- if (isType) {
- selectedType = type;
- } else {
- selectedLocation = type;
- }
- setState(() {});
- },
- child: FContainer(
- height: 40,
- margin: const EdgeInsets.symmetric(horizontal: 2),
- decoration: BoxDecoration(
- color: (isType ? selectedType == type : selectedLocation == type)
- ? const Color.fromARGB(255, 101, 211, 71)
- : const Color.fromRGBO(70, 70, 70, 1),
- border: Border.all(color: const Color.fromRGBO(124, 124, 124, 1)),
- borderRadius: BorderRadius.circular(5),
- ),
- // margin: const EdgeInsets.symmetric(horizontal: 11, vertical: 5),
- child: FCenter(
- child: FText(
- type.toString(),
- style: const TextStyle(
- color: Colors.white,
- ),
- ),
- ),
- ),
- ),
- );
- }
- // 构建测量项标签【用于组合测量项顶部】
- FWidget _buildItemTitle(int itemIndex) {
- final itemMeta = measureData.curItemMetaList[itemIndex];
- final transValue = measureLanguage.t('measure', itemMeta.description);
- // 非英文环境下显示中英文,否则只显示英文
- final ifShowCN = !i18nBook.isCurrentEnglish &&
- transValue != itemMeta.description &&
- measureData.measureSystemSetting.showAnnotation;
- return FContainer(
- decoration: const BoxDecoration(
- border: Border(
- bottom: BorderSide(
- color: buttonBorderHighlight, width: buttonBorderHighlightWidth),
- ),
- ),
- child: FSizedBox(
- height: 50,
- width: double.infinity,
- child: FColumn(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- if (ifShowCN)
- FText(
- transValue,
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- color: buttonTextColor,
- fontFamily: fontFamily,
- fontSize: 12,
- ),
- ),
- FText(
- itemMeta.description,
- style: const TextStyle(
- color: buttonTextColor,
- ),
- ),
- ],
- ),
- ),
- );
- }
- /// 子测量项容器
- FWidget _buildChildItemContainer(ItemMeta itemMeta) {
- final activeName = itemMeta.description;
- final isSpecial = MeasurespecialsupportedTerms.items.contains(activeName);
- if (isSpecial) {
- //是否为特殊组合测量项
- return const SpecialItemHR();
- } else if (CustomComboItemGroup.specialItemTypes
- .contains(itemMeta.measureType)) {
- return CustomComboItemGroup(
- activeIndex: activeChildItemIndex,
- businessParent: widget,
- itemMeta: itemMeta,
- onChildClick: (int childItemIndex) {
- selectChildItem(childItemIndex);
- },
- );
- } else {
- return FContainer(
- decoration: const BoxDecoration(
- color: childContainerBackground,
- borderRadius: BorderRadius.only(
- bottomLeft: Radius.circular(5), bottomRight: Radius.circular(5)),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 5),
- child: FColumn(
- children: (itemMeta.childItems)
- .asMap()
- .entries
- .map(
- (e) => _buildChildItemButton(
- e.value,
- e.key,
- ),
- )
- .toList(),
- ),
- );
- }
- }
- // 构建子测量项按钮
- FWidget _buildChildItemButton(ItemMeta itemMeta, int childItemIndex) {
- final isActived = childItemIndex == activeChildItemIndex;
- return FContainer(
- width: double.infinity,
- margin: const EdgeInsetsDirectional.all(5),
- child: FElevatedButton(
- businessParent: widget,
- name: "selectChildItemIdnex:$childItemIndex",
- onPressed: () {
- selectChildItem(childItemIndex);
- },
- child: FText(
- itemMeta.description,
- ),
- style: ElevatedButton.styleFrom(
- backgroundColor: isActived ? null : buttonBackgroundColor,
- side: BorderSide(
- color: isActived ? Colors.transparent : buttonBorderColor,
- ),
- ),
- ));
- }
- }
|