StyleToolGraphicsImpl.mesa
Written by Linda Gass September 10, 1982 4:34 pm
Last Edit by Linda Gass November 4, 1982 3:44 pm
Last Edited by: Plass, March 28, 1983 3:03 pm
Last Edited by: Beach, February 22, 1984 3:37:14 pm PST
Pavel, June 26, 1985 11:28:06 pm PDT
DIRECTORY
ChoiceButtons USING [GetSelectedButton, PromptDataRef],
Containers USING [ChildXBound, ChildYBound, Create],
Icons USING [IconFlavor, NewIconFromFile],
Imager USING [Box, Context, DoSave, MaskBox, MaskFill, MaskStrokeTrajectory, SetColor, SetStrokeEnd, SetStrokeJoint, SetStrokeWidth, SetFont, SetXY, ShowRope, StrokeJoint, StrokeEnd, black, white],
ImagerBackdoor USING [GetBounds, invert],
ImagerBox USING [BoxFromExtents, BoxFromRect],
ImagerColor USING [ColorFromRGB, ConstantColor],
ImagerFont USING [Font, RopeBoundingBox],
ImagerPath USING [LineTo, MoveTo, PathProc, Trajectory],
IO USING [int, PutFR],
MessageWindow USING [Clear],
Real USING [FixI],
Rope USING [Equal, ROPE],
StyleToolBuilders USING [DisplayRealInViewer],
StyleToolConvert USING [GetRealFromViewer],
StyleToolDefs USING [MarginType, PageBoundaryType, StyleToolHandle, ValueAndUnitsRef],
StyleToolGraphics,
StyleToolGraphicsMisc USING [CreateNumbersContainer, defaultInterval, HitAMargin, HitAPage, InsidePage, ScreenToLeftMargin, ScreenToRightMargin, ScreenToBindingMargin, ScreenToTopMargin, ScreenToBottomMargin, ScreenToPageWidth, ScreenToPageLength, SetUpNumbers],
TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPTable],
VFonts USING [EstablishFont],
ViewerClasses USING [NotifyProc, PaintProc, Viewer, ViewerClass, ViewerClassRec],
ViewerEvents USING [EventProc, RegisterEventProc, ViewerEvent],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass];
StyleToolGraphicsImpl: CEDAR PROGRAM
IMPORTS ChoiceButtons, Containers, Icons, Imager, ImagerBackdoor, ImagerBox, ImagerColor, ImagerFont, ImagerPath, IO, MessageWindow, Real, Rope, StyleToolBuilders, StyleToolConvert, StyleToolGraphicsMisc, TIPUser, VFonts, ViewerEvents, ViewerOps
EXPORTS StyleToolGraphics =
BEGIN OPEN StyleToolDefs, StyleToolGraphicsMisc;
PaintInfoRef: TYPE = REF PaintInfoRec;
PaintInfoRec: TYPE = RECORD [
whatToChange: Changeables,  -- part of layout to change
x,y: REAL       -- Mouse coordinates
];
Changeables: TYPE = {all, margin, page};
gray: ImagerColor.ConstantColor = ImagerColor.ColorFromRGB[[0.5, 0.5, 0.5]];
gridThickness: REAL = 1.0;
pageOutlineThickness: REAL = 2.0; 
marginThickness: REAL = 1.0;
layoutIcon: Icons.IconFlavor = Icons.NewIconFromFile["StyleTool.icons", 3];
CreateLayoutContainer: PUBLIC PROCEDURE [handle: StyleToolHandle] =
{
nexty: INTEGER;
handle.layoutGraphics.container ← Containers.Create[info:
[name: "PAGE LAYOUT", scrollable: FALSE, iconic: FALSE, icon: layoutIcon]];
nexty ← CreateNumbersContainer[handle];
handle.layoutGraphics.interval ← defaultInterval;
SetUpNumbers[handle];
CreateGraphicsViewer[handle, nexty];
ViewerOps.PaintViewer[handle.layoutGraphics.container, all];
};
DestroyProc: ViewerEvents.EventProc =
{
handle: StyleToolHandle ← NARROW[viewer.data];
handle.layoutGraphics.container ← NIL;
handle.layoutGraphics.exists ← FALSE;
};
CreateGraphicsViewer: PROCEDURE [handle: StyleToolHandle, starty: INTEGER] =
{
handle.layoutGraphics.viewer ←
ViewerOps.CreateViewer[flavor: $LayoutViewer,
info: [parent: handle.layoutGraphics.container, wx: 0, wy: starty, scrollable: FALSE, border: FALSE, data: handle]];
[] ← ViewerEvents.RegisterEventProc[proc: DestroyProc, event: destroy, filter: handle.layoutGraphics.viewer];
Since we have created our own viewer class, we can attach anything we want to the data field of the viewer rec. We put the handle there so that in future calls to the paint proc, we can have handle on the StyleTool.
Containers.ChildXBound[handle.layoutGraphics.container, handle.layoutGraphics.viewer];
Containers.ChildYBound[handle.layoutGraphics.container, handle.layoutGraphics.viewer];
};
UpdateValue: PROCEDURE[displayInfo: ChoiceButtons.PromptDataRef, newValue: REAL] = INLINE
{
StyleToolBuilders.DisplayRealInViewer[newValue, displayInfo.textViewer];
};
LayoutPainter: ViewerClasses.PaintProc =
{
handle: StyleToolHandle ← NARROW[self.data];
MessageWindow.Clear[];
IF whatChanged = NIL THEN
{
bounds: Imager.Box ← ImagerBox.BoxFromRect[ImagerBackdoor.GetBounds[context]];
DrawGrid[handle, context, clear, bounds];
DrawPage[handle, context];
DrawNumbers[handle, context, bounds];
DrawUnits[handle, context];
DrawMargins[handle, context];
}
ELSE
{
paintInfo: PaintInfoRef ← NARROW[whatChanged];
SELECT paintInfo.whatToChange FROM
margin => ChangeMargin[handle, context, paintInfo.x, paintInfo.y];
page => ChangePage[handle, context, paintInfo.x, paintInfo.y];
all => {
DrawPage[handle, context];
DrawMargins[handle, context];
};
ENDCASE => ERROR;
};
};
NotifyEvents: ViewerClasses.NotifyProc =
{
handle: StyleToolHandle ← NARROW[self.data];
iMouse, jMouse: REAL;
InterpretAtom: PROCEDURE [atom: ATOM] =
{
paintInfo: PaintInfoRef;
SELECT atom FROM
$StartMarginMode =>
IF InsidePage[handle, iMouse, jMouse] THEN
{
IF (handle.layoutGraphics.currentMargin ←
HitAMargin[handle, iMouse, jMouse]) # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [margin, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
};
$Margin =>
IF InsidePage[handle, iMouse, jMouse] THEN
{
IF handle.layoutGraphics.currentMargin = none THEN
{
IF (handle.layoutGraphics.currentMargin ←
HitAMargin[handle, iMouse, jMouse]) # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [margin, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
}
ELSE
{
paintInfo ← NEW [PaintInfoRec ← [margin, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
};
$EndMarginMode =>
IF InsidePage[handle, iMouse, jMouse] THEN
{
IF handle.layoutGraphics.currentMargin # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [margin, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
};
$StartPageMode =>
IF (handle.layoutGraphics.currentPage ←
HitAPage[handle, iMouse, jMouse]) # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [page, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
$Page =>
IF handle.layoutGraphics.currentPage = none THEN
{
IF (handle.layoutGraphics.currentPage ←
HitAPage[handle, iMouse, jMouse]) # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [page, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
}
ELSE
{
paintInfo ← NEW [PaintInfoRec ← [page, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
$EndPageMode =>
IF handle.layoutGraphics.currentPage # none THEN
{
paintInfo ← NEW [PaintInfoRec ← [all, iMouse, jMouse]];
ViewerOps.PaintViewer[viewer: self, hint: client, whatChanged: paintInfo, clearClient: FALSE];
};
ENDCASE;
};
FOR items: LIST OF REF ANY ← input, items.rest UNTIL items = NIL DO
WITH items.first SELECT FROM
x: TIPUser.TIPScreenCoords =>
{
iMouse ← x.mouseX;
jMouse ← x.mouseY;
};
x: ATOM =>
InterpretAtom[x];
ENDCASE;
ENDLOOP;
};
DrawGrid: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, clear: BOOLEAN, bounds: Imager.Box] =
{
xpos, ypos, rem: INTEGER;
path: ImagerPath.Trajectory;
Start on an even interval boundary
xpos ← Real.FixI[bounds.xmin];
rem ← (xpos MOD handle.layoutGraphics.interval);
IF rem # 0 THEN
xpos ← xpos + handle.layoutGraphics.interval - rem;
ypos ← Real.FixI[bounds.ymin];
rem ← ypos MOD handle.layoutGraphics.interval;
IF rem # 0 THEN
ypos ← ypos + handle.layoutGraphics.interval - rem;
First clear the viewer if necessary
IF ~clear THEN
{
Imager.SetColor[context, Imager.white];
Imager.MaskBox[context, bounds];
};
Now draw the grid
Imager.SetColor[context, gray];
Imager.SetStrokeWidth[context, gridThickness];
Imager.SetStrokeEnd[context, butt];
WHILE xpos <= bounds.xmax OR ypos <= bounds.ymax DO
Vertical lines
path ← ImagerPath.MoveTo[[xpos, bounds.ymin]];
path ← ImagerPath.LineTo[path, [xpos, bounds.ymax]];
Imager.MaskStrokeTrajectory[context, path];
Horizontal lines
path ← ImagerPath.MoveTo[[bounds.xmin, ypos]];
path ← ImagerPath.LineTo[path, [bounds.xmax, ypos]];
Imager.MaskStrokeTrajectory[context, path];
xpos ← xpos + handle.layoutGraphics.interval;
ypos ← ypos + handle.layoutGraphics.interval;
ENDLOOP;
};
DrawPage: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics; -- for screenPage, interval, indent, pageWidth, pageLength
pageVal: REAL;
path: ImagerPath.Trajectory;
DetermineIndent[handle];
DetermineSkipAndIncrement[handle];
screenPage.xmin ← indent*interval;
pageVal ← StyleToolConvert.GetRealFromViewer[pageWidth.textViewer];
screenPage.xmax ← ((pageVal / (increment/skip)) + indent) * interval;
screenPage.ymin ← indent*interval;
pageVal ← StyleToolConvert.GetRealFromViewer[pageLength.textViewer];
screenPage.ymax ← ((pageVal / (increment/skip)) + indent) * interval;
Clear the area which is the page
Imager.SetColor[context, Imager.white];
Imager.MaskBox[context, handle.layoutGraphics.screenPage];
Now draw the outline of the page
Imager.SetColor[context, Imager.black];
Imager.SetStrokeWidth[context, pageOutlineThickness];
Imager.SetStrokeJoint[context, mitered];
path ← ImagerPath.MoveTo[[screenPage.xmin, screenPage.ymin]];
path ← ImagerPath.LineTo[path, [screenPage.xmax, screenPage.ymin]];
path ← ImagerPath.LineTo[path, [screenPage.xmax, screenPage.ymax]];
path ← ImagerPath.LineTo[path, [screenPage.xmin, screenPage.ymax]];
path ← ImagerPath.LineTo[path, [screenPage.xmin, screenPage.ymin]];
Imager.MaskStrokeTrajectory[context, path, TRUE];
};
DetermineIndent: PROCEDURE [handle: StyleToolHandle] = {
units: Rope.ROPE ← ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref];
SELECT TRUE FROM
Rope.Equal[units, "points", FALSE]    => handle.layoutGraphics.indent ← 4; 
Rope.Equal[units, "picas", FALSE]   => handle.layoutGraphics.indent ← 4;
Rope.Equal[units, "inches", FALSE]   => handle.layoutGraphics.indent ← 2;
Rope.Equal[units, "centimeters", FALSE]  => handle.layoutGraphics.indent ← 4;
Rope.Equal[units, "millimeters", FALSE]  => handle.layoutGraphics.indent ← 4;
Rope.Equal[units, "didot points", FALSE]  => handle.layoutGraphics.indent ← 4;
ENDCASE          => handle.layoutGraphics.indent ← 2;
};
DrawText: PROC [context: Imager.Context, x, y: REAL, rope: Rope.ROPE] =
{
font: ImagerFont.Font ← VFonts.EstablishFont[family: "Helvetica", size: 8, bold: TRUE];
rxmin, rxmax, rymin, rymax: REAL;
x0, y0, x1, y1: REAL;
Path: ImagerPath.PathProc =
{
moveTo[[x0, y0]];
lineTo[[x1, y0]];
lineTo[[x1, y1]];
lineTo[[x0, y1]];
};
[[rxmin, rymin, rxmax, rymax]] ← ImagerBox.BoxFromExtents[ImagerFont.RopeBoundingBox[font, rope]];
x0 ← x - (rxmax - rxmin)/2 - 2; -- bottom right corner
y0 ← y - (rymax - rymin)/2;
x1 ← x + (rxmax - rxmin)/2 + 2; -- top left corner plus some pixels
y1 ← y + (rymax - rymin)/2;
Imager.SetColor[context, Imager.white];
Imager.MaskFill[context, Path];
Imager.SetColor[context, Imager.black];
Imager.SetXY[context, [x0 + 2, y0 + 2]];
Imager.SetFont[context, font];
Imager.ShowRope[context, rope];
};
DrawNumbers: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, bounds: Imager.Box] =
{
OPEN handle.layoutGraphics; -- for interval
xline, yline: REAL ← GetNumberLine[handle] * interval;
xpos, ypos: REAL ← indent*interval;
i: CARDINAL ← 0;
numberRope: Rope.ROPE;
Numbers accross x axis
WHILE xpos <= bounds.xmax DO
numberRope ← IO.PutFR["%g", IO.int[i]];
DrawText[context, xpos, yline, numberRope];
xpos ← xpos + skip * interval;
i ← i + increment;
ENDLOOP;
Numbers accross the y axis
i ← 0;
WHILE ypos <= bounds.ymax DO
numberRope ← IO.PutFR["%g", IO.int[i]];
DrawText[context, xline, ypos, numberRope];
ypos ← ypos + skip * interval;
i ← i + increment;
ENDLOOP;
};
GetNumberLine: PROCEDURE [handle: StyleToolHandle] RETURNS [INTEGER] =
{
units: Rope.ROPE ← ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref];
SELECT TRUE FROM
Rope.Equal[units, "points", FALSE]  => RETURN[2]; 
Rope.Equal[units, "picas", FALSE] => RETURN[2];
Rope.Equal[units, "inches", FALSE] => RETURN[1];
Rope.Equal[units, "centimeters", FALSE] => RETURN[2];
Rope.Equal[units, "millimeters", FALSE] => RETURN[2];
Rope.Equal[units, "didot points", FALSE] => RETURN[2];
ENDCASE   => RETURN[2];
};
DetermineSkipAndIncrement: PROCEDURE [handle: StyleToolHandle] =
{
units: Rope.ROPE ← ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref];
SELECT TRUE FROM
Rope.Equal[units, "points", FALSE] =>
{handle.layoutGraphics.skip ← 2;
handle.layoutGraphics.increment ← 72};
Rope.Equal[units, "picas", FALSE] =>
{handle.layoutGraphics.skip ← 1;
handle.layoutGraphics.increment ← 3};
Rope.Equal[units, "inches", FALSE] =>
{handle.layoutGraphics.skip ← 1;
handle.layoutGraphics.increment ← 1};
Rope.Equal[units, "centimeters", FALSE] =>
{handle.layoutGraphics.skip ← 2;
handle.layoutGraphics.increment ← 2};
Rope.Equal[units, "millimeters", FALSE] =>
{handle.layoutGraphics.skip ← 2;
handle.layoutGraphics.increment ← 20};
Rope.Equal[units, "didot points", FALSE] =>
{handle.layoutGraphics.skip ← 2;
handle.layoutGraphics.increment ← 50};
ENDCASE =>
{handle.layoutGraphics.skip ← 1;
handle.layoutGraphics.increment ← 1};
};
DrawUnits: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
unitsRope: Rope.ROPE;
xline, yline: REAL ← GetNumberLine[handle] * handle.layoutGraphics.interval;
unitsRope ← ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref];
DrawText[context, xline, yline, unitsRope];
};
DrawMargins: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
Imager.SetColor[context, Imager.black];
Imager.SetStrokeWidth[context, marginThickness];
Imager.SetStrokeEnd[context, butt];
DrawLeftMargin[handle, context];
DrawRightMargin[handle, context];
DrawTopMargin[handle, context];
DrawBottomMargin[handle, context];
DrawBindingMargin[handle, context];
};
DrawLeftMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics;
margin: REAL ← StyleToolConvert.GetRealFromViewer[leftMargin.textViewer];
path: ImagerPath.Trajectory;
screenLeftMargin ← screenPage.xmin + ((margin / (increment/skip)) * interval);
Dont bother drawing a margin which lies outside of the page
IF screenLeftMargin < screenPage.xmax THEN
{
path ← ImagerPath.MoveTo[[screenLeftMargin, screenPage.ymin]];
path ← ImagerPath.LineTo[path, [screenLeftMargin, screenPage.ymax]];
Imager.MaskStrokeTrajectory[context, path];
};
};
DrawRightMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics; -- for rightMargin, screenRightMargin, screenPage and interval
margin: REAL ← StyleToolConvert.GetRealFromViewer[rightMargin.textViewer];
path: ImagerPath.Trajectory;
screenRightMargin ← screenPage.xmax - ((margin / (increment/skip)) * interval);
IF screenRightMargin > screenPage.xmin THEN
{
path ← ImagerPath.MoveTo[[screenRightMargin, screenPage.ymin]];
path ← ImagerPath.LineTo[path, [screenRightMargin, screenPage.ymax]];
Imager.MaskStrokeTrajectory[context, path];
};
};
DrawTopMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics;
margin: REAL ← StyleToolConvert.GetRealFromViewer[topMargin.textViewer];
path: ImagerPath.Trajectory;
screenTopMargin ← screenPage.ymax - ((margin / (increment/skip)) * interval);
IF screenTopMargin > screenPage.ymin THEN
{
path ← ImagerPath.MoveTo[[screenPage.xmin, screenTopMargin]];
path ← ImagerPath.LineTo[path, [screenPage.xmax, screenTopMargin]];
Imager.MaskStrokeTrajectory[context, path];
};
};
DrawBottomMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics;
margin: REAL ← StyleToolConvert.GetRealFromViewer[bottomMargin.textViewer];
path: ImagerPath.Trajectory;
screenBottomMargin ← screenPage.ymin + ((margin / (increment/skip)) * interval);
IF screenBottomMargin < screenPage.ymax THEN
{
path ← ImagerPath.MoveTo[[screenPage.xmin, screenBottomMargin]];
path ← ImagerPath.LineTo[path, [screenPage.xmax, screenBottomMargin]];
Imager.MaskStrokeTrajectory[context, path];
};
};
DrawBindingMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context] =
{
OPEN handle.layoutGraphics;
offset: REAL ← StyleToolConvert.GetRealFromViewer[bindingMargin.textViewer];
path: ImagerPath.Trajectory;
screenBindingMargin ← screenLeftMargin + ((offset / (increment/skip)) * interval);
IF screenBindingMargin < screenPage.xmax THEN
{
path ← ImagerPath.MoveTo[[screenBindingMargin, screenPage.ymin]];
path ← ImagerPath.LineTo[path, [screenBindingMargin, screenPage.ymax]];
Imager.MaskStrokeTrajectory[context, path];
};
};
ChangeMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context, x, y: REAL] =
{
For each different margin we do the same procedure. First check that the new position will not cause the margin to overlap with its "opposite" margin. This means that if we are changing the right margin, we first want to check that the new right margin will not overlap the left margin, this would not make sense and it would drive the typesetter crazy. If everything is OK, then change the position of the margin.
OPEN handle.layoutGraphics;
neverLand: REAL ← 5.0;
SELECT currentMargin FROM
left =>
IF (x + neverLand) < screenRightMargin THEN
{
diff: REAL ← x - screenLeftMargin;
DrawVerticalMargin[handle, context, screenLeftMargin];
screenLeftMargin ← x;
DrawVerticalMargin[handle, context, screenLeftMargin];
UpdateValue[leftMargin, ScreenToLeftMargin[handle]];
Also redraw the binding margin accordingly
DrawVerticalMargin[handle, context, screenBindingMargin];
screenBindingMargin ← screenBindingMargin + diff;
DrawVerticalMargin[handle, context, screenBindingMargin];
No need to update the value of the binding margin since it's an offset and that hasn't changed
};
right =>
IF (x - neverLand) > screenLeftMargin THEN
{
DrawVerticalMargin[handle, context, screenRightMargin];
screenRightMargin ← x;
DrawVerticalMargin[handle, context, screenRightMargin];
UpdateValue[rightMargin, ScreenToRightMargin[handle]];
};
binding =>
IF x > screenLeftMargin THEN
{
DrawVerticalMargin[handle, context, screenBindingMargin];
screenBindingMargin ← x;
DrawVerticalMargin[handle, context, screenBindingMargin];
UpdateValue[bindingMargin, ScreenToBindingMargin[handle]];
};
top =>
IF (y - neverLand) > screenBottomMargin THEN
{
DrawHorizontalMargin[handle, context, screenTopMargin];
screenTopMargin ← y;
DrawHorizontalMargin[handle, context, screenTopMargin];
UpdateValue[topMargin, ScreenToTopMargin[handle]];
};
bottom =>
IF (y + neverLand) < screenTopMargin THEN
{
DrawHorizontalMargin[handle, context, screenBottomMargin];
screenBottomMargin ← y;
DrawHorizontalMargin[handle, context, screenBottomMargin];
UpdateValue[bottomMargin, ScreenToBottomMargin[handle]];
};
ENDCASE;
};
DrawVerticalMargin: PROCEDURE [handle: StyleToolHandle, context: Imager.Context, x: REAL] =
{
inner: PROC =
{
path: ImagerPath.Trajectory;
Imager.SetColor[context, ImagerBackdoor.invert];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, marginThickness];
path ← ImagerPath.MoveTo[[x, handle.layoutGraphics.screenPage.ymin]];
path ← ImagerPath.LineTo[path, [x, handle.layoutGraphics.screenPage.ymax]];
Imager.MaskStrokeTrajectory[context, path];
};
Imager.DoSave[context, inner];
};
DrawHorizontalMargin: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, y: REAL] =
{
inner: PROC =
{
path: ImagerPath.Trajectory;
Imager.SetColor[context, ImagerBackdoor.invert];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, marginThickness];
path ← ImagerPath.MoveTo[[handle.layoutGraphics.screenPage.xmin, y]];
path ← ImagerPath.LineTo[path, [handle.layoutGraphics.screenPage.xmax, y]];
Imager.MaskStrokeTrajectory[context, path];
};
Imager.DoSave[context, inner];
};
ChangePage: PROCEDURE [handle: StyleToolHandle, context: Imager.Context, x, y: REAL] =
{
For the different page boundaries we do the same procedure. First check that the new position will not cause the boundary to overlap with its "opposite" boundary. This means that if we are changing the right boundary, we first want to check that the new right boundary will not overlap the left boundary, this would not make sense and it would drive the typesetter crazy. If everything is OK, then change the position of the page boundary.
neverLand: REAL ← 5.0;
SELECT handle.layoutGraphics.currentPage FROM
side =>
IF (x - neverLand) > handle.layoutGraphics.screenPage.xmin THEN
{
IF x < handle.layoutGraphics.screenPage.xmax THEN
Indicates that we are making the page smaller so need to redraw the grid.
DrawSmallerPageFromRight[handle, context, x]
ELSE
DrawLargerPageFromRight[handle, context, x];
handle.layoutGraphics.screenPage.xmax ← x;
UpdateValue[handle.layoutGraphics.pageWidth, ScreenToPageWidth[handle]];
};
top =>
IF (y - neverLand) > handle.layoutGraphics.screenPage.ymin THEN
{
IF y < handle.layoutGraphics.screenPage.ymax THEN
Indicates that we are making the page smaller so need to redraw the grid
DrawSmallerPageFromTop[handle, context, y]
ELSE
DrawLargerPageFromTop[handle, context, y];
handle.layoutGraphics.screenPage.ymax ← y;
UpdateValue[handle.layoutGraphics.pageLength, ScreenToPageLength[handle]];
};
ENDCASE;
};
DrawSmallerPageFromRight: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, x: REAL] =
{
OPEN handle.layoutGraphics;
tempBox, gridBox: Imager.Box;
path: ImagerPath.Trajectory;
tempBox.xmin ← x;
tempBox.xmax ← screenPage.xmax;
tempBox.ymin ← screenPage.ymin;
tempBox.ymax ← screenPage.ymax;
Remove the old outline
Imager.SetColor[context, Imager.white];
DrawThreePageSides[context, tempBox];
White out the area to be redrawn and redraw the grid
gridBox ← tempBox;
gridBox.xmax ← tempBox.xmax + 1; -- since the page outline is 2 units wide
gridBox.ymax ← tempBox.ymax + 1;
DrawGrid[handle, context, FALSE, gridBox];
Now redraw the right page boundary
Imager.SetColor[context, Imager.black];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, pageOutlineThickness];
path ← ImagerPath.MoveTo[[tempBox.xmin, tempBox.ymin]];
path ← ImagerPath.LineTo[path, [tempBox.xmin, tempBox.ymax]];
Imager.MaskStrokeTrajectory[context, path];
Now redraw the margin
IF (screenRightMargin - (tempBox.xmax - tempBox.xmin)) > screenPage.xmin THEN
{
DrawVerticalMargin[handle, context, screenRightMargin]; -- erase old one
screenRightMargin ← screenRightMargin - (tempBox.xmax - tempBox.xmin);
DrawVerticalMargin[handle, context, screenRightMargin];
};
};
DrawSmallerPageFromTop: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, y: REAL] =
{
OPEN handle.layoutGraphics;
tempBox, gridBox: Imager.Box;
path: ImagerPath.Trajectory;
tempBox.xmin ← screenPage.xmin;
tempBox.xmax ← screenPage.xmax;
tempBox.ymin ← y;
tempBox.ymax ← screenPage.ymax;
Remove the old outline
Imager.SetColor[context, Imager.white];
DrawThreePageSidesFromTop[context, tempBox];
White out the area to be redrawn and redraw the grid
gridBox ← tempBox;
gridBox.xmax ← tempBox.xmax + 1; -- since the page outline is 2 units wide
gridBox.ymax ← tempBox.ymax + 1;
DrawGrid[handle, context, FALSE, gridBox];
Now redraw the top page boundary
Imager.SetColor[context, Imager.black];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, pageOutlineThickness];
path ← ImagerPath.MoveTo[[tempBox.xmin, tempBox.ymin]];
path ← ImagerPath.LineTo[path, [tempBox.xmax, tempBox.ymin]];
Imager.MaskStrokeTrajectory[context, path];
Now redraw the margin
IF (screenTopMargin - (tempBox.ymax - tempBox.ymin)) > screenPage.ymin THEN
{
DrawHorizontalMargin[handle, context, screenTopMargin];-- erase old one
screenTopMargin ← screenTopMargin - (tempBox.ymax - tempBox.ymin);
DrawHorizontalMargin[handle, context, screenTopMargin];
};
};
DrawLargerPageFromRight: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, x: REAL] =
{
OPEN handle.layoutGraphics;
tempBox: Imager.Box;
path: ImagerPath.Trajectory;
tempBox.xmin ← screenPage.xmax;
tempBox.xmax ← x;
tempBox.ymin ← screenPage.ymin;
tempBox.ymax ← screenPage.ymax;
Erase the old grid and old page boundary
Imager.SetColor[context, Imager.white];
Imager.MaskBox[context, tempBox];
Extend old top and bottom page boundaries and draw new right boundary
Imager.SetColor[context, Imager.black];
DrawThreePageSides[context, tempBox];
Now redraw the right margin and extend others.
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, marginThickness];
path ← ImagerPath.MoveTo[[tempBox.xmin, screenTopMargin]];
path ← ImagerPath.LineTo[path, [tempBox.xmax, screenTopMargin]];
Imager.MaskStrokeTrajectory[context, path];
path ← ImagerPath.MoveTo[[tempBox.xmin, screenBottomMargin]];
path ← ImagerPath.LineTo[path, [tempBox.xmax, screenBottomMargin]];
Imager.MaskStrokeTrajectory[context, path];
DrawVerticalMargin[handle, context, screenRightMargin]; -- erase old one
screenRightMargin ← screenRightMargin + (tempBox.xmax - tempBox.xmin);
DrawVerticalMargin[handle, context, handle.layoutGraphics.screenRightMargin];
};
DrawLargerPageFromTop: PROCEDURE
[handle: StyleToolHandle, context: Imager.Context, y: REAL] =
{
OPEN handle.layoutGraphics;
tempBox: Imager.Box;
path: ImagerPath.Trajectory;
tempBox.xmin ← screenPage.xmin;
tempBox.xmax ← screenPage.xmax;
tempBox.ymin ← screenPage.ymax-1;
tempBox.ymax ← y;
Erase the old grid and old page boundary
Imager.SetColor[context, Imager.white];
Imager.MaskBox[context, tempBox];
Extend old left and right page boundaries and draw new top boundary
Imager.SetColor[context, Imager.black];
DrawThreePageSidesFromTop[context, tempBox];
Now redraw the top margin and extend others.
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeWidth[context, marginThickness];
path ← ImagerPath.MoveTo[[screenRightMargin, tempBox.ymin]];
path ← ImagerPath.LineTo[path, [screenRightMargin, tempBox.ymax+1]];
Imager.MaskStrokeTrajectory[context, path];
path ← ImagerPath.MoveTo[[screenLeftMargin, tempBox.ymin]];
path ← ImagerPath.LineTo[path, [screenLeftMargin, tempBox.ymax+1]];
Imager.MaskStrokeTrajectory[context, path];
path ← ImagerPath.MoveTo[[screenBindingMargin, tempBox.ymin]];
path ← ImagerPath.LineTo[path, [screenBindingMargin, tempBox.ymax+1]];
Imager.MaskStrokeTrajectory[context, path];
DrawHorizontalMargin[handle,context, screenTopMargin]; -- erase old one
screenTopMargin ← screenTopMargin + (tempBox.ymax - tempBox.ymin - 1);
DrawHorizontalMargin[handle, context, screenTopMargin];
};
DrawThreePageSides: PROCEDURE [context: Imager.Context, box: Imager.Box] =
{
path: ImagerPath.Trajectory;
Imager.SetStrokeWidth[context, pageOutlineThickness];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeJoint[context, mitered];
path ← ImagerPath.MoveTo[[box.xmin, box.ymin]];
path ← ImagerPath.LineTo[path, [box.xmax, box.ymin]];
path ← ImagerPath.LineTo[path, [box.xmax, box.ymax]];
path ← ImagerPath.LineTo[path, [box.xmin, box.ymax]];
Imager.MaskStrokeTrajectory[context, path];
};
DrawThreePageSidesFromTop: PROCEDURE [context: Imager.Context, box: Imager.Box] =
{
path: ImagerPath.Trajectory;
Imager.SetStrokeWidth[context, pageOutlineThickness];
Imager.SetStrokeEnd[context, butt];
Imager.SetStrokeJoint[context, mitered];
path ← ImagerPath.MoveTo[[box.xmin, box.ymin]];
path ← ImagerPath.LineTo[path, [box.xmin, box.ymax]];
path ← ImagerPath.LineTo[path, [box.xmax, box.ymax]];
path ← ImagerPath.LineTo[path, [box.xmax, box.ymin]];
Imager.MaskStrokeTrajectory[context, path];
};
graphicsTipTable: TIPUser.TIPTable = TIPUser.InstantiateNewTIPTable["StyleToolGraphics.TIP"];
layoutViewerClass: ViewerClasses.ViewerClass ←
NEW[ViewerClasses.ViewerClassRec ← [
paint: LayoutPainter,
notify: NotifyEvents,
tipTable: graphicsTipTable
]];
ViewerOps.RegisterViewerClass[$LayoutViewer, layoutViewerClass];
END.