From 509e4850c334bb50bd2d8d066a12b89ebb79bd9b Mon Sep 17 00:00:00 2001 From: Joana Bergsiek Date: Fri, 19 Jan 2024 21:37:32 +0100 Subject: [PATCH] instead of going by updating submorphs and copying them, only watch internal values are updated so no flickering and invisible watches possible --- .../Sandblocks-Babylonian/SBCluster.class.st | 6 +- .../Sandblocks-Babylonian/SBExample.class.st | 6 +- .../SBExampleCluster.class.st | 2 +- .../SBExampleWatch.class.st | 68 ++++++++++++++++++- .../SBExploriants.class.st | 4 +- .../SBInactiveExampleWatch.class.st | 10 --- .../SBMultiverse.class.st | 46 ++++++------- .../SBPermutationGridsView.class.st | 2 +- .../Sandblocks-Utils/SBPermutation.class.st | 26 +++++++ .../SBExampleWatchView.class.st | 3 +- .../Sandblocks-Watch/SBWatchView.class.st | 38 +++++++++-- 11 files changed, 156 insertions(+), 55 deletions(-) diff --git a/packages/Sandblocks-Babylonian/SBCluster.class.st b/packages/Sandblocks-Babylonian/SBCluster.class.st index 72d3b8ed..7da66902 100644 --- a/packages/Sandblocks-Babylonian/SBCluster.class.st +++ b/packages/Sandblocks-Babylonian/SBCluster.class.st @@ -11,9 +11,9 @@ Class { SBCluster >> compressedMorphsForDisplay: aSBWatchView [ | displayedMorphs | - displayedMorphs := aSBWatchView displayedMorphs collect: [:aMorph | - aMorph watchValue morphResizer: self morphResizer. - aMorph watchValue asValueMorph]. + displayedMorphs := aSBWatchView watchValues collect: [:aWatchValue | + aWatchValue morphResizer: self morphResizer. + aWatchValue asValueMorph]. ^ (displayedMorphs size = 1) ifTrue: [displayedMorphs first] ifFalse: [self newCellMorph diff --git a/packages/Sandblocks-Babylonian/SBExample.class.st b/packages/Sandblocks-Babylonian/SBExample.class.st index f01bfd9f..1f0478d3 100644 --- a/packages/Sandblocks-Babylonian/SBExample.class.st +++ b/packages/Sandblocks-Babylonian/SBExample.class.st @@ -419,15 +419,15 @@ SBExample >> runSetup [ ] { #category : #'as yet unclassified' } -SBExample >> runSynchronouslyIgnoreReturn [ +SBExample >> runSynchUpdatingOnlyValuesOf: aCollectionOfSBWatches [ | returned | - self sendStartNotification. + aCollectionOfSBWatches do: [:aWatch | aWatch resetOnlyValuesFor: self]. SBExecutionEnvironment value: self. [returned := self evaluate] on: Error do: [:e | self scheduleLastError: e]. self scheduleLastError: nil. + aCollectionOfSBWatches do: [:aWatch | aWatch exampleFinished: self] - self sendFinishNotification. ] { #category : #'as yet unclassified' } diff --git a/packages/Sandblocks-Babylonian/SBExampleCluster.class.st b/packages/Sandblocks-Babylonian/SBExampleCluster.class.st index a1684a24..04af1ec1 100644 --- a/packages/Sandblocks-Babylonian/SBExampleCluster.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleCluster.class.st @@ -72,7 +72,7 @@ SBExampleCluster >> extractedTopHeadingsFrom: aSBMultiverse [ ^ (aSBMultiverse universes collect: [:aUniverse | self newContainerMorph addAllMorphsBack: { - SBStringMorph new contents: aUniverse activePermutation asString. + TextMorph new contents: aUniverse activePermutation asStylizedText. SBButton newApplyPermutationFor: aUniverse activePermutation}]) ] diff --git a/packages/Sandblocks-Babylonian/SBExampleWatch.class.st b/packages/Sandblocks-Babylonian/SBExampleWatch.class.st index b09aa73b..4127f8b7 100644 --- a/packages/Sandblocks-Babylonian/SBExampleWatch.class.st +++ b/packages/Sandblocks-Babylonian/SBExampleWatch.class.st @@ -124,7 +124,21 @@ SBExampleWatch >> applyResizerOnValues [ { #category : #copying } SBExampleWatch >> asInactiveCopy [ - ^ SBInactiveExampleWatch newFromWatch: self + "Ignore the existing morphs in ourselves and recreate the graphics from the data" + | copy | + copy := SBInactiveExampleWatch new + newIdentifier; + expression: (SBTextBubble new contents: self cleanedExpression sourceString); + modifyExpression: self modifyExpression veryDeepCopy; + dimensionOptions: self dimensionOptions veryDeepCopy. + + exampleToValues keys do: [:anExample | copy exampleStarting: anExample; + reportValues: (self valuesForExample: anExample) for: anExample; + exampleFinished: anExample ]. + + ^ copy + saveObjectsActivePermutations; + yourself ] { #category : #accessing } @@ -162,6 +176,19 @@ SBExampleWatch >> deleteCommandFor: aBlock [ ^ nil ] +{ #category : #accessing } +SBExampleWatch >> dimensionOptions [ + + ^ dimensionOptions +] + +{ #category : #accessing } +SBExampleWatch >> dimensionOptions: aSBComboBox [ + + "private" + dimensionOptions := aSBComboBox +] + { #category : #'event handling' } SBExampleWatch >> doubleClick: anEvent [ @@ -276,8 +303,8 @@ SBExampleWatch >> initialize [ super initialize. options := SBMorphResizer standardOptions. - exampleToDisplay := Dictionary new. - exampleToValues := Dictionary new. + exampleToDisplay := IdentityDictionary new. + exampleToValues := IdentityDictionary new. watchedExpression := SBStMessageSend new. dimensionOptions := SBComboBox new prefix: 'Morph Dimensions: '; @@ -425,6 +452,33 @@ SBExampleWatch >> reportValue: anObject for: anExample [ ifPresent: [:values | values add: anObject] ] +{ #category : #actions } +SBExampleWatch >> reportValues: aCollectionOfObjects for: anExample [ + + exampleToValues + at: anExample + ifPresent: [:values | values addAll: aCollectionOfObjects] +] + +{ #category : #'event handling' } +SBExampleWatch >> resetOnlyValuesFor: anExample [ + + "Private" + exampleToValues at: anExample put: OrderedCollection new. + (exampleToDisplay at: anExample) display resetOnlyValues + + + +] + +{ #category : #testing } +SBExampleWatch >> resumeGraphicalUpdates [ + + exampleToDisplay values do: [:anExampleValueDisplay | + anExampleValueDisplay display shouldUpdateDisplay: true] + +] + { #category : #accessing } SBExampleWatch >> selectedMorphResizer [ @@ -437,6 +491,14 @@ SBExampleWatch >> setWatchedExpressionUneditable [ watchedExpression selectable: false ] +{ #category : #testing } +SBExampleWatch >> stopGraphicalUpdates [ + + exampleToDisplay values do: [:anExampleValueDisplay | + anExampleValueDisplay display shouldUpdateDisplay: false] + +] + { #category : #accessing } SBExampleWatch >> valuesForExample: anExample [ diff --git a/packages/Sandblocks-Babylonian/SBExploriants.class.st b/packages/Sandblocks-Babylonian/SBExploriants.class.st index 7057a2da..e66b9452 100644 --- a/packages/Sandblocks-Babylonian/SBExploriants.class.st +++ b/packages/Sandblocks-Babylonian/SBExploriants.class.st @@ -149,7 +149,7 @@ SBExploriants >> tryToUpdateInBackgroundAfterChangeIn: aMethodBlock [ "aMethodBlock compiledMethod getSource asString allRangesOfRegexMatches: '(?<=activeIndex\: )\d*'." "multiverse variants select: [:aVariant | aVariant containingArtefact = aMethodBlock]""]." - updateProcessRunning ifTrue: [ + "updateProcessRunning ifTrue: [ updateProcess ifNotNil: #terminate. updateProcessRunning := false.]. @@ -163,7 +163,7 @@ SBExploriants >> tryToUpdateInBackgroundAfterChangeIn: aMethodBlock [ onTimeout: [ newMultiverse cleanUp. updateProcess := nil. updateProcessRunning := false.]. updateProcess := nil. updateProcessRunning := false. - ] forkAt: Processor userBackgroundPriority. + ] forkAt: Processor userBackgroundPriority." diff --git a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st index 2ef15b3d..e769442b 100644 --- a/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st +++ b/packages/Sandblocks-Babylonian/SBInactiveExampleWatch.class.st @@ -7,16 +7,6 @@ Class { #category : #'Sandblocks-Babylonian' } -{ #category : #'initialize-release' } -SBInactiveExampleWatch class >> newFromWatch: anActiveWatch [ - - ^ (anActiveWatch veryDeepCopy) - primitiveChangeClassTo: self basicNew; - expression: (SBTextBubble new contents: anActiveWatch cleanedExpression sourceString); - saveObjectsActivePermutations; - yourself -] - { #category : #'event handling' } SBInactiveExampleWatch class >> registerWatch: aWatch [ diff --git a/packages/Sandblocks-Babylonian/SBMultiverse.class.st b/packages/Sandblocks-Babylonian/SBMultiverse.class.st index e040b995..dfc83b18 100644 --- a/packages/Sandblocks-Babylonian/SBMultiverse.class.st +++ b/packages/Sandblocks-Babylonian/SBMultiverse.class.st @@ -109,17 +109,10 @@ SBMultiverse >> asyncKaboom [ { #category : #actions } SBMultiverse >> cleanUp [ - self resetWatchesToOriginalPermutationRunning: activeExamples. + watches do: #resumeGraphicalUpdates. (watches select: [:anOpenWatch | anOpenWatch containingArtefact isNil]) copy do: #delete ] -{ #category : #actions } -SBMultiverse >> cleanUpRemovingCopies: outOfWorldWatches [ - - self resetWatchesToOriginalPermutationRunning: activeExamples. - outOfWorldWatches copy do: #delete -] - { #category : #collecting } SBMultiverse >> findExistingOrConvertToBlocks: aCollectionOfCompiledMethods [ @@ -140,14 +133,15 @@ SBMultiverse >> gatherElements [ allMethodBlocksContainingWatches := self allCompiledMethodsContainingExampleWatches collect: #asSandblock. + universes := OrderedCollection new. + activeExamples := self allActiveExamples. + variants := (allMethodBlocksContainingVariants collect: #containedVariants) flatten. variants := variants select: #isActive. watches := (self allMethodBlocksContainingWatches collect: #containedExampleWatches) flatten. - - universes := OrderedCollection new. - activeExamples := self allActiveExamples. - + watches do: [:aWatch | activeExamples do: [:anExample | aWatch exampleStarting: anExample]. + aWatch hide]. ] @@ -162,14 +156,22 @@ SBMultiverse >> initialize [ { #category : #actions } SBMultiverse >> kaboom [ - | outOfWorldWatches | + | outOfWorldWatches permutations | "Only open watches display values when examples are run. We want to show them too" (outOfWorldWatches := watches reject: #isInEditor) do: [:aWatch | self sandblockEditor openMorph: aWatch]. + permutations := (SBPermutation allPermutationsOf: variants). + watches do: #stopGraphicalUpdates. - (SBPermutation allPermutationsOf: variants) do: [:aPermutation | + "Running the active one last" + (permutations sorted: [:a :b | a activeScore <= b activeScore ] ) do: [:aPermutation | self runPermutation: aPermutation copyingWatches: watches ]. - self resetWatchesToOriginalPermutationRunning: activeExamples. - outOfWorldWatches copy do: #delete. + + "but stay consistent of the permutation sequences for alignment in clusters" + "sorting this is cheaper than running a permutation twice just to reset to prior state" + universes := universes sorted: [:a :b | + (permutations indexOf: a activePermutation) <= (permutations indexOf: b activePermutation)]. + self cleanUp. + self triggerEvent: #updated. ] @@ -187,13 +189,6 @@ SBMultiverse >> reset [ self triggerEvent: #updated. ] -{ #category : #'action-helper' } -SBMultiverse >> resetWatchesToOriginalPermutationRunning: activeExamples [ - - SBActiveVariantPermutation value: nil. - activeExamples do: #runSynchronouslyIgnoreReturn -] - { #category : #actions } SBMultiverse >> resolve [ @@ -214,10 +209,9 @@ SBMultiverse >> resolve [ { #category : #actions } SBMultiverse >> runPermutation: aPermutation copyingWatches: allWatches [ - SBActiveVariantPermutation value: aPermutation. - activeExamples do: #runSynchronouslyIgnoreReturn. - universes add: (SBUniverse newActive: aPermutation watches: (watches collect: #asInactiveCopy)) + activeExamples do: [:anExample | anExample runSynchUpdatingOnlyValuesOf: allWatches]. + universes add: (SBUniverse newActive: aPermutation watches: (allWatches collect: #asInactiveCopy)) ] diff --git a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st index 3eeeb208..ca939d70 100644 --- a/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st +++ b/packages/Sandblocks-Babylonian/SBPermutationGridsView.class.st @@ -17,7 +17,7 @@ SBPermutationGridsView >> buildPermutationFor: aSBUniverse [ addAllMorphsBack: { self containerRow listDirection: #topToBottom; addAllMorphsBack: { - SBOwnTextMorph new contents: aSBUniverse activePermutation asString. + TextMorph new contents: aSBUniverse activePermutation asStylizedText. SBButton newApplyPermutationFor: aSBUniverse activePermutation. (SBPermutationCluster newForSize: morphResizer diff --git a/packages/Sandblocks-Utils/SBPermutation.class.st b/packages/Sandblocks-Utils/SBPermutation.class.st index bc74624f..3ee44c2c 100644 --- a/packages/Sandblocks-Utils/SBPermutation.class.st +++ b/packages/Sandblocks-Utils/SBPermutation.class.st @@ -40,6 +40,14 @@ SBPermutation class >> newCombinedOf: onePermutation and: anotherPermutation [ ] +{ #category : #accessing } +SBPermutation >> activeScore [ + + ^ (self referencedVariants collect: [:aVariant | + aVariant activeIndex = (self at: aVariant id) ifTrue: [1] ifFalse: [0]]) + inject: 0 into: [:a :c | a + c] +] + { #category : #actions } SBPermutation >> apply [ @@ -60,6 +68,24 @@ SBPermutation >> asString [ ] +{ #category : #converting } +SBPermutation >> asStylizedText [ + + | text | + text := Text fromString: self asString. + ^ self isActive + ifTrue: [text allBold] + ifFalse: [text] + + +] + +{ #category : #accessing } +SBPermutation >> isActive [ + + ^ self activeScore = self referencedVariants size +] + { #category : #accessing } SBPermutation >> referencedVariants [ diff --git a/packages/Sandblocks-Watch/SBExampleWatchView.class.st b/packages/Sandblocks-Watch/SBExampleWatchView.class.st index 7c21d8a5..0405649f 100644 --- a/packages/Sandblocks-Watch/SBExampleWatchView.class.st +++ b/packages/Sandblocks-Watch/SBExampleWatchView.class.st @@ -40,6 +40,5 @@ SBExampleWatchView >> reportValues: aCollectionOfObjects sized: aMorphResizer [ SBExampleWatchView >> updateDisplay [ super updateDisplay. - - self count: (watchValues size) asString + self count: (watchValues size) asString. ] diff --git a/packages/Sandblocks-Watch/SBWatchView.class.st b/packages/Sandblocks-Watch/SBWatchView.class.st index 47c630f8..d86e8fae 100644 --- a/packages/Sandblocks-Watch/SBWatchView.class.st +++ b/packages/Sandblocks-Watch/SBWatchView.class.st @@ -11,7 +11,8 @@ Class { 'count', 'clear', 'fallbackResizer', - 'updateScheduled' + 'updateScheduled', + 'shouldUpdateDisplay' ], #category : #'Sandblocks-Watch' } @@ -135,7 +136,8 @@ SBWatchView >> displayWatchValues [ | valuesMorph | valuesMorph := self watchValuesContainer. valuesMorph addAllMorphsBack: (watchValues collect: #asValueMorph). - + "Will sometimes not update size otherwise when rushing through runs" + valuesMorph doLayoutSafely. self displayOnScrollPane: valuesMorph. ] @@ -197,6 +199,7 @@ SBWatchView >> initialize [ numSavedValues := 1. watchValues := LinkedList new. fallbackResizer := SBMorphResizer newSmall. + shouldUpdateDisplay := true. self layoutPolicy: SBAlgebraLayout new; @@ -283,14 +286,22 @@ SBWatchView >> reportValues: aCollectionOfObjects sized: aMorphResizer [ Project current addDeferredUIMessage: [self updateDisplay]] ] +{ #category : #actions } +SBWatchView >> resetOnlyValues [ + "Private" + + count contents: '0'. + watchValues := LinkedList new. +] + { #category : #actions } SBWatchView >> resizeThrough: aMorphResizer [ "Clearing everything here as Morphs get distorted when resized multiple times." | valuesMorph | valuesMorph := self watchValuesContainer. - valuesMorph addAllMorphsBack: (self displayedMorphs - collect: #sbSnapshot + valuesMorph addAllMorphsBack: (self displayedMorphs + collect: #sbSnapshot thenDo: [:aMorph | aMorphResizer applyOn: aMorph]). self displayOnScrollPane: valuesMorph. @@ -315,6 +326,18 @@ SBWatchView >> scroller [ ^ self scrollPane scroller ] +{ #category : #accessing } +SBWatchView >> shouldUpdateDisplay [ + + ^ shouldUpdateDisplay +] + +{ #category : #accessing } +SBWatchView >> shouldUpdateDisplay: aBoolean [ + + shouldUpdateDisplay := aBoolean +] + { #category : #'object interface' } SBWatchView >> storeAsExample [ @@ -330,6 +353,7 @@ SBWatchView >> storeAsExample [ SBWatchView >> updateDisplay [ updateScheduled ifFalse: [^ self]. + shouldUpdateDisplay ifFalse: [^ self]. updateScheduled := false. @@ -368,6 +392,12 @@ SBWatchView >> watchObjectInterface [ ^ SBInterfaces topLevel, {[:o | o isEditor not]} ] +{ #category : #accessing } +SBWatchView >> watchValues [ + + ^ watchValues +] + { #category : #accessing } SBWatchView >> watchValues: aLinkedList [ "Private"