Hi guys,
If you develop an application window with multiple grouped menu items, you will certainly be able to enable/disable menu groups at once. Currently it is not possible with MenuGroupModel (Morphic). - A menu (item or group) model manages its state using enabledHolder instance variable (the enabledHolder is configured in its superclass' initialize) -- Being a value holder, one might think there is a propagation of state (enabled/disabled) changes to subwidgets, but it does not happen currently. --- Longer explanation: On static menu building, MenuGroupModel does not propagate #enable: state changes to its widget because "widget" i.v. is nil. The reason is a MenuGroupModel #enabled: is evaluated BEFORE its widget is built. How to reproduce: | mm | mm := MenuModel new addGroup: [ :group | group addItem: [ :item | item name: 'File'; icon: #openIcon asIcon; subMenu: (MenuModel new addGroup: [ : gp | gp disable; " <------ HERE we disable the group " addItem: [ : it | it name: 'Open'; icon: #openIcon asIcon; shortcut: $o meta; action: [ self inform: 'Open' ] ]; addItem: [ : it | it name: 'Save'; icon: #smallSaveIcon asIcon; shortcut: $s meta; action: [ self inform: 'Save' ] ] ]) ] ]; yourself. mm extent: 200 @ 100. mm openWithSpec. mm inspect. (it doesn't matter if #disable is sent after the #addItem: block evaluation) - Even after all MenuGroupModel widgets were built, if you try to disable a menu group dinamically: mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. you would get "Instance of OrderedCollection did not understand #enabled:" (the widget of a MenuGroupModel is an OrderedCollection!!). - However disabling/enabling MenuItemModel works: mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne menuItems first disable. - MenuItemModel gets actually disabled in the ToggleMenuItemMorph/UpdatingMenuMorph (#isEnabled:) when the Canvas draws it. - Incredibly, all disabled groups are re-enabled from several places in the image. -- When the menu is clicked, a ToolDockingBarMorph triggers re-enablement of the MenuMorph in #removeMatchString/#displayFiltered:. This is presumably the code triggered when a menu is displayed and you type to filter the menu items. Something like this: "As initially there is no matchString in the activeSubMenu, then enable all menu items". Obviously it cleans disabled items. The message flow is: DockingBarMorph>>activeSubmenu: -> MenuMorph>>removeMatchString -> MenuMorph>>displayFiltered: --> m isEnabled: isMatch - Another place where menu items are automatically disabled is this flow: FormCanvas>>draw: -> ToggleMenuItemMorph>>drawOn: --> ToggleMenuItemMorph>>isEnabled --> ToggleMenuItemMorph>>isEnabled: !!! --> MorphicMenuItemAdapter>>enabled (This actually CHANGES the enabled state on the Model, disconnecting enabled state between the morph and the model adapter) This seem to have multiple paths of resolution. I'm going to propose a fix that I tested in Pharo 6.1 and Pharo 7. I don't know yet how to fix the menu search auto-enable on key-press but would be glad to read a solution to distinguish between both uses. My idea for now is to have a Morphic property which sets #doNotAutoReEnableItems. However I will open an issue and let people check. You can test it with " Disable the group " mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. " Enable the group " mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne enable. Cheers, Hernán |
https://pharo.fogbugz.com/f/cases/21233/Disabling-a-MenuGroupModel-bug
2018-02-02 10:10 GMT-03:00 Hernán Morales Durand <[hidden email]>: > Hi guys, > > If you develop an application window with multiple grouped menu items, > you will certainly be able to enable/disable menu groups at once. > Currently it is not possible with MenuGroupModel (Morphic). > > - A menu (item or group) model manages its state using enabledHolder > instance variable (the enabledHolder is configured in its superclass' > initialize) > -- Being a value holder, one might think there is a propagation of > state (enabled/disabled) changes to subwidgets, but it does not happen > currently. > --- Longer explanation: On static menu building, MenuGroupModel does > not propagate #enable: state changes to its widget because "widget" > i.v. is nil. The reason is a MenuGroupModel #enabled: is evaluated > BEFORE its widget is built. > > How to reproduce: > | mm | > mm := MenuModel new > addGroup: [ :group | > group > addItem: [ :item | > item > name: 'File'; > icon: #openIcon asIcon; > subMenu: (MenuModel new > addGroup: [ : gp | > gp > disable; " <------ HERE we > disable the group " > addItem: [ : it | > it > name: 'Open'; > icon: #openIcon asIcon; > shortcut: $o meta; > action: [ self inform: 'Open' ] ]; > addItem: [ : it | > it > name: 'Save'; > icon: #smallSaveIcon asIcon; > shortcut: $s meta; > action: [ self inform: 'Save' ] ] ]) ] ]; > yourself. > mm extent: 200 @ 100. > mm openWithSpec. > mm inspect. > > (it doesn't matter if #disable is sent after the #addItem: block evaluation) > > - Even after all MenuGroupModel widgets were built, if you try to > disable a menu group dinamically: > > mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. > > you would get "Instance of OrderedCollection did not understand > #enabled:" (the widget of a MenuGroupModel is an OrderedCollection!!). > > - However disabling/enabling MenuItemModel works: > > mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne > menuItems first disable. > > - MenuItemModel gets actually disabled in the > ToggleMenuItemMorph/UpdatingMenuMorph (#isEnabled:) when the Canvas > draws it. > > - Incredibly, all disabled groups are re-enabled from several places > in the image. > > -- When the menu is clicked, a ToolDockingBarMorph triggers > re-enablement of the MenuMorph in > #removeMatchString/#displayFiltered:. This is presumably the code > triggered when a menu is displayed and you type to filter the menu > items. Something like this: "As initially there is no matchString in > the activeSubMenu, then enable all menu items". Obviously it cleans > disabled items. > > The message flow is: > > DockingBarMorph>>activeSubmenu: -> MenuMorph>>removeMatchString -> > MenuMorph>>displayFiltered: --> m isEnabled: isMatch > > - Another place where menu items are automatically disabled is this flow: > > FormCanvas>>draw: -> ToggleMenuItemMorph>>drawOn: --> > ToggleMenuItemMorph>>isEnabled --> ToggleMenuItemMorph>>isEnabled: !!! > --> MorphicMenuItemAdapter>>enabled (This actually CHANGES the > enabled state on the Model, disconnecting enabled state between the > morph and the model adapter) > > This seem to have multiple paths of resolution. I'm going to propose a > fix that I tested in Pharo 6.1 and Pharo 7. > I don't know yet how to fix the menu search auto-enable on key-press > but would be glad to read a solution to distinguish between both uses. > My idea for now is to have a Morphic property which sets > #doNotAutoReEnableItems. > > However I will open an issue and let people check. > > You can test it with > > " Disable the group " > mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. > > " Enable the group " > mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne enable. > > Cheers, > > Hernán |
Tx!
On Sat, Feb 3, 2018 at 12:25 AM, Hernán Morales Durand <[hidden email]> wrote: > https://pharo.fogbugz.com/f/cases/21233/Disabling-a-MenuGroupModel-bug > > > 2018-02-02 10:10 GMT-03:00 Hernán Morales Durand <[hidden email]>: >> Hi guys, >> >> If you develop an application window with multiple grouped menu items, >> you will certainly be able to enable/disable menu groups at once. >> Currently it is not possible with MenuGroupModel (Morphic). >> >> - A menu (item or group) model manages its state using enabledHolder >> instance variable (the enabledHolder is configured in its superclass' >> initialize) >> -- Being a value holder, one might think there is a propagation of >> state (enabled/disabled) changes to subwidgets, but it does not happen >> currently. >> --- Longer explanation: On static menu building, MenuGroupModel does >> not propagate #enable: state changes to its widget because "widget" >> i.v. is nil. The reason is a MenuGroupModel #enabled: is evaluated >> BEFORE its widget is built. >> >> How to reproduce: >> | mm | >> mm := MenuModel new >> addGroup: [ :group | >> group >> addItem: [ :item | >> item >> name: 'File'; >> icon: #openIcon asIcon; >> subMenu: (MenuModel new >> addGroup: [ : gp | >> gp >> disable; " <------ HERE we >> disable the group " >> addItem: [ : it | >> it >> name: 'Open'; >> icon: #openIcon asIcon; >> shortcut: $o meta; >> action: [ self inform: 'Open' ] ]; >> addItem: [ : it | >> it >> name: 'Save'; >> icon: #smallSaveIcon asIcon; >> shortcut: $s meta; >> action: [ self inform: 'Save' ] ] ]) ] ]; >> yourself. >> mm extent: 200 @ 100. >> mm openWithSpec. >> mm inspect. >> >> (it doesn't matter if #disable is sent after the #addItem: block evaluation) >> >> - Even after all MenuGroupModel widgets were built, if you try to >> disable a menu group dinamically: >> >> mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. >> >> you would get "Instance of OrderedCollection did not understand >> #enabled:" (the widget of a MenuGroupModel is an OrderedCollection!!). >> >> - However disabling/enabling MenuItemModel works: >> >> mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne >> menuItems first disable. >> >> - MenuItemModel gets actually disabled in the >> ToggleMenuItemMorph/UpdatingMenuMorph (#isEnabled:) when the Canvas >> draws it. >> >> - Incredibly, all disabled groups are re-enabled from several places >> in the image. >> >> -- When the menu is clicked, a ToolDockingBarMorph triggers >> re-enablement of the MenuMorph in >> #removeMatchString/#displayFiltered:. This is presumably the code >> triggered when a menu is displayed and you type to filter the menu >> items. Something like this: "As initially there is no matchString in >> the activeSubMenu, then enable all menu items". Obviously it cleans >> disabled items. >> >> The message flow is: >> >> DockingBarMorph>>activeSubmenu: -> MenuMorph>>removeMatchString -> >> MenuMorph>>displayFiltered: --> m isEnabled: isMatch >> >> - Another place where menu items are automatically disabled is this flow: >> >> FormCanvas>>draw: -> ToggleMenuItemMorph>>drawOn: --> >> ToggleMenuItemMorph>>isEnabled --> ToggleMenuItemMorph>>isEnabled: !!! >> --> MorphicMenuItemAdapter>>enabled (This actually CHANGES the >> enabled state on the Model, disconnecting enabled state between the >> morph and the model adapter) >> >> This seem to have multiple paths of resolution. I'm going to propose a >> fix that I tested in Pharo 6.1 and Pharo 7. >> I don't know yet how to fix the menu search auto-enable on key-press >> but would be glad to read a solution to distinguish between both uses. >> My idea for now is to have a Morphic property which sets >> #doNotAutoReEnableItems. >> >> However I will open an issue and let people check. >> >> You can test it with >> >> " Disable the group " >> mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne disable. >> >> " Enable the group " >> mm menuGroups anyOne menuItems anyOne subMenu menuGroups anyOne enable. >> >> Cheers, >> >> Hernán > |
Free forum by Nabble | Edit this page |