Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color widget in the layer-bar #54

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6c2d3e6
CC-127 Add first PoC about changing layer's title background color
aranega Nov 1, 2024
5dfafe8
Add first version of layer color widget
aranega Nov 12, 2024
6de87f1
Add first color widget in left layer bar
aranega Nov 12, 2024
4b79ce7
Add indicator to express that color is not visible even if active
aranega Nov 12, 2024
110b99b
Fix disposer logic for layer color computation
aranega Nov 13, 2024
9ea3b1e
Add support for color indicator for annotation layer
aranega Nov 21, 2024
149d030
Fix format
aranega Nov 26, 2024
4f8a477
Add color sync setting in layer state
aranega Nov 27, 2024
a3a2365
Add single color sync when only 1 label is visible in segmentation layer
aranega Nov 27, 2024
61a6c86
Fix color legend widget sync accross layerbar and layer panel
aranega Nov 27, 2024
ff96fd4
CC-167 update rainbow circle
Aiga115 Nov 27, 2024
f2e2111
Merge branch 'feature/CC-127' into feature/CC-167
Aiga115 Nov 27, 2024
f9cae7f
CC-167 reduce blur on rainbow circle
Aiga115 Nov 27, 2024
2229c8f
CC-167 update ui of circle labels
Aiga115 Nov 28, 2024
d5f9c52
Merge pull request #58 from MetaCell/feature/CC-167
aranega Dec 5, 2024
9d66b66
Fix rainbow color not removing when number of visible segment changes
aranega Dec 6, 2024
f33816a
Move color widget to the left of the title in layer bar
aranega Dec 6, 2024
340be26
Add general option for enabling/disabling color widget
aranega Dec 6, 2024
5aab0c4
Remove unused trackable boolean for color sync inside a layer
aranega Dec 6, 2024
91dbfba
Fix format
aranega Dec 6, 2024
83cde4f
Add layer bar color change on color seed change
aranega Dec 6, 2024
46c78e8
Refactor color widget in layer bar
aranega Dec 9, 2024
bddd998
Fix issue with color widget not updated when activated for the first
aranega Dec 17, 2024
491a15d
Fix unsupported style activation for layer list panel
aranega Dec 17, 2024
5b9fa3f
Merge branch 'master' into feature/CC-127
aranega Dec 17, 2024
b413a56
CC-189 make changes to ui of non color state circle
Aiga115 Dec 20, 2024
5e22083
Display a rainbow when the default annotation color is not used in the
aranega Dec 20, 2024
cd24b91
CC-189 remove comment
Aiga115 Dec 20, 2024
c9f8ecf
Change tooltip message for annotation with rainbow
aranega Dec 20, 2024
7ad72ff
Fix layer widget color not updating for annotation
aranega Dec 20, 2024
ec248e2
Merge branch 'feature/CC-127' of github.com:MetaCell/neuroglancer int…
aranega Dec 20, 2024
1f873d1
Merge pull request #60 from MetaCell/feature/CC-189
aranega Dec 20, 2024
e5fe020
CC-200 initial changes made
Aiga115 Dec 20, 2024
50cd9d2
Merge pull request #61 from MetaCell/feature/CC-200
aranega Dec 21, 2024
c42c86d
chore: formatting pass
seankmartin Jan 8, 2025
b9ed80d
feat: clarify tooltip for non-default color annotations
seankmartin Jan 8, 2025
1857d19
CC-127 Remove grid pattern when the layer type changes
aranega Jan 8, 2025
4fbb7b2
CC-127 Update color widget in the layer list when layer type changes
aranega Jan 8, 2025
66e6d39
CC-127 Add tooltip when the layer doesn't support color widget
aranega Jan 8, 2025
66405e1
CC-127 Remove redundant code for color widget from then layer list
aranega Jan 8, 2025
4520ef2
CC-127 Remove user-defined color for layers
aranega Jan 8, 2025
166ff6f
CC-127 Change setting label from color widget to color legend
aranega Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/data_panel_layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export interface ViewerUIState
inputEventBindings: InputEventBindings;
crossSectionBackgroundColor: TrackableRGB;
perspectiveViewBackgroundColor: TrackableRGB;
enableLayerColorWidget: TrackableBoolean;
}

export interface DataDisplayLayout extends RefCounted {
Expand Down Expand Up @@ -180,6 +181,7 @@ export function getCommonViewerState(viewer: ViewerUIState) {
selectedLayer: viewer.selectedLayer,
visibility: viewer.visibility,
scaleBarOptions: viewer.scaleBarOptions,
enableLayerColorWidget: viewer.enableLayerColorWidget,
};
}

