--- a/AssistantApplication.st Thu Oct 22 21:07:29 2009 +0200
+++ b/AssistantApplication.st Thu Oct 22 21:24:38 2009 +0200
@@ -13,23 +13,93 @@
!AssistantApplication class methodsFor:'documentation'!
-documentation'
+documentation
+"
+ an easy to use framework for assistant-dialog applications.
+ These are multipage applications, in which the user is able to navigate
+ along achain of pages as specified in the AssistantSpec
+
+ see stx:doc/coding:DemoAssistant for a demo example.
+ see ProjectBuilderAssistantApplication for a concrete example.
+"
! !
!AssistantApplication class methodsFor:'help'!
-hodsFor:'help'
+flyByHelpSpec
+ <resource: #help>
+
+ ^ super flyByHelpSpec addPairsFrom:#(
+
+#backButton
+'Navigate to the previous page %(previousPageInfo)'
+
+#nextButton
+'Navigate to the next page %(nextPageInfo)'
+
+)
! !
!AssistantApplication class methodsFor:'image specs'!
-:'image specs'
+bulletIcon
+ "This resource specification was automatically generated
+ by the ImageEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the ImageEditor may not be able to read the specification."
+
+ "
+ self bulletIcon inspect
+ ImageEditor openOnClass:self andSelector:#bulletIcon
+ Icon flushCachedIcons
+ "
+
+ <resource: #image>
+
+ ^Icon
+ constantNamed:'AssistantApplication class bulletIcon'
+ ifAbsentPut:[(Depth2Image new) width: 16; height: 16; photometric:(#palette); bitsPerSample:(#[2]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@% @@BPA @@P@D@@ @@ @D@@D@A@@A@@ @@ @A@@P@@$@X@@@% @@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 84 84 84 170 170 170 255 255 255]; mask:((Depth1Image new) width: 16; height: 16; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@<@O<@?0G? _>A?8G? O<@?0@<@@@@@@@@@b') ; yourself); yourself]
!
-); yourself]
+leftArrowIcon
+ "This resource specification was automatically generated
+ by the ImageEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the ImageEditor may not be able to read the specification."
+
+ "
+ self leftArrowIcon inspect
+ ImageEditor openOnClass:self andSelector:#leftArrowIcon
+ Icon flushCachedIcons
+ "
+
+ <resource: #image>
+
+ ^Icon
+ constantNamed:'AssistantApplication class leftArrowIcon'
+ ifAbsentPut:[(Depth2Image new) width: 16; height: 16; photometric:(#palette); bitsPerSample:(#[2]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@G@@@@G??<@A???@@G@@@@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 84 84 84 170 170 170 255 255 255]; mask:((Depth1Image new) width: 16; height: 16; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@A@@L@A0@O@A?>O?9??''?>O?8_? <@A0@C@@D@@@@b') ; yourself); yourself]
!
-); yourself]
+rightArrowIcon
+ "This resource specification was automatically generated
+ by the ImageEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the ImageEditor may not be able to read the specification."
+
+ "
+ self rightArrowIcon inspect
+ ImageEditor openOnClass:self andSelector:#rightArrowIcon
+ Icon flushCachedIcons
+ "
+
+ <resource: #image>
+
+ ^Icon
+ constantNamed:'AssistantApplication class rightArrowIcon'
+ ifAbsentPut:[(Depth2Image new) width: 16; height: 16; photometric:(#palette); bitsPerSample:(#[2]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@M@@O??4@C??=@@@@M@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a') ; colorMapFromArray:#[0 0 0 84 84 84 170 170 170 255 255 255]; mask:((Depth1Image new) width: 16; height: 16; photometric:(#blackIs0); bitsPerSample:(#[1]); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@ @C@@N@@<G?8_?1??''?>_?1?>@C0@N@@0@B@@@@b') ; yourself); yourself]
! !
!AssistantApplication class methodsFor:'interface specs'!
@@ -56,7 +126,6 @@
(WindowSpec
label: 'NewApplication'
name: 'NewApplication'
- min: (Point 534 440)
bounds: (Rectangle 0 0 534 440)
menu: mainMenu
)
@@ -88,19 +157,17 @@
collection: (
(SequenceViewSpec
name: 'PagesLabelList'
- layout: (LayoutFrame 0 0 0 0 0 1 0 0.6)
+ layout: (LayoutFrame 0 0 0 0 0 1 0 0.7)
level: 0
enableChannel: false
hasHorizontalScrollBar: true
hasVerticalScrollBar: true
- miniScrollerHorizontal: true
- miniScrollerVertical: true
useIndex: true
sequenceList: pageLabelsInList
)
(HTMLViewSpec
name: 'HTMLBrowser1'
- layout: (LayoutFrame 0 0 0 0.6 0 1 0 1)
+ layout: (LayoutFrame 0 0 0 0.7 0 1 0 1)
level: 0
hasHorizontalScrollBar: true
hasVerticalScrollBar: true
@@ -216,43 +283,31 @@
!AssistantApplication class methodsFor:'menu specs'!
-enableChannel: finishButtonEnabled
- extent: (Point 65 22)
- )
- (ActionButtonSpec
- label: 'Cancel'
- name: 'Button8'
- translateLabel: true
- resizeForLabel: true
- model: doCancel
- extent: (Point 65 22)
- )
- )
-
- )
- )
- )
-
- )
- )
- (LabelSpec
- label: 'Label'
- name: 'Label1'
- layout: (LayoutFrame 1 0 -25 1 -1 1 -1 1)
- level: -1
- translateLabel: true
- labelChannel: infoHolder
- adjust: left
- )
- )
-
- )
- )
-! !
+mainMenu
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+ "
+ MenuEditor new openOnClass:AssistantApplication andSelector:#mainMenu
+ (Menu new fromLiteralArrayEncoding:(AssistantApplication mainMenu)) startUp
+ "
-!AssistantApplication class methodsFor:'required protocol'!
+ <resource: #menu>
-label: 'Exit'
+ ^
+ #(Menu
+ (
+ (MenuItem
+ label: 'File'
+ translateLabel: true
+ submenu:
+ (Menu
+ (
+ (MenuItem
+ label: 'Exit'
itemValue: closeRequest
translateLabel: true
)
@@ -292,53 +347,23 @@
)
! !
+!AssistantApplication class methodsFor:'required protocol'!
+
+assistantSpec
+ "must return a sequenceable collection of assistantPageSpecs - one for each page"
+
+ self subclassResponsibility
+! !
+
!AssistantApplication methodsFor:'actions'!
-)
- (MenuItem
- label: 'Help'
- translateLabel: true
- startGroup: right
- submenu:
- (Menu
- (
- (MenuItem
- label: 'Documentation'
- itemValue: openDocumentation
- translateLabel: true
- )
- (MenuItem
- label: '-'
- )
- (MenuItem
- label: 'About this Application...'
- itemValue: openAboutThisApplication
- translateLabel: true
- )
- )
- nil
- nil
- )
- )
- )
- nil
- nil
- )
-!
+canGoBackward
+ |currentPageSpec previousPageSpec|
-)
- )
- nil
- nil
- )
- )
- )
- nil
- nil
- )
-!
-
-ector) ifFalse:[^ false].
+ "/ see if we are allowed to leave...
+ currentPageSpec := self currentPageSpec.
+ currentPageSpec canLeaveQuerySelector notNil ifTrue:[
+ (self perform:currentPageSpec canLeaveQuerySelector) ifFalse:[^ false].
].
"/ see if we are allowed to enter the next...
@@ -351,27 +376,15 @@
^ true
!
-"/ see if we are allowed to enter the next...
- previousPageSpec := self previousEnabledPageSpec.
- previousPageSpec isNil ifTrue:[^ false].
+canGoForward
+ |currentPageSpec nextPageSpec|
- previousPageSpec canEnterQuerySelector notNil ifTrue:[
- (self perform:previousPageSpec canEnterQuerySelector) ifFalse:[^ false].
- ].
- ^ true
-!
+ self currentPageIndex == self numberOfPages ifTrue:[^ false].
-he next...
- previousPageSpec := self previousEnabledPageSpec.
- previousPageSpec isNil ifTrue:[^ false].
-
- previousPageSpec canEnterQuerySelector notNil ifTrue:[
- (self perform:previousPageSpec canEnterQuerySelector) ifFalse:[^ false].
- ].
- ^ true
-!
-
-lf perform:currentPageSpec canLeaveQuerySelector) ifFalse:[^ false].
+ "/ see if we are allowed to leave...
+ currentPageSpec := self currentPageSpec.
+ currentPageSpec canLeaveQuerySelector notNil ifTrue:[
+ (self perform:currentPageSpec canLeaveQuerySelector) ifFalse:[^ false].
].
"/ see if we are allowed to enter the next...
@@ -382,11 +395,23 @@
(self perform:nextPageSpec canEnterQuerySelector) ifFalse:[^ false].
].
^ true
-! !
+!
+
+doCancel
+ self closeRequest
+!
-!AssistantApplication methodsFor:'aspects'!
+doFinish
+ self closeRequest
+!
-tPageSpec leaveCallbackSelector notNil ifTrue:[
+goBackward
+ |currentPageSpec|
+
+ (self canGoBackward) ifFalse:[^ self].
+
+ currentPageSpec := self currentPageSpec.
+ currentPageSpec leaveCallbackSelector notNil ifTrue:[
self perform:currentPageSpec leaveCallbackSelector
].
@@ -400,28 +425,7 @@
self updateButtonEnableState.
!
-self perform:currentPageSpec leaveCallbackSelector
- ].
-
- self currentPageIndexHolder value:((self indexOfPreviousEnabledPageSpec) max:1).
-
- currentPageSpec := self currentPageSpec.
- currentPageSpec enterCallbackSelector notNil ifTrue:[
- self perform:currentPageSpec enterCallbackSelector
- ].
-
- self updateButtonEnableState.
-!
-
-Spec := self currentPageSpec.
- currentPageSpec enterCallbackSelector notNil ifTrue:[
- self perform:currentPageSpec enterCallbackSelector
- ].
-
- self updateButtonEnableState.
-!
-
-oForward
+goForward
|currentPageSpec|
(self canGoForward) ifFalse:[^ self].
@@ -439,57 +443,131 @@
].
self updateButtonEnableState.
+! !
+
+!AssistantApplication methodsFor:'aspects'!
+
+assistantSpec
+ ^ self class assistantSpec
!
-otNil ifTrue:[
- self perform:currentPageSpec leaveCallbackSelector
- ].
-
- self currentPageIndexHolder value:(self indexOfNextEnabledPageSpec).
+backButtonEnabled
+ <resource: #uiAspect>
- currentPageSpec := self currentPageSpec.
- currentPageSpec enterCallbackSelector notNil ifTrue:[
- self perform:currentPageSpec enterCallbackSelector
+ backButtonEnabled isNil ifTrue:[
+ backButtonEnabled := false asValue.
].
-
- self updateButtonEnableState.
+ ^ backButtonEnabled.
!
-Nil ifTrue:[
- self perform:currentPageSpec enterCallbackSelector
- ].
+backButtonLabelHolder
+ <resource: #uiAspect>
- self updateButtonEnableState.
-!
-
-assistantSpec
+ backButtonLabelHolder isNil ifTrue:[
+ backButtonLabelHolder := self backButtonLabel asValue.
+ ].
+ ^ backButtonLabelHolder.
!
-!
+backButtonVisible
+ <resource: #uiAspect>
-backButtonLabelHolder.
+ backButtonVisible isNil ifTrue:[
+ backButtonVisible := true asValue.
+ ].
+ ^ backButtonVisible.
!
-ButtonVisible.
-!
+currentPageIndexHolder
+ <resource: #uiAspect>
-IndexHolder onChangeSend:#updateCanvas to:self
+ currentPageIndexHolder isNil ifTrue:[
+ currentPageIndexHolder := 1 asValue.
+ currentPageIndexHolder onChangeSend:#updateCanvas to:self
].
^ currentPageIndexHolder.
!
-il ifTrue:[
+currentPageInfoHTMLHolder
+ <resource: #uiAspect>
+
+ currentPageInfoHTMLHolder isNil ifTrue:[
currentPageInfoHTMLHolder := ValueHolder new.
].
^ currentPageInfoHTMLHolder.
!
-True:[
+currentPageSpecHolder
+ <resource: #uiAspect>
+
+ currentPageSpecHolder isNil ifTrue:[
currentPageSpecHolder := nil asValue.
].
^ currentPageSpecHolder.
!
+finishButtonEnabled
+ <resource: #uiAspect>
+
+ finishButtonEnabled isNil ifTrue:[
+ finishButtonEnabled := false asValue.
+ ].
+ ^ finishButtonEnabled.
+!
+
+finishButtonVisible
+ <resource: #uiAspect>
+
+ finishButtonVisible isNil ifTrue:[
+ finishButtonVisible := false asValue.
+ ].
+ ^ finishButtonVisible.
+!
+
+forwardButtonEnabled
+ <resource: #uiAspect>
+
+ forwardButtonEnabled isNil ifTrue:[
+ forwardButtonEnabled := false asValue.
+ ].
+ ^ forwardButtonEnabled.
+!
+
+forwardButtonVisible
+ <resource: #uiAspect>
+
+ forwardButtonVisible isNil ifTrue:[
+ forwardButtonVisible := true asValue.
+ ].
+ ^ forwardButtonVisible.
+!
+
+nextButtonLabelHolder
+ <resource: #uiAspect>
+
+ nextButtonLabelHolder isNil ifTrue:[
+ nextButtonLabelHolder := self nextButtonLabel asValue.
+ ].
+ ^ nextButtonLabelHolder.
+!
+
+pageInfoHolder
+ <resource: #uiAspect>
+
+ pageInfoHolder isNil ifTrue:[
+ pageInfoHolder := nil asValue.
+ ].
+ ^ pageInfoHolder.
+!
+
+pageLabelsInList
+ pageLabelsInList isNil ifTrue:[
+ pageLabelsInList := List new.
+ pageLabelsInList contents:(self pageLabelsInListWithBullet).
+ ].
+ ^ pageLabelsInList
+!
+
pageLabelsInListWithBullet
|newList|
@@ -514,37 +592,15 @@
!AssistantApplication methodsFor:'help'!
-pageInfoHolder isNil ifTrue:[
- pageInfoHolder := nil asValue.
- ].
- ^ pageInfoHolder.
-!
+flyByHelpTextForKey:aKey
+ <resource: #help>
-pageInfoHolder isNil ifTrue:[
- pageInfoHolder := nil asValue.
- ].
- ^ pageInfoHolder.
-! !
-
-!AssistantApplication methodsFor:'initialization & release'!
+ |text bindings nextSpec prevSpec|
-ith:(TextView defaultSelectionForegroundColor) on:(TextView defaultSelectionBackgroundColor) );
- icon:(self class rightArrowIcon);
- image2:(self class leftArrowIcon)
- ] ifFalse:[
- (self isPageEnabledAtIndex:index) ifFalse:[
- entry colorizeAllWith:(Button defaultDisabledForegroundColor) "Color grey".
- ] ifTrue:[
- entry
- ].
- ].
- ].
- ^ newList
-! !
+ text := super flyByHelpTextForKey:aKey.
-!AssistantApplication methodsFor:'look'!
-
-revSpec := self previousEnabledPageSpec.
+ nextSpec := self nextEnabledPageSpec.
+ prevSpec := self previousEnabledPageSpec.
bindings := Dictionary new.
bindings
@@ -555,14 +611,15 @@
put:(nextSpec notNil ifTrue:[ '"',nextSpec pageTitle,'"' ] ifFalse:['']).
^ self resources string:text withArgs:bindings.
-!
+! !
-xtSpec notNil ifTrue:[ '"',nextSpec pageTitle,'"' ] ifFalse:['']).
+!AssistantApplication methodsFor:'initialization & release'!
- ^ self resources string:text withArgs:bindings.
-!
+postBuildWith:aBuilder
+ |maxCanvasExtent|
-self updateCanvas.
+ super postBuildWith:aBuilder.
+ self updateCanvas.
maxCanvasExtent := (self assistantSpec
collect:[:eachPageSpec |
@@ -578,58 +635,48 @@
self window extent:(maxCanvasExtent + (200 @ 40)).
! !
-!AssistantApplication methodsFor:'private'!
-
-|windowSpecSelector specArray windowSpec|
-
- windowSpecSelector := eachPageSpec windowSpecSelector.
- specArray := self perform:windowSpecSelector ifNotUnderstood:[self class perform:windowSpecSelector].
- windowSpec := specArray decodeAsLiteralArray.
- windowSpec window bounds extent.
- ]
- ) max.
+!AssistantApplication methodsFor:'look'!
- self window extent:(maxCanvasExtent + (200 @ 40)).
-!
-
-[self class perform:windowSpecSelector].
- windowSpec := specArray decodeAsLiteralArray.
- windowSpec window bounds extent.
- ]
- ) max.
-
- self window extent:(maxCanvasExtent + (200 @ 40)).
+backButtonLabel
+ ^ LabelAndIcon
+ label:(resources string:'Back')
+ icon:(self backButtonEnabled value
+ ifTrue:[ToolbarIconLibrary leftArrow24x24Icon]
+ ifFalse:[ToolbarIconLibrary leftArrow24x24disabledIcon])
!
-windowSpec := specArray decodeAsLiteralArray.
- windowSpec window bounds extent.
- ]
- ) max.
-
- self window extent:(maxCanvasExtent + (200 @ 40)).
+nextButtonLabel
+ ^ LabelAndTwoIcons new
+ string:(resources string:'Next');
+ image2:(self forwardButtonEnabled value
+ ifTrue:[ToolbarIconLibrary rightArrow24x24Icon]
+ ifFalse:[ToolbarIconLibrary rightArrow24x24disabledIcon])
!
-windowSpec window bounds extent.
- ]
- ) max.
+pageLabels
+ ^ self assistantSpec collect:[:specEntry | specEntry pageTitle].
+! !
- self window extent:(maxCanvasExtent + (200 @ 40)).
-!
+!AssistantApplication methodsFor:'private'!
-Arrow24x24disabledIcon])
-!
+canFinish
+ |pageIndex pageSpec|
-ication methodsFor:'private'
-!
-
-isNil
+ pageIndex := self currentPageIndexHolder value.
+ pageSpec := self assistantSpec at:pageIndex.
+ ^ pageSpec canLeaveQuerySelector isNil
or:[ self perform:pageSpec canLeaveQuerySelector ]
!
-elf assistantSpec at:(self currentPageIndex).
+currentPageIndex
+ ^ self currentPageIndexHolder value
!
-c
+currentPageSpec
+ ^ self assistantSpec at:(self currentPageIndex).
+!
+
+indexOfNextEnabledPageSpec
|delta currentPageIndex|
currentPageIndex := self currentPageIndex.
@@ -646,37 +693,65 @@
^ nil
!
-ndex := self currentPageIndex.
+indexOfPreviousEnabledPageSpec
+ |delta currentPageIndex|
+
+ currentPageIndex := self currentPageIndex.
delta := 1.
[
- (currentPageIndex + delta) <= (self numberOfPages)
- and:[ (self isPageEnabledAtIndex:(currentPageIndex + delta)) not ]
+ (currentPageIndex - delta) > 0
+ and:[ (self isPageEnabledAtIndex:(currentPageIndex - delta)) not ]
] whileTrue:[
delta := delta + 1.
].
- (currentPageIndex + delta) <= (self numberOfPages) ifTrue:[
- ^ (currentPageIndex + delta).
+ (currentPageIndex - delta) > 0 ifTrue:[
+ ^ (currentPageIndex - delta).
].
^ nil
!
-tPageIndex + delta)) not ]
- ] whileTrue:[
- delta := delta + 1.
- ].
- (currentPageIndex + delta) <= (self numberOfPages) ifTrue:[
- ^ (currentPageIndex + delta).
- ].
- ^ nil
+isPageEnabledAtIndex:index
+ |isEnabledSelector|
+
+ isEnabledSelector := (self assistantSpec at:index) isEnabledQuerySelector.
+ ^ isEnabledSelector isNil or:[ (self perform:isEnabledSelector) ]
+!
+
+nextEnabledPageSpec
+ |index|
+
+ index := self indexOfNextEnabledPageSpec.
+ index isNil ifTrue:[^ nil].
+ ^ self assistantSpec at:index.
+!
+
+nextPageSpec
+ ^ self assistantSpec at:(self currentPageIndex + 1).
+!
+
+numberOfPages
+ ^ self assistantSpec size
+!
+
+previousEnabledPageSpec
+ |index|
+
+ index := self indexOfPreviousEnabledPageSpec.
+ index isNil ifTrue:[^ nil].
+ ^ self assistantSpec at:index.
+!
+
+previousPageSpec
+ ^ self assistantSpec at:(self currentPageIndex - 1).
! !
!AssistantApplication methodsFor:'update'!
-.
- (currentPageIndex + delta) <= (self numberOfPages) ifTrue:[
- ^ (currentPageIndex + delta).
- ].
- ^ nil
+updateButtonEnableState
+ self backButtonEnabled value:(self canGoBackward).
+ self forwardButtonEnabled value:(self canGoForward).
+ self backButtonLabelHolder value:(self backButtonLabel).
+ self nextButtonLabelHolder value:(self nextButtonLabel).
!
updateCanvas
@@ -705,5 +780,5 @@
!AssistantApplication class methodsFor:'documentation'!
version_CVS
- ^ '$Header: /cvs/stx/stx/libwidg2/AssistantApplication.st,v 1.10 2009-10-22 19:07:29 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libwidg2/AssistantApplication.st,v 1.11 2009-10-22 19:24:38 cg Exp $'
! !