'From etoys2.2 of 24 September 2007 [latest update: #1677] on 1 October 2007 at 3:08:25 pm'! "Change Set: embedDynamic-sw Date: 1 October 2007 Author: Scott Wallace Make the 'embed' command compute its potential targets dynamically, rather than in a static submenu which is quickly obsoleted if the menu is pinned up and then things are moved around. Use an updating-menu-item, so that when embedding is irrelevant, the item is grayed out, rather than offering the lone baffling choice 'world', and so that the list of potential targets is correct up to the moment rather than reflecting the state of affairs at the time the halo menu was first put up. The embed feature is still far from user-friendly, since the list of possible targets is still computed based on a core sample directly beneath the morph's (reference) position point, as it has been from the very beginning of Morphic. I'm sure this is also very baffling to users, and really ought to be reinvented. With this update, a number of tweaks attempt to improve the experience, in any case. When the embed menu is put up, the menu title is more helpful, and the choice of depositing the object on the 'desktop' now is represented by 'desktop' rather than by the enigmatic 'world', and the object's current container is highlighted in red so the user will easily be able to discern which choice will be a no-op. Finally, there is bulletproofing now in place against the unusual but not unknown situation in which an attempt is made to embed an object in one of its own sub (or sub-sub) morphs, which fomerly led to infinite recursion. This update also trims out several more items from the universal red halo menu in the eToyFriendly case: - no layout menu - no stacks and cards. Also, a fix to UpdatingMenuMorph which assurse that the icons in the menu title bar are correct, and a fix to UpdatingMenuItemMorph that allows enablement to work even if there is no wording selector are finally now brought into the mainstream image; these fixes been present in the Vancouver, TinLizzie, and Moshi lines for four years..."! !Morph methodsFor: 'menus' stamp: 'sw 9/28/2007 02:38'! addStandardHaloMenuItemsTo: aMenu hand: aHandMorph "Add standard halo items to the menu" | unlockables | self isWorldMorph ifTrue: [^ self addWorldHaloMenuItemsTo: aMenu hand: aHandMorph]. self mustBeBackmost ifFalse: [aMenu add: 'send to back' translated action: #goBehind. aMenu add: 'bring to front' translated action: #comeToFront. aMenu addWithLabel: 'embed...' translated enablement: #embedEnabled action: #showEmbedMenu. aMenu balloonTextForLastItem: 'present a menu of potential embeddeding targets for this object, and embed it in the one chosen.' translated. aMenu addLine]. self addFillStyleMenuItems: aMenu hand: aHandMorph. self addBorderStyleMenuItems: aMenu hand: aHandMorph. self addDropShadowMenuItems: aMenu hand: aHandMorph. Preferences eToyFriendly ifFalse: [self addHaloActionsTo: aMenu. self addLayoutMenuItems: aMenu hand: aHandMorph]. owner isTextMorph ifTrue:[self addTextAnchorMenuItems: aMenu hand: aHandMorph]. aMenu addLine. self addToggleItemsToHaloMenu: aMenu. aMenu addLine. Preferences eToyFriendly ifFalse: [self addCopyItemsTo: aMenu]. self addPlayerItemsTo: aMenu. Preferences eToyFriendly ifFalse: [self addExportMenuItems: aMenu hand: aHandMorph. self addStackItemsTo: aMenu]. self addMiscExtrasTo: aMenu. Preferences eToyFriendly ifFalse: [Preferences noviceMode ifFalse: [self addDebuggingItemsTo: aMenu hand: aHandMorph]]. aMenu addLine. aMenu defaultTarget: self. aMenu addLine. unlockables _ self submorphs select: [:m | m isLocked]. unlockables size == 1 ifTrue: [aMenu add: ('unlock "{1}"' translated format: {unlockables first externalName}) action: #unlockContents]. unlockables size > 1 ifTrue: [aMenu add: 'unlock all contents' translated action: #unlockContents. aMenu add: 'unlock...' translated action: #unlockOneSubpart]. aMenu defaultTarget: aHandMorph. ! ! !Morph methodsFor: 'meta-actions' stamp: 'sw 9/29/2007 01:01'! addEmbeddingMenuItemsTo: aMenu hand: aHandMorph "Construct a menu offerring embed targets for the receiver. If the incoming menu is is not degenerate, add the constructed menu as a submenu; in any case, answer the embed-target menu" | menu w | menu _ MenuMorph new defaultTarget: self. w _ self world. self potentialEmbeddingTargets reverseDo: [:m | menu add: (m == w ifTrue: ['desktop' translated] ifFalse: [m knownName ifNil:[m class name asString]]) target: m selector: #addMorphFrontFromWorldPosition: argumentList: {self topRendererOrSelf}. m == self topRendererOrSelf owner ifTrue: [menu lastItem color: Color red]]. aMenu ifNotNil: [menu submorphCount > 0 ifTrue:[aMenu add:'embed into' translated subMenu: menu]]. ^ menu! ! !Morph methodsFor: 'meta-actions' stamp: 'sw 10/1/2007 14:31'! embedEnabled "Answer whether there would be a reasonable set of alternatives for embedding." ^ self potentialEmbeddingTargets size > 1! ! !Morph methodsFor: 'meta-actions' stamp: 'sw 9/29/2007 01:25'! showEmbedMenu "Put up a menu offering embed targets. Emphasize the current position. Theoretically this method will only be called when there are at least two alternatives." | aMenu | aMenu := self addEmbeddingMenuItemsTo: nil hand: ActiveHand. aMenu title: 'embed ' translated, self externalName, ' in...' translated. aMenu popUpInWorld! ! !Morph methodsFor: '*connectors-embeddings' stamp: 'sw 10/1/2007 14:29'! addMorphFrontFromWorldPosition: aMorph "Add as a submorph the given morph, using its current world position as a guide for location." | addSlot prompt itsOwner | (self hasOwner: aMorph) ifTrue: "tricky situation that can arise in embed" [itsOwner := aMorph owner. aMorph delete. itsOwner addMorphFrontFromWorldPosition: self]. self addMorphFront: aMorph fromWorldPosition: aMorph positionInWorld. addSlot := self shouldAddSlotForEmbeddedMorph: aMorph. addSlot ifFalse: [ ^self ]. prompt := self shouldPromptForSlotForEmbeddedMorph: aMorph. (prompt not or: [ self confirm: ('add slot for {1}' translated format: {aMorph externalName}) ]) ifTrue: [ self assuredPlayer createSlotFor: aMorph ].! ! !UpdatingMenuItemMorph methodsFor: '*green' stamp: 'sw 9/29/2007 00:49'! updateContents "Update the receiver's contents, both with regard to wording and to enablement. The wordingProvider is sent the wordingSelector (if any) to obtain the desired wording, and the wordingProvider is sent the enablementSelector (if any) to determine whether the item should be enabled." | newString enablement nArgs | wordingProvider ifNil: [^ self]. enablementSelector ifNotNil: [(enablement _ self enablement) == isEnabled ifFalse: [self isEnabled: enablement]]. wordingSelector ifNil: [^ self]. nArgs _ wordingSelector numArgs. newString _ nArgs == 0 ifTrue: [wordingProvider perform: wordingSelector] ifFalse: [(nArgs == 1 and: [wordingArgument notNil]) ifTrue: [wordingProvider perform: wordingSelector with: wordingArgument] ifFalse: [nArgs == arguments size ifTrue: [wordingProvider perform: wordingSelector withArguments: arguments]]]. newString = (self contentString ifNil: [contents]) ifFalse: [self contents: newString. MenuIcons decorateMenu: owner]! ! !UpdatingMenuMorph methodsFor: '*green' stamp: 'sw 8/7/2003 16:34'! updateMenu "Reconstitute the menu by first removing the contents and then building it afresh" self removeAllMorphs. self removeProperty: #hasTitlebarWidgets. updater perform: updateSelector with: self. stayUp == true ifTrue: [self removeStayUpBox] ! !