'From Squeak3.6 of ''6 October 2003'' [latest update: #5424] on 14 October 2003 at 11:53:20 pm'! "Change Set: HierarchyNavigation-ar Date: 14 October 2003 Author: Andreas Raab Adds default keyboard navigation for hierarchical lists. If no keystrokeSelector is set, the default keyboard navigation is used. If a keystrokeSelector is set, it is the models responsibility to invoke the lists #arrowKey: method if keyboard navigation is desired. The effect is (for example) immediately noticable in the file list and the object explorer"! !SimpleHierarchicalListMorph methodsFor: 'event handling' stamp: 'ar 10/14/2003 23:40'! keyStroke: event "Process potential command keys" | args aCharacter | (self scrollByKeyboard: event) ifTrue: [^self]. aCharacter := event keyCharacter. keystrokeActionSelector isNil ifTrue: [^self arrowKey: aCharacter]. (args := keystrokeActionSelector numArgs) = 1 ifTrue: [^model perform: keystrokeActionSelector with: aCharacter]. args = 2 ifTrue: [^model perform: keystrokeActionSelector with: aCharacter with: self]. ^self error: 'The keystrokeActionSelector must be a 1- or 2-keyword symbol'! ! !SimpleHierarchicalListMorph methodsFor: 'selection' stamp: 'ar 10/14/2003 23:39'! selectionIndex: idx "Called internally to select the index-th item." | theMorph range index | idx ifNil: [^ self]. index := idx min: scroller submorphs size max: 0. (theMorph _ index = 0 ifTrue: [nil] ifFalse: [scroller submorphs at: index]) ifNotNil: [((theMorph bounds top - scroller offset y) >= 0 and: [(theMorph bounds bottom - scroller offset y) <= bounds height]) ifFalse: ["Scroll into view -- should be elsewhere" range _ self totalScrollRange. scrollBar value: (range > 0 ifTrue: [((index-1 * theMorph height) / self totalScrollRange) truncateTo: scrollBar scrollDelta] ifFalse: [0]). scroller offset: -3 @ (range * scrollBar value)]]. self selectedMorph: theMorph! ! !SimpleHierarchicalListMorph methodsFor: 'keyboard navigation' stamp: 'ar 10/14/2003 23:38'! arrowKey: aChar "Handle a keyboard navigation character. Answer true if handled, false if not." | keyEvent | keyEvent := aChar asciiValue. keyEvent == 31 ifTrue:["down" self setSelectionIndex: self getSelectionIndex+1. ^true]. keyEvent == 30 ifTrue:["up" self setSelectionIndex: (self getSelectionIndex-1 max: 1). ^true]. keyEvent == 1 ifTrue: ["home" self setSelectionIndex: 1. ^true]. keyEvent == 4 ifTrue: ["end" self setSelectionIndex: scroller submorphs size. ^true]. keyEvent == 11 ifTrue: ["page up" self setSelectionIndex: (self getSelectionIndex - self numSelectionsInView max: 1). ^true]. keyEvent == 12 ifTrue: ["page down" self setSelectionIndex: self getSelectionIndex + self numSelectionsInView. ^true]. keyEvent == 29 ifTrue:["right" selectedMorph ifNotNil:[ (selectedMorph canExpand and:[selectedMorph isExpanded not]) ifTrue:[self toggleExpandedState: selectedMorph] ifFalse:[self setSelectionIndex: self getSelectionIndex+1]. ]. ^true]. keyEvent == 28 ifTrue:["left" selectedMorph ifNotNil:[ (selectedMorph isExpanded) ifTrue:[self toggleExpandedState: selectedMorph] ifFalse:[self setSelectionIndex: (self getSelectionIndex-1 max: 1)]. ]. ^true]. ^false! ! !SimpleHierarchicalListMorph methodsFor: 'keyboard navigation' stamp: 'ar 10/14/2003 23:38'! getSelectionIndex ^scroller submorphs indexOf: selectedMorph! ! !SimpleHierarchicalListMorph methodsFor: 'keyboard navigation' stamp: 'ar 10/14/2003 23:39'! setSelectionIndex: idx "Called internally to select the index-th item." | theMorph index | idx ifNil: [^ self]. index := idx min: scroller submorphs size max: 0. theMorph _ index = 0 ifTrue: [nil] ifFalse: [scroller submorphs at: index]. self setSelectedMorph: theMorph.! ! !SimpleHierarchicalListMorph methodsFor: 'keyboard navigation' stamp: 'ar 10/14/2003 23:39'! toggleExpandedState: aMorph aMorph toggleExpandedState. self adjustSubmorphPositions. ! !