<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
                                        Hi Christoph.<div><br></div><div>Thanks. I think that the expected pattern is a little bit different, though. The explicit use of Generator is unfortunate but can be easily avoided. :-)</div><div><br></div><div>allStringsAfter: morph do: block</div><div>   "..."</div><div><br></div><div>allStringsAfter: morph</div><div>   ^ Array streamContents: [:stream |</div><div>      self allStringsAfter: morph do: [:string |</div><div>         stream nextPut: string]]</div><div><br></div><div>hasStringsAfter: morph</div><div>   self allStringsAfter: morph do: [:string | ^ true].</div><div>   ^ false</div><div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div>
                                        <blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color: #AAAAAA; margin-top: 10px;">Am 25.05.2021 19:39:07 schrieb commits@source.squeak.org <commits@source.squeak.org>:</p><div style="font-family:Arial,Helvetica,sans-serif">A new version of Morphic was added to project The Inbox:<br>http://source.squeak.org/inbox/Morphic-ct.1771.mcz<br><br>==================== Summary ====================<br><br>Name: Morphic-ct.1771<br>Author: ct<br>Time: 25 May 2021, 7:38:48.072683 pm<br>UUID: 5a9ddaf0-a062-7047-b5b2-d2ae2da3fe15<br>Ancestors: Morphic-mt.1769<br><br>Fixes a bottleneck when opening a yellow button menu on a morph that contains a very large number of subsub*morphs. On not-so-fast systems, this can be reproduced using:<br><br>     self systemNavigation browseAllSelect: #notNil<br><br>On faster systems, you might need to write a small toolbuilder application to reproduce the bottleneck. I have an app with >10k list items in my image which actually blocked the image for several seconds when I yellow-clicked the window.<br><br>Fixed the problem without duplicating the logic of #allStringsAfter: by using a generator.<br><br>=============== Diff against Morphic-mt.1769 ===============<br><br>Item was changed:<br>  ----- Method: Morph>>addYellowButtonMenuItemsTo:event: (in category 'menu') -----<br>  addYellowButtonMenuItemsTo: aMenu event: evt <br>     "Populate aMenu with appropriate menu items for a  <br>      yellow-button (context menu) click."<br>     aMenu defaultTarget: self.<br>    ""<br>          Preferences noviceMode<br>                ifFalse: [aMenu addStayUpItem].<br>       ""<br>          self addModelYellowButtonItemsTo: aMenu event: evt.<br>   ""<br>          Preferences generalizedYellowButtonMenu<br>               ifFalse: [^ self].<br>    ""<br>          aMenu addLine.<br>        aMenu add: 'inspect' translated action: #inspect.<br>     ""<br>          aMenu addLine.<br>        self world selectedObject == self<br>             ifTrue: [aMenu add: 'deselect' translated action: #removeHalo]<br>                ifFalse: [aMenu add: 'select' translated action: #addHalo].<br>   ""<br>          (self isWorldMorph<br>                    or: [self mustBeBackmost<br>                      or: [self wantsToBeTopmost]])<br>                 ifFalse: [""<br>                        aMenu addLine.<br>                        aMenu add: 'send to back' translated action: #goBehind.<br>                       aMenu add: 'bring to front' translated action: #comeToFront.<br>                          self addEmbeddingMenuItemsTo: aMenu hand: evt hand].<br>          ""<br>          self isWorldMorph<br>             ifFalse: [""<br>        Smalltalk<br>             at: #NCAAConnectorMorph<br>               ifPresent: [:connectorClass | <br>                        aMenu addLine.<br>                        aMenu add: 'connect to' translated action: #startWiring.<br>                      aMenu addLine].<br>       ""<br>  <br>                      self isFullOnScreen<br>                           ifFalse: [aMenu add: 'move onscreen' translated action: #goHome]].<br>    ""<br>          Preferences noviceMode<br>                ifFalse: [""<br>                        self addLayoutMenuItems: aMenu hand: evt hand.<br>                        (owner notNil<br>                                         and: [owner isTextMorph])<br>                             ifTrue: [self addTextAnchorMenuItems: aMenu hand: evt hand]].<br>         ""<br>          self isWorldMorph<br>             ifFalse: [""<br>                        aMenu addLine.<br>                        self addToggleItemsToHaloMenu: aMenu].<br>        ""<br>          aMenu addLine.<br>        self isWorldMorph<br>             ifFalse: [aMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:].<br>+         (Generator on: [:gen | self streamAllStringsAfter: nil on: gen]) in: [:gen |<br>+                 "optimized!! #allStringsAfter: can be slow for large subtrees."<br>+            gen atEnd ifFalse: [<br>+                         aMenu add: 'copy text' translated action: #clipText]].<br>-       (self allStringsAfter: nil) isEmpty<br>-          ifFalse: [aMenu add: 'copy text' translated action: #clipText].<br>       ""<br>          self addExportMenuItems: aMenu hand: evt hand.<br>        ""<br>          (Preferences noviceMode not<br>                   and: [self isWorldMorph not])<br>                 ifTrue: [""<br>                         aMenu addLine.<br>                        aMenu add: 'adhere to edge...' translated action: #adhereToEdge].<br>     ""<br>          self addCustomMenuItems: aMenu hand: evt hand!<br><br>Item was changed:<br>  ----- Method: Morph>>allStringsAfter: (in category 'debug and other') -----<br>+ allStringsAfter: aSubmorph<br>- allStringsAfter: aSubmorph <br>-        "return an OrderedCollection of strings of text in my submorphs.  If aSubmorph is non-nil, begin with that container."<br>  <br>+         ^ OrderedCollection streamContents: [:stream |<br>+               self streamAllStringsAfter: aSubmorph on: stream]!<br>-   | list ok |<br>-  list := OrderedCollection new.<br>-       ok := aSubmorph isNil.<br>-       self allMorphsDo: <br>-                   [:sub | | string | <br>-                  ok ifFalse: [ok := sub == aSubmorph].   "and do this one too"<br>-                      ok <br>-                          ifTrue: <br>-                                     [(string := sub userString) ifNotNil: <br>-                                                       [string isString ifTrue: [list add: string] ifFalse: [list addAll: string]]]].<br>-       ^list!<br><br>Item was added:<br>+ ----- Method: Morph>>streamAllStringsAfter:on: (in category 'debug and other') -----<br>+ streamAllStringsAfter: aSubmorph on: aStream<br>+      "Stream all strings of text in my submorphs on aStream. If aSubmorph is non-nil, begin with that container."<br>+ <br>+   | ok |<br>+       ok := aSubmorph isNil.<br>+       self allMorphsDo: [:sub | | string |<br>+                 ok ifFalse: [ok := sub == aSubmorph].<br>+                "and do this one too"<br>+              ok ifTrue: [<br>+                         (string := sub userString)<br>+                           ifNotNil: [string isString<br>+                                   ifTrue: [aStream nextPut: string]<br>+                                    ifFalse: [aStream nextPutAll: string]]]].!<br><br><br></div></blockquote></div>