<> <> <> <> <> DIRECTORY Cursors USING [AddCursorCorner, SetCursor], Imager USING [Context, MaskBits, SetColor, XOR], InputFocus USING [CaptureButtons, ReleaseButtons], MessageWindow USING [Append, Clear], Process USING [Detach], Rope USING [ROPE], TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPTable], ViewerClasses USING [NotifyProc, Viewer], ViewerLocks USING [LockViewerTree, ReleaseViewerTree], ViewerOps USING [AcquireContext, ComputeColumn, MoveBoundary, PaintViewer, ReleaseContext], ViewerSpecs, WindowManager USING [RestoreCursor]; ViewerAdjustImpl: CEDAR MONITOR IMPORTS Cursors, Imager, InputFocus, MessageWindow, Process, TIPUser, ViewerLocks, ViewerOps, ViewerSpecs, WindowManager EXPORTS ViewerOps SHARES ViewerClasses, ViewerLocks, ViewerOps = BEGIN OPEN ViewerClasses; viewerMinHeight: INTEGER ~ ViewerSpecs.captionHeight; AdjustMode: TYPE = {top, bottom, column, none} ; mode: AdjustMode _ none; context: Imager.Context; adjustBottom: BOOL; xPos, width, minY, maxY: INTEGER; lastX, lastY: INTEGER _ LAST[INTEGER]; Adjust: PUBLIC ENTRY PROC [viewer: Viewer] = { ViewerLocks.LockViewerTree[]; InputFocus.CaptureButtons[BoundaryAdjustNotify, vaTIP, viewer]; context _ ViewerOps.AcquireContext[NIL]; Imager.SetColor[context, Imager.XOR]; <<[minY, maxY] _ ComputeYBounds[viewer];>> minY _ ViewerSpecs.openBottomY; maxY _ ViewerSpecs.openLeftTopY; xPos _ viewer.wx; width _ viewer.ww; adjustBottom _ FALSE; }; EndAdjust: PROC = { ChangeMode[none, 0, 0]; InputFocus.ReleaseButtons[]; ViewerOps.ReleaseContext[context]; ViewerLocks.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 => { 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]; SetMsg[]}; ENDCASE => {WindowManager.RestoreCursor[]; SetMsg[]}; mode _ newMode; IF mode#none THEN Feedback[mouseX, mouseY]; }; SetMsg: PROC [msg: Rope.ROPE _ NIL] = TRUSTED INLINE { <> IF msg=NIL THEN Process.Detach[FORK MessageWindow.Clear[]] ELSE Process.Detach[FORK MessageWindow.Append[msg, TRUE]]; }; grey: CARDINAL _ 122645B; Feedback: PROC [x, y: INTEGER, remove: BOOL _ FALSE] = { GreyRectangle: PROC [x, y, w, h: INTEGER] = TRUSTED INLINE { Imager.MaskBits[context, @grey, 1, [0,0,16,1], [x,y,w,h]]; }; Show: PROC [x, y: INTEGER] = { IF mode=column THEN { GreyRectangle[x-1, y, 2, ViewerSpecs.openLeftTopY-y+1]; GreyRectangle[0, y-1, ViewerSpecs.screenW, 2]; } ELSE GreyRectangle[xPos, y+1, width, 2]; }; 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}; }; Clip: PROC [position: TIPUser.TIPScreenCoords] RETURNS [x, y: INTEGER] = { OPEN ViewerSpecs; fudge: INTEGER = 15; x _ position.mouseX; y _ position.mouseY; <> IF ABS[x-(screenW/2)] < fudge THEN x _ (screenW/2) ELSE IF ABS[x-initialOpenLeftWidth] < fudge THEN x _ initialOpenLeftWidth; 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 _ rows*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. <> <<{ OPEN ViewerSpecs;>> <> <> <> <<};>> <> <> <> <> <> <> <