'From Squeak 2.4c of May 10, 1999 on 28 June 1999 at 10:41:28 pm'! "Change Set: BrowserKeyboardEnhancements Date: 28 June 1999 Author: Joshua Gargus This enhancement lets you navigate through the panes of a Browser with the left and right arrow keys. You can also query a Browser for its desired focus pane. For example, if you are using my WindowSelection enhancement (highly recommended ;-), then when you select a window, the keyboard focus can be switched to the desired pane. Doesn't work outside of Morphic, although it wouldn't be hard to make it do so. This won't work on existing Browsers; open new ones. You will also have to reinstate the default flaps; I didn't do this in the postscript so as not to hose anyone's custom flaps."! StringHolder subclass: #Browser instanceVariableNames: 'systemOrganizer classOrganizer metaClassOrganizer systemCategoryListIndex classListIndex messageCategoryListIndex messageListIndex editSelection metaClassIndicated panes paneIndex ' classVariableNames: 'RecentClasses ' poolDictionaries: '' category: 'Interface-Browser'! MorphicModel subclass: #SystemWindow instanceVariableNames: 'labelString stripes label closeBox collapseBox activeOnlyOnTop paneMorphs paneRects collapsedFrame fullFrame isCollapsed focusMorph ' classVariableNames: 'TopWindow ' poolDictionaries: '' category: 'Morphic-Windows'! !Browser methodsFor: 'initialize-release' stamp: 'jcg 6/22/1999 17:43'! openAsMorphClassEditing: editString "Create a pluggable version a Browser on just a single class." | window switches codePane messageList categoryList | window _ (SystemWindow labelled: 'later') model: self. window addMorph: (PluggableListMorph on: self list: #classListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #classListMenu: keystroke: #classListKey:from:) frame: (0@0 extent: 0.5@0.06). switches _ self buildMorphicSwitches. window addMorph: switches frame: (0.5@0 extent: 0.5@0.06). switches borderWidth: 0. categoryList _ PluggableListMorph on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu: . window addMorph: categoryList frame: (0@0.06 extent: 0.5@0.30). messageList _ PluggableListMorph on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from: . window addMorph: messageList frame: (0.5@0.06 extent: 0.5@0.30). codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. editString ifNotNil: [codePane editString: editString. codePane hasUnacceptedEdits: true]. window addMorph: codePane frame: (0@0.36 corner: 1@1). "impose an order on the panes." panes _ Array new: 3. panes at: 1 put: categoryList. panes at: 2 put: messageList. panes at: 3 put: codePane. paneIndex _ 1. "default focus pane." window focusMorph: categoryList. ^ window! ! !Browser methodsFor: 'initialize-release' stamp: 'jcg 6/22/1999 17:44'! openAsMorphEditing: editString "Create a pluggable version of all the views for a Browser, including views and controllers." | window switches codePane classCatList classList messageCatList messageList | window _ (SystemWindow labelled: 'later') model: self. classCatList _ PluggableListMorph on: self list: #systemCategoryList selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex: menu: #systemCategoryMenu: keystroke: #systemCatListKey:from:. window addMorph: classCatList frame: (0@0 extent: 0.25@0.4). classList _ PluggableListMorph on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu: keystroke: #classListKey:from:. window addMorph: classList frame: (0.25@0 extent: 0.25@0.3). switches _ self buildMorphicSwitches. window addMorph: switches frame: (0.25@0.3 extent: 0.25@0.1). switches borderWidth: 0. messageCatList _ PluggableListMorph on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. window addMorph: messageCatList frame: (0.5@0 extent: 0.25@0.4). messageList _ PluggableListMorph on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. messageList menuTitleSelector: #messageListSelectorTitle. window addMorph: messageList frame: (0.75@0 extent: 0.25@0.4). codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. editString ifNotNil: [codePane editString: editString. codePane hasUnacceptedEdits: true]. window addMorph: codePane frame: (0@0.4 corner: 1@1). "impose an order on the panes" panes _ Array new: 5. panes at: 1 put: classCatList. panes at: 2 put: classList. panes at: 3 put: messageCatList. panes at: 4 put: messageList. panes at: 5 put: codePane. paneIndex _ 1. "Default focus pane." window focusMorph: classCatList. ^ window! ! !Browser methodsFor: 'initialize-release' stamp: 'jcg 6/22/1999 17:45'! openAsMorphMessageEditing: editString "Create a pluggable version a Browser on just a messageCategory." | window codePane messageList | window _ (SystemWindow labelled: 'later') model: self. messageList _ PluggableListMorph on: self list: #messageListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. window addMorph: messageList frame: (0@0 extent: 1.0@0.06). codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. editString ifNotNil: [codePane editString: editString. codePane hasUnacceptedEdits: true]. window addMorph: codePane frame: (0@0.06 corner: 1@1). "impose an order on the panes." panes _ Array new: 2. panes at: 1 put: messageList. panes at: 2 put: codePane. paneIndex _ 1. "Default focus pane." window focusMorph: messageList. ^ window! ! !Browser methodsFor: 'initialize-release' stamp: 'jcg 6/22/1999 17:45'! openAsMorphMsgCatEditing: editString "Create a pluggable version a Browser on just a messageCategory." | window codePane messageList | window _ (SystemWindow labelled: 'later') model: self. window addMorph: (PluggableListMorph on: self list: #messageCatListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageCategoryMenu:) frame: (0@0 extent: 1.0@0.06). messageList _ PluggableListMorph on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. window addMorph: messageList frame: (0@0.06 extent: 1.0@0.30). codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. editString ifNotNil: [codePane editString: editString. codePane hasUnacceptedEdits: true]. window addMorph: codePane frame: (0@0.36 corner: 1@1). "impose an order on the panes." panes _ Array new: 2. panes at: 1 put: messageList. panes at: 2 put: codePane. paneIndex _ 1. "Default focus pane." window focusMorph: messageList. ^ window! ! !Browser methodsFor: 'initialize-release' stamp: 'jcg 6/22/1999 17:45'! openAsMorphSysCatEditing: editString "Create a pluggable version of all the views for a Browser, including views and controllers." | window switches codePane classList categoryList messageList | window _ (SystemWindow labelled: 'later') model: self. window addMorph: (PluggableListMorph on: self list: #systemCategorySingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #systemCategoryMenu: keystroke: #systemCatListKey:from:) frame: (0@0 extent: 1.0@0.06). classList _ PluggableListMorph on: self list: #classList selected: #classListIndex changeSelected: #classListIndex: menu: #classListMenu: keystroke: #classListKey:from:. window addMorph: classList frame: (0@0.06 extent: 0.3333@0.24). switches _ self buildMorphicSwitches. window addMorph: switches frame: (0@0.3 extent: 0.3333@0.06). switches borderWidth: 0. categoryList _ PluggableListMorph on: self list: #messageCategoryList selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex: menu: #messageCategoryMenu:. window addMorph: categoryList frame: (0.3333@0.06 extent: 0.3333@0.30). messageList _ PluggableListMorph on: self list: #messageList selected: #messageListIndex changeSelected: #messageListIndex: menu: #messageListMenu:shifted: keystroke: #messageListKey:from:. window addMorph: messageList frame: (0.6666@0.06 extent: 0.3333@0.30). codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying: readSelection: #contentsSelection menu: #codePaneMenu:shifted:. editString ifNotNil: [codePane editString: editString. codePane hasUnacceptedEdits: true]. window addMorph: codePane frame: (0@0.36 corner: 1@1). "impose an order on the panes." panes _ Array new: 4. panes at: 1 put: classList. panes at: 2 put: categoryList. panes at: 3 put: messageList. panes at: 4 put: codePane. paneIndex _ 1. "Default focus pane." window focusMorph: classList. ^ window! ! !Browser methodsFor: 'keyboard' stamp: 'jcg 6/28/1999 22:39'! arrowKey: aChar from: view "Add handling of left and right arrows, too." | keyEvent | "Skip if we're not morphic." Smalltalk isMorphic ifFalse: [^super arrowKey: aChar from: view]. (keyEvent _ aChar asciiValue) > 31 ifTrue: [^ self]. "Quick return, out of range" keyEvent == 28 ifTrue: [ "left arrow" (self pane: view; currentHand) newKeyboardFocus: self previousPane. ^ self]. keyEvent == 29 ifTrue: [ "right arrow" (self pane: view; currentHand) newKeyboardFocus: self nextPane. ^ self]. super arrowKey: aChar from: view. ! ! !Browser methodsFor: 'panes' stamp: 'jcg 6/22/1999 13:38'! nextPane "Sets the current pane to the next one, and returns it." (panes isNil or: [paneIndex isNil]) ifTrue: [^ nil]. (paneIndex = panes size) ifTrue: [paneIndex _ 1] ifFalse: [paneIndex _ paneIndex + 1]. ^ panes at: paneIndex.! ! !Browser methodsFor: 'panes' stamp: 'jcg 6/22/1999 13:38'! pane "Gets the current pane." (panes isNil or: [paneIndex isNil]) ifTrue: [^ nil] ifFalse: [^ panes at: paneIndex]! ! !Browser methodsFor: 'panes' stamp: 'jcg 6/22/1999 13:37'! pane: aPane "Sets the currently active pane, doing nothing if the argument is not a valid pane." | index | index _ panes indexOf: aPane. (index isZero) ifFalse: [paneIndex _ index]. ! ! !Browser methodsFor: 'panes' stamp: 'jcg 6/22/1999 13:38'! previousPane "Sets the current pane to the next one, and returns it." (panes isNil or: [paneIndex isNil]) ifTrue: [^ nil]. (paneIndex = 1) ifTrue: [paneIndex _ panes size] ifFalse: [paneIndex _ paneIndex - 1]. ^ panes at: paneIndex.! ! !SystemWindow methodsFor: 'panes' stamp: 'jcg 6/22/1999 04:50'! focusMorph "Answer the morph that should be given the keyboard focus if someone wants to give it to us." ^ focusMorph ! ! !SystemWindow methodsFor: 'panes' stamp: 'jcg 6/22/1999 04:55'! focusMorph: aSubmorph "Set the morph that should be given the keyboard to the given submorph." (submorphs contains: [:m | m = aSubmorph]) ifTrue: [focusMorph _ aSubmorph] ifFalse: [focusMorph _ nil]. ! ! Browser removeSelector: #getNextPane! Browser removeSelector: #getPreviousPane! Browser removeSelector: #getCurrentPane!