import 'package:fis_measure/interfaces/process/items/item.dart'; import 'package:fis_measure/interfaces/process/items/item_feature.dart'; import 'package:fis_measure/interfaces/process/items/measure_terms.dart'; import 'package:fis_measure/interfaces/process/visuals/visual_area.dart'; import 'package:fis_measure/interfaces/process/visuals/visual.dart'; import 'package:fis_measure/interfaces/process/viewports/viewport.dart'; import 'package:fis_measure/interfaces/process/modes/mode.dart'; import 'package:fis_common/event/event_type.dart'; import 'package:fis_measure/interfaces/process/workspace/application.dart'; import 'package:fis_measure/interfaces/process/workspace/point_info.dart'; import 'package:fis_measure/process/primitives/ellipse.dart'; import 'package:fis_measure/process/primitives/location.dart'; import 'package:fis_measure/process/primitives/straightline.dart'; import 'package:flutter/painting.dart'; import 'package:vid/us/vid_us_image.dart'; import 'package:vid/us/vid_us_probe.dart'; import 'package:vid/us/vid_us_unit.dart'; import '../visual/visual.dart'; class Application implements IApplication { late VidUsProbe _probe; VidUsImage? _frame; List? _visuals; IMeasureItem? _activeItem; bool _canMeasure = false; Size _displaySize = Size.zero; final Set _items = {}; Application(VidUsProbe probe) { _probe = probe; } @override bool get canMeasure => _canMeasure; @override set canMeasure(bool value) { if (value != _canMeasure) { _canMeasure = value; _doCanMeasureChanged(); } } bool get isProbeConvex => probe.type == VidUsProbeType.Convex; @override VidUsProbe get probe => _probe; @override String get applicationName => _probe.application.applicationName; @override String get categoryName => _probe.application.applicationCategoryName; @override IMode get currentMode => currentVisualArea.mode; @override IViewPort get currentViewPort => currentVisualArea.viewport!; @override IVisual get currentVisual => visuals.firstWhere((e) => e.activeArea != null); @override IVisualArea get currentVisualArea => currentVisual.activeArea!; @override VidUsImage? get frameData => _frame; @override List get visuals => _visuals!; @override Set get items => _items; @override Size get displaySize => _displaySize; @override set displaySize(Size value) { if (value != _displaySize) { _displaySize = value; } } @override List get avaliableModes { final modes = []; for (var visual in visuals) { modes.addAll(visual.modes); } return modes; } @override IMeasureItem? get activeItem => _activeItem; set activeItem(IMeasureItem? value) { if (value != _activeItem) { _activeItem?.featureUpdated.removeListener(_onActiveItemFeatureUpdated); _activeItem = value; if (_activeItem != null) { _items.add(_activeItem!); _activeItem!.featureUpdated.addListener(_onActiveItemFeatureUpdated); } activeItemChanged.emit(this, value); _doMeasureRerender(); } } @override var currentModeChanged = FEventHandler(); @override var visualAreaChanged = FEventHandler(); @override var canMeasureChanged = FEventHandler(); @override var activeItemChanged = FEventHandler(); @override var measureRerenderReady = FEventHandler(); @override void loadFrame(VidUsImage frame) { bool frameLoaded = _frame != null; _frame = frame; if (!frameLoaded && canMeasure) { _loadVisuals(); } } @override PointInfo createPointInfo(Offset offset, PointInfoType type) { if (frameData == null) { throw NullThrownError(); } final width = displaySize.width; final height = displaySize.height; final x = offset.dx / width; final y = offset.dy / height; final percentOffset = Offset(x, y); final info = PointInfo.fromOffset(percentOffset, type); info.hostVisualArea = visuals.first.visualAreas.first; // TODO: 找区域 activeItem?.execute(info); return info; } @override void switchItemByName(String name) { // TODO: create from map if (name == MeasureTerms.Distance) { activeItem = StraightLine.createDistance( ItemMeta( MeasureTerms.Distance, { "Description": MeasureTerms.Distance, "BriefDescription": "D", "Unit": VidUsUnit.cm, }, ), ); return; } if (name == MeasureTerms.Perimeter) { activeItem = Ellipse( ItemMeta( MeasureTerms.Perimeter, { "Description": MeasureTerms.Perimeter, "BriefDescription": MeasureTerms.Perimeter, "Unit": VidUsUnit.cm, }, ), null, ); return; } if (name == MeasureTerms.Area) { activeItem = Ellipse( ItemMeta( MeasureTerms.Area, { "Description": MeasureTerms.Area, "BriefDescription": MeasureTerms.Area, "Unit": VidUsUnit.cm2, }, ), null, ); return; } if (name == MeasureTerms.Depth) { final Location Function(ItemMeta, [IMeasureItem?]) fn = isProbeConvex ? Location.createTissueConvexDepth : Location.createTissueDepth; activeItem = fn( ItemMeta( MeasureTerms.Depth, { "Description": MeasureTerms.Depth, "BriefDescription": MeasureTerms.Depth, "Unit": VidUsUnit.cm, }, ), null, ); return; } } void _doMeasureRerender() { measureRerenderReady.emit(this, null); } void _doCanMeasureChanged() { canMeasureChanged.emit(this, canMeasure); _clear(); if (canMeasure) { if (frameData != null) { _loadVisuals(); } } } void _onActiveItemFeatureUpdated(Object sender, IMeasureItemFeature? e) { _doMeasureRerender(); } void _loadVisuals() { _clearVisuals(); for (final data in frameData!.visuals) { _visuals!.add(VisualBase(data)); } } void _clear() { for (var item in items) { item.clear(); } _clearVisuals(); } void _clearVisuals() { _visuals = []; } }