From 09bf590426cd7b0c8c11bb784151627682315f3f Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 8 Nov 2018 00:00:59 +0100 Subject: [PATCH 1/9] action bar accept elements at the start and at the end --- src/Spec-Core/ActionBarPresenter.class.st | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Spec-Core/ActionBarPresenter.class.st b/src/Spec-Core/ActionBarPresenter.class.st index 044ef53a4..bb8c909fb 100644 --- a/src/Spec-Core/ActionBarPresenter.class.st +++ b/src/Spec-Core/ActionBarPresenter.class.st @@ -16,17 +16,30 @@ ActionBarPresenter class >> adapterName [ { #category : #adding } ActionBarPresenter >> add: aButtonPresenter [ - items add: aButtonPresenter + (items + at: #start + ifAbsentPut: [ OrderedCollection new ] ) + add: aButtonPresenter +] + +{ #category : #adding } +ActionBarPresenter >> addLast: aButtonPresenter [ + + (items + at: #end + ifAbsentPut: [ OrderedCollection new ] ) + add: aButtonPresenter ] { #category : #initialization } ActionBarPresenter >> initialize [ super initialize. - items := OrderedCollection new asValueHolder + items := Dictionary new asValueHolder ] { #category : #api } ActionBarPresenter >> items [ + ^ items value ] From 05916942b42c455f59824c9bcb250979493e3e66 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 8 Nov 2018 03:11:33 +0100 Subject: [PATCH 2/9] formatting --- src/Spec-Core/DialogWindowPresenter.class.st | 17 ++++++++++------- src/Spec-Core/WindowPresenter.class.st | 8 +++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Spec-Core/DialogWindowPresenter.class.st b/src/Spec-Core/DialogWindowPresenter.class.st index 20d63434e..ee31c805e 100644 --- a/src/Spec-Core/DialogWindowPresenter.class.st +++ b/src/Spec-Core/DialogWindowPresenter.class.st @@ -20,17 +20,20 @@ DialogWindowPresenter class >> adapterName [ { #category : #private } DialogWindowPresenter >> buildWithSpecLayout: aSpec [ "Build the widget using the spec name provided as argument" - | widget | + (self spec notNil and: [ self needRebuild not ]) - ifTrue: [ widget := self widget ] - ifFalse: [ contents := self presenter buildWithSpecLayout: aSpec. + ifTrue: [ + widget := self widget ] + ifFalse: [ + contents := self presenter buildWithSpecLayout: aSpec. widget := self adapterFrom: self retrieveDefaultSpec. contents := nil ]. - self extent - ifNotNil: [ :ex | - (widget respondsTo: #extent:) - ifTrue: [ widget extent: ex ] ]. + + self extent ifNotNil: [ :ex | + (widget respondsTo: #extent:) ifTrue: [ + widget extent: ex ] ]. + ^ widget ] diff --git a/src/Spec-Core/WindowPresenter.class.st b/src/Spec-Core/WindowPresenter.class.st index a3aff52ed..0028c9ce6 100644 --- a/src/Spec-Core/WindowPresenter.class.st +++ b/src/Spec-Core/WindowPresenter.class.st @@ -78,11 +78,13 @@ WindowPresenter >> askOkToClose [ { #category : #private } WindowPresenter >> buildWithSpecLayout: aSpec [ "Build the widget using the spec name provided as argument" - | adapter widget | + (self spec notNil and: [ self needRebuild not ]) - ifTrue: [ widget := self widget ] - ifFalse: [ adapter := self adapterFrom: self retrieveDefaultSpec. + ifTrue: [ + widget := self widget ] + ifFalse: [ + adapter := self adapterFrom: self retrieveDefaultSpec. widget := adapter widget. self addModelIn: widget withSpecLayout: aSpec ]. self ensureExtentFor: widget. From 9172edb970cfe2d110411919b54466ae3aaed252 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 8 Nov 2018 13:05:05 +0100 Subject: [PATCH 3/9] make dialogs to behave more or less like windows (the call #prepareWindow:) centered properties of a window is now a property: it will announce on change (because it can be set before or after creation and it was not working on first case) --- src/Spec-Core/DialogWindowPresenter.class.st | 6 ++++-- src/Spec-Core/WindowPresenter.class.st | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Spec-Core/DialogWindowPresenter.class.st b/src/Spec-Core/DialogWindowPresenter.class.st index ee31c805e..41332aedc 100644 --- a/src/Spec-Core/DialogWindowPresenter.class.st +++ b/src/Spec-Core/DialogWindowPresenter.class.st @@ -27,8 +27,10 @@ DialogWindowPresenter >> buildWithSpecLayout: aSpec [ widget := self widget ] ifFalse: [ contents := self presenter buildWithSpecLayout: aSpec. - widget := self adapterFrom: self retrieveDefaultSpec. - contents := nil ]. + [ + widget := (self adapterFrom: self retrieveDefaultSpec) widget. + self addModelIn: widget withSpecLayout: aSpec ] + ensure: [ contents := nil ] ]. self extent ifNotNil: [ :ex | (widget respondsTo: #extent:) ifTrue: [ diff --git a/src/Spec-Core/WindowPresenter.class.st b/src/Spec-Core/WindowPresenter.class.st index 0028c9ce6..952e045b7 100644 --- a/src/Spec-Core/WindowPresenter.class.st +++ b/src/Spec-Core/WindowPresenter.class.st @@ -11,7 +11,8 @@ Class { 'isResizeable', 'statusbarHolder', 'toolBarHolder', - 'menuHolder' + 'menuHolder', + 'centered' ], #category : #'Spec-Core-Support' } @@ -57,8 +58,8 @@ WindowPresenter >> addModelIn: widget withSpec: aSpec [ { #category : #private } WindowPresenter >> addModelIn: widget withSpecLayout: aSpec [ - self presenter ifNil: [ ^ self ]. + self presenter ifNil: [ ^ self ]. self presenter prepareWindow: self. self changed: #addModelIn:withSpecLayout: @@ -100,7 +101,7 @@ WindowPresenter >> cancelled [ { #category : #api } WindowPresenter >> centered [ - self changed: #centered with: #() + centered value: true ] { #category : #api } @@ -171,12 +172,20 @@ WindowPresenter >> initialize [ initialExtent := nil asValueHolder. isClosedHolder := false asValueHolder. isResizeable := true asValueHolder. + centered := false asValueHolder. menuHolder := nil asValueHolder. toolBarHolder := nil asValueHolder. statusbarHolder := nil asValueHolder. - presenter whenChangedDo: [:m | self updateTitle ]. + presenter whenChangedDo: [ :m | self updateTitle ]. + centered whenChangedDo: [ :m | self changed: #centered with: #() ] +] + +{ #category : #testing } +WindowPresenter >> isCentered [ + + ^ centered value ] { #category : #testing } From 53524742c117c6a7f632a6ea3664df6836d6fb6a Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 8 Nov 2018 14:46:10 +0100 Subject: [PATCH 4/9] make dialogs understand #prepareWindow: and act in consequence. --- .../MorphicDialogWindowAdapter.class.st | 61 +++++++++++++------ .../MorphicWindowAdapter.class.st | 48 +++++++++++---- .../SpecDialogWindow.class.st | 2 +- 3 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st index fdc6d52d0..676ecdfc6 100644 --- a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st +++ b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st @@ -7,15 +7,44 @@ Class { #category : #'Spec-MorphicAdapters-Base' } +{ #category : #private } +MorphicDialogWindowAdapter >> add: aMorph toWindow: aWindow [ + "do nothing, the morph is already managed" +] + +{ #category : #private } +MorphicDialogWindowAdapter >> addModelIn: widgetToBuild withSpecLayout: aSpec [ + "Since dialogs work different to regular windows in several aspects. I needed to introduce + some hooks to make things work and I'm not particulary happy with them (but I do not + find a better solution without reimplementing the whole thing). So, here is the explanation + of the changes: + First, a dialog *contains* an area, a content panel and a toolbar panel (this is correct IMO + and I wonder why windows do not behave in same way and they mix all morphs (headers, button, + contents). Anyway, important thing is when dialog arrives here, contents ARE ALREADY THERE. + I need then to replace it instead just add it. + I replace the mainPanel (which contains contents and button bar) because like that I get the + status bar at the end (where it belongs)" + + self + addContent: widgetToBuild mainPanel + toWindow: widgetToBuild +] + +{ #category : #factory } +MorphicDialogWindowAdapter >> buildToolBar [ + + +] + { #category : #factory } MorphicDialogWindowAdapter >> buildWidget [ ^ SpecDialogWindow new - specWidget: self contentMorph; - setToolbarFrom: self toolbarBlock; - model: self model; - initialize; - yourself + specWidget: self model contents; + setToolbarFrom: [ self model toolbar ]; + model: self model; + initialize; + yourself ] { #category : #'spec protocol' } @@ -25,12 +54,6 @@ MorphicDialogWindowAdapter >> cancelAction: aBlock [ ifNotNil: [:w | w cancelAction: aBlock ] ] -{ #category : #'widget API' } -MorphicDialogWindowAdapter >> contentMorph [ - - ^ self model contents -] - { #category : #'spec protocol' } MorphicDialogWindowAdapter >> okAction: aBlock [ @@ -50,16 +73,20 @@ MorphicDialogWindowAdapter >> open [ self widget openInWorld ] -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> toolbar: aToolbar [ +{ #category : #private } +MorphicDialogWindowAdapter >> replace: aMorph with: containerMorph onWindow: aSpecWindow [ + + containerMorph layoutFrame: aMorph layoutFrame. + aSpecWindow + replaceSubmorph: aMorph + by: containerMorph - self widgetDo: [ :w | w toolbar: aToolbar ] ] -{ #category : #'widget API' } -MorphicDialogWindowAdapter >> toolbarBlock [ +{ #category : #'spec protocol' } +MorphicDialogWindowAdapter >> toolbar: aToolbar [ - ^ [ self model toolbar ] + self widgetDo: [ :w | w toolbar: aToolbar ] ] { #category : #'spec protocol' } diff --git a/src/Spec-MorphicAdapters/MorphicWindowAdapter.class.st b/src/Spec-MorphicAdapters/MorphicWindowAdapter.class.st index e4df8d920..7488ebb3e 100644 --- a/src/Spec-MorphicAdapters/MorphicWindowAdapter.class.st +++ b/src/Spec-MorphicAdapters/MorphicWindowAdapter.class.st @@ -26,16 +26,21 @@ MorphicWindowAdapter >> aboutTitle [ ] { #category : #private } -MorphicWindowAdapter >> addContent: aMorph to: aSpecWindow [ +MorphicWindowAdapter >> add: containerMorph toWindow: aSpecWindow [ + + aSpecWindow + addMorph: containerMorph + fullFrame: LayoutFrame identity +] + +{ #category : #private } +MorphicWindowAdapter >> addContent: aMorph toWindow: aSpecWindow [ | containerMorph | - containerMorph := PanelMorph new - layoutPolicy: TableLayout new; - hResizing: #spaceFill; - vResizing: #spaceFill; - listDirection: #topToBottom; - yourself. - + containerMorph := self newContainerMorph. + "hook to allow my children to replace an already built morph" + self replace: aMorph with: containerMorph onWindow: aSpecWindow. + "add all decorations (menu, toolbar and statusbar)" self model hasMenu ifTrue: [ self addMenuTo: containerMorph ]. self model hasToolBar ifTrue: [ self addToolBarTo: containerMorph ]. containerMorph addMorphBack: aMorph. @@ -44,9 +49,7 @@ MorphicWindowAdapter >> addContent: aMorph to: aSpecWindow [ vResizing: #spaceFill. self model hasStatusBar ifTrue: [ self addStatusBarTo: containerMorph ]. - aSpecWindow - addMorph: containerMorph - fullFrame: LayoutFrame identity + self add: containerMorph toWindow: aSpecWindow ] { #category : #private } @@ -64,14 +67,14 @@ MorphicWindowAdapter >> addMenuTo: aMorph [ MorphicWindowAdapter >> addModelIn: widgetToBuild withSpec: aSpec [ self addContent: (self model model buildWithSpec: aSpec) - to: widgetToBuild + toWindow: widgetToBuild ] { #category : #protocol } MorphicWindowAdapter >> addModelIn: widgetToBuild withSpecLayout: aSpec [ self addContent: (self model presenter buildWithSpecLayout: aSpec) - to: widgetToBuild + toWindow: widgetToBuild ] { #category : #'widget API' } @@ -200,6 +203,17 @@ MorphicWindowAdapter >> modalRelativeTo: aWindow [ self widgetDo: [ :w | aWindow setModal: w ] ] +{ #category : #private } +MorphicWindowAdapter >> newContainerMorph [ + + ^ PanelMorph new + layoutPolicy: TableLayout new; + hResizing: #spaceFill; + vResizing: #spaceFill; + listDirection: #topToBottom; + yourself +] + { #category : #'widget API' } MorphicWindowAdapter >> okToChange [ ^ self model okToChange @@ -239,6 +253,14 @@ MorphicWindowAdapter >> rebuildWithSpecLayout: aSpec [ self widget model: self ] +{ #category : #private } +MorphicWindowAdapter >> replace: aMorph with: containerMorph onWindow: aSpecWindow [ + "If the window is already built, I need to replace old generated content with new + content with decorations. This is not the case of regular windows, but my children + may need this hook." + +] + { #category : #icons } MorphicWindowAdapter >> taskbarIcon [ ^ self model taskbarIcon diff --git a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st index 24d55d6f7..d5065d2d2 100644 --- a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st +++ b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st @@ -99,7 +99,7 @@ SpecDialogWindow >> newMainPanel [ | panel | panel := self newDialogPanel. self newContentMorph ifNotNil: [:m | panel addMorphBack: m ]. - self newButtonRow ifNotNil: [:m | panel addMorphBack: m ]. + self newButtonRow ifNotNil: [:m | panel addMorphBack: m ]. ^ panel ] From 718a58d17b464805be31d5768a55317c1acf06f4 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Thu, 15 Nov 2018 16:15:41 +0100 Subject: [PATCH 5/9] buttons need to be defined by presenter, not as a hardcoded bar --- src/Spec-Core/ComposablePresenter.class.st | 9 ++++++ src/Spec-Core/DialogWindowPresenter.class.st | 31 ++++++++++++++++++-- src/Spec-Core/WindowPresenter.class.st | 8 ++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/Spec-Core/ComposablePresenter.class.st b/src/Spec-Core/ComposablePresenter.class.st index b563beb08..6ccce86a8 100644 --- a/src/Spec-Core/ComposablePresenter.class.st +++ b/src/Spec-Core/ComposablePresenter.class.st @@ -936,6 +936,15 @@ ComposablePresenter >> owner: anObject [ owner := anObject. ] +{ #category : #api } +ComposablePresenter >> prepareDialogButtons: aDialogWindowPresenter [ + "override this to set buttons other than the default (Ok, Cancel)." + + aDialogWindowPresenter + addButton: 'Ok' do: [ "do nothing" ]; + addButton: 'Cancel' do: [ "do nothing" ] +] + { #category : #api } ComposablePresenter >> prepareWindow: aWindowPresenter [ "override this to set window values before opening. diff --git a/src/Spec-Core/DialogWindowPresenter.class.st b/src/Spec-Core/DialogWindowPresenter.class.st index 41332aedc..b8018286b 100644 --- a/src/Spec-Core/DialogWindowPresenter.class.st +++ b/src/Spec-Core/DialogWindowPresenter.class.st @@ -6,7 +6,8 @@ Class { #superclass : #WindowPresenter, #instVars : [ 'contents', - 'toolbar' + 'toolbar', + 'buttons' ], #category : #'Spec-Core-Support' } @@ -17,6 +18,15 @@ DialogWindowPresenter class >> adapterName [ ^ #DialogWindowAdapter ] +{ #category : #accessing } +DialogWindowPresenter >> addButton: aString do: aBlock [ + "Adds button logic to dialog." + + buttons + at: aString + put: aBlock +] + { #category : #private } DialogWindowPresenter >> buildWithSpecLayout: aSpec [ "Build the widget using the spec name provided as argument" @@ -39,6 +49,14 @@ DialogWindowPresenter >> buildWithSpecLayout: aSpec [ ^ widget ] +{ #category : #accessing } +DialogWindowPresenter >> buttons [ + "buttons is an ordered dictionary that matches labels with actions. + Default action will always be the last one." + + ^ buttons +] + { #category : #api } DialogWindowPresenter >> cancelAction: aBlock [ @@ -63,7 +81,9 @@ DialogWindowPresenter >> initialize [ super initialize. toolbar := OkCancelToolbar new asValueHolder. - toolbar whenChangedDo: [ :t | self changed: #toolbar: with: { t } ] + toolbar whenChangedDo: [ :t | self changed: #toolbar: with: { t } ]. + + buttons := OrderedDictionary new ] { #category : #api } @@ -78,6 +98,13 @@ DialogWindowPresenter >> okButtonEnabled: aBoolean [ self changed: #okButtonEnabled: with: { aBoolean } ] +{ #category : #private } +DialogWindowPresenter >> prepareWindow [ + + super prepareWindow. + self presenter prepareDialogButtons: self +] + { #category : #api } DialogWindowPresenter >> toolbar [ diff --git a/src/Spec-Core/WindowPresenter.class.st b/src/Spec-Core/WindowPresenter.class.st index 952e045b7..91d615539 100644 --- a/src/Spec-Core/WindowPresenter.class.st +++ b/src/Spec-Core/WindowPresenter.class.st @@ -60,7 +60,7 @@ WindowPresenter >> addModelIn: widget withSpec: aSpec [ WindowPresenter >> addModelIn: widget withSpecLayout: aSpec [ self presenter ifNil: [ ^ self ]. - self presenter prepareWindow: self. + self prepareWindow. self changed: #addModelIn:withSpecLayout: with: { widget. aSpec } @@ -260,6 +260,12 @@ WindowPresenter >> openWithSpecLayout: aSpec [ self updateTitle. ] +{ #category : #private } +WindowPresenter >> prepareWindow [ + + self presenter prepareWindow: self +] + { #category : #accessing } WindowPresenter >> presenter [ From f8f110020bc98c7dd60790b050ea4bae97d94ab9 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Wed, 21 Nov 2018 16:27:05 +0100 Subject: [PATCH 6/9] kind of working, but I still need some refactor on it --- src/Spec-Core/ComposablePresenter.class.st | 25 ++++--- src/Spec-Core/DialogWindowPresenter.class.st | 67 +++++++++---------- src/Spec-Core/TextPresenter.class.st | 8 +++ src/Spec-Core/WindowPresenter.class.st | 14 ++-- .../PrepareWindowExample.class.st | 22 +++--- .../MorphicButtonBarAdapter.class.st | 54 +++++++++++++++ .../MorphicDialogWindowAdapter.class.st | 44 +++--------- .../SpecDialogWindow.class.st | 9 ++- src/Spec-PolyWidgets/EditableList.class.st | 16 +++-- 9 files changed, 150 insertions(+), 109 deletions(-) create mode 100644 src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st diff --git a/src/Spec-Core/ComposablePresenter.class.st b/src/Spec-Core/ComposablePresenter.class.st index 6ccce86a8..5d169c50b 100644 --- a/src/Spec-Core/ComposablePresenter.class.st +++ b/src/Spec-Core/ComposablePresenter.class.st @@ -573,6 +573,7 @@ ComposablePresenter >> initialize [ { #category : #initialization } ComposablePresenter >> initializeDialogWindow: aWindow [ "used to initialize the model in the case of the use into a dialog window" + ] { #category : #initialization } @@ -633,6 +634,12 @@ ComposablePresenter >> initializeWidgets [ self subclassResponsibility ] +{ #category : #initialization } +ComposablePresenter >> initializeWindow: aWindowPresenter [ + "override this to set window values before opening. + You may want to add a menu, a toolbar or a statusbar" +] + { #category : #'instance creation' } ComposablePresenter >> instantiate: aComposablePresenterClass [ "Instantiate a ComposablePresenter subclass and set its instance owner" @@ -936,19 +943,17 @@ ComposablePresenter >> owner: anObject [ owner := anObject. ] -{ #category : #api } +{ #category : #initialization } ComposablePresenter >> prepareDialogButtons: aDialogWindowPresenter [ "override this to set buttons other than the default (Ok, Cancel)." - aDialogWindowPresenter - addButton: 'Ok' do: [ "do nothing" ]; - addButton: 'Cancel' do: [ "do nothing" ] -] - -{ #category : #api } -ComposablePresenter >> prepareWindow: aWindowPresenter [ - "override this to set window values before opening. - You may want to add a menu, a toolbar or a statusbar" + aDialogWindowPresenter + addButton: 'Ok' do: [ :presenter | + presenter triggerOkAction. + presenter close ]; + addButton: 'Cancel' do: [ :presenter | + presenter triggerCancelAction. + presenter close ] ] { #category : #accessing } diff --git a/src/Spec-Core/DialogWindowPresenter.class.st b/src/Spec-Core/DialogWindowPresenter.class.st index b8018286b..8f1781b0d 100644 --- a/src/Spec-Core/DialogWindowPresenter.class.st +++ b/src/Spec-Core/DialogWindowPresenter.class.st @@ -6,8 +6,10 @@ Class { #superclass : #WindowPresenter, #instVars : [ 'contents', - 'toolbar', - 'buttons' + 'buttons', + 'okAction', + 'cancelAction', + 'cancelled' ], #category : #'Spec-Core-Support' } @@ -22,9 +24,11 @@ DialogWindowPresenter class >> adapterName [ DialogWindowPresenter >> addButton: aString do: aBlock [ "Adds button logic to dialog." - buttons - at: aString - put: aBlock + ^ buttons add: (ButtonPresenter new + owner: self; + label: aString; + action: [ aBlock cull: self ]; + yourself) ] { #category : #private } @@ -60,13 +64,13 @@ DialogWindowPresenter >> buttons [ { #category : #api } DialogWindowPresenter >> cancelAction: aBlock [ - ^ self changed: #cancelAction: with: { aBlock } + cancelAction := aBlock ] { #category : #api } DialogWindowPresenter >> cancelled [ - ^ self toolbar cancelled + ^ cancelled ] { #category : #accessing } @@ -79,52 +83,45 @@ DialogWindowPresenter >> contents [ DialogWindowPresenter >> initialize [ super initialize. - - toolbar := OkCancelToolbar new asValueHolder. - toolbar whenChangedDo: [ :t | self changed: #toolbar: with: { t } ]. - - buttons := OrderedDictionary new + buttons := OrderedCollection new. + self initializeDefaultActions ] -{ #category : #api } -DialogWindowPresenter >> okAction: aBlock [ - - ^ self changed: #okAction: with: { aBlock } -] - -{ #category : #api } -DialogWindowPresenter >> okButtonEnabled: aBoolean [ - - self changed: #okButtonEnabled: with: { aBoolean } +{ #category : #initialization } +DialogWindowPresenter >> initializeDefaultActions [ + "default ok/cancel actions. + this is just for backwards compatibility" + self okAction: [ + cancelled := false. + self close ]. + self cancelAction: [ + cancelled := true. + self close ] ] -{ #category : #private } -DialogWindowPresenter >> prepareWindow [ +{ #category : #initialization } +DialogWindowPresenter >> initializeWindow [ - super prepareWindow. + super initializeWindow. self presenter prepareDialogButtons: self ] { #category : #api } -DialogWindowPresenter >> toolbar [ - - ^ toolbar value -] - -{ #category : #api } -DialogWindowPresenter >> toolbar: aBar [ +DialogWindowPresenter >> okAction: aBlock [ - toolbar value: aBar + okAction := aBlock ] { #category : #api } DialogWindowPresenter >> triggerCancelAction [ - self changed: #triggerCancelAction with: #() + cancelAction ifNil: [ ^ self ]. + cancelAction cull: self ] { #category : #api } DialogWindowPresenter >> triggerOkAction [ - self changed: #triggerOkAction with: #() + okAction ifNil: [ ^ self ]. + okAction cull: self ] diff --git a/src/Spec-Core/TextPresenter.class.st b/src/Spec-Core/TextPresenter.class.st index f5178d04c..0b6f0aa78 100644 --- a/src/Spec-Core/TextPresenter.class.st +++ b/src/Spec-Core/TextPresenter.class.st @@ -166,6 +166,14 @@ TextPresenter >> acceptBlock: aBlockWithOneArgument [ actionToPerformHolder value: aBlockWithOneArgument ] +{ #category : #private } +TextPresenter >> acceptText: aString [ + "Used to set the text value comming from the adapter (we do not want to re-send + this value to the adapter, hence we set it 'raw', not triggering events)" + + textHolder rawValue: aString +] + { #category : #api } TextPresenter >> askBeforeDiscardingEdits [ diff --git a/src/Spec-Core/WindowPresenter.class.st b/src/Spec-Core/WindowPresenter.class.st index 91d615539..b05605e02 100644 --- a/src/Spec-Core/WindowPresenter.class.st +++ b/src/Spec-Core/WindowPresenter.class.st @@ -60,7 +60,7 @@ WindowPresenter >> addModelIn: widget withSpec: aSpec [ WindowPresenter >> addModelIn: widget withSpecLayout: aSpec [ self presenter ifNil: [ ^ self ]. - self prepareWindow. + self initializeWindow. self changed: #addModelIn:withSpecLayout: with: { widget. aSpec } @@ -182,6 +182,12 @@ WindowPresenter >> initialize [ centered whenChangedDo: [ :m | self changed: #centered with: #() ] ] +{ #category : #initialization } +WindowPresenter >> initializeWindow [ + + self presenter initializeWindow: self +] + { #category : #testing } WindowPresenter >> isCentered [ @@ -260,12 +266,6 @@ WindowPresenter >> openWithSpecLayout: aSpec [ self updateTitle. ] -{ #category : #private } -WindowPresenter >> prepareWindow [ - - self presenter prepareWindow: self -] - { #category : #accessing } WindowPresenter >> presenter [ diff --git a/src/Spec-Examples/PrepareWindowExample.class.st b/src/Spec-Examples/PrepareWindowExample.class.st index a1fb601ad..9c080ba0c 100644 --- a/src/Spec-Examples/PrepareWindowExample.class.st +++ b/src/Spec-Examples/PrepareWindowExample.class.st @@ -54,6 +54,17 @@ PrepareWindowExample >> initializeWidgets [ BEWARE: This elements will be added just when you will open the presenter as a window or dialog. Otherwise, your component will behave just as another composable presenter.' ] +{ #category : #initialization } +PrepareWindowExample >> initializeWindow: aWindowPresenter [ + "I'm called whenever the component will be displayed in a window (or dialog). + This is usually attained sending #openWithSpec or #openDialogWithSpec." + + aWindowPresenter + menu: (menu := self newMenu); + toolBar: (toolBar := self newToolBar); + statusBar: (statusBar := self newStatusBar) +] + { #category : #'private factory' } PrepareWindowExample >> newFileMenu [ @@ -113,17 +124,6 @@ PrepareWindowExample >> popMessage [ statusBar popMessage ] -{ #category : #api } -PrepareWindowExample >> prepareWindow: aWindowPresenter [ - "I'm called whenever the component will be displayed in a window (or dialog). - This is usually attained sending #openWithSpec or #openDialogWithSpec." - - aWindowPresenter - menu: (menu := self newMenu); - toolBar: (toolBar := self newToolBar); - statusBar: (statusBar := self newStatusBar) -] - { #category : #actions } PrepareWindowExample >> pushMessage [ diff --git a/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st b/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st new file mode 100644 index 000000000..39c4b7c4b --- /dev/null +++ b/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st @@ -0,0 +1,54 @@ +Class { + #name : #MorphicButtonBarAdapter, + #superclass : #AbstractMorphicAdapter, + #category : #'Spec-MorphicAdapters-Base' +} + +{ #category : #accessing } +MorphicButtonBarAdapter class >> defaultHeight [ + + ^ 30 +] + +{ #category : #accessing } +MorphicButtonBarAdapter class >> defaultItemSeparation [ + + ^ 3@0 +] + +{ #category : #factory } +MorphicButtonBarAdapter >> addModelTo: panelMorph [ + + self model items do: [ :each | + panelMorph addMorph: (each buildWithSpec + width: 100; + hResizing: #rigid; + yourself) ] +] + +{ #category : #factory } +MorphicButtonBarAdapter >> buildWidget [ + | panelMorph | + + panelMorph := PanelMorph new + changeTableLayout; + listDirection: self listDirection; + hResizing: #spaceFill; + vResizing: #rigid; + cellInset: self class defaultItemSeparation; + height: self class defaultHeight; + yourself. + + self addModelTo: panelMorph. + + ^ panelMorph +] + +{ #category : #factory } +MorphicButtonBarAdapter >> listDirection [ + + self model isPlaceAtEnd ifTrue: [ ^ #rightToLeft ]. + self model isPlaceAtStart ifTrue: [ ^ #leftToRight ]. + + self error: 'Undefined location to place buttons.' +] diff --git a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st index 676ecdfc6..5a357d378 100644 --- a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st +++ b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st @@ -27,13 +27,20 @@ MorphicDialogWindowAdapter >> addModelIn: widgetToBuild withSpecLayout: aSpec [ self addContent: widgetToBuild mainPanel - toWindow: widgetToBuild + toWindow: widgetToBuild. + + widgetToBuild setToolbarFrom: [ self buildButtonBar ] ] { #category : #factory } -MorphicDialogWindowAdapter >> buildToolBar [ +MorphicDialogWindowAdapter >> buildButtonBar [ + | buttonBar | + buttonBar := ButtonBarPresenter new placeAtEnd. + self model buttons do: [ :buttonPresenter | + buttonBar add: buttonPresenter ]. + ^ buttonBar ] { #category : #factory } @@ -41,26 +48,11 @@ MorphicDialogWindowAdapter >> buildWidget [ ^ SpecDialogWindow new specWidget: self model contents; - setToolbarFrom: [ self model toolbar ]; model: self model; initialize; yourself ] -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> cancelAction: aBlock [ - - ^ self widget - ifNotNil: [:w | w cancelAction: aBlock ] -] - -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> okAction: aBlock [ - - ^ self widget - ifNotNil: [:w | w okAction: aBlock ] -] - { #category : #'spec protocol' } MorphicDialogWindowAdapter >> okButtonEnabled: aBoolean [ @@ -82,21 +74,3 @@ MorphicDialogWindowAdapter >> replace: aMorph with: containerMorph onWindow: aSp by: containerMorph ] - -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> toolbar: aToolbar [ - - self widgetDo: [ :w | w toolbar: aToolbar ] -] - -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> triggerCancelAction [ - - self widget ifNotNil: [:w | w toolbar triggerCancelAction ] -] - -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> triggerOkAction [ - - self widget ifNotNil: [:w | w toolbar triggerOkAction ] -] diff --git a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st index d5065d2d2..a98e442dc 100644 --- a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st +++ b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st @@ -27,14 +27,13 @@ SpecDialogWindow >> cancelled [ { #category : #actions } SpecDialogWindow >> close [ - super close. - self toolbar cancel + super close ] { #category : #actions } SpecDialogWindow >> escapePressed [ - self toolbar triggerCancelAction + self model triggerCancelAction ] { #category : #focus } @@ -114,9 +113,9 @@ SpecDialogWindow >> setToolbarFrom: aBlock [ | newToolbar | newToolbar := aBlock value. + newToolbar owner: self. - toolbar := newToolbar. - newToolbar owner: self + self toolbar: newToolbar ] { #category : #accessing } diff --git a/src/Spec-PolyWidgets/EditableList.class.st b/src/Spec-PolyWidgets/EditableList.class.st index a4b69d4a8..ea138b552 100644 --- a/src/Spec-PolyWidgets/EditableList.class.st +++ b/src/Spec-PolyWidgets/EditableList.class.st @@ -99,12 +99,6 @@ EditableList >> initialize [ okBlock := [ ]. ] -{ #category : #initialization } -EditableList >> initializeDialogWindow: aWindow [ - super initializeDialogWindow: aWindow. - aWindow okAction: [ self performOkAction ] -] - { #category : #initialization } EditableList >> initializePresenter [ super initializePresenter @@ -194,6 +188,16 @@ EditableList >> performOkAction [ okBlock value ] +{ #category : #initialization } +EditableList >> prepareDialogButtons: aWindow [ + + aWindow + addButton: 'Ok' + do: [ :presenter | + self performOkAction. + presenter close ] +] + { #category : #accessing } EditableList >> removeButton [ ^ removeButton From b3b1411a258840279c254f23778b309d85a5880d Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Fri, 23 Nov 2018 12:17:20 +0100 Subject: [PATCH 7/9] using #initializeDialogWindow: instead #prepareDialogButtons: to be more compatible --- src/Spec-Core/ComposablePresenter.class.st | 28 ++++++++----------- src/Spec-Core/DialogWindowPresenter.class.st | 2 +- .../MorphicDialogWindowAdapter.class.st | 9 ++---- src/Spec-PolyWidgets/EditableList.class.st | 20 ++++++------- 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/Spec-Core/ComposablePresenter.class.st b/src/Spec-Core/ComposablePresenter.class.st index 5d169c50b..08f060ea2 100644 --- a/src/Spec-Core/ComposablePresenter.class.st +++ b/src/Spec-Core/ComposablePresenter.class.st @@ -571,9 +571,17 @@ ComposablePresenter >> initialize [ ] { #category : #initialization } -ComposablePresenter >> initializeDialogWindow: aWindow [ - "used to initialize the model in the case of the use into a dialog window" - +ComposablePresenter >> initializeDialogWindow: aDialogWindowPresenter [ + "used to initialize the model in the case of the use into a dialog window. + Override this to set buttons other than the default (Ok, Cancel)." + + aDialogWindowPresenter + addButton: 'Ok' do: [ :presenter | + presenter triggerOkAction. + presenter close ]; + addButton: 'Cancel' do: [ :presenter | + presenter triggerCancelAction. + presenter close ] ] { #category : #initialization } @@ -896,7 +904,6 @@ ComposablePresenter >> openDialogWithSpecLayout: aSpec [ ifFalse: [ self presenterWindow: (DialogWindowPresenter new presenter: self). self presenterWindow openWithSpecLayout: aSpec. - self initializeDialogWindow: self presenterWindow. self presenterWindow updateTitle. self takeKeyboardFocus ]. @@ -943,19 +950,6 @@ ComposablePresenter >> owner: anObject [ owner := anObject. ] -{ #category : #initialization } -ComposablePresenter >> prepareDialogButtons: aDialogWindowPresenter [ - "override this to set buttons other than the default (Ok, Cancel)." - - aDialogWindowPresenter - addButton: 'Ok' do: [ :presenter | - presenter triggerOkAction. - presenter close ]; - addButton: 'Cancel' do: [ :presenter | - presenter triggerCancelAction. - presenter close ] -] - { #category : #accessing } ComposablePresenter >> presenterWindow [ ^ window value diff --git a/src/Spec-Core/DialogWindowPresenter.class.st b/src/Spec-Core/DialogWindowPresenter.class.st index 8f1781b0d..a1f424f01 100644 --- a/src/Spec-Core/DialogWindowPresenter.class.st +++ b/src/Spec-Core/DialogWindowPresenter.class.st @@ -103,7 +103,7 @@ DialogWindowPresenter >> initializeDefaultActions [ DialogWindowPresenter >> initializeWindow [ super initializeWindow. - self presenter prepareDialogButtons: self + self presenter initializeDialogWindow: self ] { #category : #api } diff --git a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st index 5a357d378..2360219f2 100644 --- a/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st +++ b/src/Spec-MorphicAdapters/MorphicDialogWindowAdapter.class.st @@ -9,7 +9,8 @@ Class { { #category : #private } MorphicDialogWindowAdapter >> add: aMorph toWindow: aWindow [ - "do nothing, the morph is already managed" + + aWindow specWidget: aMorph ] { #category : #private } @@ -53,12 +54,6 @@ MorphicDialogWindowAdapter >> buildWidget [ yourself ] -{ #category : #'spec protocol' } -MorphicDialogWindowAdapter >> okButtonEnabled: aBoolean [ - - self widget ifNotNil: [ :w | w toolbar okButton enabled: aBoolean ] -] - { #category : #protocol } MorphicDialogWindowAdapter >> open [ diff --git a/src/Spec-PolyWidgets/EditableList.class.st b/src/Spec-PolyWidgets/EditableList.class.st index ea138b552..3bae95080 100644 --- a/src/Spec-PolyWidgets/EditableList.class.st +++ b/src/Spec-PolyWidgets/EditableList.class.st @@ -99,6 +99,16 @@ EditableList >> initialize [ okBlock := [ ]. ] +{ #category : #initialization } +EditableList >> initializeDialogWindow: aWindow [ + + aWindow + addButton: 'Ok' + do: [ :presenter | + self performOkAction. + presenter close ] +] + { #category : #initialization } EditableList >> initializePresenter [ super initializePresenter @@ -188,16 +198,6 @@ EditableList >> performOkAction [ okBlock value ] -{ #category : #initialization } -EditableList >> prepareDialogButtons: aWindow [ - - aWindow - addButton: 'Ok' - do: [ :presenter | - self performOkAction. - presenter close ] -] - { #category : #accessing } EditableList >> removeButton [ ^ removeButton From 2ee5addbd3dd5549550cdfdca148126665519095 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Tue, 27 Nov 2018 11:53:12 +0100 Subject: [PATCH 8/9] deprecate OCToolbar and child --- src/Spec-Core/OkCancelToolbar.class.st | 7 +++++++ src/Spec-Core/OkToolbar.class.st | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/Spec-Core/OkCancelToolbar.class.st b/src/Spec-Core/OkCancelToolbar.class.st index 5951b8c02..e5d9cad6c 100644 --- a/src/Spec-Core/OkCancelToolbar.class.st +++ b/src/Spec-Core/OkCancelToolbar.class.st @@ -23,6 +23,13 @@ OkCancelToolbar class >> defaultSpec [ yourself ] +{ #category : #deprecation } +OkCancelToolbar class >> isDeprecated [ + "You should use a ToolBarPresenter" + + ^ true +] + { #category : #specs } OkCancelToolbar class >> title [ diff --git a/src/Spec-Core/OkToolbar.class.st b/src/Spec-Core/OkToolbar.class.st index ff89d671a..6c8d98add 100644 --- a/src/Spec-Core/OkToolbar.class.st +++ b/src/Spec-Core/OkToolbar.class.st @@ -21,6 +21,13 @@ OkToolbar class >> defaultSpec [ yourself ] +{ #category : #deprecation } +OkToolbar class >> isDeprecated [ + "You should use a ToolBarPresenter" + + ^ true +] + { #category : #specs } OkToolbar class >> title [ From e5616849052cfc7753749b583ebdba00d53242e0 Mon Sep 17 00:00:00 2001 From: Esteban Lorenzano Date: Tue, 27 Nov 2018 14:52:41 +0100 Subject: [PATCH 9/9] fix focus order for button bar --- src/Spec-Core/ButtonBarPresenter.class.st | 1 + .../MorphicButtonBarAdapter.class.st | 1 + .../SpecDialogWindow.class.st | 18 ++++-------------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/Spec-Core/ButtonBarPresenter.class.st b/src/Spec-Core/ButtonBarPresenter.class.st index f0ac91ac2..9aa78e9c4 100644 --- a/src/Spec-Core/ButtonBarPresenter.class.st +++ b/src/Spec-Core/ButtonBarPresenter.class.st @@ -17,6 +17,7 @@ ButtonBarPresenter class >> adapterName [ { #category : #adding } ButtonBarPresenter >> add: aButtonPresenter [ + aButtonPresenter owner: self. items add: aButtonPresenter ] diff --git a/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st b/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st index 39c4b7c4b..29d25bf5a 100644 --- a/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st +++ b/src/Spec-MorphicAdapters/MorphicButtonBarAdapter.class.st @@ -20,6 +20,7 @@ MorphicButtonBarAdapter class >> defaultItemSeparation [ MorphicButtonBarAdapter >> addModelTo: panelMorph [ self model items do: [ :each | + self model focusOrder add: each. panelMorph addMorph: (each buildWithSpec width: 100; hResizing: #rigid; diff --git a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st index a98e442dc..5e609d69a 100644 --- a/src/Spec-MorphicAdapters/SpecDialogWindow.class.st +++ b/src/Spec-MorphicAdapters/SpecDialogWindow.class.st @@ -24,12 +24,6 @@ SpecDialogWindow >> cancelled [ ^ self toolbar cancelled ] -{ #category : #actions } -SpecDialogWindow >> close [ - - super close -] - { #category : #actions } SpecDialogWindow >> escapePressed [ @@ -65,13 +59,6 @@ SpecDialogWindow >> initialize [ self beResizeable ] -{ #category : #accessing } -SpecDialogWindow >> model: aModel [ - super model: aModel. - aModel presenter focusOrder addLast: toolbar. - toolbar focusOrder addLast: model -] - { #category : #accessing } SpecDialogWindow >> newButtonRow [ @@ -115,7 +102,10 @@ SpecDialogWindow >> setToolbarFrom: aBlock [ newToolbar := aBlock value. newToolbar owner: self. - self toolbar: newToolbar + self toolbar: newToolbar. + + self model presenter focusOrder addLast: toolbar. + toolbar focusOrder addLast: self model ] { #category : #accessing }