-- BoundaryAdjustImpl.mesa; Edited by McGregor on September 1, 1982 4:07 pm

DIRECTORY
Cursors USING [SetCursor],
Graphics USING [Context, DrawBox, SetPaintMode],
InputFocus USING [CaptureButtons, ReleaseButtons],
TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords],
ViewerClasses,
ViewerOps USING [AcquireContext, CreateViewer, EnumerateViewers, EnumProc,
 MoveBoundary, MoveViewer, ReleaseContext, RegisterViewerClass, XYWH2Box],
ViewerSpecs,
WindowManager USING [RestoreCursor];

BoundaryAdjustImpl: PROGRAM

IMPORTS Cursors, Graphics, InputFocus, TIPUser, ViewerSpecs,
 ViewerOps, WindowManager
SHARES ViewerOps =

BEGIN OPEN ViewerClasses, ViewerSpecs;

width: INTEGER = 7; -- size of adjustment box on screen
height: INTEGER = 5;

inProgress: BOOLEANFALSE;
lastX, lastY: INTEGERLAST[INTEGER];
context: Graphics.Context;

BoundaryAdjustPaint: PaintProc = BEGIN OPEN self;
 hiddenIcon: BOOLEANFALSE;
 IconHidden: ViewerOps.EnumProc = BEGIN
  IF v.iconic AND v.wy+v.wh > ViewerSpecs.openBottomY THEN BEGIN
   hiddenIcon ← TRUE;
   RETURN[FALSE];
   END;
  END;
 ViewerOps.EnumerateViewers[IconHidden];
IF hiddenIcon THEN Graphics.DrawBox[context, ViewerOps.XYWH2Box[0, 0, cw, ch]]
ELSE BEGIN
  Graphics.DrawBox[context, ViewerOps.XYWH2Box[0, 0, cw, 1]];
  Graphics.DrawBox[context, ViewerOps.XYWH2Box[0, 0, 1, ch]];
  Graphics.DrawBox[context, ViewerOps.XYWH2Box[cw-1, 0, 1, ch]];
  Graphics.DrawBox[context, ViewerOps.XYWH2Box[0, ch-1, cw, 1]];
  END;
END;

BoundaryAdjustNotify: PRIVATE NotifyProc = BEGIN
ENABLE UNWIND => {InputFocus.ReleaseButtons[]; ViewerOps.ReleaseContext[context]};
 mouseX, mouseY: INTEGER;
Start: PROC = BEGIN
  inProgress ← TRUE;
  Cursors.SetCursor[scrollLeftRight];
  InputFocus.CaptureButtons[BoundaryAdjustNotify, boundaryAdjustClass.tipTable, self];
  context ← ViewerOps.AcquireContext[NIL];
  [] ← Graphics.SetPaintMode[context, invert];
  END;
FOR list: LIST OF REF ANY ← input, list.rest UNTIL list = NIL DO
WITH list.first SELECT FROM
  x: ATOM => SELECT x FROM
   $Move => BEGIN
    IF ~inProgress THEN Start[];
    Feedback[self, mouseX, mouseY];
    END;
   $Start => IF ~inProgress THEN Start[];
   $End => IF inProgress THEN BEGIN
    InputFocus.ReleaseButtons[];
    Feedback[self, LAST[INTEGER], LAST[INTEGER], TRUE];
    ViewerOps.ReleaseContext[context];
    ViewerOps.MoveViewer[self, mouseX-(width/2), mouseY-self.wh, self.ww, self.wh];
    ViewerOps.MoveBoundary[mouseX, mouseY];
    WindowManager.RestoreCursor[];
    inProgress ← FALSE;
    END;
   ENDCASE => ERROR;
  z: TIPUser.TIPScreenCoords => [mouseX, mouseY] ← Clip[z];
  ENDCASE => ERROR;
ENDLOOP;
END;

Feedback: PROC [self: Viewer, x,y: INTEGER, remove: BOOLEANFALSE] = BEGIN
Show: PROC [x, y: INTEGER] = INLINE BEGIN
  Graphics.DrawBox[context, [x, y, x+2, openLeftTopY]];
  Graphics.DrawBox[context, [0, y-2, screenW, y]];
  END;
IF lastX=x AND lastY=y THEN RETURN; -- no change
IF lastX#LAST[INTEGER] THEN Show[lastX, lastY];
IF remove THEN lastX ← lastY ← LAST[INTEGER]
ELSE {Show[x, y]; lastX ← x; lastY ← y};
END;

Clip: PROC [position: TIPUser.TIPScreenCoords] RETURNS [x, y: INTEGER] = BEGIN
OPEN ViewerSpecs;
 x ← SELECT position.mouseX FROM
  < width    => width,
  > screenW-width => screenW-width,
  ENDCASE    => position.mouseX;
 y ← SELECT position.mouseY FROM
  < height    => height,
  < iconHeight+iconSpacing+(iconHeight/2) => iconHeight+iconSpacing,
  ENDCASE    => 2*(iconHeight+iconSpacing);
END;

boundaryAdjustClass: ViewerClass ← NEW[ViewerClassRec ← [
 paint: BoundaryAdjustPaint,
 notify: BoundaryAdjustNotify,
 tipTable: TIPUser.InstantiateNewTIPTable["/Indigo/CedarViewers/Viewers/BoundaryAdjust.tip"],
 cursor: bullseye
 ]];

ba: ViewerClasses.Viewer;

ViewerOps.RegisterViewerClass[$BoundaryAdjust, boundaryAdjustClass]; -- plug in to Viewers

ba ← ViewerOps.CreateViewer[flavor: $BoundaryAdjust, info: [name: "BA",
 wx: ViewerSpecs.openLeftWidth-(width/2), wy: ViewerSpecs.openBottomY-height,
 ww: width, wh: height, column: static], paint: FALSE];
ba.border ← FALSE;
ViewerOps.MoveViewer[ba, ba.wx, ba.wy, ba.ww, ba.wh]; -- recalculate client size

END.