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/StSettingsTrackerTest.class.st b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st new file mode 100644 index 000000000..459aa3955 --- /dev/null +++ b/src/NewTools-SettingsBrowser-Tests/StSettingsTrackerTest.class.st @@ -0,0 +1,134 @@ +Class { + #name : 'StSettingsTrackerTest', + #superclass : 'TestCase', + #instVars : [ + 'tracker' + ], + #category : 'NewTools-SettingsBrowser-Tests', + #package : 'NewTools-SettingsBrowser-Tests' +} + +{ #category : 'private' } +StSettingsTrackerTest >> newMockSettingDeclaration: id [ + + | declaration | + + declaration := SettingDeclaration new + name: 'MockSettingDeclaration' , id asString; + yourself. + declaration + target: MockSettingTarget; + selector: #default; + default: true. + ^ declaration. +] + +{ #category : 'tests' } +StSettingsTrackerTest >> newSettingsTracker [ + + ^ StSettingsTracker new +] + +{ #category : 'running' } +StSettingsTrackerTest >> setUp [ + + super setUp. + tracker := StSettingsTracker new. + +] + +{ #category : 'tests' } +StSettingsTrackerTest >> submitPresenter: settingItem [ + + settingItem open. + settingItem setterPresenter adapter + keyDown: $s + shift: false + meta: true + control: false + option: false. +] + +{ #category : 'running' } +StSettingsTrackerTest >> tearDown [ + + self class codeSupportAnnouncer unsubscribe: self. + "Clean SettingUpdated subscriptions" + (self class codeSupportAnnouncer subscriptions subscriptionsHandling: SettingUpdated new) + do: [ : s | self class codeSupportAnnouncer removeSubscription: s ]. + tracker sessionLog ifNotEmpty: [ : collection | collection removeLast ]. + super tearDown +] + +{ #category : 'tests' } +StSettingsTrackerTest >> testBooleanSettingUpdated [ + "Check if the updated setting was tracked" + + | settingItem | + + self + when: SettingUpdated + do: [ : ann | + self assert: ann oldValue. + self deny: ann newValue ]. + + settingItem := true asSettingPresenter: (self newMockSettingDeclaration: 1). + settingItem value: false. + +] + +{ #category : 'tests' } +StSettingsTrackerTest >> testNumberSettingUpdated [ + "Check if the updated setting was tracked" + + | settingItem | + + self + when: SettingUpdated + do: [ : ann | + self assert: ann oldValue asNumber equals: 10. + self assert: ann newValue asNumber equals: 20 ]. + + settingItem := 10 asSettingPresenter: (self newMockSettingDeclaration: 2). + settingItem value: 20. + + +] + +{ #category : 'tests' } +StSettingsTrackerTest >> testTextSettingUpdated [ + "Check if the updated setting was tracked" + + | settingItem | + + self + when: SettingUpdated + do: [ : ann | + self assert: ann oldValue equals: 'Adios'. + self assert: ann newValue equals: 'Hola' ]. + + settingItem := 'Adios' asSettingPresenter: (self newMockSettingDeclaration: 3). + settingItem value: 'Hola'. + +] + +{ #category : 'accessing' } +StSettingsTrackerTest >> tracker [ + + ^ tracker +] + +{ #category : 'accessing' } +StSettingsTrackerTest >> tracker: anObject [ + + tracker := anObject +] + +{ #category : 'tests' } +StSettingsTrackerTest >> when: anAnnouncement do: aBlock [ + + self class codeSupportAnnouncer weak + when: anAnnouncement + do: [ :ann | aBlock cull: ann ] + for: self +] diff --git a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st index aee75a8bd..034abd462 100644 --- a/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingBooleanPresenterItem.class.st @@ -10,13 +10,15 @@ Class { } { #category : 'initialization' } -StSettingBooleanPresenterItem >> initializePresenters [ +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 ]. - super initializePresenters. - + whenDeactivatedDo: [ self updateSetting: self model value: false ]; + whenChangedDo: self updateSettingBlock. + super initializePresenters ] { #category : 'initialization' } diff --git a/src/NewTools-SettingsBrowser/StSettingDirectoryPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingDirectoryPresenterItem.class.st index 0d9a2fd75..1f87450cd 100644 --- a/src/NewTools-SettingsBrowser/StSettingDirectoryPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingDirectoryPresenterItem.class.st @@ -15,6 +15,11 @@ StSettingDirectoryPresenterItem >> initializePresenters [ setterPresenter := self newTextInput beEditable; placeholder: self model label; + whenSubmitDo: [ : newValue | + self codeSupportAnnouncer announce: (SettingUpdated + declaration: self model + oldValue: nil + newValue: newValue) ]; yourself. labeledPresenter := (self instantiate: self labeledPresenterClass on: self) label: self model label; diff --git a/src/NewTools-SettingsBrowser/StSettingDropListPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingDropListPresenterItem.class.st index 6ea1c8594..a7906922d 100644 --- a/src/NewTools-SettingsBrowser/StSettingDropListPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingDropListPresenterItem.class.st @@ -30,8 +30,12 @@ StSettingDropListPresenterItem >> updateSetting: aSettingDeclaration [ ifNotNil: [ (self model target perform: self model targetSelector) perform: self model setSelector - with: aSettingDeclaration default ] - + with: aSettingDeclaration default ]. + "to do: https://github.com/pharo-spec/Spec/issues/1663" + self codeSupportAnnouncer announce: (SettingUpdated + declaration: self model + oldValue: nil + newValue: aSettingDeclaration) ] { #category : 'accessing' } diff --git a/src/NewTools-SettingsBrowser/StSettingMultipleDropListPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingMultipleDropListPresenterItem.class.st index 52fc1acd4..f17f49ebd 100644 --- a/src/NewTools-SettingsBrowser/StSettingMultipleDropListPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingMultipleDropListPresenterItem.class.st @@ -26,7 +26,8 @@ StSettingMultipleDropListPresenterItem >> initializePresenters [ setterPresenter := self newDropList items: #(#bold #italic #normal 'bold italic' ); - selectItem: modelDefault emphasis; + selectItem: modelDefault emphasis; + whenSelectedItemChangedDo: self updateSettingBlock; yourself. super initializePresenters. ] diff --git a/src/NewTools-SettingsBrowser/StSettingNumberPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingNumberPresenterItem.class.st index 96cb494ec..76d0cb78a 100644 --- a/src/NewTools-SettingsBrowser/StSettingNumberPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingNumberPresenterItem.class.st @@ -24,7 +24,8 @@ StSettingNumberPresenterItem >> beInteger [ { #category : 'initialization' } StSettingNumberPresenterItem >> initializePresenters [ - setterPresenter := self newNumberInput. + setterPresenter := self newNumberInput + whenSubmitDo: self updateSettingBlock. super initializePresenters. ] diff --git a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st index 45bd2e66f..4ab2ac8c2 100644 --- a/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingPresenterItem.class.st @@ -18,6 +18,13 @@ Class { #tag : 'Widgets' } +{ #category : 'initialization' } +StSettingPresenterItem >> codeSupportAnnouncer [ + "See comment in SystemEnvironment>>#codeSupportAnnouncer" + + ^ self class codeSupportAnnouncer +] + { #category : 'layout' } StSettingPresenterItem >> defaultLayout [ @@ -78,6 +85,17 @@ StSettingPresenterItem >> setterPresenter: anObject [ setterPresenter := anObject ] +{ #category : 'initialization' } +StSettingPresenterItem >> updateSettingBlock [ + "Answer a responsible to announce that a setting has been updated" + + ^ [ : newValue | + self codeSupportAnnouncer announce: (SettingUpdated + declaration: self model + oldValue: self model realValue + newValue: newValue) ] +] + { #category : 'accessing' } StSettingPresenterItem >> value: anObject [ "Set the receiver's value to anObject" diff --git a/src/NewTools-SettingsBrowser/StSettingTextPresenterItem.class.st b/src/NewTools-SettingsBrowser/StSettingTextPresenterItem.class.st index 411f75983..5669e83e1 100644 --- a/src/NewTools-SettingsBrowser/StSettingTextPresenterItem.class.st +++ b/src/NewTools-SettingsBrowser/StSettingTextPresenterItem.class.st @@ -15,6 +15,11 @@ StSettingTextPresenterItem >> initializePresenters [ setterPresenter := self newTextInput beEditable; placeholder: self model label; + whenSubmitDo: [ : newValue | + self codeSupportAnnouncer announce: (SettingUpdated + declaration: self model + oldValue: nil + newValue: newValue) ]; yourself. super initializePresenters. ] diff --git a/src/NewTools-SettingsBrowser/StSettingsCategoriesPresenter.class.st b/src/NewTools-SettingsBrowser/StSettingsCategoriesPresenter.class.st index 111c243c2..0ec53029a 100644 --- a/src/NewTools-SettingsBrowser/StSettingsCategoriesPresenter.class.st +++ b/src/NewTools-SettingsBrowser/StSettingsCategoriesPresenter.class.st @@ -16,12 +16,13 @@ Class { { #category : 'initialization' } StSettingsCategoriesPresenter >> categoriesAsPresenters [ + "Answer a of each one instantiated on a setting node + representing a category of settings" ^ self settingsCategories collect: [ : node | (self instantiate: StSettingsCategoryItemPresenter - on: node) - addStyle: 'superCategoryList' ] + on: node) addStyle: 'superCategoryList' ] ] { #category : 'accessing' } diff --git a/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st b/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st index 61565b8d9..e80fa3aab 100644 --- a/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st +++ b/src/NewTools-SettingsBrowser/StSettingsMainPresenter.class.st @@ -16,7 +16,8 @@ Class { 'detailsPresenter', 'mainCategoriesPresenter', 'buttonBarPresenter', - 'exporter' + 'exporter', + 'tracker' ], #category : 'NewTools-SettingsBrowser-UI', #package : 'NewTools-SettingsBrowser', @@ -136,16 +137,27 @@ StSettingsMainPresenter >> defaultOutputPort [ StSettingsMainPresenter >> exportSettings [ | nodes actions | + self exportedFileFullName asFileReference exists + ifTrue: [ + (self confirm: 'Do you want to overwrite the existing settings?') + ifFalse: [ ^ self ] ]. nodes := self settingsTree nodeList. actions := nodes collect: [ : e | e item exportSettingAction ] thenReject: [ : e | e isNil ]. self exporter exportAllSettings: actions. - self inform: 'Settings were exported to ' , self exporter exportedFileFullName. + self inform: 'Settings were exported to ' , self exportedFileFullName. buttonBarPresenter enable ] +{ #category : 'initialization' } +StSettingsMainPresenter >> exportedFileFullName [ + "Answer a with the receiver's file name used to store the exported settings" + + ^ self exporter exportedFileFullName +] + { #category : 'accessing' } StSettingsMainPresenter >> exporter [ @@ -167,8 +179,9 @@ StSettingsMainPresenter >> initialize [ self currentApplication propertyAt: #settingsTree ifAbsentPut: [ StSettingsTree new ]; styleSheet: self class styleSheet. - super initialize. + super initialize. exporter := StSettingsExporter new. + tracker := StSettingsTracker new. ] { #category : 'initialization' } @@ -177,7 +190,12 @@ StSettingsMainPresenter >> initializeButtonBar [ buttonBarPresenter := self newButtonBar placeAtEnd; add: (self newButton - addStyle: 'large'; + icon: (self iconNamed: #history); + label: 'History'; + help: 'Changed settings'; + action: [ StSettingsTracker sessionLog inspect ]; + yourself); + add: (self newButton icon: (self iconNamed: #openFromUrl); label: 'Load'; help: 'Load settings from a file'; @@ -193,7 +211,7 @@ StSettingsMainPresenter >> initializeButtonBar [ add: (self newButton icon: (self iconNamed: #cancel); action: [ self delete ]; - label: 'Cancel'; + label: 'Close'; yourself). ] @@ -263,3 +281,15 @@ StSettingsMainPresenter >> selectDialog: fileReferneces [ openModal. ] + +{ #category : 'accessing' } +StSettingsMainPresenter >> tracker [ + + ^ tracker +] + +{ #category : 'accessing' } +StSettingsMainPresenter >> tracker: anObject [ + + tracker := anObject +] diff --git a/src/NewTools-SettingsBrowser/StSettingsTracker.class.st b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st new file mode 100644 index 000000000..dcc164824 --- /dev/null +++ b/src/NewTools-SettingsBrowser/StSettingsTracker.class.st @@ -0,0 +1,62 @@ +Class { + #name : 'StSettingsTracker', + #superclass : 'Object', + #classVars : [ + 'SessionLog' + ], + #category : 'NewTools-SettingsBrowser-Logging', + #package : 'NewTools-SettingsBrowser', + #tag : 'Logging' +} + +{ #category : 'class initialization' } +StSettingsTracker class >> initialize [ + + SessionLog := OrderedCollection new. +] + +{ #category : 'class initialization' } +StSettingsTracker class >> reset [ +