'From Cuis 6.0 [latest update: #5969] on 4 August 2023 at 8:13:28 am'!
!classDefinition: #LayoutSpec category: #'Morphic-Layouts'!
Object subclass: #LayoutSpec
	instanceVariableNames: 'morph fixedWidth fixedHeight offAxisEdgeWeight proportionalWidth proportionalHeight'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-Layouts'!
!LayoutSpec commentStamp: 'jmv 9/3/2018 00:07:43' prior: 0!
LayoutSpecs are the basis for the layout mechanism. Any Morph can be given a LayoutSpec, but in order to honor it, its owner must be a LayoutMorph.

A LayoutSpec specifies how a morph wants to be layed out. It can specify either a fixed width or a fraction of some available owner width. Same goes for height. If a fraction is specified, a minimum extent is also possible.


Alternatives:
	- proportionalWidth notNil, fixedWidth notNil	->		Use fraction of available space, take fixedWidth as minimum desired width
	- proportionalWidth isNil, fixedWidth isNil		->		Use current morph width
	- proportionalWidth isNil, fixedWidth notNil		->		Use fixedWidth
	- proportionalWidth notNil, fixedWidth isNil		->		NOT VALID

Same goes for proportionalHeight and fixedHeight
!


!LayoutSpec methodsFor: 'initialization' stamp: 'KenD 6/4/2020 13:11:57'!
initialize
	"Just some reasonable defaults, use all available space"
	offAxisEdgeWeight _ 0.5.
	fixedWidth _ 0.
	fixedHeight _ 0.
	proportionalWidth _ 1.0.
	proportionalHeight _ 1.0! !


!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 9/28/2021 15:19:43'!
fixedHeight
	^proportionalHeight isNil ifTrue: [fixedHeight ifNil: [morph morphExtentInOwner y]] ifFalse: [ 0 ]! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:11:42'!
fixedHeight: aNumber
	"aNumber is taken as the fixed height to use.
	No proportional part."
	fixedHeight := aNumber.
	proportionalHeight := nil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 9/28/2021 15:22:19'!
fixedOrMorphHeight: aNumber
	"aNumber is taken as the fixed height to use.
	No proportional part."
	fixedHeight
		ifNotNil: [ fixedHeight _ aNumber ]
		ifNil: [ fixedHeight _ aNumber.
			  morph morphHeightInOwner: aNumber 
		].
	proportionalHeight _ nil! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:11:58'!
fixedOrMorphWidth: aNumber
	"aNumber is taken as the fixed width to use.
	No proportional part."
	fixedWidth
		ifNotNil: [ fixedWidth := aNumber ]
		ifNil: [ fixedWidth := aNumber.
			morph morphWidthInOwner: aNumber ].
	proportionalWidth := nil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 9/28/2021 15:20:04'!
fixedWidth
	^proportionalWidth isNil ifTrue: [fixedWidth ifNil: [morph morphExtentInOwner x]] ifFalse: [ 0 ]! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:12:04'!
fixedWidth: aNumber
	"aNumber is taken as the fixed width to use.
	No proportional part."
	fixedWidth := aNumber.
	proportionalWidth := nil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 2/23/2011 14:46'!
morph: aMorph
	morph _ aMorph! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 9/28/2021 12:37:14'!
offAxisEdgeWeight
	^offAxisEdgeWeight ifNil: [ 0.5 ]! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:12:19'!
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) }
	"
	| 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 ]
		].
	offAxisEdgeWeight := edgeWeight.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 8/25/2010 13:55'!
proportionalHeight: aNumber
	^self proportionalHeight: aNumber minimum: 0.0! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:12:44'!
proportionalHeight: aNumberOrNil minimum: otherNumberOrNil
	"Alternatives: same as in #proportionalWidth:minimum:, see comment there"
	proportionalHeight := aNumberOrNil.
	fixedHeight := otherNumberOrNil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'jmv 8/25/2010 13:55'!
proportionalWidth: aNumber
	^self proportionalWidth: aNumber minimum: 0! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:12:50'!
proportionalWidth: aNumberOrNil minimum: otherNumberOrNil
	"Alternatives:
		- proportionalWidth notNil, fixedWidth notNil 	->		Use fraction of available space, take fixedWidth as minimum desired width
		- proportionalWidth isNil, fixedWidth isNil  	->		Use current morph width
		- proportionalWidth isNil, fixedWidth notNil 	->		Use fixedWidth
		- proportionalWidth notNil, fixedWidth isNil 	->		NOT VALID"
	proportionalWidth := aNumberOrNil.
	fixedWidth := otherNumberOrNil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:13:01'!
