Viewing contents of file '../idllib/contrib/fanning/ps_form.pro'
;+
; NAME:
; PS_FORM
;
; PURPOSE:
;
; This function displays a form the user can interactively manipulate
; to configure the PostScript device driver (PS) setup. The function returns
; a structure of keywords that can be sent directly to the DEVICE command
; via its _EXTRA keyword
;
; AUTHOR:
;
; FANNING SOFTWARE CONSULTING
; David Fanning, Ph.D.
; 2642 Bradbury Court
; Fort Collins, CO 80521 USA
; Phone: 970-221-0438
; E-mail: davidf@dfanning.com
; Coyote's Guide to IDL Programming: http://www.dfanning.com
;
; MAJOR TOPICS:
;
; Device Drivers, Hardcopy Output, PostScript Output
;
; PROCEDURE:
;
; This is a pop-up form widget. It is a modal or blocking widget.
; Keywords appropriate for the PostScript (PS) DEVICE command are returned.
; The yellow box in the upper right hand corner of the form represents the
; PostScript page. The green box represents the "window" on the PostScript
; page where the graphics will be drawn.
;
; Use your LEFT mouse button to move the plot "window" around the page.
; Use your RIGHT mouse button to draw your own plot window on the page.
;
; The CREATE FILE and ACCEPT buttons are meant to indicate slightly
; different operations, although this is sometimes confusing. My idea
; is that PS_FORM is a *configuration* dialog, something the user displays
; if he or she wants to change the way the PostScript device is configured.
; Thus, in many of my widget programs if the user clicks a "Write PostScript File"
; button, I just go ahead and write a PostScript file without displaying the
; form. (I can do this because I always keep a copy of the current device
; configuration in my info structure.) To get to the form, the user must
; select a "Configure PostScript Device" button.
;
; At that time, the user might select the ACCEPT button to just change
; the PostScript device configurations. Or the user can select the
; CREATE FILE button, which both accepts the configuration *and* creates
; a PostScript file. If you find the CREATE FILE button confusing, you
; can just edit it out of the form and use the ACCEPT button for the
; same purpose.
;
; HELP:
;
; formInfo = PS_FORM(/Help)
;
; USAGE:
;
; The calling procedure for this function in a widget program will look something
; like this:
;
; info.ps_config = PS_FORM(/Initialize)
; ...
; formInfo = PS_FORM(Cancel=canceled, Create=create, $
; Defaults=info.ps_config, Parent=event.top)
;
; IF NOT canceled THEN BEGIN
; IF create THEN BEGIN
; thisDevice = !D.Name
; Set_Plot, "PS"
; Device, _Extra=formInfo
;
; Enter Your Graphics Commands Here!
;
; Device, /Close
; Set_Plot, thisDevice
; ENDIF
; info.ps_config = formInfo
; ENDIF
;
; OPTIONAL INPUT PARAMETERS:
;
; XOFFSET -- Optional xoffset of the top-level base of PS_Form. Default is
; to try to center the form on the display.
;
; YOFFSET -- Optional yoffset of the top-level base of PS_Form. Default is
; to try to center the form on the display.
;
; INPUT KEYWORD PARAMETERS:
;
; BITS_PER_PIXEL -- The initial configuration of the bits per pixel button.
;
; BLOCKING -- Set this keyword to make this a blocking widget under IDL 5.0.
; (All widget programs block under IDL 4.0.)
;
; COLOR -- The initial configuration of the color switch.
;
; DEFAULTS -- A stucture variable of the same type and structure as the
; RETURN VALUE of PS_FORM. It will set initial conditions. This makes
; it possible to start PS_FORM up again with the same values it had the
; last time it was called. For example:
;
; mysetup = PS_FORM()
; newsetup = PS_FORM(Defaults=mysetup)
;
; NOTE: Using the DEFAULTS keyword will nullify any of the other
; DEVICE-type keywords listed above (e.g., XSIZE, ENCAPSULATED, etc.)
;
; ENCAPSULATED -- The initial configuration of the encapsulated switch.
;
; FILENAME -- The initial filename to be used on the form.
;
; HELP -- Prints a helpful message in the output log.
;
; INCHES -- The initial configuration of the inches/cm switch.
;
; INITIALIZE -- If this keyword is set, the program immediately returns the
; "localdefaults" structure. This gives you the means to configue the
; PostScript device without displaying the form to the user. I use this
; to write a PostScript file directly and also to initialize my info
; structure field that contains the current PostScript form setup. Passing
; the setup structure into PS_FORM via the DEFAULTS keyword gives my PS_FORM
; a program "memory".
;
; info.ps_setup = PS_FORM(/Initialize)
;
; LANDSCAPE -- The initial configuration of the landscape/portrait switch.
;
; LOCALDEFAULTS -- A structure like the DEFAULTS structure. Used if the
; "Local Defaults" button is pressed in the form. This gives you the
; opportunity to have a "local" as well as "system" default setup.
; If this keyword is not used, the procedure PS_Form_Set_Personal_Local_Defaults
; is called. Use this procedure (see below) to define your own local
; defaults.
;
; XOFFSET -- The initial XOffSet of the PostScript window.
;
; YOFFSET -- The initial YOffSet of the PostScript window.
;
; XSIZE -- The initial XSize of the PostScript window.
;
; YSIZE -- The initial YSize of the PostScript window.
;
; OUTPUT KEYWORD PARAMETERS
;
; CANCEL -- This is an OUTPUT keyword. It is used to check if the user
; selected the "Cancel" button on the form. Check this variable rather
; than the return value of the function, since the return value is designed
; to be sent directly to the DEVICE procedure. The varible is set to 1 if
; the user selected the "Cancel" button. Otherwise, it is set to 0.
;
; CREATE -- This output keyword can be used to determine if the user
; selected the 'Create File' button rather than the 'Accept' button.
; The value is 1 if selected, and 0 otherwise.
;
; RETURN VALUE:
;
; formInfo = { PS_FORM_INFO, $
; xsize:0.0, $ ; The x size of the plot
; xoff:0.0, $ ; The x offset of the plot
; ysize:0.0, $ ; The y size of the plot
; yoff:0.0 $ ; The y offset of the plot
; filename:'', $ ; The name of the output file
; inches:0 $ ; Inches or centimeters?
; color:0, $ ; Color on or off?
; bits_per_pixel:0, $ ; How many bits per image pixel?
; encapsulated:0,$ ; Encapsulated or regular PostScript?
; landscape:0 } ; Landscape or portrait mode?
;
; MAJOR FUNCTIONS and PROCEDURES:
;
; None. Designed to work originally in conjunction with XWindow,
; a resizable graphics window.
;
; MODIFICATION HISTORY:
;
; Written by: David Fanning, RSI, March 1995.
; Given to attendees of IDL training courses.
;
; Modified to work when grapics device set to PostScript: 6 May 95.
; Modified to configure initial conditions via keywords: 13 October 95.
; Modified to load personal local defaults if LocalDefaults keyword not
; used: 3 Nov 95.
; Found and fixed bits_per_pixel error in Local Defaults setting
; procedure: 3 Nov 95.
; Modified to produce initial plot box with the same aspect ratio as
; the current graphics window. (XSIZE or YSIZE keywords overrule this
; behavior.) 22 Apr 96.
; Fixed annoying behavior of going to default-sized plot box when selecting
; the Landscape or Portrait option. Now keeps current plot box size.
; 22 Apr 96.
; Made the size and offset text widgets a little bigger and changed the
; size and offset formatting from F4.2 to F5.2 to accomodate larger plot
; box sizes. 29 Apr 96.
; Fixed a bug in the filename text widget that caused a crash when a CR
; was hit. 3 Sept 96.
; Added the Initialize keyword to immediately return the "localdefaults"
; structure. 27 Oct 96.
; Fixed another problem with the BITS_PER_PIXEL keyword. 27 Oct 96.
; Made the return value a named structure of the name PS_FORM_INFO.
; 3 Nov 96.
; Discovered and fixed a problem whereby YOFFSET was set incorrectly if
; LOCALDEFAULTS was used instead of DEFAULTS keyword. 3 Nov 96.
; Fixed bug in how Portrait mode was set using YSIZE and XSIZE keywords.
; 25 Nov 96.
; Fixed a bug in how YOFFSET was calculated when in Landscape mode. 27 Nov 96.
; Fixed a memory leak with the local defaults pointer. 25 Jan 97.
; Added the CREATE keyword and modified the appearance of the form. 22 Apr 97.
; Modifed subroutine names to avoid confusion. 22 Apr 97.
; Fixed a bug I introduced when I added the CREATE keyword. 23 Apr 97.
; Modified the program for IDL 5. 30 May 97, DWF.
; Fixed Inches to CM exclusive button problem. 30 May 97, DWF.
; Fixed a problem when the widget is killed with the mouse. 30 May 97. DWF
; Added a Select Filename button. 12 Oct 97.
; Modified program layout slightly. 12 Oct 97.
; Added valid directory/file error checking for the filename. 12 Oct 97. DWF
; Added further support for IDL 5 modal functionality. 20 Oct 97. DWF
;
;-
Pro PS_Form_Set_Personal_Local_Defaults, ptr
; If you don't use the LocalDefaults keyword, you can use
; this procedure to define local defaults for yourself.
; This procedure will be called if the keyword is not used.
; If you don't want to set local defaults, don't put anything
; in this procedure.
CD, Current=thisDirectory
filename = Filepath(Root_Dir=thisDirectory, 'idl.ps')
personalDefaults = { PS_FORM_INFO, $
xsize:7.0, $ ; The x size of the plot
xoff:1.0, $ ; The x offset of the plot
ysize:5.0, $ ; The y size of the plot
yoff:3.0, $ ; The y offset of the plot
filename:filename, $ ; The name of the output file
inches:1, $ ; Inches on.
color:0, $ ; Color off.
bits_per_pixel:8, $ ; 8 bits per image pixel.
encapsulated:0,$ ; Encapsulated file off.
landscape:0 } ; Portrait mode on.
Handle_Value, ptr, personalDefaults, /Set, /No_Copy
END ;*******************************************************************
Pro PS_FORM_Select_File, event
; Allows the user to select a filename for writing.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Start with the name in the filename widget.
Widget_Control, info.filename, Get_Value=initialFilename
initialFilename = initialFilename(0)
filename = Pickfile(/Write, File=initialFilename)
IF filename NE '' THEN $
Widget_Control, info.filename, Set_Value=filename
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Function PS_Form_PlotBox_Coords, xsize, ysize, xoff, yoff, inches
; This function converts sizes and offsets to appropriate
; Device coordinates for drawing the PLOT BOX on the PostScript
; page. The return value is a [2,5] array.
returnValue = IntArr(2,5)
IF inches EQ 0 THEN BEGIN
xs = xsize * 10.0 / 2.54
ys = ysize * 10.0 / 2.54
xof = xoff * 10.0 / 2.54
yof = yoff * 10.0 / 2.54
ENDIF ELSE BEGIN
xs = xsize * 10.0
ys = ysize * 10.0
xof = xoff * 10.0
yof = yoff * 10.0
ENDELSE
xcoords = Round([xof, xof+xs, xof+xs, xof, xof])
ycoords = Round([yof, yof, yof+ys, yof+ys, yof])
returnValue(0,*) = xcoords
returnValue(1,*) = ycoords
RETURN, returnValue
END ;*******************************************************************
Pro PS_Form_Set_Local_Defaults, event
; Define local variables
xsize = 0
ysize = 0
xoff = 0
yoff = 0
landscape = 0
encapsulated = 0
color = 0
filename = ''
bits_per_pixel = 0
inches = 0
; Get the info structure out of the TLB.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Are there local defaults loaded in the program?
check = Handle_Info(info.localDefaultPtr)
IF check EQ 0 THEN BEGIN
ok = Widget_Message('No local defaults loaded in program.')
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
; Get the local defaults structure and process it.
; Special processing for YOffset.
Handle_Value, info.localDefaultPtr, defaults
yoff_flag = 0
names = Tag_Names(defaults)
yoff_test = Where(names EQ 'YOFF')
IF yoff_test(0) GT 0 THEN yoff_flag = 1 ELSE yoff_flag = 0
FOR j=0,N_Elements(names)-1 DO BEGIN
IF names(j) NE 'YOFF' THEN BEGIN
str = names(j) + '= defaults.' + names(j)
dummy = Execute(str)
ENDIF
ENDFOR
; Process YOffset if yoff_flag is set. (ASSUMING xoff is DEFINED
; and passed in with the DEFAULTS!!)
IF yoff_flag THEN BEGIN
yof = Where(names EQ 'YOFF')
IF landscape EQ 1 AND inches EQ 0 THEN BEGIN
yoff = xoff
str = 'xoff = 27.94 - defaults.' + names(yof)
ENDIF
IF landscape EQ 1 AND inches EQ 1 THEN BEGIN
yoff = xoff
str = 'xoff = 11.0 - defaults.' + names(yof)
ENDIF
IF landscape EQ 0 AND inches EQ 0 THEN $
str = 'yoff = defaults.' + names(yof)
IF landscape EQ 0 AND inches EQ 1 THEN $
str = 'yoff = defaults.' + names(yof)
dummy = Execute(str(0))
ENDIF
IF landscape EQ 1 THEN BEGIN
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Landscape page outline
; and the default Landscape box outline
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
coords = PS_Form_PlotBox_Coords(xsize, ysize, xoff, yoff, inches)
PlotS, coords(0,*), coords(1,*), Color=info.boxcolor, /Device
; Draw the Landscape page outline in the pixmap
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
; Make the draw widget the current graphics window
WSet, info.wid
; Change the labels to their default values
xsizeStr = String(xsize, Format='(F5.2)')
ysizeStr = String(ysize, Format='(F5.2)')
xoffStr = String(xoff, Format='(F5.2)')
yoffStr = String(yoff, Format='(F5.2)')
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsizeStr
Widget_Control, info.ysize, Set_Value=ysizeStr
Widget_Control, info.xoff, Set_Value=xoffStr
Widget_Control, info.yoff, Set_Value=yoffStr
; Set up the landscape x and y default maximums and minimums
info.lbox_xmax = Max(coords(0,*))
info.lbox_ymax = Max(coords(1,*))
info.lbox_xmin = Min(coords(0,*))
info.lbox_ymin = Min(coords(1,*))
ENDIF ELSE BEGIN
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Portrait page outline
; and the default Portrait box outline
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, Color=info.pagecolor
coords = PS_Form_PlotBox_Coords(xsize, ysize, xoff, yoff, inches)
PlotS, coords(0,*), coords(1,*), Color=info.boxcolor, /Device
; Draw the Portrait page outline on the pixmap and then reset the
; current graphics window
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, $
Color=info.pagecolor
WSet, info.wid
; Change the labels to their default values
xsizeStr = String(xsize, Format='(F5.2)')
ysizeStr = String(ysize, Format='(F5.2)')
xoffStr = String(xoff, Format='(F5.2)')
yoffStr = String(yoff, Format='(F5.2)')
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsizeStr
Widget_Control, info.ysize, Set_Value=ysizeStr
Widget_Control, info.xoff, Set_Value=xoffStr
Widget_Control, info.yoff, Set_Value=yoffStr
; Set up the portrait x and y maximums and minimums
info.pbox_xmax = Max(coords(0,*))
info.pbox_ymax = Max(coords(1,*))
info.pbox_xmin = Min(coords(0,*))
info.pbox_ymin = Min(coords(1,*))
ENDELSE
; Set encapsulation buttons.
IF encapsulated EQ 0 THEN BEGIN
Widget_Control, info.encap_on, Set_Button=0
Widget_Control, info.encap_off, Set_Button=1
info.encapsulated = encapsulated
ENDIF ELSE BEGIN
Widget_Control, info.encap_on, Set_Button=1
Widget_Control, info.encap_off, Set_Button=0
info.encapsulated = encapsulated
ENDELSE
; Set color buttons.
IF color EQ 0 THEN BEGIN
Widget_Control, info.col_on, Set_Button=0
Widget_Control, info.col_off, Set_Button=1
info.color = color
ENDIF ELSE BEGIN
Widget_Control, info.col_on, Set_Button=1
Widget_Control, info.col_off, Set_Button=0
info.color = color
ENDELSE
; Set inch/cm buttons.
IF inches EQ 0 THEN BEGIN
Widget_Control, info.inch, Set_Button=0
Widget_Control, info.cm, Set_Button=1
info.inches = inches
ENDIF ELSE BEGIN
Widget_Control, info.inch, Set_Button=1
Widget_Control, info.cm, Set_Button=0
info.inches = inches
ENDELSE
; Set bits_per_pixel buttons.
CASE bits_per_pixel OF
2: BEGIN
Widget_Control, info.bit2, Set_Button=1
Widget_Control, info.bit8, Set_Button=0
Widget_Control, info.bit4, Set_Button=0
info.bits_per_pixel = 2
END
4: BEGIN
Widget_Control, info.bit2, Set_Button=0
Widget_Control, info.bit4, Set_Button=1
Widget_Control, info.bit8, Set_Button=0
info.bits_per_pixel = 4
END
8: BEGIN
Widget_Control, info.bit2, Set_Button=0
Widget_Control, info.bit8, Set_Button=1
Widget_Control, info.bit4, Set_Button=0
info.bits_per_pixel = 8
END
ENDCASE
; Set default filename.
Widget_Control, info.filename, Set_Value=filename
; Set protrait/landscape button.
IF landscape EQ 0 THEN BEGIN
Widget_Control, info.land, Set_Button=0
Widget_Control, info.port, Set_Button=1
info.landscape = landscape
ENDIF ELSE BEGIN
Widget_Control, info.land, Set_Button=1
Widget_Control, info.port, Set_Button=0
info.landscape = landscape
ENDELSE
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro PS_Form_Set_System_Defaults, event
; This event handler sets up the system default values. There will
; be different defaults based on whether the form is in landscape
; or portrait mode when the button is selected.
; Get the info stucture.
Widget_Control, event.top, Get_UValue=info, /No_Copy
IF info.landscape EQ 1 THEN BEGIN
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Landscape page outline
; and the default Landscape box outline
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
PlotS, info.lplotbox_x, info.lplotbox_y, Color=info.boxcolor, /Device
; Draw the Landscape page outline in the pixmap
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
; Make the draw widget the current graphics window
WSet, info.wid
; Change the labels to their default values
xsize = '24.13'
ysize = '17.78'
xoff = '1.91'
yoff = '1.91'
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Set up the landscape x and y default maximums and minimums
info.lbox_xmax = 106
info.lbox_ymax = 82
info.lbox_xmin = 8
info.lbox_ymin = 8
ENDIF ELSE BEGIN
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Portrait page outline
; and the default Portrait box outline
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, $
Color=info.pagecolor
PlotS, info.pplotbox_x, info.pplotbox_y, Color=info.boxcolor, /Device
; Draw the Portrait page outline on the pixmap and then reset the
; current graphics window
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, $
Color=info.pagecolor
WSet, info.wid
; Change the labels to their default values
xsize = '17.78'
ysize = '12.70'
xoff = '1.91'
yoff = '12.70'
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Set up the portrait x and y maximums and minimums
info.pbox_xmax = 82
info.pbox_ymax = 106
info.pbox_xmin = 8
info.pbox_ymin = 60
ENDELSE
; Set encapsulation buttons.
Widget_Control, info.encap_on, Set_Button=0
Widget_Control, info.encap_off, Set_Button=1
info.encapsulated = 0
; Set color buttons.
Widget_Control, info.col_on, Set_Button=0
Widget_Control, info.col_off, Set_Button=1
info.color = 0
; Set inch/cm buttons.
Widget_Control, info.inch, Set_Button=0
Widget_Control, info.cm, Set_Button=1
info.inches = 0
; Set bits_per_pixel buttons.
Widget_Control, info.bit2, Set_Button=0
Widget_Control, info.bit8, Set_Button=0
Widget_Control, info.bit4, Set_Button=1
info.bits_per_pixel = 4
; Set default filename.
filename = 'idl.ps'
Widget_Control, info.filename, Set_Value=filename
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro PS_Form_Null_Events, event
END ;*******************************************************************
Function PS_Form_What_Button_Type, event
; Checks event.type to find out what kind of button
; was clicked in a draw widget. This is NOT an event handler.
type = ['DOWN', 'UP', 'MOTION', 'SCROLL']
Return, type(event.type)
END ;*******************************************************************
Function PS_Form_What_Button_Pressed, event
; Checks event.press to find out what kind of button
; was pressed in a draw widget. This is NOT an event handler.
button = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT']
Return, button(event.press)
END ;*******************************************************************
Function PS_Form_What_Button_Released, event
; Checks event.release to find out what kind of button
; was released in a draw widget. This is NOT an event handler.
button = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT']
Return, button(event.release)
END ;*******************************************************************
Pro PS_Form_NumEvents, event
; If an event comes here, read the offsets and sizes from the
; form and draw the appropriately sized box in the draw widget.
Widget_Control, event.top, Get_UValue= info, /No_Copy
; Get current values for offset and sizes
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
Widget_Control, info.xoff, Get_Value=xoff
Widget_Control, info.yoff, Get_Value=yoff
xsize = xsize(0)
ysize = ysize(0)
xoff = xoff(0)
yoff = yoff(0)
; Don't let the user pick sizes that don't make sense
; Sizes must fit on page along with minimum offsets
IF info.inches EQ 1 THEN Begin ; Calculation in inches
IF info.landscape EQ 0 THEN Begin ; Portrait Mode
xsize = 0.25 > xsize < 8.25
ysize = 0.25 > ysize < 10.75
IF xsize + xoff GT 8.25 THEN xoff = 8.5 - xsize
IF ysize + yoff GT 10.75 THEN yoff = 11.0 - ysize
ENDIF ELSE Begin ; Landscape Mode
ysize = 0.25 > ysize < 8.25
xsize = 0.25 > xsize < 10.75
IF xsize + xoff GT 10.75 THEN xoff = 11.0 - xsize
IF ysize + yoff GT 8.25 THEN yoff = 8.5 - ysize
ENDELSE
ENDIF ELSE Begin ; Calculation in centimeters
IF info.landscape EQ 0 THEN Begin ; Portrait Mode
xsize = 1 > xsize < 20.95
ysize = 1 > ysize < 27.30
IF xsize + xoff GT 20.95 THEN xoff = 20.95 - xsize
IF ysize + yoff GT 27.30 THEN yoff = 27.30 - ysize
ENDIF ELSE Begin ; Landscape Mode
ysize = 1 > ysize < 20.95
xsize = 1 > xsize < 27.30
IF xsize + xoff GT 27.30 THEN xoff = 27.30 - xsize
IF ysize + yoff GT 20.95 THEN yoff = 20.95 - ysize
ENDELSE
ENDELSE
; Put correct sizes back into the text fields
Widget_Control, info.xsize, $
Set_Value=StrTrim(String(xsize, Format='(F5.2)'), 2)
Widget_Control, info.ysize, $
Set_Value=StrTrim(String(ysize, Format='(F5.2)'), 2)
Widget_Control, info.xoff, Set_Value=StrTrim(String(xoff, Format='(F5.2)'), 2)
Widget_Control, info.yoff, Set_Value=StrTrim(String(yoff, Format='(F5.2)'), 2)
; Convert sizes to Device coordinates
IF info.inches EQ 1 THEN Begin ; 1 inch equals 10 pixels
xsize = xsize * 10.0
xoff = xoff * 10.0
ysize = ysize * 10.0
yoff = yoff * 10.0
ENDIF ELSE Begin ; 2.54 cm equals 1 inch equals 10 pixels
xsize = xsize * 10.0 / 2.54
xoff = xoff * 10.0 / 2.54
ysize = ysize * 10.0 / 2.54
yoff = yoff * 10.0 / 2.54
ENDELSE
; Make the draw widget the current graphics window
WSet, info.wid
; Copy the page outline from the pixmap
Device, Copy=[0, 0, 114, 114, 0, 0, info.pixwid]
; Draw the appropriately sized box
PlotS, [xoff, xoff+xsize, xoff+xsize, xoff, xoff], Color=info.boxcolor, $
[yoff, yoff, yoff+ysize, yoff+ysize, yoff], /Device
; Update the box parameters
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.pbox_xmax = (xoff + xsize)
info.pbox_xmin = xoff
info.pbox_ymax = (yoff + ysize)
info.pbox_ymin = yoff
ENDIF ELSE Begin ; Landscape mode
info.lbox_xmax = (xoff + xsize)
info.lbox_xmin = xoff
info.lbox_ymax = (yoff + ysize)
info.lbox_ymin = yoff
ENDELSE
; Put the info structure back into the top-level base
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro PS_Form_MoveBox, event
; This is the event handler that allows the user to "move"
; the plot box around in the page window. It will set the
; event handler back to "PS_Form_Draw_Events" when it senses an
; "UP" draw button event and it will also turn PS_Form_Draw_Motion_Events
; OFF.
; Get the info structure out of the top-level base.
Widget_Control, event.top, Get_UValue=info, /No_Copy
whatButtonType = PS_Form_What_Button_Type(event)
IF whatButtonType EQ 'UP' THEN Begin
Widget_Control, info.draw, Draw_Motion_Events=0, $ ; Motion events off
Event_Pro='PS_Form_Draw_Events' ; Change to normal processing
; Copy page outline from the pixmap
Device, Copy=[0, 0, 114, 114, 0, 0, info.pixwid]
; Draw the final box shape
Plots, [info.xmin, info.xmin, info.xmax, info.xmax, info.xmin], $
Color=info.boxcolor, [info.ymin, info.ymax, info.ymax, info.ymin, $
info.ymin], /Device
; Update new offsets
IF info.inches EQ 0 THEN Begin ; Offset in Centimeters
xoff = (info.xmin/10.0) * 2.54
yoff = (info.ymin/10.0) * 2.54
ENDIF ELSE Begin ; Offset in Inches
xoff = (info.xmin/10.0)
yoff = (info.ymin/10.0)
ENDELSE
; Update new offsets in the offset boxes on the form.
Widget_Control, info.xoff, $
Set_Value=StrTrim(String(xoff, Format='(F5.2)'), 2)
Widget_Control, info.yoff, $
Set_Value=StrTrim(String(yoff, Format='(F5.2)'), 2)
; Update the new box parameters in the info structure
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.pbox_xmax = info.xmax
info.pbox_xmin = info.xmin
info.pbox_ymax = info.ymax
info.pbox_ymin = info.ymin
ENDIF ELSE Begin ; Landscape mode
info.lbox_xmax = info.xmax
info.lbox_xmin = info.xmin
info.lbox_ymax = info.ymax
info.lbox_ymin = info.ymin
ENDELSE
; Put the info structure back in the top-level base and RETURN
Widget_Control, event.top, Set_UValue=info, /No_Copy
Return
ENDIF
; You come to this section of the code for all events except
; an UP button event. Most of the action in this event handler
; occurs here.
; Make the draw widget the current graphics window
WSet, info.wid
; Copy the page outline from the pixmap into the window, thus
; erasing the last box you drew.
Device, Copy=[0, 0, 114, 114, 0, 0, info.pixwid]
; Calculate the length of of the current box
xlength = info.xmax - info.xmin
ylength = info.ymax - info.ymin
; Calculate location of lower-left corner of box.
; Constrain the box to lie inside the page outline.
IF info.landscape EQ 0 THEN Begin ; Portrait Mode
test = info.xmin + event.x - info.mouse_x
info.xmin = 2.5 > test
info.xmin = info.xmin < (86 - xlength)
test = info.ymin + event.y - info.mouse_y
info.ymin = 2.5 > test
info.ymin = info.ymin < (111 - ylength)
ENDIF ELSE Begin ; Landscape Mode
test = info.xmin + event.x - info.mouse_x
info.xmin = 2.5 > test
info.xmin = info.xmin < (111 - xlength)
test = info.ymin + event.y - info.mouse_y
info.ymin = 2.5 > test
info.ymin = info.ymin < (86 - ylength)
ENDELSE
; Calculate upper-right corners of the box
info.xmax = info.xmin + xlength
info.ymax = info.ymin + ylength
; Draw the new box on the display
Plots, [info.xmin, info.xmin, info.xmax, info.xmax, info.xmin], $
Color=info.boxcolor, [info.ymin, info.ymax, info.ymax, info.ymin, $
info.ymin], /Device
; Update the mouse pointer
info.mouse_x = event.x
info.mouse_y = event.y
; Put the info structure back into the top-level base.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro Ps_Form_DrawBox, event
; This event handler is summoned when a RIGHT button is clicked
; in the draw widget. It allows the user to draw the outline of a
; box with the mouse. It will continue drawing the new box shape
; until an UP event is detected. Then it will set the event handler
; back to PS_Form_Draw_Events and turn PS_Form_Draw_Motion_Events to OFF.
; Get the info structure out of the top-level base.
Widget_Control, event.top, Get_UValue=info, /No_Copy
whatButtonType = PS_Form_What_Button_Type(event)
IF whatButtonType EQ 'UP' THEN Begin
Widget_Control, info.draw, Draw_Motion_Events=0, $ ; Motion events off
Event_Pro='PS_Form_Draw_Events' ; Change to normal processing
; Make the draw widget the current graphics window
WSet, info.wid
; Copy the page outline from the pixmap
Device, Copy=[0, 0, 114, 114, 0, 0, info.pixwid]
; Draw the final box shape
PlotS, [info.xs, info.xs, info.xcur, info.xcur, info.xs], $
Color=info.boxcolor, [info.ys, info.ycur, info.ycur, info.ys, info.ys],$
/Device
; Update new box sizes and offsets
xmax = (info.xs > info.xcur)
xmin = (info.xs < info.xcur)
ymax = (info.ys > info.ycur)
ymin = (info.ys < info.ycur)
IF info.inches EQ 0 THEN Begin ; Values in Centimeters (10 pixels/inch)
xoff = (xmin/10.0 * 2.54)
yoff = ymin/10.0 * 2.54
xsize = (xmax - xmin)/10.0 * 2.54
ysize = (ymax - ymin)/10.0 * 2.54
ENDIF ELSE Begin ; Values in Inches (10 pixels/inch)
xoff = (xmin/10.0)
yoff = (ymin/10.0)
xsize = (xmax - xmin)/10.0
ysize = (ymax - ymin)/10.0
ENDELSE
; Update the new sizes in the size and offset boxes
Widget_Control, info.xsize, $
Set_Value=StrTrim(String(xsize, Format='(F5.2)'), 2)
Widget_Control, info.ysize, $
Set_Value=StrTrim(String(ysize, Format='(F5.2)'), 2)
Widget_Control, info.xoff, $
Set_Value=StrTrim(String(xoff, Format='(F5.2)'), 2)
Widget_Control, info.yoff, $
Set_Value=StrTrim(String(yoff, Format='(F5.2)'), 2)
; Update the box location
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.pbox_xmax = info.xcur > info.xs
info.pbox_xmin = info.xcur < info.xs
info.pbox_ymax = info.ycur > info.ys
info.pbox_ymin = info.ycur < info.ys
ENDIF ELSE Begin ; Landscape mode
info.lbox_xmax = info.xcur > info.xs
info.lbox_xmin = info.xcur < info.xs
info.lbox_ymax = info.ycur > info.ys
info.lbox_ymin = info.ycur < info.ys
ENDELSE
; Put the info structure back into the top-level base and RETURN
Widget_Control, event.top, Set_UValue=info, /No_Copy
Return
ENDIF
; This is the potion of the code that handles all events except for
; UP button events. The bulk of the work is done here. Basically,
; you need to erase the old box and draw a new box at the new
; location. Just keep doing this until you get an UP event.
; Make the draw widget be the current graphics window
WSet, info.wid
; Copy the page outline from the pixmap
Device, Copy=[0, 0, 114, 114, 0, 0, info.pixwid]
; Locate the current position of the cursor. Make sure it is
; located inside the page outline.
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.xcur = 2.5 > event.x < 84.5
info.ycur = 2.5 > event.y < 109.5
ENDIF ELSE Begin ; Landscape mode
info.xcur = 2.5 > event.x < 109.5
info.ycur = 2.5 > event.y < 84.5
ENDELSE
; Draw the new box on the display
Plots, [info.xs, info.xs, info.xcur, info.xcur, info.xs], $
Color=info.boxcolor, [info.ys, info.ycur, info.ycur, info.ys, info.ys], $
/Device
; Put the info structure back in the top-level base.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro PS_Form_Draw_Events, event
whatButtonType = PS_Form_What_Button_Type(event)
IF whatButtonType NE 'DOWN' THEN Return
; Get info structure out of TLB
Widget_Control, event.top, Get_UValue=info, /No_Copy
whatButtonPressed = PS_Form_What_Button_Pressed(event)
CASE whatButtonPressed OF
'RIGHT': Begin
; Resize the plot box interactively. Change the event handler
; to PS_Form_DrawBox. All subsequent events will be handled by
; PS_Form_DrawBox until an UP event is detected. Then you will
; return to this event handler. Also, turn motion events ON.
Widget_Control, event.id, Event_Pro='PS_Form_DrawBox', $
Draw_Motion_Events=1
; Portrait mode or landscape mode? Set constraints accordingly
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.xs = 2.5 > event.x < 85.0
info.ys = 2.5 > event.y < 110.0
info.xcur = 2.5 > event.x < 85.0
info.ycur = 2.5 > event.y < 110.0
ENDIF ELSE Begin ; Landscape mode
info.xs = 2.5 > event.x < 110.0
info.ys = 2.5 > event.y < 85.0
info.xcur = 2.5 > event.x < 110.0
info.ycur = 2.5 > event.y < 85.0
ENDELSE
Plots, [info.xs, info.xs, info.xcur, info.xcur, info.xs], $
Color=info.boxcolor, $
[info.ys, info.ycur, info.ycur, info.ys, info.ys], /Device
End
'LEFT': Begin
; Resize the plot box interactively. Change the event handler
; to PS_Form_MoveBox. All subsequent events will be handled by
; PS_Form_MoveBox until an UP event is detected. Then you will
; return to this event handler. Also, turn motion events ON.
; Copy max and min values into the info structure from the
; current box size
IF info.landscape EQ 0 THEN Begin ; Portrait mode
info.xmax = info.pbox_xmax
info.xmin = info.pbox_xmin
info.ymax = info.pbox_ymax
info.ymin = info.pbox_ymin
ENDIF ELSE Begin ; Landscape mode
info.xmax = info.lbox_xmax
info.xmin = info.lbox_xmin
info.ymax = info.lbox_ymax
info.ymin = info.lbox_ymin
ENDELSE
; Only move the box if the cursor is inside the box.
;If it is NOT, then RETURN.
IF event.x LT info.xmin OR event.x GT info.xmax OR event.y $
LT info.ymin OR event.y GT info.ymax THEN Begin
Widget_Control, event.top, Set_UValue=info, /No_Copy
Return
ENDIF
; Relocate the event handler and turn motion events ON.
Widget_Control, event.id, Event_Pro='PS_Form_MoveBox', $
Draw_Motion_Events=1
; Locate the cursor point inside the box that will be moved
info.mouse_x = event.x
info.mouse_y = event.y
End
ELSE: ; Middle button ignored in this program
ENDCASE
; Put the info structure back into the top-level base
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Pro PS_Form_Event, event
; This is the main event handler for PS_FORM. It handles
; the exclusive buttons on the form. Other events on the form
; will have their own event handlers.
; Get the name of the event structure
name = Tag_Names(event, /Structure_Name)
; If name is NOT "WIDGET_BUTTON" or this is not a button
; selection event, RETURN.
IF name NE 'WIDGET_BUTTON' OR event.select NE 1 THEN Return
; Get the info structure out of the top-level base
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Get the User Value of the Button
Widget_Control, event.id, Get_UValue=thisButton
; Respond appropriately to whatever button was selected
CASE thisButton OF
'INCHES': Begin
; Get current centimeter values
IF info.inches NE 1 THEN BEGIN
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
Widget_Control, info.xoff, Get_Value=xoff
Widget_Control, info.yoff, Get_Value=yoff
; Set values to inches and make a string
xsize = StrTrim(String(Float(xsize) / 2.54, Format='(F5.2)'), 2)
ysize = StrTrim(String(Float(ysize) / 2.54, Format='(F5.2)'), 2)
xoff = StrTrim(String(Float(xoff) / 2.54, Format='(F5.2)'), 2)
yoff = StrTrim(String(Float(yoff) / 2.54, Format='(F5.2)'), 2)
; Put inch values on the labels
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Update the info structure to indicate that current status is inches
info.inches = 1
EndIF
End
'CENTIMETERS': Begin
; Get current inch values
IF info.inches NE 0 THEN Begin
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
Widget_Control, info.xoff, Get_Value=xoff
Widget_Control, info.yoff, Get_Value=yoff
; Set values to centimeters and make a string
xsize = StrTrim(String(Float(xsize) * 2.54, Format='(F5.2)'), 2)
ysize = StrTrim(String(Float(ysize) * 2.54, Format='(F5.2)'), 2)
xoff = StrTrim(String(Float(xoff) * 2.54, Format='(F5.2)'), 2)
yoff = StrTrim(String(Float(yoff) * 2.54, Format='(F5.2)'), 2)
; Put inch values on the labels
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Update the info structure to indicate that current
; status is centimeters
info.inches = 0
EndIF
End
'COLOR_ON': Begin
; Update the info structure to indicate that current status
; is COLOR ON
info.color = 1
End
'COLOR_OFF': Begin
; Update the info structure to indicate that current status
; is COLOR OFF
info.color = 0
End
'BITS2': Begin
; Update the info structure to indicate that current status is BITS=2
info.bits_per_pixel = 2
End
'BITS4': Begin
; Update the info structure to indicate that current status is BITS=4
info.bits_per_pixel = 4
End
'BITS8': Begin
; Update the info structure to indicate that current status is BITS=8
info.bits_per_pixel = 8
End
'LANDSCAPE': Begin
; Going to landscape mode. Have to change the draw widget window.
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Landscape page outline
; and the default Landscape box outline
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
; Get the curent sizes of the box.
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
xsize = Float(xsize(0))
ysize = Float(ysize(0))
; Calculate new offsets.
IF info.inches EQ 1 THEN xoff = (11.0 - xsize) / 2.0
IF info.inches EQ 0 THEN xoff = (27.95 - xsize) / 2.0
IF info.inches EQ 1 THEN yoff = (8.5 - ysize) / 2.0
IF info.inches EQ 0 THEN yoff = (21.60 - ysize) / 2.0
; Constrain user sizes and offsets to fit on the page.
IF info.inches EQ 0 THEN BEGIN
xsize = 0.64 > xsize < 27.3
ysize = 0.64 > ysize < 20.95
xoff = 0.64 > xoff < 27.3
yoff = 0.64 > yoff < 20.95
ENDIF
IF info.inches EQ 1 THEN BEGIN
xsize = 0.25 > xsize < 10.75
ysize = 0.25 > ysize < 8.25
xoff = 0.25 > xoff < 10.75
yoff = 0.25 > yoff < 8.25
ENDIF
; Get the box coordinates.
box = PS_Form_PlotBox_Coords(xsize, ysize, xoff, yoff, info.inches)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
PlotS, box, Color=info.boxcolor, /Device
; Draw the Landscape page outline in the pixmap
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.landbox_x, info.landbox_y, /Device, Color=info.pagecolor
; Make the draw widget the current graphics window
WSet, info.wid
; Change the labels to their default values
xsize = String(xsize, Format='(F5.2)')
ysize = String(ysize, Format='(F5.2)')
xoff = String(xoff, Format='(F5.2)')
yoff = String(yoff, Format='(F5.2)')
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Set up the landscape x and y default maximums and minimums
info.lbox_xmax = Max(box(0,*))
info.lbox_ymax = Max(box(1,*))
info.lbox_xmin = Min(box(0,*))
info.lbox_ymin = Min(box(1,*))
; Set landscape mode
info.landscape = 1
End
'PORTRAIT': Begin
; Going to landscape mode. Have to change the draw widget window.
; Make the draw widget the current graphics window
WSet, info.wid
; Erase the old window and draw the Portrait page outline
; and the default Portrait box outline
Erase
; Get the curent sizes of the box.
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
xsize = Float(xsize(0))
ysize = Float(ysize(0))
; Calculate new offsets.
IF info.inches EQ 1 THEN xoff = (8.5 - xsize) / 2.0
IF info.inches EQ 0 THEN xoff = (21.6 - xsize) / 2.0
IF info.inches EQ 1 THEN yoff = (11.0 - ysize) / 2.0
IF info.inches EQ 0 THEN yoff = (27.95 - ysize) / 2.0
; Constrain user sizes and offsets to fit on the page.
IF info.inches EQ 0 THEN BEGIN
xsize = 0.64 > xsize < 27.3
ysize = 0.64 > ysize < 20.95
xoff = 0.64 > xoff < 27.3
yoff = 0.64 > yoff < 20.95
ENDIF
IF info.inches EQ 1 THEN BEGIN
xsize = 0.25 > xsize < 10.75
ysize = 0.25 > ysize < 8.25
xoff = 0.25 > xoff < 10.75
yoff = 0.25 > yoff < 8.25
ENDIF
; Get the box coordinates.
box = PS_Form_PlotBox_Coords(xsize, ysize, xoff, yoff, info.inches)
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, $
Color=info.pagecolor
PlotS, box, Color=info.boxcolor, /Device
; Draw the Portrait page outline on the pixmap and then reset the
; current graphics window
WSet, info.pixwid
Erase
; Make the draw widget have a charcoal background color.
TV, Replicate(info.charcoal,114,114)
PlotS, info.portraitbox_x, info.portraitbox_y, /Device, $
Color=info.pagecolor
WSet, info.wid
; Change the labels to their default values
xsize = String(xsize, Format='(F5.2)')
ysize = String(ysize, Format='(F5.2)')
xoff = String(xoff, Format='(F5.2)')
yoff = String(yoff, Format='(F5.2)')
; Put the new default values into the appropriate boxes on the form
Widget_Control, info.xsize, Set_Value=xsize
Widget_Control, info.ysize, Set_Value=ysize
Widget_Control, info.xoff, Set_Value=xoff
Widget_Control, info.yoff, Set_Value=yoff
; Set up the portrait x and y maximums and minimums
info.pbox_xmax = Max(box(0,*))
info.pbox_ymax = Max(box(1,*))
info.pbox_xmin = Min(box(0,*))
info.pbox_ymin = Min(box(1,*))
; Set portrait mode
info.landscape = 0
End
'ENCAPSULATED_ON': Begin
; Update the info structure to indicate that current status
; is ENCAPSULATED ON
info.encapsulated = 1
End
'ENCAPSULATED_OFF': Begin
; Update the info structure to indicate that current status
; is ENCAPSULATED OFF
info.encapsulated = 0
End
'ACCEPT': Begin
; The user wants to accept the information in the form.
; The procedure is to gather all the information from the
; form and then fill out a formInfo structure variable
; with the information. The formInfo structure is stored
; in a pointer. The reason for this is that we want the
; information to exist even after the form is destroyed.
; Gather the information from the form
Widget_Control, info.filename, Get_Value=filename
; Is this a valid filename? Does the directory exist?
; Can you write the file?
filename = filename(0)
; Extract the file path.
CASE !Version.OS_Family OF
'Windows' : sep = '\' ; PCs
'MacOS' : sep = ':' ; Macintoshes
'vms' : sep = ']' ; VMS machines
ELSE : sep = '/' ; Unix machines
ENDCASE
; Find the last occurrance of a separator in a filename.
loc = RStrPos(filename, sep)
; Extract the root name of the file
shortfile = StrMid(filename, loc+1, StrLen(filename) - (loc+1))
directory = StrMid(filename, 0, (StrLen(filename)-StrLen(shortfile))-1)
; Can you change to this directory?
Catch, error
IF error NE 0 THEN BEGIN
ok = Widget_Message(['"' + directory +'"', $
'does not seem to exist. Try again.'])
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
CD, Current=thisDirectory
CD, directory
; Can you write to this directory? It appears that WindowsNT
; allows IDL to write to a non-writeable directory without
; causing an error, although no file is actually written.
; I'm looking into it.
Catch, error
IF error NE 0 THEN BEGIN
ok = Widget_Message(['The directory or file does not', $
'appear to be writable. Try again.'])
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
OpenW, lun, 'ps_form.tmp', /Get_Lun, /Delete
variable = 1
WriteU, lun, variable
Free_Lun, lun
CD, thisDirectory
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
Widget_Control, info.xoff, Get_Value=xoff
Widget_Control, info.yoff, Get_Value=yoff
; I am shielding the user from the strangeness of PostScript
; Landscape mode, in which the X and Y offsets are rotated
; 180 degrees. Thus, in the form, the offsets are calculated from
; the lower-left corner in both Landscape and Portrait mode.
; This means I have to monkey around to get the proper offsets
; if the form is in Landscape mode.
IF info.landscape EQ 1 THEN Begin
IF info.inches EQ 1 THEN pagesize = 11.0 ELSE pagesize = 11.0 * 2.54
temp = yoff ; Switch x and y offsets
yoff = pagesize - xoff ; Offset really calculated from right of page
xoff = temp
ENDIF
; Fill out the formInfo structure with the information
formInfo = { cancel:0, $ ; The CANCEL flag
create:0, $ ; The CREATE flag
xsize:Float(xsize(0)), $ ; The x size of the plot
xoff:Float(xoff(0)), $ ; The x offset of the plot
ysize:Float(ysize(0)), $ ; The y size of the plot
yoff:Float(yoff(0)), $ ; The y offset of the plot
filename:filename(0), $ ; The name of the file
inches:info.inches, $ ; Inches or centimeters?
color:info.color, $ ; Color on or off?
bits_per_pixel:info.bits_per_pixel, $ ; How many bits per pixel?
encapsulated:info.encapsulated,$ ; Encapsulated file?
landscape:info.landscape } ; Landscape or portrait mode?
; Put the formInfo structure into the location pointer
; to by the pointer
Handle_Value, info.ptr, formInfo, /Set, /No_Copy
; Delete the pixmap window
WDelete, info.pixwid
; Restore the user's color table
TVLct, info.red, info.green, info.blue
; Destroy the PS_FORM widget program
Widget_Control, event.top, /Destroy
End
'CREATE': Begin
; The user wants to accept the information in the form and
; create the file. The procedure is the same as ACCEPT above.
; Gather the information from the form
Widget_Control, info.filename, Get_Value=filename
; Is this a valid filename? Does the directory exist?
; Can you write the file?
filename = filename(0)
; Extract the file path.
CASE !Version.OS_Family OF
'Windows' : sep = '\' ; PCs
'MacOS' : sep = ':' ; Macintoshes
'vms' : sep = ']' ; VMS machines
ELSE : sep = '/' ; Unix machines
ENDCASE
; Find the last occurrance of a separator in a filename.
loc = RStrPos(filename, sep)
; Extract the root name of the file
shortfile = StrMid(filename, loc+1, StrLen(filename) - (loc+1))
directory = StrMid(filename, 0, (StrLen(filename)-StrLen(shortfile))-1)
; Can you change to this directory?
Catch, error
IF error NE 0 THEN BEGIN
ok = Widget_Message(['"' + directory +'"', $
'does not seem to exist. Try again.'])
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
CD, Current=thisDirectory
CD, directory
; Can you write to this directory? It appears that WindowsNT
; allows IDL to write to a non-writeable directory without
; causing an error, although no file is actually written.
; I'm looking into it.
Catch, error
IF error NE 0 THEN BEGIN
ok = Widget_Message(['The directory or file does not', $
'appear to be writable. Try again.'])
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
OpenW, lun, 'ps_form.tmp', /Get_Lun, /Delete
variable = 1
WriteU, lun, variable
Free_Lun, lun
CD, thisDirectory
Widget_Control, info.xsize, Get_Value=xsize
Widget_Control, info.ysize, Get_Value=ysize
Widget_Control, info.xoff, Get_Value=xoff
Widget_Control, info.yoff, Get_Value=yoff
; I am shielding the user from the strangeness of PostScript
; Landscape mode, in which the X and Y offsets are rotated
; 180 degrees. Thus, in the form, the offsets are calculated from
; the lower-left corner in both Landscape and Portrait mode.
; This means I have to monkey around to get the proper offsets
; if the form is in Landscape mode.
IF info.landscape EQ 1 THEN Begin
IF info.inches EQ 1 THEN pagesize = 11.0 ELSE pagesize = 11.0 * 2.54
temp = yoff ; Switch x and y offsets
yoff = pagesize - xoff ; Offset really calculated from right of page
xoff = temp
ENDIF
; Fill out the formInfo structure with the information
formInfo = { cancel:0, $ ; The CANCEL flag
create:1, $ ; The CREATE flag
xsize:Float(xsize(0)), $ ; The x size of the plot
xoff:Float(xoff(0)), $ ; The x offset of the plot
ysize:Float(ysize(0)), $ ; The y size of the plot
yoff:Float(yoff(0)), $ ; The y offset of the plot
filename:filename(0), $ ; The name of the file
inches:info.inches, $ ; Inches or centimeters?
color:info.color, $ ; Color on or off?
bits_per_pixel:info.bits_per_pixel, $ ; How many bits per pixel?
encapsulated:info.encapsulated,$ ; Encapsulated file?
landscape:info.landscape } ; Landscape or portrait mode?
; Put the formInfo structure into the location pointer
; to by the pointer
Handle_Value, info.ptr, formInfo, /Set, /No_Copy
; Delete the pixmap window
WDelete, info.pixwid
; Restore the user's color table
TVLct, info.red, info.green, info.blue
; Destroy the PS_FORM widget program
Widget_Control, event.top, /Destroy
End
'CANCEL': Begin
; The user wants to cancel out of this form. We need a way to
; do that gracefully. Our method here is to set a "cancel"
; field in the formInfo structure.
formInfo = {cancel:1, create:0}
; Put the formInfo structure into the location pointer to
; by the pointer
Handle_Value, info.ptr, formInfo, /Set, /No_Copy
; Delete the pixmap window
WDelete, info.pixwid
; Restore the user's color table
TVLct, info.red, info.green, info.blue
; Destroy the PS_FORM widget program
Widget_Control, event.top, /Destroy
End
ENDCASE
; Put the info structure back into the top-level base if the
; base is still in existence.
If Widget_Info(event.top, /Valid) THEN $
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;*******************************************************************
Function PS_Form, xoffset, yoffset, Cancel=cancelButton, Help=help, $
XSize=xsize, YSize=ysize, XOffset=xoff, YOffset=yoff, $
Inches=inches, Color=color, Bits_Per_Pixel=bits_per_pixel, $
Encapsulated=encapsulated, Landscape=landscape, Filename=filename, $
Defaults=defaults, LocalDefaults=localDefaults, Initialize=initialize, $
Create=createButton, Parent=parent
; If the Help keyword is set, print some help information and return
IF Keyword_Set(help) THEN BEGIN
Doc_Library, 'PS_FORM'
RETURN, 0
ENDIF
; I want inches to be the default case.
IF N_ELEMENTS(inches) EQ 0 THEN inches = 1
; Check other keyword parameters.
IF N_Elements(localDefaults) EQ 0 THEN BEGIN
localDefaultPtr = Handle_Create()
PS_Form_Set_Personal_Local_Defaults, localDefaultPtr
ENDIF ELSE localDefaultPtr = Handle_Create(Value=localDefaults)
IF Keyword_Set(initialize) THEN BEGIN
; Get the local defaults and return them without asking the user
; for input.
Handle_Value, localDefaultPtr, localdefaults, /No_Copy
Handle_Free, localDefaultPtr
RETURN, localdefaults
ENDIF
; Special processing for YOffset.
yoff_flag = 0
IF N_Elements(localdefaults) NE 0 THEN BEGIN
names = Tag_Names(localdefaults)
yoff_test = Where(names EQ 'YOFF')
IF yoff_test(0) GT 0 THEN yoff_flag = 1 ELSE yoff_flag = 0
FOR j=0,N_Elements(names)-1 DO BEGIN
IF names(j) NE 'YOFF' THEN BEGIN
str = names(j) + '= localdefaults.' + names(j)
dummy = Execute(str)
ENDIF
ENDFOR
ENDIF
IF N_Elements(defaults) NE 0 THEN BEGIN
names = Tag_Names(defaults)
yoff_test = Where(names EQ 'YOFF')
IF yoff_test(0) GT 0 THEN yoff_flag = 1 ELSE yoff_flag = 0
FOR j=0,N_Elements(names)-1 DO BEGIN
IF names(j) NE 'YOFF' THEN BEGIN
str = names(j) + '= defaults.' + names(j)
dummy = Execute(str)
ENDIF
ENDFOR
ENDIF
landscape = Keyword_Set(landscape)
color = Keyword_Set(color)
encapsulated = Keyword_Set(encapsulated)
inches = Keyword_Set(inches)
IF N_Elements(bits_per_pixel) EQ 0 THEN bits_per_pixel = 8
IF NOT (bits_per_pixel NE 2 OR bits_per_pixel NE 4 $
OR bits_per_pixel NE 8) THEN BEGIN
ok = Widget_Message(['Bits_Per_Pixel keyword set with incorrect ' , $
'value of ' + StrTrim(bits_per_pixel,2) + '.', '', $
'Setting Bits_Per_Pixel = 8.'])
bits_per_pixel = 8
ENDIF
IF N_ELements(filename) EQ 0 THEN BEGIN
CD, Current=thisDir
filename = Filepath(Root_Dir=thisDir, 'idl.ps')
ENDIF
; Process YOffset if yoff_flag is set. (ASSUMING xoff is DEFINED
; and passed in with the DEFAULTS or LOCALDEFAULTS!!)
IF yoff_flag THEN BEGIN
IF N_ELEMENTS(defaults) EQ 0 THEN defaults = localdefaults
yof = Where(names EQ 'YOFF')
IF landscape EQ 1 AND inches EQ 0 THEN BEGIN
yoff = xoff
str = 'xoff = 27.94 - defaults.' + names(yof)
ENDIF
IF landscape EQ 1 AND inches EQ 1 THEN BEGIN
yoff = xoff
str = 'xoff = 11.0 - defaults.' + names(yof)
ENDIF
IF landscape EQ 0 AND inches EQ 0 THEN $
str = 'yoff = defaults.' + names(yof)
IF landscape EQ 0 AND inches EQ 1 THEN $
str = 'yoff = defaults.' + names(yof)
dummy = Execute(str(0))
ENDIF
; Portrait mode
IF landscape EQ 0 THEN BEGIN
; Check for undefined sizes and offsets. Use current window
; aspect ratio if no XSIZE or YSIZE keywords are used.
IF N_Elements(xsize) EQ 0 AND N_Elements(ysize) EQ 0 THEN BEGIN
IF !D.Window NE -1 THEN $
aspect = Float(!D.X_VSize) / !D.Y_VSize ELSE aspect = 1.0
IF aspect GE 1 THEN BEGIN
xsize = 7.0
ysize = xsize / aspect
ENDIF ELSE BEGIN
ysize = 7.0
xsize = ysize * aspect
ENDELSE
IF inches EQ 0 THEN BEGIN
xsize = xsize * 2.54
ysize = ysize * 2.54
ENDIF
ENDIF
IF N_Elements(xsize) EQ 0 THEN BEGIN
IF inches EQ 0 THEN xsize = 17.75
IF inches EQ 1 THEN xsize = 17.75 / 2.54
ENDIF
IF N_Elements(ysize) EQ 0 THEN BEGIN
IF inches EQ 0 THEN ysize = 12.70
IF inches EQ 1 THEN ysize = 12.70 / 2.54
ENDIF
IF N_Elements(xoff) EQ 0 THEN BEGIN
IF inches EQ 1 THEN xoff = (8.5 - xsize) / 2.0
IF inches EQ 0 THEN xoff = (21.6 - xsize) / 2.0
ENDIF
IF N_Elements(yoff) EQ 0 THEN BEGIN
IF inches EQ 1 THEN yoff = (11.0 - ysize) / 2.0
IF inches EQ 0 THEN yoff = (27.95 - ysize) / 2.0
ENDIF
; Constrain user sizes and offsets to fit on the page.
IF inches EQ 0 THEN BEGIN
xsize = 0.64 > xsize < 20.95
ysize = 0.64 > ysize < 27.3
xoff = 0.64 > xoff < 20.95
yoff = 0.64 > yoff < 27.3
ENDIF
IF inches EQ 1 THEN BEGIN
xsize = 0.25 > xsize < 8.25
ysize = 0.25 > ysize < 10.75
xoff = 0.25 > xoff < 8.25
yoff = 0.25 > yoff < 10.75
ENDIF
ENDIF
; Landscape mode
IF landscape EQ 1 THEN BEGIN
; Check for undefined sizes and offsets. Use current window
; aspect ratio if no XSIZE or YSIZE keywords are used.
IF N_Elements(xsize) EQ 0 AND N_Elements(ysize) EQ 0 THEN BEGIN
IF !D.Window NE -1 THEN $
aspect = Float(!D.X_VSize) / !D.Y_VSize ELSE aspect = 1.0
IF aspect GE 1 THEN BEGIN
xsize = 7.0
ysize = xsize / aspect
ENDIF ELSE BEGIN
ysize = 7.0
xsize = ysize * aspect
ENDELSE
IF inches EQ 0 THEN BEGIN
xsize = xsize * 2.54
ysize = ysize * 2.54
ENDIF
ENDIF
; Check for undefined sizes and offsets
IF N_Elements(xsize) EQ 0 THEN BEGIN
IF inches EQ 1 THEN xsize = 9.5
IF inches EQ 0 THEN xsize = 24.13
ENDIF
IF N_Elements(ysize) EQ 0 THEN BEGIN
IF inches EQ 1 THEN ysize = 7.0
IF inches EQ 0 THEN ysize = 17.78
ENDIF
IF N_Elements(xoff) EQ 0 THEN BEGIN
IF inches EQ 1 THEN xoff = (11.0 - xsize) / 2.0
IF inches EQ 0 THEN xoff = (27.94 - xsize) / 2.0
ENDIF
IF N_Elements(yoff) EQ 0 THEN BEGIN
IF inches EQ 1 THEN yoff = (8.5 - ysize) / 2.0
IF inches EQ 0 THEN yoff = (21.60 - ysize) / 2.0
ENDIF
; Constrain user sizes and offsets to fit on the page.
IF inches EQ 0 THEN BEGIN
xsize = 0.64 > xsize < 27.3
ysize = 0.64 > ysize < 20.95
xoff = 0.64 > xoff < 27.3
yoff = 0.64 > yoff < 20.95
ENDIF
IF inches EQ 1 THEN BEGIN
xsize = 0.25 > xsize < 10.75
ysize = 0.25 > ysize < 8.25
xoff = 0.25 > xoff < 10.75
yoff = 0.25 > yoff < 8.25
ENDIF
ENDIF
; Put sizes and offsets into strings that can be placed in
; the text widgets.
sizeFormat = '(F5.2)'
xsize_str = String(xsize, Format=sizeFormat)
ysize_str = String(ysize, Format=sizeFormat)
xoff_str = String(xoff, Format=sizeFormat)
yoff_str = String(yoff, Format=sizeFormat)
; This program cannot work if the graphics device is already set
; to PostScript. So if it is, set it to the native OS graphics device.
; Remember to set it back later.
IF !D.Name EQ 'PS' THEN BEGIN
oldName = 'PS'
thisDevice = Byte(!Version.OS)
thisDevice = StrUpCase( thisDevice(0:2) )
IF thisDevice EQ 'MAC' OR thisDevice EQ 'WIN' THEN Set_Plot, thisDevice ELSE Set_Plot, 'X'
ENDIF ELSE oldName = !D.Name
; Check for optional offset parameters and give defaults if not passed
Device, Get_Screen_Size=screenSize
IF N_Elements(xoffset) EQ 0 THEN xoffset = (screenSize(0) - 600) / 2.
IF N_Elements(yoffset) EQ 0 THEN yoffset = (screenSize(1) - 400) / 2.
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' AND N_Elements(parent) EQ 0 THEN BEGIN
Print, ''
Print, ' Unless you are calling PS_FORM from the command line, the'
Print, ' PARENT keyword MUST be used in IDL 5 for modal operation.'
Print, ' Please modify your code if neccesary.'
ENDIF
; The TLB must be made modal in IDL 5. Requires, however, that
; the group leader be defined.
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' THEN BEGIN
tlb = Widget_Base(Title='Configure PostScript Parameters', Column=1, $
XOffset=xoffset, YOffset=yoffset, TLB_Frame_Attr=9, $
Modal=Keyword_Set(parent), Group_Leader=parent)
ENDIF ELSE BEGIN
tlb = Widget_Base(Title='Configure PostScript Parameters', Column=1, $
XOffset=xoffset, YOffset=yoffset, TLB_Frame_Attr=9)
ENDELSE
; Sub-bases for layout
sizebase = Widget_Base(tlb, Row=1, Align_Center=1)
numbase = Widget_Base(sizebase, Column=1)
numsub1 = Widget_Base(numbase, Row=1)
junk = Widget_Label(numsub1, Value=' Units: ')
junksub = Widget_Base(numsub1, Row=1, /Exclusive)
inch = Widget_Button(junksub, Value='Inches', UValue='INCHES')
cm = Widget_Button(junksub, Value='Centimeters', $
UValue='CENTIMETERS')
IF inches EQ 1 THEN Widget_Control, inch, Set_Button=1 ELSE $
Widget_Control, cm, Set_Button=1
numsub2 = Widget_Base(numbase, Row=1, Event_Pro='PS_Form_NumEvents')
lab1base = Widget_Base(numsub2, Column=1, Base_Align_Center=1)
junk = Widget_Label(lab1base, Value='XSize: ')
junk = Widget_Label(lab1base, Value='XOffset: ')
lab2base = Widget_Base(numsub2, Column=1, Base_Align_Center=1)
xsizew = Widget_Text(lab2base, Scr_XSize=60, /Editable, $
Value=xsize_str, UValue=xsize)
xoffw = Widget_Text(lab2base, Scr_XSize=60, /Editable, $
Value=xoff_str, UValue=xoff)
lab3base = Widget_Base(numsub2, Column=1, Base_Align_Center=1)
junk = Widget_Label(lab3base, Value='YSize: ')
junk = Widget_Label(lab3base, Value='YOffset: ')
lab2base = Widget_Base(numsub2, Column=1, Base_Align_Center=1)
ysizew = Widget_Text(lab2base, Scr_XSize=60, /Editable, $
Value=ysize_str, UValue=ysize)
yoffw = Widget_Text(lab2base, Scr_XSize=60, /Editable, $
Value=yoff_str, UValue=yoff)
drawbase = Widget_Base(sizebase, Row=1)
draw = Widget_Draw(drawbase, XSize=114, YSize=114, $
Event_Pro='PS_Form_Draw_Events', Button_Events=1)
colorbase = Widget_Base(tlb, Row=1, Align_Center=1)
colorlabel = Widget_Label(colorbase, Value='Color:')
coloron = Widget_Base(colorbase, Row=1, /Exclusive, Frame=1)
col_on = Widget_Button(coloron, Value='On', UValue='COLOR_ON')
col_off = Widget_Button(coloron, Value='Off', UValue='COLOR_OFF')
IF color EQ 0 THEN Widget_Control, col_off, Set_Button=1 ELSE $
Widget_Control, col_on, Set_Button=1
bitslabel = Widget_Label(colorbase, Value='Bits')
bitsw = Widget_Base(colorbase, Row=1, /Exclusive, /frame)
bit2 = Widget_Button(bitsw, Value='2', UValue='BITS2')
bit4 = Widget_Button(bitsw, Value='4', UValue='BITS4')
bit8 = Widget_Button(bitsw, Value='8', UValue='BITS8')
CASE bits_per_pixel OF
2: Widget_Control, bit2, Set_Button=1
4: Widget_Control, bit4, Set_Button=1
8: Widget_Control, bit8, Set_Button=1
ENDCASE
orientbase = Widget_Base(tlb, Row=1, Align_Center=1)
junk = Widget_Label(orientbase, Value='Orientation: ')
junkbase = Widget_Base(orientbase, Row=1, /Frame, /Exclusive)
land = Widget_Button(junkbase, Value='Landscape', UValue='LANDSCAPE')
port = Widget_Button(junkbase, Value='Portrait', UValue='PORTRAIT')
IF landscape EQ 0 THEN Widget_Control, port, Set_Button=1 ELSE $
Widget_Control, land, Set_Button=1
junk = Widget_Label(orientbase, Value='Encapsulated: ')
junkbase = Widget_Base(orientbase, Row=1, /Exclusive, /Frame)
encap_on = Widget_Button(junkbase, Value='On', $
UValue='ENCAPSULATED_ON')
encap_off = Widget_Button(junkbase, Value='Off', $
UValue='ENCAPSULATED_OFF')
IF encapsulated EQ 0 THEN Widget_Control, encap_off, $
Set_Button=1 ELSE Widget_Control, encap_on, Set_Button=1
filenamebase = Widget_Base(tlb, Column=1, Align_Center=1)
fbase = Widget_Base(filenamebase, Row=1)
textlabel = Widget_Label(fbase, Value='Filename: ')
; Set up text widget with an event handler that ignores any event.
filenamew = Widget_Text(fbase, /Editable, Scr_XSize=250, $
Value=filename, Event_Pro='PS_Form_Null_Events')
filebutton = Widget_Button(fbase, Value='Select Filename', $
Event_Pro='PS_FORM_Select_File')
buttonbase = Widget_Base(filenamebase, Align_Center=1, Column=1)
defbuttonbase = Widget_Base(buttonbase, Row=1)
sysdefaults = Widget_Button(defbuttonbase, Value='System Defaults', $
Event_Pro='PS_Form_Set_System_Defaults', UValue='SYSTEM')
localdefs = Widget_Button(defbuttonbase, Value='Local Defaults', $
Event_Pro='PS_Form_Set_Local_Defaults', UValue='LOCAL')
actionbuttonbase = Widget_Base(buttonbase, Row=1)
cancel = Widget_Button(actionbuttonbase, Value='Cancel', UValue='CANCEL')
create = Widget_Button(actionbuttonbase, Value='Create File', UValue='CREATE')
accept = Widget_Button(actionbuttonbase, Value='Accept', UValue='ACCEPT')
Widget_Control, tlb, /Realize
Widget_Control, draw, Get_Value=wid
WSet, wid
; How big is the top-level base? Want to size the filename text widget
; the appropriate size.
;baseSize = Widget_Info(filenamebase, /Geometry)
;textlabelSize = Widget_Info(textlabel, /Geometry)
;Widget_Control, filenamew, $
; Scr_XSize=(baseSize.XSize - textlabelSize.XSize - baseSize.XPad - $
; textlabelSize.XPad)
; Ready to set up parameters to draw the boxes on the display.
portraitbox_x = [1,1,88,88,1]
portraitbox_y = [1, 112, 112, 1, 1]
landbox_x = [1, 112, 112, 1, 1]
landbox_y = [1, 1, 88, 88, 1]
; Convert sizes and offsets to Device coordinates.
boxInfo = PS_Form_PlotBox_Coords(xsize, ysize, xoff, yoff, inches)
IF landscape EQ 0 THEN BEGIN
pbox_xmax = Max(boxInfo(0,*))
pbox_xmin = Min(boxInfo(0,*))
pbox_ymax = Max(boxInfo(1,*))
pbox_ymin = Min(boxInfo(1,*))
lbox_xmax = 0
lbox_xmin = 0
lbox_ymax = 0
lbox_ymin = 0
ENDIF ELSE BEGIN
pbox_xmax = 0
pbox_xmin = 0
pbox_ymax = 0
pbox_ymin = 0
lbox_xmax = Max(boxInfo(0,*))
lbox_xmin = Min(boxInfo(0,*))
lbox_ymax = Max(boxInfo(1,*))
lbox_ymin = Min(boxInfo(1,*))
ENDELSE
; Get the colors in the current color table
TVLct, r, g, b, /Get
; Modify color indices N_Colors-2, N_Colors-3 and N_Colors-4 for
; drawing colors
; The number of colors in the session can be less then the
; number of colors in the color vectors on PCs (and maybe other
; computers), so take the smaller value. (Bug fix?)
ncol = !D.N_Colors < N_Elements(r)
red = r
green = g
blue=b
red(ncol-4:ncol-2) = [70B, 0B, 255B]
green(ncol-4:ncol-2) = [70B, 255B, 255B]
blue(ncol-4:ncol-2) = [70B, 0B, 0B]
; Load the newly modified colortable
TVLct, red, green, blue
; Make the draw widget have a charcoal background color.
TV, Replicate(ncol-4,114,114)
; Draw a page box in the draw widget
IF landscape EQ 0 THEN PlotS, portraitbox_x, portraitbox_y, /Device, Color=ncol-2 ELSE $
PlotS, landbox_x, landbox_y, /Device, Color=ncol-2
; Draw a plot box in the draw widget
PlotS, boxInfo(0,*), boxInfo(1,*), /Device, Color=ncol-3
; Create a pixmap and draw the page box on it
Window, /Free, XSize=114, YSize=114, /Pixmap
pixwid = !D.Window
WSet, pixwid
TV, Replicate(ncol-4,114,114)
IF landscape EQ 0 THEN PlotS, portraitbox_x, portraitbox_y, /Device, Color=ncol-2 ELSE $
PlotS, landbox_x, landbox_y, /Device, Color=ncol-2
WSet, wid
; Create a pointer to store the formInfo structure from the form
ptr = Handle_Create()
; Create an info structure to store information required by the program
info = {draw:draw, $ ; The draw widget id
pixwid:pixwid, $ ; The pixmap window id
wid:wid, $ ; The draw widget window id
xsize:xsizew, $ ; The widget id to get XSIZE
ysize:ysizew, $ ; The widget id to get YSIZE
xoff:xoffw, $ ; The widget id to get XOFFSET
yoff:yoffw, $ ; The widget id to get YOFFSET
filename:filenamew, $ ; The widget id to get FILENAME
inch:inch, $ ; The widget id of inch button.
cm:cm, $ ; The widget id of cm button.
col_on:col_on, $ ; The widget id of color on button.
col_off:col_off, $ ; The widget id of color off button.
bit2:bit2, $ ; The widget id of bit=2 button.
bit4:bit4, $ ; The widget id of bit=4 button.
bit8:bit8, $ ; The widget id of bit=8 button.
encap_on:encap_on, $ ; The widget id of encapsulate on button.
encap_off:encap_off, $ ; The widget id of encapsulate off button.
land:land, $ ; The widget id of the landscape button.
port:port, $ ; The widget id of the portrait button.
portraitbox_x:portraitbox_x, $ ; Portrait page outline x (default)
portraitbox_y:portraitbox_y, $ ; Portrait page outline y (default)
pplotbox_x:[8, 8, 82, 82, 8], $ ; Portrait box outline x (default)
pplotbox_y:[60, 106, 106, 60, 60], $ ; Portrait box outline y (default)
landbox_x:landbox_x, $ ; Landscape page outline x (default)
landbox_y:landbox_y, $ ; Landscape page outline y (default)
lplotbox_x:[8, 8, 106, 106, 8], $ ; Landscape box outline x (default)
lplotbox_y:[8, 82, 82, 8, 8], $ ; Landscape box outline y (default)
pbox_xmax:pbox_xmax, $ ; Current portrait box x maximum
pbox_xmin:pbox_xmin, $ ; Current portrait box x minimum
pbox_ymax:pbox_ymax, $ ; Current portrait box y maximum
pbox_ymin:pbox_ymin, $ ; Current portrait box Y minimum
lbox_xmax:lbox_xmax, $ ; Current landscape box x maximum
lbox_xmin:lbox_xmin, $ ; Current landscape box x minimum
lbox_ymax:lbox_ymax, $ ; Current landscape box y maximum
lbox_ymin:lbox_ymin, $ ; Current landscape box y minimum
inches:inches, $ ; Inches = 1, Centimeters = 0
color:color, $ ; Color = 1, B&W = 0
bits_per_pixel:bits_per_pixel, $ ; Number of bits per pixel
landscape:landscape, $ ; Landscape mode = 1, Portrait mode = 0
encapsulated:encapsulated, $ ; Encapsulated = 1, Non-encapsulated = 0
pagecolor:ncol-2, $ ; Color to draw page outline (yellow)
boxcolor:ncol-3, $ ; Color to draw plot box (green)
charcoal:ncol-4, $ ; Color to put as background in the draw widget
red:r, $ ; Old red color vector
green:g, $ ; Old green color vector
blue:b, $ ; Old blue color vector
ptr:ptr, $ ; Pointer to store data from the form.
localDefaultPtr:localDefaultPtr, $ ; Pointer to local default structure.
xs:0.0, $ ; X value of static corner of box
ys:0.0, $ ; Y value of static corner of box
xcur:0.0, $ ; X value of moving corner of box
ycur:0.0, $ ; Y value of moving corner of box
mouse_x:0.0, $ ; X value of mouse in moving box
mouse_y:0.0, $ ; Y value of mouse in moving box
xmax:0.0, $ ; Temporary X max value of moving box
ymax:0.0, $ ; Temporary Y max value of moving box
xmin:0.0, $ ; Temporary X min value of moving box
ymin:0.0 } ; Temporary Y min value of moving box
; Store the info structure in the top-level base
Widget_Control, tlb, Set_UValue=info, /No_Copy
; Set this widget program up as a modal or blocking widget. What this means
; is that you will return to the line after this XManager call when the
; widget is destroyed.
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' THEN XManager, 'ps_form', tlb ELSE $
XManager, 'ps_form', tlb, /Modal
; Get the formInfo structure from the pointer location.
Handle_Value, ptr, formInfo, /No_Copy
; Make sure the user didn't click a close button.
IF N_Elements(formInfo) EQ 0 THEN Begin
Handle_Free, ptr
cancelButton = 1
createButton = 0
RETURN, 0
EndIF
; Make sure you aren't running through the XManager call.
stillValid = Widget_Info(tlb, /Valid_ID)
IF N_Elements(formInfo) EQ 0 AND stillValid THEN Begin
ok = Widget_Message(['The PARENT keyword MUST be used', $
'in the PS_FORM call in IDL 5.', 'Please modify your code.'])
cancelButton = 1
createButton = 0
RETURN, 0
EndIF
; Strip the CANCEL field out of the formInfo structure so the
; cancelButton flag can be returned via the CANCEL keyword and the
; formInfo structure is suitable for passing directly to the DEVICE
; procedure through its _Extra keyword.
cancelButton = formInfo.cancel
createButton = formInfo.create
IF NOT cancelButton THEN BEGIN
formInfo = { PS_FORM_INFO, $
xsize:formInfo.xsize, $
xoff:formInfo.xoff, $
ysize:formInfo.ysize, $
yoff:formInfo.yoff, $
filename:formInfo.filename, $
inches:formInfo.inches, $
color:formInfo.color, $
bits_per_pixel:formInfo.bits_per_pixel, $
encapsulated:formInfo.encapsulated, $
landscape:formInfo.landscape }
ENDIF ELSE formInfo = 0 ; Return a throw-away value
; Free up the space allocated to the pointers and the data
Handle_Free, ptr
IF N_Elements(localDefaultPtr) NE 0 THEN Handle_Free, localDefaultPtr
; Restore graphics device.
Set_Plot, oldname
RETURN, formInfo
END ;*******************************************************************