Expand Down
44 changes: 43 additions & 1 deletion src/layer/annotation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ import { RenderLayerRole } from "#src/renderlayer.js";
import type { SegmentationDisplayState } from "#src/segmentation_display_state/frontend.js";
import type { TrackableBoolean } from "#src/trackable_boolean.js";
import { TrackableBooleanCheckbox } from "#src/trackable_boolean.js";
import { makeCachedLazyDerivedWatchableValue } from "#src/trackable_value.js";
import {
makeCachedLazyDerivedWatchableValue,
observeWatchable,
} from "#src/trackable_value.js";
import type {
AnnotationLayerView,
MergedAnnotationStates,
Expand Down Expand Up @@ -713,8 +716,47 @@ export class AnnotationUserLayer extends Base {
return x;
}

observeLayerColor(callback: () => void) {
const disposer = super.observeLayerColor(callback);
const subDisposer = observeWatchable(
callback,
this.annotationDisplayState.color,
);
const shaderDisposer = observeWatchable(
callback,
this.annotationDisplayState.shader,
);
return () => {
disposer();
subDisposer();
shaderDisposer();
};
}

get automaticLayerBarColor() {
const shaderHasDefaultColor =
this.annotationDisplayState.shader.value.includes("defaultColor");
if (shaderHasDefaultColor && this.annotationDisplayState.color.value) {
const [r, g, b] = this.annotationDisplayState.color.value;
return `rgb(${r * 255}, ${g * 255}, ${b * 255})`;
}

return undefined;
}

colorWidgetTooltip(): string | undefined {
const shaderHasDefaultColor =
this.annotationDisplayState.shader.value.includes("defaultColor");
if (shaderHasDefaultColor && this.annotationDisplayState.color.value) {
return `The color comes from the selected shader default color`;
}

return "Your shader code doesn't use the default color, we cannot determine which color you are using";
}

static type = "annotation";
static typeAbbreviation = "ann";
static supportsLayerBarColorSyncOption = true;
}

function makeShaderCodeWidget(layer: AnnotationUserLayer) {
Expand Down
44 changes: 44 additions & 0 deletions src/layer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,30 @@ export class UserLayer extends RefCounted {
}

static supportsPickOption = false;
static supportsLayerBarColorSyncOption = false;

pick = new TrackableBoolean(true, true);

selectionState: UserLayerSelectionState;

messages = new MessageList();

observeLayerColor(_: () => void): () => void {
return () => {};
}

get automaticLayerBarColor(): string | undefined {
return "";
}

get layerBarColor(): string | undefined {
return this.automaticLayerBarColor;
}

colorWidgetTooltip(): string | undefined {
return undefined;
}

initializeSelectionState(state: this["selectionState"]) {
state.generation = -1;
state.localPositionValid = false;
Expand Down Expand Up @@ -740,6 +757,33 @@ export class ManagedUserLayer extends RefCounted {
}
}

get layerBarColor(): string | undefined {
const userLayer = this.layer;
return userLayer?.layerBarColor;
}

colorWidgetTooltip(): string | undefined {
const userLayer = this.layer;
return userLayer?.colorWidgetTooltip();
}

observeLayerColor(callback: () => void): () => void {
const userLayer = this.layer;
if (userLayer !== null) {
return userLayer.observeLayerColor(callback);
}
return () => {};
}

get supportsLayerBarColorSyncOption() {
const userLayer = this.layer;
return (
userLayer !== null &&
(userLayer.constructor as typeof UserLayer)
.supportsLayerBarColorSyncOption
);
}

/**
* If layer is not null, tranfers ownership of a reference.
*/
Expand Down
58 changes: 58 additions & 0 deletions src/layer/segmentation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ import {
IndirectWatchableValue,
makeCachedDerivedWatchableValue,
makeCachedLazyDerivedWatchableValue,
observeWatchable,
registerNestedSync,
TrackableValue,
WatchableValue,
Expand Down Expand Up @@ -1282,9 +1283,66 @@ export class SegmentationUserLayer extends Base {
);
}

observeLayerColor(callback: () => void) {
const disposer = super.observeLayerColor(callback);
const defaultColorDisposer = observeWatchable(
callback,
this.displayState.segmentDefaultColor,
);
const visibleSegmentDisposer =
this.displayState.segmentationGroupState.value.visibleSegments.changed.add(
callback,
);
const colorHashChangeDisposer =
this.displayState.segmentationColorGroupState.value.segmentColorHash.changed.add(
callback,
);
return () => {
disposer();
defaultColorDisposer();
visibleSegmentDisposer();
colorHashChangeDisposer();
};
}

get automaticLayerBarColor() {
if (this.displayState.segmentDefaultColor.value) {
const [r, g, b] = this.displayState.segmentDefaultColor.value;
return `rgb(${r * 255}, ${g * 255}, ${b * 255})`;
}

const visibleSegments =
this.displayState.segmentationGroupState.value.visibleSegments;
if (visibleSegments.size === 1) {
const id = [...visibleSegments][0];
const color =
this.displayState.segmentationColorGroupState.value.segmentColorHash.computeCssColor(
id,
);
return color;
}

return undefined;
}

colorWidgetTooltip(): string {
if (this.displayState.segmentDefaultColor.value) {
return `The color comes from the manually selected color`;
}

const visibleSegments =
this.displayState.segmentationGroupState.value.visibleSegments;
if (visibleSegments.size === 1) {
const id = [...visibleSegments][0];
return `The color of the visible segment with id "${id}"`;
}
return "The segmentation layer has multiple segments visible";
}

static type = "segmentation";
static typeAbbreviation = "seg";
static supportsPickOption = true;
static supportsLayerBarColorSyncOption = true;
}

