import { getRoot, types } from "mobx-state-tree"; import { FF_DEV_3391, isFF } from "../../utils/feature-flags"; import { BaseTag } from "../TagBase"; import { SNAP_TO_PIXEL_MODE } from "../../components/ImageView/Image"; const ControlBase = types .model({ ...(isFF(FF_DEV_3391) ? { id: types.identifier, name: types.string, } : { name: types.identifier, }), smart: true, smartonly: false, isControlTag: true, }) .volatile(() => ({ snapMode: SNAP_TO_PIXEL_MODE.EDGE, })) .views((self) => ({ // historically two "types" were used and we should keep that backward compatibility: // 1. name of control tag for describing labeled region; // 2. label type to attach corresponding value to this region. // usually they are the same, but with some problems: // a. for hypertextlabels label type should be "htmllabels"; // original type are overwritten by Tree#buildData with real tag name, // so _type was introduced to contain desired result type; // b. but for textarea they differ from each other: "textarea" and "text". // so now there is simple way to distinguish and overwrite them via two methods: get resultType() { return self.type; }, // and get valueType() { return self.type; }, get toNameTag() { return self.annotation.names.get(self.toname); }, selectedValues() { throw new Error("Control tag needs to implement selectedValues method in views"); }, get result() { return self.annotation.results.find((r) => r.from_name === self); }, getSnappedPoint(point) { if (self.snap === "pixel") { return self.toNameTag.snapPointToPixel(point, self.snapMode); } return point; }, get smartEnabled() { const smart = self.smart ?? false; const autoAnnotation = getRoot(self)?.autoAnnotation ?? false; // @todo: Not sure why smartonly ignores autoAnnotation; It was like this from the beginning return (autoAnnotation && smart) || self.smartonly || false; }, })); export default types.compose(ControlBase, BaseTag);