StyleToolBuildersImpl.mesa;
Written by Linda Gass on August 9, 1982 9:48 am
Last Edit by Linda Gass on November 4, 1982 2:25 pm
Last Edited by: Plass, March 28, 1983 2:57 pm
DIRECTORY

Buttons USING [Button, ButtonProc, Create, SetDisplayStyle],
ChoiceButtons USING [BuildEnumTypeSelection, BuildTextPrompt, BuildTriStateButton,
 ButtonList, PromptDataRef, SelectionNotifierProc],
Containers USING [ChildXBound, ChildYBound, Container, Create],
IO USING [int, PutFToRope, real],
Labels USING [Create, Label, Set, SetDisplayStyle],
MessageWindow USING [Append, Blink],
Rope USING [Equal, ROPE],
StyleToolDefs,
StyleToolBuilders,
StyleToolConvert USING [ConvertUnits, GetRealFromViewer],
StyleToolGraphics USING [CreateLayoutContainer],
VFonts USING [CharWidth, EstablishFont, Font, StringWidth],
ViewerClasses USING [Viewer],
ViewerOps USING [CreateViewer, EstablishViewerPosition, MoveViewer],
ViewerTools USING [InhibitUserEdits, MakeNewTextViewer, SetContents, SetSelection];

StyleToolBuildersImpl: CEDAR PROGRAM

IMPORTS Buttons, ChoiceButtons, Containers, IO, Labels, MessageWindow, Rope, StyleToolConvert, StyleToolDefs, StyleToolGraphics, VFonts, ViewerOps, ViewerTools
EXPORTS StyleToolBuilders =

BEGIN OPEN StyleToolDefs, StyleToolBuilders;

largeLabelFont: VFonts.Font ← VFonts.EstablishFont[family: "Helvetica", size: 12, bold: TRUE,
 italic: FALSE, defaultOnFailure: TRUE];
mediumLabelFont: VFonts.Font ← VFonts.EstablishFont[family: "Helvetica", size: 10, bold: TRUE,
 italic: FALSE, defaultOnFailure: TRUE];
smallLabelFont: VFonts.Font ←VFonts.EstablishFont[family: "Helvetica", size: 8, bold: TRUE, italic:
FALSE, defaultOnFailure: TRUE];
tinyLabelFont: VFonts.Font ←VFonts.EstablishFont[family: "Helvetica", size: 6, bold: FALSE, italic:
FALSE, defaultOnFailure: TRUE];

styleFormatLookWidth: INTEGER = 200; -- width of text viewer for style name, format name, looks
realWidth: CARDINAL ← 6*VFonts.CharWidth['0]; -- width of text viewer for real #'s

extraSpace: CARDINAL ← 2;     -- provides a little extra spacing
lineSpace: CARDINAL ← entryHeight + 2;  -- vertical leading space between lines of text
dividerHeight: CARDINAL ← 15;    -- height of dividers

BadNumber: SIGNAL = CODE;
EmptyList: SIGNAL = CODE;
CurrentNameNotInList: SIGNAL = CODE;
stretchShrinkStart: INTEGER ← 230;  -- x position of stretch shrink container
midway: INTEGER 210;     -- half way point in StyleTool container
---- ---- ---- ---- ---- ---- ---- ----
BuildStyleNameField: PUBLIC PROCEDURE[handle: StyleToolHandle] = BEGIN
handle.styleNameData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.outer,
 y: handle.height,
 title: "Style Name:",
 default: "default",
 font: largeLabelFont,
 textViewerWidth: styleFormatLookWidth
 ];
handle.height ← handle.styleNameData.newy + extraSpace; -- interline spacing
END;
BuildFormatNameField: PUBLIC PROC[handle: StyleToolHandle] = BEGIN
handle.formatNameData ← ChoiceButtons.BuildTextPrompt[viewer: handle.outer, y: handle.height,
 title: "Format Name:", font: mediumLabelFont, textViewerWidth: styleFormatLookWidth];
handle.height ← handle.formatNameData.newy + extraSpace; -- interline spacing
END;
BuildLooksField: PUBLIC PROCEDURE [handle: StyleToolHandle] = BEGIN
handle.looksData ← ChoiceButtons.BuildTextPrompt[viewer: handle.outer, y: handle.height,
 title: "Looks:", font: mediumLabelFont, textViewerWidth: styleFormatLookWidth];
