From 16c4d24078cd98030133f1e26dec2b64a1f5aece Mon Sep 17 00:00:00 2001 From: Yann Le Goff Date: Wed, 31 Jul 2024 18:35:28 +0200 Subject: [PATCH] Add a single popover panel on the top of the screen + lazy load the grouped and single properties. --- .../PyramidPopingPresenterBuilder.class.st | 24 ++- src/Pyramid/PyramidPropertiesManager.class.st | 9 +- ...amidPropertiesManagerForSelection.class.st | 16 +- .../PyramidPropertyPopupPresenter.class.st | 12 +- ...ramidSinglePopingPresenterBuilder.class.st | 193 +++++++++++++++++ ...ramidSinglePropertyPopupPresenter.class.st | 199 ++++++++++++++++++ 6 files changed, 442 insertions(+), 11 deletions(-) create mode 100644 src/Pyramid/PyramidSinglePopingPresenterBuilder.class.st create mode 100644 src/Pyramid/PyramidSinglePropertyPopupPresenter.class.st diff --git a/src/Pyramid/PyramidPopingPresenterBuilder.class.st b/src/Pyramid/PyramidPopingPresenterBuilder.class.st index ac7cf9b0..d85033d4 100644 --- a/src/Pyramid/PyramidPopingPresenterBuilder.class.st +++ b/src/Pyramid/PyramidPopingPresenterBuilder.class.st @@ -7,7 +7,10 @@ I create a presenter with a main input to change property of all element at once Class { #name : #PyramidPopingPresenterBuilder, #superclass : #PyramidPropertyPresenterBuilder, - #category : 'Pyramid-property' + #instVars : [ + 'popupFactory' + ], + #category : #'Pyramid-property' } { #category : #'as yet unclassified' } @@ -43,14 +46,11 @@ PyramidPopingPresenterBuilder >> buildLayoutAll: presenterAll grouped: presenter buttonPopup := SpButtonPresenter new icon: (Smalltalk ui icons iconNamed: #edit); - help: 'Show groups and individuals values'; + help: 'Show groups and individuals values'; yourself. buttonPopup action: [ - (PyramidPopoverFactory - makeWithPresenter: presenterPopup - relativeTo: buttonPopup - position: SpPopoverPosition left) popup ]. + (self popupFactory value: presenterPopup value: buttonPopup) popup ]. ^ self layoutForAll: presenterAll buttonPopup: buttonPopup ] @@ -178,3 +178,15 @@ PyramidPopingPresenterBuilder >> makeNewInput [ strings: self property pyramidInputPresenterStrings; yourself ] + +{ #category : #'as yet unclassified' } +PyramidPopingPresenterBuilder >> popupFactory [ + + ^ popupFactory +] + +{ #category : #'as yet unclassified' } +PyramidPopingPresenterBuilder >> popupFactory: anObject [ + + popupFactory := anObject +] diff --git a/src/Pyramid/PyramidPropertiesManager.class.st b/src/Pyramid/PyramidPropertiesManager.class.st index bc4c20bc..f2256276 100644 --- a/src/Pyramid/PyramidPropertiesManager.class.st +++ b/src/Pyramid/PyramidPropertiesManager.class.st @@ -7,7 +7,7 @@ Class { 'presenterStrategy', 'history' ], - #category : 'Pyramid-property' + #category : #'Pyramid-property' } { #category : #removing } @@ -20,6 +20,7 @@ PyramidPropertiesManager >> addAllProperties: aCollection [ PyramidPropertiesManager >> addProperty: aPyramidProperty [ aPyramidProperty commandExecutor: self commandExecutor. + aPyramidProperty presenterBuilder: self makePresenterBuilder. self properties add: aPyramidProperty ] @@ -61,6 +62,12 @@ PyramidPropertiesManager >> initialize [ presenterStrategy := PyramidHideEmptyPropertyStrategy new ] +{ #category : #'as yet unclassified' } +PyramidPropertiesManager >> makePresenterBuilder [ + + ^ self shouldBeImplemented +] + { #category : #accessing } PyramidPropertiesManager >> presenterStrategy [ diff --git a/src/Pyramid/PyramidPropertiesManagerForSelection.class.st b/src/Pyramid/PyramidPropertiesManagerForSelection.class.st index 60a4f063..8a88adb9 100644 --- a/src/Pyramid/PyramidPropertiesManagerForSelection.class.st +++ b/src/Pyramid/PyramidPropertiesManagerForSelection.class.st @@ -6,7 +6,7 @@ Class { 'shouldComputeProperties', 'projectModel' ], - #category : 'Pyramid-property' + #category : #'Pyramid-property' } { #category : #'as yet unclassified' } @@ -33,6 +33,20 @@ PyramidPropertiesManagerForSelection >> initialize [ commandExecutor afterDo: [ self projectModel informElementsChanged ] ] +{ #category : #'as yet unclassified' } +PyramidPropertiesManagerForSelection >> makePresenterBuilder [ + + | popupPanel | + popupPanel := PyramidSinglePropertyPopupPresenter new + originPresenter: self presenter; + popoverDirection: SpPopoverPosition left; + yourself. + + ^ PyramidSinglePopingPresenterBuilder new + popupPanel: popupPanel; + yourself +] + { #category : #accessing } PyramidPropertiesManagerForSelection >> presenter [ diff --git a/src/Pyramid/PyramidPropertyPopupPresenter.class.st b/src/Pyramid/PyramidPropertyPopupPresenter.class.st index afb43214..c0ed6333 100644 --- a/src/Pyramid/PyramidPropertyPopupPresenter.class.st +++ b/src/Pyramid/PyramidPropertyPopupPresenter.class.st @@ -8,7 +8,7 @@ Class { 'groupedPresenters', 'name' ], - #category : 'Pyramid-property' + #category : #'Pyramid-property' } { #category : #accessing } @@ -101,12 +101,12 @@ PyramidPropertyPopupPresenter >> layoutWith: aCollection [ label: self name; displayBold: [ :t | true ]; yourself) - width: 150; + width: self popupExtent x; add: self buttonGroup width: 75; add: self buttonIndividual width: 75; yourself) expand: false; - add: scroll height: 300; + add: scroll height: self popupExtent y; yourself ] @@ -132,6 +132,12 @@ PyramidPropertyPopupPresenter >> name: aString grouped: groupedCollection indivi self buttonGroup state ifTrue: [ self showGroupPresenter ] ifFalse: [ self showIndividualPresenter ]. ] +{ #category : #'as yet unclassified' } +PyramidPropertyPopupPresenter >> popupExtent [ + + ^ 250 @ 500 +] + { #category : #'as yet unclassified' } PyramidPropertyPopupPresenter >> showGroupPresenter [ diff --git a/src/Pyramid/PyramidSinglePopingPresenterBuilder.class.st b/src/Pyramid/PyramidSinglePopingPresenterBuilder.class.st new file mode 100644 index 00000000..17c8000e --- /dev/null +++ b/src/Pyramid/PyramidSinglePopingPresenterBuilder.class.st @@ -0,0 +1,193 @@ +Class { + #name : #PyramidSinglePopingPresenterBuilder, + #superclass : #PyramidPropertyPresenterBuilder, + #instVars : [ + 'popupPanel' + ], + #category : #'Pyramid-property' +} + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> build [ + + | presenterAll layout | + presenterAll := self buildPresenterAll. + + self cluster size > 1 + ifTrue: [ + layout := self buildLayoutAllGroupedAndIndividual: presenterAll ] + ifFalse: [ layout := self buildLayoutOnlyForAll: presenterAll ]. + + ^ SpPresenter new + layout: layout; + yourself +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildLayoutAllGroupedAndIndividual: presenterAll [ + + | buttonPopup | + buttonPopup := SpButtonPresenter new + icon: (Smalltalk ui icons iconNamed: #edit); + help: 'Show groups and individuals values'; + yourself. + + buttonPopup action: [ + self popupPanel lastPropertyShown: self property. + self popupPanel + name: self property name + grouped: self buildPresentersGrouped + individual: self buildPresentersIndividual. + self popupPanel popup ]. + + self updatePopupPanel. + + ^ self layoutForAll: presenterAll buttonPopup: buttonPopup +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildLayoutOnlyForAll: presenterAll [ + + | buttonPopup | + buttonPopup := SpButtonPresenter new + icon: (Smalltalk ui icons iconNamed: #edit); + enabled: false; + yourself. + + ^ self layoutForAll: presenterAll buttonPopup: buttonPopup +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildPresenterAll [ + + | input | + input := self makeNewInput. + + self cluster isEmpty ifTrue: [ + input emptyValue. + ^ input ]. + + self cluster isTargetsSameArguments + ifTrue: [ input value: self cluster groups first ] + ifFalse: [ input mixedValues ]. + + input whenValueChangedDo: [ :value | + self property commandExecutor + use: self property command + on: self cluster allTargets + with: value ]. + ^ input +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildPresenterWithButtonsFor: anAssociation withLabel: aString [ + + | input buttonApplyToAll layout | + input := self makeNewInput. + input value: anAssociation key. + input whenValueChangedDo: [ :value | + self property commandExecutor + use: self property command + on: anAssociation value + with: value ]. + + buttonApplyToAll := SpButtonPresenter new + icon: (Smalltalk ui icons iconNamed: #smallExpert); + help: 'Apply this value to all selected elements.'; + action: [ + self property commandExecutor + use: self property command + on: self cluster allTargets + with: input value ]. + layout := self + layoutForLabel: aString + input: input + button: buttonApplyToAll. + ^ SpPresenter new + layout: layout; + yourself +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildPresentersGrouped [ + + | size label | + self cluster isEmpty ifTrue: [ ^ { } ]. + ^ self cluster groupedAssociations associations collect: [ :each | + size := each value size. + label := size = 1 + ifTrue: [ '1 element' ] + ifFalse: [ size printString , ' elements' ]. + self buildPresenterWithButtonsFor: each withLabel: label ] +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> buildPresentersIndividual [ + + | label | + self cluster isEmpty ifTrue: [ ^ { } ]. + ^ self cluster individualAssociations collect: [ :each | + label := each value first hash printString. + self buildPresenterWithButtonsFor: each withLabel: label ] +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> layoutForAll: presenterAll buttonPopup: buttonPopup [ + + ^ SpBoxLayout newVertical + spacing: 4; + add: (SpBoxLayout newHorizontal + spacing: 4; + vAlignCenter; + add: buttonPopup width: 24; + add: (SpLabelPresenter new + label: self property name; + displayBold: [ :t | true ]; + yourself); + yourself) + height: 24; + add: presenterAll expand: false; + yourself +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> layoutForLabel: aString input: anInput button: aButton [ + + ^ SpBoxLayout newHorizontal + spacing: 4; + vAlignCenter; + add: aString width: 80; + add: anInput; + add: aButton width: 24; + yourself +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> makeNewInput [ + + ^ self property pyramidInputPresenterClass new + strings: self property pyramidInputPresenterStrings; + yourself +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> popupPanel [ + + ^ popupPanel +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> popupPanel: anObject [ + + popupPanel := anObject +] + +{ #category : #'as yet unclassified' } +PyramidSinglePopingPresenterBuilder >> updatePopupPanel [ + + self popupPanel lastPropertyShown = self property ifFalse: [ ^ self ]. + self popupPanel + name: self property name + grouped: self buildPresentersGrouped + individual: self buildPresentersIndividual +] diff --git a/src/Pyramid/PyramidSinglePropertyPopupPresenter.class.st b/src/Pyramid/PyramidSinglePropertyPopupPresenter.class.st new file mode 100644 index 00000000..c36b1b59 --- /dev/null +++ b/src/Pyramid/PyramidSinglePropertyPopupPresenter.class.st @@ -0,0 +1,199 @@ +Class { + #name : #PyramidSinglePropertyPopupPresenter, + #superclass : #SpPresenter, + #instVars : [ + 'buttonIndividual', + 'buttonGroup', + 'individualPresenters', + 'groupedPresenters', + 'name', + 'originPresenter', + 'popoverDirection', + 'lastPropertyShown' + ], + #category : #'Pyramid-property' +} + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> buttonGroup [ + + ^ buttonGroup +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> buttonIndividual [ + + ^ buttonIndividual +] + +{ #category : #layout } +PyramidSinglePropertyPopupPresenter >> defaultLayout [ + + ^ SpBoxLayout newVertical +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> groupedPresenters [ + + ^ groupedPresenters +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> groupedPresenters: anObject [ + + groupedPresenters := anObject +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> individualPresenters [ + + ^ individualPresenters +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> individualPresenters: anObject [ + + individualPresenters := anObject +] + +{ #category : #'initialization - deprecated' } +PyramidSinglePropertyPopupPresenter >> initializePresenters [ + + individualPresenters := { }. + groupedPresenters := { }. + name := 'Unknow'. + + buttonIndividual := SpRadioButtonPresenter new + label: 'Individual'; + yourself. + buttonGroup := SpRadioButtonPresenter new + label: 'Group'; + yourself. + + buttonIndividual associatedRadioButtons: { buttonGroup }. + self buttonGroup click. + buttonIndividual whenActivatedDo: [ self showIndividualPresenter ]. + buttonGroup whenActivatedDo: [ self showGroupPresenter ] +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> lastPropertyShown [ + + ^ lastPropertyShown +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> lastPropertyShown: anObject [ + + lastPropertyShown := anObject +] + +{ #category : #'as yet unclassified' } +PyramidSinglePropertyPopupPresenter >> layoutWith: aCollection [ + + | inputsLayout scroll | + inputsLayout := SpBoxLayout newVertical + spacing: 4; + yourself. + aCollection do: [ :each | inputsLayout add: each height: 24 ]. + inputsLayout add: ''. + + aCollection + ifEmpty: [ + scroll := SpLabelPresenter new + label: 'nothing to see here'; + yourself ] + ifNotEmpty: [ + scroll := SpScrollableLayout new child: (SpPresenter new + layout: inputsLayout; + yourself) ]. + + ^ SpBoxLayout newVertical + spacing: 4; + add: (SpBoxLayout newHorizontal + spacing: 4; + add: (SpLabelPresenter new + label: self name; + displayBold: [ :t | true ]; + yourself) + width: self popupExtent x; + add: self buttonGroup width: 75; + add: self buttonIndividual width: 75; + yourself) + expand: false; + add: scroll height: self popupExtent y; + yourself +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> name [ + + ^ name +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> name: anObject [ + + name := anObject +] + +{ #category : #'as yet unclassified' } +PyramidSinglePropertyPopupPresenter >> name: aString grouped: groupedCollection individual: individualCollection [ + + self name: aString. + self individualPresenters: individualCollection. + self groupedPresenters: groupedCollection. + + self buttonGroup state ifTrue: [ self showGroupPresenter ] ifFalse: [ self showIndividualPresenter ]. +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> originPresenter [ + + ^ originPresenter +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> originPresenter: anObject [ + + originPresenter := anObject +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> popoverDirection [ + + ^ popoverDirection +] + +{ #category : #accessing } +PyramidSinglePropertyPopupPresenter >> popoverDirection: anObject [ + + popoverDirection := anObject +] + +{ #category : #api } +PyramidSinglePropertyPopupPresenter >> popup [ + + (PyramidPopoverFactory + makeWithPresenter: self + relativeTo: self originPresenter + position: self popoverDirection) popup +] + +{ #category : #'as yet unclassified' } +PyramidSinglePropertyPopupPresenter >> popupExtent [ + + ^ 250 @ 500 +] + +{ #category : #'as yet unclassified' } +PyramidSinglePropertyPopupPresenter >> showGroupPresenter [ + + self layout: (self layoutWith: self groupedPresenters). +] + +{ #category : #'as yet unclassified' } +PyramidSinglePropertyPopupPresenter >> showIndividualPresenter [ + + self layout: (self layoutWith: self individualPresenters) +]