Skip to content

Color legend in the layer-bar #693

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

Open
wants to merge 82 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 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
98a4294
Merge branch 'master' into feature/CC-127
aranega Mar 26, 2025
6e15065
CC-202 Fix unsupported icon not displayed by default
aranega Mar 26, 2025
0926187
Merge branch 'master' into feature/CC-298
seankmartin Apr 28, 2025
93217ab
feat: change color widget to color background
seankmartin Apr 28, 2025
e311ddb
feat: remove color legend as being a setting
seankmartin Apr 28, 2025
733d81e
fix: add initial call to color widget update
seankmartin Apr 28, 2025
b568dd2
feat: remove layer tooltip color
seankmartin Apr 28, 2025
8f1f38c
refactor: use css data attributes not add/remove class
seankmartin Apr 28, 2025
8333ea7
fix: remove pick color and unused CSS
seankmartin Apr 28, 2025
44077cf
fix: restore parity with main and lower opacity on hidden
seankmartin Apr 28, 2025
ee68aef
refactor, fix: rename element, and change visible as part of update
seankmartin Apr 28, 2025
933092c
Merge pull request #81 from MetaCell/feature/CC-298
seankmartin Apr 29, 2025
fd2c89f
CC-127 Refactor logic for computing the color of segmentation layer
aranega May 1, 2025
2a78274
feat: don't show color on hidden layers
seankmartin May 8, 2025
39f2f25
refactor: separate the color from the text label in top bar
seankmartin May 8, 2025
4f853a4
fix: restore rainbow color
seankmartin May 8, 2025
eae82d3
refactor: colors is now array not string
seankmartin May 8, 2025
5ee68bc
feat: support up to three seg colors in layer bar
seankmartin May 8, 2025
fc9174d
feat: allow multi color in side bar
seankmartin May 8, 2025
1154441
feat: sort colors so that not random in UI
seankmartin May 8, 2025
6584197
refactor: clean up a little the color getting from seg layer
seankmartin May 8, 2025
cc41269
refactor: simplify css
seankmartin May 8, 2025
e8760f5
chore: format
seankmartin May 8, 2025
5dbb801
fix: when creating a new layer or copying a layer the underlying user…
seankmartin May 8, 2025
9d80629
refactor: replace magic number by const
seankmartin May 8, 2025
fb4b89e
fix: don't double multi setup listeners
seankmartin May 12, 2025
5b0744c
feat(ui): improve color indicators
seankmartin May 12, 2025
6e842f6
fix: correct style for single color
seankmartin May 12, 2025
6d56fa9
CC-327 Remove empty string from list for default value
aranega May 14, 2025
549be41
feat: support showing no color on seg layers with no seg and show all…
seankmartin May 14, 2025
4c70d35
Merge pull request #82 from MetaCell/feature/CC-327
seankmartin May 14, 2025
36c5551
chore: format and liknt
seankmartin May 14, 2025
abfcb81
feat: complete hide color in side bar for archived layers
seankmartin May 14, 2025
8965e1f
fix: layer top bar also listens to color change
seankmartin May 15, 2025
e8e0759
fix: reverse side bar colors so in same order as top bar
seankmartin May 15, 2025
a865f5e
fix: have rainbow in list panel match order for consistency
seankmartin May 16, 2025
2f24d1f
fix: correct listening for color change if the layer was already ready
seankmartin May 21, 2025
6889758
fix: listen to color change in layers that changed type or were newly…
seankmartin May 21, 2025
4e87837
fix: account for both fixed color usage and manually mapping seg IDs …
seankmartin May 22, 2025
dcd280b
feat: remove color rainbow from top bar
seankmartin May 22, 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
34 changes: 33 additions & 1 deletion src/layer/annotation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ import {
TrackableBoolean,
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 @@ -731,8 +734,37 @@ 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 automaticLayerBarColors() {
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;
}

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

function makeShaderCodeWidget(layer: AnnotationUserLayer) {
Expand Down
35 changes: 35 additions & 0 deletions src/layer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,26 @@ 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 automaticLayerBarColors(): string[] | undefined {
return [];
}

get layerBarColors(): string[] | undefined {
return this.automaticLayerBarColors;
}

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

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

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
84 changes: 83 additions & 1 deletion src/layer/segmentation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
RenderScaleHistogram,
trackableRenderScaleTarget,
} from "#src/render_scale_statistics.js";
import { SegmentColorHash } from "#src/segment_color.js";
import { getCssColor, SegmentColorHash } from "#src/segment_color.js";
import type {
SegmentationColorGroupState,
SegmentationDisplayState,
Expand All @@ -54,6 +54,7 @@ import type {
import {
augmentSegmentId,
bindSegmentListWidth,
getBaseObjectColor,
makeSegmentWidget,
maybeAugmentSegmentId,
registerCallbackWhenSegmentationDisplayStateChanged,
Expand Down Expand Up @@ -95,6 +96,7 @@ import {
IndirectWatchableValue,
makeCachedDerivedWatchableValue,
makeCachedLazyDerivedWatchableValue,
observeWatchable,
registerNestedSync,
TrackableValue,
WatchableValue,
Expand Down Expand Up @@ -131,6 +133,8 @@ import { makeWatchableShaderError } from "#src/webgl/dynamic_shader.js";
import type { DependentViewContext } from "#src/widget/dependent_view_widget.js";
import { registerLayerShaderControlsTool } from "#src/widget/shader_controls.js";

const MAX_LAYER_BAR_UI_INDICATOR_COLORS = 6;

export class SegmentationUserLayerGroupState
extends RefCounted
implements SegmentationGroupState
Expand Down Expand Up @@ -1287,9 +1291,87 @@ 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,
);
const showAllByDefaultDisposer =
this.displayState.ignoreNullVisibleSet.changed.add(callback);
return () => {
disposer();
defaultColorDisposer();
visibleSegmentDisposer();
colorHashChangeDisposer();
showAllByDefaultDisposer();
};
}

get automaticLayerBarColors() {
const { displayState } = this;
const visibleSegmentsSet =
displayState.segmentationGroupState.value.visibleSegments;
const fixedColor = displayState.segmentDefaultColor.value;

const noVisibleSegments = visibleSegmentsSet.size === 0;
const tooManyVisibleSegments =
visibleSegmentsSet.size > MAX_LAYER_BAR_UI_INDICATOR_COLORS;
const hasMappedColors =
displayState.segmentationColorGroupState.value.segmentStatedColors.size >
0;
const isFixedColorOnly = fixedColor !== undefined && !hasMappedColors;
const showAllByDefault = displayState.ignoreNullVisibleSet.value;

if (noVisibleSegments) {
if (!showAllByDefault) return []; // No segments visible
if (isFixedColorOnly) return [getCssColor(fixedColor)];
return undefined; // Rainbow colors
}
if (isFixedColorOnly) {
return [getCssColor(fixedColor)]; // All segments show as one color
}

// Because manually mapped colors are not guaranteed to be unique,
// we need to actually check all the visible segments if
// manually mapped colors are used
if (!hasMappedColors && tooManyVisibleSegments) {
return undefined; // Too many segments to show
}

const visibleSegments = [...visibleSegmentsSet];
const colors = visibleSegments.map((id) => {
const color = getCssColor(getBaseObjectColor(displayState, id));
return { color, id };
});

// Sort the colors by their segment ID
// Otherwise, the order is random which is a bit confusing in the UI
colors.sort((a, b) => {
const aId = a.id;
const bId = b.id;
return aId < bId ? -1 : aId > bId ? 1 : 0;
});

const uniqueColors = [...new Set(colors.map((color) => color.color))];
if (uniqueColors.length > MAX_LAYER_BAR_UI_INDICATOR_COLORS) {
return undefined; // Too many colors to show
}
return uniqueColors;
}

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

registerLayerControls(SegmentationUserLayer);
Expand Down
25 changes: 20 additions & 5 deletions src/ui/layer_bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,11 @@
border-color: #daa520;
}

.neuroglancer-layer-item[data-pick="true"] .neuroglancer-layer-item-label {
background-color: #939;
}

.neuroglancer-layer-item-label {
display: inline-block;
position: relative;
background-color: #222;
padding-right: 3px;
z-index: 1;
}

.neuroglancer-layer-item-number {
Expand Down Expand Up @@ -134,6 +130,25 @@
align-items: center;
}

.neuroglancer-layer-item-label-wrapper {
position: relative;
overflow: hidden;
}

.neuroglancer-layer-item-label-color {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 0;
}

.neuroglancer-layer-item-label-color[data-color="multi"] {
transform: scale(1.2);
filter: blur(8px);
}

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