<< StyleToolGraphicsImpl.mesa Written by Linda Gass September 10, 1982 4:34 pm Last Edit by Linda Gass November 4, 1982 3:44 pm>> <> <> DIRECTORY ChoiceButtons USING [GetSelectedButton, PromptDataRef], Containers USING [ChildXBound, ChildYBound, Create], Graphics USING [black, Box, Color, Context, DrawBox, DrawArea, DrawStroke, DrawRope, FontRef, GetBounds, LineTo, MoveTo, NewPath, PaintMode, Path, Rectangle, RopeBox, SetColor, SetCP, SetPaintMode, white], GraphicsColor USING [RGBToColor], Icons USING [NewIconFromFile], 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], VFonts USING [EstablishFont, Font, GraphicsFont], ViewerClasses USING [NotifyProc, PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass]; StyleToolGraphicsImpl: CEDAR PROGRAM IMPORTS ChoiceButtons, Containers, Graphics, GraphicsColor, Icons, IO, MessageWindow, Real, Rope, StyleToolBuilders, StyleToolConvert, StyleToolGraphicsMisc, TIPUser, VFonts, 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: Graphics.Color = GraphicsColor.RGBToColor[0.5, 0.5, 0.5]; gridThickness: REAL = 1.0; pageOutlineThickness: REAL = 2.0; marginThickness: REAL = 1.0; CreateLayoutContainer: PUBLIC PROCEDURE [handle: StyleToolHandle] = { nexty: INTEGER; handle.layoutGraphics.container _ Containers.Create[info: [name: "PAGE LAYOUT", scrollable: FALSE, iconic: FALSE, column: left, icon: Icons.NewIconFromFile["StyleTool.icons", 3]]]; nexty _ CreateNumbersContainer[handle]; handle.layoutGraphics.interval _ defaultInterval; SetUpNumbers[handle]; CreateGraphicsViewer[handle, nexty]; ViewerOps.PaintViewer[handle.layoutGraphics.container, all]; }; <> << handle: StyleToolHandle _ NARROW[clientData]; IF ~MessageWindow.Confirm["Confirm discarding all edits . . ."] THEN RETURN; ViewerOps.DestroyViewer[handle.layoutGraphics.container]; handle.layoutGraphics.container _ NIL; handle.layoutGraphics.exists _ FALSE; };>> CreateGraphicsViewer: PROCEDURE [handle: StyleToolHandle, starty: INTEGER] = { layoutViewerClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: LayoutPainter, notify: NotifyEvents, coordSys: bottom, tipTable: TIPUser.InstantiateNewTIPTable["StyleToolGraphics.TIP"] ]]; ViewerOps.RegisterViewerClass[$LayoutViewer, layoutViewerClass]; handle.layoutGraphics.viewer _ ViewerOps.CreateViewer[flavor: $LayoutViewer, info: [ parent: handle.layoutGraphics.container, wx: 0, wy: starty, scrollable: FALSE, border: FALSE, data: handle]]; << 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: Graphics.Box _ Graphics.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: Graphics.Context, clear: BOOLEAN, bounds: Graphics.Box] = { xpos, ypos, rem: INTEGER; path: Graphics.Path; << 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 { Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, bounds]; }; << now draw the grid>> Graphics.SetColor[context, gray]; path _ Graphics.NewPath[]; WHILE xpos <= bounds.xmax OR ypos <= bounds.ymax DO << vertical lines>> Graphics.MoveTo[path, xpos, bounds.ymin, TRUE]; -- flush = true to flush out previous path Graphics.LineTo[path, xpos, bounds.ymax]; Graphics.DrawStroke[context, path, gridThickness]; << horizontal lines>> Graphics.MoveTo[path, bounds.xmin, ypos, TRUE]; Graphics.LineTo[path, bounds.xmax, ypos]; Graphics.DrawStroke[context, path, gridThickness]; xpos _ xpos + handle.layoutGraphics.interval; ypos _ ypos + handle.layoutGraphics.interval; ENDLOOP; }; DrawPage: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { << start the proper amount of units in>> OPEN handle.layoutGraphics; -- for screenPage, interval, indent, pageWidth, pageLength pageVal: REAL; path: Graphics.Path; 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>> Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, handle.layoutGraphics.screenPage]; << now draw the outline of the page>> Graphics.SetColor[context, Graphics.black]; path _ Graphics.NewPath[]; Graphics.MoveTo[path, screenPage.xmin, screenPage.ymin]; Graphics.LineTo[path, screenPage.xmax, screenPage.ymin]; Graphics.LineTo[path, screenPage.xmax, screenPage.ymax]; Graphics.LineTo[path, screenPage.xmin, screenPage.ymax]; Graphics.LineTo[path, screenPage.xmin, screenPage.ymin]; Graphics.DrawStroke[context, path, pageOutlineThickness]; }; 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; }; DrawNumbers: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context, bounds: Graphics.Box] = { OPEN handle.layoutGraphics; -- for interval font: Graphics.FontRef _ VFonts.GraphicsFont[VFonts.EstablishFont[ family: "Helvetica", size: 10, bold: TRUE, italic: FALSE, defaultOnFailure: TRUE]]; xline, yline: REAL _ GetNumberLine[handle] * interval; xpos, ypos: REAL _ indent*interval; rxmin, rxmax, rymin, rymax: REAL; x0, y0, x1, y1: REAL; i: CARDINAL _ 0; numberRope: Rope.ROPE; path: Graphics.Path _ Graphics.NewPath[]; << numbers accross x axis>> WHILE xpos <= bounds.xmax DO numberRope _ IO.PutFR["%g", IO.int[i]]; [rxmin, rymin, rxmax, rymax] _ Graphics.RopeBox[font, numberRope]; x0 _ xpos - (rxmax - rxmin)/2 - 2; -- bottom right corner y0 _ yline - (rymax - rymin)/2; x1 _ xpos + (rxmax - rxmin)/2 + 2; -- top left corner plus some pixels y1 _ yline + (rymax - rymin)/2; Graphics.SetColor[context, Graphics.white]; Graphics.MoveTo[path, x0, y0, TRUE]; Graphics.Rectangle[path, x0, y0, x1, y1]; Graphics.DrawArea[context, path]; Graphics.SetColor[context, Graphics.black]; Graphics.SetCP[context, x0 + 2, y0 + 2]; Graphics.DrawRope[self: context, rope: numberRope, font: font]; 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]]; [rxmin, rymin, rxmax, rymax] _ Graphics.RopeBox[font, numberRope]; x0 _ xline - (rxmax - rxmin)/2 - 2; -- bottom right corner y0 _ ypos - (rymax - rymin)/2; x1 _ xline + (rxmax - rxmin)/2 + 2; -- top left corner plus some pixels y1 _ ypos + (rymax - rymin)/2; Graphics.SetColor[context, Graphics.white]; Graphics.MoveTo[path, x0, y0, TRUE]; Graphics.Rectangle[path, x0, y0, x1, y1]; Graphics.DrawArea[context, path]; Graphics.SetColor[context, Graphics.black]; Graphics.SetCP[context, x0 + 2, y0 + 2]; Graphics.DrawRope[self: context, rope: numberRope, font: font]; 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: Graphics.Context] = { unitsRope: Rope.ROPE; font: Graphics.FontRef _ VFonts.GraphicsFont[VFonts.EstablishFont[ family: "Helvetica", size: 8, bold: TRUE, italic: FALSE, defaultOnFailure: TRUE]]; xline, yline: REAL _ GetNumberLine[handle] * handle.layoutGraphics.interval; rxmin, rxmax, rymin, rymax: REAL; x0, y0, x1, y1: REAL; path: Graphics.Path _ Graphics.NewPath[]; unitsRope _ ChoiceButtons.GetSelectedButton[handle.layoutGraphics.units.ref]; [rxmin, rymin, rxmax, rymax] _ Graphics.RopeBox[font, unitsRope]; x0 _ xline - (rxmax - rxmin)/2 - 2; -- bottom right corner y0 _ yline - (rymax - rymin)/2; x1 _ xline + (rxmax - rxmin)/2 + 2; -- top left corner plus some pixels y1 _ yline + (rymax - rymin)/2; Graphics.SetColor[context, Graphics.white]; Graphics.MoveTo[path, x0, y0]; Graphics.Rectangle[path, x0, y0, x1, y1]; Graphics.DrawArea[context, path]; Graphics.SetColor[context, Graphics.black]; Graphics.SetCP[context, x0 + 2, y0 + 2]; Graphics.DrawRope[self: context, rope: unitsRope, font: font]; }; DrawMargins: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { Graphics.SetColor[context, Graphics.black]; DrawLeftMargin[handle, context]; DrawRightMargin[handle, context]; DrawTopMargin[handle, context]; DrawBottomMargin[handle, context]; DrawBindingMargin[handle, context]; }; DrawLeftMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { OPEN handle.layoutGraphics; -- for leftMargin, screenLeftMargin, screenPage and interval margin: REAL _ StyleToolConvert.GetRealFromViewer[leftMargin.textViewer]; path: Graphics.Path _ Graphics.NewPath[]; screenLeftMargin _ screenPage.xmin + ((margin / (increment/skip)) * interval); IF screenLeftMargin < screenPage.xmax THEN { -- Dont bother drawing a margin which lies outside of the page Graphics.MoveTo[path, screenLeftMargin, screenPage.ymin]; Graphics.LineTo[path, screenLeftMargin, screenPage.ymax]; Graphics.DrawStroke[context, path, marginThickness]; }; }; DrawRightMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { OPEN handle.layoutGraphics; -- for rightMargin, screenRightMargin, screenPage and interval margin: REAL _ StyleToolConvert.GetRealFromViewer[rightMargin.textViewer]; path: Graphics.Path _ Graphics.NewPath[]; screenRightMargin _ screenPage.xmax - ((margin / (increment/skip)) * interval); IF screenRightMargin > screenPage.xmin THEN { Graphics.MoveTo[path, screenRightMargin, screenPage.ymin]; Graphics.LineTo[path, screenRightMargin, screenPage.ymax]; Graphics.DrawStroke[context, path, marginThickness]; }; }; DrawTopMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { OPEN handle.layoutGraphics; -- for topMargin, screenTopMargin, screenPage and interval margin: REAL _ StyleToolConvert.GetRealFromViewer[topMargin.textViewer]; path: Graphics.Path _ Graphics.NewPath[]; screenTopMargin _ screenPage.ymax - ((margin / (increment/skip)) * interval); IF screenTopMargin > screenPage.ymin THEN { Graphics.MoveTo[path, screenPage.xmin, screenTopMargin]; Graphics.LineTo[path, screenPage.xmax, screenTopMargin]; Graphics.DrawStroke[context, path, marginThickness]; }; }; DrawBottomMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { OPEN handle.layoutGraphics; -- for bottomMargin, screenBottomMargin, screenPage and interval margin: REAL _ StyleToolConvert.GetRealFromViewer[bottomMargin.textViewer]; path: Graphics.Path _ Graphics.NewPath[]; screenBottomMargin _ screenPage.ymin + ((margin / (increment/skip)) * interval); IF screenBottomMargin < screenPage.ymax THEN { Graphics.MoveTo[path, screenPage.xmin, screenBottomMargin]; Graphics.LineTo[path, screenPage.xmax, screenBottomMargin]; Graphics.DrawStroke[context, path, marginThickness]; }; }; DrawBindingMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context] = { OPEN handle.layoutGraphics; -- for bindingMargin, screenBindingMargin, screenPage and interval offset: REAL _ StyleToolConvert.GetRealFromViewer[bindingMargin.textViewer]; path: Graphics.Path _ Graphics.NewPath[]; screenBindingMargin _ screenLeftMargin + ((offset / (increment/skip)) * interval); IF screenBindingMargin < screenPage.xmax THEN { Graphics.MoveTo[path, screenBindingMargin, screenPage.ymin]; Graphics.LineTo[path, screenBindingMargin, screenPage.ymax]; Graphics.DrawStroke[context, path, marginThickness]; }; }; ChangeMargin: PROCEDURE [handle: StyleToolHandle, context: Graphics.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; -- for currentMargin, screenRightMargin, screenLeftMargin, rightMargin, leftMargin, etc 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: Graphics.Context, x: REAL] = { oldPaintMode: Graphics.PaintMode _ Graphics.SetPaintMode[context, invert]; path: Graphics.Path _ Graphics.NewPath[]; Graphics.MoveTo[path, x, handle.layoutGraphics.screenPage.ymin]; Graphics.LineTo[path, x, handle.layoutGraphics.screenPage.ymax]; Graphics.DrawStroke[context, path, marginThickness]; [] _ Graphics.SetPaintMode[context, oldPaintMode]; }; DrawHorizontalMargin: PROCEDURE[handle: StyleToolHandle, context: Graphics.Context, y: REAL]={ oldPaintMode: Graphics.PaintMode _ Graphics.SetPaintMode[context, invert]; path: Graphics.Path _ Graphics.NewPath[]; Graphics.MoveTo[path, handle.layoutGraphics.screenPage.xmin, y]; Graphics.LineTo[path, handle.layoutGraphics.screenPage.xmax, y]; Graphics.DrawStroke[context, path, marginThickness]; [] _ Graphics.SetPaintMode[context, oldPaintMode]; }; ChangePage: PROCEDURE [handle: StyleToolHandle, context: Graphics.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: Graphics.Context, x: REAL] = { OPEN handle.layoutGraphics; -- for screenPage, screenRightMargin tempBox, gridBox: Graphics.Box; path: Graphics.Path _ Graphics.NewPath[]; tempBox.xmin _ x; tempBox.xmax _ screenPage.xmax; tempBox.ymin _ screenPage.ymin; tempBox.ymax _ screenPage.ymax; << remove the old outline>> Graphics.SetColor[context, Graphics.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 >> Graphics.SetColor[context, Graphics.black]; Graphics.MoveTo[path, tempBox.xmin, tempBox.ymin]; Graphics.LineTo[path, tempBox.xmin, tempBox.ymax]; Graphics.DrawStroke[context, path, pageOutlineThickness]; << 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: Graphics.Context, y: REAL] = { OPEN handle.layoutGraphics; -- for screenPage, screenTopMargin tempBox, gridBox: Graphics.Box; path: Graphics.Path _ Graphics.NewPath[]; tempBox.xmin _ screenPage.xmin; tempBox.xmax _ screenPage.xmax; tempBox.ymin _ y; tempBox.ymax _ screenPage.ymax; << remove the old outline>> Graphics.SetColor[context, Graphics.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 >> Graphics.SetColor[context, Graphics.black]; Graphics.MoveTo[path, tempBox.xmin, tempBox.ymin]; Graphics.LineTo[path, tempBox.xmax, tempBox.ymin]; Graphics.DrawStroke[context, path, pageOutlineThickness]; << 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: Graphics.Context, x: REAL] = { OPEN handle.layoutGraphics; -- for screenPage,screenTopMargin,screenBottomMargin,screenRightMargin tempBox: Graphics.Box; path: Graphics.Path _ Graphics.NewPath[]; tempBox.xmin _ screenPage.xmax; tempBox.xmax _ x; tempBox.ymin _ screenPage.ymin; tempBox.ymax _ screenPage.ymax; -- erase the old grid and old page boundary Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, tempBox]; << extend old top and bottom page boundaries and draw new right boundary>> Graphics.SetColor[context, Graphics.black]; DrawThreePageSides[context, tempBox]; << now redraw the right margin and extend others.>> Graphics.MoveTo[path, tempBox.xmin, screenTopMargin]; Graphics.LineTo[path, tempBox.xmax, screenTopMargin]; Graphics.DrawStroke[context, path, marginThickness]; Graphics.MoveTo[path, tempBox.xmin, screenBottomMargin, TRUE]; Graphics.LineTo[path, tempBox.xmax, screenBottomMargin]; Graphics.DrawStroke[context, path, marginThickness]; DrawVerticalMargin[handle, context, screenRightMargin];-- erase old one screenRightMargin _ screenRightMargin + (tempBox.xmax - tempBox.xmin); DrawVerticalMargin[handle, context, handle.layoutGraphics.screenRightMargin]; }; DrawLargerPageFromTop: PROCEDURE [handle: StyleToolHandle, context: Graphics.Context, y: REAL] = { OPEN handle.layoutGraphics; -- for screenPage, screenRightMargin, screenLeftMargin, screenBindingMargin tempBox: Graphics.Box; path: Graphics.Path _ Graphics.NewPath[]; tempBox.xmin _ screenPage.xmin; tempBox.xmax _ screenPage.xmax; tempBox.ymin _ screenPage.ymax-1; tempBox.ymax _ y; << erase the old grid and old page boundary>> Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, tempBox]; << extend old left and right page boundaries and draw new top boundary>> Graphics.SetColor[context, Graphics.black]; DrawThreePageSidesFromTop[context, tempBox]; << now redraw the top margin and extend others.>> Graphics.MoveTo[path, screenRightMargin, tempBox.ymin]; Graphics.LineTo[path, screenRightMargin, tempBox.ymax+1]; Graphics.DrawStroke[context, path, marginThickness]; Graphics.MoveTo[path, screenLeftMargin, tempBox.ymin, TRUE]; Graphics.LineTo[path, screenLeftMargin, tempBox.ymax+1]; Graphics.DrawStroke[context, path, marginThickness]; Graphics.MoveTo[path, screenBindingMargin, tempBox.ymin, TRUE]; Graphics.LineTo[path, screenBindingMargin, tempBox.ymax+1]; Graphics.DrawStroke[context, path, marginThickness]; DrawHorizontalMargin[handle,context, screenTopMargin];-- erase old one screenTopMargin _ screenTopMargin + (tempBox.ymax - tempBox.ymin - 1); DrawHorizontalMargin[handle, context, screenTopMargin]; }; DrawThreePageSides: PROCEDURE [context: Graphics.Context, box: Graphics.Box] = { path: Graphics.Path _ Graphics.NewPath[]; Graphics.MoveTo[path, box.xmin, box.ymin]; Graphics.LineTo[path, box.xmax, box.ymin]; Graphics.LineTo[path, box.xmax, box.ymax]; Graphics.LineTo[path, box.xmin, box.ymax]; Graphics.DrawStroke[context, path, pageOutlineThickness]; }; DrawThreePageSidesFromTop: PROCEDURE [context: Graphics.Context, box: Graphics.Box] = { path: Graphics.Path _ Graphics.NewPath[]; Graphics.MoveTo[path, box.xmin, box.ymin]; Graphics.LineTo[path, box.xmin, box.ymax]; Graphics.LineTo[path, box.xmax, box.ymax]; Graphics.LineTo[path, box.xmax, box.ymin]; Graphics.DrawStroke[context, path, pageOutlineThickness]; }; END.