[squeak-dev] The Inbox: Morphic-phite.428.mcz
Philipp Tessenow
phite at nada1.de
Sun Apr 25 18:25:16 UTC 2010
Hi,
I refactored the docking bar to be extendable with custom menu entries.
Every class may implement #menuEntrySpecification to answer a
MenuEntrySpec - see:
^ MenuEntrySpec newFrom: (Dictionary newFromPairs: #(
#contents 'Well... hello?'
#help 'Displays the Hello World'
#location #('Help')
#target MenuMorph #selector #inform: #arguments #('Hello World!')
#position #first))
Which adds a menuEntry 'Well... Hello?' in the first slot of the Help-menu.
It is possible to select as many subMenus as you like.
MenuEntries can be position within a menu by defining it's position
(#first, #last, #(#before 'aMenu'), #(#after 'aMenu')
As MenuEntrySpecs can are created with a Dictionary you can leave field
you don't want to declare. (As is did with #icon and #selectedIcon in my
example).
Comments please :)
regards,
Philipp
Am 25.04.2010 18:16, schrieb commits at source.squeak.org:
> A new version of Morphic was added to project The Inbox:
> http://source.squeak.org/inbox/Morphic-phite.428.mcz
>
> ==================== Summary ====================
>
> Name: Morphic-phite.428
> Author: phite
> Time: 25 April 2010, 8:16:06.137 pm
> UUID: a876e2b3-d755-1845-9002-16c2c0dde809
> Ancestors: Morphic-ar.427
>
> Refactored DockingBar to add dynamically add entries.
>
> Any class that implements #menuEntrySpecification may create a new menuEntry.
>
> #menuEntrySpecification answers a MenuEntrySpec.
> Example:
> menuEntrySpecification
> "Answer a MenuEntrySpec object that declares my menuEntrie in the world docking"
>
> ^ MenuEntrySpec newFrom: (Dictionary newFromPairs: #(
> #contents 'Well... hello?'
> #help 'Displays the Hello World'
> #location #('Help')
> #target MenuMorph #selector #inform: #arguments #('Hello World!')
> #position #first))
>
> #location specifies the location within the DockingBar. It may be #() to create a top-level menu or #('Help' 'subMenu1' 'subMenu2') to create a menuEntry within some sub menus in Help.
>
> #position may be #first, #last or #(before 'Keyboard Shortcuts'), #(#after ''Keyboard Shortcuts'') to declare the menuEntry's position within the a menu.
>
> =============== Diff against Morphic-ar.427 ===============
>
> Item was added:
> + ----- Method: MenuEntrySpec>>selectedIcon (in category 'accessing') -----
> + selectedIcon
> +
> + ^ selectedIcon!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>selectedIcon: (in category 'accessing') -----
> + selectedIcon: anIcon
> +
> + selectedIcon := anIcon!
>
> Item was changed:
> ----- Method: DockingBarMorph>>add:icon:selectedIcon:help:subMenu: (in category 'construction') -----
> add: wordingString icon: aForm selectedIcon: anotherForm help: helpString subMenu: aMenuMorph
> "Append the given submenu with the given label."
> +
> + self add: wordingString icon: aForm selectedIcon: anotherForm help: helpString subMenu: aMenuMorph position: {#back}.!
> - | item |
> - item := DockingBarItemMorph new
> - contents: wordingString;
> - subMenu: aMenuMorph;
> - icon: aForm;
> - selectedIcon: anotherForm.
> - helpString isNil ifFalse: [
> - item setBalloonText: helpString ].
> - self addMorphBack: item!
>
> Item was added:
> + ----- Method: MenuEntrySpec classSide>>newFrom: (in category 'as yet unclassified') -----
> + newFrom: aDict
> + "Creates a new MenuEntrySpec from a Dictionary.
> + Possible keys are: #contents, #help, #icon, #selectedIcon,
> + #target, #selector, #argument, #location, #position
> + where #location describes where the menuEntry should be placed
> + #location -> nil creates a new menuEntry in the DockingBar
> + #location -> #('Tools' 'subMenu' 'subMenu2') puts the menuEntry into submenus
> + and where #position describes the position of the menuEntry within a menu eg.
> + #position -> #last - adds the menuEntry at the end of the menu (#first at the beginning)
> + #position -> #(#before 'Help') - adds the menuEntry just before the 'Help' entry (#after adds it after the entry)"
> +
> + ^ self new
> + contents: (aDict at: #contents ifAbsent: '');
> + help: (aDict at: #help ifAbsent: nil);
> + icon: (aDict at: #icon ifAbsent: nil);
> + selectedIcon: (aDict at: #selectedIcon ifAbsent: nil);
> + target: (aDict at: #target ifAbsent: nil);
> + selector: (aDict at: #selector ifAbsent: nil);
> + arguments: (aDict at: #arguments ifAbsent: nil);
> + location: (aDict at: #location ifAbsent: nil);
> + position: (aDict at: #position ifAbsent: #last)!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>selector (in category 'accessing') -----
> + selector
> +
> + ^ selector!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>installOn: (in category 'menu-creation') -----
> + installOn: aDockingBar
> + "Installs a menuEntry corresponding to this specification into the given DockingBar"
> +
> + | menu |
> + menu := self findOrCreateLocationIn: aDockingBar.
> + menu subMenu ifNil: [ menu addSubMenu: [:subMenu |] ].
> + menu subMenu addItem: [ :item |
> + item
> + contents: self contents;
> + help: self help;
> + icon: self icon;
> + target: self target;
> + selector: self selector;
> + arguments: self arguments.
> + (item respondsTo: #selectedIcon:) ifTrue: [ item selectedIcon: self selectedIcon ].]
> + at: self position.!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>target: (in category 'accessing') -----
> + target: anObject
> +
> + target := anObject!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>position (in category 'accessing') -----
> + position
> +
> + ^ position!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>location (in category 'accessing') -----
> + location
> + "An Array containing the menu and submenues the menu should be placed."
> +
> + ^ location!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>contents (in category 'accessing') -----
> + contents
> + "The label of the menuEntry."
> +
> + ^ contents!
>
> Item was added:
> + ----- Method: MenuMorph>>addMenuItem:at: (in category 'construction') -----
> + addMenuItem: aMenuItemMorph at: position
> + "adds the Menu at the given position. Position is an Array of the form
> + {#last}, {#first}, {#before . 'Help'}, {#after . 'Tools'}"
> +
> + ((position at: 1) = #first) ifTrue: [ ^ self addMorphFront: aMenuItemMorph ].
> + ((position at: 1) = #before) ifTrue: [ ^ self addMorph: aMenuItemMorph inFrontOf:
> + (self menus detect: [ :menu | menu contents = (position at: 2) ]) ].
> + ((position at: 1) = #after) ifTrue: [ ^ self addMorph: aMenuItemMorph behind:
> + (self menus detect: [ :menu | menu contents = (position at: 2) ]) ].
> + "#last"
> + self addMorphBack: aMenuItemMorph.!
>
> Item was added:
> + ----- Method: DockingBarMenuMorph>>menus (in category 'as yet unclassified') -----
> + menus
> + "Answers an array of my menuEntries"
> + ^ self submorphs select: [:aMorph | aMorph isKindOf: MenuItemMorph]!
>
> Item was added:
> + ----- Method: TheWorldMainDockingBar>>searchForMenuSpecs (in category 'construction') -----
> + searchForMenuSpecs
> + "This is a one-time only method for creating the worlds DockingBar. Here we scann all classes for #menuEntrySpecification methods and answer an Array of all menuSpecs found."
> +
> + ^ ((self systemNavigation allClassesImplementing: #menuEntrySpecification)
> + collect: [ :aClass | aClass theNonMetaClass menuEntrySpecification])!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>arguments: (in category 'accessing') -----
> + arguments: anArray
> +
> + arguments := anArray!
>
> Item was added:
> + ----- Method: DockingBarMorph>>subMenu (in category 'accessing') -----
> + subMenu
> + "This is for convenience and makes the DockingBar look more like a MenuMorph."
> +
> + ^ self!
>
> Item was added:
> + ----- Method: DockingBarMorph>>addMenu:atPosition: (in category 'construction') -----
> + addMenu: item atPosition: position
> + "adds the Menu at the given position. Position is an Array of the form
> + {#last}, {#first}, {#before . 'Help'}, {#after . 'Tools'}"
> +
> + ((position at: 1) = #first) ifTrue: [ ^ self addMorphFront: item ].
> + ((position at: 1) = #before) ifTrue: [ ^ self addMorph: item inFrontOf:
> + (self menus detect: [ :menu | menu contents = (position at: 2) ]) ].
> + ((position at: 1) = #after) ifTrue: [ ^ self addMorph: item behind:
> + (self menus detect: [ :menu | menu contents = (position at: 2) ]) ].
> + "#last"
> + self addMorphBack: item.!
>
> Item was added:
> + ----- Method: TheWorldMainDockingBar>>customMenusOn: (in category 'construction') -----
> + customMenusOn: aDockingBar
> + "Searches for MenuEntrySpecs and add the corresponding menus to the docking bar."
> + | menuSpecs |
> + menuSpecs := self searchForMenuSpecs sortBy: [ :a :b | a location size > b location size].
> + menuSpecs do: [ :spec |
> + spec installOn: aDockingBar].!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>icon: (in category 'accessing') -----
> + icon: anIcon
> +
> + icon := anIcon!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>findOrCreateLocationIn: (in category 'menu-creation') -----
> + findOrCreateLocationIn: aDockingBar
> + "find the menu my location points at - create it, if it does not exist."
> +
> + | currentMenu |
> + location size = 0 ifTrue: [ ^ aDockingBar ].
> + currentMenu := aDockingBar.
> + (1 to: location size) do: [ :i |
> + currentMenu := currentMenu menus detect:
> + [ :m | m contents = (location at: i) ]
> + ifNone: [
> + currentMenu subMenu ifNil: [ currentMenu addSubMenu:[:subMenu| ]].
> + currentMenu subMenu addItem: [:item|
> + item contents: (location at: i)].
> + currentMenu menus detect: [ :m | m contents = (location at: i) ]]].
> + ^ currentMenu!
>
> Item was added:
> + ----- Method: DockingBarMorph>>addItem:at: (in category 'construction') -----
> + addItem: aBlock at: position
> + | item |
> + item := DockingBarItemMorph new.
> + aBlock value: item.
> + self addMenu: item atPosition: position.!
>
> Item was added:
> + ----- Method: MenuItemMorph>>menus (in category 'accessing') -----
> + menus
> + "Answers an array of my submenus"
> + self subMenu ifNil: [ ^ #() ].
> + ^ self subMenu submorphs select: [:aMorph | aMorph isKindOf: MenuItemMorph]!
>
> Item was added:
> + ----- Method: DockingBarItemMorph>>menus (in category 'as yet unclassified') -----
> + menus
> + "Answers an array of my submenus"
> + self subMenu ifNil: [ ^ #() ].
> + ^ self subMenu submorphs select: [:aMorph | aMorph isKindOf: MenuItemMorph]!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>target (in category 'accessing') -----
> + target
> +
> + ^ target!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>location: (in category 'accessing') -----
> + location: stringOrArray
> + "Encapsulates the parameter into an Array."
> +
> + stringOrArray ifNil: [ location := #() ].
> + stringOrArray isString ifTrue: [ location := #(stringOrArray) ].
> + stringOrArray isArray ifTrue: [ location := stringOrArray ].!
>
> Item was added:
> + ----- Method: MenuMorph>>addItem:at: (in category 'construction') -----
> + addItem: aBlock at: position
> + | item |
> + item := MenuItemMorph new.
> + aBlock value: item.
> + self addMenuItem: item at: position!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>selector: (in category 'accessing') -----
> + selector: aSymbol
> +
> + selector := aSymbol!
>
> Item was added:
> + ----- Method: DockingBarMorph>>menus (in category 'menu') -----
> + menus
> + "Answers an array of menus in this docking bar"
> + ^ self submorphs select: [:aMorph | aMorph isKindOf: MenuItemMorph]!
>
> Item was changed:
> ----- Method: DockingBarMorph>>add:icon:help:subMenu: (in category 'construction') -----
> add: wordingString icon: aForm help: helpString subMenu: aMenuMorph
> "Append the given submenu with the given label."
> +
> + self add: wordingString icon: aForm selectedIcon: nil help: helpString subMenu: aMenuMorph.!
> - | item |
> - item := DockingBarItemMorph new.
> - item contents: wordingString.
> - item subMenu: aMenuMorph.
> - item icon: aForm.
> - helpString isNil
> - ifFalse: [item setBalloonText: helpString].
> - self addMorphBack: item!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>help: (in category 'accessing') -----
> + help: aString
> +
> + help := aString!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>position: (in category 'accessing') -----
> + position: symbolOrArray
> + "The Array either is kind of #(#symbol) - where #symbol is #first or #last
> + or #(#symbol 'string') - where #symbol is #before or #after and string is the label of a menu"
> +
> + symbolOrArray isSymbol ifTrue: [ position := { symbolOrArray } ].
> + symbolOrArray isArray ifTrue: [ position := symbolOrArray ].!
>
> Item was added:
> + ----- Method: MenuMorph>>menus (in category 'accessing') -----
> + menus
> + "Answers an array of my menuEntries"
> + ^ self submorphs select: [:aMorph | aMorph isKindOf: MenuItemMorph]!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>arguments (in category 'accessing') -----
> + arguments
> +
> + ^ arguments!
>
> Item was added:
> + ----- Method: DockingBarMorph>>add:icon:selectedIcon:help:subMenu:position: (in category 'construction') -----
> + add: wordingString icon: aForm selectedIcon: anotherForm help: helpString subMenu: aMenuMorph position: position
> + "Append the given submenu with the given label."
> + | item |
> + item := DockingBarItemMorph new
> + contents: wordingString;
> + subMenu: aMenuMorph;
> + icon: aForm;
> + selectedIcon: anotherForm.
> + helpString isNil ifFalse: [
> + item setBalloonText: helpString ].
> + self addMenu: item atPosition: position.!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>help (in category 'accessing') -----
> + help
> +
> + ^ help!
>
> Item was added:
> + Object subclass: #MenuEntrySpec
> + instanceVariableNames: 'contents help icon selectedIcon target selector location arguments position'
> + classVariableNames: ''
> + poolDictionaries: ''
> + category: 'Morphic-Menus-DockingBar'!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>contents: (in category 'accessing') -----
> + contents: aString
> + "The label of the menuEntry."
> +
> + contents := aString!
>
> Item was changed:
> ----- Method: DockingBarMorph>>addItem: (in category 'construction') -----
> addItem: aBlock
> +
> + self addItem: aBlock at: { #last }.!
> - | item |
> - item := DockingBarItemMorph new.
> - aBlock value: item.
> - self addMorphBack: item!
>
> Item was added:
> + ----- Method: MenuEntrySpec>>icon (in category 'accessing') -----
> + icon
> +
> + ^ icon!
>
> Item was changed:
> ----- Method: TheWorldMainDockingBar>>menusOn: (in category 'construction') -----
> + menusOn: aDockingBar
> - menusOn: aDockingBar
>
> self
> squeakMenuOn: aDockingBar;
> projectsMenuOn: aDockingBar;
> toolsMenuOn: aDockingBar;
> extrasMenuOn: aDockingBar;
> windowsMenuOn: aDockingBar;
> + helpMenuOn: aDockingBar;
> + customMenusOn: aDockingBar.
> - helpMenuOn: aDockingBar.
> aDockingBar addSpacer.
> self
> searchBarOn: aDockingBar;
> clockOn: aDockingBar!
>
> Item was changed:
> ----- Method: MenuMorph>>addItem: (in category 'construction') -----
> addItem: aBlock
> + self addItem: aBlock at: { #last }!
> - | item |
> - item := MenuItemMorph new.
> - aBlock value: item.
> - self addMenuItem: item!
>
> Item was removed:
> - ----- Method: MenuMorph>>addMenuItem: (in category 'construction') -----
> - addMenuItem: aMenuItemMorph
> - self addMorphBack: aMenuItemMorph!
>
>
>
More information about the Squeak-dev
mailing list
|