@@ -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