'From Cuis 5.0 [latest update: #4145] on 21 May 2020 at 3:26:39 pm'!

!Symbol methodsFor: 'testing' stamp: 'KenD 4/30/2020 11:52:10'!
is: aSymbol
	"Answer false if I am not a Symbol.
	 ??Note: A Symbol is also a String; should we check for #String and answer false??"
	^#Symbol = aSymbol or: [ super is: aSymbol]! !


!Morph methodsFor: 'geometry' stamp: 'KenD 5/21/2020 15:17:30'!
allocHeightForFactor: aFactor

	"Morphs with LayoutSpecs may specify propottional layouts and minimum extents
	  amountToAlloc * proportion * factor >= minHeight
	so breakeven is when
	  amountToAlloc = minHeight / proportion * factor"
	| minHeight |
	minHeight := self minimumLayoutHeight.
	^(self isProportionalHeight)
		ifFalse:  [ minHeight ]
		ifTrue: [ minHeight / (aFactor * self layoutSpec privateProportionalHeight) ]! !

!Morph methodsFor: 'geometry' stamp: 'KenD 5/21/2020 13:46:57'!
allocWidthForFactor: aFactor

	"Morphs with LayoutSpecs may specify propottional layouts and minimum extents
	  amountToAlloc * proportion * factor >= minWidth
	so breakeven is when
	  amountToAlloc = minWidth / proportion * factor"
	| minWidth |
	minWidth := self minimumLayoutWidth.
	^(self isProportionalWidth)
		ifFalse:  [ minWidth ]
		ifTrue: [ minWidth / (aFactor * self layoutSpec privateProportionalWidth) ]! !

!Morph methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:48:34'!
minLayoutHeight

	self flag: #depricated.
	^ self layoutSpecOrNil 
		ifNil: [ self morphHeight ] 
		ifNotNil: [ :ls | ls minimumSpecHeight ]
! !

!Morph methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:48:26'!
minLayoutWidth
	
	self flag: #depricated.
	^ self layoutSpecOrNil 
		ifNil: [ self morphWidth ] 
		ifNotNil: [ :ls |  ls minimumSpecWidth ]! !

!Morph methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:42:30'!
minimumLayoutHeight
	"I combine information from a Morph and its optional LayoutSpec"
	| minHeight |
	minHeight :=  self minimumExtent y. "from morph (me)."
	^ self layoutSpecOrNil 
		ifNil: [ minHeight ] 
		ifNotNil: [ :ls | minHeight max: (ls minimumSpecHeight )]
! !

!Morph methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:43:28'!
minimumLayoutWidth
	"I combine information from a Morph and its optional LayoutSpec"
	| minWidth |
	minWidth :=  self minimumExtent x. "from morph (me)."
	^ self layoutSpecOrNil 
		ifNil: [ minWidth ] 
		ifNotNil: [ :ls | minWidth max: (ls minimumSpecWidth )]
! !

!Morph methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:49:06'!
requiredWidthOrSpec
	"If not proportional width, then a fixed or morph width"
	self flag: #depricated.

	self layoutSpec 
		ifNil:  [ ^self width ]
		ifNotNil: [ :ls | 
			ls privateProportionalWidth
				ifNil:  [ ^ls fixedOrMorphWidth ]
				ifNotNil: [ ^ls ]
		]! !

!Morph methodsFor: 'testing' stamp: 'KenD 5/11/2020 13:04:22'!
isProportionalHeight

	"Answer true if I have a layoutSpec which specifies a proportional layout"
	^self layoutSpecOrNil 
		ifNil:  [ false ]
		ifNotNil: [ :ls |  ls isProportionalHeight ]! !

!Morph methodsFor: 'testing' stamp: 'KenD 5/11/2020 13:04:10'!
isProportionalWidth

	"Answer true if I have a layoutSpec which specifies a proportional layout"
	^self layoutSpecOrNil 
		ifNil:  [ false ]
		ifNotNil: [ :ls |  ls isProportionalWidth ]! !


!PluggableButtonMorph methodsFor: 'geometry' stamp: 'KenD 5/5/2020 12:15:55'!
minLayoutHeight

	^ self minimumExtent y! !

!PluggableButtonMorph methodsFor: 'geometry' stamp: 'KenD 5/5/2020 12:16:08'!
minLayoutWidth

	^ self minimumExtent x! !

!PluggableButtonMorph methodsFor: 'geometry' stamp: 'KenD 5/5/2020 17:07:16'!
minimumExtent

	| e |
	e _ Preferences windowTitleFont pointSize + 2.
	^e@e! !


!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 5/2/2020 15:09:07'!
axisEdgeWeight

	^ padding! !

