StyleToolGraphicsMiscImpl.mesa
Written by Linda Gass September 23, 1982 12:36 pm
Last Edit by Linda Gass November 4, 1982 3:48 pm
-- Last Edited by: Plass, March 28, 1983 3:03 pm

DIRECTORY
Buttons USING [Button, ButtonProc, Create, SetDisplayStyle],
ChoiceButtons USING [BuildEnumTypeSelection, BuildTextPrompt, GetSelectedButton, PromptDataRef, SelectionNotifierProc, UpdateChoiceButtons],
Containers USING [ChildXBound, Create],
Graphics USING [Box, Color],
MessageWindow USING [Append, Blink],
Rope USING [Cat, Equal, ROPE],
Rules USING [Rule, Create],
StyleToolBuilders USING [DisplayRealInViewer],
StyleToolConvert USING [ConvertUnits, GetRealFromViewer],
StyleToolDefs USING [MarginType, PageBoundaryType, StyleToolHandle, unitsList, ValueAndUnitsRef],
StyleToolGraphicsMisc,
VFonts USING [CharWidth, EstablishFont, Font],
ViewerClasses USING [Viewer],
ViewerOps USING [CreateViewer, EstablishViewerPosition, PaintViewer],
ViewerTools USING [GetContents, SetContents];

StyleToolGraphicsMiscImpl: CEDAR PROGRAM
IMPORTS Buttons, ChoiceButtons, Containers, MessageWindow, Rope, Rules, StyleToolBuilders, StyleToolConvert, StyleToolDefs, VFonts, ViewerOps, ViewerTools
EXPORTS StyleToolGraphicsMisc =
BEGIN OPEN StyleToolDefs, StyleToolGraphicsMisc;
Default values so that the page layout graphics have something reasonable to start out with
defaultUnits: PUBLIC Rope.ROPE ← "inches";

numbersContainerFont: PUBLIC VFonts.Font ← VFonts.EstablishFont[family: "Helvetica", size: 10, bold: TRUE, italic: FALSE, defaultOnFailure: TRUE];
setButtonFont: PUBLIC VFonts.Font ← VFonts.EstablishFont[family: "Helvetica", size: 14, bold: TRUE, italic: FALSE, defaultOnFailure: TRUE];
realWidth: PUBLIC INTEGER ← 6*VFonts.CharWidth['0]; -- width of text viewer for real #'s
CreateNumbersContainer: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [INTEGER] = {
OPEN handle.layoutGraphics;  -- for numbersContainer, container, etc
height: INTEGER ← 0; -- the height of this container
rule: Rules.Rule;
y1, y2: INTEGER;  -- the y positions of the 1st and 2nd rows of items
numbersContainer ← Containers.Create[[iconic: FALSE, scrollable: FALSE, border: FALSE, parent: container, wx: 0, wy: 0]];
Containers.ChildXBound[container, numbersContainer];
now create all the individual information viewers.
y1 ← 0;
units.ref ← ChoiceButtons.BuildEnumTypeSelection[viewer: numbersContainer, x: 0, y: y1, title: "Units", buttonNames: unitsList, default: defaultUnits, borderOnButtons: FALSE, notifyClientProc: ChangeUnits, clientdata: handle, style: flipThru];
units.prev ← defaultUnits;
y2 ← units.ref.nexty;
setButton ← Buttons.Create[info: [wx: 0, wy: y2, name: "Set", border: TRUE, parent: numbersContainer], proc: SetProc, clientData: handle, fork: TRUE, font: setButtonFont];
pageWidth ← ChoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: units.ref.nextx+6, y: y1, title: "Page Width:", font: numbersContainerFont, textViewerWidth: realWidth];
pageLength ← ChoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: units.ref.nextx+6, y: y2, title: "Page Length:", font: numbersContainerFont, textViewerWidth: realWidth];
leftMargin ← ChoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: pageLength.newx+6, y: y1, title: "Left Margin:", font: numbersContainerFont, textViewerWidth: realWidth];
rightMargin 𡤌hoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: pageLength.newx+6, y: y2, title: "Right Margin:", font: numbersContainerFont, textViewerWidth: realWidth];
topMargin ← ChoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: rightMargin.newx+6, y: y1, title: "Top Margin:", font: numbersContainerFont, textViewerWidth: realWidth];
bottomMargin𡤌hoiceButtons.BuildTextPrompt[viewer: numbersContainer, x:rightMargin.newx+6, y: y2, title: "Bottom Margin:", font: numbersContainerFont, textViewerWidth: realWidth];
bindingMargin ← ChoiceButtons.BuildTextPrompt[viewer: numbersContainer, x: topMargin.newx + 6, y: y1, title: "Binding Margin:", font: numbersContainerFont, textViewerWidth: realWidth];
height ← bottomMargin.newy + 3;
ViewerOps.EstablishViewerPosition[numbersContainer, numbersContainer.wx,
 numbersContainer.wy, numbersContainer.ww, height];
