; $Id: box_cursor.pro,v 1.9 1999/01/16 01:22:09 scottm Exp $ ; ; Copyright (c) 1990-1999, Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. ; pro box_cursor, x0, y0, nx, ny, INIT = init, FIXED_SIZE = fixed_size, $ MESSAGE = message ;+ ; NAME: ; BOX_CURSOR ; ; PURPOSE: ; Emulate the operation of a variable-sized box cursor (also known as ; a "marquee" selector). ; ; CATEGORY: ; Interactive graphics. ; ; CALLING SEQUENCE: ; BOX_CURSOR, x0, y0, nx, ny [, INIT = init] [, FIXED_SIZE = fixed_size] ; ; INPUTS: ; No required input parameters. ; ; OPTIONAL INPUT PARAMETERS: ; x0, y0, nx, and ny give the initial location (x0, y0) and ; size (nx, ny) of the box if the keyword INIT is set. Otherwise, the ; box is initially drawn in the center of the screen. ; ; KEYWORD PARAMETERS: ; INIT: If this keyword is set, x0, y0, nx, and ny contain the initial ; parameters for the box. ; ; FIXED_SIZE: If this keyword is set, nx and ny contain the initial ; size of the box. This size may not be changed by the user. ; ; MESSAGE: If this keyword is set, print a short message describing ; operation of the cursor. ; ; OUTPUTS: ; x0: X value of lower left corner of box. ; y0: Y value of lower left corner of box. ; nx: width of box in pixels. ; ny: height of box in pixels. ; ; The box is also constrained to lie entirely within the window. ; ; COMMON BLOCKS: ; None. ; ; SIDE EFFECTS: ; A box is drawn in the currently active window. It is erased ; on exit. ; ; RESTRICTIONS: ; Works only with window system drivers. ; ; PROCEDURE: ; The graphics function is set to 6 for eXclusive OR. This ; allows the box to be drawn and erased without disturbing the ; contents of the window. ; ; Operation is as follows: ; Left mouse button: Move the box by dragging. ; Middle mouse button: Resize the box by dragging. The corner ; nearest the initial mouse position is moved. ; Right mouse button: Exit this procedure, returning the ; current box parameters. ; ; MODIFICATION HISTORY: ; DMS, April, 1990. ; DMS, April, 1992. Made dragging more intutitive. ; June, 1993 - Bill Thompson ; prevented the box from having a negative size. ; SJL, Nov, 1997. Formatted, conform to IDL style guide. ; Prevented crash from unitialized corner. ; RJF, Feb, 1998. Replaced !ERROR_STATE.CODE w/ !MOUSE.BUTTON and ; fixed some problems w/sizing when a corner might swap. ;- DEVICE, GET_GRAPHICS = old, SET_GRAPHICS = 6 ;Set xor col = !D.N_COLORS -1 corner = 0 if KEYWORD_SET(message) then begin print, "Drag Left button to move box." print, "Drag Middle button near a corner to resize box." print, "Right button when done." endif if KEYWORD_SET(init) eq 0 then begin ;Supply default values for box: if KEYWORD_SET(fixed_size) eq 0 then begin nx = !D.X_SIZE/8 ;no fixed size. ny = !D.X_SIZE/8 endif x0 = !D.X_SIZE/2 - nx/2 y0 = !D.Y_SIZE/2 - ny/2 endif button = 0 old_button = 1 goto, middle while(1) do begin old_button = button cursor, x, y, 2, /DEV ;Wait for a button button = !MOUSE.BUTTON if ((old_button eq 0) and (button ne 0)) then begin mx0 = x ;For dragging, mouse locn... my0 = y x00 = x0 ;Orig start of ll corner y00 = y0 endif if (!MOUSE.BUTTON eq 1) then begin ;Drag entire box? x0 = x00 + x - mx0 y0 = y00 + y - my0 endif ;;New size? if ((!MOUSE.BUTTON eq 2) and (KEYWORD_SET(fixed_size) eq 0)) $ then begin if (old_button eq 0) then begin ;Find closest corner mind = 1e6 for i=0,3 do begin d = float(px[i]-x)^2 + float(py[i]-y)^2 if (d lt mind) then begin mind = d corner = i endif endfor nx0 = nx ;Save sizes. ny0 = ny endif dx = x - mx0 & dy = y - my0 ;Distance dragged... case corner of 0: begin x0 = x00 + dx & y0 = y00 + dy nx = nx0 -dx & ny = ny0 - dy endcase 1: begin y0 = y00 + dy nx = nx0 + dx & ny = ny0 - dy endcase 2: begin nx = nx0 + dx & ny = ny0 + dy endcase 3: begin x0 = x00 + dx nx = nx0 - dx & ny = ny0 + dy endcase endcase endif if ((old_button ne 0) or (button ne 0)) then begin plots, px, py, COL=col, /DEV, THICK=1, LINES=0 ;Erase previous box empty ;Decwindow bug endif if (!MOUSE.BUTTON eq 4) then begin ;Quitting? DEVICE,SET_GRAPHICS = old return endif middle: if (nx lt 0) then begin x0 = x0 + nx nx = -nx case corner of 0: corner = 1 1: corner = 0 2: corner = 3 3: corner = 2 endcase ; reset the starting drag point... mx0 = x & my0 = y x00 = x0 & y00 = y0 nx0 = nx & ny0 = ny endif if (ny lt 0) then begin y0 = y0 + ny ny = -ny case corner of 0: corner = 3 3: corner = 0 1: corner = 2 2: corner = 1 endcase ; reset the starting drag point... mx0 = x & my0 = y x00 = x0 & y00 = y0 nx0 = nx & ny0 = ny endif x0 = x0 > 0 y0 = y0 > 0 x0 = x0 < (!D.X_SIZE-1 - nx) ;Never outside window y0 = y0 < (!D.Y_SIZE-1 - ny) px = [x0, x0 + nx, x0 + nx, x0, x0] ;X points py = [y0, y0, y0 + ny, y0 + ny, y0] ;Y values if ((old_button ne 0) or (button ne 0)) then begin plots,px, py, COL=col, /DEV, THICK=1, LINES=0 ;Draw the box empty ;Decwindow bug endif wait, .1 ;Dont hog it all endwhile end