handle.height ← handle.looksData.newy + entryVSpace;
END;
BuildRuleField: PUBLIC PROCEDURE [handle: StyleToolHandle] = BEGIN
place in the upper right hand corner of the Style Tool
handle.ruleType ← ChoiceButtons.BuildEnumTypeSelection[viewer: handle.outer, x: 320, y: 18, buttonNames: ruleList, style: menuSelection, notifyClientProc: ChangeDisplay, clientdata: handle, allInOneRow: FALSE, maxWidth: 400, default: "StyleRule"];
END;
ChangeDisplay: ChoiceButtons.SelectionNotifierProc = {
depending upon which rule button was selected, display different information
oldy: INTEGER;
handle: StyleToolHandle ← NARROW[clientdata];
SELECT TRUE FROM
 Rope.Equal[name, "ScreenRule"]  => { -- take away the print information
   
OPEN handle.swap;  -- for penalty, jamCodeInfo, layoutHeader and layout
   oldy ← penalty.outer.wy;
   ViewerOps.MoveViewer[penalty.outer, LAST[INTEGER], penalty.outer.wy,
    penalty.outer.ww, penalty.outer.wh]; -- move out to "infinity" in x dimension
   
ViewerOps.MoveViewer[layoutHeader.outer, LAST[INTEGER], layoutHeader.outer.wy,
    layoutHeader.outer.ww, layoutHeader.outer.wh];
   
ViewerOps.MoveViewer[layout.outer, LAST[INTEGER], layout.outer.wy,
    layout.outer.ww, layout.outer.wh];
   ViewerOps.MoveViewer[jamCodeInfo.outer, 0, oldy, jamCodeInfo.outer.ww,
    jamCodeInfo.outer.wh];
   ViewerOps.MoveViewer[handle.display.stretchShrinkContainer, LAST[INTEGER],
    handle.display.stretchShrinkContainer.wy,
    handle.display.stretchShrinkContainer.ww,
    handle.display.stretchShrinkContainer.wh];
   };
 Rope.Equal[name, "PrintRule"], Rope.Equal[name, "StyleRule"] => {
   OPEN handle.swap;  -- for penalty, jamCodeInfo, layoutHeader and layout
   IF penalty.outer.wx = LAST[INTEGER] THEN {
    -- dont bother to move any viewers if not necessary
    IF layout.visible THEN
     ViewerOps.MoveViewer[jamCodeInfo.outer,0,layout.outer.wy+layout.outer.wh+2,
     jamCodeInfo.outer.ww, jamCodeInfo.outer.wh]
    ELSE ViewerOps.MoveViewer[jamCodeInfo.outer, 0, layoutHeader.outer.wy +
     layoutHeader.outer.wh + 6, jamCodeInfo.outer.ww, jamCodeInfo.outer.wh];
    ViewerOps.MoveViewer[penalty.outer, 0, penalty.outer.wy, penalty.outer.ww,
     penalty.outer.wh];
    ViewerOps.MoveViewer[layoutHeader.outer, 0, layoutHeader.outer.wy,
     layoutHeader.outer.ww, layoutHeader.outer.wh];
    IF layout.visible THEN
     ViewerOps.MoveViewer[layout.outer, 0, layout.outer.wy, layout.outer.ww,
      layout.outer.wh];
    ViewerOps.MoveViewer[handle.display.stretchShrinkContainer, stretchShrinkStart,
     handle.display.stretchShrinkContainer.wy,
     handle.display.stretchShrinkContainer.ww,
     handle.display.stretchShrinkContainer.wh];
    };
   };
ENDCASE => ERROR;
};
---- ---- ---- ---- ---- ---- ---- ----
DisplayRealInViewer: PUBLIC PROCEDURE [num: REAL, v: ViewerClasses.Viewer] = BEGIN
ViewerTools.SetContents[v, IO.PutFToRope[realNumberFormat, IO.real[num]]];
END;
DisplayIntInViewer: PUBLIC PROCEDURE [num: INTEGER, v: ViewerClasses.Viewer] = BEGIN
ViewerTools.SetContents[v, IO.PutFToRope[integerFormat, IO.int[num]]];
END;
BuildValueAndUnits: PROCEDURE [container: Containers.Container, x,y: CARDINAL ← 0, itemTitle: Rope.ROPE, itemDefault: Rope.ROPE ← NIL] RETURNS [newValueAndUnits: ValueAndUnitsRef] = BEGIN
newValueAndUnits ← NEW[ValueAndUnitsRec];
newValueAndUnits.valueData ← ChoiceButtons.BuildTextPrompt[
 viewer: container,
 x: x, y: y,
 title: itemTitle,
 default: itemDefault,
 textViewerWidth: realWidth
 ];
newValueAndUnits.units ← ChoiceButtons.BuildEnumTypeSelection [
 viewer: container,
 x: newValueAndUnits.valueData.newx + 5,
 y: y + 2,  -- add 4 so that the units are aligned with the text prompt (otherwise too high)
 buttonNames: unitsList,
 default: "points",
 borderOnButtons: FALSE,
 notifyClientProc: ChangeUnits,
 clientdata: newValueAndUnits,
 style: flipThru
 ];
newValueAndUnits.originalUnits ← "points";
END;
ChangeUnits: ChoiceButtons.SelectionNotifierProc = BEGIN
this gets called with the newly chosen units (name).
valueAndUnits: ValueAndUnitsRef ← NARROW[clientdata];
newValue: REAL;
IF valueAndUnits.valueData.textViewer.newVersion THEN {
 valueAndUnits.originalValue ← newValue ← StyleToolConvert.GetRealFromViewer[
  valueAndUnits.valueData.textViewer! BadNumber => GOTO Leave];
 valueAndUnits.originalUnits ← PrevRope[unitsList, name];
 }
