diff --git a/packages/Sandblocks-Babylonian/Object.extension.st b/packages/Sandblocks-Babylonian/Object.extension.st index 45b2b7f7..20481b1c 100644 --- a/packages/Sandblocks-Babylonian/Object.extension.st +++ b/packages/Sandblocks-Babylonian/Object.extension.st @@ -1,5 +1,13 @@ Extension { #name : #Object } +{ #category : #'*Sandblocks-Babylonian' } +Object >> asSBWatchValue [ + + ^ SBWatchValue + value: self sbSnapshot + identityHash: self identityHash +] + { #category : #'*Sandblocks-Babylonian' } Object class >> exampleBlock [ diff --git a/packages/Sandblocks-Babylonian/SBCluster.class.st b/packages/Sandblocks-Babylonian/SBCluster.class.st index 7da66902..292f2d3b 100644 --- a/packages/Sandblocks-Babylonian/SBCluster.class.st +++ b/packages/Sandblocks-Babylonian/SBCluster.class.st @@ -109,6 +109,17 @@ SBCluster >> newTopRowFrom: aCollectionOfMorphs [ (self wrapInCell: aMorph owner flexVertically: true flexHorizontally: false) borderWidth: 0]) ] +{ #category : #visualisation } +SBCluster >> sortedWatchValuesFor: anExample givenWatches: aCollectionOfWatches [ + + | allValues | + allValues := SortedCollection sortBlock: [:a :b | a chronologicalPosition <= b chronologicalPosition]. + aCollectionOfWatches exampleToDisplay at: anExample + ifPresent: [:aSBWatchView | allValues addAll: aSBWatchView watchValues ] + ifAbsent: [{}]. + ^ allValues +] + { #category : #visualisation } SBCluster >> visualize [ @@ -117,9 +128,7 @@ SBCluster >> visualize [ matrix := self buildDisplayMatrix. (matrix rowCount < 2 or: [matrix columnCount < 2]) - ifTrue:[ - self addMorph: (SBOwnTextMorph new contents: 'No watches to display'). - ^ self]. + ifTrue:[self visualizeNothingToDisplay. ^ self]. self addAllMorphsBack: { self newTopRowFrom: (matrix atRow: 1) allButFirst. "ignore placeholder morph" @@ -133,6 +142,13 @@ SBCluster >> visualize [ collect: [:aMorph | self wrapInCell: aMorph])}} ] +{ #category : #visualisation } +SBCluster >> visualizeNothingToDisplay [ + + self addMorph: (SBOwnTextMorph new contents: 'No watches to display') + +] + { #category : #helper } SBCluster >> wrapInCell: aMorph [ @@ -151,12 +167,13 @@ SBCluster >> wrapInCell: aMorph flexVertically: aVBoolean flexHorizontally: aHBo (((aMorph fullBounds extent <= cell extent) or: [aVBoolean and: (aMorph fullBounds width <= cell width)]) - or: [aHBoolean and: (aMorph fullBounds height <= cell height)]) + or: [aHBoolean and: (aMorph fullBounds height <= cell height)] + or: [aVBoolean and: aHBoolean]) ifTrue: [cell addMorph: aMorph. ^ cell]. targetExtent := cell extent - (cell borderWidth@cell borderWidth). aVBoolean ifTrue: [targetExtent setX: targetExtent x setY: aMorph fullBounds height]. - aHBoolean ifTrue: [targetExtent setX: aMorph fullBounds width setY: targetExtent height]. + aHBoolean ifTrue: [targetExtent setX: aMorph fullBounds width setY: targetExtent y]. self flag: #todo. "Another way besides turning into an image to keep interactions.-jb" cell addMorph: (ImageMorph new diff --git a/packages/Sandblocks-Babylonian/SBExample.class.st b/packages/Sandblocks-Babylonian/SBExample.class.st index 1f0478d3..e8be6d13 100644 --- a/packages/Sandblocks-Babylonian/SBExample.class.st +++ b/packages/Sandblocks-Babylonian/SBExample.class.st @@ -12,7 +12,8 @@ Class { 'active', 'errorDecorator', 'returnValue', - 'reportedError' + 'reportedError', + 'traceSize' ], #category : #'Sandblocks-Babylonian' } @@ -86,13 +87,13 @@ SBExample class >> self: aBlock args: aCollection label: aString assert: anAsser ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> active [ ^ active ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBExample >> addAssertion [ @@ -100,32 +101,32 @@ SBExample >> addAssertion [ self addAssertion: self newNullBlock ] -{ #category : #'as yet unclassified' } +{ #category : #layout } SBExample >> addAssertion: aBlock [ self addMorphBack: (SBStringMorph new contents: 'assert:'). ^ self addMorphBack: aBlock ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> argumentsBlock [ ^ self submorphs sixth ] -{ #category : #'as yet unclassified' } +{ #category : #callbacks } SBExample >> artefactSaved: aMethod [ (aMethod isMethod and: [self active]) ifTrue: [self run] ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> assertionBlock [ ^ self submorphCount > 7 ifTrue: [self submorphs ninth] ifFalse: [nil] ] -{ #category : #'as yet unclassified' } +{ #category : #'event handling' } SBExample >> click: anEvent [ super click: anEvent. @@ -140,7 +141,7 @@ SBExample >> click: anEvent [ "currentProcess debug: error signalerContext title: error asString full: true."] ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> collectTypeInfo [ | arguments receiver selector | @@ -161,19 +162,19 @@ SBExample >> collectTypeInfo [ do: []]] ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> currentMethodMap [ ^ (self sandblockEditor methods select: #exists) collect: [:method | method compiledMethod sandblocksFastHash -> method] as: Dictionary ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> currentSelf [ ^ currentSelf ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBExample >> debug [ @@ -190,19 +191,19 @@ SBExample >> debug [ self sandblockEditor errors focusErrors ] -{ #category : #'as yet unclassified' } +{ #category : #'event handling' } SBExample >> doubleClick: anEvent [ self toggleRunning ] -{ #category : #'as yet unclassified' } +{ #category : #'colors and color policies' } SBExample >> drawnColor [ ^ self colorPolicy toolColorFor: self ] -{ #category : #'as yet unclassified' } +{ #category : #evaluate } SBExample >> evaluate [ | arguments | @@ -211,13 +212,13 @@ SBExample >> evaluate [ ^ currentSelf perform: self containingArtefact selector asSymbol withArguments: arguments ] -{ #category : #'as yet unclassified' } +{ #category : #evaluate } SBExample >> evaluateArguments [ ^ self argumentsBlock childSandblocks collect: [:block | Compiler evaluate: block sourceString] ] -{ #category : #'as yet unclassified' } +{ #category : #evaluate } SBExample >> evaluateIn: aBlock [ | arguments | @@ -226,13 +227,13 @@ SBExample >> evaluateIn: aBlock [ ^ aBlock value: [currentSelf perform: self containingArtefact selector asSymbol withArguments: arguments] ] -{ #category : #'as yet unclassified' } +{ #category : #evaluate } SBExample >> evaluateSelf [ ^ Compiler evaluate: self selfBlock veryDeepCopy sourceString ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> execute [ | newSelf arguments | @@ -241,7 +242,7 @@ SBExample >> execute [ ^ newSelf perform: self containingArtefact selector asSymbol withArguments: arguments ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> executeForBlock: aBlock ifFound: aClosure [ [ | newSelf arguments | @@ -259,13 +260,14 @@ SBExample >> executeForBlock: aBlock ifFound: aClosure [ do: [:err | SBWatch report: err for: 477523582] ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBExample >> initialize [ super initialize. active := false. processRunning := false. + traceSize := 0. self layoutInset: 8; @@ -277,7 +279,7 @@ SBExample >> initialize [ cellGap: 4 * self scalingFactor ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBExample >> intoWorld: aWorld [ super intoWorld: aWorld. @@ -285,7 +287,7 @@ SBExample >> intoWorld: aWorld [ "self startRunning" ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> isCurrent [ ^ currentProcess == Processor activeProcess @@ -303,13 +305,13 @@ SBExample >> isMorphExample [ ^ false ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> label [ ^ nameInput contents ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> lastError: anError [ lastError := anError. @@ -337,7 +339,7 @@ SBExample >> lastError: anError [ errorIndicator := nil] ] -{ #category : #'as yet unclassified' } +{ #category : #layout } SBExample >> layoutCommands [ ^ SBAlgebraCommand container @@ -346,32 +348,38 @@ SBExample >> layoutCommands [ SBAlgebraCommand group data: {a layoutCommands. SBAlgebraCommand gap. b layoutCommands. SBAlgebraCommand softLineOrGap}]), {self lastSubmorph layoutCommands} ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> nameBlock [ ^ self submorphs second ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBExample >> outOfWorld: aWorld [ currentProcess ifNotNil: #terminate. super outOfWorld: aWorld ] -{ #category : #'as yet unclassified' } +{ #category : #printing } SBExample >> printOn: aStream [ aStream nextPutAll: 'example' ] -{ #category : #'as yet unclassified' } +{ #category : #testing } SBExample >> providesExecutionEnvironment [ ^ true ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } +SBExample >> registerWatchValue [ + + traceSize := traceSize + 1 +] + +{ #category : #execution } SBExample >> run [ self runSetup. @@ -390,7 +398,7 @@ SBExample >> run [ currentProcess := nil. processRunning := false. Project current addDeferredUIMessage: [ - returnValue reportValues: {returned} sized: SBMorphResizer newThumbmail. + returnValue reportValues: {returned asSBWatchValue} sized: SBMorphResizer newThumbmail. returnValue updateDisplay. self sendFinishNotification] ] forkAt: Processor userBackgroundPriority. @@ -398,7 +406,7 @@ SBExample >> run [ ^ currentProcess ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBExample >> runOnlyThis [ @@ -406,7 +414,7 @@ SBExample >> runOnlyThis [ self startRunning ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> runSetup [ self containingArtefact valid ifFalse: [^ self]. @@ -415,14 +423,16 @@ SBExample >> runSetup [ errorDecorator ifNotNil: #detach. errorDecorator := nil. + traceSize := 0. returnValue clear. ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> runSynchUpdatingOnlyValuesOf: aCollectionOfSBWatches [ | returned | aCollectionOfSBWatches do: [:aWatch | aWatch resetOnlyValuesFor: self]. + traceSize := 0. SBExecutionEnvironment value: self. [returned := self evaluate] on: Error do: [:e | self scheduleLastError: e]. self scheduleLastError: nil. @@ -430,13 +440,13 @@ SBExample >> runSynchUpdatingOnlyValuesOf: aCollectionOfSBWatches [ ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> scheduleLastError: anError [ Project current addDeferredUIMessage: [self lastError: anError] ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBExample >> self: aBlock args: aCollectionBlock label: aString [ self @@ -454,34 +464,34 @@ SBExample >> self: aBlock args: aCollectionBlock label: aString [ updateIcon ] -{ #category : #'as yet unclassified' } +{ #category : #initialization } SBExample >> self: aBlock args: aCollectionBlock label: aString assert: anAssertBlock [ self self: aBlock args: aCollectionBlock label: aString. self addAssertion: anAssertBlock ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } SBExample >> selfBlock [ ^ self submorphs fourth ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> sendFinishNotification [ self sandblockEditor allMorphsDo: [:morph | (morph isSandblock and: [morph listensToExamples]) ifTrue: [morph exampleFinished: self]] ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> sendStartNotification [ self sandblockEditor allBlocksDo: [:morph | morph listensToExamples ifTrue: [morph exampleStarting: self]] ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBExample >> showReachability [ @@ -494,7 +504,7 @@ SBExample >> showReachability [ self sandblockEditor colorPolicy: policy ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> startRunning [ active ifTrue: [^ self]. @@ -504,13 +514,13 @@ SBExample >> startRunning [ self run ] -{ #category : #'as yet unclassified' } +{ #category : #'stepping and presenter' } SBExample >> stepTime [ ^ 2000 ] -{ #category : #'as yet unclassified' } +{ #category : #execution } SBExample >> stopRunning [ active ifFalse: [^ false]. @@ -524,7 +534,7 @@ SBExample >> stopRunning [ (morph isSandblock and: [morph listensToExamples]) ifTrue: [morph exampleStopped: self]] ] -{ #category : #'as yet unclassified' } +{ #category : #actions } SBExample >> toggleRunning [ @@ -533,14 +543,20 @@ SBExample >> toggleRunning [ ifTrue: [self stopRunning] ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } +SBExample >> traceSize [ + + ^ traceSize +] + +{ #category : #layout } SBExample >> updateIcon [ icon changeIconName: (self active ifTrue: [#iconPause] ifFalse: [#iconPlay]) ] -{ #category : #'as yet unclassified' } +{ #category : #copying } SBExample >> veryDeepCopyWith: aCopier [ | copy oldError | @@ -553,7 +569,7 @@ SBExample >> veryDeepCopyWith: aCopier [ ^ copy ] -{ #category : #'as yet unclassified' } +{ #category : #printing } SBExample >> writeSourceOn: aStream [ aStream nextPut: $(. diff --git a/packages/Sandblocks-Babylonian/SBExampleCluster.class.st b/packages/Sandblocks-Babylonian/SBExampleCluster.class.st index c84dbaca..bee77678 100644 --- a/packages/Sandblocks-Babylonian/SBExampleCluster.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleCluster.class.st @@ -71,7 +71,10 @@ SBExampleCluster >> extractedTopHeadingsFrom: aSBMultiverse [ ^ (aSBMultiverse universes collect: [:aUniverse | self newContainerMorph - listDirection: #leftToRight; + listDirection: #bottomToTop; + cellPositioning: #topLeft; + cellGap: 3; + cellInset: 3; addAllMorphsBack: { SBButton newApplyPermutationFor: aUniverse activePermutation. SBPermutationLabel newDisplaying: aUniverse activePermutation}]) diff --git a/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st b/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st index 7b5c20ab..4b8ba62b 100644 --- a/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleGridsView.class.st @@ -1,6 +1,6 @@ Class { #name : #SBExampleGridsView, - #superclass : #SBGridResultsView, + #superclass : #SBSwitchableResultsView, #category : #'Sandblocks-Babylonian' } @@ -21,8 +21,8 @@ SBExampleGridsView >> buildExampleFor: aNumber [ self containerRow listDirection: #topToBottom; addAllMorphsBack: { SBOwnTextMorph new contents: 'example: ', (self multiverse activeExamples at: aNumber) label. - SBExampleCluster - newForSize: morphResizer + self currentClusterClass + newForSize: self selectedResizer multiverse: self multiverse displaying: aNumber}. LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). @@ -30,6 +30,14 @@ SBExampleGridsView >> buildExampleFor: aNumber [ self updateContainerWidth. ] +{ #category : #accessing } +SBExampleGridsView >> currentClusterClass [ + + ^ isDisplayingTrace + ifTrue: [SBExampleTrace] + ifFalse: [SBExampleCluster] +] + { #category : #updating } SBExampleGridsView >> gridSize [ diff --git a/packages/Sandblocks-Babylonian/SBExampleTrace.class.st b/packages/Sandblocks-Babylonian/SBExampleTrace.class.st new file mode 100644 index 00000000..222aa956 --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBExampleTrace.class.st @@ -0,0 +1,50 @@ +Class { + #name : #SBExampleTrace, + #superclass : #SBExampleCluster, + #category : #'Sandblocks-Babylonian' +} + +{ #category : #visualisation } +SBExampleTrace >> buildDisplayMatrix [ + + | matrix displayedExample | + matrix := Matrix + rows: 2 + columns: self multiverse universes size. + displayedExample := self multiverse watches first examples at: self displayedIndex. + + matrix atRow: 1 put: (self extractedTopHeadingsFrom: self multiverse). + self multiverse universes withIndexDo: [:aUniverse :column | + matrix + at: 2 + at: column + put: (SBTrace + newForSize: self morphResizer + example: displayedExample + watches: aUniverse watches)]. + + ^ matrix +] + +{ #category : #visualisation } +SBExampleTrace >> visualize [ + + | matrix | + self submorphs copy do: #delete. + self multiverse watches ifEmpty: [self visualizeNothingToDisplay. ^ self]. + + matrix := self buildDisplayMatrix. + self addAllMorphsBack: {self newContainerMorph + listDirection: #leftToRight; + cellPositioning: #topLeft; + cellInset: 0; + addAllMorphsBack:( + (matrix atRow: 2) withIndexCollect: [:aTrace :i | + self wrapInCell: (aTrace addMorphFront:( + self newContainerMorph + wrapCentering: #center; + hResizing: #spaceFill; + addMorphBack: (matrix at: 1 at: i))) + flexVertically: true + flexHorizontally: true ])} +] diff --git a/packages/Sandblocks-Babylonian/SBExampleValueDisplay.class.st b/packages/Sandblocks-Babylonian/SBExampleValueDisplay.class.st index e192da9e..e3508187 100644 --- a/packages/Sandblocks-Babylonian/SBExampleValueDisplay.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleValueDisplay.class.st @@ -131,9 +131,9 @@ SBExampleValueDisplay >> newChangeVizButton [ ] { #category : #'event handling' } -SBExampleValueDisplay >> reportValues: aCollectionOfObjects name: aString sized: aSBMorphResizer [ +SBExampleValueDisplay >> reportValues: aCollectionOfWatchValues name: aString sized: aSBMorphResizer [ - display reportValues: aCollectionOfObjects sized: aSBMorphResizer. + display reportValues: aCollectionOfWatchValues sized: aSBMorphResizer. label contents: aString. label visible: aString notEmpty. hadValue := true diff --git a/packages/Sandblocks-Babylonian/SBExampleWatch.class.st b/packages/Sandblocks-Babylonian/SBExampleWatch.class.st index 4127f8b7..3b364996 100644 --- a/packages/Sandblocks-Babylonian/SBExampleWatch.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleWatch.class.st @@ -77,14 +77,13 @@ SBExampleWatch class >> report: aValue for: aSymbol [ { #category : #'event handling' } SBExampleWatch class >> report: aValue for: aSymbol modifying: aBlock [ - | reg watchers example | + | watchers example | example := SBExecutionEnvironment value ifNil: [^ aValue]. - reg := self registry. - watchers := reg select: [:watcher | watcher notNil + watchers := self registry select: [:watcher | watcher notNil and: [watcher identifier = aSymbol] and: [watcher isActive]]. - watchers do: [:watcher | watcher reportValue: aValue for: example]. + watchers do: [:watcher | watcher reportValue: aValue asSBWatchValue for: example]. ^ aValue ] @@ -252,9 +251,9 @@ SBExampleWatch >> exampleToDisplay: anExampleToDisplayDict [ ] { #category : #accessing } -SBExampleWatch >> exampleToValues: anExampleToCollectionOfObjectsDict [ +SBExampleWatch >> exampleToValues: anExampleToCollectionOfWatchValuesDict [ - exampleToValues := anExampleToCollectionOfObjectsDict + exampleToValues := anExampleToCollectionOfWatchValuesDict ] { #category : #accessing } @@ -389,7 +388,9 @@ SBExampleWatch >> modifiedValuesFor: anExample [ ^ exampleToValues at: anExample ifPresent: [:aCollection | aCollection - collect: [:anObject | self modifyExpression evaluateWithArguments: {anObject}]] + collect: [:aWatchValue | |modifiedResult | + modifiedResult := self modifyExpression evaluateWithArguments: {aWatchValue watchedValue}. + aWatchValue shallowCopy watchedValue: modifiedResult.]] ifAbsent: [{}] ] @@ -445,19 +446,24 @@ SBExampleWatch >> replaceWithWatchedExpression [ ] { #category : #actions } -SBExampleWatch >> reportValue: anObject for: anExample [ +SBExampleWatch >> reportValue: aWatchValue for: anExample [ exampleToValues at: anExample - ifPresent: [:values | values add: anObject] + ifPresent: [:values | + anExample registerWatchValue. + values add: (aWatchValue + tracePosition: anExample traceSize; + occuringWatchId: self identifier + yourself)] ] { #category : #actions } -SBExampleWatch >> reportValues: aCollectionOfObjects for: anExample [ +SBExampleWatch >> reportValues: aCollectionOfWatchValues for: anExample [ exampleToValues at: anExample - ifPresent: [:values | values addAll: aCollectionOfObjects] + ifPresent: [:values | values addAll: aCollectionOfWatchValues] ] { #category : #'event handling' } diff --git a/packages/Sandblocks-Babylonian/SBGridResultsView.class.st b/packages/Sandblocks-Babylonian/SBGridResultsView.class.st index 13bb11d2..1c288d1b 100644 --- a/packages/Sandblocks-Babylonian/SBGridResultsView.class.st +++ b/packages/Sandblocks-Babylonian/SBGridResultsView.class.st @@ -50,7 +50,7 @@ SBGridResultsView >> newGridContainer [ SBGridResultsView >> updateContainerWidth [ gridContainer width: - self gridSize safeSquareRoot ceiling + (self gridSize safeSquareRoot ceiling + 1) * (gridContainer lastSubmorph fullBounds width + (2 * gridContainer cellInset) + (2 * gridContainer cellGap) diff --git a/packages/Sandblocks-Babylonian/SBLiveView.class.st b/packages/Sandblocks-Babylonian/SBLiveView.class.st index 6c772eca..d599ca09 100644 --- a/packages/Sandblocks-Babylonian/SBLiveView.class.st +++ b/packages/Sandblocks-Babylonian/SBLiveView.class.st @@ -66,7 +66,7 @@ SBLiveView >> buildSetUpRow [ { #category : #building } SBLiveView >> buttons [ - ^ {self updateButton. self rebuildButton. self resolveButton} + ^ super buttons, {self resolveButton} ] { #category : #actions } diff --git a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st index 61ec95bf..232118d8 100644 --- a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st +++ b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st @@ -1,6 +1,6 @@ Class { #name : #SBPermutationGridsView, - #superclass : #SBGridResultsView, + #superclass : #SBSwitchableResultsView, #category : #'Sandblocks-Babylonian' } @@ -19,14 +19,22 @@ SBPermutationGridsView >> buildPermutationFor: aSBUniverse [ addAllMorphsBack: { SBPermutationLabel newDisplaying: aSBUniverse activePermutation. SBButton newApplyPermutationFor: aSBUniverse activePermutation. - (SBPermutationCluster - newForSize: morphResizer + (self currentClusterClass + newForSize: self selectedResizer havingWatches: aSBUniverse watches)}. LineMorph from: 0@0 to: 0@50 color: Color black width: 2}). self updateContainerWidth. ] +{ #category : #building } +SBPermutationGridsView >> currentClusterClass [ + + ^ isDisplayingTrace + ifTrue: [SBPermutationTraces] + ifFalse: [SBPermutationCluster] +] + { #category : #updating } SBPermutationGridsView >> gridSize [ diff --git a/packages/Sandblocks-Babylonian/SBPermutationTraces.class.st b/packages/Sandblocks-Babylonian/SBPermutationTraces.class.st new file mode 100644 index 00000000..ee3bf67d --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBPermutationTraces.class.st @@ -0,0 +1,53 @@ +Class { + #name : #SBPermutationTraces, + #superclass : #SBPermutationCluster, + #category : #'Sandblocks-Babylonian' +} + +{ #category : #converting } +SBPermutationTraces >> buildDisplayMatrix [ + + | matrix | + self hasNothingToDisplay ifTrue: [^ Matrix new]. + matrix := Matrix + rows: 2 + columns: self watches first examples size. + + matrix atRow: 1 put: (self extractedTopHeadingsFrom: self watches). + matrix atRow: 2 put: (self watches first examples collect: [:anExample | + SBTrace + newForSize: self morphResizer + example: anExample + watches: self watches]). + + ^ matrix +] + +{ #category : #converting } +SBPermutationTraces >> hasNothingToDisplay [ + + ^ self watches isEmpty or: [self watches first examples isEmpty] +] + +{ #category : #converting } +SBPermutationTraces >> visualize [ + + | matrix | + self submorphs copy do: #delete. + self hasNothingToDisplay ifTrue: [self visualizeNothingToDisplay. ^ self]. + + matrix := self buildDisplayMatrix. + self addAllMorphsBack: {self newContainerMorph + listDirection: #leftToRight; + cellPositioning: #topLeft; + cellInset: 0; + addAllMorphsBack:( + (matrix atRow: 2) withIndexCollect: [:aTrace :i | + self wrapInCell: (aTrace addMorphFront:( + self newContainerMorph + wrapCentering: #center; + hResizing: #spaceFill; + addMorphBack: (matrix at: 1 at: i))) + flexVertically: true + flexHorizontally: true ])} +] diff --git a/packages/Sandblocks-Babylonian/SBResultsView.class.st b/packages/Sandblocks-Babylonian/SBResultsView.class.st index a1238e79..c1f33bfd 100644 --- a/packages/Sandblocks-Babylonian/SBResultsView.class.st +++ b/packages/Sandblocks-Babylonian/SBResultsView.class.st @@ -1,9 +1,6 @@ Class { #name : #SBResultsView, #superclass : #SBExploriantsView, - #instVars : [ - 'morphResizer' - ], #category : #'Sandblocks-Babylonian' } @@ -13,14 +10,6 @@ SBResultsView >> buildAllPossibleResults [ self subclassResponsibility ] -{ #category : #initialization } -SBResultsView >> initialize [ - - super initialize. - - morphResizer := SBMorphResizer newThumbmail. -] - { #category : #actions } SBResultsView >> visualize [ diff --git a/packages/Sandblocks-Babylonian/SBSwitchableResultsView.class.st b/packages/Sandblocks-Babylonian/SBSwitchableResultsView.class.st new file mode 100644 index 00000000..569bf136 --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBSwitchableResultsView.class.st @@ -0,0 +1,97 @@ +" +Offer to switch between trace based and a grid based view +" +Class { + #name : #SBSwitchableResultsView, + #superclass : #SBGridResultsView, + #instVars : [ + 'isDisplayingTrace', + 'dimensionOptions' + ], + #category : #'Sandblocks-Babylonian' +} + +{ #category : #actions } +SBSwitchableResultsView >> applyResizer [ + + self visualize. + self multiverse sandblockEditor markSaved: SBExploriants uniqueInstance +] + +{ #category : #building } +SBSwitchableResultsView >> buildDimensionOptions [ + + | options | + options := SBMorphResizer standardOptions. + + ^ SBComboBox new + prefix: 'Morph Dimensions: '; + labels: (options collect: #label); + values: options; + object: options third; + when: #selectionChanged send: #applyResizer to: self +] + +{ #category : #accessing } +SBSwitchableResultsView >> buttons [ + + ^ super buttons, {self toggleViewButton} +] + +{ #category : #accessing } +SBSwitchableResultsView >> currentClusterClass [ + + ^ self subclassResponsibility +] + +{ #category : #accessing } +SBSwitchableResultsView >> initialize [ + + super initialize. + + isDisplayingTrace := false. + dimensionOptions := self buildDimensionOptions +] + +{ #category : #accessing } +SBSwitchableResultsView >> selectedResizer [ + + ^ dimensionOptions object +] + +{ #category : #building } +SBSwitchableResultsView >> toggleIcon [ + + ^ isDisplayingTrace + ifTrue: [SBIcon iconToggleOn] + ifFalse: [SBIcon iconToggleOff] +] + +{ #category : #accessing } +SBSwitchableResultsView >> toggleView [ + + isDisplayingTrace := isDisplayingTrace not. + + self visualize +] + +{ #category : #building } +SBSwitchableResultsView >> toggleViewButton [ + + ^ SBButton new + icon: self toggleIcon + label: 'Group By Watches <> In Execution Order' + do: [self toggleView]; + cornerStyle: #squared +] + +{ #category : #actions } +SBSwitchableResultsView >> visualize [ + + self clean. + + self block addMorph: dimensionOptions. + self buildButtonRow. + + self buildAllPossibleResults +] diff --git a/packages/Sandblocks-Babylonian/SBTrace.class.st b/packages/Sandblocks-Babylonian/SBTrace.class.st new file mode 100644 index 00000000..a835d348 --- /dev/null +++ b/packages/Sandblocks-Babylonian/SBTrace.class.st @@ -0,0 +1,74 @@ +Class { + #name : #SBTrace, + #superclass : #Morph, + #category : #'Sandblocks-Babylonian' +} + +{ #category : #'initialize-release' } +SBTrace class >> newForSize: aMorphResizer example: anExample watches: aCollectionOfWatches [ + + ^ self new visualizeFor: anExample withWatches: aCollectionOfWatches resizer: aMorphResizer + +] + +{ #category : #visualization } +SBTrace >> addSectionFor: aWatchValue resizer: aMorphResizer [ + + self addMorphBack: ( + self placeHolderMorph + addMorphBack: (TextMorph new contents: (aWatchValue expressionString asText + addAttribute: (TextColor color: Color gray); + yourself)); + addMorphBack: ([aWatchValue morphResizer: aMorphResizer. + aWatchValue asValueMorph] value); + yourself) + +] + +{ #category : #initialization } +SBTrace >> initialize [ + + super initialize. + + self changeTableLayout; + color: Color white; + listDirection: #topToBottom; + cellPositioning: #topRight; + layoutInset: 0@3; + cellInset: 0@2; + hResizing: #shrinkWrap; + vResizing: #shrinkWrap +] + +{ #category : #visualization } +SBTrace >> placeHolderMorph [ + + ^ Morph new + changeTableLayout; + color: Color white; + layoutInset: 3@0; + cellInset: 2@0; + listDirection: #leftToRight; + cellPositioning: #bottomRight; + hResizing: #shrinkWrap; + vResizing: #shrinkWrap +] + +{ #category : #visualization } +SBTrace >> sortedWatchValuesFor: anExample givenWatches: aCollectionOfWatches [ + + | allValues | + allValues := SortedCollection sortBlock: [:a :b | a tracePosition <= b tracePosition]. + aCollectionOfWatches do: [:aWatch | + aWatch exampleToDisplay at: anExample + ifPresent: [:aSBWatchView | allValues addAll: aSBWatchView display watchValues ] + ifAbsent: [{}]]. + ^ allValues +] + +{ #category : #visualization } +SBTrace >> visualizeFor: anExample withWatches: aCollectionOfWatches resizer: aMorphResizer [ + + (self sortedWatchValuesFor: anExample givenWatches: aCollectionOfWatches) + do: [:aWatchValue | self addSectionFor: aWatchValue resizer: aMorphResizer] +] diff --git a/packages/Sandblocks-Babylonian/SBWatchValue.class.st b/packages/Sandblocks-Babylonian/SBWatchValue.class.st index 635516f3..22af2819 100644 --- a/packages/Sandblocks-Babylonian/SBWatchValue.class.st +++ b/packages/Sandblocks-Babylonian/SBWatchValue.class.st @@ -4,7 +4,9 @@ Class { #instVars : [ 'watchedValue', 'watchedValueIdentityHash', - 'morphResizer' + 'morphResizer', + 'tracePosition', + 'occuringWatchId' ], #category : #'Sandblocks-Babylonian' } @@ -51,6 +53,12 @@ SBWatchValue >> explore [ self watchedValue explore ] +{ #category : #accessing } +SBWatchValue >> expressionString [ + + ^ self occuringWatch expression sourceString +] + { #category : #'initialize-release' } SBWatchValue >> initialize [ @@ -59,6 +67,7 @@ SBWatchValue >> initialize [ watchedValue := 0. watchedValueIdentityHash := 0 identityHash. morphResizer := SBMorphResizer newIdentity. + tracePosition := 0. ] { #category : #accessing } @@ -74,6 +83,19 @@ SBWatchValue >> morphResizer: aSBMorphResizer [ ] +{ #category : #accessing } +SBWatchValue >> occuringWatch [ + + ^ SBExampleWatch registry detect: [:aWatch | + aWatch notNil and: [aWatch identifier = occuringWatchId]] +] + +{ #category : #accessing } +SBWatchValue >> occuringWatchId: aNumber [ + + occuringWatchId := aNumber +] + { #category : #printing } SBWatchValue >> printOn: aStream [ @@ -82,6 +104,18 @@ SBWatchValue >> printOn: aStream [ self watchedValue printOn: aStream. ] +{ #category : #accessing } +SBWatchValue >> tracePosition [ + + ^ tracePosition +] + +{ #category : #accessing } +SBWatchValue >> tracePosition: aNumber [ + + tracePosition := aNumber +] + { #category : #accessing } SBWatchValue >> watchedValue [ diff --git a/packages/Sandblocks-Core/SBWatch.class.st b/packages/Sandblocks-Core/SBWatch.class.st index 177de001..cadbf1b6 100644 --- a/packages/Sandblocks-Core/SBWatch.class.st +++ b/packages/Sandblocks-Core/SBWatch.class.st @@ -33,7 +33,7 @@ SBWatch class >> report: aValue for: identifier [ | reg watchers | reg := self registry. watchers := reg select: [:watcher | watcher notNil and: [watcher identifier = identifier]]. - watchers do: [:watcher | watcher reportValue: aValue]. + watchers do: [:watcher | watcher reportValue: aValue asSBWatchValue]. ^ aValue ] @@ -219,10 +219,10 @@ SBWatch >> printOn: aStream [ ] { #category : #'as yet unclassified' } -SBWatch >> reportValue: anObject [ +SBWatch >> reportValue: aWatchValue [ - display reportValue: anObject. - self logOutput ifTrue: [Transcript showln: anObject] + display reportValue: aWatchValue. + self logOutput ifTrue: [Transcript showln: aWatchValue watchedValue] ] { #category : #actions } diff --git a/packages/Sandblocks-Watch/SBExampleWatchView.class.st b/packages/Sandblocks-Watch/SBExampleWatchView.class.st index 0405649f..c0f2279c 100644 --- a/packages/Sandblocks-Watch/SBExampleWatchView.class.st +++ b/packages/Sandblocks-Watch/SBExampleWatchView.class.st @@ -29,9 +29,9 @@ SBExampleWatchView >> initialize [ ] { #category : #accessing } -SBExampleWatchView >> reportValues: aCollectionOfObjects sized: aMorphResizer [ +SBExampleWatchView >> reportValues: aCollectionOfWatchValues sized: aMorphResizer [ - aCollectionOfObjects do: [:anObject | self addValue: anObject sized: aMorphResizer]. + aCollectionOfWatchValues do: [:anObject | self addValue: anObject sized: aMorphResizer]. updateScheduled := true ] diff --git a/packages/Sandblocks-Watch/SBWatchView.class.st b/packages/Sandblocks-Watch/SBWatchView.class.st index d86e8fae..47fe9b0b 100644 --- a/packages/Sandblocks-Watch/SBWatchView.class.st +++ b/packages/Sandblocks-Watch/SBWatchView.class.st @@ -25,13 +25,10 @@ SBWatchView class >> saving: anInteger [ ] { #category : #accessing } -SBWatchView >> addValue: anObject sized: aSBMorphResizer [ +SBWatchView >> addValue: aWatchValue sized: aSBMorphResizer [ (watchValues size >= numSavedValues and: [numSavedValues > 0]) ifTrue: [watchValues removeFirst]. - ^ watchValues addLast: (SBWatchValue - value: anObject sbSnapshot - identityHash: anObject identityHash - sized: aSBMorphResizer) + ^ watchValues addLast: (aWatchValue morphResizer: aSBMorphResizer) ] { #category : #'insert/delete' } @@ -269,17 +266,17 @@ SBWatchView >> printOn: aStream [ ] { #category : #actions } -SBWatchView >> reportValue: anObject [ +SBWatchView >> reportValue: aWatchValue [ - self reportValues: {anObject} sized: SBMorphResizer newIdentity + self reportValues: {aWatchValue} sized: SBMorphResizer newIdentity ] { #category : #actions } -SBWatchView >> reportValues: aCollectionOfObjects sized: aMorphResizer [ +SBWatchView >> reportValues: aCollectionOfWatchValues sized: aMorphResizer [ self fallbackResizer: aMorphResizer. - aCollectionOfObjects do: [:anObject | self addValue: anObject sized: aMorphResizer]. - self count: self count contents + aCollectionOfObjects size. + aCollectionOfWatchValues do: [:anObject | self addValue: anObject sized: aMorphResizer]. + self count: self count contents + aCollectionOfWatchValues size. updateScheduled ifFalse: [ updateScheduled := true.