setProportionalHeight: aNumberOrNil
	"Alternatives: same as in #proportionalWidth:minimum:, see comment there"
	proportionalHeight := aNumberOrNil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:13:07'!
setProportionalWidth: aNumberOrNil
	"Alternatives:
		- proportionalWidth notNil, fixedWidth notNil	->		Use fraction of available space, take fixedWidth as minimum desired width
		- proportionalWidth isNil, fixedWidth isNil		->		Use current morph width
		- proportionalWidth isNil, fixedWidth notNil		->		Use fixedWidth
		- proportionalWidth notNil, fixedWidth isNil		->		NOT VALID"
	proportionalWidth := aNumberOrNil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:13:15'!
useMorphHeight
	"Do not attempt to layout height. Use current morph height if at all possible."
	fixedHeight := nil.
	proportionalHeight := nil.
	self updateContainingLayout.! !

!LayoutSpec methodsFor: 'accessing' stamp: 'KenD 8/4/2023 08:13:21'!
useMorphWidth
	"Do not attempt to layout width. Use current morph width if at all possible."
	fixedWidth := nil.
	proportionalWidth := nil.
	self updateContainingLayout.! !


!LayoutSpec methodsFor: 'layout' stamp: 'jmv 9/28/2021 15:19:48'!
fixedOrMinimumLayoutHeight
	^fixedHeight ifNil: [ morph morphExtentInOwner y ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'jmv 9/28/2021 15:20:00'!
fixedOrMinimumLayoutWidth
	^fixedWidth ifNil: [ morph morphExtentInOwner x ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/28/2020 21:35:37'!
minimumShrinkHeight
	"Generally prefer asking the morph itself!!"

	proportionalHeight ifNil: [ ^0 ].
	^fixedHeight ifNil: [0]! !

!LayoutSpec methodsFor: 'layout' stamp: 'KenD 5/28/2020 21:35:20'!
minimumShrinkWidth
	"Generally prefer asking the morph itself!!"

	proportionalWidth ifNil: [ ^0 ].
	^fixedWidth ifNil: [0]! !

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

	^ self minimumSpecWidth @ self minimumSpecHeight ! !

!LayoutSpec methodsFor: 'layout' stamp: 'jmv 9/28/2021 15:19:55'!
minimumSpecHeight
	"If fixedHeight is not nil, use it.  
	 If fixdHeight and propostionlHeight are nil, use morphHeight"

	^ fixedHeight ifNil: [ proportionalHeight ifNotNil: [ 0 ] ifNil: [ morph morphExtentInOwner y ] ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'jmv 9/28/2021 15:20:08'!
minimumSpecWidth
	"If fixedWidth is not nil, use it.  
	 If fixdWidth and propostionlWidth are nil, use morphWidth"

	^ fixedWidth ifNil: [ proportionalWidth ifNotNil: [ 0 ] ifNil: [ morph morphExtentInOwner x ] ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'jmv 3/6/2020 18:02:32'!
proportionaLayoutlHeight

	^ proportionalHeight ifNil: [ 0 ]! !

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

	^ proportionalHeight ifNil: [ 0 ]! !

!LayoutSpec methodsFor: 'layout' stamp: 'jmv 3/6/2020 18:03:02'!
proportionalLayoutWidth

	^ proportionalWidth ifNil: [ 0 ]! !


!LayoutSpec methodsFor: 'testing' stamp: 'jmv 4/18/2022 10:51:25'!
isProportionalHeight
	"Zero actuaqlly means fixed height."

	^ proportionalHeight notNil and: [ proportionalHeight isZero not ].! !

!LayoutSpec methodsFor: 'testing' stamp: 'jmv 4/18/2022 10:50:58'!
isProportionalWidth
	"Zero actuaqlly means fixed width."

	^ proportionalWidth notNil and: [ proportionalWidth isZero not ].! !

!LayoutSpec methodsFor: 'testing' stamp: 'jmv 2/16/2016 13:14'!
usesMorphExtent
	"Does not attempt to layout width or height. Uses current morph extent."

	^fixedWidth isNil and: [ proportionalWidth isNil 
		and: [ fixedHeight isNil and: [ proportionalHeight isNil ]]]! !

!LayoutSpec methodsFor: 'testing' stamp: 'jmv 2/16/2016 13:12'!
usesMorphHeight
	"Does not attempt to layout height. Uses current morph height."

	^fixedHeight isNil and: [ proportionalHeight isNil ]! !

!LayoutSpec methodsFor: 'testing' stamp: 'jmv 2/16/2016 13:12'!
usesMorphWidth
	"Does not attempt to layout width. Uses current morph width."

	^fixedWidth isNil and: [ proportionalWidth isNil ]! !


!LayoutSpec methodsFor: 'private' stamp: 'KenD 8/4/2023 08:10:56'!
updateContainingLayout

	self morph 
		ifNotNil: [ :myMorph |
			myMorph containingLayout 
				ifNotNil: [ :myLayout | myLayout layoutSubmorphs ]
		].! !


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

!LayoutSpec methodsFor: '*ui-layout-panel' stamp: 'KenD 12/24/2013 15:14'!
privateFixedHeight

	^ fixedHeight! !

!LayoutSpec methodsFor: '*ui-layout-panel' stamp: 'KenD 12/24/2013 15:15'!
privateFixedWidth

	^ fixedWidth! !

!LayoutSpec methodsFor: '*ui-layout-panel' stamp: 'KenD 12/24/2013 15:15'!
privateProportionalHeight

	^ proportionalHeight! !

!LayoutSpec methodsFor: '*ui-layout-panel' stamp: 'KenD 12/24/2013 15:15'!
privateProportionalWidth

	^ proportionalWidth ! !


!LayoutSpec methodsFor: '*ui-metaproperties' stamp: 'KenD 12/14/2021 12:44:31'!
icon

	^ VisualPropertyMenuItem layoutIcon ! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

!classDefinition: 'LayoutSpec class' category: #'Morphic-Layouts'!
LayoutSpec class
	instanceVariableNames: ''!

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 12/20/2010 18:34'!
fixedExtent: aPoint
	^ self fixedWidth: aPoint x fixedHeight: aPoint y! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:07'!
fixedHeight: aNumber
	"Will use all available width"
	^self new fixedHeight: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:07'!
fixedWidth: aNumber
	"Will use all available height"
	^self new fixedWidth: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 12/9/2010 10:33'!
fixedWidth: aNumber fixedHeight: otherNumber
	^ LayoutSpec new
		fixedWidth: aNumber;
		fixedHeight: otherNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'KenD 5/22/2020 13:49:12'!
fixedWidth: aNumber fixedHeight: otherNumber offAxisEdgeWeight: aSymbolOrNumber
	^ LayoutSpec new
		fixedWidth: aNumber;
		fixedHeight: otherNumber;
		offAxisEdgeWeight: aSymbolOrNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:12'!
fixedWidth: aNumber proportionalHeight: otherNumber

	^self new
		fixedWidth: aNumber;
		proportionalHeight: otherNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'KenD 5/22/2020 13:54:56'!
fixedWidth: aNumber proportionalHeight: otherNumber offAxisEdgeWeight: aSymbolOrNumber

	^self new
		fixedWidth: aNumber;
		proportionalHeight: otherNumber;
		offAxisEdgeWeight: aSymbolOrNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 2/24/2011 12:29'!
keepMorphExtent
	^self new
		useMorphWidth;
		useMorphHeight! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 12/30/2011 11:59'!
morphHeightFixedWidth: aNumber

	^self new
		fixedWidth: aNumber;
		useMorphHeight! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/27/2010 10:27'!
morphHeightProportionalWidth: aNumber

	^self new
		proportionalWidth: aNumber;
		useMorphHeight! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 12/30/2011 12:00'!
morphWidthFixedHeight: aNumber

	^self new
		useMorphWidth;
		fixedHeight: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/27/2010 10:28'!
morphWidthProportionalHeight: aNumber

	^self new
		useMorphWidth;
		proportionalHeight: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:07'!
proportionalHeight: aNumber
	"Will use all available width"
	^self new proportionalHeight: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:07'!
proportionalWidth: aNumber
	"Will use all available height"
	^self new proportionalWidth: aNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:13'!
proportionalWidth: aNumber fixedHeight: otherNumber

	^self new
		proportionalWidth: aNumber;
		fixedHeight: otherNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'KenD 5/22/2020 13:55:19'!
proportionalWidth: aNumber fixedHeight: otherNumber offAxisEdgeWeight: aSymbolOrNumber

	^self new
		proportionalWidth: aNumber;
		fixedHeight: otherNumber;
		offAxisEdgeWeight: aSymbolOrNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:18'!
proportionalWidth: aNumber proportionalHeight: otherNumber

	^self new
		proportionalWidth: aNumber;
		proportionalHeight: otherNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'KenD 5/22/2020 13:56:21'!
proportionalWidth: aNumber proportionalHeight: otherNumber offAxisEdgeWeight: aSymbolOrNumber

	^self new
		proportionalWidth: aNumber;
		proportionalHeight: otherNumber;
		offAxisEdgeWeight: aSymbolOrNumber! !

!LayoutSpec class methodsFor: 'instance creation' stamp: 'jmv 8/25/2010 14:09'!
useAll
	"Use all available space"
	^self new! !