ELSE newValue ← valueAndUnits.originalValue;

newValue ← StyleToolConvert.ConvertUnits[newValue, valueAndUnits.originalUnits, name];
-- Now redisplay the new value
DisplayRealInViewer[newValue, valueAndUnits.valueData.textViewer];
valueAndUnits.valueData.textViewer.newVersion ← FALSE;
EXITS Leave => RETURN;
END;
ChangeLeading: ChoiceButtons.SelectionNotifierProc = BEGIN
this gets called with the newly chosen units (name).
leadingInfo: LeadingRef ← NARROW[clientdata];
leadingValue, stretchValue, shrinkValue: REAL;
IF leadingInfo.leading.valueData.textViewer.newVersion THEN {
 leadingInfo.leading.originalValue ← leadingValue ←
  StyleToolConvert.GetRealFromViewer[leadingInfo.leading.valueData.textViewer
  ! BadNumber => GOTO Leave];
 leadingInfo.leading.originalUnits ← PrevRope[unitsList, name];
 }
ELSE leadingValue ← leadingInfo.leading.originalValue;

IF leadingInfo.stretch.textViewer.newVersion THEN
 leadingInfo.originalStretch ← stretchValue ← StyleToolConvert.GetRealFromViewer[
  leadingInfo.stretch.textViewer ! BadNumber => GOTO Leave]
ELSE stretchValue ← leadingInfo.originalStretch;

IF leadingInfo.shrink.textViewer.newVersion THEN
 leadingInfo.originalShrink ← shrinkValue ← StyleToolConvert.GetRealFromViewer[
  leadingInfo.shrink.textViewer ! BadNumber => GOTO Leave]
ELSE shrinkValue ← leadingInfo.originalShrink;

leadingValue ← StyleToolConvert.ConvertUnits[leadingValue,
 leadingInfo.leading.originalUnits, name];
stretchValue ← StyleToolConvert.ConvertUnits[stretchValue,
 leadingInfo.leading.originalUnits, name];
shrinkValue ← StyleToolConvert.ConvertUnits[shrinkValue,
 leadingInfo.leading.originalUnits, name];
-- Now redisplay the new values
DisplayRealInViewer[leadingValue, leadingInfo.leading.valueData.textViewer];
leadingInfo.leading.valueData.textViewer.newVersion ← FALSE;
DisplayRealInViewer[stretchValue, leadingInfo.stretch.textViewer];
DisplayRealInViewer[shrinkValue, leadingInfo.shrink.textViewer];
leadingInfo.leading.valueData.textViewer.newVersion ← FALSE;
leadingInfo.stretch.textViewer.newVersion ← FALSE;
leadingInfo.shrink.textViewer.newVersion ← FALSE;
EXITS Leave => RETURN;
END;
PrevRope: PROCEDURE [ropeList: ChoiceButtons.ButtonList, currentName: Rope.ROPE] RETURNS [prev: Rope.ROPE] = BEGIN
eachName: ChoiceButtons.ButtonList;
IF ropeList # NIL THEN {
 prev ← ropeList.first;
 eachName ← ropeList.rest;
 }
