From 0adb9352e914779ea1a5e759799a6c5baa95e478 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Tue, 28 Nov 2023 23:54:37 +0100 Subject: [PATCH 1/8] Adds basic live view --- .../SBDiffTabView.class.st | 21 ++- .../SBExploriants.class.st | 16 +++ .../SBExploriantsView.class.st | 2 +- .../SBInactiveExampleWatch.class.st | 7 +- .../SBInactiveExampleWatch.extension.st | 7 +- .../SBInputBroadcaster.class.st | 66 +++++++++ .../Sandblocks-Babylonian/SBLiveView.class.st | 131 ++++++++++++++++++ packages/Sandblocks-Core/SBTabView.class.st | 4 +- 8 files changed, 243 insertions(+), 11 deletions(-) create mode 100644 packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st create mode 100644 packages/Sandblocks-Babylonian/SBLiveView.class.st diff --git a/packages/Sandblocks-Babylonian/SBDiffTabView.class.st b/packages/Sandblocks-Babylonian/SBDiffTabView.class.st index 2b6e70f5..6119ecbf 100644 --- a/packages/Sandblocks-Babylonian/SBDiffTabView.class.st +++ b/packages/Sandblocks-Babylonian/SBDiffTabView.class.st @@ -7,6 +7,22 @@ Class { #category : #'Sandblocks-Babylonian' } +{ #category : #nil } +SBDiffTabView >> addButton [ + + ^ SBButton new + icon: (SBIcon iconPlus + size: 7.0 sbScaled; + color: (Color green)) + do: [self addTab]; + makeSmall; + cornerStyle: #squared; + vResizing: #spaceFill; + balloonText: 'Add'; + cellGap: -1.0 sbScaled; + layoutInset: (4.0 @ 4.0) sbScaled +] + { #category : #callbacks } SBDiffTabView >> artefactSaved: aMethodBlock [ @@ -54,13 +70,14 @@ SBDiffTabView >> buildView [ SBDiffTabView >> diffButton [ ^ SBButton new - icon: (SBIcon iconCodeFork size: 12.0 sbScaled) + icon: (SBIcon iconCodeFork size: 12.0) do: [self toggleDiffView]; makeSmall; balloonText: 'Toggle diff to others'; + vResizing: #spaceFill; cornerStyle: #squared; cellGap: -1.0 sbScaled; - layoutInset: (4.0 @ 3.0) sbScaled + layoutInset: (4.0 @ 3.0) ] { #category : #diffing } diff --git a/packages/Sandblocks-Babylonian/SBExploriants.class.st b/packages/Sandblocks-Babylonian/SBExploriants.class.st index 14f65139..0f1a04c5 100644 --- a/packages/Sandblocks-Babylonian/SBExploriants.class.st +++ b/packages/Sandblocks-Babylonian/SBExploriants.class.st @@ -43,6 +43,22 @@ SBExploriants >> = other [ ^ self class = other class ] +{ #category : #'as yet unclassified' } +SBExploriants >> cacheType: aClass for: aBlock [ +] + +{ #category : #'as yet unclassified' } +SBExploriants >> evaluationContext [ + + ^ nil +] + +{ #category : #'as yet unclassified' } +SBExploriants >> evaluationReceiver [ + + ^ self object +] + { #category : #initialization } SBExploriants >> initialize [ diff --git a/packages/Sandblocks-Babylonian/SBExploriantsView.class.st b/packages/Sandblocks-Babylonian/SBExploriantsView.class.st index 6b87edc1..3add0d53 100644 --- a/packages/Sandblocks-Babylonian/SBExploriantsView.class.st +++ b/packages/Sandblocks-Babylonian/SBExploriantsView.class.st @@ -17,7 +17,7 @@ SBExploriantsView class >> block: aSBBlock named: aString [ { #category : #'instance creation' } SBExploriantsView class >> getTabsInMultiverse: aSBMultiverse [ - ^ {SBPermutationGridsView. SBExampleGridsView. SBPlainResultsView. SBVariantsView} + ^ {SBPermutationGridsView. SBExampleGridsView. SBPlainResultsView. SBLiveView. SBVariantsView} collect: [:mySubclass | mySubclass newMultiverse: aSBMultiverse] ] diff --git a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st index 308117de..91c075be 100644 --- a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st +++ b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st @@ -57,7 +57,8 @@ SBInactiveExampleWatch >> saveObjectsActivePermutations [ "Force morphs to persist their permutation even when on the UI process" exampleToDisplay associationsDo: [:anExampleDisplayPair | anExampleDisplayPair value displayedWatchValueBlocks do: [:aValueMorph | - SBExploriants objectToPermutation - at: aValueMorph lastSubmorph - put: SBActiveVariantPermutation value]]. + aValueMorph lastSubmorph allMorphsDo: [:aSubMorph | + SBExploriants objectToPermutation + at: aSubMorph + put: SBActiveVariantPermutation value]]]. ] diff --git a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.extension.st b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.extension.st index 50276e55..0b86b4f6 100644 --- a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.extension.st +++ b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.extension.st @@ -12,7 +12,8 @@ SBInactiveExampleWatch >> saveObjectsActivePermutations [ "Force morphs to persist their permutation even when on the UI process" exampleToDisplay associationsDo: [:anExampleDisplayPair | anExampleDisplayPair value displayedWatchValueBlocks do: [:aValueMorph | - SBExploriants objectToPermutation - at: aValueMorph lastSubmorph - put: SBActiveVariantPermutation value]]. + aValueMorph lastSubmorph allMorphsDo: [:aSubMorph | + SBExploriants objectToPermutation + at: aSubMorph + put: SBActiveVariantPermutation value]]]. ] diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st new file mode 100644 index 00000000..8d1eb2e4 --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -0,0 +1,66 @@ +Class { + #name : #SBInputBroadcaster, + #superclass : #Morph, + #instVars : [ + 'listeners' + ], + #category : #'Sandblocks-Babylonian' +} + +{ #category : #events } +SBInputBroadcaster >> filterEvent: anEvent for: aMorph [ + + self flag: #todo. "Die Position im Morph in den listener transformieren" + self listeners do: [:aListener | aListener processEvent: (anEvent copy position: aListener position)]. + ^ anEvent +] + +{ #category : #'events-processing' } +SBInputBroadcaster >> handleMouseOver: anEvent [ + + super handleMouseOver: anEvent. + anEvent hand newKeyboardFocus: self. + +] + +{ #category : #'event handling' } +SBInputBroadcaster >> handlesKeyboard: evt [ + + ^ true + +] + +{ #category : #initialization } +SBInputBroadcaster >> initialize [ + + super initialize. + + listeners := OrderedCollection new. + + self + addKeyboardCaptureFilter: self; + "addMouseCaptureFilter: self;" + extent: 300@200; + color: Color veryLightGray; + changeTableLayout; + listDirection: #topToBottom; + wrapCentering: #center; + listCentering: #center; + addMorph: (StringMorph new + contents: 'Enter Input here'; + color: Color white; + yourself) + +] + +{ #category : #accessing } +SBInputBroadcaster >> listeners [ + + ^ listeners +] + +{ #category : #accessing } +SBInputBroadcaster >> listeners: aCollectionOfMorphs [ + + listeners := aCollectionOfMorphs. +] diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st new file mode 100644 index 00000000..00bd7a74 --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -0,0 +1,131 @@ +Class { + #name : #SBLiveView, + #superclass : #SBGridResultsView, + #instVars : [ + 'broadcaster' + ], + #category : #'Sandblocks-Babylonian' +} + +{ #category : #'as yet unclassified' } +SBLiveView >> buildAllPossibleResults [ + + self multiverse universes do: [:aUniverse | self buildPreviewFor: aUniverse activePermutation] +] + +{ #category : #'as yet unclassified' } +SBLiveView >> buildBrodcaster [ + + self block addMorphBack: (SBRow new + changeTableLayout; + hResizing: #spaceFill; + wrapCentering: #center; + listCentering: #center; + cellPositioning: #center; + addMorph: (broadcaster := SBInputBroadcaster new)) +] + +{ #category : #'as yet unclassified' } +SBLiveView >> buildPreviewFor: aPermutation [ + + gridContainer addMorphBack: (self containerRow cellPositioning: #center; + addAllMorphsBack: { + self containerRow listDirection: #topToBottom; + addAllMorphsBack: { + SBOwnTextMorph new contents: aPermutation asString. + SBButton newApplyPermutationFor: aPermutation. + self newRegisteredListenerFor: aPermutation}. + LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). + + self updateContainerWidth. +] + +{ #category : #'as yet unclassified' } +SBLiveView >> buildSetUpRow [ + + self block addMorph: (SBRow new + changeTableLayout; + hResizing: #spaceFill; + wrapCentering: #center; + listCentering: #center; + cellPositioning: #center; + cellGap: 8 * self scalingFactor; + addMorphBack: (SBIcon iconSpinner + balloonText: 'Toggle stepping'; + on: #click send: #toggleStepping to: self); + addMorphBack: (SBStringMorph new contents: 'Setup:'); + addMorphBack: (([Morph new] asSandblock statements first) width: 200)) +] + +{ #category : #'as yet unclassified' } +SBLiveView >> clean [ + + self block submorphs allButFirst copy do: #delete. + + gridContainer := self newGridContainer. +] + +{ #category : #'as yet unclassified' } +SBLiveView >> evaluateSetUp [ + + ^ self setUpMorph evaluate +] + +{ #category : #'as yet unclassified' } +SBLiveView >> gridObjects [ + + ^ self multiverse universes +] + +{ #category : #initialization } +SBLiveView >> initialize [ + + super initialize. + + self name: 'Live View'. + self buildSetUpRow. +] + +{ #category : #'as yet unclassified' } +SBLiveView >> listeners [ + + ^ broadcaster listeners +] + +{ #category : #'as yet unclassified' } +SBLiveView >> newRegisteredListenerFor: aPermutation [ + + | listener | + listener := self evaluateSetUp. + broadcaster listeners add: listener. + + listener allMorphsDo: [:aSubMorph | + SBExploriants objectToPermutation at: aSubMorph put: aPermutation]. + + ^ listener + +] + +{ #category : #'as yet unclassified' } +SBLiveView >> setUpMorph [ + + ^ self block firstSubmorph "setup row" lastSubmorph +] + +{ #category : #'as yet unclassified' } +SBLiveView >> toggleStepping [ + + self listeners do: [:aMorph | + aMorph isStepping ifFalse: [aMorph startStepping] ifTrue: [aMorph stopStepping]] +] + +{ #category : #'as yet unclassified' } +SBLiveView >> visualize [ + + self clean. + + self buildBrodcaster. + self block addMorphBack: self updateButton. + self block addMorphBack: gridContainer. + self buildAllPossibleResults. +] diff --git a/packages/Sandblocks-Core/SBTabView.class.st b/packages/Sandblocks-Core/SBTabView.class.st index a299ca6f..68d361ed 100644 --- a/packages/Sandblocks-Core/SBTabView.class.st +++ b/packages/Sandblocks-Core/SBTabView.class.st @@ -113,7 +113,7 @@ SBTabView >> addButton [ ^ SBButton new icon: (SBIcon iconPlus - size: 8.0 sbScaled; + size: 7.0 sbScaled; color: (Color green)) do: [self addTab]; makeSmall; @@ -121,7 +121,7 @@ SBTabView >> addButton [ vResizing: #spaceFill; balloonText: 'Add'; cellGap: -1.0 sbScaled; - layoutInset: (4.0 @ 5.0) sbScaled + layoutInset: (4.0 @ 4.0) sbScaled ] { #category : #commands } From 07e07d9a371690aa1fa5d68807956dab4d8e7d4e Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Mon, 4 Dec 2023 18:22:50 +0100 Subject: [PATCH 2/8] Adds basic mouse and drop event handling --- .../SBExampleGridsView.class.st | 4 +- .../SBGridResultsView.class.st | 4 +- .../SBInputBroadcaster.class.st | 99 +++++++++++++++---- .../Sandblocks-Babylonian/SBLiveView.class.st | 55 +++++++---- .../SBPermutationGridsView.class.st | 4 +- 5 files changed, 121 insertions(+), 45 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st b/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st index ece2e6bb..7b5c20ab 100644 --- a/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st @@ -31,9 +31,9 @@ SBExampleGridsView >> buildExampleFor: aNumber [ ] { #category : #updating } -SBExampleGridsView >> gridObjects [ +SBExampleGridsView >> gridSize [ - ^ self multiverse activeExamples + ^ self multiverse activeExamples size ] { #category : #initialization } diff --git a/packages/Sandblocks-Babylonian/SBGridResultsView.class.st b/packages/Sandblocks-Babylonian/SBGridResultsView.class.st index ab2c8af9..13bb11d2 100644 --- a/packages/Sandblocks-Babylonian/SBGridResultsView.class.st +++ b/packages/Sandblocks-Babylonian/SBGridResultsView.class.st @@ -17,7 +17,7 @@ SBGridResultsView >> clean [ ] { #category : #updating } -SBGridResultsView >> gridObjects [ +SBGridResultsView >> gridSize [ self subclassResponsibility ] @@ -50,7 +50,7 @@ SBGridResultsView >> newGridContainer [ SBGridResultsView >> updateContainerWidth [ gridContainer width: - self gridObjects size safeSquareRoot ceiling + self gridSize safeSquareRoot ceiling * (gridContainer lastSubmorph fullBounds width + (2 * gridContainer cellInset) + (2 * gridContainer cellGap) diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st index 8d1eb2e4..4924d268 100644 --- a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -1,17 +1,61 @@ Class { #name : #SBInputBroadcaster, - #superclass : #Morph, + #superclass : #SBBlock, #instVars : [ - 'listeners' + 'listeners', + 'mice', + 'miceContainers' ], #category : #'Sandblocks-Babylonian' } +{ #category : #input } +SBInputBroadcaster >> absorbsInput: anEvent [ + + ^ true +] + +{ #category : #accessing } +SBInputBroadcaster >> addListener: aMorph [ + + self listeners add: aMorph. + self mice add: CircleMorph newPin. + + "adding mice as our own morphs will cause rattling" + self containers add: (Morph new + color: Color transparent; + extent: aMorph extent). + self containers last addMorph: aMorph. + self containers last addMorph: mice last. + + ^ self containers last + +] + +{ #category : #accessing } +SBInputBroadcaster >> containers [ + + ^ miceContainers +] + { #category : #events } SBInputBroadcaster >> filterEvent: anEvent for: aMorph [ - self flag: #todo. "Die Position im Morph in den listener transformieren" - self listeners do: [:aListener | aListener processEvent: (anEvent copy position: aListener position)]. + self listeners withIndexDo: [:aListener :i | | targetPosition newEvent | + targetPosition := self translatedPositionOf: anEvent from: aMorph to: aListener. + newEvent := anEvent copy. + + anEvent isDropEvent + ifTrue: [newEvent translateTo: targetPosition] + ifFalse: [newEvent translateBy: targetPosition - anEvent position]. + + aListener processEvent: newEvent. + (self mice at: i) position: targetPosition. + + (aListener containsPoint: targetPosition) + ifTrue: [(self mice at: i) show] + ifFalse: [(self mice at: i) hide]]. + ^ anEvent ] @@ -20,7 +64,7 @@ SBInputBroadcaster >> handleMouseOver: anEvent [ super handleMouseOver: anEvent. anEvent hand newKeyboardFocus: self. - + self sandblockEditor selectNoInput: self. ] { #category : #'event handling' } @@ -36,20 +80,15 @@ SBInputBroadcaster >> initialize [ super initialize. listeners := OrderedCollection new. + mice := OrderedCollection new. + miceContainers := OrderedCollection new. self + addEventCaptureFilter: self; addKeyboardCaptureFilter: self; - "addMouseCaptureFilter: self;" - extent: 300@200; - color: Color veryLightGray; - changeTableLayout; - listDirection: #topToBottom; - wrapCentering: #center; - listCentering: #center; - addMorph: (StringMorph new - contents: 'Enter Input here'; - color: Color white; - yourself) + addMouseCaptureFilter: self; + canDrag: false; + color: Color veryLightGray ] @@ -60,7 +99,31 @@ SBInputBroadcaster >> listeners [ ] { #category : #accessing } -SBInputBroadcaster >> listeners: aCollectionOfMorphs [ +SBInputBroadcaster >> mice [ + + ^ mice +] + +{ #category : #'events-processing' } +SBInputBroadcaster >> mouseEnter: anEvent [ + + super mouseEnter: anEvent. + anEvent hand newKeyboardFocus: self. +] - listeners := aCollectionOfMorphs. +{ #category : #events } +SBInputBroadcaster >> translatedPositionOf: anEvent from: anOriginMorph to: aTargetMorph [ + + | localAbsPoint localRelPoint targetAbsPoint | + localAbsPoint := anEvent position - anOriginMorph position. + localRelPoint := localAbsPoint / anOriginMorph extent. + targetAbsPoint := (localRelPoint * aTargetMorph extent) + aTargetMorph position. + + ^ targetAbsPoint rounded +] + +{ #category : #'event handling' } +SBInputBroadcaster >> wantsKeyboardFocus [ + + ^ true ] diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 00bd7a74..06f6043d 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -7,25 +7,36 @@ Class { #category : #'Sandblocks-Babylonian' } -{ #category : #'as yet unclassified' } +{ #category : #building } SBLiveView >> buildAllPossibleResults [ self multiverse universes do: [:aUniverse | self buildPreviewFor: aUniverse activePermutation] ] -{ #category : #'as yet unclassified' } +{ #category : #building } SBLiveView >> buildBrodcaster [ - self block addMorphBack: (SBRow new + gridContainer addMorphBack: (self containerRow cellPositioning: #center; + addAllMorphsBack: { + self containerRow listDirection: #topToBottom; + addAllMorphsBack: { + SBOwnTextMorph new contents: 'Event Broadcaster'. + broadcaster := SBInputBroadcaster new}. + LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). + + "gridContainer addMorphBack: (SBRow new changeTableLayout; hResizing: #spaceFill; wrapCentering: #center; listCentering: #center; cellPositioning: #center; - addMorph: (broadcaster := SBInputBroadcaster new)) + addMorph: (broadcaster := SBInputBroadcaster new))" + + self updateContainerWidth. + ] -{ #category : #'as yet unclassified' } +{ #category : #building } SBLiveView >> buildPreviewFor: aPermutation [ gridContainer addMorphBack: (self containerRow cellPositioning: #center; @@ -40,7 +51,7 @@ SBLiveView >> buildPreviewFor: aPermutation [ self updateContainerWidth. ] -{ #category : #'as yet unclassified' } +{ #category : #building } SBLiveView >> buildSetUpRow [ self block addMorph: (SBRow new @@ -54,10 +65,10 @@ SBLiveView >> buildSetUpRow [ balloonText: 'Toggle stepping'; on: #click send: #toggleStepping to: self); addMorphBack: (SBStringMorph new contents: 'Setup:'); - addMorphBack: (([Morph new] asSandblock statements first) width: 200)) + addMorphBack: ([Morph new] asSandblock width: 200)) ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBLiveView >> clean [ self block submorphs allButFirst copy do: #delete. @@ -65,16 +76,16 @@ SBLiveView >> clean [ gridContainer := self newGridContainer. ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBLiveView >> evaluateSetUp [ - ^ self setUpMorph evaluate + ^ self setUpMorph evaluate value ] -{ #category : #'as yet unclassified' } -SBLiveView >> gridObjects [ +{ #category : #updating } +SBLiveView >> gridSize [ - ^ self multiverse universes + ^ self multiverse universes size + 1 ] { #category : #initialization } @@ -86,40 +97,40 @@ SBLiveView >> initialize [ self buildSetUpRow. ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBLiveView >> listeners [ ^ broadcaster listeners ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBLiveView >> newRegisteredListenerFor: aPermutation [ - | listener | + | listener container | listener := self evaluateSetUp. - broadcaster listeners add: listener. + container := broadcaster addListener: listener. listener allMorphsDo: [:aSubMorph | SBExploriants objectToPermutation at: aSubMorph put: aPermutation]. - ^ listener + ^ container ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBLiveView >> setUpMorph [ ^ self block firstSubmorph "setup row" lastSubmorph ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBLiveView >> toggleStepping [ self listeners do: [:aMorph | aMorph isStepping ifFalse: [aMorph startStepping] ifTrue: [aMorph stopStepping]] ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBLiveView >> visualize [ self clean. @@ -128,4 +139,6 @@ SBLiveView >> visualize [ self block addMorphBack: self updateButton. self block addMorphBack: gridContainer. self buildAllPossibleResults. + + broadcaster extent: self listeners last extent. ] diff --git a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st index 101b5d4a..3eeeb208 100644 --- a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st +++ b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st @@ -28,9 +28,9 @@ SBPermutationGridsView >> buildPermutationFor: aSBUniverse [ ] { #category : #updating } -SBPermutationGridsView >> gridObjects [ +SBPermutationGridsView >> gridSize [ - ^ self multiverse universes + ^ self multiverse universes size ] { #category : #initialization } From dd97bea5d5487138bcb3cef56ec263780a13d639 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Mon, 4 Dec 2023 22:55:44 +0100 Subject: [PATCH 3/8] Rebuild this button --- .../SBExploriants.class.st | 21 ++++- .../SBInputBroadcaster.class.st | 12 +++ .../Sandblocks-Babylonian/SBLiveView.class.st | 77 +++++++++++++++---- .../SBResultsView.class.st | 2 +- 4 files changed, 92 insertions(+), 20 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBExploriants.class.st b/packages/Sandblocks-Babylonian/SBExploriants.class.st index 0f1a04c5..99f652ce 100644 --- a/packages/Sandblocks-Babylonian/SBExploriants.class.st +++ b/packages/Sandblocks-Babylonian/SBExploriants.class.st @@ -43,17 +43,32 @@ SBExploriants >> = other [ ^ self class = other class ] -{ #category : #'as yet unclassified' } +{ #category : #'ast helpers' } +SBExploriants >> binding: aString for: block class: aClass ifPresent: aBlock [ + + "See SBStContainer >> binding: for: class: ifPresent: " + | outer | + Symbol hasInterned: aString ifTrue: [:sym | | binding | + binding := aClass bindingOf: sym environment: UndefinedObject environment. + binding ifNotNil: [^ aBlock value: ((SBStName poolDeclaration: aString binding: binding) binding: binding)]]. + + outer := self outerArtefact. + (outer notNil and: [outer isSmalltalk]) ifTrue: [^ self outerArtefact binding: aString for: block class: aClass ifPresent: aBlock]. + + ^ nil +] + +{ #category : #testing } SBExploriants >> cacheType: aClass for: aBlock [ ] -{ #category : #'as yet unclassified' } +{ #category : #testing } SBExploriants >> evaluationContext [ ^ nil ] -{ #category : #'as yet unclassified' } +{ #category : #testing } SBExploriants >> evaluationReceiver [ ^ self object diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st index 4924d268..81b2fa48 100644 --- a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -111,6 +111,18 @@ SBInputBroadcaster >> mouseEnter: anEvent [ anEvent hand newKeyboardFocus: self. ] +{ #category : #accessing } +SBInputBroadcaster >> replaceListener: oldListener with: newListener [ + + | index | + index := self listeners indexOf: oldListener ifAbsent: [^ self]. + + (self containers at: index) replaceSubmorph: (self listeners at: index) by: newListener. + self listeners at: index put: newListener. + (self containers at: index) extent: newListener extent. + +] + { #category : #events } SBInputBroadcaster >> translatedPositionOf: anEvent from: anOriginMorph to: aTargetMorph [ diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 06f6043d..9fcf216e 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -21,34 +21,34 @@ SBLiveView >> buildBrodcaster [ self containerRow listDirection: #topToBottom; addAllMorphsBack: { SBOwnTextMorph new contents: 'Event Broadcaster'. + SBOwnTextMorph new contents: 'Interact to send events'. broadcaster := SBInputBroadcaster new}. LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). - "gridContainer addMorphBack: (SBRow new - changeTableLayout; - hResizing: #spaceFill; - wrapCentering: #center; - listCentering: #center; - cellPositioning: #center; - addMorph: (broadcaster := SBInputBroadcaster new))" - - self updateContainerWidth. +] + +{ #category : #building } +SBLiveView >> buildButtonRow [ + self block addMorphBack: (SBRow new + changeTableLayout; + cellGap: 8 * self scalingFactor; + addAllMorphsBack: {self updateButton. self rebuildButton}) ] { #category : #building } SBLiveView >> buildPreviewFor: aPermutation [ - + + | preview | + preview := self newRegisteredListenerFor: aPermutation. gridContainer addMorphBack: (self containerRow cellPositioning: #center; addAllMorphsBack: { self containerRow listDirection: #topToBottom; - addAllMorphsBack: { + addAllMorphsBack: { SBOwnTextMorph new contents: aPermutation asString. - SBButton newApplyPermutationFor: aPermutation. - self newRegisteredListenerFor: aPermutation}. + self newPermutationButtonRowFor: aPermutation showing: preview. + preview}. LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). - - self updateContainerWidth. ] { #category : #building } @@ -103,6 +103,17 @@ SBLiveView >> listeners [ ^ broadcaster listeners ] +{ #category : #building } +SBLiveView >> newPermutationButtonRowFor: aPermutation showing: aPreview [ + + ^ SBRow new + changeTableLayout; + cellGap: 8 * self scalingFactor; + addAllMorphsBack: { + SBButton newApplyPermutationFor: aPermutation. + self rebuildButtonIn: aPreview applying: aPermutation. } +] + { #category : #initialization } SBLiveView >> newRegisteredListenerFor: aPermutation [ @@ -117,6 +128,39 @@ SBLiveView >> newRegisteredListenerFor: aPermutation [ ] +{ #category : #initialization } +SBLiveView >> newRegisteredListenerFor: aPermutation replacing: anOldListener [ + + | listener | + listener := self evaluateSetUp. + broadcaster replaceListener: anOldListener with: listener. + + listener allMorphsDo: [:aSubMorph | + SBExploriants objectToPermutation at: aSubMorph put: aPermutation]. + +] + +{ #category : #building } +SBLiveView >> rebuildButton [ + + ^ SBButton new + icon: SBIcon iconRotateRight + label: 'Re-Build Setup' + do: [self visualize]; + cornerStyle: #squared +] + +{ #category : #building } +SBLiveView >> rebuildButtonIn: aContainer applying: aPermutation [ + + ^ SBButton new + icon: (SBIcon iconRotateRight size: 8.0 sbScaled) + label: 'Re-Build This' + do: [self newRegisteredListenerFor: aPermutation replacing: aContainer lastSubmorph]; + makeSmall; + cornerStyle: #squared +] + { #category : #accessing } SBLiveView >> setUpMorph [ @@ -136,9 +180,10 @@ SBLiveView >> visualize [ self clean. self buildBrodcaster. - self block addMorphBack: self updateButton. + self buildButtonRow. self block addMorphBack: gridContainer. self buildAllPossibleResults. broadcaster extent: self listeners last extent. + self updateContainerWidth. ] diff --git a/packages/Sandblocks-Babylonian/SBResultsView.class.st b/packages/Sandblocks-Babylonian/SBResultsView.class.st index d0b5d2cb..b43d72b4 100644 --- a/packages/Sandblocks-Babylonian/SBResultsView.class.st +++ b/packages/Sandblocks-Babylonian/SBResultsView.class.st @@ -33,7 +33,7 @@ SBResultsView >> updateButton [ ^ SBButton new icon: SBIcon iconRotateLeft - label: 'Re-Generate' + label: 'Re-Generate Multiverse' do: [self multiverse initialize]; cornerStyle: #squared ] From 165354eb8aa0daa9e65f185eec45ba5d3992fced Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Tue, 5 Dec 2023 01:08:18 +0100 Subject: [PATCH 4/8] handle errors in live view setup --- .../SBInputBroadcaster.class.st | 2 +- .../Sandblocks-Babylonian/SBLiveView.class.st | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st index 81b2fa48..0d50009b 100644 --- a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -19,7 +19,7 @@ SBInputBroadcaster >> absorbsInput: anEvent [ SBInputBroadcaster >> addListener: aMorph [ self listeners add: aMorph. - self mice add: CircleMorph newPin. + self mice add: CircleMorph newPin hide. "adding mice as our own morphs will cause rattling" self containers add: (Morph new diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 9fcf216e..edb6d3d2 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -2,7 +2,10 @@ Class { #name : #SBLiveView, #superclass : #SBGridResultsView, #instVars : [ - 'broadcaster' + 'broadcaster', + 'errorDecorator', + 'errorIcon', + 'reportedError' ], #category : #'Sandblocks-Babylonian' } @@ -79,7 +82,13 @@ SBLiveView >> clean [ { #category : #actions } SBLiveView >> evaluateSetUp [ - ^ self setUpMorph evaluate value + | return | + errorIcon ifNotNil: #delete. + return := [self setUpMorph evaluate value asMorph] + on: Error do: [:err | self reportError: err. err asMorph]. + + + ^ return ] { #category : #updating } @@ -161,6 +170,31 @@ SBLiveView >> rebuildButtonIn: aContainer applying: aPermutation [ cornerStyle: #squared ] +{ #category : #actions } +SBLiveView >> reportError: anError [ + + reportedError ifNotNil: [ + errorIcon ifNotNil: #delete. + errorIcon := nil. + reportedError := nil.]. + reportedError := anError. + + "reportedError := self multiverse sandblockEditor + reportError: anError + process: ((Process forContext: anError signalerContext copyStack priority: Processor activeProcess priority) + shouldResumeFromDebugger: false; + yourself) + source: self." + errorIcon ifNil: [ + self block firstSubmorph addMorphBack: (errorIcon := SBIcon iconFlash + large; + color: (Color r: 1 g: 0.6 b: 0.0))]. + + (SBSmallError findOpenContextFrom: anError signalerContext in: self multiverse sandblockEditor) + ifNotNil: [:b | b attachDecorator: (errorDecorator := SBErrorDecorator new message: anError asString; subtle: true; yourself)]. + +] + { #category : #accessing } SBLiveView >> setUpMorph [ From eae4e4e65eebc256b351b96b480a477d5d225977 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Wed, 6 Dec 2023 14:26:53 +0100 Subject: [PATCH 5/8] Simplifies error notification --- .../Sandblocks-Babylonian/SBLiveView.class.st | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index edb6d3d2..38c4c7a8 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -173,25 +173,19 @@ SBLiveView >> rebuildButtonIn: aContainer applying: aPermutation [ { #category : #actions } SBLiveView >> reportError: anError [ - reportedError ifNotNil: [ - errorIcon ifNotNil: #delete. - errorIcon := nil. - reportedError := nil.]. - reportedError := anError. + reportedError ifNotNil: [errorIcon delete. errorIcon := nil. reportedError := nil]. - "reportedError := self multiverse sandblockEditor + reportedError := self multiverse sandblockEditor reportError: anError process: ((Process forContext: anError signalerContext copyStack priority: Processor activeProcess priority) shouldResumeFromDebugger: false; yourself) - source: self." - errorIcon ifNil: [ - self block firstSubmorph addMorphBack: (errorIcon := SBIcon iconFlash - large; - color: (Color r: 1 g: 0.6 b: 0.0))]. + source: self. + + self block firstSubmorph addMorphBack: (errorIcon := SBIcon iconFlash). (SBSmallError findOpenContextFrom: anError signalerContext in: self multiverse sandblockEditor) - ifNotNil: [:b | b attachDecorator: (errorDecorator := SBErrorDecorator new message: anError asString; subtle: true; yourself)]. + ifNotNil: [:b | b attachDecorator: (errorDecorator := SBErrorDecorator new message: anError asString; subtle: false; yourself)]. ] From bc079ccd8d71ecc2a265ad500c1c4e4f8bef9ca8 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Thu, 7 Dec 2023 18:08:15 +0100 Subject: [PATCH 6/8] Mousecklicks work; rebuild listener when deleted & clicking rebuild --- .../SBInputBroadcaster.class.st | 97 ++++++++++++++++--- .../Sandblocks-Babylonian/SBLiveView.class.st | 11 ++- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st index 0d50009b..19a3598f 100644 --- a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -4,7 +4,8 @@ Class { #instVars : [ 'listeners', 'mice', - 'miceContainers' + 'miceContainers', + 'stateHands' ], #category : #'Sandblocks-Babylonian' } @@ -20,13 +21,15 @@ SBInputBroadcaster >> addListener: aMorph [ self listeners add: aMorph. self mice add: CircleMorph newPin hide. + self stateHands add: HandMorph new. "adding mice as our own morphs will cause rattling" self containers add: (Morph new color: Color transparent; - extent: aMorph extent). - self containers last addMorph: aMorph. - self containers last addMorph: mice last. + extent: aMorph extent; + setProperty: #sbListener toValue: aMorph; + yourself). + self containers last addAllMorphsBack: {mice last. aMorph.}. ^ self containers last @@ -38,23 +41,38 @@ SBInputBroadcaster >> containers [ ^ miceContainers ] +{ #category : #events } +SBInputBroadcaster >> eventProcessMouse: aMouse goingTo: aPosition in: aMorph [ + + aMouse position: aPosition. + (aMorph containsPoint: aPosition) + ifTrue: [aMouse show] + ifFalse: [aMouse hide] +] + { #category : #events } SBInputBroadcaster >> filterEvent: anEvent for: aMorph [ - self listeners withIndexDo: [:aListener :i | | targetPosition newEvent | - targetPosition := self translatedPositionOf: anEvent from: aMorph to: aListener. + self listeners withIndexDo: [:aListener :i | + | localTarget newEvent delta | + localTarget := self translatedPositionOf: anEvent from: aMorph to: aListener. + delta := localTarget - anEvent position. newEvent := anEvent copy. - anEvent isDropEvent - ifTrue: [newEvent translateTo: targetPosition] - ifFalse: [newEvent translateBy: targetPosition - anEvent position]. + newEvent translateBy: delta. + anEvent isDropEvent ifTrue: [newEvent translateTo: localTarget]. - aListener processEvent: newEvent. - (self mice at: i) position: targetPosition. + (self needsHandHandling: newEvent) + ifTrue: [ + self simulateGlobalHand: (self stateHands at: i) + for: newEvent + in: aListener + pos: self activeHand position + delta.] + ifFalse: [aListener processEvent: newEvent.]. - (aListener containsPoint: targetPosition) - ifTrue: [(self mice at: i) show] - ifFalse: [(self mice at: i) hide]]. + self eventProcessMouse: (self mice at: i) + goingTo: localTarget + in: aListener.]. ^ anEvent ] @@ -82,6 +100,7 @@ SBInputBroadcaster >> initialize [ listeners := OrderedCollection new. mice := OrderedCollection new. miceContainers := OrderedCollection new. + stateHands := OrderedCollection new. self addEventCaptureFilter: self; @@ -92,6 +111,22 @@ SBInputBroadcaster >> initialize [ ] +{ #category : #accessing } +SBInputBroadcaster >> insertListener: aListener into: aContainer [ + + | index | + index := self containers indexOf: aContainer ifAbsent: [^ self]. + + (self containers at: index) + addMorphBack: aListener; + extent: aListener extent; + setProperty: #sbListener toValue: aListener. + + aListener topLeft: (self containers at: index) topLeft. + self listeners at: index put: aListener. + +] + { #category : #accessing } SBInputBroadcaster >> listeners [ @@ -111,16 +146,45 @@ SBInputBroadcaster >> mouseEnter: anEvent [ anEvent hand newKeyboardFocus: self. ] +{ #category : #events } +SBInputBroadcaster >> needsHandHandling: anEvent [ + + "rechte maustaste im sbeditor ausschließen?" + ^ anEvent isMouse + and: [anEvent isMouseDown or: [anEvent isMouseUp]] +] + { #category : #accessing } SBInputBroadcaster >> replaceListener: oldListener with: newListener [ | index | index := self listeners indexOf: oldListener ifAbsent: [^ self]. - (self containers at: index) replaceSubmorph: (self listeners at: index) by: newListener. + (self containers at: index) + replaceSubmorph: (self listeners at: index) + by: newListener; + extent: newListener extent; + setProperty: #sbListener toValue: newListener. self listeners at: index put: newListener. - (self containers at: index) extent: newListener extent. +] + +{ #category : #events } +SBInputBroadcaster >> simulateGlobalHand: aHand for: anEvent in: aMorph pos: aPosition [ + + aMorph owner ifNotNil: [:theOwner | theOwner addMorphBack: aHand]. + + anEvent + position: aPosition; + setHand: aHand. + aHand handleEvent: anEvent. + aMorph owner ifNotNil: [:theOwner | theOwner removeMorph: aHand]. +] + +{ #category : #accessing } +SBInputBroadcaster >> stateHands [ + + ^ stateHands ] { #category : #events } @@ -129,6 +193,7 @@ SBInputBroadcaster >> translatedPositionOf: anEvent from: anOriginMorph to: aTar | localAbsPoint localRelPoint targetAbsPoint | localAbsPoint := anEvent position - anOriginMorph position. localRelPoint := localAbsPoint / anOriginMorph extent. + localRelPoint := (localRelPoint x clampLow: 0 high: 1)@(localRelPoint y clampLow: 0 high: 1). targetAbsPoint := (localRelPoint * aTargetMorph extent) + aTargetMorph position. ^ targetAbsPoint rounded diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 38c4c7a8..046b3733 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -138,11 +138,14 @@ SBLiveView >> newRegisteredListenerFor: aPermutation [ ] { #category : #initialization } -SBLiveView >> newRegisteredListenerFor: aPermutation replacing: anOldListener [ +SBLiveView >> newRegisteredListenerFor: aPermutation in: aContainer [ - | listener | + | listener oldListener | listener := self evaluateSetUp. - broadcaster replaceListener: anOldListener with: listener. + oldListener := aContainer valueOfProperty: #sbListener. + oldListener owner + ifNil: [broadcaster insertListener: listener into: aContainer] + ifNotNil: [broadcaster replaceListener: oldListener with: listener]. listener allMorphsDo: [:aSubMorph | SBExploriants objectToPermutation at: aSubMorph put: aPermutation]. @@ -165,7 +168,7 @@ SBLiveView >> rebuildButtonIn: aContainer applying: aPermutation [ ^ SBButton new icon: (SBIcon iconRotateRight size: 8.0 sbScaled) label: 'Re-Build This' - do: [self newRegisteredListenerFor: aPermutation replacing: aContainer lastSubmorph]; + do: [self newRegisteredListenerFor: aPermutation in: aContainer]; makeSmall; cornerStyle: #squared ] From 27014ac5445719cf9b562f4c726f3668e32be609 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Mon, 11 Dec 2023 17:30:37 +0100 Subject: [PATCH 7/8] Little quality of lives --- packages/Sandblocks-Babylonian/SBExploriants.class.st | 6 ++++++ .../Sandblocks-Babylonian/SBInputBroadcaster.class.st | 11 ++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBExploriants.class.st b/packages/Sandblocks-Babylonian/SBExploriants.class.st index 99f652ce..e27ceca4 100644 --- a/packages/Sandblocks-Babylonian/SBExploriants.class.st +++ b/packages/Sandblocks-Babylonian/SBExploriants.class.st @@ -58,6 +58,12 @@ SBExploriants >> binding: aString for: block class: aClass ifPresent: aBlock [ ^ nil ] +{ #category : #ui } +SBExploriants >> buildView [ + + self addMorphBack: (self activeBlock hResizing: #shrinkWrap) +] + { #category : #testing } SBExploriants >> cacheType: aClass for: aBlock [ ] diff --git a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st index 19a3598f..bc3f3c5a 100644 --- a/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st +++ b/packages/Sandblocks-Babylonian/SBInputBroadcaster.class.st @@ -57,11 +57,8 @@ SBInputBroadcaster >> filterEvent: anEvent for: aMorph [ | localTarget newEvent delta | localTarget := self translatedPositionOf: anEvent from: aMorph to: aListener. delta := localTarget - anEvent position. - newEvent := anEvent copy. - - newEvent translateBy: delta. - anEvent isDropEvent ifTrue: [newEvent translateTo: localTarget]. - + newEvent := anEvent copy translateBy: delta. + (self needsHandHandling: newEvent) ifTrue: [ self simulateGlobalHand: (self stateHands at: i) @@ -149,9 +146,9 @@ SBInputBroadcaster >> mouseEnter: anEvent [ { #category : #events } SBInputBroadcaster >> needsHandHandling: anEvent [ - "rechte maustaste im sbeditor ausschließen?" ^ anEvent isMouse and: [anEvent isMouseDown or: [anEvent isMouseUp]] + and: [(SBPreferences rightClickContextMenu and: [anEvent yellowButtonPressed]) not] ] { #category : #accessing } @@ -178,7 +175,7 @@ SBInputBroadcaster >> simulateGlobalHand: aHand for: anEvent in: aMorph pos: aPo setHand: aHand. aHand handleEvent: anEvent. - aMorph owner ifNotNil: [:theOwner | theOwner removeMorph: aHand]. + aHand delete. ] { #category : #accessing } From 5a05c6783e39b9d79b8db4405e672f697a4b9846 Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Wed, 13 Dec 2023 15:22:58 +0100 Subject: [PATCH 8/8] Adds a synchronisation to live view --- .../Sandblocks-Babylonian/SBLiveView.class.st | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 046b3733..2d6c31bf 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -120,7 +120,8 @@ SBLiveView >> newPermutationButtonRowFor: aPermutation showing: aPreview [ cellGap: 8 * self scalingFactor; addAllMorphsBack: { SBButton newApplyPermutationFor: aPermutation. - self rebuildButtonIn: aPreview applying: aPermutation. } + self rebuildButtonIn: aPreview applying: aPermutation. + self synchronizeButtonIn: aPreview} ] { #category : #initialization } @@ -138,16 +139,15 @@ SBLiveView >> newRegisteredListenerFor: aPermutation [ ] { #category : #initialization } -SBLiveView >> newRegisteredListenerFor: aPermutation in: aContainer [ +SBLiveView >> privateRegisterListener: aNewListener for: aPermutation in: aContainer [ - | listener oldListener | - listener := self evaluateSetUp. + | oldListener | oldListener := aContainer valueOfProperty: #sbListener. oldListener owner - ifNil: [broadcaster insertListener: listener into: aContainer] - ifNotNil: [broadcaster replaceListener: oldListener with: listener]. + ifNil: [broadcaster insertListener: aNewListener into: aContainer] + ifNotNil: [broadcaster replaceListener: oldListener with: aNewListener]. - listener allMorphsDo: [:aSubMorph | + aNewListener allMorphsDo: [:aSubMorph | SBExploriants objectToPermutation at: aSubMorph put: aPermutation]. ] @@ -168,11 +168,18 @@ SBLiveView >> rebuildButtonIn: aContainer applying: aPermutation [ ^ SBButton new icon: (SBIcon iconRotateRight size: 8.0 sbScaled) label: 'Re-Build This' - do: [self newRegisteredListenerFor: aPermutation in: aContainer]; + do: [self rebuildRegisteredListenerFor: aPermutation in: aContainer]; makeSmall; cornerStyle: #squared ] +{ #category : #initialization } +SBLiveView >> rebuildRegisteredListenerFor: aPermutation in: aContainer [ + + self privateRegisterListener: self evaluateSetUp for: aPermutation in: aContainer + +] + { #category : #actions } SBLiveView >> reportError: anError [ @@ -198,6 +205,29 @@ SBLiveView >> setUpMorph [ ^ self block firstSubmorph "setup row" lastSubmorph ] +{ #category : #building } +SBLiveView >> synchronizeButtonIn: aContainer [ + + ^ SBButton new + icon: (SBIcon iconRecycle size: 8.0 sbScaled) + label: 'Synchronize others' + do: [self synchronizePreviewsWith: aContainer]; + makeSmall; + cornerStyle: #squared +] + +{ #category : #building } +SBLiveView >> synchronizePreviewsWith: aContainer [ + + | replacingListener | + replacingListener := (aContainer valueOfProperty: #sbListener). + (broadcaster containers reject: [:someContainer | aContainer == someContainer]) + do: [:otherContainer | + self privateRegisterListener: replacingListener veryDeepCopy + for: (SBExploriants objectToPermutation at: (otherContainer valueOfProperty: #sbListener)) + in: otherContainer ] +] + { #category : #actions } SBLiveView >> toggleStepping [