create the divider
rule ← Rules.Create[[wx: 0, wy: height, wh: 2, scrollable: FALSE, iconic: FALSE, parent: container]];
Containers.ChildXBound[container, rule];
RETURN[height + 4];
};
SetProc: Buttons.ButtonProc = {
causes the information in the numbers container to be applied to the graphics viewer
handle: StyleToolHandle ← NARROW[clientData];
theButton: Buttons.Button ← NARROW[parent];
units: Rope.ROPE;
Buttons.SetDisplayStyle[theButton, $WhiteOnBlack];
First determine the units
units ← ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref];
DetermineInterval[handle, units];
ViewerOps.PaintViewer[handle.layoutGraphics.container, client];
Also make sure that the proper values get set for the original page layout parameters
SetOriginals[handle, handle.swap.layout.pageWidth, handle.layoutGraphics.pageWidth, units]; SetOriginals[handle, handle.swap.layout.pageLength, handle.layoutGraphics.pageLength, units];
SetOriginals[handle, handle.swap.layout.leftMargin, handle.layoutGraphics.leftMargin, units];
SetOriginals[handle, handle.swap.layout.rightMargin, handle.layoutGraphics.rightMargin, units];
SetOriginals[handle, handle.swap.layout.topMargin, handle.layoutGraphics.topMargin, units];
SetOriginals[handle, handle.swap.layout.bottomMargin, handle.layoutGraphics.bottomMargin,
 units];
SetOriginals[handle, handle.swap.layout.bindingMargin, handle.layoutGraphics.bindingMargin,
 units];