ELSE SIGNAL EmptyList;
WHILE (eachName # NIL) AND (eachName.first # currentName) DO
 prev ← eachName.first;
 eachName ← eachName.rest;
ENDLOOP;
IF (eachName = NIL) AND (ropeList.first # currentName) THEN SIGNAL CurrentNameNotInList;
END;
BuildDivider: PROC [name: Rope.ROPENIL, container: Containers.Container, y: INTEGER] = BEGIN
creates a gray divider with an optional name in it. Makes the divider as wide as parent
dividerLabel: Labels.Label←Labels.Create[
 info:[name: name, parent: container, wy: y, border: TRUE],
 font: smallLabelFont];
Labels.SetDisplayStyle[dividerLabel, $BlackOnGrey];
Containers.ChildXBound[container, dividerLabel];
END;
---- ---- ---- ---- ---- ---- ---- ----
BuildDisplayViewer: PUBLIC PROC [handle: StyleToolHandle] = BEGIN
BuildFontInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
width: INTEGER = 400;
otherY: INTEGER;   -- y position of non-standard font name label, computed later
tempLabel: Labels.Label; -- temporary placeholder for font face label
nextX: INTEGER ← 0;  -- used for placing font face buttons

BuildDivider["FONT INFORMATION:", handle.outer, handle.height];
handle.height ← handle.height + entryHeight + entryVSpace;

handle.display.fontFamilyChoice ← ChoiceButtons.BuildEnumTypeSelection[
 viewer: handle.outer,
 x: 0,
 y: handle.height,
 title: "Font Family: ",
 buttonNames: fontFamilyList,
 notifyClientProc: FontFamilyCheck,
 clientdata: handle,
 style: menuSelection,
 allInOneRow: FALSE,
 maxWidth: width -- just a guess
 ];
handle.height ← handle.display.fontFamilyChoice.nexty + entryVSpace;

otherY ← handle.height - entryVSpace - entryHeight + 2;
handle.display.fontFamilyOtherLabel ← Labels.Create[[wx: midway, wy: otherY,
 ww: VFonts.StringWidth["Font Name: "], wh: entryHeight, parent: handle.outer,
 border: FALSE]];
handle.display.fontFamilyOtherViewer ← ViewerTools.MakeNewTextViewer[[parent:
 handle.outer, wx: handle.display.fontFamilyOtherLabel.wx +
 handle.display.fontFamilyOtherLabel.ww + 6, wy: otherY + 2, wh: entryHeight,
 scrollable: FALSE, border: FALSE]];
Containers.ChildXBound[handle.outer, handle.display.fontFamilyOtherViewer];
The following has been replaced by experiment Tri-State buttons
handle.display.fontFaceChoice ← ChoiceButtons.BuildEnumTypeSelection[handle.outer, 0,
 handle.height, "Font Face: ", fontFaceList, NIL, TRUE, NIL, NIL, menuSelection];
handle.height ← handle.height + entryHeight + space;
tempLabel ← Labels.Create[[name: "Font Face: ", parent: handle.outer, wy: handle.height,
 wh: entryHeight, border: FALSE]];
nextX ← tempLabel.wx + tempLabel.ww + entryHSpace;
[handle.display.boldFontFace, nextX] ← ChoiceButtons.BuildTriStateButton[handle.outer,
 nextX, handle.height, "Bold"];
[handle.display.italicFontFace, nextX] ← ChoiceButtons.BuildTriStateButton[handle.outer,
 nextX, handle.height, "Italic"];
handle.display.fontSizeInfo ← BuildValueAndUnits[container: handle.outer, x: midway,
 y: handle.height - 4, itemTitle: "Font Size:"]; -- subtract 4 from y value to align
handle.height ← handle.height + entryHeight + entryVSpace;

handle.display.fontAlphabetsChoice ← ChoiceButtons.BuildEnumTypeSelection[
 handle.outer, 0, handle.height, "Font Alphabets:", fontAlphabetsList, NIL, TRUE, NIL,
NIL, NIL, menuSelection];
handle.height ← handle.height + entryHeight + entryVSpace;

handle.display.fontUnderliningChoice ← ChoiceButtons.BuildEnumTypeSelection[handle.outer,
 0,handle.height,"Font Underlining:", fontUnderliningList, NIL, TRUE, NIL, NIL, NIL,
 menuSelection];
handle.height ← handle.height + entryHeight + entryVSpace;
END;
BuildIndentInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
space: CARDINAL ← 4;
BuildRow: PROC [name1, name2: Rope.ROPE] RETURNS [v1, v2: ValueAndUnitsRef] = BEGIN
v1 ← BuildValueAndUnits[container: handle.outer, y: handle.height, itemTitle: name1];
v2 ← BuildValueAndUnits[container: handle.outer, x: midway, y: handle.height,
 itemTitle: name2];
handle.height ← handle.height + lineSpace;
END;
BuildDivider["INDENT INFORMATION:", handle.outer, handle.height];
handle.height ← handle.height + entryHeight;

[handle.display.leftIndentInfo, handle.display.rightIndentInfo] ← BuildRow["Left Indent:",
 "Right Indent: "];
[handle.display.firstIndentInfo, handle.display.restIndentInfo] ← BuildRow["First Indent:",
 "Rest Indent: "];
[handle.display.topIndentInfo, handle.display.bottomIndentInfo]← BuildRow["Top Indent: ",
 "Bottom Indent:"];
handle.height ← handle.height + extraSpace;
END;
BuildLeadingInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
Build a separate container for the leading since we will want to move the stretch and shrink fields out of the way if we are specifying a screen rule  
height: CARDINAL ← 0;
BuildStretchAndShrink: PROC RETURNS[stretchData, shrinkData: ChoiceButtons.PromptDataRef] = {
stretchData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.display.stretchShrinkContainer, x: 0, y: height, title: "stretch:",
 textViewerWidth: realWidth];
shrinkData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.display.stretchShrinkContainer, x: stretchData.newx, y: height,
 title: "shrink:", textViewerWidth: realWidth];
};
BuildDivider["LEADING INFORMATION:", handle.outer, handle.height];
handle.height ← handle.height + entryHeight;

handle.display.leadingContainer ← Containers.Create[[wy: handle.height, scrollable: FALSE,
 border: FALSE, parent: handle.outer]];
Containers.ChildXBound[handle.outer, handle.display.leadingContainer];
handle.display.stretchShrinkContainer ← Containers.Create[[wx: stretchShrinkStart,
 scrollable: FALSE, border: FALSE, parent: handle.display.leadingContainer]];
Containers.ChildXBound[handle.display.leadingContainer,
 handle.display.stretchShrinkContainer];
Containers.ChildYBound[handle.display.leadingContainer,
 handle.display.stretchShrinkContainer];
handle.display.leadingInfo ← NEW[LeadingRec];
handle.display.leadingInfo.leading ← NEW[ValueAndUnitsRec];
handle.display.leadingInfo.leading.valueData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.display.leadingContainer, y: height, title:"Leading: ",
 textViewerWidth: realWidth];
