Hi Eliot,<br>
<br>
nice idea - I'm just wondering why we should restrict this feature to workspaces, what about unsaved changes in a system browser or a transcript or anything else?<br>
<br>
Nevertheless, if I select the "find workspace" entry by keyboard and press Enter, I get a DNU on TheWorldMainDockingBar>>findWorkspace from [] in MenuItemMorph>>invokeWithEvent:. Could you fix that?<br>
<br>
Also, because of the contraction I cannot type-to-filter any part of the workspace text but only text from the beginning or ending. So in the long term, we might want to move that truncation into the MenuMorph so that we can scan the full text for filter terms.<br>
<br>
Best,<br>
Christoph<br>
<br>
<font color="#808080">---<br>
</font><i><font color="#808080">Sent from </font></i><i><u><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><font color="#808080">Squeak Inbox Talk</font></a></u></i><br>
<br>
On 2021-11-04T19:44:12+00:00, commits@source.squeak.org wrote:<br>
<br>
> Eliot Miranda uploaded a new version of Morphic to project The Trunk:<br>
> http://source.squeak.org/trunk/Morphic-eem.1786.mcz<br>
> <br>
> ==================== Summary ====================<br>
> <br>
> Name: Morphic-eem.1786<br>
> Author: eem<br>
> Time: 4 November 2021, 12:44:06.340704 pm<br>
> UUID: 6a2f11a1-29ae-4254-b9a7-585512357c51<br>
> Ancestors: Morphic-mt.1785<br>
> <br>
> Add a Find Workspace... item to teh end of the Find Window menu. This finds and activates a workspace in any project (my life has too many projecvts with too many workspaces in them to lve without this kind of help).<br>
> <br>
> Abstracting the facility to search for other kinds of windows is left as an exercise to the reader (I don't see the need for being able to find other than workspaces, but that might be just me).<br>
> <br>
> Needs System-eem.1245.<br>
> <br>
> =============== Diff against Morphic-mt.1785 ===============<br>
> <br>
> Item was added:<br>
> + ----- Method: MorphicProject>>topMorphicProject (in category 'accessing') -----<br>
> + topMorphicProject<br>
> +     parentProject == self ifTrue: [^self].<br>
> +     parentProject ifNil: [self nilParentError].<br>
> +     ^parentProject isMorphic<br>
> +         ifTrue: [parentProject topMorphicProject]<br>
> +         ifFalse: [self]!<br>
> <br>
> Item was changed:<br>
> ----- Method: TheWorldMainDockingBar>>listWindowsOn: (in category 'submenu - windows') -----<br>
> listWindowsOn: menu<br>
> <br>
>     | windows |<br>
>     windows := self allVisibleWindows sorted: [:winA :winB |<br>
>         ((winA model isNil or: [winB model isNil]) or: [winA model name = winB model name])<br>
>             ifTrue: [winA label < winB label]<br>
>             ifFalse: [winA model name < winB model name]].<br>
>     windows ifEmpty: [ <br>
>         menu addItem: [ :item | <br>
>             item<br>
>                 contents: 'No Windows' translated;<br>
>                 isEnabled: false ] ].<br>
>     windows do: [ :each |<br>
>         | windowColor |<br>
>         windowColor := (each model respondsTo: #windowColorToUse)<br>
>             ifTrue: [each model windowColorToUse]<br>
>             ifFalse: [UserInterfaceTheme current get: #uniformWindowColor for: Model]. <br>
>         menu addItem: [ :item |<br>
>             item <br>
>                 contents: (self windowMenuItemLabelFor: each);<br>
>                 icon: (self colorIcon: windowColor);<br>
>                 target: each;<br>
>                 selector: #comeToFront;<br>
>                 subMenuUpdater: self<br>
>                 selector: #windowMenuFor:on:<br>
>                 arguments: { each };<br>
>                 action: [ each beKeyWindow; expand ] ] ].<br>
>     menu<br>
>         addLine;<br>
>         add: 'Collapse all windows' target: (Project current world) selector: #collapseAllWindows;<br>
>         add: 'Close all windows' target: self selector: #closeAllWindowsUnsafe;<br>
>         addItem: [:item | item<br>
>             contents: 'Close all windows without changes';<br>
>             target: self;<br>
>             icon: MenuIcons smallBroomIcon;<br>
>             selector: #closeAllWindows];<br>
> +         add: 'Close all windows but workspaces' target: self selector: #closeAllWindowsButWorkspaces;<br>
> +         addItem:<br>
> +             [ :item |<br>
> +             item <br>
> +                 contents: 'Find Workspace...';<br>
> +                 target: self;<br>
> +                 selector: #findWorkspace;<br>
> +                 subMenuUpdater: self<br>
> +                     selector: #workspacesMenuFor:<br>
> +                         arguments: #()]!<br>
> -         add: 'Close all windows but workspaces' target: self selector: #closeAllWindowsButWorkspaces.!<br>
> <br>
> Item was added:<br>
> + ----- Method: TheWorldMainDockingBar>>selectWorkspace:window:inProject:contents: (in category 'submenu - windows') -----<br>
> + selectWorkspace: aWorkspace window: aSystemWindow inProject: aMorphicProject contents: contents<br>
> +     aMorphicProject<br>
> +         addDeferredUIMessage: [aSystemWindow comeToFront];<br>
> +         enter "Does nothing if already the current project..."<br>
> +     !<br>
> <br>
> Item was added:<br>
> + ----- Method: TheWorldMainDockingBar>>workspacesMenuFor: (in category 'submenu - windows') -----<br>
> + workspacesMenuFor: anUpdatingMenuMorph<br>
> +     | allWorkspaces |<br>
> +     allWorkspaces := Set new.<br>
> +     Project current topMorphicProject withChildrenDo:<br>
> +         [:project|<br>
> +         project world submorphs do:<br>
> +             [:m|<br>
> +             (m model isKindOf: Workspace) ifTrue:<br>
> +                 [allWorkspaces add:<br>
> +                     {    m model.<br>
> +                         m.<br>
> +                         project.<br>
> +                         m model contents ifEmpty:<br>
> +                             [(m model dependents detect: [:d| d isTextView] ifNone: nil) textMorph contents] }]]].<br>
> +     "Sort workspaces with non-empty ones first..."<br>
> +     (allWorkspaces sorted:<br>
> +         [:t1 :t2|<br>
> +         t1 last isEmpty == t2 last isEmpty<br>
> +             ifTrue: [t1 second label <= t2 second label]<br>
> +             ifFalse: [t1 last notEmpty]]) do:<br>
> +         [:tuple|<br>
> +         anUpdatingMenuMorph addItem:<br>
> +             [:item | item<br>
> +                 contents: tuple second label, ': ', (tuple last asString contractTo: 128);<br>
> +                 target: self;<br>
> +                 selector: #selectWorkspace:window:inProject:contents:;<br>
> +                 arguments: tuple]]!<br>
> <br>