[Cuis-dev] PaddedMorph preview
ken.dickey at whidbey.com
ken.dickey at whidbey.com
Mon Sep 9 08:09:43 PDT 2024
I implemented the original suggestion of #padding in a PaddedMorph and
have the example code attached.
Layered approach with (too) many fileIns. Do in order.
Workspace code attached.
If anyone gets a chance, good to play with before Wednesday's Meetup.
Good on ya,
-KenD
-------------- next part --------------
'From Cuis7.1 [latest update: #6679] on 8 September 2024 at 1:20:17 pm'!
!classDefinition: #PaddedMorph category: #'Morphic-Kernel'!
BoxedMorph subclass: #PaddedMorph
instanceVariableNames: 'padding'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Kernel'!
!PaddedMorph commentStamp: '<historical>' prior: 0!
In addition to a border, there is a padding area which acts as a frame around interior contents.
!
!classDefinition: #LayoutMorph category: #'Morphic-Layouts'!
PaddedMorph subclass: #LayoutMorph
instanceVariableNames: 'direction separation axisEdgeWeight doAdoptWidgetsColor useEdgeSpace '
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Layouts'!
!Morph methodsFor: 'accessing' stamp: 'KenD 9/7/2024 20:00:16'!
padding
"We have no padding (see PaddedMorph).
If anyone asks, answer value for no padding"
^`0 at 0`! !
!BoxedMorph methodsFor: 'geometry' stamp: 'KenD 9/7/2024 20:42:11'!
minimumExtent
"This returns the minimum extent that the morph may be shrunk to.
It is expressed in the morph own coordinates, like morphExtent."
^ super minimumExtent + (self borderWidth * 2)! !
!PaddedMorph methodsFor: 'geometry' stamp: 'KenD 9/7/2024 20:33:57'!
interiorExtent
"Answer extent inset from borderWidth and Padding"
^self morphExtent - (2 * self borderWidth) - (2 * self padding)! !
!PaddedMorph methodsFor: 'geometry' stamp: 'KenD 9/8/2024 12:56:27'!
interiorOrigin
"Answer point from borderWidth and Padding"
| x y |
x := self borderWidth + self padding x.
y := self borderWidth + self padding y.
^x @ y! !
!PaddedMorph methodsFor: 'geometry' stamp: 'KenD 9/7/2024 20:41:48'!
minimumExtent
"This returns the minimum extent that the morph may be shrunk to.
It is expressed in the morph own coordinates, like morphExtent."
^ super minimumExtent + (self padding + self borderWidth * 2)! !
!PaddedMorph methodsFor: 'accessing' stamp: 'KenD 9/7/2024 20:22:38'!
padding
^padding ifNil: [ 0 at 0 ]! !
!PaddedMorph methodsFor: 'accessing' stamp: 'KenD 9/7/2024 20:12:59'!
padding: numberOrPoint
padding := ((numberOrPoint class = Point)
ifTrue: [numberOrPoint]
ifFalse: [numberOrPoint @ numberOrPoint]).
self morphExtent: (self minimumExtent max: self morphExtent).
self redrawNeeded! !
!PaddedMorph methodsFor: 'initialization' stamp: 'KenD 9/7/2024 20:11:22'!
initialize
super initialize.
padding :=`0 at 0`! !
!classDefinition: #LayoutMorph category: #'Morphic-Layouts'!
PaddedMorph subclass: #LayoutMorph
instanceVariableNames: 'direction separation axisEdgeWeight doAdoptWidgetsColor useEdgeSpace'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Layouts'!
-------------- next part --------------
'From Cuis7.1 [latest update: #6680] on 8 September 2024 at 2:38:28 pm'!
!classDefinition: #ImageMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #ImageMorph
instanceVariableNames: 'image '
classVariableNames: 'DefaultForm '
poolDictionaries: ''
category: 'Morphic-Widgets'!
!classDefinition: #LabelMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #LabelMorph
instanceVariableNames: 'font emphasis contents '
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Widgets'!
!classDefinition: #TextParagraphMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #TextParagraphMorph
instanceVariableNames: 'textComposition setsHeightOnContent shrinkFromExtent '
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Widgets'!
!LayoutMorph methodsFor: 'geometry' stamp: 'KenD 9/8/2024 12:52:03'!
minimumExtent: cachedValues
"Answer size sufficient to frame my submorphs."
| width height mle subs |
width := 0.
height := 0.
subs := self submorphsToLayout.
(self direction = #vertical)
ifTrue: [ "Column"
subs do: [ :sm |
mle := sm minimumLayoutExtent: cachedValues.
"use maximum width across submorphs"
width := width max: mle x.
"sum up submorph heights, excluding separation"
height := height + mle y.
].
width := width + (2 * self padding x).
height := height + (2 * self padding y) + (subs size - 1 * self ySeparation)
]
ifFalse: [ "Row"
subs do: [ :sm |
mle := sm minimumLayoutExtent: cachedValues.
"sum up submorphs width"
width := width + mle x.
"use maximum height across submorph"
height := height max: mle y.
].
width := width + (2 * self padding x) + (subs size - 1 * self xSeparation).
height := height + (2 * self padding y).
].
^ (width @ height) + self extentBorder ! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/8/2024 13:13:06'!
layoutBounds
"Return the bounds for laying out children of the receiver"
^ self interiorOrigin extent: self interiorExtent ! !
!ImageMorph methodsFor: 'drawing' stamp: 'KenD 9/8/2024 12:28:10'!
drawOn: aCanvas
(padding > `0 at 0`) ifTrue: [ | innerOrigin |
"Make use of my color in area between border and image"
innerOrigin := borderWidth @ borderWidth.
aCanvas
fillRectangle: (innerOrigin extent: extent - (2 * innerOrigin ))
color: color].
(borderWidth > 0) ifTrue: [
aCanvas
frameRectangle: (`0 at 0` extent: extent)
color: borderColor
borderWidth: borderWidth
borderStyleSymbol: #simple ].
aCanvas image: image at: self interiorOrigin.
! !
!ImageMorph methodsFor: 'drawing' stamp: 'KenD 9/8/2024 13:02:20'!
minimumExtent
^image extent + self extentBorder + (2 * self padding)! !
!TextParagraphMorph methodsFor: 'drawing' stamp: 'KenD 9/8/2024 12:35:17'!
drawOn: aCanvas
aCanvas
fillRectangle: self localBounds color: color.
aCanvas
drawTextComposition: textComposition
at: self interiorOrigin
extent: self interiorExtent
color: Theme current text
selectionColor: `Color red`
avoidOverhang: true.
aCanvas
frameRectangle: self localBounds
color: borderColor
borderWidth: borderWidth
borderStyleSymbol: nil! !
!TextParagraphMorph methodsFor: 'geometry' stamp: 'KenD 9/8/2024 13:08:10'!
minimumExtent
^3 at 1 * FontFamily defaultLineSpacing ceiling + 2 + (2 * self interiorOrigin) ! !
!InnerTextMorph methodsFor: 'drawing' stamp: 'KenD 9/7/2024 20:43:52'!
drawOn: aCanvas
"Draw the receiver on a canvas"
false ifTrue: [ self debugDrawLineRectsOn: aCanvas ]. "show line rects for debugging"
aCanvas
drawTextComposition: self textComposition
at: (self borderWidth @ self borderWidth)
extent: extent
color: color
selectionColor: (Theme current textHighlightFocused: self hasKeyboardFocus).
model actualContents isEmpty ifTrue: [
owner
valueOfProperty: #emptyTextDisplayMessage
ifPresentDo: [ :msg |
aCanvas
drawString: msg
at: (self borderWidth @ self borderWidth)
font: nil
color: Theme current textEmptyDisplayMessage ]].! !
!classDefinition: #ImageMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #ImageMorph
instanceVariableNames: 'image'
classVariableNames: 'DefaultForm'
poolDictionaries: ''
category: 'Morphic-Widgets'!
!classDefinition: #LabelMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #LabelMorph
instanceVariableNames: 'font emphasis contents'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Widgets'!
!classDefinition: #TextParagraphMorph category: #'Morphic-Widgets'!
PaddedMorph subclass: #TextParagraphMorph
instanceVariableNames: 'textComposition setsHeightOnContent shrinkFromExtent'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Widgets'!
-------------- next part --------------
'From Cuis7.1 [latest update: #6680] on 8 September 2024 at 2:39:48 pm'!
!LabelMorph methodsFor: 'drawing' stamp: 'KenD 9/8/2024 13:06:07'!
drawOn: aCanvas
aCanvas
drawString: (contents ifNil: [ '' ])
at: self interiorOrigin
font: self fontToUse
color: color.
(borderWidth > 0) ifTrue: [
aCanvas
frameRectangle: (`0 at 0` extent: extent)
color: borderColor
borderWidth: borderWidth
borderStyleSymbol: #simple ]! !
!LabelMorph methodsFor: 'geometry' stamp: 'KenD 9/8/2024 13:05:40'!
minimumExtent
^ self measureContents + (2 * self interiorOrigin) ! !
-------------- next part --------------
'From Cuis7.1 [latest update: #6682] on 8 September 2024 at 2:50:11 pm'!
!LayoutMorph class methodsFor: 'examples' stamp: 'KenD 9/3/2024 16:00:52'!
exampleEdgesColumn
"Show 2 cases :1 useEdgeSpace true and 1 false"
" self exampleEdgesColumn "
| withEdge noEdge upSpec downSpec |
withEdge := self newColumn :: padding: (20 @ 20); separation: 20.
noEdge := self newColumn :: padding: (0 @ 0); separation: 20.
upSpec := LayoutSpec keepMorphExtent :: offAxisEdgeWeight: 0.
upSpec proportionalWidth: 0.8 minimum: 100; proportionalHeight: 0.8 minimum: 100.
downSpec := LayoutSpec keepMorphExtent :: offAxisEdgeWeight: 1.
downSpec proportionalWidth: 0.5 minimum: 100; proportionalHeight: 0.5 minimum: 100.
withEdge addMorph: (BoxedMorph new :: color: Color blue; layoutSpec: upSpec).
noEdge addMorph: (BoxedMorph new :: color: Color blue; layoutSpec: upSpec).
withEdge addMorph: (LabelMorph new :: contents: 'WITH Padding').
noEdge addMorph: (LabelMorph new :: contents: 'withOUT Padding').
withEdge addMorph: (BoxedMorph new :: layoutSpec: downSpec).
noEdge addMorph: (BoxedMorph new :: layoutSpec: downSpec).
withEdge openInWorld.
noEdge openInWorld.! !
!LayoutMorph class methodsFor: 'examples' stamp: 'KenD 9/3/2024 16:01:46'!
exampleEdgesRow
"Show 2 cases: 1 useEdgeSpace true and 1 false"
" self exampleEdgesRow "
| withEdge noEdge upSpec downSpec |
withEdge := self newRow :: padding: (20 @ 20); separation: 20.
noEdge := self newRow :: padding: (0 @ 0); separation: 20.
upSpec := LayoutSpec keepMorphExtent :: offAxisEdgeWeight: 0.
upSpec proportionalWidth: 0.8 minimum: 100; proportionalHeight: 0.8 minimum: 100.
downSpec := LayoutSpec keepMorphExtent :: offAxisEdgeWeight: 1.
downSpec proportionalWidth: 0.5 minimum: 100; proportionalHeight: 0.5 minimum: 100.
withEdge addMorph: (BoxedMorph new :: color: Color blue; layoutSpec: upSpec).
noEdge addMorph: (BoxedMorph new :: color: Color blue; layoutSpec: upSpec).
withEdge addMorph: (LabelMorph new :: contents: 'WITH Padding').
noEdge addMorph: (LabelMorph new :: contents: 'withOUT Padding').
withEdge addMorph: (BoxedMorph new :: layoutSpec: downSpec).
noEdge addMorph: (BoxedMorph new :: layoutSpec: downSpec).
withEdge openInWorld.
noEdge openInWorld.! !
-------------- next part --------------
'From Cuis7.1 [latest update: #6683] on 8 September 2024 at 3:22:27 pm'!
!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 9/4/2024 11:50:46'!
padding: numberOrPoint
super padding: numberOrPoint.
self layoutSubmorphs ! !
!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 9/3/2024 15:45:58'!
useEdgeSpace
self flag: #deprecated.
^ self padding > (0 @ 0)! !
!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 9/4/2024 11:48:55'!
useEdgeSpace: aBoolean
self flag: #deprecated.
aBoolean
ifTrue: [ self padding: (self xSeparation @ self ySeparation) ]
ifFalse: [self padding: (0 at 0)].
self layoutSubmorphs
! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:40:24'!
layoutSubmorphsHorizontallyIn: boundsForLayout
"Compute a new layout based on the given layout bounds."
| visibleSubmorphs gap gapCount widths widthToAllocate leftOver x height y cache |
"Preconditions: self isRow & morphExtent >= minimumLayoutExtent"
(visibleSubmorphs := self submorphsToLayout reversed "Display Order")
ifEmpty: [ ^ self. "Nothing to layout, besides `sum` below, would fail" ].
gap := self xSeparation.
gapCount := visibleSubmorphs size - 1. "gap between each contained Morph"
widthToAllocate := boundsForLayout width - (gapCount * gap).
cache := IdentityDictionary new.
widths := self widthsFor: visibleSubmorphs within: widthToAllocate minLayoutExtentCache: cache.
leftOver := widthToAllocate - widths sum.
x := boundsForLayout left + (leftOver * self axisEdgeWeight).
visibleSubmorphs with: widths do: [ :sm :smWidth |
height := self offAxisHeightFor: sm within: boundsForLayout height minLayoutExtentCache: cache.
y := self offAxisYOffsetFor: sm within: boundsForLayout height - height.
sm fitInto: (x @ (boundsForLayout top + y) extent: smWidth @ height).
x := x + smWidth + gap.
]! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:52:11'!
layoutSubmorphsVerticallyIn: boundsForLayout
"Compute a new layout based on the given layout bounds."
| visibleSubmorphs gap gapCount heights heightToAllocate leftOver y width x cache |
"Preconditions: self isRow & morphExtent >= minimumLayoutExtent"
(visibleSubmorphs := self submorphsToLayout reversed "Display Order")
ifEmpty: [ ^ self. "Nothing to layout, besides `sum` below, would fail" ].
gap := self ySeparation.
gapCount := visibleSubmorphs size - 1. "gap between each contained Morph"
heightToAllocate := boundsForLayout height - (gapCount * gap).
cache := IdentityDictionary new.
heights := self heightsFor: visibleSubmorphs within: heightToAllocate minLayoutExtentCache: cache.
leftOver := heightToAllocate - heights sum.
y := boundsForLayout top + (leftOver * self axisEdgeWeight).
visibleSubmorphs with: heights do: [ :sm :smHeight |
width := self offAxisWidthFor: sm within: boundsForLayout width minLayoutExtentCache: cache.
x := self offAxisXOffsetFor: sm within: boundsForLayout width - width.
sm fitInto: (boundsForLayout left + x @ y extent: width @ smHeight).
y := y + smHeight + gap.
]! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:45:27'!
offAxisHeightFor: aMorph within: availableHeight minLayoutExtentCache: cache
"Answer height for a single morph -- offAxis calculation for a Row"
^(availableHeight * aMorph layoutSpec proportionalLayoutHeight)
max: (aMorph minimumLayoutExtent: cache) y.! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:45:59'!
offAxisWidthFor: aMorph within: availableWidth minLayoutExtentCache: cache
"Answer width for a single morph -- offAxis calculation for a Column"
^ (availableWidth * aMorph layoutSpec proportionalLayoutWidth)
max: (aMorph minimumLayoutExtent: cache) x.
! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:48:57'!
offAxisXOffsetFor: aMorph within: availableWidth
"Answer x offset for a single morph -- offAxis calculation for a Column"
^ availableWidth * aMorph layoutSpec offAxisEdgeWeight. ! !
!LayoutMorph methodsFor: 'layout' stamp: 'KenD 9/3/2024 18:48:36'!
offAxisYOffsetFor: aMorph within: availableHeight
"Answer y offset for a single morph -- offAxis calculation for a Row"
^ availableHeight * aMorph layoutSpec offAxisEdgeWeight! !
-------------- next part --------------
'From Cuis7.1 [latest update: #6684] on 9 September 2024 at 7:50:05 am'!
!classDefinition: #LayoutMorph category: #'Morphic-Layouts'!
PaddedMorph subclass: #LayoutMorph
instanceVariableNames: 'direction separation axisEdgeWeight doAdoptWidgetsColor useEdgeSpace '
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Layouts'!
!LayoutMorph methodsFor: 'initialization' stamp: 'KenD 9/9/2024 07:49:27'!
initialize
super initialize.
separation := 0.
axisEdgeWeight := 0.0.
padding := `0 at 0`.
doAdoptWidgetsColor := false! !
!methodRemoval: LayoutMorph #useEdgeSpace stamp: 'KenD 9/9/2024 07:48:53'!
LayoutMorph removeSelector: #useEdgeSpace!
!methodRemoval: LayoutMorph #useEdgeSpace: stamp: 'KenD 9/9/2024 07:48:49'!
LayoutMorph removeSelector: #useEdgeSpace:!
!classDefinition: #LayoutMorph category: #'Morphic-Layouts'!
PaddedMorph subclass: #LayoutMorph
instanceVariableNames: 'direction separation axisEdgeWeight doAdoptWidgetsColor'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Layouts'!
-------------- next part --------------
labelMorph := LabelMorph new
borderWidth: 2;
borderColor: Color red;
color: Color cyan;
padding: 0.
imageMorph := ImageMorph new
borderWidth: 6;
borderColor: Color green;
padding: 0.
layoutMorph := LayoutMorph newColumn
borderWidth: 2;
borderColor: Color yellow;
padding: 0;
separation: 0;
addMorph: labelMorph;
addMorph: imageMorph;
scaleBy: 3;
openInWorld.
labelMorph padding: 4.
imageMorph padding: 6.
layoutMorph padding: 8.
layoutMorph padding: 0; morphExtent: layoutMorph minimumExtent.
layoutMorph separation: 3.
LayoutMorph exampleEdgesColumn.
LayoutMorph exampleEdgesRow.
More information about the Cuis-dev
mailing list