handle.display.leadingInfo.leading.units ← ChoiceButtons.BuildEnumTypeSelection [viewer:
 handle.display.leadingContainer, x: handle.display.leadingInfo.leading.valueData.newx + 5,
 y: height + 2, buttonNames: unitsList, default: "points", borderOnButtons: FALSE,
 notifyClientProc: ChangeLeading, clientdata: handle.display.leadingInfo, style: flipThru];
[handle.display.leadingInfo.stretch, handle.display.leadingInfo.shrink] ←
 BuildStretchAndShrink[];
height ← height + lineSpace;

handle.display.topLeadingInfo ← NEW[LeadingRec];
handle.display.topLeadingInfo.leading ← NEW[ValueAndUnitsRec];
handle.display.topLeadingInfo.leading.valueData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.display.leadingContainer, y: height, title:"Top Leading: ",
 textViewerWidth: realWidth];
handle.display.topLeadingInfo.leading.units ← ChoiceButtons.BuildEnumTypeSelection[
 viewer: handle.display.leadingContainer,
 x: handle.display.topLeadingInfo.leading.valueData.newx + 5,
 y: height + 2, buttonNames: unitsList, default: "points", borderOnButtons: FALSE,
 notifyClientProc: ChangeLeading,clientdata: handle.display.topLeadingInfo,style: flipThru];
[handle.display.topLeadingInfo.stretch, handle.display.topLeadingInfo.shrink] ←
 BuildStretchAndShrink[];
height ← height + lineSpace;

handle.display.bottomLeadingInfo ← NEW[LeadingRec];
handle.display.bottomLeadingInfo.leading ← NEW[ValueAndUnitsRec];
handle.display.bottomLeadingInfo.leading.valueData ← ChoiceButtons.BuildTextPrompt[
 viewer: handle.display.leadingContainer,y: height, title:"Bottom Leading:",
 textViewerWidth: realWidth];
handle.display.bottomLeadingInfo.leading.units ← ChoiceButtons.BuildEnumTypeSelection[
 viewer: handle.display.leadingContainer,
 x: handle.display.bottomLeadingInfo.leading.valueData.newx + 5,
 y: height + 2, buttonNames: unitsList, default: "points", borderOnButtons: FALSE,
 notifyClientProc: ChangeLeading, clientdata: handle.display.bottomLeadingInfo,
 style: flipThru];
[handle.display.bottomLeadingInfo.stretch, handle.display.bottomLeadingInfo.shrink] ←
 BuildStretchAndShrink[];
height ← height + lineSpace + extraSpace;
handle.height ← handle.height + height;
ViewerOps.EstablishViewerPosition[handle.display.leadingContainer, 0,
 handle.display.leadingContainer.wy, handle.display.leadingContainer.ww, height];
ViewerOps.EstablishViewerPosition[handle.display.stretchShrinkContainer,
 handle.display.stretchShrinkContainer.wx, handle.display.stretchShrinkContainer.wy,
 handle.display.stretchShrinkContainer.ww, handle.display.stretchShrinkContainer.wh];
END;
BuildMiscInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
BuildDivider["MISCELLANEOUS INFORMATION:", handle.outer, handle.height];
handle.height ← handle.height + entryHeight;

handle.display.minLineGapInfo ← BuildValueAndUnits[container: handle.outer,
 y: handle.height, itemTitle: "Minimum distance between tops and bottoms of lines:"];
handle.height ← handle.height + lineSpace;

handle.display.vshiftInfo ← BuildValueAndUnits[container: handle.outer, y: handle.height,
 itemTitle: "Distance to raise text above baseline:"];
handle.height ← handle.height + lineSpace;

handle.display.tabStopsViewer ← ChoiceButtons.BuildTextPrompt[viewer: handle.outer,
 y: handle.height, title: "Number of spaces equivalent to one tab:",
 textViewerWidth: realWidth].textViewer;
handle.height ← handle.height + lineSpace + extraSpace;

handle.display.lineFormattingChoice ← ChoiceButtons.BuildEnumTypeSelection[handle.outer,
 0, handle.height, "Line Formatting:", lineFormattingList, NIL, TRUE, NIL, NIL, NIL,
 menuSelection];
handle.height ← handle.height + entryHeight + entryVSpace;
END;
BuildArtworkInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
AddEntry: PROCEDURE [name: Rope.ROPE] RETURNS [v: ViewerClasses.Viewer] = BEGIN
 v ← ChoiceButtons.BuildTextPrompt[viewer: handle.outer, y: handle.height, title: name,
  textViewerWidth: realWidth].textViewer;
 handle.height ← handle.height + lineSpace;
END;
BuildDivider["TIOGA ARTWORK INFORMATION:", handle.outer, handle.height];
handle.height ← handle.height + entryHeight + entryVSpace;

handle.display.pathTypeChoice ← ChoiceButtons.BuildEnumTypeSelection[handle.outer, 0,
 handle.height, "Path Type:", pathTypeList, NIL, FALSE, NIL, NIL, NIL, menuSelection];