!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 4/30/2020 11:54:47'!
axisEdgeWeight: aSymbolOrNumber
	"Along the Major or Layout Axis, subMorphs may be attracted toward one side (0.0) or the other (1.0).  This is the 	 	 LayoutMorph's axisEdgeWeight.  A numeric value is between 0.0 and 1.0

	If a Row, one can specify this weight symbolically as
	  { #rowLeft (0.0), #center (0.5), #rowRight (1.0)}

	If a Column, one can specify the weight symbolically as:
	  { #columnTop (0.0), #center (0.5), #columnBottom (1.0) }"
"	
	self axisEdgeWeight: #rowLeft.	-- axis must be horizontal 
	self axisEdgeWeight: #columnTop.	-- axis must be vertical
"
	| edgeWeight |
	(aSymbolOrNumber is: #Number)
		ifTrue: [ (aSymbolOrNumber between: 0.0 and: 1.0)
			ifTrue: [edgeWeight := aSymbolOrNumber ] 
			ifFalse: [self error: 'axisEdgeWeight ', aSymbolOrNumber printString, ' is out of range 0.0 to 1.0']
		]
		ifFalse: [
			(self direction = #horizontal) 
				ifTrue: [ "Row"
					edgeWeight := aSymbolOrNumber
						caseOf: {
							[ #rowLeft ] -> [ 0.0 ].
							[ #center ] -> [ 0.5 ].
							[ #rowRight ] -> [ 1.0 ]
						}
						otherwise: [ self error: 'bad axisEdgeWeight for Row: ', aSymbolOrNumber printString ].
				]
				ifFalse: [ "vertical => Column"
					edgeWeight := aSymbolOrNumber
						caseOf: {
							[ #columnTop ] -> [ 0.0 ].
							[ #center ] -> [ 0.5 ].
							[ #columnBottom ] -> [ 1.0 ]
						}
						otherwise: [ self error: 'bad axisEdgeWeight for Column: ', aSymbolOrNumber printString ].
				]
		].
	padding := edgeWeight.
	"self layoutSubmorphs"! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/21/2020 15:21:59'!
heightsFor: visibleSubs within: overallHeight
	"Answer array of morphHeights for visibleSubs."
	"Preconditions: 
		ySepararations already subtracted from overallHeight.
		overallHeight is large enough to contain minimumLayoutHeights of visibleSubs."
	
	| numSubs scaleFactor heightToAllocate
	  sumOfFixedOrPropMin sumOfPropMin sumOfPropDesired sumOfFixedMin
	  allocatedHeights propIndices desiredProps
	  maxOfMinAllocHeight belowBalanceProps sumOfDeltas
	 |
	numSubs := visibleSubs size.
	sumOfFixedOrPropMin := 0.
	sumOfFixedMin := 0.
	sumOfPropMin := 0.
	sumOfPropDesired := 0. "sum of percentage fractions; may be more than 100%"
	allocatedHeights := Array ofSize: numSubs.
	desiredProps   := Array ofSize: numSubs.
	propIndices := Set new. "keep set of proportional morph indices"
	1 to: numSubs do: [ :index | | sm layoutHeightMin |
		sm := visibleSubs at: index.
		layoutHeightMin := sm minimumLayoutHeight.
		sumOfFixedOrPropMin := sumOfFixedOrPropMin +  layoutHeightMin.
		allocatedHeights at: index put: layoutHeightMin.
		(sm isProportionalHeight)
			ifTrue:  [ | propDesired |
				propIndices add: index.
				propDesired := sm layoutSpec privateProportionalHeight.
				desiredProps at: index put: propDesired.
				sumOfPropDesired := sumOfPropDesired + propDesired.
				sumOfPropMin := sumOfPropMin + layoutHeightMin.
			]
			ifFalse: [ "Allocate height for non-proportional-height morphs"
				sumOfFixedMin := sumOfFixedMin + layoutHeightMin.
			]
	 ].
"Transcript log: 'minAllocs=', allocatedHeights asString."
	(propIndices size > 0)
	 	ifTrue: [ propIndices := propIndices asArray reversed ]  "easy to index"
		ifFalse: [ ^ allocatedHeights ]. "already finished"
	((overallHeight - sumOfFixedOrPropMin) < 2) "@@tune@@"
		ifTrue: [ ^ allocatedHeights ]. "close enough"
			
	"All fixed heights allocated; rest is for proportional + leftOver"
	heightToAllocate := (overallHeight - sumOfFixedMin) max: 0.
	scaleFactor := 1.0 / (sumOfPropDesired max: 1.0).  "if > 100% then below 1"

	"Find the min alloc size at which adding height is above max of minHeights
	 Keep the proportions over the minHeights at this allocatin.
	"
	maxOfMinAllocHeight := propIndices max: [ :morphIndex | 
		(visibleSubs at: morphIndex) allocHeightForFactor: scaleFactor 
	].
	belowBalanceProps := Array ofSize: visibleSubs size.
	propIndices do: [ :morphIndex | | heightAtBalance | 
		heightAtBalance := maxOfMinAllocHeight * scaleFactor * (desiredProps at: morphIndex).
		belowBalanceProps at: morphIndex
							   put: heightAtBalance "delta above min height"
							   	- ((visibleSubs at: morphIndex) minimumLayoutHeight)
	].
	sumOfDeltas := belowBalanceProps sum: [ :b | b ifNil: [0]].
	(sumOfDeltas < 0.001) ifTrue: [
		propIndices do: [ :morphIndex |
				allocatedHeights at: morphIndex 
								put: (heightToAllocate 
										* scaleFactor 
										* (desiredProps at: morphIndex)).
		].
		^ allocatedHeights "space desired = 100%"
	].
	propIndices do: [ :morphIndex |  "normalize"
		belowBalanceProps
			at: morphIndex
			put: ((belowBalanceProps at: morphIndex) / sumOfDeltas)
	].
"Transcript log: 'belowBalanceProps=', belowBalanceProps asString.
Transcript log: 'heightToAllocate=', heightToAllocate asString,
				    ' maxOfMinAllocHeight=', maxOfMinAllocHeight asString.
"
     "Below the balance point, calculate proportions from belowBalanceProps,
	above, use desiredProps"
	"@@ reduce when sumOfPropDesired < 1@@"
	(heightToAllocate <= maxOfMinAllocHeight)
		ifTrue: [ "below balance point"
			(sumOfPropDesired < 1.0) "Trim off space to save"
				ifTrue: [ heightToAllocate := heightToAllocate * sumOfPropDesired ].
			propIndices do: [ :morphIndex | |  minHeight |
				minHeight := allocatedHeights at: morphIndex.
				allocatedHeights at: morphIndex
								put: (minHeight + 
									(((heightToAllocate - sumOfPropMin ) 
									* (belowBalanceProps at: morphIndex)) max: 0.0))
			]
		]
		ifFalse: [ "above balance point"
			propIndices do: [ :morphIndex |
				allocatedHeights at: morphIndex 
								put: (heightToAllocate * scaleFactor * (desiredProps at: morphIndex))
			]
		].
	
	^ allocatedHeights! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/12/2020 14:07:31'!
offHorizontalMetricFor: aMorph withinExtent: boundsForLayout 
	"Answer a point: height@y for a single morph -- offAxis calculation for a Row"
	
	| spec minMorphHeight theSeparation proportionalHeight 
	availableForPropHeight actualPropHeight
	leftOver yPos |
	spec := aMorph layoutSpec.
	theSeparation := self ySeparation.
	minMorphHeight := aMorph minimumLayoutHeight.
	availableForPropHeight := (boundsForLayout height)  - (2 * theSeparation)..
	proportionalHeight := spec proportionalLayoutHeight min: 1.0.
	actualPropHeight := (availableForPropHeight * proportionalHeight)
							 max: minMorphHeight.
	leftOver := availableForPropHeight - actualPropHeight.
		
	yPos := boundsForLayout origin y
			+ theSeparation 
			+ (leftOver * spec offAxisEdgeWeight). "first Y, edge shifted"

	^ actualPropHeight @ yPos
	
	! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/12/2020 14:07:42'!
offVerticalMetricFor: aMorph withinExtent: boundsForLayout
	"Answer a point:  x@width for a single morph -- offAxis calculation for a Column"

	| spec minMorphWidth theSeparation proportionalWidth 
 	availableForPropWidth actualPropWidth
	leftOver xPos |
	spec := aMorph layoutSpec.
	theSeparation := self xSeparation.
	minMorphWidth := aMorph minimumLayoutWidth.
	availableForPropWidth := (boundsForLayout width) - (2 * theSeparation).
	proportionalWidth := spec proportionalLayoutWidth min: 1.0.
	actualPropWidth := (availableForPropWidth * proportionalWidth)
						 	max: minMorphWidth.
	leftOver := availableForPropWidth - actualPropWidth.
	
	xPos := boundsForLayout origin x 
			+ theSeparation 
			+ (leftOver * spec offAxisEdgeWeight). "first X, edge shifted"

	^ xPos @ actualPropWidth 
	! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/21/2020 15:13:55'!
widthsFor: visibleSubs within: overallWidth
	"Answer array of morphWidths for visibleSubs."
	"Preconditions: 
		ySepararations already subtracted from overallWidth.
		overallWidth is large enough to contain minimumLayoutWidths of visibleSubs."
	
	| numSubs scaleFactor widthToAllocate
	  sumOfFixedOrPropMin sumOfPropMin sumOfPropDesired sumOfFixedMin
	  allocatedWidths propIndices desiredProps
	  maxOfMinAllocWidth belowBalanceProps sumOfDeltas
	 |
	numSubs := visibleSubs size.
	sumOfFixedOrPropMin := 0.
	sumOfFixedMin := 0.
	sumOfPropMin := 0.
	sumOfPropDesired := 0. "sum of percentage fractions; may be more than 100%"
	allocatedWidths := Array ofSize: numSubs.
	desiredProps   := Array ofSize: numSubs.
	propIndices := Set new. "keep set of proportional morph indices"
	1 to: numSubs do: [ :index | | sm layoutWidthMin |
		sm := visibleSubs at: index.
		layoutWidthMin := sm minimumLayoutWidth.
		sumOfFixedOrPropMin := sumOfFixedOrPropMin +  layoutWidthMin.
		allocatedWidths at: index put: layoutWidthMin.
		(sm isProportionalWidth)
			ifTrue:  [ | propDesired |
				propIndices add: index.
				propDesired := sm layoutSpec privateProportionalWidth.
				desiredProps at: index put: propDesired.
				sumOfPropDesired := sumOfPropDesired + propDesired.
				sumOfPropMin := sumOfPropMin + layoutWidthMin.
			]
			ifFalse: [ "Allocate width for non-proportional-width morphs"
				sumOfFixedMin := sumOfFixedMin + layoutWidthMin.
			]
	 ].
"Transcript log: 'minAllocs=', allocatedWidths asString."
	(propIndices size > 0)
	 	ifTrue: [ propIndices := propIndices asArray reversed ]  "easy to index"
		ifFalse: [ ^ allocatedWidths ]. "already finished"
	((overallWidth - sumOfFixedOrPropMin) < 2) "@@tune@@"
		ifTrue: [ ^ allocatedWidths ]. "close enough"
			
	"All fixed widths allocated; rest is for proportional + leftOver"
	widthToAllocate := (overallWidth - sumOfFixedMin) max: 0.
	scaleFactor := 1.0 / (sumOfPropDesired max: 1.0).  "if > 100% then below 1"

	"Find the min alloc size at which adding width is above max of minWidths
	 Keep the proportions over the minWidths at this allocatin.
	"
	maxOfMinAllocWidth := propIndices max: [ :morphIndex | 
		(visibleSubs at: morphIndex) allocWidthForFactor: scaleFactor 
	].
	belowBalanceProps := Array ofSize: visibleSubs size.
	propIndices do: [ :morphIndex | | widthAtBalance | 
		widthAtBalance := maxOfMinAllocWidth * scaleFactor * (desiredProps at: morphIndex).
		belowBalanceProps at: morphIndex
							   put: widthAtBalance "delta above min width"
							   	- ((visibleSubs at: morphIndex) minimumLayoutWidth)
	].
	sumOfDeltas := belowBalanceProps sum: [ :b | b ifNil: [0]].
	(sumOfDeltas < 0.001) ifTrue: [
		propIndices do: [ :morphIndex |
				allocatedWidths at: morphIndex 
								put: (widthToAllocate 
										* scaleFactor 
										* (desiredProps at: morphIndex)).
		].
		^ allocatedWidths "space desired = 100%"
	].
	propIndices do: [ :morphIndex |  "normalize"
		belowBalanceProps
			at: morphIndex
			put: ((belowBalanceProps at: morphIndex) / sumOfDeltas)
	].
"Transcript log: 'belowBalanceProps=', belowBalanceProps asString.
Transcript log: 'widthToAllocate=', widthToAllocate asString,
				    ' maxOfMinAllocWidth=', maxOfMinAllocWidth asString.
"
     "Below the balance point, calculate proportions from belowBalanceProps,
	above, use desiredProps"
	"@@ reduce when sumOfPropDesired < 1@@"
	(widthToAllocate <= maxOfMinAllocWidth)
		ifTrue: [ "below balance point"
			(sumOfPropDesired < 1.0) "Trim off space to save"
				ifTrue: [ widthToAllocate := widthToAllocate * sumOfPropDesired ].
			propIndices do: [ :morphIndex | |  minWidth |
				minWidth := allocatedWidths at: morphIndex.
				allocatedWidths at: morphIndex
								put: (minWidth + 
									(((widthToAllocate - sumOfPropMin ) 
									* (belowBalanceProps at: morphIndex)) max: 0.0))
			]
		]
		ifFalse: [ "above balance point"
			propIndices do: [ :morphIndex |
				allocatedWidths at: morphIndex 
								put: (widthToAllocate * scaleFactor * (desiredProps at: morphIndex))
			]
		].
	
	^ allocatedWidths! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/21/2020 15:21:44'!
zheightsFor: visibleSubs within: overallHeight
	"Answer array of morphHeights for visibleSubs."
	"Preconditions: 
		ySepararations already subtracted from overallHeight.
		overallHeight is large enough to contain minimumLayoutHeights of visibleSubs."
	
	| numSubs scaleFactor heightToAllocate
	  sumOfFixedOrPropMin sumOfPropMin sumOfPropDesired sumOfFixedMin
	  allocatedHeights propIndices desiredProps
	  maxOfMinAllocHeight belowBalanceProps sumOfDeltas
	 |
	numSubs := visibleSubs size.
	sumOfFixedOrPropMin := 0.
	sumOfFixedMin := 0.
	sumOfPropMin := 0.
	sumOfPropDesired := 0. "sum of percentage fractions; may be more than 100%"
	allocatedHeights := Array ofSize: numSubs.
	desiredProps   := Array ofSize: numSubs.
	propIndices := Set new. "keep set of proportional morph indices"
	1 to: numSubs do: [ :index | | sm layoutHeightMin |
		sm := visibleSubs at: index.
		layoutHeightMin := sm minimumLayoutHeight.
		sumOfFixedOrPropMin := sumOfFixedOrPropMin +  layoutHeightMin.
		allocatedHeights at: index put: layoutHeightMin.
		(sm isProportionalHeight)
			ifTrue:  [ | propDesired |
				propIndices add: index.
				propDesired := sm layoutSpec privateProportionalHeight.
				desiredProps at: index put: propDesired.
				sumOfPropDesired := sumOfPropDesired + propDesired.
				sumOfPropMin := sumOfPropMin + layoutHeightMin.
			]
			ifFalse: [ "Allocate height for non-proportional-height morphs"
				sumOfFixedMin := sumOfFixedMin + layoutHeightMin.
			]
	 ].
"Transcript log: 'minAllocs=', allocatedHeights asString."
	(propIndices size > 0)
	 	ifTrue: [ propIndices := propIndices asArray reversed ]  "easy to index"
		ifFalse: [ ^ allocatedHeights ]. "already finished"
	((overallHeight - sumOfFixedOrPropMin) < 2) "@@tune@@"
		ifTrue: [ ^ allocatedHeights ]. "close enough"
			
	"All fixed heights allocated; rest is for proportional + leftOver"
	heightToAllocate := (overallHeight - sumOfFixedMin) max: 0.
	scaleFactor := 1.0 / (sumOfPropDesired max: 1.0).  "if > 100% then below 1"

	"Find the min alloc size at which adding height is above max of minHeights
	 Keep the proportions over the minHeights at this allocatin.
	"
	maxOfMinAllocHeight := propIndices max: [ :morphIndex | 
		(visibleSubs at: morphIndex) allocHeightForFactor: scaleFactor 
	].
	belowBalanceProps := Array ofSize: visibleSubs size.
	propIndices do: [ :morphIndex | | heightAtBalance | 
		heightAtBalance := maxOfMinAllocHeight * scaleFactor * (desiredProps at: morphIndex).
		belowBalanceProps at: morphIndex
							   put: heightAtBalance "delta above min height"
							   	- ((visibleSubs at: morphIndex) minimumLayoutHeight)
	].
	sumOfDeltas := belowBalanceProps sum: [ :b | b ifNil: [0]].
	(sumOfDeltas < 0.001) ifTrue: [
		propIndices do: [ :morphIndex |
				allocatedHeights at: morphIndex 
								put: (heightToAllocate 
										* scaleFactor 
										* (desiredProps at: morphIndex)).
		].
		^ allocatedHeights "space desired = 100%"
	].
	propIndices do: [ :morphIndex |  "normalize"
		belowBalanceProps
			at: morphIndex
			put: ((belowBalanceProps at: morphIndex) / sumOfDeltas)
	].
"Transcript log: 'belowBalanceProps=', belowBalanceProps asString.
Transcript log: 'heightToAllocate=', heightToAllocate asString,
				    ' maxOfMinAllocHeight=', maxOfMinAllocHeight asString.
"
     "Below the balance point, calculate proportions from belowBalanceProps,
	above, use desiredProps"
	"@@ reduce when sumOfPropDesired < 1@@"
	(heightToAllocate <= maxOfMinAllocHeight)
		ifTrue: [ "below balance point"
			(sumOfPropDesired < 1.0) "Trim off space to save"
				ifTrue: [ heightToAllocate := heightToAllocate * sumOfPropDesired ].
			propIndices do: [ :morphIndex | |  minHeight |
				minHeight := allocatedHeights at: morphIndex.
				allocatedHeights at: morphIndex
								put: (minHeight + 
									(((heightToAllocate - sumOfPropMin ) 
									* (belowBalanceProps at: morphIndex)) max: 0.0))
			]
		]
		ifFalse: [ "above balance point"
			propIndices do: [ :morphIndex |
				allocatedHeights at: morphIndex 
								put: (heightToAllocate * scaleFactor * (desiredProps at: morphIndex))
			]
		].
	
	^ allocatedHeights! !

!LayoutMorph methodsFor: 'testing' stamp: 'KenD 5/4/2020 12:58:45'!
isColumn

	^ direction = #vertical! !

!LayoutMorph methodsFor: 'testing' stamp: 'KenD 5/4/2020 12:57:59'!
isRow

	^ direction = #horizontal! !

!LayoutMorph methodsFor: 'private' stamp: 'KenD 5/5/2020 17:24:59'!
proportionalHeightNormalizationFactor

	| sumOfProportional |
	sumOfProportional _ self submorphsToLayout sum: [ :m | m layoutSpec proportionalLayoutHeight ].
	^1.0 / (sumOfProportional max: 1.0).! !


!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 4/30/2020 09:34:28'!
offAxisEdgeWeight
	^minorDirectionPadding! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 4/30/2020 11:42:46'!
offAxisEdgeWeight: aSymbolOrNumber
	"A LayoutSpec may indicate a weighting perpendicular to the Layout Axis.   
	
	 This is the LayoutSpec's offAxisEdgeWeight which is between 0.0 and 1.0.

	As with LayoutSpec's a symbol may be used.

	If in a Row (preferred): { #rowTop (0.0), #center (0.5), #rowBottom (1.0)}

	If in a Column (preferred): { #columnLeft (0.0), #center (0.5), #columnRight (1.0) }

	Also accepted: { #leftOrTop (0.0), #center (0.5), #rightOrBottom (1.0) }
	
	Because the layout axis is determined by the owning LayoutMorph,
	 we can't check directionality of symbols.
	The specificity allowed is to document a statement of programming intent.
	"
	| edgeWeight |
	edgeWeight := (aSymbolOrNumber is: #Number)
		ifTrue: [ (aSymbolOrNumber between: 0.0 and: 1.0)
			ifTrue: [ aSymbolOrNumber ] 
			ifFalse: [self error: 'axisEdgeWeight ', aSymbolOrNumber printString, ' is out of range 0.0 to 1.0']
		]
		ifFalse: [ aSymbolOrNumber
			caseOf: {
				[ #leftOrTop ] -> [ 0.0 ].
				[ #rowTop ] -> [ 0.0 ].
				[ #columnLeft ] -> [ 0.0 ].
				[ #center ] -> [ 0.5 ].
				[ #rightOrBottom ] -> [ 1.0 ].
				[ #rowBottom ] -> [ 1.0 ].
				[ #columnRight ] -> [ 1.0 ]
			}
			otherwise: [ self error: 'bad offAxisEdgeWeight specifier: ', aSymbolOrNumber  printString ]
		].
	minorDirectionPadding _ edgeWeight! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:52:07'!
fixedOrMorphHeight
	self flag: #depricated.
	^fixedHeight ifNil: [ morph morphHeight ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:51:58'!
fixedOrMorphWidth

	self flag: #depricated.
	^fixedWidth ifNil: [ morph morphWidth ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:51:04'!
minimumSpecExtent

	^ self minimumSpecWidth @ self minimumSpecHeight ! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:36:37'!
minimumSpecHeight
	"If fixedHeight is not nil, use it.  
	 If fixdHeight and propostionlHeight are nil, use morphHeight"

	^ fixedHeight ifNil: [ proportionalHeight ifNotNil: [ 0 ] ifNil: [ morph morphHeight ] ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/11/2020 12:37:14'!
minimumSpecWidth
	"If fixedWidth is not nil, use it.  
	 If fixdWidth and propostionlWidth are nil, use morphWidth"

	^ fixedWidth ifNil: [ proportionalWidth ifNotNil: [ 0 ] ifNil: [ morph morphWidth ] ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/5/2020 17:24:59'!
proportionalLayoutHeight

	^ proportionalHeight ifNil: [ 0 ]! !

!LayoutSpec methodsFor: '*morphic-misc1' stamp: 'KenD 4/18/2015 20:18'!
morph
	"For #showHalo"
	^ morph! !

!LayoutSpec methodsFor: '*morphic-misc1' stamp: 'KenD 12/24/2013 15:15'!
privateFixedWidth

	^ fixedWidth! !

!LayoutSpec methodsFor: '*morphic-misc1' stamp: 'KenD 12/24/2013 15:15'!
privateProportionalWidth

	^ proportionalWidth ! !


!Morph methodsFor: 'geometry' stamp: 'KenD 5/11/2020 12:39:18'!
minimumLayoutExtent
	"This returns the minimum extent that the morph may be shrunk to, 
	when resizing LayoutMorphs or when adjusting a LayoutAdjustingMorph. 
	It is expressed in the morph own coordinates, like morphExtent."

	"This method combines the information from a Morph and its optional LayoutSpec"
	| minExtent |
	minExtent _ self minimumExtent.
	^ layoutSpec
		ifNil: [ minExtent ]
		ifNotNil: [ minExtent max: ( layoutSpec minimumSpecWidth @ layoutSpec minimumSpecHeight ) ]! !


!BrowserCommentTextMorph methodsFor: 'displaying' stamp: 'KenD 5/5/2020 17:24:59'!
hidePane

	self hide.
	separator visible ifTrue: [
		proportionalHeight _ self layoutSpec proportionalLayoutHeight.
		separatorHeight _ separator layoutSpec fixedOrMorphHeight ].
	separator layoutSpec fixedHeight: 0.
	self layoutSpec proportionalHeight: 0.
	separator ifNotNil: [ separator hide ]! !


!LayoutMorph methodsFor: 'accessing' stamp: 'KenD 5/15/2020 17:49:30'!
addMorphFrontFromWorldPosition: aMorph

	aMorph layoutSpecOrNil ifNil: [aMorph layoutSpec: LayoutSpec keepMorphExtent ].
	self addMorphFront: aMorph.
	self layoutSubmorphs.
! !

!LayoutMorph methodsFor: 'adjust' stamp: 'KenD 5/5/2020 17:24:59'!
adjustVerticallyBy: aLayoutAdjustMorph at: aPoint
	| delta t ts b bs tNewHeight bNewHeight i tCurrentHeight bCurrentHeight |
	i _ submorphs indexOf: aLayoutAdjustMorph.
	t _ self submorphs at: i +1.
	ts _ t layoutSpec.
	tCurrentHeight _ t morphHeight max: 1.	"avoid division by zero"
	b _ self submorphs at: i - 1.
	bs _ b layoutSpec.
	bCurrentHeight _ b morphHeight max: 1.	"avoid division by zero"
	delta _ aPoint y - aLayoutAdjustMorph referencePosition y.
	delta _ delta max: t minimumLayoutExtent y - tCurrentHeight.
	delta _ delta min: bCurrentHeight - b minimumLayoutExtent y.
	delta = 0 ifTrue: [ ^self ].
	tNewHeight _ tCurrentHeight + delta.
	bNewHeight _ bCurrentHeight - delta.
	(ts isProportionalHeight and: [ bs isProportionalHeight ])
		ifTrue: [ | bottomNewProportion toDistribute topNewProportion |	"If both proportional, update them"
			topNewProportion _ tNewHeight / (tNewHeight + bNewHeight).
			bottomNewProportion _ 1.0 - topNewProportion.
			toDistribute _ ts proportionalLayoutHeight + bs proportionalLayoutHeight.
			ts setProportionalHeight: topNewProportion * toDistribute.
			bs setProportionalHeight: bottomNewProportion * toDistribute ]
		ifFalse: ["If at least one is fixed, update only the fixed"
			ts isProportionalHeight ifFalse: [
				ts fixedOrMorphHeight: tNewHeight ].
			bs isProportionalHeight ifFalse: [
				bs fixedOrMorphHeight: bNewHeight ]].
	self layoutSubmorphs! !

!LayoutMorph methodsFor: 'geometry' stamp: 'KenD 5/15/2020 19:24:31'!
minimumExtent
	"Answer size sufficient to frame my submorphs."
	
	| width height |
	width  := 0.
	height := 0.
	(self direction =  #vertical)
		ifTrue: [ "Column"
			self submorphsToLayout do: [ :sm | 
				"use maximum width across submorphs"
				width := width max: sm minimumLayoutWidth.
				"sum up submorph heights, including separation"
				height := height + (sm minimumLayoutHeight) + self ySeparation.
			].
			width  := width + (2 * self xSeparation). "separation on each side"
			height := height + self ySeparation. "one side already separated"
		]
		ifFalse: [ "Row"
			self submorphsToLayout do: [ :sm |
				"sum up submorphs width"
				width := width + (sm minimumLayoutWidth) + self xSeparation.
				"use maximum height across submorph"
				height := height max: sm minimumLayoutHeight.
			].
			height := height + (2 * self ySeparation). "separation on each side"
			width  := width + self xSeparation.       "one side already separated"
		].

	^ (width @ height) + self extentBorder! !

!LayoutMorph methodsFor: 'initialization' stamp: 'KenD 5/12/2020 09:23:30'!
beColumn
	direction _ #vertical.
	padding ifNil: [self padding: #center].
	self layoutSubmorphs.! !

!LayoutMorph methodsFor: 'initialization' stamp: 'KenD 5/12/2020 09:23:35'!
beRow
	direction _ #horizontal.
	padding ifNil: [self padding: #left].
	self layoutSubmorphs.! !

!LayoutMorph methodsFor: 'layout' stamp: 'pb 3/17/2020 13:41:27'!
layoutBounds
	"Return the bounds for laying out children of the receiver"

	^ self morphLocalBounds! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/9/2020 14:25:12'!
layoutSubmorphs
	"Compute a new layout based on the given layout bounds."

	submorphs isEmpty ifTrue: [
		layoutNeeded _ false.
		^self].

	"Invariant: morphExtent >=  minimumLayoutExtent"
	self refreshExtent.
	
	direction == #horizontal ifTrue: [
		self layoutSubmorphsHorizontallyIn: self layoutBounds ].

	direction == #vertical ifTrue: [
		self layoutSubmorphsVerticallyIn: self layoutBounds ].

	layoutNeeded _ false! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/12/2020 14:10:38'!
layoutSubmorphsHorizontallyIn: boundsForLayout
	"Compute a new layout based on the given layout bounds."

	| visibleSubmorphs sumOfWidths theSeparation widthsArray 
	widthToAllocate leftOver nextX | 
	"Preconditions: self isRow & morphExtent >= minimumLayoutExtent"
	visibleSubmorphs := self submorphsToLayout reversed.  "Display Order"
	theSeparation := self xSeparation.

	widthToAllocate := (boundsForLayout width - ((visibleSubmorphs size + 1) * theSeparation)).
	widthsArray := self widthsFor: visibleSubmorphs within: widthToAllocate.
	sumOfWidths := widthsArray sum: [ :w | w ] .
	leftOver := widthToAllocate - sumOfWidths.
	nextX := boundsForLayout origin x
				+ theSeparation 
				+ (leftOver * self axisEdgeWeight). "first X, edge shifted"
"Transcript log: 'first X=', nextX asString, ' leftOver=', leftOver asString; cr.
"	1 to: visibleSubmorphs size do: [ :index | | sm smX smWidth heightAndY newExtent |
		sm := visibleSubmorphs at: index.
		smX := nextX.
		smWidth := widthsArray at: index.
		nextX := smX + smWidth + theSeparation.
		heightAndY := self offHorizontalMetricFor: sm withinExtent: boundsForLayout.
		sm morphPosition: smX @ (heightAndY y).
		newExtent :=  smWidth @ (heightAndY x).
		(sm morphExtent = newExtent) ifFalse: [ sm morphExtent: newExtent ].
	]
! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/12/2020 14:09:59'!
layoutSubmorphsVerticallyIn: boundsForLayout
	"Compute a new layout based on the given layout bounds."

	| visibleSubmorphs sumOfHeights theSeparation heightsArray 
	heightToAllocate leftOver nextY | 
	"Preconditions: self isRow & morphExtent >= minimumLayoutExtent"
	visibleSubmorphs := self submorphsToLayout reversed.  "Display Order"

	theSeparation := self ySeparation.
	heightToAllocate := (boundsForLayout height - ((visibleSubmorphs size + 1) * theSeparation)).
	heightsArray := self heightsFor: visibleSubmorphs within: heightToAllocate.
	sumOfHeights := heightsArray sum: [ :w | w ] .
	leftOver := heightToAllocate - sumOfHeights.
	nextY := boundsForLayout origin y
				+ theSeparation 
				+ (leftOver * self axisEdgeWeight). "first Y, edge shifted"
"Transcript log: 'first Y=', nextY asString, ' leftOver=', leftOver asString; cr.
"	1 to: visibleSubmorphs size do: [ :index | | sm smY smHeight xAndWidth newExtent |
		sm := visibleSubmorphs at: index.
		smY := nextY.
		smHeight := heightsArray at: index.
		nextY := smY + smHeight + theSeparation.
		xAndWidth := self offVerticalMetricFor: sm withinExtent: boundsForLayout.
		sm morphPosition: (xAndWidth x) @ smY.
		newExtent :=  (xAndWidth y) @ smHeight.
		(sm morphExtent = newExtent) ifFalse: [ sm morphExtent: newExtent ].
	]
! !

!LayoutMorph methodsFor: 'layout' stamp: 'KenD 5/9/2020 14:24:33'!
refreshExtent
	"Invariant: my morphExtent >= my minimumExtent"
		
	self morphExtent: (self morphExtent max: self minimumExtent)! !


!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 5/5/2020 08:16:57'!
fixedOrMorphHeight: aNumber
	"aNumber is taken as the fixed height to use.
	No proportional part."
	fixedHeight
		ifNotNil: [ fixedHeight _ aNumber ]
		ifNil: [ fixedHeight _ aNumber.
			    morph morphHeight: aNumber 
		].
	proportionalHeight _ nil! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 5/5/2020 08:17:15'!
fixedOrMorphWidth: aNumber
	"aNumber is taken as the fixed width to use.
	No proportional part."
	fixedWidth
		ifNotNil: [ fixedWidth _ aNumber ]
		ifNil: [ fixedWidth _ aNumber. morph morphWidth: aNumber ].
	proportionalWidth _ nil! !

!methodRemoval: LayoutSpec #heightFor: stamp: 'KenD 5/21/2020 15:18:13'!
LayoutSpec removeSelector: #heightFor:!
!methodRemoval: LayoutSpec #proportionaLayoutlHeight stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #proportionaLayoutlHeight!
!methodRemoval: LayoutSpec #fixedOrMinimumLayoutWidth stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #fixedOrMinimumLayoutWidth!
!methodRemoval: LayoutSpec #widthFor: stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #widthFor:!
!methodRemoval: LayoutSpec #minimumLayoutHeight stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #minimumLayoutHeight!
!methodRemoval: LayoutSpec #minimumLayoutWidth stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #minimumLayoutWidth!
!methodRemoval: LayoutSpec #fixedOrMinimumLayoutHeight stamp: 'KenD 5/15/2020 14:02:11'!
LayoutSpec removeSelector: #fixedOrMinimumLayoutHeight!
!methodRemoval: LayoutMorph #test3widthsFor:within: stamp: 'KenD 5/21/2020 15:16:29'!
LayoutMorph removeSelector: #test3widthsFor:within:!
!methodRemoval: LayoutMorph #oRIGwidthsFor:within: stamp: 'KenD 5/21/2020 15:16:36'!
LayoutMorph removeSelector: #oRIGwidthsFor:within:!
!methodRemoval: LayoutMorph #proportionalWidthNormalizationFactor stamp: 'KenD 5/15/2020 14:02:11'!
LayoutMorph removeSelector: #proportionalWidthNormalizationFactor!

!Morph reorganize!
('accessing' adoptWidgetsColor: beSticky color location lock morphId resistsRemoval taskbar toggleStickiness unlock unlockContents)
('accessing - properties' hasProperty: isLocked isSticky lock: name name: removeProperty: setProperty:toValue: sticky: valueOfProperty: valueOfProperty:ifAbsent: valueOfProperty:ifPresentDo:)
('as yet unclassified' canDiscardEdits disregardUnacceptedEdits rotationDegrees: whenUIinSafeState:)
('caching' clearId fullReleaseCachedState releaseCachedState)
('change reporting' addedMorph: invalidateDisplayRect:from: invalidateLocalRect:)
('classification' isWorldMorph)
('copying' copy copyForClipboard duplicate)
('debug and other' addDebuggingItemsTo:hand: buildDebugMenu: inspectOwnerChain ownerChain resumeAfterDrawError resumeAfterStepError)
('drawing' addPossiblyUncoveredAreasIn:to: clipsLastSubmorph drawOn: drawingFails drawingFailsNot hide icon imageForm: imageForm:depth: isKnownFailing refreshWorld show visible visible:)
('dropping/grabbing' aboutToBeGrabbedBy: aboutToGrab: dropFiles: justDroppedInto:event: justGrabbedFrom: rejectDropMorphEvent: wantsDroppedMorph:event: wantsToBeDroppedInto:)
('e-toy support' embeddedInMorphicWindowLabeled: unlockOneSubpart wantsRecolorHandle)
('events' click:localPosition: doubleClick:localPosition: dragEvent:localPosition: keyDown: keyStroke: keyUp: mouseButton1Down:localPosition: mouseButton1Up:localPosition: mouseButton2Down:localPosition: mouseButton2Up:localPosition: mouseButton3Down:localPosition: mouseButton3Up:localPosition: mouseEnter: mouseHover:localPosition: mouseLeave: mouseMove:localPosition: mouseScroll:localPosition: mouseStillDown windowEvent:)
('event handling testing' allowsFilesDrop allowsMorphDrop allowsSubmorphDrag handlesKeyboard handlesMouseDown: handlesMouseHover handlesMouseOver: handlesMouseScroll: handlesMouseStillDown:)
('event handling' mouseButton2Activity mouseStillDownStepRate mouseStillDownThreshold)
('events-alarms' addAlarm:after: addAlarm:with:after: addAlarm:withArguments:after: alarmScheduler removeAlarm:)
('events-processing' containsPoint:event: dispatchEvent:localPosition: focusKeyboardFor: handleFocusEvent: processDropFiles:localPosition: processDropMorph:localPosition: processKeyDown:localPosition: processKeyUp:localPosition: processKeystroke:localPosition: processMouseDown:localPosition: processMouseEnter:localPosition: processMouseLeave:localPosition: processMouseMove:localPosition: processMouseOver:localPosition: processMouseScroll:localPosition: processMouseStillDown processMouseUp:localPosition: processUnknownEvent:localPosition: processWindowEvent:localPosition: rejectsEvent:)
('fileIn/out' prepareToBeSaved storeDataOn:)
('focus handling' hasKeyboardFocus hasMouseFocus keyboardFocusChange:)
('geometry' allocHeightForFactor: allocWidthForFactor: extentBorder externalize: externalizeDisplayBounds: externalizeDistance: externalizeDistanceToWorld: externalizeToWorld: fontPreferenceChanged internalize: internalizeDistance: internalizeDistanceFromWorld: internalizeFromWorld: minimumExtent minimumLayoutExtent morphAlign:with: morphBounds morphBounds: morphBoundsInWorld morphBoundsInWorld: morphExtent morphExtent: morphExtentInWorld morphExtentInWorld: morphFullBoundsInWorld morphHeight morphLocalBounds morphPosition morphPosition: morphPositionInWorld morphPositionInWorld: morphTopLeft morphWidth rotateBy: rotation:scale: scaleBy: worldBoundsForHalo)
('geometry eToy' referencePosition referencePosition:)
('geometry testing' fullContainsPoint: isOrthoRectangularMorph morphContainsPoint:)
('halos and balloon help' addHalo addHalo: addHalo:from: addHandlesTo:box: addOptionalHandlesTo:box: balloonHelpDelayTime balloonText comeToFrontAndAddHalo deleteBalloon editBalloonHelpContent: editBalloonHelpText halo mouseDownOnHelpHandle: noHelpString okayToBrownDragEasily okayToResizeEasily okayToRotateEasily removeHalo setBalloonText: showBalloon: showBalloon:hand: transferHalo:from: wantsBalloon wantsHalo wantsHaloHandleWithSelector:inHalo:)
('initialization' inATwoWayScrollPane initialize intoWorld: openInHand openInWorld openInWorld:)
('iteration of all morphs' nextMorph nextMorphPart2 nextMorphThat: previousMorph previousMorphThat:)
('layout' acceptDroppingMorph:event: layoutSubmorphs layoutSubmorphsIfNeeded minItemWidth minLayoutHeight minLayoutWidth minimumLayoutHeight minimumLayoutWidth requiredWidthOrSpec someSubmorphPositionOrExtentChanged)
('layout-properties' layoutSpec layoutSpec: layoutSpecOrNil)
('macpal' flash flashWith:)
('menus' addAddHandMenuItemsForHalo:hand: addColorMenuItems:hand: addCopyItemsTo: addCustomHaloMenuItems:hand: addExportMenuItems:hand: addHaloActionsTo: addStandardHaloMenuItemsTo:hand: addTitleForHaloMenu: addToggleItemsToHaloMenu: expand exportAsBMP exportAsJPEG lockUnlockMorph lockedString maybeAddCollapseItemTo: stickinessString)
('meta-actions' addEmbeddingMenuItemsTo:hand: buildHandleMenu: copyToClipboard: dismissMorph duplicateMorph: maybeDuplicateMorph potentialEmbeddingTargets resizeFromMenu resizeMorph)
('naming' label)
('object serialization' objectForDataStream:)
('player' okayToDuplicate)
('printing' printOn:)
('rotate scale and flex' rotationDegrees)
('stepping' shouldGetStepsFrom: startStepping startStepping: startStepping:in:stepTime: startStepping:stepTime: startSteppingStepTime: step stepAt: stopStepping stopStepping: wantsSteps)
('structure' allOwnersDo: allOwnersReverseDo: firstOwnerSuchThat: hasOwner: isInWorld owner owningWindow root veryLastLeaf withAllOwnersDo: withAllOwnersReverseDo: world)
('submorphs-accessing' allMorphsDo: clippedSubmorph findDeepSubmorphThat:ifAbsent: findSubmorphBinary: firstSubmorph hasSubmorphs lastSubmorph noteNewOwner: submorphBehind: submorphCount submorphInFrontOf: submorphs submorphsBehind:do: submorphsDo: submorphsDrawingOutsideReverseDo: submorphsInFrontOf:do: submorphsReverseDo: submorphsSatisfying: unclippedSubmorphsReverseDo:)
('submorphs-add/remove' addAllMorphs: addAllMorphs:after: addMorph: addMorph:behind: addMorph:inFrontOf: addMorph:position: addMorphBack: addMorphBack:position: addMorphFront: addMorphFront:position: addMorphFrontFromWorldPosition: atFront comeToFront delete dismissViaHalo goBehind privateDelete removeAllMorphs removeAllMorphsIn: removeMorph: removedMorph: replaceSubmorph:by:)
('testing' hasModel is: isCollapsed isOpaqueMorph isOwnedByHand isOwnedByWorld isProportionalHeight isProportionalWidth isReallyVisible stepTime)
('updating' redrawNeeded)
('user interface' activateWindow activateWindowAndSendTopToBack: collapse showAndComeToFront toggleCollapseOrShow)
('private' privateAddAllMorphs:atIndex: privateAddMorph:atIndex: privateAddMorph:atIndex:position: privateAnyOwnerHandlesMouseScroll: privateOwner: privatePosition: privateRemove: privateSubmorphs)
('previewing' beginPreview endPreview endPreviewAndToggleCollapseOrShow morphBehindBeforePreview morphBehindBeforePreview: previewing previewing: visibleBeforePreview visibleBeforePreview:)
('*morphic-misc1' addCustomMenuItems:hand: boxExtent changeColor colorizeLayouts containingLayout editMyLayoutSpec frameLayouts:depth: frameNonLayouts:depth: messageWindow nameForWorkspace shadowNonLayouts showDropTarget showLayouts showNonLayouts signMorphForMe unShadowNonLayouts)
('*morph-metaproperties' morphForDrag openVisualPropertyEditor propertiesDict valueWhenDropped)
!


!LayoutMorph reorganize!
('accessing' addMorphFrontFromWorldPosition: adoptWidgetsColor: axisEdgeWeight axisEdgeWeight: direction padding: separation: xSeparation ySeparation)
('adjust' adjustBy:at: adjustHorizontallyBy:at: adjustVerticallyBy:at:)
('convenience methods' addAdjusterAndMorph:fixedHeight: addAdjusterAndMorph:layoutSpec: addAdjusterAndMorph:proportionalHeight: addAdjusterAndMorph:proportionalWidth: addMorph:fixedHeight: addMorph:fixedWidth: addMorph:proportionalHeight: addMorph:proportionalWidth: addMorphKeepMorphHeight: addMorphUseAll: addMorphs: addMorphs:widthProportionalTo:)
('geometry' minimumExtent)
('initialization' beColumn beRow defaultColor doAdoptWidgetsColor initialize)
('layout' heightsFor:within: layoutBounds layoutSubmorphs layoutSubmorphsHorizontallyIn: layoutSubmorphsVerticallyIn: offHorizontalMetricFor:withinExtent: offVerticalMetricFor:withinExtent: refreshExtent submorphsToLayout widthsFor:within: zheightsFor:within:)
('submorphs-add/remove' addAdjusterMorph addMorph: addMorph:layoutSpec:)
('testing' is: isColumn isRow)
('private' proportionalHeightNormalizationFactor)
('layout in owner' layoutSpec)
('*morphic-misc1' addCustomMenuItems:hand: direction: editMe padding)
!


!LayoutSpec reorganize!
('initialization' initialize)
('accessing' fixedHeight: fixedOrMorphHeight: fixedOrMorphWidth: fixedWidth: minorDirectionPadding minorDirectionPadding: morph: offAxisEdgeWeight offAxisEdgeWeight: proportionalHeight: proportionalHeight:minimum: proportionalWidth: proportionalWidth:minimum: setProportionalHeight: setProportionalWidth: useMorphHeight useMorphWidth)
('layout' fixedOrMorphHeight fixedOrMorphWidth minimumSpecExtent minimumSpecHeight minimumSpecWidth proportionalLayoutHeight proportionalLayoutWidth)
('testing' isProportionalHeight isProportionalWidth usesMorphExtent usesMorphHeight usesMorphWidth)
('*morphic-misc1' morph privateFixedHeight privateFixedWidth privateProportionalHeight privateProportionalWidth)
!

