diff --git a/src/layer/segmentation/style.css b/src/layer/segmentation/style.css index dd92be019..359f45ee7 100644 --- a/src/layer/segmentation/style.css +++ b/src/layer/segmentation/style.css @@ -136,3 +136,19 @@ + .neuroglancer-tool-button { margin-left: 1em; } + +.neuroglancer-segment-list-entry .neuroglancer-color-widget { + border: none; + border-color: transparent; + appearance: none; + background-color: transparent; + padding: 0; + margin: 0; + margin-left: 3px; + height: 19px; + width: 20px; +} + +.neuroglancer-segment-list-entry .neuroglancer-color-widget.overridden { + background-color: white; +} diff --git a/src/segmentation_display_state/frontend.ts b/src/segmentation_display_state/frontend.ts index df36d1249..bc50bca9c 100644 --- a/src/segmentation_display_state/frontend.ts +++ b/src/segmentation_display_state/frontend.ts @@ -47,7 +47,12 @@ import { observeWatchable, registerNestedSync } from "#src/trackable_value.js"; import { isWithinSelectionPanel } from "#src/ui/selection_details.js"; import type { Uint64Map } from "#src/uint64_map.js"; import { setClipboard } from "#src/util/clipboard.js"; -import { useWhiteBackground } from "#src/util/color.js"; +import { + TrackableRGB, + packColor, + serializeColor, + useWhiteBackground +} from "#src/util/color.js"; import { RefCounted } from "#src/util/disposable.js"; import { measureElementClone } from "#src/util/dom.js"; import type { vec3 } from "#src/util/geom.js"; @@ -59,13 +64,14 @@ import { makeCopyButton } from "#src/widget/copy_button.js"; import { makeEyeButton } from "#src/widget/eye_button.js"; import { makeFilterButton } from "#src/widget/filter_button.js"; import { makeStarButton } from "#src/widget/star_button.js"; +import { ColorWidget } from "#src/widget/color"; export class Uint64MapEntry { constructor( public key: Uint64, public value?: Uint64, public label?: string | undefined, - ) {} + ) { } toString() { const { key, value, label } = this; let baseString: string; @@ -347,6 +353,8 @@ const segmentWidgetTemplate = (() => { filterElement.classList.add("neuroglancer-segment-list-entry-filter"); const filterIndex = template.childElementCount; template.appendChild(filterElement); + const colorWidgetIndex = template.childElementCount; + template.appendChild(ColorWidget.template()); return { template, copyContainerIndex, @@ -357,6 +365,7 @@ const segmentWidgetTemplate = (() => { labelIndex, filterIndex, starIndex, + colorWidgetIndex, unmappedIdIndex: -1, unmappedCopyIndex: -1, }; @@ -426,7 +435,7 @@ function makeRegisterSegmentWidgetEventHandlers( const onMouseEnter = (event: Event) => { const entryElement = event.currentTarget as HTMLElement; const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); displayState.segmentSelectionState.set(id); if (!isWithinSelectionPanel(entryElement)) { @@ -437,7 +446,7 @@ function makeRegisterSegmentWidgetEventHandlers( const selectHandler = (event: Event) => { const entryElement = event.currentTarget as HTMLElement; const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); displayState.selectSegment( id, @@ -470,7 +479,7 @@ function makeRegisterSegmentWidgetEventHandlers( const visibleCheckboxHandler = (event: Event) => { const entryElement = getEntryElement(event); const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); const { selectedSegments, visibleSegments } = displayState.segmentationGroupState.value; @@ -486,7 +495,7 @@ function makeRegisterSegmentWidgetEventHandlers( const filterHandler = (event: Event) => { const entryElement = getEntryElement(event); const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); displayState.filterBySegmentLabel(id); event.stopPropagation(); @@ -504,7 +513,7 @@ function makeRegisterSegmentWidgetEventHandlers( } const entryElement = event.currentTarget as HTMLElement; const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); displayState.moveToSegment(id); }; @@ -539,11 +548,34 @@ function makeRegisterSegmentWidgetEventHandlers( starButton.addEventListener("click", (event: MouseEvent) => { const entryElement = getEntryElement(event); const idString = entryElement.dataset.id!; - const id = tempStatedColor; + const id = tempObjectId; id.tryParseString(idString); const { selectedSegments } = displayState.segmentationGroupState.value; selectedSegments.set(id, !selectedSegments.has(id)); }); + + const trackableRGB = new TrackableRGB(vec3.fromValues(0, 0, 0)); + trackableRGB.changed.add(() => { + const testU = new Uint64(packColor(trackableRGB.value)); + const idString = element.dataset.id!; + const id = tempObjectId; + id.tryParseString(idString); + displayState.segmentStatedColors.value.delete(id); + displayState.segmentStatedColors.value.set(id, testU); + }); + + // TODO, need to register disposer? + new ColorWidget( + trackableRGB, + undefined, + children[template.colorWidgetIndex] as HTMLInputElement, + () => { + const idString = element.dataset.id!; + const id = tempObjectId; + id.tryParseString(idString); + displayState.segmentStatedColors.value.delete(id); + }, + ); }; } @@ -641,7 +673,7 @@ export class SegmentWidgetFactory