I am a class representing a graphical element of a seaside application. A component has state (instance variables, that might be backtracked using #registerObjectForBacktracking:), behavior decorations, children and an appearance that is specified in #renderContentOn:. A component might chose to display another component with #call:. Child Components: It is common for a component to display instances of other components while rendering itself. It does this by passing them into the #render: method of WAHtmlRenderer. For example, this #renderContentOn: method simply renders a heading and then displays a counter component immediately below it: renderContentOn: html html heading: 'My Counter' level: 3. html render: myCounter. It's important that you use #render:, rather than directly calling the #renderContentOn: method of the subcomponent. The following is *not* correct: renderContentOn: html html heading: 'My Counter' level: 3. myCounter renderContentOn: html. "DON'T DO THIS". These subcomponents are usually instance variables of the component that is "embedding" them. They are commonly created as part of the components #initialize method: initialize myCounter := WACounter new. They may also be stored in a collection. One fairly common pattern is to keep a lazily initialized dictionary of subcomponents that match a collection of model items. For example, if you wanted a BudgetItemRow subcomponent for each member of budgetItems, you might do something like this: initialize budgetRows := Dictionary new. rowForItem: anItem ^budgetRows at: anItem ifAbsentPut: [ BudgetItemRow item: anItem ]. renderContentOn: html self budgetItems do: [ :each | html render: (self rowForItem: each) ] separatedBy: [ html horizontalLine ]. Each parent component *must* implement a #children method that returns a collection of all of the subcomponents that it might display on the next render. For the above two examples, #children might look like this: children ^Array with: myCounter or this: children ^self budgetItems collect: [ :each | self rowForItem: each ]. Call/Answer: If a subcomponent makes a #call: to another component, that component will appear in place of the subcomponent. In the first example, if myCounter made a #call: to DateSelector, that DateSelector would appear in the context of the counter's parent, with the 'My Counter' heading above it. Since a subcomponent has not been #call:'d, in general #answer: is a no-op. However, the parent may attach an #onAnswer: block to the subcomponent to be notified if it sends #answer:. This allows one component to be used both from #call: and through embedding. For example: initialize dateSelector := WADateSelector new onAnswer: [ :date | self dateChosen: date ].
ProtoObjectObjectWAPresenterWAComponent
- FactorialTableComponent
- FileInComponent
- FlatStacieMainView
- GoodsServerConsole
- GoodsServerView
- GraphView
- GuestbookEntryRemoval
- GuestbookView
- ImageCatalogView
- KidsPublisherHome
- MISPublisher
- PageUploader
- PublisherFileList
- ReaderBookList
- ReaderReviewPage
- ReviewerBookList
- SCBrowserHistoryView
- SCComponent
- SCFrontDoor
- SCMenu
- SCMenuTestClient
- SCMenuTestClientChild
- SCTestComponent1
- SCTestComponent2
- SCTestComponent3
- SCTestComponent4
- SCTestComponent5
- SCTestRunner
- SelectorWithCalendar
- SelectorWithCalendarExample
- ShoppingListAdviceView
- WAAlphabeticBatchedList
- WABatchSelection
- WABatchTest
- WABatchedList
- WABrowser
- WACacheTest
- WACallbackTest
- WACanvasTest
- WAChangePassword
- WAClosureTest
- WAConfigurationBrowser
- WAConfigurationEditor
- WACounter
- WADateSelector
- WADateTable
- WADispatcherEditor
- WAEmailConfirmation
- WAEncodingTest
- WAErrorTest
- WAExampleBrowser
- WAExpiryTest
- WAFormDialog
- WAFrameComponent
- WAHalo
- WAHomeTest
- WAHtmlTest
- WAImageTest
- WAInputDialog
- WAInputTest
- WAInspector
- WALibraryBrowser
- WALiveRequestTest
- WALoginDialog
- WAMemoryUse
- WAMiniCalendar
- WAMultiCounter
- WANavigation
- WANavigationBar
- WAParentTest
- WAPath
- WAReport
- WAScreenshot
- WASelection
- WAStore
- WAStoreCartConfirmation
- WAStoreCartView
- WAStoreFillCart
- WAStoreInfo
- WAStoreItemView
- WATask
- WATaskTest
- WATrail
- WAUploadTest
- WAVersionUploader
- WAWalkback
| decoration |
| decoration |
|---|
| as yet unclassified |
|---|
| addDecoration: newDecoration |
| prev dec | prev _ nil. dec _ self decoration. [dec ~~ self and: [self decoration: dec shouldWrap: newDecoration]] whileTrue: [prev _ dec. dec _ dec owner]. newDecoration owner: dec. prev ifNil: [self decoration: newDecoration] ifNotNil: [prev owner: newDecoration]. ^ newDecoration |
| allDecorationsDo: aBlock |
| ea | ea _ self decoration. [ea notNil and: [ea ~~ self]] whileTrue: [aBlock value: ea. ea _ ea owner] |
| authenticateWith: anAuthenticator during: aBlock |
^ self decorateWith: (WABasicAuthentication new authenticator: anAuthenticator) during: aBlock |
| children |
"This method is really important. It should return a collection of all subcomponents of the current component that will be rendered in #renderContentOn:. Components that are displayed using #call: are *not* children." ^ #() |
| childrenDo: aBlock |
self children do: [:ea | ea ifNotNil: [aBlock value: ea]] |
| decorateWith: aDecoration during: aBlock |
| val | self addDecoration: aDecoration. val _ aBlock value. self removeDecoration: aDecoration. ^ val |
| decoration |
decoration ifNil: [decoration _ WAStateHolder new contents: self]. ^ decoration contents |
| decoration: aDecoration |
decoration contents: aDecoration |
| decoration: oldDecoration shouldWrap: newDecoration |
^ (oldDecoration isGlobal and: [newDecoration isGlobal not]) or: [oldDecoration isDelegation and: [newDecoration isLocal]] |
| decorationChainDo: aBlock |
aBlock value: self decoration |
| delegations |
| delegations | delegations _ OrderedCollection new. self allDecorationsDo: [:ea | ea isDelegation ifTrue: [delegations add: ea]]. ^ delegations |
| home |
self delegations do: [:ea | self removeDecoration: ea] |
| initializeDecoration |
decoration _ WAStateHolder new contents: self |
| nextPresentersDo: aBlock |
self childrenDo: [:ea | ea decorationChainDo: aBlock] |
| removeDecoration: aDecoration |
| dec | dec _ self decoration. dec = aDecoration ifTrue: [self decoration: dec owner. ^ self]. [dec notNil] whileTrue: [dec owner = aDecoration ifTrue: [dec owner: aDecoration owner. ^ self] ifFalse: [dec _ dec owner]] |
| renderOn: aRenderer |
"Do not override this methods on your component, override instead #renderContentOn: and in addition to not invoke directly renderContentOn: on subcomponent in such method but use instead html render: subcomponent." self decorationChainDo: [ :each | each renderWithContext: aRenderer context ]. |
| visiblePresentersDo: aBlock |
self decorationChainDo: [:ea | ea withNextPresentersDo: aBlock] |
| call/answer |
|---|
| answer |
self answer: self |
| answer: anObject |
self decorationChainDo: [:ea | ea handleAnswer: anObject] |
| call: aComponent |
^ AnswerContinuation currentDo: [:cc | self show: aComponent onAnswer: cc] |
| handleAnswer: anObject |
^ false |
| onAnswer: aBlock |
^ self addDecoration: (WAAnswerHandler new block: aBlock) |
| show: aComponent |
self show: aComponent onAnswer: [:v] |
| show: aComponent onAnswer: aBlock |
| delegation event | delegation _ WADelegation new delegate: aComponent. event _ nil. event _ aComponent onAnswer: [:v | delegation remove. event remove. aBlock value: v]. self addDecoration: delegation. WARenderNotification raiseSignal |
| convenience |
|---|
| activeComponent |
self visiblePresentersDo: [:ea | ea isDecoration ifFalse: [^ ea]] |
| addMessage: aString |
self addDecoration: (WAMessageDecoration new message: aString) |
| confirm: aString |
^ self call: (WAYesOrNoDialog new addMessage: aString) |
| inform: aString |
self call: (WAFormDialog new addMessage: aString) |
| isolate: aBlock |
|txn val | txn _ WATransaction new. val _ self decorateWith: txn during: aBlock. txn close. ^ val |
| request: aString |
^ self request: aString default: '' |
| request: aString default: initialString |
^ self request: aString label: nil default: initialString |
| request: requestString label: labelString |
^ self request: requestString label: labelString default: '' |
| request: requestString label: labelString default: initialString |
^ self call: ((WAInputDialog new label: labelString; default: initialString) addMessage: requestString) |
| validateWith: aBlock |
self addDecoration: (WAValidationDecoration new validateWith: aBlock) |
| rendering |
|---|
| script |
^ nil |
| style |
^ nil |
| as yet unclassified |
|---|
| applicationWithPath: aString |
| app | app _ WAApplication path: aString. app configuration addAncestor: WARenderLoopConfiguration localConfiguration. app preferenceAt: #rootComponent put: self. ^ app |
| canBeRoot |
"When returning true, the component can be registered as a standalone application from the config interface." ^ false |
| new |
^ self basicNew initializeDecoration initialize |
| registerAsApplication: appName |
|app| app _ self applicationWithPath: appName. WADispatcher default registerEntryPoint: app at: appName. ^ app |
| registerAsAuthenticatedApplication: appName |
| app user password |
app _ self registerAsApplication: appName.
app configuration addAncestor: WAAuthConfiguration localConfiguration.
[user _ FillInTheBlank
request: ('Please choose an administrator\username for the application ''', appName asString , '''') withCRs.
user = ''] whileTrue.
[password _ FillInTheBlank
request: 'Please enter a password for ', user printString.
password = ''] whileTrue.
app preferenceAt: #login put: user.
app preferenceAt: #password put: password.
^ app
|