<> <> <> <> <> <> DIRECTORY Cursors USING [AddCursorCorner, SetCursor], Imager USING [Color, Context, MaskRectangleI, SetColor], ImagerBackdoor USING [MakeStipple], InputFocus USING [CaptureButtons, ReleaseButtons], Rope USING [ROPE], TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPTable], ViewerClasses USING [NotifyProc, Viewer], ViewerOps USING [ComputeColumn, MoveBoundary, PaintViewer], ViewerPrivate USING [LockViewerTree, PaintScreen, ReleaseViewerTree], ViewerSpecs USING [bwScreenWidth, captionHeight, iconHeight, iconRows, iconSpacing, openBottomY, openTopY], WindowManager USING [RestoreCursor]; ViewerAdjustImpl: CEDAR MONITOR IMPORTS Cursors, Imager, ImagerBackdoor, InputFocus, TIPUser, ViewerOps, ViewerPrivate, ViewerSpecs, WindowManager EXPORTS ViewerOps = BEGIN OPEN ViewerClasses; AdjustMode: TYPE = {top, bottom, column, none}; mode: AdjustMode _ none; stickyHeight, adjustBottom: BOOL; xPos, width, minY, maxY: INTEGER; lastX, lastY: INTEGER _ LAST[INTEGER]; Adjust: PUBLIC ENTRY PROC [viewer: Viewer, sticky: BOOL _ TRUE] = { ViewerPrivate.LockViewerTree[]; InputFocus.CaptureButtons[BoundaryAdjustNotify, vaTIP, viewer]; <<[minY, maxY] _ ComputeYBounds[viewer];>> minY _ ViewerSpecs.openBottomY; maxY _ ViewerSpecs.openTopY; xPos _ viewer.wx; width _ viewer.ww; stickyHeight _ sticky; adjustBottom _ FALSE; }; EndAdjust: PROC = { ChangeMode[none, 0, 0]; InputFocus.ReleaseButtons[]; ViewerPrivate.ReleaseViewerTree[]; }; BoundaryAdjustNotify: NotifyProc = { ENABLE UNWIND => EndAdjust[]; mouseX, mouseY: INTEGER; FOR list: LIST OF REF ANY _ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => SELECT x FROM $Abort => { <> <> <> <> <> <> EndAdjust[]; IF self.openHeight = 0 THEN ViewerOps.PaintViewer[self, caption] ELSE {self.openHeight _ 0; ViewerOps.ComputeColumn[self.column]}; }; $Move => { SELECT mode FROM top => IF mouseX NOT IN [self.wx..self.wx+self.ww) THEN ChangeMode[column, mouseX, mouseY] ELSE IF mouseY <= self.wy THEN ChangeMode[bottom, mouseX, mouseY] ELSE Feedback[mouseX, mouseY]; bottom => IF mouseX NOT IN [self.wx..self.wx+self.ww) THEN ChangeMode[column, mouseX, mouseY] ELSE IF mouseY >= self.wy+self.wh THEN ChangeMode[top, mouseX, mouseY] ELSE Feedback[mouseX, mouseY]; column => Feedback[mouseX, mouseY]; ENDCASE => { ViewerOps.PaintViewer[self, caption]; ChangeMode[top, mouseX, mouseY]; }; }; $End => { viewerMinHeight: NAT ~ ViewerSpecs.captionHeight; change: AdjustMode _ mode; EndAdjust[]; SELECT change FROM top => { <> <> self.openHeight _ MAX[viewerMinHeight, mouseY-self.wy]; ViewerOps.ComputeColumn[self.column]; }; bottom => { <> <> self.openHeight _ MAX[viewerMinHeight, self.wy+self.wh-mouseY]; ViewerOps.ComputeColumn[self.column]; }; column => ViewerOps.MoveBoundary[mouseX, mouseY]; ENDCASE; }; ENDCASE => NULL; z: TIPUser.TIPScreenCoords => [mouseX, mouseY] _ Clip[z]; ENDCASE => ERROR; ENDLOOP; }; ChangeMode: PROC [newMode: AdjustMode, mouseX, mouseY: INTEGER] = { Feedback[LAST[INTEGER], LAST[INTEGER], TRUE]; SELECT newMode FROM top => {Cursors.SetCursor[pointUp]; Cursors.AddCursorCorner[upperSide]}; bottom => {Cursors.SetCursor[pointDown]; Cursors.AddCursorCorner[lowerSide]}; column => {Cursors.SetCursor[activate]}; ENDCASE => {WindowManager.RestoreCursor[]}; mode _ newMode; IF mode#none THEN Feedback[mouseX, mouseY]; }; adjustStipple: Imager.Color ~ ImagerBackdoor.MakeStipple[stipple: 122645B, xor: TRUE]; Feedback: PROC [x, y: INTEGER, remove: BOOL _ FALSE] = { action: PROC [context: Imager.Context] ~ { Show: PROC [x, y: INTEGER] = { IF mode=column THEN { Imager.MaskRectangleI[context, x-1, y, 2, ViewerSpecs.openTopY-y]; Imager.MaskRectangleI[context, 0, y-1, ViewerSpecs.bwScreenWidth, 2]; } ELSE Imager.MaskRectangleI[context, xPos, y-1, width, 2]; }; IF lastX=x AND lastY=y THEN RETURN; -- no change Imager.SetColor[context, adjustStipple]; IF lastX#LAST[INTEGER] THEN Show[lastX, lastY]; IF remove THEN lastX _ lastY _ LAST[INTEGER] ELSE {Show[x, y]; lastX _ x; lastY _ y}; }; ViewerPrivate.PaintScreen[bw, action, FALSE]; }; standardLeftWidth: INTEGER ~ 600; -- should be in ViewerSpecs Clip: PROC [position: TIPUser.TIPScreenCoords] RETURNS [x, y: INTEGER] = { OPEN ViewerSpecs; fudge: INTEGER = 15; screenW: INTEGER ~ ViewerSpecs.bwScreenWidth; x _ position.mouseX; y _ position.mouseY; <> IF ABS[x-(screenW/2)] < fudge THEN x _ (screenW/2) ELSE IF ABS[x-standardLeftWidth] < fudge THEN x _ standardLeftWidth; IF mode=column THEN { IF y<=openBottomY THEN adjustBottom _ TRUE; -- must move below column to adjust bottom IF adjustBottom THEN { rowHeight: INTEGER = iconHeight+iconSpacing; <> IF y>rowHeight THEN { rows: INTEGER = MIN[(y+iconHeight/2), maxY]/rowHeight; y _ MIN[rows, iconRows]*rowHeight; }; } ELSE y _ openBottomY; -- pin y if not adjusting bottom } ELSE y _ MIN[maxY, MAX[minY, y]]; }; vaTIP: TIPUser.TIPTable _ TIPUser.InstantiateNewTIPTable["ViewerAdjust.tip"]; END. <<>> <> <> <> <> <> <> <> <> <> <> <> <> <