From 79e30d21762d0c57ac97a747d0f9015226f8dfca Mon Sep 17 00:00:00 2001 From: Hernan Morales Durand <4825959+hernanmd@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:35:56 +0100 Subject: [PATCH 01/17] Get the real value when getting a setting presenter from a setting declaration. Announce SettingUpdated on checkboxes only if the setting effectively changed. Fix checkboxes items always opening with the default value instead of the real value. Add announcer support in StSettingPresenterItem --- .../SettingDeclaration.extension.st | 5 ++++- .../StSettingBooleanPresenterItem.class.st | 15 ++++++++++++--- .../StSettingPresenterItem.class.st | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st b/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st index 136f1222f..c6f1e547c 100644 --- a/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st +++ b/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st @@ -5,7 +5,10 @@ SettingDeclaration >> asSettingPresenter [ "Answer an appropriate container for the receiver's value" ^ self precondition value - ifTrue: [ self default asSettingPresenter: self ] + ifTrue: [ + self hasValue + ifTrue: [ self realValue asSettingPresenter: self ] + ifFalse: [ self default asSettingPresenter: self ] ] ifFalse: [ SpNullPresenter new ] ] diff --git a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st index aee75a8bd..3f4b7d4cd 100644 --- a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st @@ -12,9 +12,17 @@ Class { { #category : 'initialization' } StSettingBooleanPresenterItem >> initializePresenters [ - setterPresenter := self newCheckBox + setterPresenter := self newCheckBox. + setterPresenter + state: self model realValue; whenActivatedDo: [ self updateSetting: self model value: true ]; - whenDeactivatedDo: [ self updateSetting: self model value: false ]. + whenDeactivatedDo: [ self updateSetting: self model value: false ]; + whenChangedDo: [ : newValue : oldValue | + newValue = oldValue ifFalse: [ + self announcer announce: (SettingUpdated + declaration: self model + oldValue: oldValue + newValue: newValue) ] ]. super initializePresenters. ] @@ -43,5 +51,6 @@ StSettingBooleanPresenterItem >> updateSetting: aSettingDeclaration value: aBool { #category : 'accessing' } StSettingBooleanPresenterItem >> value: aBoolean [ - self setterPresenter state: aBoolean + self setterPresenter state: aBoolean. + ] diff --git a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st index a96fdc1dd..667a37a71 100644 --- a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st @@ -18,6 +18,14 @@ Class { #tag : 'Widgets' } +{ #category : 'accessing' } +StSettingPresenterItem >> announcer [ + "Answer a to notify receiver changes" + + ^ self environment codeSupportAnnouncer + +] + { #category : 'layout' } StSettingPresenterItem >> defaultLayout [ @@ -26,6 +34,12 @@ StSettingPresenterItem >> defaultLayout [ yourself ] +{ #category : 'initialization' } +StSettingPresenterItem >> environment [ + + ^ SystemEnvironment new +] + { #category : 'initialization' } StSettingPresenterItem >> initializePresenters [ "Set a label and description presenters as baseline for every setting" From 03166c371c97540552468027d41ab0fdd865e6b1 Mon Sep 17 00:00:00 2001 From: Hernan Morales Durand <4825959+hernanmd@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:45:09 +0100 Subject: [PATCH 02/17] Add support for logging setting updates WiP --- .../StSettingsSessionLogTest.class.st | 95 +++++++ .../StSettingsTrackerTest.class.st | 12 + .../SettingDeclaration.extension.st | 5 +- .../StSettingBooleanPresenterItem.class.st | 15 +- .../StSettingPresenterItem.class.st | 14 - .../StSettingSessionLog.class.st | 260 ++++++++++++++++++ .../StSettingSessionLogEntry.class.st | 7 + .../StSettingsTracker.class.st | 85 ++++++ .../StSettingsTree.class.st | 10 +- 9 files changed, 472 insertions(+), 31 deletions(-) create mode 100644 src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st create mode 100644 src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st create mode 100644 src/NewTools-SettingsBrowser/StSettingSessionLog.class.st create mode 100644 src/NewTools-SettingsBrowser/StSettingSessionLogEntry.class.st create mode 100644 src/NewTools-SettingsBrowser/StSettingsTracker.class.st diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st new file mode 100644 index 000000000..15d0c0e7f --- /dev/null +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st @@ -0,0 +1,95 @@ +Class { + #name : 'StSettingsSessionLogTest', + #superclass : 'TestCase', + #category : 'NewTools-SettingsBrowser-Tests', + #package : 'NewTools-SettingsBrowser-Tests' +} + +{ #category : 'tests' } +StSettingsSessionLogTest >> fileNameForTesting [ + + ^ 'test.phSetting' + +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> fileSystemForTesting [ + + ^ FileSystem memory +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> newSettingSession [ + + ^ StSettingSessionLog new + baseDirectory: self fileSystemForTesting; + yourself +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> testChangedSettings [ + | v1 v2 v3 settingSession | + + v1 := 'v1'. + v2 := 'v2'. + v3 := 'v3'. + + settingSession := self newSettingSession. + + settingSession basicContents: v1. + settingSession flush. + + settingSession basicContents: v2. + settingSession flush. + + settingSession basicContents: v3. + settingSession flush. + + self assert: settingSession changedSettings size equals: 3. + self assert: settingSession changedSettings first content equals: v1. + self assert: settingSession changedSettings second content equals: v2. + self assert: settingSession changedSettings third content equals: v3 + +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> testFlush [ + | session | + + session := self newSettingSession. + session basicContents: 'test'. + + self assert: session contents isEmpty. + + session flush. + + self assert: session contents equals: 'test' + + + +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> testFromReference [ + | memory file settingEntry | + + memory := self fileSystemForTesting. + file := memory / self fileNameForTesting. + file writeStreamDo: [ :stream | stream << 'TEST']. + + settingEntry := StSettingSessionLog fromReference: file. + self assert: settingEntry fileReference equals: file. + +] + +{ #category : 'tests' } +StSettingsSessionLogTest >> testStoreSettingEntry [ + | v1 settingSession | + + v1 := 'v1'. + settingSession := self newSettingSession. + settingSession basicContents: v1. + settingSession flush. + self deny: settingSession changedSettings isEmpty. + self assert: settingSession changedSettings first content equals: v1 +] diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st new file mode 100644 index 000000000..1659b7b60 --- /dev/null +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st @@ -0,0 +1,12 @@ +Class { + #name : 'StSettingsTrackerTest', + #superclass : 'TestCase', + #category : 'NewTools-SettingsBrowser-Tests', + #package : 'NewTools-SettingsBrowser-Tests' +} + +{ #category : 'tests' } +StSettingsTrackerTest >> newSettingsTracker [ + + ^ StSettingsTracker new +] diff --git a/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st b/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st index c6f1e547c..136f1222f 100644 --- a/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st +++ b/src/NewTools-SettingsBrowser/SettingDeclaration.extension.st @@ -5,10 +5,7 @@ SettingDeclaration >> asSettingPresenter [ "Answer an appropriate container for the receiver's value" ^ self precondition value - ifTrue: [ - self hasValue - ifTrue: [ self realValue asSettingPresenter: self ] - ifFalse: [ self default asSettingPresenter: self ] ] + ifTrue: [ self default asSettingPresenter: self ] ifFalse: [ SpNullPresenter new ] ] diff --git a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st index 3f4b7d4cd..aee75a8bd 100644 --- a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st @@ -12,17 +12,9 @@ Class { { #category : 'initialization' } StSettingBooleanPresenterItem >> initializePresenters [ - setterPresenter := self newCheckBox. - setterPresenter - state: self model realValue; + setterPresenter := self newCheckBox whenActivatedDo: [ self updateSetting: self model value: true ]; - whenDeactivatedDo: [ self updateSetting: self model value: false ]; - whenChangedDo: [ : newValue : oldValue | - newValue = oldValue ifFalse: [ - self announcer announce: (SettingUpdated - declaration: self model - oldValue: oldValue - newValue: newValue) ] ]. + whenDeactivatedDo: [ self updateSetting: self model value: false ]. super initializePresenters. ] @@ -51,6 +43,5 @@ StSettingBooleanPresenterItem >> updateSetting: aSettingDeclaration value: aBool { #category : 'accessing' } StSettingBooleanPresenterItem >> value: aBoolean [ - self setterPresenter state: aBoolean. - + self setterPresenter state: aBoolean ] diff --git a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st index 667a37a71..a96fdc1dd 100644 --- a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st @@ -18,14 +18,6 @@ Class { #tag : 'Widgets' } -{ #category : 'accessing' } -StSettingPresenterItem >> announcer [ - "Answer a to notify receiver changes" - - ^ self environment codeSupportAnnouncer - -] - { #category : 'layout' } StSettingPresenterItem >> defaultLayout [ @@ -34,12 +26,6 @@ StSettingPresenterItem >> defaultLayout [ yourself ] -{ #category : 'initialization' } -StSettingPresenterItem >> environment [ - - ^ SystemEnvironment new -] - { #category : 'initialization' } StSettingPresenterItem >> initializePresenters [ "Set a label and description presenters as baseline for every setting" diff --git a/src/NewTools-SettingsBrowser/StSettingSessionLog.class.st b/src/NewTools-SettingsBrowser/StSettingSessionLog.class.st new file mode 100644 index 000000000..938b55907 --- /dev/null +++ b/src/NewTools-SettingsBrowser/StSettingSessionLog.class.st @@ -0,0 +1,260 @@ +Class { + #name : 'StSettingSessionLog', + #superclass : 'Object', + #instVars : [ + 'baseDirectory', + 'fileName', + 'creationTime', + 'fileReference', + 'flushContents', + 'mutex', + 'flushAction', + 'contentReceived', + 'flushProcess', + 'timeToWait', + 'versionLog', + 'modificationTime' + ], + #category : 'NewTools-SettingsBrowser-Logging', + #package : 'NewTools-SettingsBrowser', + #tag : 'Logging' +} + +{ #category : 'instance creation' } +StSettingSessionLog class >> fromReference: aFileReference [ + + ^ self new fromReference: aFileReference +] + +{ #category : 'accessing' } +StSettingSessionLog >> baseDirectory [ + + ^ baseDirectory ifNil:[ StSettingsTracker cacheDirectory ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> baseDirectory: anObject [ + + baseDirectory := anObject +] + +{ #category : 'private' } +StSettingSessionLog >> basicContents: aString [ + + flushContents := aString +] + +{ #category : 'accessing - versions' } +StSettingSessionLog >> changedSettings [ + "Answer a of " + + ^ Array streamContents: [ :stream | + self versionLog entriesDo: [ :anEntry | + stream nextPut: anEntry ] ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> contentReceived [ + + ^ contentReceived +] + +{ #category : 'accessing' } +StSettingSessionLog >> contentReceived: anObject [ + + contentReceived := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> contents [ + + ^ self fileReference + ifExists: [ :ref | ref contents ] + ifAbsent: [ '' ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> contents: aString [ + + aString asString trimmed ifEmpty: [ ^ self ]. + mutex critical: [ + self basicContents: aString. + contentReceived := true. + self spawnFlushProcess ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> creationTime [ + + ^ creationTime +] + +{ #category : 'accessing' } +StSettingSessionLog >> creationTime: anObject [ + + creationTime := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> creationTimeForFileName [ + + ^ (self creationTime asString + copyReplaceAll: ':' with: '-') + copyReplaceAll: '.' with: '-' +] + +{ #category : 'accessing' } +StSettingSessionLog >> fileName [ + + ^ fileName ifNil: [ fileName := self creationTimeForFileName ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> fileName: anObject [ + + fileName := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> fileReference [ + + ^ (self baseDirectory / self fileName) withExtension: StSettingsTracker settingExtension +] + +{ #category : 'accessing' } +StSettingSessionLog >> fileReference: anObject [ + + fileReference := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> flush [ + + mutex critical: [ + flushContents ifNil: [ ^ self ]. + self fileReference parent ensureCreateDirectory. + self fileReference + ensureDelete; + writeStreamDo: [ :stream | + stream << flushContents ]. + flushContents := nil. + self storeChangedSetting. + self touch. + flushAction ifNotNil: [ + flushAction value ] ] +] + +{ #category : 'accessing' } +StSettingSessionLog >> flushAction [ + + ^ flushAction +] + +{ #category : 'accessing' } +StSettingSessionLog >> flushAction: anObject [ + + flushAction := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> flushContents [ + + ^ flushContents +] + +{ #category : 'accessing' } +StSettingSessionLog >> flushProcess [ + + ^ flushProcess +] + +{ #category : 'accessing' } +StSettingSessionLog >> flushProcess: anObject [ + + flushProcess := anObject +] + +{ #category : 'instance creation' } +StSettingSessionLog >> fromReference: aFileReference [ + + aFileReference parent = self baseDirectory + ifFalse: [ self baseDirectory: aFileReference parent ]. + fileName := aFileReference basenameWithoutExtension. + creationTime := aFileReference creationTime +] + +{ #category : 'initialization' } +StSettingSessionLog >> initialize [ + + super initialize. + contentReceived := false. + creationTime := DateAndTime now. + timeToWait := 10 milliSeconds. + mutex := Mutex new +] + +{ #category : 'accessing' } +StSettingSessionLog >> mutex [ + + ^ mutex +] + +{ #category : 'accessing' } +StSettingSessionLog >> mutex: anObject [ + + mutex := anObject +] + +{ #category : 'accessing' } +StSettingSessionLog >> spawnFlushProcess [ + + (flushProcess isNotNil + and: [ flushProcess isTerminated not ]) + ifTrue: [ ^ self ]. + + flushProcess := [ + [ contentReceived ] whileTrue: [ + contentReceived := false. + self timeToWait wait ]. + self flush. + flushProcess := nil. + "in case I need to restart" + contentReceived ifTrue: [ self spawnFlushProcess ]. + ] fork +] + +{ #category : 'accessing - versions' } +StSettingSessionLog >> storeChangedSetting [ + | entry | + + "store new version" + entry := OmEntry content: self contents. + entry tags at: #timestamp put: DateAndTime now. + self versionLog newEntry: entry + +] + +{ #category : 'accessing' } +StSettingSessionLog >> timeToWait [ + + ^ timeToWait +] + +{ #category : 'accessing' } +StSettingSessionLog >> timeToWait: aDuration [ + + timeToWait := aDuration +] + +{ #category : 'accessing' } +StSettingSessionLog >> touch [ + + modificationTime := DateAndTime now +] + +{ #category : 'accessing - versions' } +StSettingSessionLog >> versionLog [ + + ^ versionLog ifNil: [ + versionLog := OmFileStore fromFile: (self fileReference withExtension: 'ombu') ] +] diff --git a/src/NewTools-SettingsBrowser/StSettingSessionLogEntry.class.st b/src/NewTools-SettingsBrowser/StSettingSessionLogEntry.class.st new file mode 100644 index 000000000..fdff297e9 --- /dev/null +++ b/src/NewTools-SettingsBrowser/StSettingSessionLogEntry.class.st @@ -0,0 +1,7 @@ +Class { + #name : 'StSettingSessionLogEntry', + #superclass : 'Object', + #category : 'NewTools-SettingsBrowser-Logging', + #package : 'NewTools-SettingsBrowser', + #tag : 'Logging' +} diff --git a/src/NewTools-SettingsBrowser/StSettingsTracker.class.st b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st new file mode 100644 index 000000000..9dda0028e --- /dev/null +++ b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st @@ -0,0 +1,85 @@ +Class { + #name : 'StSettingsTracker', + #superclass : 'Object', + #classVars : [ + 'SettingCacheDirectory' + ], + #category : 'NewTools-SettingsBrowser-Logging', + #package : 'NewTools-SettingsBrowser', + #tag : 'Logging' +} + +{ #category : 'accessing' } +StSettingsTracker class >> cacheDirectory [ + + ^ SettingCacheDirectory ifNil: [ self defaultCacheDirectory ] +] + +{ #category : 'defaults' } +StSettingsTracker class >> defaultCacheDirectory [ + + ^ (FileLocator localDirectory / 'settings-cache') ensureCreateDirectory +] + +{ #category : 'accessing' } +StSettingsTracker class >> settingExtension [ + + ^ 'phSetting' +] + +{ #category : 'opening' } +StSettingsTracker class >> settingsKeywords [ + + ^ (Pragma allNamed: #systemsettings) collect: [: p | p method selector ] +] + +{ #category : 'settings' } +StSettingsTracker class >> settingsOn: aBuilder [ + + + (aBuilder setting: #settingCacheDirectory ) + parent: #pharoSystem; + type: #Directory; + default: self defaultCacheDirectory; + target: StSettingsTree; + description: 'The path to the local Settings cache that stores all Setting updates in ' , self settingExtension , ' files'; + label: 'Local Setting cache directory'. +] + +{ #category : 'accessing - versions' } +StSettingsTracker >> changedSettings [ + "Answer a of " + + ^ self storedChangedSettings flatCollect: [ : aSessionLog | aSessionLog changedSettings ] +] + +{ #category : 'initialization' } +StSettingsTracker >> initialize [ + "Subscribe settings to register their changes" + + super initialize. + self class codeSupportAnnouncer weak + when: SettingUpdated + send: #settingUpdated: + to: self + +] + +{ #category : 'initialization' } +StSettingsTracker >> settingUpdated: aSetting [ + + self shouldBeImplemented +] + +{ #category : 'accessing - versions' } +StSettingsTracker >> storedChangedSettings [ + + ^ (self storedChangedSettingsFiles sorted: #modificationTime descending) + collect: [ :each | StSettingSessionLog fromReference: each ] +] + +{ #category : 'accessing - versions' } +StSettingsTracker >> storedChangedSettingsFiles [ + + ^ self class cacheDirectory allChildrenMatching: '*.' , self class settingExtension +] diff --git a/src/NewTools-SettingsBrowser/StSettingsTree.class.st b/src/NewTools-SettingsBrowser/StSettingsTree.class.st index 60e4da60e..6184421d8 100644 --- a/src/NewTools-SettingsBrowser/StSettingsTree.class.st +++ b/src/NewTools-SettingsBrowser/StSettingsTree.class.st @@ -1,12 +1,20 @@ Class { #name : 'StSettingsTree', #superclass : 'SettingTree', + #instVars : [ + 'versionLog', + 'baseDirectory', + 'fileName' + ], + #classVars : [ + 'SettingCacheDirectory' + ], #category : 'NewTools-SettingsBrowser-Model', #package : 'NewTools-SettingsBrowser', #tag : 'Model' } -{ #category : 'opening' } +{ #category : 'instance creation' } StSettingsTree class >> settingsKeywords [ ^ (Pragma allNamed: #systemsettings) collect: [: p | p method selector ] From cc0a4f2de6c1a0e338fb835a8384305728e8a121 Mon Sep 17 00:00:00 2001 From: Hernan Morales Durand <4825959+hernanmd@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:32:18 +0100 Subject: [PATCH 03/17] Initialize the application before super initialization that needs the settingTree already present in the application's properties. Announce SettingUpdated on checkboxes only if the setting effectively changed. Fix checkboxes items always opening with the default value instead of the real value. --- .../StSettingsTrackerTest.class.st | 49 +++++++++++++++++++ .../StSettingBooleanPresenterItem.class.st | 18 +++++-- .../StSettingsMainPresenter.class.st | 5 +- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st index 1659b7b60..c68cb723b 100644 --- a/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st @@ -1,6 +1,10 @@ Class { #name : 'StSettingsTrackerTest', #superclass : 'TestCase', + #instVars : [ + 'tracker', + 'numberOfAnnouncements' + ], #category : 'NewTools-SettingsBrowser-Tests', #package : 'NewTools-SettingsBrowser-Tests' } @@ -10,3 +14,48 @@ StSettingsTrackerTest >> newSettingsTracker [ ^ StSettingsTracker new ] + +{ #category : 'running' } +StSettingsTrackerTest >> setUp [ + + super setUp. + numberOfAnnouncements := 0. + tracker := self newSettingsTracker. + +] + +{ #category : 'tests' } +StSettingsTrackerTest >> testSettingUpdated [ + "Check if the updated setting was tracked" + + "Simulate a setting change" + + + self when: SettingUpdated do: [ : ann | + self assert: (tracker changedSettings includes: ann) ] + + +] + +{ #category : 'accessing' } +StSettingsTrackerTest >> tracker [ + + ^ tracker +] + +{ #category : 'accessing' } +StSettingsTrackerTest >> tracker: anObject [ + + tracker := anObject +] + +{ #category : 'tests' } +StSettingsTrackerTest >> when: anAnnouncement do: aBlock [ + + self class codeChangeAnnouncer + when: anAnnouncement + do: [ :ann | + numberOfAnnouncements := numberOfAnnouncements + 1. + aBlock cull: ann ] + for: self +] diff --git a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st index aee75a8bd..98d02f7a8 100644 --- a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st @@ -10,13 +10,21 @@ Class { } { #category : 'initialization' } -StSettingBooleanPresenterItem >> initializePresenters [ +StSettingBooleanPresenterItem >> initializePresenters [ setterPresenter := self newCheckBox - whenActivatedDo: [ self updateSetting: self model value: true ]; - whenDeactivatedDo: [ self updateSetting: self model value: false ]. - super initializePresenters. - + state: self model realValue; + whenActivatedDo: [ + self updateSetting: self model value: true ]; + whenDeactivatedDo: [ + self updateSetting: self model value: false ]; + whenChangedDo: [ :newValue :oldValue | + newValue = oldValue ifFalse: [ + self announcer announce: (SettingUpdated + declaration: self model + oldValue: oldValue + newValue: newValue) ] ]. + super initializePresenters ] { #category : 'initialization' } diff --git a/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st b/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st index 13dd62f0b..961bdde76 100644 --- a/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st +++ b/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st @@ -139,10 +139,11 @@ StSettingsMainPresenter >> followPath: aStSettingNode in: aCollection [ { #category : 'initialization' } StSettingsMainPresenter >> initialize [ - super initialize. self currentApplication propertyAt: #settingsTree ifAbsentPut: StSettingsTree new; - styleSheet: self class styleSheet + styleSheet: self class styleSheet. + super initialize. + ] { #category : 'initialization' } From d76f3130dc29e8d6f7c7fce7a159c617ccda5b27 Mon Sep 17 00:00:00 2001 From: Hernan Morales Durand <4825959+hernanmd@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:39:57 +0100 Subject: [PATCH 04/17] Add mocks for testing setting updates --- .../StSettingsSessionLogTest.class.st | 83 ++++++++++++++++--- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st index 15d0c0e7f..1744e0119 100644 --- a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st @@ -5,20 +5,83 @@ Class { #package : 'NewTools-SettingsBrowser-Tests' } -{ #category : 'tests' } +{ #category : 'private' } StSettingsSessionLogTest >> fileNameForTesting [ ^ 'test.phSetting' ] -{ #category : 'tests' } +{ #category : 'private' } +StSettingsSessionLogTest >> fileReferenceForTesting [ + + ^ self fileSystemForTesting / self fileNameForTesting. +] + +{ #category : 'private' } StSettingsSessionLogTest >> fileSystemForTesting [ ^ FileSystem memory ] -{ #category : 'tests' } +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSetting1 [ + + ^ SettingUpdated + declaration: (self newMockSettingDeclaration: 1) + oldValue: false + newValue: true +] + +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSetting2 [ + + ^ SettingUpdated + declaration: (self newMockSettingDeclaration: 2) + oldValue: 0 + newValue: 100 +] + +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSetting3 [ + + ^ SettingUpdated + declaration: (self newMockSettingDeclaration: 3) + oldValue: 'Old Value' + newValue: 'New Value' +] + +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSetting: aMockSetting asSTON: stream [ + + ^ (STONWriter on: (ZnCharacterWriteStream on: stream)) + prettyPrint: true; + newLine: OSPlatform current lineEnding; + nextPut: aMockSetting + +] + +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSettingAsSTONString: aMockSetting [ + + ^ (ByteArray streamContents: [ :stream | + self + newMockSetting: aMockSetting + asSTON: stream ]) asString + +] + +{ #category : 'private' } +StSettingsSessionLogTest >> newMockSettingDeclaration: id [ + + ^ SettingDeclaration new + name: 'MockSettingDeclaration' , id asString; + target: self; + selector: #mockDefault; + default: true +] + +{ #category : 'private' } StSettingsSessionLogTest >> newSettingSession [ ^ StSettingSessionLog new @@ -30,9 +93,9 @@ StSettingsSessionLogTest >> newSettingSession [ StSettingsSessionLogTest >> testChangedSettings [ | v1 v2 v3 settingSession | - v1 := 'v1'. - v2 := 'v2'. - v3 := 'v3'. + v1 := self newMockSettingAsSTONString: self newMockSetting1. + v2 := self newMockSettingAsSTONString: self newMockSetting2. + v3 := self newMockSettingAsSTONString: self newMockSetting3. settingSession := self newSettingSession. @@ -71,10 +134,9 @@ StSettingsSessionLogTest >> testFlush [ { #category : 'tests' } StSettingsSessionLogTest >> testFromReference [ - | memory file settingEntry | + | file settingEntry | - memory := self fileSystemForTesting. - file := memory / self fileNameForTesting. + file := self fileReferenceForTesting. file writeStreamDo: [ :stream | stream << 'TEST']. settingEntry := StSettingSessionLog fromReference: file. @@ -86,10 +148,11 @@ StSettingsSessionLogTest >> testFromReference [ StSettingsSessionLogTest >> testStoreSettingEntry [ | v1 settingSession | - v1 := 'v1'. + v1 := self newMockSettingAsSTONString: self newMockSetting1. settingSession := self newSettingSession. settingSession basicContents: v1. settingSession flush. + self deny: settingSession changedSettings isEmpty. self assert: settingSession changedSettings first content equals: v1 ] From 6ca3a6d1e9e670ea7b8fea904e9aae3f0117ea35 Mon Sep 17 00:00:00 2001 From: Hernan Morales Durand <4825959+hernanmd@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:31:40 +0100 Subject: [PATCH 05/17] Add settings tracker mocks and tests --- .../MockSettingTarget.class.st | 17 ++++++ .../StSettingsSessionLogAbstractTest.class.st | 56 +++++++++++++++++++ .../StSettingsSessionLogTest.class.st | 43 +------------- .../StSettingsTrackerTest.class.st | 19 +++++-- .../StSettingBooleanPresenterItem.class.st | 2 +- .../StSettingsTracker.class.st | 34 ++++++++++- 6 files changed, 125 insertions(+), 46 deletions(-) create mode 100644 src/NewTools-SettingsBrowser-Tests/MockSettingTarget.class.st create mode 100644 src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogAbstractTest.class.st diff --git a/src/NewTools-SettingsBrowser-Tests/MockSettingTarget.class.st b/src/NewTools-SettingsBrowser-Tests/MockSettingTarget.class.st new file mode 100644 index 000000000..3bf4b0a02 --- /dev/null +++ b/src/NewTools-SettingsBrowser-Tests/MockSettingTarget.class.st @@ -0,0 +1,17 @@ +Class { + #name : 'MockSettingTarget', + #superclass : 'Object', + #category : 'NewTools-SettingsBrowser-Tests', + #package : 'NewTools-SettingsBrowser-Tests' +} + +{ #category : 'accessing' } +MockSettingTarget class >> default [ + + ^ true +] + +{ #category : 'accessing' } +MockSettingTarget class >> default: aBoolean [ + +] diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogAbstractTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogAbstractTest.class.st new file mode 100644 index 000000000..8d09f8086 --- /dev/null +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogAbstractTest.class.st @@ -0,0 +1,56 @@ +Class { + #name : 'StSettingsSessionLogAbstractTest', + #superclass : 'TestCase', + #category : 'NewTools-SettingsBrowser-Tests', + #package : 'NewTools-SettingsBrowser-Tests' +} + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> fileNameForTesting [ + + ^ 'test.phSetting' + +] + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> fileReferenceForTesting [ + + ^ self fileSystemForTesting / self fileNameForTesting. +] + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> fileSystemForTesting [ + + ^ FileSystem memory root +] + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> newMockSettingDeclaration: id [ + + | declaration | + + declaration := SettingDeclaration new + name: 'MockSettingDeclaration' , id asString; + yourself. + declaration + target: MockSettingTarget; + selector: #default; + default: true. + ^ declaration. +] + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> newSettingSession [ + + ^ StSettingSessionLog new + baseDirectory: self fileSystemForTesting; + yourself +] + +{ #category : 'private' } +StSettingsSessionLogAbstractTest >> newSettingSession: aFileReference [ + + ^ StSettingSessionLog new + fromReference: aFileReference; + yourself +] diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st index 1744e0119..f3f151e7b 100644 --- a/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsSessionLogTest.class.st @@ -1,29 +1,10 @@ Class { #name : 'StSettingsSessionLogTest', - #superclass : 'TestCase', + #superclass : 'StSettingsSessionLogAbstractTest', #category : 'NewTools-SettingsBrowser-Tests', #package : 'NewTools-SettingsBrowser-Tests' } -{ #category : 'private' } -StSettingsSessionLogTest >> fileNameForTesting [ - - ^ 'test.phSetting' - -] - -{ #category : 'private' } -StSettingsSessionLogTest >> fileReferenceForTesting [ - - ^ self fileSystemForTesting / self fileNameForTesting. -] - -{ #category : 'private' } -StSettingsSessionLogTest >> fileSystemForTesting [ - - ^ FileSystem memory -] - { #category : 'private' } StSettingsSessionLogTest >> newMockSetting1 [ @@ -71,24 +52,6 @@ StSettingsSessionLogTest >> newMockSettingAsSTONString: aMockSetting [ ] -{ #category : 'private' } -StSettingsSessionLogTest >> newMockSettingDeclaration: id [ - - ^ SettingDeclaration new - name: 'MockSettingDeclaration' , id asString; - target: self; - selector: #mockDefault; - default: true -] - -{ #category : 'private' } -StSettingsSessionLogTest >> newSettingSession [ - - ^ StSettingSessionLog new - baseDirectory: self fileSystemForTesting; - yourself -] - { #category : 'tests' } StSettingsSessionLogTest >> testChangedSettings [ | v1 v2 v3 settingSession | @@ -120,13 +83,13 @@ StSettingsSessionLogTest >> testFlush [ | session | session := self newSettingSession. - session basicContents: 'test'. + session basicContents: (self newMockSettingAsSTONString: self newMockSetting1). self assert: session contents isEmpty. session flush. - self assert: session contents equals: 'test' + self assert: session contents equals: (self newMockSettingAsSTONString: self newMockSetting1) diff --git a/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st index c68cb723b..5ed21e092 100644 --- a/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st @@ -1,6 +1,6 @@ Class { #name : 'StSettingsTrackerTest', - #superclass : 'TestCase', + #superclass : 'StSettingsSessionLogAbstractTest', #instVars : [ 'tracker', 'numberOfAnnouncements' @@ -21,18 +21,29 @@ StSettingsTrackerTest >> setUp [ super setUp. numberOfAnnouncements := 0. tracker := self newSettingsTracker. + tracker class cacheDirectory: self fileSystemForTesting. ] +{ #category : 'running' } +StSettingsTrackerTest >> tearDown [ + + self tracker class reset. + super tearDown. +] + { #category : 'tests' } StSettingsTrackerTest >> testSettingUpdated [ "Check if the updated setting was tracked" - "Simulate a setting change" - + | settingItem | self when: SettingUpdated do: [ : ann | - self assert: (tracker changedSettings includes: ann) ] + self assert: (tracker changedSettings includes: ann) ]. + + settingItem := true asSettingPresenter: (self newMockSettingDeclaration: 1). + settingItem value: false. + ] diff --git a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st index 98d02f7a8..3cad63576 100644 --- a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st @@ -20,7 +20,7 @@ StSettingBooleanPresenterItem >> initializePresenters [ self updateSetting: self model value: false ]; whenChangedDo: [ :newValue :oldValue | newValue = oldValue ifFalse: [ - self announcer announce: (SettingUpdated + self class codeChangeAnnouncer announce: (SettingUpdated declaration: self model oldValue: oldValue newValue: newValue) ] ]. diff --git a/src/NewTools-SettingsBrowser/StSettingsTracker.class.st b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st index 9dda0028e..0844f7045 100644 --- a/src/NewTools-SettingsBrowser/StSettingsTracker.class.st +++ b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st @@ -11,16 +11,33 @@ Class { { #category : 'accessing' } StSettingsTracker class >> cacheDirectory [ + "Answer a pointing to the directory used for storing setting updates" ^ SettingCacheDirectory ifNil: [ self defaultCacheDirectory ] ] +{ #category : 'accessing' } +StSettingsTracker class >> cacheDirectory: aFileReference [ + + SettingCacheDirectory := aFileReference +] + { #category : 'defaults' } StSettingsTracker class >> defaultCacheDirectory [ - + "Answer a pointing to the default directory used for storing setting updates" + ^ (FileLocator localDirectory / 'settings-cache') ensureCreateDirectory ] +{ #category : 'class initialization' } +StSettingsTracker class >> reset [ + "Reset the receiver's setting cache directory" +