Buttons.SetDisplayStyle[theButton, $BlackOnWhite];
};
SetOriginals: PROCEDURE [handle: StyleToolHandle, origRef: ValueAndUnitsRef, curRef: ChoiceButtons.PromptDataRef, units: Rope.ROPE] = {
ViewerTools.SetContents[origRef.valueData.textViewer,
 ViewerTools.GetContents[curRef.textViewer]];
ChoiceButtons.UpdateChoiceButtons[handle.swap.layout.outer, origRef.units, units];
};
ChangeUnits: ChoiceButtons.SelectionNotifierProc = {
handle: StyleToolHandle ← NARROW[clientdata];
determine what the old units were
oldunits: Rope.ROPE ← handle.layoutGraphics.units.prev;
now update the previous units IFF the new units are not ems, ens or spaces. This is a kludge to get around not having conversions for ems, ens and spaces. (They are font dependent)
IF ~(Rope.Equal[name, "ems", FALSE]) AND ~(Rope.Equal[name, "ens",FALSE]) AND
 ~(Rope.Equal[name, "spaces", FALSE]) THEN {
 handle.layoutGraphics.units.prev ← name;
 ChangeValuesInViewers[handle, oldunits, name];
 };
};
ChangeValuesInViewers: PROCEDURE [handle: StyleToolHandle, oldUnits, newUnits: Rope.ROPE] = {
ChangeViewerValue[handle.layoutGraphics.pageWidth, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.pageLength, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.rightMargin, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.leftMargin, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.topMargin, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.bottomMargin, newUnits, oldUnits];
ChangeViewerValue[handle.layoutGraphics.bindingMargin, newUnits, oldUnits];
};
ChangeViewerValue: PROCEDURE [ref: ChoiceButtons.PromptDataRef, newUnits, oldUnits: Rope.ROPE] = {
value: REAL ← StyleToolConvert.GetRealFromViewer[ref.textViewer];
value ← StyleToolConvert.ConvertUnits[value, oldUnits, newUnits];
StyleToolBuilders.DisplayRealInViewer[value, ref.textViewer];
};
DetermineInterval: PROCEDURE [handle: StyleToolHandle, units: Rope.ROPE] = {
ChangeToDefault: PROCEDURE = {
MessageWindow.Append[Rope.Cat["Sorry, not implemented. Using ", defaultUnits], TRUE];
MessageWindow.Blink[];
ChoiceButtons.UpdateChoiceButtons[handle.layoutGraphics.numbersContainer,
 handle.layoutGraphics.units.ref, defaultUnits];
handle.layoutGraphics.interval ← defaultInterval;
-- convert all the margins, etc back to default units
ChangeValuesInViewers[handle, handle.layoutGraphics.units.prev, defaultUnits];
handle.layoutGraphics.units.prev ← defaultUnits;
};
SELECT TRUE FROM
 Rope.Equal[units, "points", FALSE]   => handle.layoutGraphics.interval ← 20; 
 Rope.Equal[units, "picas", FALSE]    => handle.layoutGraphics.interval ← 20;
 Rope.Equal[units, "inches", FALSE]   => handle.layoutGraphics.interval ← 40;
 Rope.Equal[units, "centimeters", FALSE]  => handle.layoutGraphics.interval ← 16;
 Rope.Equal[units, "millimeters", FALSE]  => handle.layoutGraphics.interval ← 16;
 Rope.Equal[units, "didot points", FALSE]  => handle.layoutGraphics.interval ← 16;
 Rope.Equal[units, "ems", FALSE]    => ChangeToDefault[];
 Rope.Equal[units, "ens", FALSE]    => ChangeToDefault[];
 Rope.Equal[units, "spaces", FALSE]   => ChangeToDefault[];
ENDCASE;
};
ConvertAndDisplay: PROCEDURE [ref: ValueAndUnitsRef, defaultValue: REAL, displayInfo: ChoiceButtons.PromptDataRef] = {
takes the value currently on display in the StyleTool (that is, in the ValueAndUnitsRef provided), converts it to inches and returns converted value in form of rope. If the value currently on display in the StyleTool was zero, the default value provided is used
value: REAL;
value ← StyleToolConvert.GetRealFromViewer[ref.valueData.textViewer];
IF (value = 0.0) THEN
 value ← defaultValue
ELSE
 value ← StyleToolConvert.ConvertUnits[value, ChoiceButtons.GetSelectedButton[ref.units],
  defaultUnits];
StyleToolBuilders.DisplayRealInViewer[value, displayInfo.textViewer];
};
SetUpNumbers: PUBLIC PROCEDURE [handle: StyleToolHandle] = {
initially we will default to inches. The user can change the units later
ConvertAndDisplay[handle.swap.layout.pageWidth, defaultPageWidth,
 handle.layoutGraphics.pageWidth];
ConvertAndDisplay[handle.swap.layout.pageLength, defaultPageLength,
 handle.layoutGraphics.pageLength];
ConvertAndDisplay[handle.swap.layout.leftMargin, defaultLeftMargin,
 handle.layoutGraphics.leftMargin];
ConvertAndDisplay[handle.swap.layout.rightMargin, defaultRightMargin,
 handle.layoutGraphics.rightMargin];
ConvertAndDisplay[handle.swap.layout.topMargin, defaultTopMargin,
 handle.layoutGraphics.topMargin];
ConvertAndDisplay[handle.swap.layout.bottomMargin, defaultBottomMargin,
 handle.layoutGraphics.bottomMargin];
ConvertAndDisplay[handle.swap.layout.bindingMargin, defaultBindingMargin,
 handle.layoutGraphics.bindingMargin];
};
InsidePage: PUBLIC PROCEDURE [handle: StyleToolHandle, x, y: REAL] RETURNS [BOOLEAN] = {
We check for less than or equal or greater than or equal so that the user can bring the margins right up to the page boundaries if desired.
IF (x <= handle.layoutGraphics.screenPage.xmax) AND
 (x >= handle.layoutGraphics.screenPage.xmin) AND
 (y <= handle.layoutGraphics.screenPage.ymax) AND
 (y >= handle.layoutGraphics.screenPage.ymin) THEN
RETURN [TRUE]
ELSE RETURN [FALSE];
};
HitAMargin: PUBLIC PROCEDURE [handle: StyleToolHandle, x,y: REAL] RETURNS [MarginType] = {
check vertical margins first (left and right). This is so that when there is an equally likely chance of choosing one of two margins (eg - the top margin or the left margin) the vertical margin will be chosen. This would happen if the mouse was on or very near to an intersection point. This situation will not happen with 2 vertical margins
epsilon: REAL ← 1.0;
IF (handle.layoutGraphics.screenLeftMargin <= x + epsilon) AND
 (handle.layoutGraphics.screenLeftMargin >= x - epsilon) THEN RETURN [left]
ELSE IF (handle.layoutGraphics.screenBindingMargin <= x + epsilon) AND
 (handle.layoutGraphics.screenBindingMargin >= x - epsilon) THEN RETURN [binding]
ELSE IF (handle.layoutGraphics.screenRightMargin <= x + epsilon) AND
 (handle.layoutGraphics.screenRightMargin >= x - epsilon) THEN RETURN [right]
ELSE IF (handle.layoutGraphics.screenTopMargin <= y + epsilon) AND
 (handle.layoutGraphics.screenTopMargin >= y - epsilon) THEN RETURN [top]
ELSE IF (handle.layoutGraphics.screenBottomMargin <= y+epsilon) AND
 (handle.layoutGraphics.screenBottomMargin >= y - epsilon) THEN RETURN [bottom]
ELSE RETURN [none];
};
HitAPage: PUBLIC PROCEDURE [handle: StyleToolHandle, x,y: REAL] RETURNS [PageBoundaryType] = {
check vertical page boundaries first (left and right). This is so that when there is an equally likely chance of choosing one of two page boundaries (eg - the top page boundary or the right page boundary) the vertical page boundary will be chosen. This would happen if the mouse was on or very near to an intersection point.
epsilon: REAL ← 3.0;
IF (handle.layoutGraphics.screenPage.xmin <= x + epsilon) AND
 (handle.layoutGraphics.screenPage.xmin >= x - epsilon) THEN {
OPEN MessageWindow; -- for Append and Blink
 Append["You cannot move the left page boundary to change the page width", TRUE];
 Blink[];
RETURN [none];
 }
ELSE IF (handle.layoutGraphics.screenPage.xmax <= x + epsilon) AND
 (handle.layoutGraphics.screenPage.xmax >= x - epsilon) THEN RETURN [side]
ELSE IF (handle.layoutGraphics.screenPage.ymax <= y + epsilon) AND
 (handle.layoutGraphics.screenPage.ymax >= y - epsilon) THEN RETURN [top]
ELSE IF (handle.layoutGraphics.screenPage.ymin <= y+epsilon) AND
 (handle.layoutGraphics.screenPage.ymin >= y - epsilon) THEN {
OPEN MessageWindow; -- for Append and Blink
 Append["You cannot move the bottom page boundary to change the page length", TRUE];
 Blink[];
RETURN [none]
 }
ELSE RETURN [none];
};
ScreenToLeftMargin: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics; -- for screenLeftMargin, screenPage, interval, increment
RETURN[((screenLeftMargin - screenPage.xmin)/ interval) * (increment/skip)];
};
ScreenToRightMargin: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics; -- for screenRightMargin, screenPage, interval, increment
RETURN[((screenPage.xmax - screenRightMargin)/ interval) * (increment/skip)];
};
ScreenToBindingMargin: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics; -- for screenBindingMargin, screenLeftMargin, interval, increment
RETURN[((screenBindingMargin - screenLeftMargin)/ interval) * (increment/skip)];
};
ScreenToTopMargin: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics; -- for screenTopMargin, screenPage, interval, increment
RETURN[((screenPage.ymax - screenTopMargin)/ interval) * (increment/skip)];
};
ScreenToBottomMargin: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics; -- for screenBottomMargin, screenPage, interval, increment
RETURN[((screenBottomMargin - screenPage.ymin)/ interval) * (increment/skip)];
};
ScreenToPageWidth: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics;  -- for screenPage, interval, increment
RETURN[((screenPage.xmax - screenPage.xmin)/ interval) * (increment/skip)];
};
ScreenToPageLength: PUBLIC PROCEDURE [handle: StyleToolHandle] RETURNS [REAL] = {
OPEN handle.layoutGraphics;  -- for screenPage, interval, increment
RETURN[((screenPage.ymax - screenPage.ymin)/ interval) * (increment/skip)];
};
END.