"{ Package: 'stx:libwidg2' }"
ApplicationModel subclass:#AssistantApplication
instanceVariableNames:'currentPageSpecHolder backButtonEnabled forwardButtonEnabled
backButtonVisible forwardButtonVisible finishButtonVisible
finishButtonEnabled currentPageInfoHTMLHolder
currentPageIndexHolder backButtonLabelHolder
nextButtonLabelHolder pageLabelsInList'
classVariableNames:''
poolDictionaries:''
category:'Views-DialogBoxes'
!
!AssistantApplication class methodsFor:'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'!
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'!
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]
!
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]
!
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'!
windowSpec
"This resource specification was automatically generated
by the UIPainter of ST/X."
"Do not manually edit this!! If it is corrupted,
the UIPainter may not be able to read the specification."
"
UIPainter new openOnClass:AssistantApplication andSelector:#windowSpec
AssistantApplication new openInterface:#windowSpec
AssistantApplication open
"
<resource: #canvas>
^
#(FullSpec
name: windowSpec
window:
(WindowSpec
label: 'NewApplication'
name: 'NewApplication'
bounds: (Rectangle 0 0 534 440)
menu: mainMenu
)
component:
(SpecCollection
collection: (
(MenuPanelSpec
name: 'ToolBar1'
layout: (LayoutFrame 0 0 0 0 0 1 40 0)
menu: toolbarMenu
textDefault: true
)
(ViewSpec
name: 'Box1'
layout: (LayoutFrame 0 0 40 0 0 1 -25 1)
component:
(SpecCollection
collection: (
(VariableHorizontalPanelSpec
name: 'VariableHorizontalPanel1'
layout: (LayoutFrame 0 0 0 0 0 1 -40 1)
component:
(SpecCollection
collection: (
(SequenceViewSpec
name: 'List1'
level: 0
enableChannel: false
hasHorizontalScrollBar: true
hasVerticalScrollBar: true
useIndex: true
sequenceList: pageLabelsInList
)
(SubCanvasSpec
name: 'SubCanvas1'
hasHorizontalScrollBar: false
hasVerticalScrollBar: false
miniScrollerHorizontal: false
miniScrollerVertical: false
specHolder: currentPageSpecHolder
createNewBuilder: false
)
)
)
handles: (Any 0.5 1.0)
)
(HorizontalPanelViewSpec
name: 'ButtonPanel1'
layout: (LayoutFrame 0 0 -40 1 0 0.5 0 1)
horizontalLayout: centerMax
verticalLayout: center
horizontalSpace: 3
verticalSpace: 3
component:
(SpecCollection
collection: (
(ActionButtonSpec
label: 'Back'
name: 'Button1'
activeHelpKey: backButton
visibilityChannel: backButtonVisible
translateLabel: true
labelChannel: backButtonLabelHolder
model: goBackward
enableChannel: backButtonEnabled
extent: (Point 132 22)
)
(ActionButtonSpec
label: 'Next'
name: 'Button2'
activeHelpKey: nextButton
visibilityChannel: forwardButtonVisible
translateLabel: true
labelChannel: nextButtonLabelHolder
model: goForward
enableChannel: forwardButtonEnabled
extent: (Point 132 22)
)
)
)
)
(HorizontalPanelViewSpec
name: 'ButtonPanel2'
layout: (LayoutFrame 0 0.5 -40 1 0 1 0 1)
horizontalLayout: centerMax
verticalLayout: center
horizontalSpace: 3
verticalSpace: 3
ignoreInvisibleComponents: false
component:
(SpecCollection
collection: (
(ActionButtonSpec
label: 'Finish'
name: 'Button7'
visibilityChannel: finishButtonVisible
translateLabel: true
resizeForLabel: true
model: doFinish
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
)
)
)
)
! !
!AssistantApplication class methodsFor:'menu specs'!
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
"
<resource: #menu>
^
#(Menu
(
(MenuItem
label: 'File'
translateLabel: true
submenu:
(Menu
(
(MenuItem
label: 'Exit'
itemValue: closeRequest
translateLabel: true
)
)
nil
nil
)
)
(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
)
! !
!AssistantApplication class methodsFor:'required protocol'!
assistantSpec
"must return a sequenceable collection of assistantPageSpecs - one for each page"
self subclassResponsibility
! !
!AssistantApplication methodsFor:'actions'!
canGoBackward
|currentPageSpec previousPageSpec|
"/ 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...
previousPageSpec := self previousEnabledPageSpec.
previousPageSpec isNil ifTrue:[^ false].
previousPageSpec canEnterQuerySelector notNil ifTrue:[
(self perform:previousPageSpec canEnterQuerySelector) ifFalse:[^ false].
].
^ true
!
canGoForward
|currentPageSpec nextPageSpec|
self currentPageIndex == self numberOfPages ifTrue:[^ 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...
nextPageSpec := self nextEnabledPageSpec.
nextPageSpec isNil ifTrue:[^ false].
nextPageSpec canEnterQuerySelector notNil ifTrue:[
(self perform:nextPageSpec canEnterQuerySelector) ifFalse:[^ false].
].
^ true
!
doCancel
self closeRequest
!
doFinish
self closeRequest
!
goBackward
|currentPageSpec|
(self canGoBackward) ifFalse:[^ self].
currentPageSpec := self currentPageSpec.
currentPageSpec leaveCallbackSelector notNil ifTrue:[
self perform:currentPageSpec leaveCallbackSelector
].
self currentPageIndexHolder value:((self indexOfPreviousEnabledPageSpec) max:1).
currentPageSpec := self currentPageSpec.
currentPageSpec enterCallbackSelector notNil ifTrue:[
self perform:currentPageSpec enterCallbackSelector
].
self updateButtonEnableState.
!
goForward
|currentPageSpec|
(self canGoForward) ifFalse:[^ self].
currentPageSpec := self currentPageSpec.
currentPageSpec leaveCallbackSelector notNil ifTrue:[
self perform:currentPageSpec leaveCallbackSelector
].
self currentPageIndexHolder value:(self indexOfNextEnabledPageSpec).
currentPageSpec := self currentPageSpec.
currentPageSpec enterCallbackSelector notNil ifTrue:[
self perform:currentPageSpec enterCallbackSelector
].
self updateButtonEnableState.
! !
!AssistantApplication methodsFor:'aspects'!
assistantSpec
^ self class assistantSpec
!
backButtonEnabled
<resource: #uiAspect>
backButtonEnabled isNil ifTrue:[
backButtonEnabled := false asValue.
].
^ backButtonEnabled.
!
backButtonLabelHolder
<resource: #uiAspect>
backButtonLabelHolder isNil ifTrue:[
backButtonLabelHolder := self backButtonLabel asValue.
].
^ backButtonLabelHolder.
!
backButtonVisible
<resource: #uiAspect>
backButtonVisible isNil ifTrue:[
backButtonVisible := true asValue.
].
^ backButtonVisible.
!
currentPageIndexHolder
<resource: #uiAspect>
currentPageIndexHolder isNil ifTrue:[
currentPageIndexHolder := 1 asValue.
currentPageIndexHolder onChangeSend:#updateCanvas to:self
].
^ currentPageIndexHolder.
!
currentPageInfoHTMLHolder
<resource: #uiAspect>
currentPageInfoHTMLHolder isNil ifTrue:[
currentPageInfoHTMLHolder := ValueHolder new.
].
^ currentPageInfoHTMLHolder.
!
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.
!
pageLabelsInList
pageLabelsInList isNil ifTrue:[
pageLabelsInList := List new.
pageLabelsInList contents:(self pageLabelsInListWithBullet).
].
^ pageLabelsInList
!
pageLabelsInListWithBullet
|newList|
newList := self pageLabels.
newList := newList with:(1 to:newList size)
collect:[:entry :index |
index == self currentPageIndex ifTrue:[
LabelAndTwoIcons new
string:entry;
icon:(self class rightArrowIcon);
image2:(self class leftArrowIcon)
] ifFalse:[
(self isPageEnabledAtIndex:index) ifFalse:[
entry asText colorizeAllWith:(Button defaultDisabledForegroundColor) "Color grey".
] ifTrue:[
entry
].
].
].
^ newList
! !
!AssistantApplication methodsFor:'help'!
flyByHelpTextForKey:aKey
<resource: #help>
|text bindings nextSpec prevSpec|
text := super flyByHelpTextForKey:aKey.
nextSpec := self nextEnabledPageSpec.
prevSpec := self previousEnabledPageSpec.
bindings := Dictionary new.
bindings
at:#'previousPageInfo'
put:(prevSpec notNil ifTrue:[ '"',prevSpec pageTitle,'"' ] ifFalse:['']).
bindings
at:#'nextPageInfo'
put:(nextSpec notNil ifTrue:[ '"',nextSpec pageTitle,'"' ] ifFalse:['']).
^ self resources string:text withArgs:bindings.
! !
!AssistantApplication methodsFor:'initialization & release'!
postBuildWith:aBuilder
|maxCanvasExtent|
super postBuildWith:aBuilder.
self updateCanvas.
maxCanvasExtent := (self assistantSpec
collect:[:eachPageSpec |
|windowSpecSelector specArray windowSpec|
windowSpecSelector := eachPageSpec windowSpecSelector.
specArray := self perform:windowSpecSelector ifNotUnderstood:[self class perform:windowSpecSelector].
windowSpec := specArray decodeAsLiteralArray.
windowSpec window bounds extent.
]
) max.
self window extent:(maxCanvasExtent + (200 @ 40)).
! !
!AssistantApplication methodsFor:'look'!
backButtonLabel
^ LabelAndIcon
label:(resources string:'Back')
icon:(self backButtonEnabled value
ifTrue:[ToolbarIconLibrary leftArrow24x24Icon]
ifFalse:[ToolbarIconLibrary leftArrow24x24disabledIcon])
!
nextButtonLabel
^ LabelAndTwoIcons new
string:(resources string:'Next');
image2:(self forwardButtonEnabled value
ifTrue:[ToolbarIconLibrary rightArrow24x24Icon]
ifFalse:[ToolbarIconLibrary rightArrow24x24disabledIcon])
!
pageLabels
^ self assistantSpec collect:[:specEntry | specEntry pageTitle].
! !
!AssistantApplication methodsFor:'private'!
canFinish
|pageIndex pageSpec|
pageIndex := self currentPageIndexHolder value.
pageSpec := self assistantSpec at:pageIndex.
^ pageSpec canLeaveQuerySelector isNil
or:[ self perform:pageSpec canLeaveQuerySelector ]
!
currentPageIndex
^ self currentPageIndexHolder value
!
currentPageSpec
^ self assistantSpec at:(self currentPageIndex).
!
indexOfNextEnabledPageSpec
|delta currentPageIndex|
currentPageIndex := self currentPageIndex.
delta := 1.
[
(currentPageIndex + delta) <= (self numberOfPages)
and:[ (self isPageEnabledAtIndex:(currentPageIndex + delta)) not ]
] whileTrue:[
delta := delta + 1.
].
(currentPageIndex + delta) <= (self numberOfPages) ifTrue:[
^ (currentPageIndex + delta).
].
^ nil
!
indexOfPreviousEnabledPageSpec
|delta currentPageIndex|
currentPageIndex := self currentPageIndex.
delta := 1.
[
(currentPageIndex - delta) > 0
and:[ (self isPageEnabledAtIndex:(currentPageIndex - delta)) not ]
] whileTrue:[
delta := delta + 1.
].
(currentPageIndex - delta) > 0 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).
!
updateButtonEnableState
self backButtonEnabled value:(self canGoBackward).
self forwardButtonEnabled value:(self canGoForward).
self backButtonLabelHolder value:(self backButtonLabel).
self nextButtonLabelHolder value:(self nextButtonLabel).
!
updateCanvas
|pageIndex pageSpec sel uiSpec|
pageIndex := self currentPageIndex.
pageSpec := self currentPageSpec.
sel := pageSpec windowSpecSelector.
uiSpec := self perform:sel ifNotUnderstood:[ self class perform:sel ].
self pageLabelsInList contents:(self pageLabelsInListWithBullet).
self currentPageSpecHolder value:uiSpec.
self window label:(pageSpec pageTitle).
self finishButtonVisible value:(pageIndex == self numberOfPages).
self backButtonEnabled value:(pageIndex > 1).
self forwardButtonEnabled value:(pageIndex < self numberOfPages).
self finishButtonEnabled value:(pageIndex == self numberOfPages and:[ self canFinish ]).
self backButtonLabelHolder value:(self backButtonLabel).
self nextButtonLabelHolder value:(self nextButtonLabel).
! !
!AssistantApplication class methodsFor:'documentation'!
version_CVS
^ '$Header: /cvs/stx/stx/libwidg2/AssistantApplication.st,v 1.7 2009-10-21 13:32:50 cg Exp $'
! !