Skip to content

Commit 0df21c5

Browse files
authored
Merge pull request #114 from MetaCell/fix/enum-default-select
feat: create an enum default select
2 parents 1414c0e + 7471b55 commit 0df21c5

File tree

2 files changed

+104
-4
lines changed

2 files changed

+104
-4
lines changed

src/ui/annotation_schema_tab.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,33 @@
6060
width: 100%;
6161
}
6262

63+
.neuroglancer-annotation-schema-enum-default-selector {
64+
display: flex;
65+
align-items: center;
66+
margin-bottom: 12px;
67+
}
68+
69+
.neuroglancer-annotation-schema-enum-default-label {
70+
margin-right: 8px;
71+
font-size: 12px;
72+
color: #ccc;
73+
}
74+
75+
.neuroglancer-annotation-schema-enum-default-select {
76+
background: #2a2a2a;
77+
border: 1px solid #555;
78+
color: white;
79+
padding: 2px 4px;
80+
border-radius: 2px;
81+
font-size: 12px;
82+
width: 100%;
83+
}
84+
85+
.neuroglancer-annotation-schema-enum-default-select:focus {
86+
border-color: #007acc;
87+
outline: none;
88+
}
89+
6390
.neuroglancer-annotation-schema-default-value-input {
6491
text-align: left;
6592
width: 100%;

src/ui/annotation_schema_tab.ts

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,14 @@ class AnnotationUIProperty extends RefCounted {
196196
// For numeric types, we can set the default value directly
197197
const type = this.spec.type;
198198
if (isAnnotationTypeNumeric(type)) {
199-
this.defaultValueElements[0].value = numberToStringFixed(defaultValue, 4);
199+
const enumLabels = (this.spec as AnnotationNumericPropertySpec)
200+
.enumLabels;
201+
if (!isEnumType(enumLabels)) {
202+
this.defaultValueElements[0].value = numberToStringFixed(
203+
defaultValue,
204+
4,
205+
);
206+
}
200207
}
201208
// For color types, we need to unpack the color and set the RGB values
202209
else if (type.startsWith("rgb")) {
@@ -511,6 +518,11 @@ class AnnotationUIProperty extends RefCounted {
511518

512519
const inputs: (HTMLInputElement | HTMLTextAreaElement)[] = [];
513520

521+
if (!this.readonly) {
522+
const defaultSelector = this.createEnumDefaultSelector(oldProperty);
523+
enumContainer.appendChild(defaultSelector);
524+
}
525+
514526
for (let i = 0; i < enumValues!.length; i++) {
515527
const entryInputs = this.createEnumEntry(
516528
enumValues![i],
@@ -532,6 +544,48 @@ class AnnotationUIProperty extends RefCounted {
532544
return inputs;
533545
}
534546

547+
private createEnumDefaultSelector(
548+
enumProperty: AnnotationNumericPropertySpec,
549+
): HTMLDivElement {
550+
const selectorContainer = document.createElement("div");
551+
selectorContainer.className =
552+
"neuroglancer-annotation-schema-enum-default-selector";
553+
554+
const label = document.createElement("label");
555+
label.textContent = "Default:";
556+
label.className = "neuroglancer-annotation-schema-enum-default-label";
557+
558+
const select = document.createElement("select");
559+
select.className = "neuroglancer-annotation-schema-enum-default-select";
560+
561+
enumProperty.enumValues?.forEach((value: number, index: number) => {
562+
const option = document.createElement("option");
563+
option.value = String(value);
564+
if (!enumProperty.enumLabels) {
565+
option.textContent = "Non-schema value";
566+
} else {
567+
option.textContent = enumProperty.enumLabels[index];
568+
}
569+
option.selected = value === enumProperty.default;
570+
select.appendChild(option);
571+
});
572+
573+
select.addEventListener("change", (event) => {
574+
const selectedValue = parseFloat(
575+
(event.target as HTMLSelectElement).value,
576+
);
577+
const existingProperty = this.getPropertyByIdentifier(
578+
enumProperty.identifier,
579+
) as AnnotationNumericPropertySpec;
580+
this.updateProperty(existingProperty, { default: selectedValue });
581+
});
582+
583+
selectorContainer.appendChild(label);
584+
selectorContainer.appendChild(select);
585+
586+
return selectorContainer;
587+
}
588+
535589
private createNumericInputs(
536590
type: AnnotationPropertyType,
537591
oldProperty: any,
@@ -585,13 +639,21 @@ class AnnotationUIProperty extends RefCounted {
585639
);
586640
const newEnumValues = [...currentEnumValues!, suggestedEnumValue];
587641

642+
// Keep the current default value if it's still valid
643+
// otherwise use the first value
644+
// this could occur if the user deletes all values then adds a new one
645+
const currentDefault = currentProperty.default;
646+
const newDefault = newEnumValues.includes(currentDefault)
647+
? currentDefault
648+
: newEnumValues[0];
649+
588650
this.updateProperty(currentProperty, {
589651
enumValues: newEnumValues,
590652
enumLabels: [
591653
...currentProperty.enumLabels!,
592654
`${suggestedEnumValue} (label)`,
593655
],
594-
default: newEnumValues[0],
656+
default: newDefault,
595657
} as AnnotationNumericPropertySpec);
596658
},
597659
});
@@ -700,9 +762,17 @@ class AnnotationUIProperty extends RefCounted {
700762
(_, i) => i !== enumIndex,
701763
);
702764

765+
// If we're deleting the current default value, set the new default to the first remaining value
766+
const deletedValue = currentProperty.enumValues![enumIndex];
767+
const newDefault =
768+
currentProperty.default === deletedValue
769+
? (newEnumValues[0] ?? 0)
770+
: currentProperty.default;
771+
703772
this.updateProperty(currentProperty, {
704773
enumValues: newEnumValues,
705774
enumLabels: newEnumLabels,
775+
default: newDefault,
706776
});
707777
},
708778
});
@@ -1021,7 +1091,10 @@ export class AnnotationSchemaView extends Tab {
10211091

10221092
private updateAnnotationText() {
10231093
const setOrViewText = this.readonly.value ? "View read-only" : "Set";
1024-
this.schemaViewTextElement.textContent = `${setOrViewText} annotation property (metadata) schema for this layer which applies to all annotations in this layer.`;
1094+
const setExplainText = this.readonly.value
1095+
? ""
1096+
: " Changing a default value in the schema is not retroactive and only applies to new annotations.";
1097+
this.schemaViewTextElement.textContent = `${setOrViewText} annotation property (metadata) schema for this layer which applies to all annotations in this layer.${setExplainText}`;
10251098
}
10261099

10271100
private updateElementVisibility() {
@@ -1470,7 +1543,7 @@ export class AnnotationSchemaView extends Tab {
14701543
if (isEnum && isAnnotationTypeNumeric(type)) {
14711544
return {
14721545
enumValues: [0],
1473-
enumLabels: ["Default"],
1546+
enumLabels: ["0 (label)"],
14741547
};
14751548
}
14761549
return {};

0 commit comments

Comments
 (0)