1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027 |
- Smalltalk createPackage: 'Moka-Views'!
- MKSingleAspectView subclass: #MKButtonView
- instanceVariableNames: 'default label icon'
- package: 'Moka-Views'!
- I am a push button view. My default controller is `MKButtonController`.
- My controller must answer to `#onPressed`.
- - Instances can be set a `default` button
- - Use `#label:` to set the label string!
- cssClass
- ^ String streamContents: [ :stream |
- stream << super cssClass << ' mk_button'.
- self isDefault
- ifTrue: [ stream << ' default' ] ]
- default
- ^ default
- default: aBoolean
- default := aBoolean
- icon
- ^ icon
- icon: aString
- icon := aString
- label
- ^ label ifNil: [ self defaultLabel ]
- label: aString
- label := aString
- tag
- ^ 'button'
- defaultControllerClass
- ^ MKButtonController
- defaultLabel
- ^ 'OK'
- defaultLayout
- ^ super defaultLayout
- width: 80;
- height: 24;
- yourself
- renderContentOn: html
- self hasIcon ifTrue: [
- html img
- class: 'mk_icon';
- src: self icon ].
- html with: self label
- hasIcon
- ^ self icon notNil
- isDefault
- ^ self default ifNil: [ false ]
- MKSingleAspectView subclass: #MKCheckboxView
- instanceVariableNames: 'id'
- package: 'Moka-Views'!
- I am a checkbox view. My default controller is `MKCheckboxController`.
- My controller must answer to `#onToggled:`.
- - If no `aspect` is provided, the ckeckbox state will always be off.
- - use `#label:` to set the label string.!
- checked
- ^ self aspectValue ifNil: [ false ]
- cssClass
- ^ super cssClass, ' mk_checkbox'
- id
- ^ id ifNil: [ id := 1000000 atRandom asString ]
- defaultControllerClass
- ^ MKCheckboxController
- defaultLayout
- ^ super defaultLayout
- width: 16;
- height: 16;
- yourself
- update
- self checked
- ifTrue: [ root asJQuery addClass: 'checked' ]
- ifFalse: [ root asJQuery removeClass: 'checked' ]
- renderContentOn: html
- self checked ifTrue: [
- root asJQuery addClass: 'checked' ].
-
- root at: 'tabindex' put: '0'
- MKCheckboxView subclass: #MKSwitchView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am a switch view, similar to a `MKCheckboxView` but displayed as a switch.
- My default controller is `MKCheckboxController`.!
- checkboxCssClass
- ^ 'mk_switch'
- cssClass
- ^ super cssClass, ' mk_switch'
- defaultLayout
- ^ super defaultLayout
- width: 48;
- height: 20;
- yourself
- MKLayoutView subclass: #MKImageView
- instanceVariableNames: 'imagePath alternativeContents'
- package: 'Moka-Views'!
- I display an image.
- Note that several views support adding icons using either `#icon:` or `#iconBlock:`.
- Create instances using `MKImageView class>>imagePath:`.!
- alternativeContents
- ^ alternativeContents ifNil: [ self imagePath ]
- alternativeContents: aString
- alternativeContents := aString
- imagePath
- ^ imagePath ifNil: [ '' ]
- imagePath: aString
- imagePath := aString
- tag
- ^ 'img'
- renderContentOn: html
- root
- src: self imagePath;
- alt: self alternativeContents
- imagePath: aString
- ^ self new
- imagePath: aString;
- yourself
- MKSingleAspectView subclass: #MKLabelView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am an label view. I display a `String`.!
- cssClass
- ^ super cssClass, ' mk_label'
- defaultControllerClass
- ^ super defaultControllerClass
- defaultLayout
- ^ MKLabelLayout new
- height: 24;
- top: 0;
- left:0;
- right: 0;
- textAlign: 'left';
- yourself
- textAlign: aString
- self layout textAlign: aString
- renderContentOn: html
- html with: self aspectValue
- MKLabelView subclass: #MKHeadingView
- instanceVariableNames: 'level'
- package: 'Moka-Views'!
- I display a heading, with a `level` from 1 to 6.!
- cssClass
- ^ String streamContents: [ :stream |
- stream
- << super cssClass
- << ' mk_heading level'
- << self level asString ]
- level
- ^ level ifNil: [ 1 ]
- level: aNumber
- level := aNumber
- tag
- ^ 'h', self level asString
- MKLayoutView subclass: #MKOverlayView
- instanceVariableNames: 'childView'
- package: 'Moka-Views'!
- I display an transparent overlay, typically over other views, except my `childView`.
- Create instances using the class-side `childView:` method.!
- childView
- ^ childView
- childView: aView
- childView := aView
- children
- ^ { self childView }
- cssClass
- ^ super cssClass, ' mk_overlay'
- remove
- super remove.
- self childView remove
- defaultControllerClass
- ^ MKOverlayController
- renderContentOn: html
- "Left empty on purpose.
- No Content is rendered, as the childView is actually displayed separately"
- childView: aView
- ^ self new
- childView: aView;
- yourself
- MKLayoutView subclass: #MKPaneView
- instanceVariableNames: 'views'
- package: 'Moka-Views'!
- I am a view containing other views.
- Use `#addView:` to add a view to the pane.!
- children
- ^ self views
- cssClass
- ^ super cssClass, ' mk_pane'
- views
- ^ views ifNil: [ views := OrderedCollection new ]
- addView: aView
- self views add: aView
- defaultLayout
- ^ MKPaneLayout new
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- yourself
- borderBottom: aNumber
- self layout borderBottom: aNumber
- borderLeft: aNumber
- self layout borderLeft: aNumber
- borderRight: aNumber
- self layout borderRight: aNumber
- borderTop: aNumber
- self layout borderTop: aNumber
- renderContentOn: html
- self views do: [ :each |
- html with: each ]
- MKPaneView subclass: #MKPanelView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am similar to a `MKPaneView` but I am scrollable and display a light background.!
- cssClass
- ^ super cssClass, ' mk_panel'
- MKAspectsView subclass: #MKSelectionView
- instanceVariableNames: 'selectionAspect collectionAspect displayBlock iconBlock'
- package: 'Moka-Views'!
- I an abstract selection view of a list of elements.
- Rendering can be customized with `#displayBlock:` and `#iconBlock:`. Both take the item of the list as argument and answer a string.!
- collection
- ^ self valueForAspect: self collectionAspect
- collectionAspect
- ^ collectionAspect
- collectionAspect: aSelector
- collectionAspect := aSelector
- displayBlock
- ^ displayBlock ifNil: [ self defaultDisplayBlock ]
- displayBlock: aBlock
- displayBlock := aBlock
- iconBlock
- ^ iconBlock
- iconBlock: aBlock
- iconBlock := aBlock
- selectedItem
- ^ self valueForAspect: self selectionAspect
- selectionAspect
- ^ selectionAspect
- selectionAspect: aSelector
- selectionAspect := aSelector
- defaultDisplayBlock
- ^ [ :item | item asString ]
- renderIconFor: anObject on: html
- self hasIcon ifTrue: [
- html img
- class: 'mk_icon';
- src: (self iconBlock value: anObject) ]
- hasIcon
- ^ self iconBlock notNil
- model: aModel collectionAspect: collectionSelector selectionAspect: selectionSelector
- ^ (self model: aModel)
- collectionAspect: collectionSelector;
- selectionAspect: selectionSelector;
- yourself
- MKSelectionView subclass: #MKDropdownView
- instanceVariableNames: 'modalPaneView listView'
- package: 'Moka-Views'!
- I am a push button view. My default controller is `MKButtonController`.
- My controller must answer to `#onPressed`.
- - Instances can be set a `default` button
- - Use `#label:` to set the label string!
- cssClass
- ^ super cssClass, ' mk_dropdown'
- selectedListItem
- ^ (root asJQuery find: ':selected') text
- tag
- ^ 'button'
- update: anAnnouncement
- ({self selectionAspect. self collectionAspect}
- includes: anAnnouncement aspect) ifTrue: [
- self update ]
- popupList
- "Show a new list view inside a modal pane"
- self modalPaneView
- left: self domPosition x;
- top: self domPosition y;
- render.
- self listView focus
- defaultControllerClass
- ^ MKDropdownController
- defaultLayout
- ^ super defaultLayout
- width: 120;
- height: 24;
- yourself
- renderContentOn: html
- html div class: 'mk_dropdown_arrows'.
- self renderIconFor: self selectedItem on: html.
- html with: (self displayBlock value: self selectedItem)
- listView
- ^ listView ifNil: [
- listView := (MKDropdownListView
- model: self model
- collectionAspect: self collectionAspect
- selectionAspect: self selectionAspect)
- width: self width;
- height: 'auto';
- displayBlock: self displayBlock;
- iconBlock: self iconBlock;
- yourself ]
- modalPaneView
- ^ modalPaneView ifNil: [
- modalPaneView := (MKModalDecorator decorate: self listView)
- extraCssClass: 'mk_dropdown_pane';
- closeOnEnter: true;
- closeOnClick: true;
- yourself.
- modalPaneView
- on: MKViewRemoved
- send: #focus
- to: self.
- modalPaneView ]
- MKSelectionView subclass: #MKListView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I display a list of elements in a list control field.!
- activeItem
- ^ self findItemFor: (root asJQuery find: '.', self selectedCssClass)
- cssClass
- ^ super cssClass, ' mk_list'
- findItemFor: aListItem
- ^ aListItem asJQuery data at: 'item'
- findListItemFor: anObject
- ^ (((root asJQuery find: 'li')
- filter: [ :thisArg | (thisArg asJQuery data: 'item') = anObject ] currySelf) eq: 0)
- selectedCssClass
- ^ 'selected'
- tag
- ^ 'ul'
- activateItem: anObject
- self activateListItem: (self findListItemFor: anObject)
- activateListItem: aListItem
- | item |
-
- (aListItem get: 0) ifNil: [ ^ self ].
- aListItem parent children removeClass: self selectedCssClass.
- aListItem addClass: self selectedCssClass.
-
- self ensureVisible: aListItem
- defaultControllerClass
- ^ MKListController
- ensureVisible: aListItem
- "Move the scrollbar to show the active element"
-
- | parent position |
- (aListItem get: 0) ifNil: [ ^ self ].
- position := self positionOf: aListItem.
- parent := aListItem parent.
-
- aListItem position top < 0 ifTrue: [
- (parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem position top - 10) ].
- aListItem position top + aListItem height > parent height ifTrue: [
- (parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem height - (parent height - aListItem position top)) +10 ].
-
- self announce: (MKViewScroll view: self)
- positionOf: aListItem
- "TODO: rewrite in smalltalk"
- <return aListItem.parent().children().get().indexOf(aListItem.get(0)) + 1>
- renderContentOn: html
- self collection do: [ :each |
- self renderItem: each on: html ].
-
- "make the list focusable"
- root at: 'tabindex' put: '0'
- renderItem: anObject on: html
- | li |
-
- li := html li.
- li asJQuery data: 'item' put: anObject.
-
- self selectedItem = anObject ifTrue: [
- li class: self selectedCssClass ].
- li with: [ self renderIconFor: anObject on: html ].
- li with: (self displayBlock value: anObject)
- update: anAnnouncement
- anAnnouncement aspect = self selectionAspect ifTrue: [
- self updateSelectedItem ].
-
- anAnnouncement aspect = self collectionAspect ifTrue: [
- self update ]
- updateSelectedItem
- self activateItem: self selectedItem
- model: aModel collectionAspect: collectionSelector selectionAspect: selectionSelector
- ^ (self model: aModel)
- collectionAspect: collectionSelector;
- selectionAspect: selectionSelector;
- yourself
- MKListView subclass: #MKDropdownListView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am similar to a `MKListView`, but inside a `MKDropdownView`.!
- cssClass
- ^ super cssClass, ' mk_dropdown_list'
- defaultControllerClass
- ^ MKDropdownListController
- MKListView subclass: #MKSourceListView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am similar to a `MKListView`, but displayed slightly differently, in a similar way as in the left-side the of Finder in OSX.!
- cssClass
- ^ super cssClass, ' mk_sourcelist'
- MKLayoutView subclass: #MKSplitView
- instanceVariableNames: 'firstView secondView splitter thickness minimumThickness'
- package: 'Moka-Views'!
- I am the superclass of all split views. I arrange two child view with a splitter between them.
- Create instances using the class-side method `firstView:secondView:`.!
- children
- ^ { self firstView. self secondView }
- cssClass
- ^ super cssClass, ' mk_split_view'
- firstView
- ^ firstView
- firstView: aView
- firstView := MKDecorator decorate: aView
- minimumThickness
- ^ minimumThickness ifNil: [ self defaultMinimumThickness ]
- minimumThickness: aNumber
- minimumThickness := aNumber
- secondView
- ^ secondView
- secondView: aView
- secondView := MKDecorator decorate: aView
- splitter
- "Answer the `splitter` TagBrush"
-
- ^ splitter
- splitterCssClass
- ^ 'mk_splitter'
- thickness
- ^ thickness ifNil: [ self defaultThickness ]
- thickness: aNumber
- thickness := aNumber
- defaultMinimumThickness
- ^ 50
- defaultThickness
- ^ 300
- renderContentOn: html
- html with: self firstView.
- splitter := html div class: self splitterCssClass.
- html with: self secondView.
-
- self controller placeSplitter: self thickness
- firstView: aView secondView: anotherView
- ^ self new
- firstView: aView;
- secondView: anotherView;
- yourself
- MKSplitView subclass: #MKHorizontalSplitView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I split my child views vertically.!
- cssClass
- ^ super cssClass, ' horizontal'
- leftThickness: aNumber
- self thickness: aNumber.
- self controller: MKLeftFixedHorizontalSplitController new
- rightThickness: aNumber
- self thickness: aNumber.
- self controller: MKRightFixedHorizontalSplitController new
- secondView: aView
- super secondView: aView.
- self secondView
- right: 0;
- left: 'auto'
- defaultControllerClass
- ^ MKLeftFixedHorizontalSplitController
- setupEventHandlers
- splitter asJQuery draggable: #{
- 'axis' -> 'x'.
- 'containment' -> splitter asJQuery parent.
- 'helper' -> 'clone'.
- 'cursor' -> 'ew-resize'.
- 'stop' -> [ self resized ].
- 'drag' -> [ :event :ui | self controller onResize: event helper: ui ] }
- MKSplitView subclass: #MKVerticalSplitView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I split my child views horizontally.!
- bottomThickness: aNumber
- self thickness: aNumber.
- self controller: MKBottomFixedVerticalSplitController new
- cssClass
- ^ super cssClass, ' vertical'
- secondView: aView
- super secondView: aView.
- self secondView
- bottom: 0;
- top: 'auto'
- topThickness: aNumber
- self thickness: aNumber.
- self controller: MKTopFixedVerticalSplitController new
- defaultControllerClass
- ^ MKTopFixedVerticalSplitController
- setupEventHandlers
- splitter asJQuery draggable: #{
- 'axis' -> 'y'.
- 'containment' -> splitter asJQuery parent.
- 'cursor' -> 'ns-resize'.
- 'helper' -> 'clone'.
- 'stop' -> [ self resized ].
- 'drag' -> [ :event :ui | self controller onResize: event helper: ui ] }
- MKSingleAspectView subclass: #MKTextAreaView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am an text area view. My default controller is `MKAnyKeyInputController`.
- My controller must answer to `#onKeyPressed:`.!
- cssClass
- ^ super cssClass, ' mk_textarea'
- tag
- ^ 'textarea'
- value
- ^ root asJQuery val
- defaultControllerClass
- ^ MKAnyKeyInputController
- defaultLayout
- ^ super defaultLayout
- width: 160;
- height: 80;
- yourself
- renderContentOn: html
- root with: self aspectValue
- update
- root ifNotNil: [ root asJQuery val: self aspectValue ]
- MKTextAreaView subclass: #MKInputView
- instanceVariableNames: ''
- package: 'Moka-Views'!
- I am an input view. My default controller is `MKEnterInputController`.
- My controller must answer to `#onKeyPressed:`.!
- cssClass
- ^ 'moka_view mk_input'
- tag
- ^ 'input'
- defaultControllerClass
- ^ MKEnterInputController
- defaultLayout
- ^ super defaultLayout
- width: 160;
- height: 24;
- yourself
- renderContentOn: html
- root value: self aspectValue
- triggerChangeOnAnyKey
- self controller: MKAnyKeyInputController new
- triggerChangeOnEnter
- self controller: MKEnterInputController new
|