handle.height ← handle.height + entryHeight + entryVSpace;

handle.display.areaHueViewer ← AddEntry["Area Hue:"];
handle.display.areaSaturationViewer ← AddEntry["Area Saturation:"];
handle.display.areaBrightnessViewer ← AddEntry["Area Brightness:"];
handle.display.outlineHueViewer ← AddEntry["Outline Hue:"];
handle.display.outlineSaturationViewer ← AddEntry["Outline Saturation:"];
handle.display.outlineBrightnessViewer ← AddEntry["Outline Brightness:"];
handle.display.textHueViewer ← AddEntry["Text Hue:"];
handle.display.textSaturationViewer ← AddEntry["Text Saturation:"]; 
handle.display.textBrightnessViewer ← AddEntry["Text Brightness:"];
handle.display.textRotationViewer ← AddEntry["Text Rotation:"]; 
handle.display.lineWeightViewer ← AddEntry["Line Weight:"];
END;
BuildFontInfo[handle];
BuildIndentInfo[handle];
BuildLeadingInfo[handle];
BuildMiscInfo[handle];
-- BuildArtworkInfo[handle];
END;
---- ---- ---- ---- ---- ---- ---- ----
FontFamilyCheck: ChoiceButtons.SelectionNotifierProc = BEGIN
handle: StyleToolHandle ← NARROW[clientdata];
IF Rope.Equal[name, "other", FALSE] THEN {-- put up the font name field for user type in
 Labels.Set[handle.display.fontFamilyOtherLabel, "Font Name:"];
 ViewerTools.SetSelection[handle.display.fontFamilyOtherViewer];
 }
ELSE {
-- make sure the font name field doesn't exist
 Labels.Set[handle.display.fontFamilyOtherLabel, ""];
 ViewerTools.SetContents[handle.display.fontFamilyOtherViewer, ""];
 };
END;
---- ---- ---- ---- ---- ---- ---- ----
BuildSwapArea: PUBLIC PROCEDURE [handle: StyleToolHandle] = BEGIN
handle.swap.outer ← Containers.Create[[wy: handle.height, scrollable: FALSE, border: FALSE,
 parent: handle.outer]];
Containers.ChildXBound[handle.outer, handle.swap.outer];
Containers.ChildYBound[handle.outer, handle.swap.outer];
BuildPenaltyInfo[handle];
BuildPageInfo[handle];
BuildJaMCodeViewer[handle];
ViewerOps.EstablishViewerPosition[handle.swap.outer, 0, handle.swap.outer.wy,
 handle.swap.outer.ww, handle.swap.height];
handle.height ← handle.height + handle.swap.height;
END;
BuildPenaltyInfo: PROC [handle: StyleToolHandle] = BEGIN
SetUp: PROC [name: Rope.ROPE, x: INTEGER ← 0] RETURNS [v: ViewerClasses.Viewer] = {
v ← ChoiceButtons.BuildTextPrompt[viewer: handle.swap.penalty.outer, x: x,
 y: handle.swap.penalty.height, title: name, textViewerWidth: realWidth].textViewer;
};
SetUpRow: PROC [name1, name2: Rope.ROPE] RETURNS [v1, v2: ViewerClasses.Viewer] = {  
v1 ← SetUp[name1, 0];
v2 ← SetUp[name2, midway];
handle.swap.penalty.height ← handle.swap.penalty.height + lineSpace;
}; 
handle.swap.penalty.outer ← Containers.Create[[wy: handle.swap.height, scrollable: FALSE,
 border: FALSE, parent: handle.swap.outer]];
Containers.ChildXBound[handle.swap.outer, handle.swap.penalty.outer];
BuildDivider["PAGE BREAK PENALTY INFORMATION:", handle.swap.penalty.outer,
 handle.swap.penalty.height];
handle.swap.penalty.height ← handle.swap.penalty.height + entryHeight;

handle.swap.penalty.pageBreakPenalty ← SetUp["Page Break Penalty:"];
handle.swap.penalty.height ← handle.swap.penalty.height + lineSpace;
[handle.swap.penalty.afterFirstLinePenalty, handle.swap.penalty.beforeLastLinePenalty] ←
 SetUpRow["After First Line Penalty:", "Before Last Line Penalty:"];  
[handle.swap.penalty.beforeFirstLinePenalty, handle.swap.penalty.afterLastLinePenalty] ←
 SetUpRow["Before First Line Penalty:", "After Last Line Penalty:"];
ViewerOps.EstablishViewerPosition[handle.swap.penalty.outer, 0, handle.swap.penalty.outer.wy,
 handle.swap.penalty.outer.ww, handle.swap.penalty.height];
handle.swap.height ← handle.swap.height + handle.swap.penalty.height + 2;
END;
BuildPageInfo: PROCEDURE[handle: StyleToolHandle] = BEGIN
AddRow: PROC [name1, name2: Rope.ROPE] RETURNS [v1, v2: ValueAndUnitsRef] = BEGIN
v1 ← BuildValueAndUnits[container: handle.swap.layout.outer, y: handle.swap.layout.height,
 itemTitle: name1];
