import chroma from "chroma-js";
|
import { observe } from "mobx";
|
import { useContext, useEffect, useMemo, useState } from "react";
|
import { ImageViewContext } from "../components/ImageView/ImageViewContext";
|
import Constants, { defaultStyle } from "../core/Constants";
|
import { isDefined } from "../utils/utilities";
|
|
const defaultStyles = {
|
defaultOpacity: defaultStyle.opacity,
|
defaultFillColor: defaultStyle.fillcolor,
|
defaultStrokeColor: defaultStyle.strokecolor,
|
defaultStrokeColorHighlighted: Constants.HIGHLIGHTED_STROKE_COLOR,
|
defaultStrokeWidth: defaultStyle.strokewidth,
|
defaultStrokeWidthHighlighted: Constants.HIGHLIGHTED_STROKE_WIDTH,
|
defaultSuggestionWidth: Constants.SUGGESTION_STROKE_WIDTH,
|
};
|
|
type StyleOptions = typeof defaultStyles & {
|
region: any;
|
highlighted?: boolean;
|
shouldFill?: boolean;
|
suggestion?: boolean;
|
includeFill?: boolean;
|
useStrokeAsFill?: boolean;
|
sameStrokeWidthForSelected?: boolean;
|
};
|
|
export const getRegionStyles = ({
|
region,
|
highlighted = false,
|
shouldFill = false,
|
useStrokeAsFill = false,
|
sameStrokeWidthForSelected = false,
|
suggestion = false,
|
defaultOpacity = defaultStyle.opacity,
|
defaultFillColor = defaultStyle.fillcolor,
|
defaultStrokeColor = defaultStyle.strokecolor,
|
defaultStrokeColorHighlighted = Constants.HIGHLIGHTED_STROKE_COLOR,
|
defaultStrokeWidth = defaultStyle.strokewidth,
|
defaultStrokeWidthHighlighted = Constants.HIGHLIGHTED_STROKE_WIDTH,
|
defaultSuggestionWidth = Constants.SUGGESTION_STROKE_WIDTH,
|
}: StyleOptions) => {
|
const style = region.style || region.tag;
|
|
const selected = region.inSelection || highlighted;
|
|
const fillopacity = style?.fillopacity;
|
const opacity = isDefined(fillopacity) ? fillopacity : style?.opacity;
|
|
const fillColor = shouldFill
|
? chroma((useStrokeAsFill ? style?.strokecolor : style?.fillcolor) ?? defaultFillColor)
|
.darken(0.3)
|
.alpha(+(opacity ?? defaultOpacity ?? 0.5))
|
.css()
|
: null;
|
|
const strokeColor = selected ? defaultStrokeColorHighlighted : chroma(style?.strokecolor ?? defaultStrokeColor).css();
|
|
const strokeWidth = (() => {
|
if (suggestion) {
|
return defaultSuggestionWidth;
|
}
|
if (selected && !sameStrokeWidthForSelected) {
|
return defaultStrokeWidthHighlighted;
|
}
|
return +(style?.strokewidth ?? defaultStrokeWidth);
|
})();
|
|
return {
|
strokeColor,
|
fillColor,
|
strokeWidth,
|
};
|
};
|
|
export const useRegionStyles = (region: any, options: Partial<StyleOptions> = {}) => {
|
const { suggestion } = useContext(ImageViewContext) ?? {};
|
const [highlighted, setHighlighted] = useState(region.highlighted);
|
const [shouldFill, setShouldFill] = useState(region.fill ?? (options.useStrokeAsFill || options.includeFill));
|
|
const styles = useMemo(() => {
|
return getRegionStyles({
|
...defaultStyles,
|
...(options ?? {}),
|
highlighted,
|
shouldFill,
|
region,
|
suggestion,
|
});
|
}, [region, suggestion, options, highlighted, shouldFill]);
|
|
useEffect(() => {
|
const disposeObserver = ["highlighted", "fill"].map((prop) => {
|
try {
|
return observe(
|
region,
|
prop,
|
({ newValue }) => {
|
switch (prop) {
|
case "highlighted":
|
return setHighlighted(newValue);
|
case "fill":
|
return setShouldFill(newValue);
|
}
|
},
|
true,
|
);
|
} catch (e) {
|
return () => {};
|
}
|
});
|
|
return () => {
|
disposeObserver.forEach((dispose) => dispose());
|
};
|
}, [region]);
|
|
return styles;
|
};
|