<> <> <> DIRECTORY Cursors, InputFocus, Graphics, LFUtil, TIPUser, ViewerClasses, ViewerOps, UserTerminal ; LFUtilImpl: CEDAR MONITOR IMPORTS Cursors, InputFocus, Graphics, TIPUser, ViewerOps EXPORTS LFUtil SHARES ViewerOps ~ BEGIN lastX, lastY: INTEGER _ LAST[INTEGER]; topY, leftX, sourceBottom, sourceHeight, sourceLeft, sourceWidth: INTEGER; mode: {waitingForUpperLeft, waitingForLowerRight, done, abort} _ done; context: Graphics.Context; ready: CONDITION; AbortAdjust: PUBLIC SIGNAL ~ CODE; GetArea: PUBLIC ENTRY PROC RETURNS [sMin, fMin: INTEGER, sSize, fSize: NAT] = { ENABLE UNWIND => NULL; grey: CARDINAL ~ 122645B; mode _ waitingForUpperLeft; InputFocus.CaptureButtons[BoxAdjustNotify, vaTIP]; Cursors.SetCursor[crossHairsCircle]; context _ ViewerOps.AcquireContext[NIL]; [] _ Graphics.SetPaintMode[context, invert]; Graphics.SetStipple[context, grey]; lastX _ lastY _ LAST[INTEGER]; UNTIL mode = done OR mode = abort DO WAIT ready ENDLOOP; IF mode = abort THEN SIGNAL AbortAdjust; sMin _ sourceBottom; sSize _ sourceHeight; fMin _ sourceLeft; fSize _ sourceWidth; }; Clip: PROC [position: TIPUser.TIPScreenCoords] RETURNS [x, y: INTEGER] = BEGIN x _ position.mouseX; y _ position.mouseY; END; BoxAdjustNotify: ENTRY ViewerClasses.NotifyProc ~ { ENABLE UNWIND => EndAdjust[]; mouseX, mouseY: INTEGER _ 0; FOR list: LIST OF REF ANY _ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => SELECT x FROM $Abort => BEGIN EndAdjust[]; mode _ done; NOTIFY ready; END; $Move => BEGIN IF mode = waitingForUpperLeft THEN { mode _ waitingForLowerRight; topY _ mouseY; leftX _ mouseX; }; Feedback[mouseX, mouseY]; END; $End => BEGIN Feedback[mouseX, mouseY]; IF mode = waitingForLowerRight THEN { mode _ done; EndAdjust[]; IF topY < mouseY THEN {t: NAT _ topY; topY _ mouseY; mouseY _ t}; IF leftX > mouseX THEN {t: NAT _ leftX; leftX _ mouseX; mouseX _ t}; sourceBottom _ mouseY; sourceHeight _ topY - mouseY + 1; sourceLeft _ leftX; sourceWidth _ mouseX - leftX + 1; NOTIFY ready; }; END; ENDCASE => NULL; z: TIPUser.TIPScreenCoords => [mouseX, mouseY] _ Clip[z]; ENDCASE => ERROR; ENDLOOP; }; EndAdjust: PROC = BEGIN Feedback[LAST[INTEGER], LAST[INTEGER], TRUE]; InputFocus.ReleaseButtons[]; ViewerOps.ReleaseContext[context]; END; Feedback: PROC [x, y: INTEGER, remove: BOOL _ FALSE] = BEGIN Show: PROC [x1, y1: INTEGER] = BEGIN x2: INTEGER _ leftX; y2: INTEGER _ topY; IF x1 > x2 THEN {t: INTEGER _ x2; x2 _ x1; x1 _ t}; IF y1 > y2 THEN {t: INTEGER _ y2; y2 _ y1; y1 _ t}; Graphics.DrawBox[context, [x1-5, y1-5, x1, y2+5]]; -- left side Graphics.DrawBox[context, [x2, y1-5, x2+5, y2+5]]; -- right side Graphics.DrawBox[context, [x1, y1-5, x2, y1]]; -- top side Graphics.DrawBox[context, [x1, y2, x2, y2+5]]; -- bottom side END; IF lastX=x AND lastY=y THEN RETURN; -- no change IF lastX#LAST[INTEGER] THEN Show[lastX, lastY]; -- to remove the old box IF remove THEN lastX _ lastY _ LAST[INTEGER] ELSE { Show[x, y]; -- to show the new box lastX _ x; lastY _ y; }; END; vaTIP: TIPUser.TIPTable _ TIPUser.InstantiateNewTIPTable["BoundingBox.tip"]; END.