requires: {#SceneElement}. provides: {#SpaceRequirement. #Layout. #Alignment. #Rack. #Box. #Border. #Restraint. #BulletinBoard}. Graphics addPrototype: #SpaceRequirement derivedFrom: {Cloneable}. SpaceRequirement addSlot: #preferredWidth valued: 0. SpaceRequirement addSlot: #preferredHeight valued: 0. SpaceRequirement addSlot: #maxX. SpaceRequirement addSlot: #maxY. SpaceRequirement addSlot: #minX. SpaceRequirement addSlot: #minY. "The size slots are points specifying (width,height) parameters for each requested option. The coordinates may be dimensioned, but if not, are interpreted as fractions of the container size. If Nil, min and max default to the preferred values. Don't access the fooX slots directly, as they have wrappers to handle defaults." sr@(SpaceRequirement traits) newPreferred: pref max: max min: min [| newSR | newSR: sr clone. newSR preferredWidth: pref x. newSR preferredHeight: pref y. newSR maxX: max x. newSR maxY: max y. newSR minX: min x. newSR minY: min y. newSR ]. Graphics addSlot: #EmptySpaceRequirement valued: (SpaceRequirement newPreferred: Point origin max: Point origin min: Point origin). sr@(SpaceRequirement traits) zero "A convenient accessor." [EmptySpaceRequirement]. sr@(SpaceRequirement traits) reset "Resets all parameters, causing the defaults to be active." [ sr preferredWidth: Nil. sr preferredHeight: Nil. sr maxX: Nil. sr maxY: Nil. sr minX: Nil. sr minY: Nil. sr ]. sr@(SpaceRequirement traits) minWidth [ sr minX ifNil: [sr preferredWidth] ]. sr@(SpaceRequirement traits) minHeight [ sr minY ifNil: [sr preferredHeight] ]. sr@(SpaceRequirement traits) maxWidth [ sr maxX ifNil: [sr preferredWidth] ]. sr@(SpaceRequirement traits) maxHeight [ sr maxY ifNil: [sr preferredHeight] ]. sr@(SpaceRequirement traits) minWidth: n [ sr minX: n ]. sr@(SpaceRequirement traits) minHeight: n [ sr minY: n ]. sr@(SpaceRequirement traits) maxWidth: n [ sr maxX: n ]. sr@(SpaceRequirement traits) maxHeight: n [ sr maxY: n ]. sr@(SpaceRequirement traits) preferredSize [ Point x: sr preferredWidth y: sr preferredHeight ]. sr@(SpaceRequirement traits) preferredSize: n@(Number traits) [ sr preferredX: n. sr preferredY: n. n ]. sr@(SpaceRequirement traits) preferredSize: p@(Point traits) [ sr preferredX: p x. sr preferredY: p y. p ]. sr1@(SpaceRequirement traits) with: sr2@(SpaceRequirement traits) collect: block into: result "Fills a SpaceRequirement's slots with the results of applying the given block to each pair of slots from the originals." [ result preferredWidth: (block applyWith: r preferredWidth with: sr2 preferredWidth). result preferredHeight: (block applyWith: r preferredHeight with: sr2 preferredHeight). result maxX: (block applyWith: r maxWidth with: sr2 maxWidth). result maxY: (block applyWith: r maxHeight with: sr2 maxHeight). result minX: (block applyWith: r maxWidth with: sr2 maxWidth). result minY: (block applyWith: r maxHeight with: sr2 maxHeight). result ]. sr1@(SpaceRequirement traits) with: sr2@(SpaceRequirement traits) collect: block "Returns a new SpaceRequirement, whose slots are the results of applying the given block to each pair of slots from the originals." [ sr1 with: sr2 collect: block into: sr1 clone ]. sr@(SpaceRequirement traits) collect: block into: result "Fills a SpaceRequirement's slots with the results of applying the given block to each slot value in the original." [ result preferredWidth: (block applyWith: sr preferredWidth). result preferredHeight: (block applyWith: sr preferredHeight). result maxX: (block applyWith: sr maxWidth). result maxY: (block applyWith: sr maxHeight). result minX: (block applyWith: sr maxWidth). result minY: (block applyWith: sr maxHeight). result ]. sr@(SpaceRequirement traits) collect: block "Returns a new SpaceRequirement, whose slots are the results of applying the given block to each slot value in the original." [ sr collect: block into: sr clone ]. sr1@(SpaceRequirement traits) + sr2@(SpaceRequirement traits) [sr1 with: sr2 collect: [| :a :b | a + b]]. sr1@(SpaceRequirement traits) - sr2@(SpaceRequirement traits) [sr1 with: sr2 collect: [| :a :b | a - b]]. sr@(SpaceRequirement traits) * n [sr collect: [| :dim | dim * n]]. sr@(SpaceRequirement traits) / n [sr collect: [| :dim | dim / n]]. sr@(SpaceRequirement traits) + n@(Magnitude traits) [sr collect: [| :dim | dim * n]]. sr@(SpaceRequirement traits) - n@(Magnitude traits) [sr collect: [| :dim | dim - n]]. SceneElement addSlot: #spaceRequirements valued: SpaceRequirement zero. se@(SceneElement traits) emptySpaceRequirement "This returns the default space requirements for leaf elements. Override it as necessary." [ SpaceRequirement zero ]. se@(SceneElement traits) childrensSpaceRequirements [ se children collect: [| :each | each spaceRequirements] ]. se@(SceneElement traits) composeSpace "Recurses through its children to compose their SpaceRequirement objects, accumulating them into the element's own." [| newSR | newSR: se emptySpaceRequirement clone. se children do: [| :each | each composeSpace]. se childrensSpaceRequirements do: [| :each | each with: newSR collect: [| :a :b | a + b] into: newSR]. newSR ]. se@(SceneElement traits) composeSpaceWithinExtent: point "Accomplishes the same task as composeSpace, but giving top-down hints on the dimensions of the result." [ ]. se@(SceneElement traits) allocateSpaceWithinExtent: point "Accomplishes the sub-task of allocateSpace, with top-down requirements on the dimensions of the result." [ ]. se@(SceneElement traits) allocateSpace "Arrange the element's children within the available space and allocate space to them according to their space requirements and its own composition rules by calling allocateSpace on each of the children." [ se allocateSpaceWithinExtent: se boundingBox extent ]. se@(SceneElement traits) spaceRequirements: sr@(SpaceRequirement traits) "This is called to indicate that composeSpace may now return something different from previous invocations and/or to update the user SpaceRequirement options." [ resend. se treeParent ifNotNil: [se treeParent noteSpaceRequirementsChangedFor: se] ]. se@(SceneElement traits) noteSpaceRequirementsChangedFor: ch@(SceneElement traits) "This is the size update notification handler. Override this to invoke different sizing behaviors." [ se spaceRequirements: se composeSpaceRequirements ]. Graphics addPrototype: #Alignment derivedFrom: {SceneElement}. Graphics addPrototype: #HorizontalAlignment derivedFrom: {Alignment}. Graphics addPrototype: #VerticalAlignment derivedFrom: {Alignment}. Graphics addPrototype: #Layout derivedFrom: {Morph}. Layout addSlot: #xSpacing valued: 0. Layout addSlot: #ySpacing valued: 0. "x and y-spacing specify how much space should be between submorphs." Layout addSlot: #alignmentX. Layout addSlot: #alignmentY. "Alignment values can be one of those below or Nil, which specifies none." Graphics addSlot: #HorizontalAlignments valued: ({#left. #center. #right} as: ExtensibleArray). Graphics addSlot: #VerticalAlignments valued: ({#top. #center. #bottom} as: ExtensibleArray). lm@(Layout traits) spacing [Point x: lm xSpacing y: lm ySpacing]. lm@(Layout traits) spacing: p@(Point traits) [ lm xSpacing: p x. lm ySpacing: p y. p ]. Graphics addPrototype: #HBox derivedFrom: {Layout}. hb@(HBox traits) composeSpace [| newSR | newSR: hb emptySpaceRequirement clone. hb childrensSpaceRequirements do: [| :each | newSR preferredHeight: newSR preferredHeight + each preferredHeight. newSR preferredWidth: (newSR preferredWidth max: each preferredWidth). newSR maxHeight: (newSR maxHeight max: each maxHeight). newSR maxWidth: newSR maxWidth + each maxWidth. newSR minHeight: (newSR minHeight max: each minHeight). newSR minWidth: newSR minWidth + each minWidth]. newSR ]. Graphics addPrototype: #VBox derivedFrom: {Layout}. vb@(VBox traits) composeSpace [| newSR | newSR: vb emptySpaceRequirement clone. vb childrensSpaceRequirements do: [| :each | newSR preferredHeight: newSR preferredHeight + each preferredHeight. newSR preferredWidth: (newSR preferredWidth max: each preferredWidth). newSR maxHeight: newSR maxHeight + each maxHeight. newSR maxWidth: (newSR maxWidth max: each maxWidth). newSR minHeight: newSR minHeight + each minHeight. newSR minWidth: (newSR minWidth max: each minWidth)]. newSR ]. Graphics addPrototype: #Rack derivedFrom: {Layout}. "Racks hold many elements in a row of the same element thickness. It will regularize the elements' thicknesses when composing them as best it can." Graphics addPrototype: #HRack derivedFrom: {Rack}. hr@(HRack traits) composeSpace [| newSR unitSR | newSR: hr emptySpaceRequirement clone. unitSR: EmptySpaceRequirement. hr childrensSpaceRequirements do: [| :each | newSR preferredHeight: (height max: each preferredHeight). unitSR preferredWidth: (width max: each preferredWidth). newSR maxHeight: (newSR maxHeight max: each maxHeight). unitSR maxWidth: (newSR maxWidth max: each maxWidth). newSR minHeight: (newSR minHeight max: each minHeight). unitSR minWidth: (newSR minWidth max: each minWidth)]. newSR: newSR + unitSR * hr children size. newSR ]. Graphics addPrototype: #VRack derivedFrom: {Rack}. vr@(VRack traits) composeSpace [| newSR unitSR | newSR: vr emptySpaceRequirement clone. unitSR: EmptySpaceRequirement. vr childrensSpaceRequirements do: [| :each | unitSR preferredHeight: (height max: each preferredHeight). newSR preferredWidth: (width max: each preferredWidth). unitSR maxHeight: (newSR maxHeight max: each maxHeight). newSR maxWidth: (newSR maxWidth max: each maxWidth). unitSR minHeight: (newSR minHeight max: each minHeight). newSR minWidth: (newSR minWidth max: each minWidth)]. newSR: newSR + unitSR * vr children size. newSR ]. Graphics addPrototype: #Stack derivedFrom: {Layout}. "Lays out elements one on top of the next, with an alignment." Graphics addPrototype: #Table derivedFrom: {Layout}. "Lays out a 2-dimensional spread of rows and columns of elements." Table addSlot: #numRows valued: 0. Table addSlot: #numColumns valued: 0. Table addSlot: #rowHeights. Table addSlot: #rowWidths. Graphics addPrototype: #Grid derivedFrom: {Layout}. "Same as a Table, but each cell is of the same size." Graphics addPrototype: #Spacing derivedFrom: {Layout}. "Lays out exactly one child with a spacing border." Graphics addPrototype: #Border derivedFrom: {Layout}. "Same as a Spacing, but with a drawn border." Graphics addPrototype: #Restraint derivedFrom: {Layout}. "Prevents the size constraints of the child from propagating beyond this element." rm@(Restraint traits) noteSpaceRequirementsChangedFor: ch@(Morph traits) "Do nothing." []. Graphics addPrototype: #BulletinBoard derivedFrom: {Layout}. "Same as Squeak's PasteUpMorph, it preserves location and size of contents."