v2 ← BuildValueAndUnits[container: handle.swap.layout.outer, x: midway,
 y: handle.swap.layout.height, itemTitle: name2];
handle.swap.layout.height ← handle.swap.layout.height + lineSpace;
END;
BuildPageLayoutDivider: PROCEDURE = BEGIN
tempButton: Buttons.Button ← NIL;
tempLabel, dividerLabel: Labels.Label;
startButtons: CARDINAL ← 250;
spaceBetweenButtons: CARDINAL ← 16;
handle.swap.layoutHeader.outer ← Containers.Create[[wy: handle.swap.height,
 scrollable: FALSE, border: FALSE, parent: handle.swap.outer]];
Containers.ChildXBound[handle.swap.outer, handle.swap.layoutHeader.outer];
dividerLabel ← Labels.Create[info: [ww: startButtons, wh: dividerHeight,
 name: "PAGE LAYOUT INFORMATION:", parent: handle.swap.layoutHeader.outer,
 border: TRUE], font: smallLabelFont];
Labels.SetDisplayStyle[dividerLabel, $BlackOnGrey];

-- now put the buttons on page layout divider
handle.swap.layout.parametersButton ← Buttons.Create[info: [wx: startButtons, wh: dividerHeight, name: "Parameters",
 border: TRUE, parent: handle.swap.layoutHeader.outer], proc: ShowPageLayoutParams,
 clientData: handle, font: smallLabelFont];
Buttons.SetDisplayStyle[handle.swap.layout.parametersButton, $BlackOnWhite];
tempLabel ← Labels.Create[info: [wx: handle.swap.layout.parametersButton.wx + handle.swap.layout.parametersButton.ww,
 ww: spaceBetweenButtons, wh: dividerHeight, parent: handle.swap.layoutHeader.outer,
 border: TRUE]];
Labels.SetDisplayStyle[tempLabel, $BlackOnGrey];
tempButton ← Buttons.Create[info: [wx: tempLabel.wx + tempLabel.ww, wh: dividerHeight,
 name: "Graphics", border: TRUE, parent: handle.swap.layoutHeader.outer],
 proc: StartGraphics, clientData: handle, font: smallLabelFont];
Buttons.SetDisplayStyle[tempButton, $BlackOnWhite];
tempLabel ← Labels.Create[info: [wx: tempButton.wx + tempButton.ww, wh: dividerHeight,
 parent: handle.swap.layoutHeader.outer, border: TRUE]];
Labels.SetDisplayStyle[tempLabel, $BlackOnGrey];
Containers.ChildXBound[handle.swap.layoutHeader.outer, tempLabel];
handle.swap.layoutHeader.height ← handle.swap.layoutHeader.height + entryHeight;
handle.swap.height ← handle.swap.height + handle.swap.layoutHeader.height;
ViewerOps.EstablishViewerPosition[handle.swap.layoutHeader.outer,
 handle.swap.layoutHeader.outer.wx, handle.swap.layoutHeader.outer.wy,
 handle.swap.layoutHeader.outer.ww, handle.swap.layoutHeader.height];
END;
BuildPageLayoutDivider[];

handle.swap.layout.outer ← Containers.Create[[wy: handle.swap.height, scrollable: FALSE,
 border: FALSE, parent: handle.swap.outer]];
Containers.ChildXBound[handle.swap.outer, handle.swap.layout.outer];

[handle.swap.layout.pageWidth, handle.swap.layout.pageLength] ← AddRow["Page Width:",
 "Page Length:"];
[handle.swap.layout.leftMargin, handle.swap.layout.rightMargin] ← AddRow["Left Margin:",
 "Right Margin:"];
[handle.swap.layout.topMargin, handle.swap.layout.bottomMargin] ← AddRow["Top Margin:",
 "Bottom Margin:"];
[handle.swap.layout.headerMargin, handle.swap.layout.footerMargin] ← AddRow[
 "Header Margin:", "Footer Margin:"]; temporarily not used
handle.swap.layout.bindingMargin ← BuildValueAndUnits[container: handle.swap.layout.outer,
 y: handle.swap.layout.height, itemTitle: "Binding Margin:"];
handle.swap.layout.height ← handle.swap.layout.height + lineSpace;
handle.swap.layout.lineLength ← BuildValueAndUnits[container: handle.swap.layout.outer,
 y: handle.swap.layout.height, itemTitle: "Line Length:"];
handle.swap.layout.height ← handle.swap.layout.height + lineSpace; temporarily not used

handle.swap.layout.column ← ChoiceButtons.BuildTextPrompt[viewer: handle.swap.layout.outer,
 y: handle.swap.layout.height, title: "Number of columns:", textViewerWidth:
 realWidth].textViewer;
handle.swap.layout.height ← handle.swap.layout.height + lineSpace; temporarily not used
ViewerOps.EstablishViewerPosition[handle.swap.layout.outer, LAST[INTEGER],
 handle.swap.layout.outer.wy, handle.swap.layout.outer.ww, handle.swap.layout.height];
