-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBlock Exchanger.cs
355 lines (325 loc) · 16.8 KB
/
Block Exchanger.cs
1
'From MIT Squeak 0.9.4 (June 1, 2003) [No updates present.] on 11 July 2015 at 3:35:27 pm'!StringMorph subclass: #MenuItemMorph instanceVariableNames: 'isInTransition isEnabled subMenu isSelected target selector arguments icon ' classVariableNames: 'SubMenuMarker ' poolDictionaries: '' category: 'Morphic-Menus'!Object subclass: #PopUpMenu instanceVariableNames: 'labelString font lineArray frame form marker selection ' classVariableNames: 'MenuStyle ' poolDictionaries: '' category: 'Tools-Menus'!SelectionMenu subclass: #CustomMenu instanceVariableNames: 'title labels dividers lastDivider isHorizontal icons includesUTF8 ' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'!!CommandBlockMorph methodsFor: 'menus'!addBlockTransformItemsToMenu: t1 | t2 t3 t4 t5 | t2 _ Dictionary new. t3 _ #((#forward: (('change x by ()' #changeXposBy:) ('change y by ()' #changeYposBy:))) (#moveSteps:direction: (('move () steps towards [ v]' #moveSteps:towardsSprite:))) (#moveSteps:towardsSprite: (('move () steps direction ( v)' #moveSteps:direction:))) (#turnRight: (('turn <-- () degrees' #turnLeft:))) (#turnLeft: (('turn --> () degrees' #turnRight:))) (#heading: (('point towards [ v]' #pointTowards:))) (#pointTowards: (('point in direction ( v)' #heading:))) (#heading (('x position' #xpos) ('y position' #ypos))) (#gotoX:y: (('go to [ v]' #gotoSpriteOrMouse:) ('glide () secs to x: () y: ()' #glideSecs:toX:y:elapsed:from:))) (#gotoSpriteOrMouse: (('go to x: () y: ()' #gotoX:y:) ('glide () secs to x: () y: ()' #glideSecs:toX:y:elapsed:from:))) (#changeXposBy: (('set x to ()' #xpos:) ('change y by ()' #changeYposBy:) ('move () steps' #forward:))) (#changeYposBy: (('set y to ()' #ypos:) ('change x by ()' #changeXposBy:) ('move () steps' #forward:))) (#xpos: (('change x by ()' #changeXposBy:) ('set y to ()' #ypos:) ('go to x: () y: ()' #gotoX:y:))) (#ypos: (('change y by ()' #changeYposBy:) ('set x to ()' #xpos:) ('go to x: () y: ()' #gotoX:y:))) (#xpos (('y position' #ypos) ('direction' #heading))) (#ypos (('x position' #xpos) ('direction' #heading))) (#wait:elapsed:from: (('wait until <>' #doWaitUntil))) (#doForever (('forever if <>' #doForeverIf) ('repeat ()' #doRepeat))) (#doForeverIf (('forever' #doForever) ('repeat until <>' #doUntil) ('if <>' #doIf))) (#doWaitUntil (('wait () secs' #wait:elapsed:from:))) (#doBlock (('sprite [ v] run' #doSpriteRun))) (#doSpriteRun (('block' #doBlock))) (#helpFor: (('run []' #doSpriteRunBlock))) (#commandSpecFor: (('call []' #spriteCallBlock) ('block []' #returnBlock:))) (#doSpriteRunBlock (('help for []' #helpFor:))) (#showWatcherForBlock: (('hide watcher for []' #hideWatcherForBlock:))) (#hideWatcherForBlock: (('show watcher for []' #showWatcherForBlock:))) (#returnBlock: (('call []' #sprite:callBlock:) ('label for []' #commandSpecFor:))) (#spriteCallBlock (('block []' #returnBlock:) ('label for []' #commandSpecFor:))) (#object:perform:withArgs: (('run code []' #runCode:))) (#runCode: (('[[]v] peform [] with args [[]v] <>' #object:perform:withArgs:))) (#costumeIndex (('' #returnCostume:) ('' #scale))) (#returnCostume: (('' #costumeIndex))) (#lookLike: (('' #nextCostume) ('' #deleteCostume:) ('' #replaceCostume:with:) ('' #newCostume:named:))) (#nextCostume (('' #lookLike:))) (#newCostume:named: (('' #lookLike:))) (#replaceCostume:with: (('' #lookLike:) ('' #deleteCostume:) ('' #newCostume:named:))) (#deleteCostume: (('' #lookLike:) ('' #replaceCostume:with:) ('' #newCostume:named:))) (#say: (('' #say:duration:elapsed:from:) ('' #think:))) (#say:duration:elapsed:from: (('' #think:duration:elapsed:from:) ('' #say:))) (#think: (('' #think:duration:elapsed:from:) ('' #say:))) (#think:duration:elapsed:from: (('' #say:duration:elapsed:from:) ('' #think:))) (#changeGraphicEffect:by: (('' #setGraphicEffect:to:) ('' #filterReset))) (#setGraphicEffect:to: (('' #changeGraphicEffect:by:) ('' #filterReset))) (#filterReset (('' #setGraphicEffect:to:) ('' #changeGraphicEffect:by:) ('' #applyFilterPackToCostume))) (#applyFilterPackToCostume (('' #setGraphicEffect:to:) ('' #changeGraphicEffect:by:) ('' #filterReset))) (#changeSizeBy: (('' #setSizeTo:))) (#setSizeTo: (('' #changeSizeBy:))) (#show (('' #hide))) (#hide (('' #show))) (#scale (('' #costumeIndex) ('' #layer))) (#comeToFront (('' #goInFrontOf:) ('' #layer:) ('' #goBackByLayers:))) (#layer: (('' #comeToFront) ('' #goBackByLayers:))) (#goBackByLayers: (('' #comeToFront) ('' #layer:))) (#layer (('' #scale))) (#goInFrontOf: (('' #goBehind:) ('' #comeToFront))) (#goBehind: (('' #goInFrontOf:) ('' #comeToFront))) (#stopAll (('' #doReturn) ('' #stopMyScripts))) (#doReturn (('' #stopAll) ('' #stopMyScripts))) (#stopMyScripts (('' #stopAll) ('' #doReturn))) (#broadcast: (('' #doBroadcastAndWait))) (#doBroadcastAndWait (('' #broadcast:))) (#deleteMe (('' #cloneMe))) (#playSound: (('' #doPlaySoundAndWait) ('' #playSound:from:to:) ('' #pauseSound:))) (#pauseSound: (('' #resumeSound:) ('' #playSound:) ('' #stopSound:))) (#resumeSound: (('' #pauseSound:) ('' #playSound:) ('' #stopSound:))) (#stopSound: (('' #stopAllSounds) ('' #playSound:))) (#stopAllSounds (('' #stopSound:) ('' #playSound:))) (#doPlaySoundAndWait (('' #playSound:) ('' #playSound:from:to:) ('' #pauseSound:))) (#playSound:from:to: (('' #doPlaySoundAndWait) ('' #playSound:) ('' #pauseSound:))) (#sounds (('' #sound:))) (#sound: (('' #sounds))) (#recordSound (('' #addSound:))) (#addSound: (('' #recordSound))) (#clearPenTrails (('' #stampCostume) ('' #stampForm:atX:y:))) (#stampCostume (('' #clearPenTrails) ('' #stampForm:atX:y:))) (#stampForm:atX:y: (('' #clearPenTrails) ('' #stampCostume))) (#putPenDown (('' #putPenUp))) (#putPenUp (('' #putPenDown))) (#penColor (('' #penHue) ('' #penShade) ('' #penSize))) (#penHue (('' #penColor) ('' #penShade) ('' #penSize))) (#penShade (('' #penColor) ('' #penHue) ('' #penSize))) (#penSize (('' #penColor) ('' #penShade) ('' #penHue))) (#penColor: (('' #setPenHueTo:) ('' #penSize:) ('' #setPenShadeTo:))) (#setPenHueTo: (('' #changePenHueBy:) ('' #penColor:) ('' #penSize:) ('' #setPenShadeTo:))) (#penSize: (('' #changePenSizeBy:) ('' #setPenHueTo:) ('' #penColor:) ('' #setPenShadeTo:))) (#setPenShadeTo: (('' #changePenShadeBy:) ('' #setPenHueTo:) ('' #penSize:) ('' #penColor:))) (#changePenHueBy: (('' #setPenHueTo:) ('' #changePenSizeBy:) ('' #changePenHueBy:))) (#changePenSizeBy: (('' #penSize:) ('' #changePenHueBy:) ('' #changePenShadeBy:))) (#changePenShadeBy: (('' #setPenShadeTo:) ('' #changePenHueBy:) ('' #changePenSizeBy:))) (#httpGet:args:accept: (('' #httpPostDocument:args:accept:request:))) (#httpPostDocument:args:accept:request: (('' #httpGet:args:accept:))) (#hostMesh (('' #joinMesh:) ('' #leaveMesh))) (#getMeshIPAdress (('' #meshVar:))) (#meshVar: (('' #getMeshIPAdress))) (#contentsOf: (('' #getElement:byID:))) (#getElement:byID: (('' #contentsOf:))) (#asciiFor: (('' #letterFromAscii:))) (#letterFromAscii: (('' #asciiFor:))) (#true (('' #false))) (#false (('' #true))) (#formHeight: (('' #formWidth:))) (#formWidth: (('' #formHeight:))) (#touching: (('' #touchingColor:) ('' #color:sees:))) (#touchingColor: (('' #color:sees:) ('' #touching:))) (#color:sees: (('' #touchingColor:) ('' #touching:))) (#mouseX (('' #mouseY))) (#mouseY (('' #mouseX))) (#keyPressed: (('' #mousePressed:))) (#mousePressed: (('' #keyPressed:))) (#showBackground: (('' #nextBackground))) (#nextBackground (('' #showBackground:))) ). t5 _ submorphs detect: [:t6 | t6 isKindOf: BlockMorph] ifNone: []. t5 ifNil: [t3 _ t3 , #((#cloneMe (('' #deleteMe))) (#doRepeat (('repeat until<>' #doUntil) ('forever' #doForever))) (#doIf (('if <> else' #doIfElse) ('forever if <>' #doForeverIf) ('repeat until <>' #doUntil))) (#doUntil (('forever if <>' #doForeverIf) ('repeat ()' #doRepeat))) )] ifNotNil: [t3 _ t3 , #((#doRepeat (('repeat until <>' #doUntil))) (#doIf (('if <> else' #doIfElse) ('repeat until <>' #doUntil))) (#doUntil (('repeat ()' #doRepeat))) )]. t3 do: [:t7 | t2 at: t7 first put: t7 second]. t4 _ t2 at: selector ifAbsent: [{nil}]. t4 do: [:t8 | t8 ifNil: [^ nil]. [t1 addIcon: (self receiver blockFromSpec: (self receiver fullBlockSpecForSelector: t8 second) color: self color) imageForm toolTip: nil action: t8 second] ifError: []]! !!CommandBlockMorph methodsFor: 'menus'!rightButtonMenu | t1 t2 t3 t4 t5 | t1 _ CustomMenu new. t1 add: 'help' action: #presentHelpScreen. (owner isKindOf: ScratchBlockPaletteMorph) ifFalse: [self addBlockTransformItemsToMenu: t1]. (owner isKindOf: ScratchBlockPaletteMorph) ifFalse: [t1 addLine. (#(#+ #- #* #/ #\\ ) includes: selector) ifTrue: [#(#+ #- #* #/ #mod ) with: #(#+ #- #* #/ #\\ ) do: [:t6 :t7 | t1 addIcon: (self receiver blockFromSpec: {'%n' , t6 , '%n'. #r. t7} color: self color) imageForm toolTip: nil action: t7]]. (#(#< #= #> ) includes: selector) ifTrue: [#(#< #= #> ) do: [:t7 | t1 addIcon: (self receiver blockFromSpec: {'%s' , t7 , '%s'. #b. t7} color: self color) imageForm toolTip: nil action: t7]]. (#(#& #| ) includes: selector) ifTrue: [#(#and #or ) with: #(#& #| ) do: [:t6 :t7 | t1 addIcon: (self receiver blockFromSpec: {'%b' , t6 , '%b'. #b. t7} color: self color) imageForm toolTip: nil action: t7]]. t1 addLine. t1 add: 'duplicate' action: #duplicate. (self owner isKindOf: BlockMorph) ifFalse: [t1 add: 'delete' action: #delete]]. t2 _ self ownerThatIsA: ScratchFrameMorph. (t2 notNil and: [#(#sensor: #sensorPressed: ) includes: selector]) ifTrue: [t1 addLine. t1 add: 'show ScratchBoard watcher' action: #showSensorBoard. t2 workPane scratchServer ifNil: [t1 add: 'enable remote sensor connections' action: #enableRemoteSensors] ifNotNil: [t1 add: 'disable remote sensor connections' action: #exitScratchSession]]. DebugMenu ifTrue: [t1 addLine. t1 add: 'show tuples' action: #showTuples]. (t3 _ t1 localize; startUp) ifNil: [^ self]. (#(#presentHelpScreen #duplicate #delete ) includes: t3) ifTrue: [^ self perform: t3]. t3 = #showSensorBoard ifTrue: [t2 showSensorBoard. ^ self]. t3 = #enableRemoteSensors ifTrue: [t2 enableRemoteSensors. ^ self]. t3 = #exitScratchSession ifTrue: [t2 exitScratchSession. ^ self]. t3 = #showTuples ifTrue: [^ self showTuples]. t3 isInfix ifFalse: [t2 _ self receiver blockSpecForSelector: t3. t2 ifNil: [^ self beep]. self selector: t3. selector numArgs = argMorphs size ifFalse: [self removeAllMorphsIn: (submorphs select: [:t8 | (t8 isKindOf: ArgMorph) | (t8 isKindOf: StringMorph)]). argMorphs _ OrderedCollection new. argPermutation _ CommandBlockMorph argPermutationForSpec: t2 withTranslation: (ScratchTranslator translationFor: t2)]. self commandSpec: t2. t5 _ (self receiver fullBlockSpecForSelector: selector) second. self isTimed: t5 = #t. (self isKindOf: ReporterBlockMorph) ifTrue: [self isBoolean: t5 = #b]. self isSpecialForm: t5 = #s | (t5 = #c). ^ self]. t4 _ '%n ' , t3 , ' %n'. '\\' = t3 ifTrue: [t4 _ ScratchTranslator translationFor: '%n mod %n']. '&' = t3 ifTrue: [t4 _ ScratchTranslator translationFor: '%b and %b']. '|' = t3 ifTrue: [t4 _ ScratchTranslator translationFor: '%b or %b']. self commandSpec: t4. self selector: t3! !!MenuItemMorph methodsFor: 'drawing'!drawOn: t1 | t2 t3 t4 | isSelected & isEnabled ifTrue: [t2 _ Display depth <= 2 ifTrue: [Color gray] ifFalse: [owner color darker]. t1 fillRectangle: self bounds color: t2]. super drawOn: t1. subMenu ifNotNil: [t1 paintImage: SubMenuMarker at: self right - 8 @ (self top + self bottom - SubMenuMarker height // 2)]. icon ifNotNil: [t3 _ self width - icon width // 2. t4 _ self height - icon height // 2. t1 paintImage: icon at: self position + (t3 @ t4)]! !!MenuItemMorph methodsFor: 'layout'!layoutInWidth: t1 height: t2 icon ifNotNil: [^ self extent: (icon extent max: t1 @ t2)]. self extent: ((self stringExtent: contents) max: t1 @ t2)! !!MenuItemMorph methodsFor: 'layout'!minHeight icon ifNotNil: [^ icon height + 2]. ^ self extent y! !!MenuItemMorph methodsFor: 'layout'!minWidth icon ifNotNil: [^ icon width + 2]. ^ (self stringWidth: contents) + (subMenu ifNil: [0] ifNotNil: [10])! !!MenuItemMorph methodsFor: 'private'!icon: t1 icon _ t1! !!MenuMorph methodsFor: 'construction'!addIcon: t1 tooltip: t2 action: t3 self addIcon: t1 tooltip: t2 target: defaultTarget selector: t3 argumentList: Array empty! !!MenuMorph methodsFor: 'construction'!addIcon: t1 tooltip: t2 target: t3 selector: t4 argumentList: t5 | t6 | t6 _ MenuItemMorph new icon: t1; contents: ''; setBalloonText: t2; target: t3; selector: t4; arguments: t5 asArray. self addMorphBack: t6! !!MVCMenuMorph class methodsFor: 'instance creation'!from: t1 title: t2 | t3 t4 t5 t6 t7 t8 t9 t10 t11 | t3 _ self new. t1 isHorizontal ifTrue: [t3 orientation: #horizontal]. t2 ifNotNil: [t2 isEmpty ifFalse: [t3 addTitle: t2]]. t7 _ t1 labelString. t4 _ t7 asString findTokens: String cr. t10 _ t1 icons. t10 ifNil: [t10 _ Array empty]. t10 size = t4 size ifFalse: [t10 _ Array new: t4 size]. t7 isText ifTrue: [t8 _ 1. t4 _ t4 collect: [:t12 | t8 _ t7 asString findString: t12 startingAt: t8. t9 _ TextEmphasis new emphasisCode: (t7 emphasisAt: t8). t12 asText addAttribute: t9]]. t5 _ t1 lineArray. t5 ifNil: [t5 _ #()]. t3 cancelValue: 0. t6 _ (1 to: t4 size) asArray. ScratchTranslator isRTL & t1 isHorizontal ifTrue: [t4 size to: 1 by: -1 do: [:t13 | t11 _ t10 at: t13. t11 isNil ifTrue: [t3 add: (t4 at: t13) action: (t6 at: t13)] ifFalse: [t3 addIcon: t11 first tooltip: t11 second action: (t6 at: t13)]. (t5 includes: t13) ifTrue: [t3 addLine]]. nil] ifFalse: [1 to: t4 size do: [:t13 | t11 _ t10 at: t13. t11 isNil ifTrue: [t3 add: (t4 at: t13) action: (t6 at: t13)] ifFalse: [t3 addIcon: t11 first tooltip: t11 second action: (t6 at: t13)]. (t5 includes: t13) ifTrue: [t3 addLine]]. nil]. (ScratchTranslator canRenderUnicode and: [t7 notNil and: [t7 isUnicode or: [(UTF8 withAll: t7) isMacRoman not]]]) ifTrue: [t3 convertItemsToUTF8]. ^ t3! !!PopUpMenu methodsFor: 'accessing'!icons ^ Array empty! !!PopUpMenu methodsFor: 'accessing'!isHorizontal ^ false! !!PopUpMenu methodsFor: 'basic control sequence'!startUpWithCaption: t1 at: t2 | t3 t4 t5 | t3 _ Display height * 3 // 4. self frameHeight > t3 ifTrue: [^ self startUpSegmented: t3 withCaption: t1 at: t2]. Smalltalk isMorphic ifTrue: [t4 _ MVCMenuMorph from: self title: t1. t5 _ t2. self isHorizontal & ScratchTranslator isRTL ifTrue: [t5 _ t2 - (t4 width @ 0)]. selection _ Cursor normal showWhile: [t4 invokeAt: t5 in: World]. ^ selection]. frame ifNil: [self computeForm]. Cursor normal showWhile: [self displayAt: t2 withCaption: t1 during: [self controlActivity]]. ^ selection! !!ScriptableScratchMorph methodsFor: 'accessing'!fullBlockSpecForSelector: t1 self class blockSpecs do: [:t2 | ((t2 isKindOf: Array) and: [(t2 at: 3) = t1]) ifTrue: [^ t2]. nil]. ^ nil! !!SelectionMenu methodsFor: 'accessing'!width ^ (MVCMenuMorph from: self title: nil) width! !!CustomMenu methodsFor: 'initialize-release'!initialize labels _ OrderedCollection new. icons _ OrderedCollection new. selections _ OrderedCollection new. dividers _ OrderedCollection new. isHorizontal _ false. lastDivider _ 0. includesUTF8 _ false! !!CustomMenu methodsFor: 'accessing'!beHorizontal isHorizontal _ true! !!CustomMenu methodsFor: 'accessing'!icons ^ icons! !!CustomMenu methodsFor: 'accessing'!isHorizontal ^ isHorizontal! !!CustomMenu methodsFor: 'construction'!add: t1 action: t2 | t3 | t3 _ String new: t1 size + 2. t3 at: 1 put: Character space. t3 replaceFrom: 2 to: t3 size - 1 with: t1. t3 at: t3 size put: Character space. t1 isUnicode ifTrue: [includesUTF8 _ true]. labels addLast: t3. icons add: nil. selections addLast: t2! !!CustomMenu methodsFor: 'construction'!addIcon: t1 toolTip: t2 action: t3 icons size = labels size ifFalse: [^ self error: 'inconsistent menu construction']. labels addLast: ' '. icons addLast: (Array with: t1 with: t2). selections addLast: t3! !!CustomMenu methodsFor: 'construction'!localize | t1 | labels _ labels collect: [:t2 | t1 _ (t2 copyFrom: 2 to: t2 size - 1) localized. t1 isUnicode ifTrue: [includesUTF8 _ true]. UTF8 withAll: ' ' , t1 , ' ']. title ifNotNil: [title _ title localized]. icons do: [:t3 | t3 ifNotNil: [t3 second ifNotNil: [t3 at: 2 put: (t3 at: 2) localized]]]! !SelectionMenu subclass: #CustomMenu instanceVariableNames: 'title labels dividers lastDivider includesUTF8 icons isHorizontal ' classVariableNames: '' poolDictionaries: '' category: 'Tools-Menus'!