@@ -218,22 +218,49 @@ export function H5BrowserDialog({ initial, onImport, onCancel }: Props) {
218218 [ updateCurrent ] ,
219219 ) ;
220220
221- const setExpandedAll = useCallback (
222- ( expand : boolean ) => {
223- updateCurrent ( ( s ) => {
224- const next = new Set < string > ( ) ;
225- if ( expand ) collectIds ( s . file . root , next ) ;
226- else next . add ( s . file . root . id ) ;
227- return { ...s , expanded : next } ;
228- } ) ;
229- } ,
230- [ updateCurrent ] ,
231- ) ;
221+ const expandAll = useCallback ( ( ) => {
222+ updateCurrent ( ( s ) => {
223+ const next = new Set < string > ( ) ;
224+ collectIds ( s . file . root , next ) ;
225+ return { ...s , expanded : next } ;
226+ } ) ;
227+ } , [ updateCurrent ] ) ;
232228
233- const restoreLayout = useCallback ( ( ) => {
229+ // Collapse all = restore the initial layout (root + first level expanded),
230+ // mirroring Qt's H5TreeWidget.restore() behaviour.
231+ const collapseAll = useCallback ( ( ) => {
234232 updateCurrent ( ( s ) => ( { ...s , expanded : defaultExpanded ( s . file . root ) } ) ) ;
235233 } , [ updateCurrent ] ) ;
236234
235+ const expandSelection = useCallback ( ( ) => {
236+ updateCurrent ( ( s ) => {
237+ const target =
238+ ( selectedNodeId && findNode ( s . file . root , selectedNodeId ) ) ||
239+ s . file . root ;
240+ const next = new Set ( s . expanded ) ;
241+ collectIds ( target , next ) ;
242+ return { ...s , expanded : next } ;
243+ } ) ;
244+ } , [ updateCurrent , selectedNodeId ] ) ;
245+
246+ const collapseSelection = useCallback ( ( ) => {
247+ updateCurrent ( ( s ) => {
248+ const target =
249+ ( selectedNodeId && findNode ( s . file . root , selectedNodeId ) ) ||
250+ s . file . root ;
251+ const ids = new Set < string > ( ) ;
252+ collectIds ( target , ids ) ;
253+ // Keep the target itself expanded only if it is the root (so the tree
254+ // never becomes a single collapsed line); descendants are all collapsed.
255+ const next = new Set < string > ( ) ;
256+ for ( const id of s . expanded ) {
257+ if ( ! ids . has ( id ) ) next . add ( id ) ;
258+ }
259+ if ( target === s . file . root ) next . add ( s . file . root . id ) ;
260+ return { ...s , expanded : next } ;
261+ } ) ;
262+ } , [ updateCurrent , selectedNodeId ] ) ;
263+
237264 const toggleCheck = useCallback (
238265 ( id : string ) => {
239266 updateCurrent ( ( s ) => {
@@ -379,14 +406,33 @@ export function H5BrowserDialog({ initial, onImport, onCancel }: Props) {
379406 Close
380407 </ button >
381408 < span className = "h5browser-spacer" />
382- < button type = "button" onClick = { ( ) => setExpandedAll ( true ) } >
409+ < button
410+ type = "button"
411+ onClick = { expandAll }
412+ disabled = { ! currentFile }
413+ >
383414 Expand all
384415 </ button >
385- < button type = "button" onClick = { ( ) => setExpandedAll ( false ) } >
416+ < button
417+ type = "button"
418+ onClick = { collapseAll }
419+ disabled = { ! currentFile }
420+ >
386421 Collapse all
387422 </ button >
388- < button type = "button" onClick = { restoreLayout } >
389- Restore
423+ < button
424+ type = "button"
425+ onClick = { expandSelection }
426+ disabled = { ! currentFile }
427+ >
428+ Expand selection
429+ </ button >
430+ < button
431+ type = "button"
432+ onClick = { collapseSelection }
433+ disabled = { ! currentFile }
434+ >
435+ Collapse selection
390436 </ button >
391437 </ div >
392438
0 commit comments