From 4170e0214943a853e7a95cf0f42d4a67483f16f4 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Mon, 22 Jan 2024 13:32:29 +0100 Subject: [PATCH 01/16] working on job lists --- .../SpFixedProgressBarState.extension.st | 2 +- .../SpMorphicProgressBarAdapter.class.st | 42 ++++++++---- src/Spec2-Core/SpJob.class.st | 17 ++--- src/Spec2-Core/SpJobListPresenter.class.st | 64 +++++++++++++++++-- src/Spec2-Core/SpJobPresenter.class.st | 32 +++++++--- .../SpProgressBarPresenter.class.st | 2 +- src/Spec2-Dialogs/SpApplication.extension.st | 21 +++++- src/Spec2-Dialogs/SpInformUserDialog.class.st | 12 ++-- 8 files changed, 149 insertions(+), 43 deletions(-) diff --git a/src/Spec2-Adapters-Morphic/SpFixedProgressBarState.extension.st b/src/Spec2-Adapters-Morphic/SpFixedProgressBarState.extension.st index a3c05b2b..bae86e39 100644 --- a/src/Spec2-Adapters-Morphic/SpFixedProgressBarState.extension.st +++ b/src/Spec2-Adapters-Morphic/SpFixedProgressBarState.extension.st @@ -9,5 +9,5 @@ SpFixedProgressBarState >> customizeMorphicBar: aProgressBarMorph [ { #category : '*Spec2-Adapters-Morphic' } SpFixedProgressBarState >> customizeMorphicLabel: aLabelMorph [ - aLabelMorph contents: (self value * 100) asInteger asString, '%' + aLabelMorph contents: ((self value * 100) asInteger min: 100) asString, '%' ] diff --git a/src/Spec2-Adapters-Morphic/SpMorphicProgressBarAdapter.class.st b/src/Spec2-Adapters-Morphic/SpMorphicProgressBarAdapter.class.st index 310a6bbe..f6a12f83 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicProgressBarAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicProgressBarAdapter.class.st @@ -49,16 +49,11 @@ SpMorphicProgressBarAdapter >> buildWidget [ vResizing: #spaceFill; yourself. - progressLabel := LabelMorph new. - - progressBar := (self progressBarState progressBarMorph from: 0 to: 1) - "changeProportionalLayout;" - hResizing: #spaceFill; - vResizing: #rigid; - height: 5; + progressLabel := LabelMorph new + contents: ''; yourself. - self progressBarState customizeMorphicBar: progressBar. + progressBar := self newProgressBar. panel addMorphBack: progressLabel; @@ -86,6 +81,17 @@ SpMorphicProgressBarAdapter >> labelStyle [ otherStyles: self presenterStyles ] +{ #category : 'factory' } +SpMorphicProgressBarAdapter >> newProgressBar [ + + ^ (self progressBarState progressBarMorph from: 0 to: 1) + hResizing: #spaceFill; + vResizing: #rigid; + height: 5; + in: [ :this | self progressBarState customizeMorphicBar: this ]; + yourself +] + { #category : 'accessing' } SpMorphicProgressBarAdapter >> progressBarState [ @@ -95,14 +101,28 @@ SpMorphicProgressBarAdapter >> progressBarState [ { #category : 'accessing' } SpMorphicProgressBarAdapter >> refreshRateInMs: nbMilliSeconds [ "The progress bar will only be updated if the time between 2 refresh is > nbMilliSeconds" - refreshRateInMs := nbMilliSeconds. + refreshRateInMs := nbMilliSeconds ] { #category : 'updating' } -SpMorphicProgressBarAdapter >> updateState [ +SpMorphicProgressBarAdapter >> updateProgressBar [ + | newProgressBar | + + newProgressBar := self newProgressBar. + self widget + replaceSubmorph: progressBar + by: newProgressBar. + progressBar := newProgressBar +] +{ #category : 'updating' } +SpMorphicProgressBarAdapter >> updateState [ | isTimeForRefresh | - self progressBarState + + (self progressBarState progressBarMorph = progressBar class) + ifFalse: [ self updateProgressBar ]. + + self progressBarState customizeMorphicLabel: progressLabel; customizeMorphicBar: progressBar. diff --git a/src/Spec2-Core/SpJob.class.st b/src/Spec2-Core/SpJob.class.st index 60d61fb3..db15787b 100644 --- a/src/Spec2-Core/SpJob.class.st +++ b/src/Spec2-Core/SpJob.class.st @@ -12,7 +12,7 @@ job := self newBlock: [ :job | progress: (0.1 * each); title: 'Youpi ', each printString. (Delay forMilliseconds: 100) wait. - ] ] + ] ]. job run. ``` @@ -78,7 +78,7 @@ SpJob >> addChild: aJob [ aJob parent: self ] -{ #category : 'accessing' } +{ #category : 'announcing' } SpJob >> announce: anAnnouncementClass [ | announcement | @@ -93,7 +93,7 @@ SpJob >> announceChange [ self announce: JobChange ] -{ #category : 'accessing' } +{ #category : 'announcing' } SpJob >> announcer [ ^ announcer ifNil: [ announcer := Announcer new ] @@ -201,8 +201,8 @@ SpJob >> lookup: lookupBlock ifNone: noneBlock [ (lookupBlock value: self) ifTrue: [ ^ self ]. ^ parent - ifNil: noneBlock - ifNotNil: [ parent lookup: lookupBlock ifNone: noneBlock ] + ifNotNil: [ parent lookup: lookupBlock ifNone: noneBlock ] + ifNil: noneBlock ] { #category : 'accessing' } @@ -291,10 +291,11 @@ SpJob >> removeChild: aJob [ { #category : 'running' } SpJob >> run [ - [ + ^ [ self prepareForRunning. - ^ block cull: self ] - ensure: [ self cleanupAfterRunning ] + block cull: self ] + ensure: [ + self cleanupAfterRunning ] ] { #category : 'accessing' } diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index eeb1e5e2..d5a6f2b0 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -39,6 +39,14 @@ SpJobListPresenter class >> example [ SpJobListPresenter >> addJobPresenter: aJob [ | presenter | + ('adding: {1}, {2}, max={3}, value={4}' format: { + aJob class. + aJob title. + aJob max. + aJob currentValue }) crTrace. + + aJob title ifEmpty: [ aJob title: 'Processing...' ]. + presenter := self instantiate: SpJobPresenter on: aJob. presenter refreshRateInMs: refreshRateInMs. self layout add: presenter expand: false. @@ -47,7 +55,15 @@ SpJobListPresenter >> addJobPresenter: aJob [ ifTrue: [ self open ]. self withWindowDo: [ :window | - window resize: 500@(layout children size * self jobPresenterHeight) ] + window resize: 500@(layout children size * self jobPresenterHeight) ] +] + +{ #category : 'private' } +SpJobListPresenter >> findJob: aJob [ + + ^ self layout children + detect: [ :each | each model = aJob ] + ifNone: [ nil ] ] { #category : 'initialization' } @@ -66,31 +82,71 @@ SpJobListPresenter >> initializeWindow: aWindowPresenter [ centered ] +{ #category : 'private - events' } +SpJobListPresenter >> jobChanged: ann [ + + (self findJob: ann job) + ifNotNil: [ :aPresenter | aPresenter updatePresenter ] +] + +{ #category : 'private - events' } +SpJobListPresenter >> jobEnd: ann [ + + self removeJobPresenter: ann job +] + { #category : 'private' } SpJobListPresenter >> jobPresenterHeight [ ^ 70 ] +{ #category : 'private - events' } +SpJobListPresenter >> jobStart: ann [ + + "Skip if already there" + (self findJob: ann job) ifNotNil: [ ^ self ]. + self addJobPresenter: ann job. + ann job run +] + +{ #category : 'private' } +SpJobListPresenter >> newJob [ + + ^ SpJob new +] + { #category : 'api' } SpJobListPresenter >> pushJob: aJob [ aJob whenStartDo: [ :ann | self addJobPresenter: ann job ]. aJob whenEndDo: [ :ann | self removeJobPresenter: ann job ]. - aJob run + aJob run +] + +{ #category : 'api' } +SpJobListPresenter >> pushJobWith: aBlock [ + | job | + + job := self newJob. + job block: aBlock. + self pushJob: job ] { #category : 'api' } SpJobListPresenter >> refreshRateInMs: anInteger [ - refreshRateInMs := anInteger. + + refreshRateInMs := anInteger ] { #category : 'private' } SpJobListPresenter >> removeJobPresenter: aJob [ | presenter | - presenter := self layout children detect: [ :each | each model = aJob ]. + presenter := self findJob: aJob. + presenter ifNil: [ ^ self ]. + self layout remove: presenter. self layout children diff --git a/src/Spec2-Core/SpJobPresenter.class.st b/src/Spec2-Core/SpJobPresenter.class.st index 7a043e9f..3de32e5f 100644 --- a/src/Spec2-Core/SpJobPresenter.class.st +++ b/src/Spec2-Core/SpJobPresenter.class.st @@ -45,15 +45,24 @@ SpJobPresenter class >> example [ run ] +{ #category : 'layout' } +SpJobPresenter >> defaultLayout [ + + ^ SpBoxLayout newTopToBottom + borderWidth: 10; + spacing: 5; + add: progressLabel expand: false; + add: progressBar expand: false; + yourself +] + { #category : 'initialization' } SpJobPresenter >> initializePresenters [ - self layout: (SpBoxLayout newTopToBottom - borderWidth: 10; - spacing: 5; - add: (progressLabel := self newLabel) expand: false; - add: (progressBar := self newProgressBar) expand: false; - yourself) + progressLabel := self newLabel label: ''. + progressBar := self newProgressBar + indeterminate; + yourself ] { #category : 'initialization' } @@ -115,12 +124,15 @@ SpJobPresenter >> setModelBeforeInitialization: aModel [ { #category : 'initialization' } SpJobPresenter >> updatePresenter [ - | currentJob | - currentJob := model ifNil: [ ^ SpJob empty ]. - + model ifNil: [ ^ self ]. + progressLabel label: model title. - progressBar fixedAt: model progress + model progress > 0 + ifTrue: [ progressBar fixedAt: model progress ] + ifFalse: [ progressBar indeterminate ]. + + progressBar withAdapterDo: [ :anAdapter | anAdapter updateState ] ] { #category : 'private' } diff --git a/src/Spec2-Core/SpProgressBarPresenter.class.st b/src/Spec2-Core/SpProgressBarPresenter.class.st index a90da698..75470076 100644 --- a/src/Spec2-Core/SpProgressBarPresenter.class.st +++ b/src/Spec2-Core/SpProgressBarPresenter.class.st @@ -30,7 +30,7 @@ SpProgressBarPresenter class >> documentFactoryMethodSelector [ SpProgressBarPresenter >> fixedAt: aNumber [ "Declare that the progress bar will be fixed at a certain value. The value should be the completed ratio between 0 and 1." - + self state: (SpFixedProgressBarState value: aNumber) ] diff --git a/src/Spec2-Dialogs/SpApplication.extension.st b/src/Spec2-Dialogs/SpApplication.extension.st index 63ee3852..088cf3a2 100644 --- a/src/Spec2-Dialogs/SpApplication.extension.st +++ b/src/Spec2-Dialogs/SpApplication.extension.st @@ -29,10 +29,25 @@ SpApplication >> inform: aString [ { #category : '*Spec2-Dialogs' } SpApplication >> informUser: aString during: aBlock [ "Displays an inform user dialog." + | result | - ^ self newInformUser - title: aString; - informUserDuring: aBlock + result := nil. + self jobList + pushJob: (SpJob + newTitle: aString + block: [ :job | + job min: 0; max: 100. + result := aBlock cull: job ]). + + ^ result +] + +{ #category : '*Spec2-Dialogs' } +SpApplication >> jobList [ + + ^ self + propertyAt: #jobList + ifAbsentPut: [ self newJobList ] ] { #category : '*Spec2-Dialogs' } diff --git a/src/Spec2-Dialogs/SpInformUserDialog.class.st b/src/Spec2-Dialogs/SpInformUserDialog.class.st index a57cce3f..92fbd1e5 100644 --- a/src/Spec2-Dialogs/SpInformUserDialog.class.st +++ b/src/Spec2-Dialogs/SpInformUserDialog.class.st @@ -51,11 +51,13 @@ SpInformUserDialog >> afterOpenAction [ openAction ifNil: [ ^ self ]. [ - [ - returnValue := openAction value. - self accept ] on: Error fork: [ :e | - self cancel. - e pass ] ] fork + [ + returnValue := openAction value. + self accept ] + on: Error fork: [ :e | + self cancel. + e pass ] + ] fork ] { #category : 'simple dialog helpers' } From ffce4ffe702fa7542420ffdd4431b3379265c451 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Wed, 24 Jan 2024 15:17:45 +0100 Subject: [PATCH 02/16] ensure clean up of box morph llast morph was remaining alive because first and last cells were keeping a reference to target morph, which is not good when you are removing a presenter and keeping alive its parent to future use) --- .../SpAbstractMorphicAdapter.class.st | 1 - .../SpMorphicBoxAdapter.class.st | 1 + .../SpMorphicBoxLayoutCalculator.class.st | 13 +++++++++++++ ...SpMorphicBoxLayoutCalculatorLeftToRight.class.st | 5 ++--- ...SpMorphicBoxLayoutCalculatorTopToBottom.class.st | 7 +++---- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Spec2-Adapters-Morphic/SpAbstractMorphicAdapter.class.st b/src/Spec2-Adapters-Morphic/SpAbstractMorphicAdapter.class.st index 2556c907..aa40b32f 100644 --- a/src/Spec2-Adapters-Morphic/SpAbstractMorphicAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpAbstractMorphicAdapter.class.st @@ -661,7 +661,6 @@ SpAbstractMorphicAdapter >> type: aString [ SpAbstractMorphicAdapter >> unsubscribe [ super unsubscribe. - self presenter hasAnnouncer ifFalse: [ ^ self ]. self presenter announcer unsubscribe: self widget; diff --git a/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st b/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st index 5e389ca2..2bd8db7e 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st @@ -250,6 +250,7 @@ SpMorphicBoxAdapter >> remove: aPresenter [ aPresenter adapter ifNotNil: [ :adapter | | morph | + adapter unsubscribe. morph := adapter widget. startPanel removeMorph: morph. endPanel removeMorph: morph. diff --git a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculator.class.st b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculator.class.st index ce33a4e2..89b67f02 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculator.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculator.class.st @@ -37,6 +37,19 @@ SpMorphicBoxLayoutCalculator class >> newProperties: anObject [ { #category : 'calculating' } SpMorphicBoxLayoutCalculator >> calculateFor: aMorph in: newBounds [ + [ self doCalculateFor: aMorph in: newBounds ] + ensure: [ self cleanUp ] +] + +{ #category : 'private' } +SpMorphicBoxLayoutCalculator >> cleanUp [ + + firstCell := lastCell := nil +] + +{ #category : 'calculating' } +SpMorphicBoxLayoutCalculator >> doCalculateFor: aMorph in: newBounds [ + self subclassResponsibility ] diff --git a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorLeftToRight.class.st b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorLeftToRight.class.st index d23921d7..0bf998d0 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorLeftToRight.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorLeftToRight.class.st @@ -53,7 +53,7 @@ SpMorphicBoxLayoutCalculatorLeftToRight >> calculateCellFor: aMorph [ ] { #category : 'calculating' } -SpMorphicBoxLayoutCalculatorLeftToRight >> calculateFor: aMorph in: newBounds [ +SpMorphicBoxLayoutCalculatorLeftToRight >> doCalculateFor: aMorph in: newBounds [ "An optimized left-to-right list layout" | inset extent posX posY centering extraPerCell cell amount last submorphs | @@ -126,6 +126,5 @@ SpMorphicBoxLayoutCalculatorLeftToRight >> calculateFor: aMorph in: newBounds [ width := width + amount ]. cell target layoutInBounds: (posX @ posY extent: width @ height). posX := posX + width + inset. - cell := cell nextCell ]. - + cell := cell nextCell ] ] diff --git a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorTopToBottom.class.st b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorTopToBottom.class.st index 3e525296..d512b900 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorTopToBottom.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicBoxLayoutCalculatorTopToBottom.class.st @@ -44,7 +44,7 @@ SpMorphicBoxLayoutCalculatorTopToBottom >> calculateCellFor: aMorph [ ] { #category : 'calculating' } -SpMorphicBoxLayoutCalculatorTopToBottom >> calculateFor: aMorph in: newBounds [ +SpMorphicBoxLayoutCalculatorTopToBottom >> doCalculateFor: aMorph in: newBounds [ "An optimized top-to-bottom list layout" | inset extent posX posY centering extraPerCell cell amount last submorphs | @@ -107,7 +107,7 @@ SpMorphicBoxLayoutCalculatorTopToBottom >> calculateFor: aMorph in: newBounds [ number := 0. extra := last := 0. cell := firstCell. - [cell == nil] whileFalse:[ + [ cell == nil ] whileFalse:[ number := number + 1. height := cell cellSize. (extraPerCell > 0 and:[cell vSpaceFill]) ifTrue:[ @@ -117,6 +117,5 @@ SpMorphicBoxLayoutCalculatorTopToBottom >> calculateFor: aMorph in: newBounds [ ]. cell target layoutInBounds: (posX @ posY extent: width @ height). posY := posY + height + inset. - cell := cell nextCell. - ]. + cell := cell nextCell ] ] From 9449ee219c32f3702afb3583b48027d9e1d937d0 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Wed, 24 Jan 2024 16:55:02 +0100 Subject: [PATCH 03/16] an attempt to run fix the pharo joblist --- src/Spec2-Core/SpApplication.class.st | 6 +++ src/Spec2-Core/SpJobListPresenter.class.st | 45 ++++++++++--------- src/Spec2-Core/SpJobPresenter.class.st | 12 ++--- .../SpProgressBarPresenter.class.st | 6 +++ src/Spec2-Dialogs/SpApplication.extension.st | 7 +-- src/Spec2-Dialogs/SpProgressDialog.class.st | 1 + src/Spec2-Layout/SpExecutableLayout.class.st | 2 +- .../SpJobListPresenterTest.class.st | 23 ++++++---- 8 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/Spec2-Core/SpApplication.class.st b/src/Spec2-Core/SpApplication.class.st index 12e58206..96fe2e5a 100644 --- a/src/Spec2-Core/SpApplication.class.st +++ b/src/Spec2-Core/SpApplication.class.st @@ -331,6 +331,12 @@ SpApplication >> registerWindow: aWindow [ self windows add: aWindow ] +{ #category : 'accessing - properties' } +SpApplication >> removeProperty: aName [ + + ^ self properties removeKey: aName ifAbsent: [ ] +] + { #category : 'accessing' } SpApplication >> reset [ diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index d5a6f2b0..83d5ebd8 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -14,20 +14,19 @@ Class { { #category : 'examples' } SpJobListPresenter class >> example [ - | jobList | - - jobList := self new. + [ 1 to: 5 do: [ :index | [ - jobList pushJob: (SpJob - newTitle: 'Job ', index asString + Job new + title: 'Job ', index asString; block: [ :job | job min: 1; max: 10. 1 to: 10 do: [ :i | job title: ('Test {1}/10' format: {i}). job value: i. - 250 milliSeconds wait ] ]). + 250 milliSeconds wait ] ]; + run. ] fork. 200 milliSeconds wait ] ] fork. @@ -39,12 +38,6 @@ SpJobListPresenter class >> example [ SpJobListPresenter >> addJobPresenter: aJob [ | presenter | - ('adding: {1}, {2}, max={3}, value={4}' format: { - aJob class. - aJob title. - aJob max. - aJob currentValue }) crTrace. - aJob title ifEmpty: [ aJob title: 'Processing...' ]. presenter := self instantiate: SpJobPresenter on: aJob. @@ -58,6 +51,14 @@ SpJobListPresenter >> addJobPresenter: aJob [ window resize: 500@(layout children size * self jobPresenterHeight) ] ] +{ #category : 'private' } +SpJobListPresenter >> ensureOpen [ + + self withWindowDo: [ :aWindow | + aWindow isOpen + ifFalse: [ self open ] ] +] + { #category : 'private' } SpJobListPresenter >> findJob: aJob [ @@ -82,15 +83,22 @@ SpJobListPresenter >> initializeWindow: aWindowPresenter [ centered ] +{ #category : 'testing' } +SpJobListPresenter >> isEmpty [ + + ^ self layout children isEmpty +] + { #category : 'private - events' } SpJobListPresenter >> jobChanged: ann [ - (self findJob: ann job) - ifNotNil: [ :aPresenter | aPresenter updatePresenter ] + (self findJob: ann job) ifNotNil: [ :aPresenter | + aPresenter model title crTrace. + aPresenter updatePresenter ] ] { #category : 'private - events' } -SpJobListPresenter >> jobEnd: ann [ +SpJobListPresenter >> jobEnd: ann [ self removeJobPresenter: ann job ] @@ -107,21 +115,18 @@ SpJobListPresenter >> jobStart: ann [ "Skip if already there" (self findJob: ann job) ifNotNil: [ ^ self ]. self addJobPresenter: ann job. - ann job run + self ensureOpen ] { #category : 'private' } SpJobListPresenter >> newJob [ - ^ SpJob new + ^ Job new ] { #category : 'api' } SpJobListPresenter >> pushJob: aJob [ - aJob whenStartDo: [ :ann | self addJobPresenter: ann job ]. - aJob whenEndDo: [ :ann | self removeJobPresenter: ann job ]. - aJob run ] diff --git a/src/Spec2-Core/SpJobPresenter.class.st b/src/Spec2-Core/SpJobPresenter.class.st index 3de32e5f..62dcab43 100644 --- a/src/Spec2-Core/SpJobPresenter.class.st +++ b/src/Spec2-Core/SpJobPresenter.class.st @@ -32,7 +32,7 @@ Class { SpJobPresenter class >> example [ | job | - job := SpJob newBlock: [ :aJob | + job := Job block: [ :aJob | aJob title: 'Test'. aJob min: 1; max: 10. 1 to: 10 do: [ :i | @@ -61,7 +61,7 @@ SpJobPresenter >> initializePresenters [ progressLabel := self newLabel label: ''. progressBar := self newProgressBar - indeterminate; + "indeterminate;" yourself ] @@ -128,19 +128,19 @@ SpJobPresenter >> updatePresenter [ model ifNil: [ ^ self ]. progressLabel label: model title. + "progressBar fixedAt: model progress." model progress > 0 ifTrue: [ progressBar fixedAt: model progress ] ifFalse: [ progressBar indeterminate ]. - - progressBar withAdapterDo: [ :anAdapter | anAdapter updateState ] + progressBar refresh ] { #category : 'private' } SpJobPresenter >> updateSubscriptions [ - model announcer weak + "model announcer weak when: JobStart send: #jobStart: to: self; when: JobChange send: #jobChanged: to: self; - when: JobEnd send: #jobEnd: to: self. + when: JobEnd send: #jobEnd: to: self." ] diff --git a/src/Spec2-Core/SpProgressBarPresenter.class.st b/src/Spec2-Core/SpProgressBarPresenter.class.st index 75470076..67f1cc24 100644 --- a/src/Spec2-Core/SpProgressBarPresenter.class.st +++ b/src/Spec2-Core/SpProgressBarPresenter.class.st @@ -74,6 +74,12 @@ SpProgressBarPresenter >> progress: aBlock every: aDelay [ self state: (SpProgressingProgressBarState progression: aBlock every: aDelay) ] +{ #category : 'api' } +SpProgressBarPresenter >> refresh [ + + ^ self withAdapterDo: [ :anAdapter | anAdapter updateState ] +] + { #category : 'private' } SpProgressBarPresenter >> state [ diff --git a/src/Spec2-Dialogs/SpApplication.extension.st b/src/Spec2-Dialogs/SpApplication.extension.st index 088cf3a2..def49f68 100644 --- a/src/Spec2-Dialogs/SpApplication.extension.st +++ b/src/Spec2-Dialogs/SpApplication.extension.st @@ -33,11 +33,12 @@ SpApplication >> informUser: aString during: aBlock [ result := nil. self jobList - pushJob: (SpJob - newTitle: aString + pushJob: (Job new + title: aString; block: [ :job | job min: 0; max: 100. - result := aBlock cull: job ]). + result := aBlock cull: job ]; + yourself). ^ result ] diff --git a/src/Spec2-Dialogs/SpProgressDialog.class.st b/src/Spec2-Dialogs/SpProgressDialog.class.st index 5997d79e..8d44ebce 100644 --- a/src/Spec2-Dialogs/SpProgressDialog.class.st +++ b/src/Spec2-Dialogs/SpProgressDialog.class.st @@ -5,6 +5,7 @@ The task can control the progress. Class { #name : 'SpProgressDialog', #superclass : 'SpInformUserDialog', + #classTraits : '{} + TraitedClass', #instVars : [ 'maxValue' ], diff --git a/src/Spec2-Layout/SpExecutableLayout.class.st b/src/Spec2-Layout/SpExecutableLayout.class.st index 5b143640..4e44caa8 100644 --- a/src/Spec2-Layout/SpExecutableLayout.class.st +++ b/src/Spec2-Layout/SpExecutableLayout.class.st @@ -270,7 +270,7 @@ SpExecutableLayout >> remove: aPresenter ifAbsent: aBlock [ ^ (children includesKey: aPresenter) ifTrue: [ children removeKey: aPresenter ] - ifFalse: aBlock + ifFalse: [ aBlock value ] ] { #category : 'private' } diff --git a/src/Spec2-Morphic-Tests/SpJobListPresenterTest.class.st b/src/Spec2-Morphic-Tests/SpJobListPresenterTest.class.st index 1d76cf30..155541fc 100644 --- a/src/Spec2-Morphic-Tests/SpJobListPresenterTest.class.st +++ b/src/Spec2-Morphic-Tests/SpJobListPresenterTest.class.st @@ -17,9 +17,10 @@ SpJobListPresenterTest >> testJobIsFinishedWhenWaitingMoreThanWorkBlockDuration self skipOnPharoCITestingEnvironment. progress := 0. - job := SpJob - newTitle: 'some job' - block: [ : myjob | 1 to: 25 do: [ :i | myjob value: i*4. 20 milliSeconds wait. ] ]. + job := Job new + title: 'some job'; + block: [ : myjob | 1 to: 25 do: [ :i | myjob value: i*4. 20 milliSeconds wait. ] ]; + yourself. [ presenter := SpJobListPresenter new pushJob: job; yourself. ] fork. @@ -35,9 +36,10 @@ SpJobListPresenterTest >> testJobIsNotFinishedWhenWaitingLessThanWorkBlockDurati self skipOnPharoCITestingEnvironment. progress := 0. - job := SpJob - newTitle: 'some job' - block: [ : myjob | 1 to: 25 do: [ :i | myjob value: i*4. 60 milliSeconds wait. ] ]. + job := Job new + title: 'some job'; + block: [ : myjob | 1 to: 25 do: [ :i | myjob value: i*4. 60 milliSeconds wait ] ]; + yourself. [ presenter := SpJobListPresenter new pushJob: job; yourself. ] fork. @@ -57,9 +59,12 @@ SpJobListPresenterTest >> testProgressDoesNotRefreshMoreThanRefreshRate [ refreshRateInMs := 150. nbUpdates := 25. counter := 0. - job := SpJob - newTitle: 'some job' - block: [ : myjob | 1 to: nbUpdates do: [ :i | myjob value: i * 4. waitBetweenJobUpdate wait. ] ]. + job := Job new + title: 'some job'; + block: [ : myjob | + 1 to: nbUpdates do: [ :i | + myjob value: i * 4. waitBetweenJobUpdate wait ] ]; + yourself. presenter := SpJobPresenter on: job. [ presenter open. From 56c25b2cefac70665d0ecf0adeaa9d7d97815d79 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Wed, 24 Jan 2024 16:59:46 +0100 Subject: [PATCH 04/16] try a better height --- src/Spec2-Core/SpJobListPresenter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 83d5ebd8..43f54d0a 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -48,7 +48,7 @@ SpJobListPresenter >> addJobPresenter: aJob [ ifTrue: [ self open ]. self withWindowDo: [ :window | - window resize: 500@(layout children size * self jobPresenterHeight) ] + window resize: 500@(layout children size * self jobPresenterHeight) + 10 ] ] { #category : 'private' } From 2264c1fb688ff9311553c252b96f07d9e9bd7c34 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Wed, 24 Jan 2024 17:20:26 +0100 Subject: [PATCH 05/16] play with the height --- src/Spec2-Core/SpJobListPresenter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 43f54d0a..1ccd534c 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -48,7 +48,7 @@ SpJobListPresenter >> addJobPresenter: aJob [ ifTrue: [ self open ]. self withWindowDo: [ :window | - window resize: 500@(layout children size * self jobPresenterHeight) + 10 ] + window resize: 500@((layout children size * self jobPresenterHeight) + 20) ] ] { #category : 'private' } From e81b7d9d0302631be7f0c1e0c3edebe742f05837 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 25 Jan 2024 14:55:28 +0100 Subject: [PATCH 06/16] do not use a push, now I am using the announcements --- src/Spec2-Dialogs/SpApplication.extension.st | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Spec2-Dialogs/SpApplication.extension.st b/src/Spec2-Dialogs/SpApplication.extension.st index def49f68..693628d8 100644 --- a/src/Spec2-Dialogs/SpApplication.extension.st +++ b/src/Spec2-Dialogs/SpApplication.extension.st @@ -32,13 +32,12 @@ SpApplication >> informUser: aString during: aBlock [ | result | result := nil. - self jobList - pushJob: (Job new - title: aString; - block: [ :job | - job min: 0; max: 100. - result := aBlock cull: job ]; - yourself). + Job new + title: aString; + block: [ :job | + job min: 0; max: 100. + result := aBlock cull: job ]; + run. ^ result ] From 99d29bec384468740eb0504e200c8d6c8ed32d26 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 09:49:01 +0100 Subject: [PATCH 07/16] force a refresh --- src/Spec2-Core/SpJobListPresenter.class.st | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 1ccd534c..ca213414 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -113,7 +113,9 @@ SpJobListPresenter >> jobPresenterHeight [ SpJobListPresenter >> jobStart: ann [ "Skip if already there" - (self findJob: ann job) ifNotNil: [ ^ self ]. + (self findJob: ann job) ifNotNil: [ :aJobPresenter | + aJobPresenter refresh. + ^ self ]. self addJobPresenter: ann job. self ensureOpen ] From 44bbfd8bea299f0e81fc3ffba6f45b4557183561 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 10:51:10 +0100 Subject: [PATCH 08/16] made job list able to work independently again. --- src/Spec2-Core/SpJob.class.st | 34 +++++++++++++++----- src/Spec2-Core/SpJobListPresenter.class.st | 22 ++++++++++--- src/Spec2-Dialogs/SpApplication.extension.st | 4 +-- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/Spec2-Core/SpJob.class.st b/src/Spec2-Core/SpJob.class.st index db15787b..167fd45a 100644 --- a/src/Spec2-Core/SpJob.class.st +++ b/src/Spec2-Core/SpJob.class.st @@ -78,7 +78,7 @@ SpJob >> addChild: aJob [ aJob parent: self ] -{ #category : 'announcing' } +{ #category : 'private - announcing' } SpJob >> announce: anAnnouncementClass [ | announcement | @@ -86,14 +86,25 @@ SpJob >> announce: anAnnouncementClass [ self announcer announce: announcement ] -{ #category : 'private' } +{ #category : 'private - announcing' } SpJob >> announceChange [ - isRunning ifFalse: [ ^ self ]. self announce: JobChange ] -{ #category : 'announcing' } +{ #category : 'private - announcing' } +SpJob >> announceEnd [ + + self announce: JobEnd +] + +{ #category : 'private - announcing' } +SpJob >> announceStart [ + + self announce: JobStart +] + +{ #category : 'private - announcing' } SpJob >> announcer [ ^ announcer ifNil: [ announcer := Announcer new ] @@ -122,7 +133,7 @@ SpJob >> cleanupAfterRunning [ isRunning := false. process := nil. - self announce: JobEnd. + self announceEnd. parent ifNotNil: [ :job | job removeChild: self ] ] @@ -175,6 +186,12 @@ SpJob >> initialize [ children := OrderedCollection new ] +{ #category : 'instance creation' } +SpJob >> installOn: aPresenter [ + + announcer := aPresenter +] + { #category : 'testing' } SpJob >> isRunning [ @@ -221,6 +238,7 @@ SpJob >> max: aNumber [ SpJob >> migrateProgressWhileUpdatingBounds: aBlockChangingBounds [ "Keep the progress value consistent while we change min / max" | progress | + progress := self progress. aBlockChangingBounds value. self progress: progress. @@ -256,10 +274,10 @@ SpJob >> prepareForRunning [ isRunning := true. process := Processor activeProcess. - self announce: JobStart + self announceStart ] -{ #category : 'progress' } +{ #category : 'accessing' } SpJob >> progress [ "Avoid negative progress and divideByZero." @@ -268,7 +286,7 @@ SpJob >> progress [ ifFalse: [ (currentValue - min) / (max - min) ] ] -{ #category : 'progress' } +{ #category : 'accessing' } SpJob >> progress: aNormalizedFloat [ "Set the progress: 0.0 - 1.0" diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index ca213414..585f1388 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -14,19 +14,20 @@ Class { { #category : 'examples' } SpJobListPresenter class >> example [ - + | jobList | + + jobList := self new. [ 1 to: 5 do: [ :index | [ - Job new + jobList pushJob: (SpJob new title: 'Job ', index asString; block: [ :job | job min: 1; max: 10. 1 to: 10 do: [ :i | job title: ('Test {1}/10' format: {i}). job value: i. - 250 milliSeconds wait ] ]; - run. + 250 milliSeconds wait ] ]). ] fork. 200 milliSeconds wait ] ] fork. @@ -67,6 +68,16 @@ SpJobListPresenter >> findJob: aJob [ ifNone: [ nil ] ] +{ #category : 'initialization' } +SpJobListPresenter >> initialize [ + + super initialize. + self announcer + when: JobStart send: #jobStart: to: self; + when: JobChange send: #jobChanged: to: self; + when: JobEnd send: #jobEnd: to: self +] + { #category : 'initialization' } SpJobListPresenter >> initializePresenters [ @@ -106,7 +117,7 @@ SpJobListPresenter >> jobEnd: ann [ { #category : 'private' } SpJobListPresenter >> jobPresenterHeight [ - ^ 70 + ^ 80 ] { #category : 'private - events' } @@ -129,6 +140,7 @@ SpJobListPresenter >> newJob [ { #category : 'api' } SpJobListPresenter >> pushJob: aJob [ + aJob installOn: self. aJob run ] diff --git a/src/Spec2-Dialogs/SpApplication.extension.st b/src/Spec2-Dialogs/SpApplication.extension.st index 693628d8..ecbf4766 100644 --- a/src/Spec2-Dialogs/SpApplication.extension.st +++ b/src/Spec2-Dialogs/SpApplication.extension.st @@ -32,12 +32,12 @@ SpApplication >> informUser: aString during: aBlock [ | result | result := nil. - Job new + self jobList pushJob: (Job new title: aString; block: [ :job | job min: 0; max: 100. result := aBlock cull: job ]; - run. + yourself). ^ result ] From 1c858e58755ca15eada3928746ab695967f8e144 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 11:39:27 +0100 Subject: [PATCH 09/16] another attempt to clean up and not let remainings --- src/Spec2-Core/SpJobListPresenter.class.st | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 585f1388..0c69ca7a 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -49,7 +49,7 @@ SpJobListPresenter >> addJobPresenter: aJob [ ifTrue: [ self open ]. self withWindowDo: [ :window | - window resize: 500@((layout children size * self jobPresenterHeight) + 20) ] + window resize: 500@((layout children size * self jobPresenterHeight) + 10) ] ] { #category : 'private' } @@ -81,7 +81,7 @@ SpJobListPresenter >> initialize [ { #category : 'initialization' } SpJobListPresenter >> initializePresenters [ - self layout: SpBoxLayout newTopToBottom + self resetLayout ] { #category : 'initialization' } @@ -168,10 +168,17 @@ SpJobListPresenter >> removeJobPresenter: aJob [ self layout remove: presenter. - self layout children - ifEmpty: [ self withWindowDo: [ :window | window close ] ]. + self layout children ifEmpty: [ + self withWindowDo: [ :window | window close ]. + self resetLayout ]. self withWindowDo: [ :window | window resize: 500@(layout children size * self jobPresenterHeight). window centered ] ] + +{ #category : 'private' } +SpJobListPresenter >> resetLayout [ + + self layout: SpBoxLayout newTopToBottom +] From 4e605794779fb0628799dc5ce2341124e110111f Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 11:45:47 +0100 Subject: [PATCH 10/16] another attempt --- src/Spec2-Core/SpJobListPresenter.class.st | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 0c69ca7a..5f8dd881 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -81,7 +81,7 @@ SpJobListPresenter >> initialize [ { #category : 'initialization' } SpJobListPresenter >> initializePresenters [ - self resetLayout + self layout: SpBoxLayout newTopToBottom ] { #category : 'initialization' } @@ -168,13 +168,13 @@ SpJobListPresenter >> removeJobPresenter: aJob [ self layout remove: presenter. - self layout children ifEmpty: [ - self withWindowDo: [ :window | window close ]. - self resetLayout ]. - self withWindowDo: [ :window | - window resize: 500@(layout children size * self jobPresenterHeight). - window centered ] + self layout children + ifNotEmpty: [ + window resize: 500@(layout children size * self jobPresenterHeight). + window centered ] + ifEmpty: [ + window close ] ] ] { #category : 'private' } From 24a63d500a3cbfb3332920ecc77acb9e5e1ee9f9 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 11:57:58 +0100 Subject: [PATCH 11/16] trying a weak --- src/Spec2-Layout/SpExecutableLayout.class.st | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Spec2-Layout/SpExecutableLayout.class.st b/src/Spec2-Layout/SpExecutableLayout.class.st index 4e44caa8..f7f9b514 100644 --- a/src/Spec2-Layout/SpExecutableLayout.class.st +++ b/src/Spec2-Layout/SpExecutableLayout.class.st @@ -306,12 +306,14 @@ SpExecutableLayout >> resolvePresenter: aPresenterOrLayout presenter: aPresenter { #category : 'accessing' } SpExecutableLayout >> selector [ + ^ selector ] { #category : 'accessing' } -SpExecutableLayout >> selector: anObject [ - selector := anObject +SpExecutableLayout >> selector: aSelector [ + + selector := aSelector ] { #category : 'private' } @@ -338,13 +340,16 @@ SpExecutableLayout >> unsubscribe [ { #category : 'events' } SpExecutableLayout >> whenChildrenAddedDo: aBlock [ - self announcer when: SpChildrenAdded do: aBlock for: aBlock receiver + self announcer weak + when: SpChildrenAdded + do: aBlock + for: aBlock receiver ] { #category : 'events' } SpExecutableLayout >> whenChildrenRemovedDo: aBlock [ - self announcer + self announcer weak when: SpChildrenRemoved do: aBlock for: aBlock receiver From eabc3b10b8bd17c4ab01829eb711a7547c97fba9 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 13:00:16 +0100 Subject: [PATCH 12/16] clean up --- .../SpMorphicBoxAdapter.class.st | 15 ++++++++------- src/Spec2-Layout/SpExecutableLayout.class.st | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st b/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st index 2bd8db7e..2dbfd83e 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicBoxAdapter.class.st @@ -247,14 +247,15 @@ SpMorphicBoxAdapter >> newWrapMorph [ { #category : 'accessing' } SpMorphicBoxAdapter >> remove: aPresenter [ + | morph adapter | - aPresenter adapter ifNotNil: [ :adapter | - | morph | - adapter unsubscribe. - morph := adapter widget. - startPanel removeMorph: morph. - endPanel removeMorph: morph. - self verifyBoxExtent ] + (adapter := aPresenter adapter) ifNil: [ ^ self ]. + + adapter unsubscribe. + morph := adapter widget. + startPanel removeMorph: morph. + endPanel removeMorph: morph. + self verifyBoxExtent ] { #category : 'accessing' } diff --git a/src/Spec2-Layout/SpExecutableLayout.class.st b/src/Spec2-Layout/SpExecutableLayout.class.st index f7f9b514..b5c4adaa 100644 --- a/src/Spec2-Layout/SpExecutableLayout.class.st +++ b/src/Spec2-Layout/SpExecutableLayout.class.st @@ -340,7 +340,7 @@ SpExecutableLayout >> unsubscribe [ { #category : 'events' } SpExecutableLayout >> whenChildrenAddedDo: aBlock [ - self announcer weak + self announcer when: SpChildrenAdded do: aBlock for: aBlock receiver @@ -349,7 +349,7 @@ SpExecutableLayout >> whenChildrenAddedDo: aBlock [ { #category : 'events' } SpExecutableLayout >> whenChildrenRemovedDo: aBlock [ - self announcer weak + self announcer when: SpChildrenRemoved do: aBlock for: aBlock receiver From 0e54fc6899f7690a5c65e572cf856a4d4a9fcb48 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 26 Jan 2024 17:35:31 +0100 Subject: [PATCH 13/16] add a mutex and a (hepefully) temporal hack to prevent the leak. --- src/Spec2-Core/SpJobListPresenter.class.st | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 5f8dd881..40520307 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -4,8 +4,11 @@ A presenter to stack jobs. Class { #name : 'SpJobListPresenter', #superclass : 'SpPresenter', + #classTraits : '{} + TraitedClass', #instVars : [ - 'refreshRateInMs' + 'refreshRateInMs', + 'mutex', + 'jobs' ], #category : 'Spec2-Core-Job', #package : 'Spec2-Core', @@ -43,11 +46,12 @@ SpJobListPresenter >> addJobPresenter: aJob [ presenter := self instantiate: SpJobPresenter on: aJob. presenter refreshRateInMs: refreshRateInMs. + + jobs at: aJob put: presenter. self layout add: presenter expand: false. self layout children size = 1 ifTrue: [ self open ]. - self withWindowDo: [ :window | window resize: 500@((layout children size * self jobPresenterHeight) + 10) ] ] @@ -63,15 +67,17 @@ SpJobListPresenter >> ensureOpen [ { #category : 'private' } SpJobListPresenter >> findJob: aJob [ - ^ self layout children - detect: [ :each | each model = aJob ] - ifNone: [ nil ] + ^ jobs + at: aJob + ifAbsent: [ nil ] ] { #category : 'initialization' } SpJobListPresenter >> initialize [ super initialize. + jobs := SmallDictionary new. + mutex := Mutex new. self announcer when: JobStart send: #jobStart: to: self; when: JobChange send: #jobChanged: to: self; @@ -103,15 +109,16 @@ SpJobListPresenter >> isEmpty [ { #category : 'private - events' } SpJobListPresenter >> jobChanged: ann [ - (self findJob: ann job) ifNotNil: [ :aPresenter | - aPresenter model title crTrace. - aPresenter updatePresenter ] + mutex critical: [ + (self findJob: ann job) + ifNotNil: [ :aPresenter | aPresenter updatePresenter ] ] ] { #category : 'private - events' } SpJobListPresenter >> jobEnd: ann [ - self removeJobPresenter: ann job + mutex critical: [ + self removeJobPresenter: ann job ] ] { #category : 'private' } @@ -124,10 +131,12 @@ SpJobListPresenter >> jobPresenterHeight [ SpJobListPresenter >> jobStart: ann [ "Skip if already there" - (self findJob: ann job) ifNotNil: [ :aJobPresenter | - aJobPresenter refresh. - ^ self ]. - self addJobPresenter: ann job. + mutex critical: [ + (self findJob: ann job) ifNotNil: [ :aJobPresenter | + aJobPresenter refresh. + ^ self ]. + self addJobPresenter: ann job ]. + self ensureOpen ] @@ -166,15 +175,21 @@ SpJobListPresenter >> removeJobPresenter: aJob [ presenter := self findJob: aJob. presenter ifNil: [ ^ self ]. + jobs removeKey: aJob. self layout remove: presenter. - + self withWindowDo: [ :window | self layout children ifNotEmpty: [ window resize: 500@(layout children size * self jobPresenterHeight). window centered ] ifEmpty: [ - window close ] ] + window close. + self flag: #HACK. "This is a hack to prevent a leak that I cannot + detect while executing this several times. Removing the job list + from the application will effectively clean up the process (but + the leak is still there, somewhere in morphic...I need to find it)" + self application removeProperty: #jobList ] ] ] { #category : 'private' } From cf9709809d2b9e5c836234ed4b1e78429fe37511 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Mon, 29 Jan 2024 10:47:12 +0100 Subject: [PATCH 14/16] adding a #moveTo: method to place windows after opened (but add a clear warning that it may not work on all backends) --- .../SpMorphicWindowAdapter.class.st | 12 ++++++------ src/Spec2-Core/SpWindowPresenter.class.st | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st b/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st index 8ba6afbd..d2abe4e5 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st @@ -115,12 +115,6 @@ SpMorphicWindowAdapter >> delete [ self application windowClosed: self ] ] -{ #category : 'protocol' } -SpMorphicWindowAdapter >> extent: aPoint [ - - ^ self widget extent: aPoint -] - { #category : 'widget API' } SpMorphicWindowAdapter >> initialExtent [ @@ -190,6 +184,12 @@ SpMorphicWindowAdapter >> minimize [ self widgetDo: [ :w | w minimize ] ] +{ #category : 'protocol' } +SpMorphicWindowAdapter >> moveTo: aPoint [ + + ^ self widget position: aPoint +] + { #category : 'widget API' } SpMorphicWindowAdapter >> okToChange [ diff --git a/src/Spec2-Core/SpWindowPresenter.class.st b/src/Spec2-Core/SpWindowPresenter.class.st index c3baa3fa..92f96deb 100644 --- a/src/Spec2-Core/SpWindowPresenter.class.st +++ b/src/Spec2-Core/SpWindowPresenter.class.st @@ -289,7 +289,10 @@ SpWindowPresenter >> initialPosition [ { #category : 'api' } SpWindowPresenter >> initialPosition: aPoint [ "Set initial position of the window. - `aPoint` is an instance of `Point`, indicating x@y coordinates" + `aPoint` is an instance of `Point`, indicating x@y coordinates + WARNING: Not all backends will support this (for example Gtk lets + the window manager position windows and hence it ignores any positioning + we set)." initialPosition := aPoint ] @@ -442,6 +445,20 @@ SpWindowPresenter >> minimize [ self withAdapterDo: [ :anAdapter | anAdapter minimize ] ] +{ #category : 'api' } +SpWindowPresenter >> moveTo: aPoint [ + "Moves the window to a specific location. + `aPoint` is an instance of `Point`, indicating x@y coordinates + + To set initial position of a window, use #initialPosition:, not this. + WARNING: Not all backends will support this (for example Gtk lets + the window manager position windows and hence it ignores any positioning + we set)." + + self withAdapterPerformOrDefer: [ :anAdapter | anAdapter moveTo: aPoint ] + +] + { #category : 'notifying' } SpWindowPresenter >> notify: aSpecNotification [ "Receives a notification and delivers it as required" From fa39043a16187d93c0293c7f938e57b8662cb230 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Mon, 29 Jan 2024 10:48:05 +0100 Subject: [PATCH 15/16] resizing a window will re-center window if window should be centered --- src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st b/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st index d2abe4e5..094aef7b 100644 --- a/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st +++ b/src/Spec2-Adapters-Morphic/SpMorphicWindowAdapter.class.st @@ -231,7 +231,9 @@ SpMorphicWindowAdapter >> rebuildWithSpecLayout: aSpec [ { #category : 'widget API' } SpMorphicWindowAdapter >> resize: aPoint [ - widget extent: aPoint + widget extent: aPoint. + self presenter isCentered + ifTrue: [ self centered ] ] { #category : 'factory' } From 407411a5d1e4956e152502b87b56d6d0277372fb Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Mon, 29 Jan 2024 11:36:36 +0100 Subject: [PATCH 16/16] remove Traited error --- src/Spec2-Core/SpJobListPresenter.class.st | 1 - src/Spec2-Dialogs/SpProgressDialog.class.st | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Spec2-Core/SpJobListPresenter.class.st b/src/Spec2-Core/SpJobListPresenter.class.st index 40520307..079f9d3b 100644 --- a/src/Spec2-Core/SpJobListPresenter.class.st +++ b/src/Spec2-Core/SpJobListPresenter.class.st @@ -4,7 +4,6 @@ A presenter to stack jobs. Class { #name : 'SpJobListPresenter', #superclass : 'SpPresenter', - #classTraits : '{} + TraitedClass', #instVars : [ 'refreshRateInMs', 'mutex', diff --git a/src/Spec2-Dialogs/SpProgressDialog.class.st b/src/Spec2-Dialogs/SpProgressDialog.class.st index 8d44ebce..5997d79e 100644 --- a/src/Spec2-Dialogs/SpProgressDialog.class.st +++ b/src/Spec2-Dialogs/SpProgressDialog.class.st @@ -5,7 +5,6 @@ The task can control the progress. Class { #name : 'SpProgressDialog', #superclass : 'SpInformUserDialog', - #classTraits : '{} + TraitedClass', #instVars : [ 'maxValue' ],