Smalltalk createPackage: 'Moka-Layouts'! Object subclass: #MKLayout instanceVariableNames: 'properties' package: 'Moka-Layouts'! !MKLayout commentStamp! I am responsible for the layout of a `MKLayoutView`.! !MKLayout methodsFor: 'accessing'! bottom: aNumber properties at: 'bottom' put: (self propertyLabelled: 'bottom' value: aNumber). (self hasProperty: 'top') ifTrue: [ self removeProperty: 'height' ]. self removeProperty: 'centerY' ! centerX: aNumber properties at: 'centerX' put: (MKHorizontalCenteringLayoutProperty layout: self value: aNumber). self removeProperty: 'left'; removeProperty: 'right' ! centerY: aNumber properties at: 'centerY' put: (MKVerticalCenteringLayoutProperty layout: self value: aNumber). self removeProperty: 'top'; removeProperty: 'bottom' ! height ^ properties at: 'height' ifPresent: [ :property | property value ] ifAbsent: [ 1 ] ! height: aNumber properties at: 'height' put: (self propertyLabelled: 'height' value: aNumber). (self hasProperty: 'top') ifTrue: [ self removeProperty: 'bottom' ] ! left: aNumber properties at: 'left' put: (self propertyLabelled: 'left' value: aNumber). (self hasProperty: 'width') ifTrue: [ self removeProperty: 'right' ]. self removeProperty: 'centerX' ! right: aNumber properties at: 'right' put: (self propertyLabelled: 'right' value: aNumber). (self hasProperty: 'width') ifTrue: [ self removeProperty: 'left' ]. self removeProperty: 'centerX' ! top: aNumber properties at: 'top' put: (self propertyLabelled: 'top' value: aNumber). (self hasProperty: 'height') ifTrue: [ self removeProperty: 'bottom' ]. self removeProperty: 'centerY' ! width ^ properties at: 'width' ifPresent: [ :property | property value ] ifAbsent: [ 1 ] ! width: aNumber properties at: 'width' put: (self propertyLabelled: 'width' value: aNumber). (self hasProperty: 'left') ifTrue: [ self removeProperty: 'right' ] ! ! !MKLayout methodsFor: 'converting'! asCssString ^ String streamContents: [ :stream | properties valuesDo: [ :each | each printCssOn: stream. stream << ';' ] ] ! ! !MKLayout methodsFor: 'factory'! propertyLabelled: aString value: aValue ^ MKLabelledLayoutProperty layout: self label: aString value: aValue ! ! !MKLayout methodsFor: 'initialization'! initialize super initialize. properties := Dictionary new ! ! !MKLayout methodsFor: 'private'! hasProperty: aString ^ properties includesKey: aString ! removeProperty: aString properties remove: aString ifAbsent: [] ! ! MKLayout subclass: #MKLabelLayout instanceVariableNames: '' package: 'Moka-Layouts'! !MKLabelLayout commentStamp! I am a specialized layout for label views. I can set a `textAlign` property, taking a string argument, `'left'`, `'center'` or `'right'`.! !MKLabelLayout methodsFor: 'accessing'! textAlign: aString "Map to CSS' text-align property. Possible values are `'left'`, `'center'` and `'right'`" properties at: 'text-align' put: (self propertyLabelled: 'text-align' value: aString) ! ! MKLayout subclass: #MKPaneLayout instanceVariableNames: '' package: 'Moka-Layouts'! !MKPaneLayout commentStamp! I am a specialized layout for pane views. I can set border widths to my views.! !MKPaneLayout methodsFor: 'accessing'! borderBottom: aNumber properties at: 'border-bottom' put: (self propertyLabelled: 'border-bottom-width' value: aNumber asMokaPixelString) ! borderLeft: aNumber properties at: 'border-left' put: (self propertyLabelled: 'border-left-width' value: aNumber asMokaPixelString) ! borderRight: aNumber properties at: 'border-right' put: (self propertyLabelled: 'border-right-width' value: aNumber asMokaPixelString) ! borderTop: aNumber properties at: 'border-top' put: (self propertyLabelled: 'border-top-width' value: aNumber asMokaPixelString) ! ! Object subclass: #MKLayoutProperty instanceVariableNames: 'layout value' package: 'Moka-Layouts'! !MKLayoutProperty commentStamp! I represent a single layout property.! !MKLayoutProperty methodsFor: 'accessing'! layout ^ layout ! layout: aLayout layout := aLayout ! value ^ value ! value: aValue value := aValue ! ! !MKLayoutProperty methodsFor: 'converting'! asCssString ^ String streamContents: [ :stream | self printCssOn: stream ] ! ! !MKLayoutProperty methodsFor: 'printing'! printCssOn: aStream self subclassResponsibility ! ! !MKLayoutProperty class methodsFor: 'instance creation'! layout: aLayout value: aValue ^ self new layout: aLayout; value: aValue; yourself ! ! MKLayoutProperty subclass: #MKHorizontalCenteringLayoutProperty instanceVariableNames: '' package: 'Moka-Layouts'! !MKHorizontalCenteringLayoutProperty methodsFor: 'accessing'! marginLeft ^ 0 - ((self layout width / 2) + self value) ! ! !MKHorizontalCenteringLayoutProperty methodsFor: 'printing'! printCssOn: aStream aStream << 'left:50%;'. aStream << 'margin-left:' << self marginLeft asMokaCssString ! ! MKLayoutProperty subclass: #MKLabelledLayoutProperty instanceVariableNames: 'label' package: 'Moka-Layouts'! !MKLabelledLayoutProperty methodsFor: 'accessing'! label ^ label ! label: aString label := aString ! ! !MKLabelledLayoutProperty methodsFor: 'printing'! printCssOn: aStream aStream << self label << ':' << self value asMokaCssString ! ! !MKLabelledLayoutProperty class methodsFor: 'instance creation'! layout: aLayout label: aString value: aValue ^ self new layout: aLayout; label: aString; value: aValue; yourself ! ! MKLayoutProperty subclass: #MKVerticalCenteringLayoutProperty instanceVariableNames: '' package: 'Moka-Layouts'! !MKVerticalCenteringLayoutProperty methodsFor: 'accessing'! marginTop ^ 0 - ((self layout height / 2) + self value) ! ! !MKVerticalCenteringLayoutProperty methodsFor: 'printing'! printCssOn: aStream aStream << 'top:50%;'. aStream << 'margin-top:' << self marginTop asMokaCssString ! ! !Number methodsFor: '*Moka-Layouts'! asMokaCssString ^ self abs > 1 ifTrue: [ self asMokaPixelString ] ifFalse: [ self asMokaPercentString ] ! asMokaPercentString ^ (self * 100) asString, '%' ! asMokaPixelString ^ self asString, 'px' ! ! !String methodsFor: '*Moka-Layouts'! asMokaCssString ^ self ! !