registerLayerControls(SegmentationUserLayer);
Expand Down
4 changes: 4 additions & 0 deletions src/layer_group_viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export interface LayerGroupViewerState {
visibleLayerRoles: WatchableSet<RenderLayerRole>;
crossSectionBackgroundColor: TrackableRGB;
perspectiveViewBackgroundColor: TrackableRGB;
enableLayerColorWidget: TrackableBoolean;
}

export interface LayerGroupViewerOptions {
Expand Down Expand Up @@ -381,6 +382,9 @@ export class LayerGroupViewer extends RefCounted {
get scaleBarOptions() {
return this.viewerState.scaleBarOptions;
}
get enableLayerColorWidget() {
return this.viewerState.enableLayerColorWidget;
}
layerPanel: LayerBar | undefined;
layout: DataPanelLayoutContainer;
toolBinder: LocalToolBinder<this>;
Expand Down
1 change: 1 addition & 0 deletions src/layer_groups_layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ function getCommonViewerState(viewer: Viewer) {
velocity: viewer.velocity.addRef(),
crossSectionBackgroundColor: viewer.crossSectionBackgroundColor,
perspectiveViewBackgroundColor: viewer.perspectiveViewBackgroundColor,
enableLayerColorWidget: viewer.enableLayerColorWidget,
};
}

Expand Down
95 changes: 95 additions & 0 deletions src/ui/layer_bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,101 @@
align-items: center;
}

.neuroglancer-layer-color-value {
border-radius: 50%;
height: 10px;
width: 10px;
}

.neuroglancer-layer-item[data-color="fixed"] .neuroglancer-layer-color-value {
border-radius: 50%;
height: 10px;
width: 10px;
}

.neuroglancer-layer-item[data-color="rainbow"] .neuroglancer-layer-color-value {
position: relative;
border-radius: 50%;
height: 10px;
width: 10px;
overflow: hidden;
}

.neuroglancer-layer-item[data-color="rainbow"]
.neuroglancer-layer-color-value::before {
content: "";
position: absolute;
top: -17.5%;
left: -17.5%;
width: 135%;
height: 135%;
background: conic-gradient(
from 0deg,
hsl(0, 100%, 50%),
hsl(60, 100%, 50%),
hsl(120, 100%, 50%),
hsl(180, 100%, 50%),
hsl(240, 100%, 50%),
hsl(300, 100%, 50%),
hsl(360, 100%, 50%)
);
filter: blur(1px);
transform: scale(1.35);
}

.neuroglancer-layer-item[data-color="unsupported"]
.neuroglancer-layer-color-value {
background-image: linear-gradient(
45deg,
rgba(128, 128, 128, 1.5) 25%,
transparent 25%
),
linear-gradient(-45deg, rgba(128, 128, 128, 1.5) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, rgba(128, 128, 128, 1.5) 75%),
linear-gradient(-45deg, transparent 75%, rgba(128, 128, 128, 1.5) 75%);
background-size: 4px 4px;
background-position:
0 0,
0 2px,
2px -2px,
-2px 0px;
}

.neuroglancer-layer-color-value-wrapper {
position: relative;
width: 10px;
height: 10px;
padding: 5px;
margin: 0 4px;
}

.neuroglancer-layer-item[data-color="unsupported"]
.neuroglancer-layer-color-value-wrapper {
position: relative;
}

.neuroglancer-layer-item[data-visible="false"]
.neuroglancer-layer-color-value-wrapper
.neuroglancer-layer-color-value,
.neuroglancer-layer-item[data-visible="false"]
.neuroglancer-layer-color-value-wrapper
.neuroglancer-layer-color-value::before {
opacity: 0.4;
}

.neuroglancer-layer-item[data-visible="false"]
.neuroglancer-layer-color-value-wrapper::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 18px;
height: 1px;
background-color: rgb(255, 255, 255);
transform: translate(-50%, -50%) rotate(135deg);
z-index: 1;
}

.neuroglancer-layer-item-value {
grid-row: 1;
grid-column: 1;
Expand Down
Loading
Loading