-- increase the swap height only by the divider width as we dont want the page layout info to be displayed initially
handle.swap.height ← handle.swap.height + 6;
END;
ShowPageLayoutParams: Buttons.ButtonProc = { 
handle: StyleToolHandle ← NARROW[clientData];
IF handle.layoutGraphics.exists THEN RETURN; -- dont show params if doing graphical layout
IF handle.swap.layout.visible THEN {
 handle.swap.layout.visible ← FALSE;
 Buttons.SetDisplayStyle[NARROW[parent], $BlackOnWhite];
Move the Page Layout viewer into oblivion and move the Jam Code Viewer up
 ViewerOps.MoveViewer[handle.swap.layout.outer, LAST[INTEGER],
  handle.swap.layout.outer.wy, handle.swap.layout.outer.ww, handle.swap.layout.outer.wh];
 ViewerOps.MoveViewer[handle.swap.jamCodeInfo.outer, 0,
  handle.swap.layoutHeader.outer.wy + handle.swap.layoutHeader.outer.wh + 6,
  handle.swap.jamCodeInfo.outer.ww, handle.swap.jamCodeInfo.outer.wh];
 }
ELSE {
 handle.swap.layout.visible ← TRUE;
 Buttons.SetDisplayStyle[NARROW[parent], $WhiteOnBlack];
Move the page layout viewer into view and move the Jam Code Viewer down
 ViewerOps.MoveViewer[handle.swap.layout.outer, 0, handle.swap.layout.outer.wy,
  handle.swap.layout.outer.ww, handle.swap.layout.outer.wh];
 ViewerOps.MoveViewer[handle.swap.jamCodeInfo.outer, 0,
  handle.swap.layout.outer.wy + handle.swap.layout.outer.wh + 6,
  handle.swap.jamCodeInfo.outer.ww, handle.swap.jamCodeInfo.outer.wh];
 };
};
StartGraphics: Buttons.ButtonProc = {
handle: StyleToolHandle ← NARROW[clientData];
IF handle.layoutGraphics.exists THEN {
 MessageWindow.Append["A page layout graphics viewer already exists!", TRUE];
 MessageWindow.Blink[];
 }
ELSE {
  handle.layoutGraphics.exists ← TRUE;  
In the future we will probably want to check that there isn't an instance of the graphics viewer already in existence (ie - another instance of the style tool created a graphics viewer). If there is one in existence already, graphics is likely to get confused.
Make sure that the parameters for page layout inside the style tool are not visible. This could cause some confusion for the user.
IF handle.swap.layout.visible THEN {  
Move the Page Layout viewer into oblivion and move the Jam Code Viewer up
ViewerOps.MoveViewer[handle.swap.layout.outer, LAST[INTEGER],
 handle.swap.layout.outer.wy, handle.swap.layout.outer.ww, handle.swap.layout.outer.wh];
ViewerOps.MoveViewer[handle.swap.jamCodeInfo.outer, 0,
 handle.swap.layoutHeader.outer.wy + handle.swap.layoutHeader.outer.wh + 6,
 handle.swap.jamCodeInfo.outer.ww, handle.swap.jamCodeInfo.outer.wh];
handle.swap.layout.visible ← FALSE;
Buttons.SetDisplayStyle[handle.swap.layout.parametersButton, $BlackOnWhite];
}; 
StyleToolGraphics.CreateLayoutContainer[handle];
};
};
BuildJaMCodeViewer: PROC [handle: StyleToolHandle] = BEGIN
handle.swap.jamCodeInfo.outer ← Containers.Create[[wy: handle.swap.height + extraSpace,
 scrollable: FALSE, border: TRUE, parent: handle.swap.outer]];
Containers.ChildXBound[handle.swap.outer, handle.swap.jamCodeInfo.outer];
Containers.ChildYBound[handle.swap.outer, handle.swap.jamCodeInfo.outer];
BuildDivider["JaM CODE CORRESPONDING TO ABOVE STYLE:", handle.swap.jamCodeInfo.outer, 0];
handle.swap.jamCodeInfo.text ← ViewerOps.CreateViewer[
 flavor: $Text,
 info: [wy: entryHeight + extraSpace,
  scrollable: TRUE,
  iconic: FALSE,
  border: FALSE,
  parent: handle.swap.jamCodeInfo.outer]
  ];
Containers.ChildXBound[handle.swap.jamCodeInfo.outer, handle.swap.jamCodeInfo.text];
Containers.ChildYBound[handle.swap.jamCodeInfo.outer, handle.swap.jamCodeInfo.text];
ViewerTools.InhibitUserEdits[handle.swap.jamCodeInfo.text];
ViewerOps.EstablishViewerPosition[handle.swap.jamCodeInfo.outer, 0,
 handle.swap.jamCodeInfo.outer.wy, handle.swap.jamCodeInfo.outer.ww,
 handle.swap.jamCodeInfo.outer.wh];
handle.swap.height ← handle.swap.height + handle.swap.jamCodeInfo.outer.wh;
END;
END.