A new version of Morphic was added to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.1771.mcz
==================== Summary ====================
Name: Morphic-ct.1771 Author: ct Time: 25 May 2021, 7:38:48.072683 pm UUID: 5a9ddaf0-a062-7047-b5b2-d2ae2da3fe15 Ancestors: Morphic-mt.1769
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:
self systemNavigation browseAllSelect: #notNil
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.
Fixed the problem without duplicating the logic of #allStringsAfter: by using a generator.
=============== Diff against Morphic-mt.1769 ===============
Item was changed: ----- Method: Morph>>addYellowButtonMenuItemsTo:event: (in category 'menu') ----- addYellowButtonMenuItemsTo: aMenu event: evt "Populate aMenu with appropriate menu items for a yellow-button (context menu) click." aMenu defaultTarget: self. "" Preferences noviceMode ifFalse: [aMenu addStayUpItem]. "" self addModelYellowButtonItemsTo: aMenu event: evt. "" Preferences generalizedYellowButtonMenu ifFalse: [^ self]. "" aMenu addLine. aMenu add: 'inspect' translated action: #inspect. "" aMenu addLine. self world selectedObject == self ifTrue: [aMenu add: 'deselect' translated action: #removeHalo] ifFalse: [aMenu add: 'select' translated action: #addHalo]. "" (self isWorldMorph or: [self mustBeBackmost or: [self wantsToBeTopmost]]) ifFalse: ["" aMenu addLine. aMenu add: 'send to back' translated action: #goBehind. aMenu add: 'bring to front' translated action: #comeToFront. self addEmbeddingMenuItemsTo: aMenu hand: evt hand]. "" self isWorldMorph ifFalse: ["" Smalltalk at: #NCAAConnectorMorph ifPresent: [:connectorClass | aMenu addLine. aMenu add: 'connect to' translated action: #startWiring. aMenu addLine]. ""
self isFullOnScreen ifFalse: [aMenu add: 'move onscreen' translated action: #goHome]]. "" Preferences noviceMode ifFalse: ["" self addLayoutMenuItems: aMenu hand: evt hand. (owner notNil and: [owner isTextMorph]) ifTrue: [self addTextAnchorMenuItems: aMenu hand: evt hand]]. "" self isWorldMorph ifFalse: ["" aMenu addLine. self addToggleItemsToHaloMenu: aMenu]. "" aMenu addLine. self isWorldMorph ifFalse: [aMenu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:]. + (Generator on: [:gen | self streamAllStringsAfter: nil on: gen]) in: [:gen | + "optimized!! #allStringsAfter: can be slow for large subtrees." + gen atEnd ifFalse: [ + aMenu add: 'copy text' translated action: #clipText]]. - (self allStringsAfter: nil) isEmpty - ifFalse: [aMenu add: 'copy text' translated action: #clipText]. "" self addExportMenuItems: aMenu hand: evt hand. "" (Preferences noviceMode not and: [self isWorldMorph not]) ifTrue: ["" aMenu addLine. aMenu add: 'adhere to edge...' translated action: #adhereToEdge]. "" self addCustomMenuItems: aMenu hand: evt hand!
Item was changed: ----- Method: Morph>>allStringsAfter: (in category 'debug and other') ----- + allStringsAfter: aSubmorph - allStringsAfter: aSubmorph - "return an OrderedCollection of strings of text in my submorphs. If aSubmorph is non-nil, begin with that container."
+ ^ OrderedCollection streamContents: [:stream | + self streamAllStringsAfter: aSubmorph on: stream]! - | list ok | - list := OrderedCollection new. - ok := aSubmorph isNil. - self allMorphsDo: - [:sub | | string | - ok ifFalse: [ok := sub == aSubmorph]. "and do this one too" - ok - ifTrue: - [(string := sub userString) ifNotNil: - [string isString ifTrue: [list add: string] ifFalse: [list addAll: string]]]]. - ^list!
Item was added: + ----- Method: Morph>>streamAllStringsAfter:on: (in category 'debug and other') ----- + streamAllStringsAfter: aSubmorph on: aStream + "Stream all strings of text in my submorphs on aStream. If aSubmorph is non-nil, begin with that container." + + | ok | + ok := aSubmorph isNil. + self allMorphsDo: [:sub | | string | + ok ifFalse: [ok := sub == aSubmorph]. + "and do this one too" + ok ifTrue: [ + (string := sub userString) + ifNotNil: [string isString + ifTrue: [aStream nextPut: string] + ifFalse: [aStream nextPutAll: string]]]].!