;+ ; GRAFFER ; Simple interactive data plotter. ; ; Usage: ; graffer[, group=group] ; ; Argument: ; file string input The initial filename for the graph ; file ; ; Keywords: ; group long input The group leader of the widget tree. ; xsize int input The x dimension of the draw widget ; ysize int input The y dimension of the draw widget ; debug input If set, then run in debugging mode. ; ; History: ; Original: 27/7/95; SJT ; Extended, polished etc.: Aug 95; SJT ; V0.00 - basic version ; V0.01 - Functions stored as strings not as arrays of values ; V0.02 - Functions have X range specified become structures ; V0.03 - Allow larger draw area, in scrolling window. ; V0.04 - Desensitize main widget when sub menus are ; shown and use CW_BGROUP instead of XMENU. (24/8/95) ; V0.05 - Add a charsize option. (30/8/95) ; V0.06 - Add option to plot text in norm coords (30/8/95) ; V0.07 - Add possible timestamp to hardcopies and also ; make hardcopy file assume the name of the data ; set (1/9/95) ; V0.08 - Add line width for axes (4/9/95) ; Add full range of axis style settings. ; V1.00 - Major restructuring of the pdefs structure and ; of the save files to keep each data-set of ; text item together (5/9/95). ; V1.01 - Add a descriptive tag to each data set. ; Add possibility of plotting error bars ; (symmetrical or otherwise). ; V1.02 - Add facilities for (a) Reading variables from ; the IDL main program level, (b) non-standard ; text alignments, (c) autosaving. Also fix a ; couple of loopholes in the interlocking. ; V1.03 - Add a "Function" box and use tracking events ; to give a brief description of all settable ; objects at the top level. (5/12/95) ; [Work-around for corruption of UVALUES of ; delete & erase buttons. (2/2/96)] ;- pro Graff_event, event widget_control, event.id, get_uvalue = object if (object eq 'CONTROL' or $ object eq 'EDITOR') then object = event.value base = widget_info(/child, event.top) widget_control, base, get_uvalue = pdefs, /no_copy idraw_flag = 1 ichange = 1b track_flag = strpos(tag_names(event, /struct), 'TRACK') ne -1 if (track_flag) then begin idraw_flag = 0 ichange = 0b if (event.enter eq 0) then begin graff_msg, pdefs.ids.hlptxt, '' goto, miss_case endif endif case object of 'Exit': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'EXIT from GRAFFER' $ else begin if (pdefs.chflag) then ido = graff_s_prompt(pdefs) $ else ido = 1b if (ido) then begin if (pdefs.transient.changes eq 0) then begin on_ioerror, no_auto openr, ilu, /get, /delete, $ ; Delete the auto save file. pdefs.dir+'#'+pdefs.name+'#' free_lun, ilu No_auto: on_ioerror, null endif graff_clear, pdefs widget_control, event.top, /destroy return endif idraw_flag = 0 ichange = 0b end 'Hard Copy': graff_msg, pdefs.ids.hlptxt, 'Make PostScript version ' + $ 'of plot' 'Hard Copy.Set up ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Define hardcopy parameters and ' + $ 'make copy' $ else begin graff_hard, pdefs end 'Hard Copy.Quick': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Make hardcopy using current setting' $ else begin graff_hard, pdefs, /no_set ichange = 0b end 'Save': graff_msg, pdefs.ids.hlptxt, 'Save plot in internal format ' + $ 'for future use, or do screen dump' 'Save.Save to current': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Save plot to currently selected filename' $ else begin graff_save, pdefs ichange = 0b end 'Save.Save as ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Save plot to new file name' $ else begin dir = pdefs.dir fc = graff_fname(pdefs.ids.graffer, pdefs.name, dir) pdefs.name = fc pdefs.dir = dir graff_save, pdefs ichange = 0b graff_set_vals, pdefs end 'Save.Dump screen': graff_msg, pdefs.ids.hlptxt, 'Make a screen ' + $ 'dump to an image file' 'Save.Dump screen.Gif': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Dump to GIF (Graphical Interchange ' + $ 'Format) file' $ else begin graff_dump, pdefs, /gif ichange = 0b idraw = 0 end 'Save.Dump screen.Tiff': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Dump to TIFF (Tagged Image File ' + $ 'Format) file' $ else begin graff_dump, pdefs, /tiff ichange = 0b idraw = 0 end 'Save.Dump screen.Nrif': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Dump to NRIF (NCAR Raster Image ' + $ 'File) ' $ else begin graff_dump, pdefs, /nrif ichange = 0b idraw = 0 end 'Open': graff_msg, pdefs.ids.hlptxt, 'Open a new GRAFFER file' 'Open.Restore ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select and open an existing file' $ else begin if (pdefs.chflag) then ido = graff_s_prompt(pdefs) $ else ido = 1b if (ido) then graff_get, pdefs ichange = 0b end 'Open.New ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Create a new file' $ else begin if (pdefs.chflag) then ido = graff_s_prompt(pdefs) $ else ido = 1b if (ido) then begin dir = pdefs.dir fc = graff_fname(pdefs.ids.graffer, '', dir) if (fc eq '') then begin graff_msg, pdefs.ids.message, 'New file not given' endif else begin graff_init, pdefs, dir+fc graff_set_vals, pdefs endelse end ichange = 0b end 'TITLE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter plot title (at top of plot)' $ else begin pdefs.title = event.value if (event.cr) then grf_focus_enter, pdefs.ids.subtitle end 'SUBTITLE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter plot subtitle (below plot)' $ else begin pdefs.subtitle = event.value if (event.cr) then grf_focus_enter, pdefs.ids.charsize end 'CHARSIZE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter character size for ' + $ 'annotations (floating point value)' $ else begin pdefs.charsize = event.value if (event.cr) then grf_focus_enter, pdefs.ids.axthick end 'AXTHICK': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter line thickness for axes ' + $ '(integer value 1-99)' $ else begin pdefs.axthick = event.value if (event.cr) then grf_focus_enter, pdefs.ids.title end 'XMIN': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter minimum value on X axis ' + $ '(floating point)' $ else begin pdefs.xrange(0) = event.value if (event.cr) then grf_focus_enter, pdefs.ids.xmax end 'XMAX': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter maximum value on X axis ' + $ '(floating point)' $ else begin pdefs.xrange(1) = event.value if (event.cr) then grf_focus_enter, pdefs.ids.xtitle end 'XLOG': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Toggle linear or logarithmic X axis' $ else pdefs.xtype = event.value 'XSTY': begin val = str_sep(event.value, '.') if (n_elements(val) eq 1) then graff_msg, pdefs.ids.hlptxt, $ 'Select X-axis style options' $ else case val(1) of 'Exact Range': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select exact (On) or ' + $ 'rounded (Off) X axis range' $ else if (val(2) eq 'Off') then $ pdefs.xsty = pdefs.xsty and (not 1) $ else pdefs.xsty = pdefs.xsty or 1 end 'Extended Range': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch "Extended" ' + $ 'X-axis range on or off' $ else if (val(2) eq 'Off') then $ pdefs.xsty = pdefs.xsty and (not 2) $ else pdefs.xsty = pdefs.xsty or 2 end 'Draw Axes': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of X axes ' + $ 'on or off' $ else if (val(2) eq 'Off') then $ pdefs.xsty = pdefs.xsty or 4 $ else pdefs.xsty = pdefs.xsty and (not 4) end 'Draw Box Axis': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of ' + $ 'right-hand X axis on or off' $ else if (val(2) eq 'Off') then $ pdefs.xsty = pdefs.xsty or 8 $ else pdefs.xsty = pdefs.xsty and (not 8) end 'Minor Ticks': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of ' + $ 'X axis minor tick marks on or off' $ else if (val(2) eq 'Off') then $ pdefs.xsty = pdefs.xsty or 32 $ else pdefs.xsty = pdefs.xsty and (not 32) end endcase end 'XLAB': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter label for the X axis' $ else begin pdefs.xtitle = event.value if (event.cr) then grf_focus_enter, pdefs.ids.xmin end 'YMIN': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter minimum value on Y axis ' + $ '(floating point)' $ else begin pdefs.yrange(0) = event.value if (event.cr) then grf_focus_enter, pdefs.ids.ymax end 'YMAX': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter maximum value on Y axis ' + $ '(floating point)' $ else begin pdefs.yrange(1) = event.value if (event.cr) then grf_focus_enter, pdefs.ids.ytitle end 'YLOG': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Toggle linear or logarithmic Y axis' $ else pdefs.ytype = event.value 'YSTY': begin val = str_sep(event.value, '.') if (n_elements(val) eq 1) then graff_msg, pdefs.ids.hlptxt, $ 'Select Y-axis style options' $ else case val(1) of 'Exact Range': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select exact (On) or ' + $ 'rounded (Off) Y axis range' $ else if (val(2) eq 'Off') then $ pdefs.ysty = pdefs.ysty and (not 1) $ else pdefs.ysty = pdefs.ysty or 1 end 'Extended Range': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch "Extended" ' + $ 'Y-axis range on or off' $ else if (val(2) eq 'Off') then $ pdefs.ysty = pdefs.ysty and (not 2) $ else pdefs.ysty = pdefs.ysty or 2 end 'Draw Axes': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of Y axes ' + $ 'on or off' $ else if (val(2) eq 'Off') then $ pdefs.ysty = pdefs.ysty or 4 $ else pdefs.ysty = pdefs.ysty and (not 4) end 'Draw Box Axis': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of ' + $ 'right-hand Y axis on or off' $ else if (val(2) eq 'Off') then $ pdefs.ysty = pdefs.ysty or 8 $ else pdefs.ysty = pdefs.ysty and (not 8) end 'Minor Ticks': begin if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Switch drawing of ' + $ 'Y axis minor tick marks on or off' $ else if (val(2) eq 'Off') then $ pdefs.ysty = pdefs.ysty or 32 $ else pdefs.ysty = pdefs.ysty and (not 32) end endcase end 'YLAB': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter label for the Y axis' $ else begin pdefs.ytitle = event.value if (event.cr) then grf_focus_enter, pdefs.ids.ymin end 'CSET': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select current data set' $ else begin graff_ch_dset, pdefs ichange = 0b idraw_flag = 0 end 'DESC': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Give the current data set a ' + $ 'memorable description' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).descript = event.value handle_value, pdefs.data, data, /no_copy, /set idraw_flag = 0 if (event.cr) then grf_focus_enter, pdefs.ids.symsize end 'PSYM': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select plotting symbol and/or ' + $ 'joining style for current data set' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).psym = event.value handle_value, pdefs.data, data, /set, /no_copy end 'SSIZE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Set size for plot symbol ' + $ 'in current data set (floating point)' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).symsize = event.value handle_value, pdefs.data, data, /no_copy, /set if (event.cr) then grf_focus_enter, pdefs.ids.colour end 'COLOUR': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Set colour index for current data ' + $ 'set (integer)' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).colour = event.value handle_value, pdefs.data, data, /set, /no_copy if (event.cr) then grf_focus_enter, pdefs.ids.thick end 'STYLE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Select line style for current data set' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).line = event.value handle_value, pdefs.data, data, /set, /no_copy end 'THICK': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Set line thickness for current ' + $ 'data set (integer)' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).thick = event.value handle_value, pdefs.data, data, /set, /no_copy if (event.cr) then grf_focus_enter, pdefs.ids.cset end 'SORT': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Toggle sorting of X axis values ' + $ 'before plotting current data set' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).sort = event.value handle_value, pdefs.data, data, /no_copy, /set end 'Function': graff_msg, pdefs.ids.hlptxt, 'Enter data in the form ' + $ 'of a function' 'Function.y = f(x) ...':if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Function with Y as a function of X' $ else graff_funct, pdefs 'Function.x = f(y) ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Function with X as a function of Y' $ else graff_funct, pdefs, /y_funct 'Function.x = f(t) & y = g(t) ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Function with both X and Y ' + $ 'functions of a parameter T' $ else graff_pfunct, pdefs 'XY data': graff_msg, pdefs.ids.hlptxt, 'Enter data for current ' + $ 'data set as X, Y data pairs (plus optional error bars)' 'XY data.From file ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Read X, Y, [error] data from an ' + $ 'external file' $ else gr_xy_read, pdefs 'XY data.Edit values ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Enter X, Y, [error] data from a ' + $ 'widget entry box' $ else gr_xy_wid, pdefs 'XY data.Top level variables ...': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Get X, Y, [error] values from IDL ' + $ 'top-level variables' $ else graff_tlv, pdefs 'ERASE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Erase the values in the current ' + $ 'data set' $ else begin handle_value, pdefs.data, data, /no_copy data(pdefs.cset).ndata = 0 data(pdefs.cset).type = 0 handle_value, data(pdefs.cset).xydata, fltarr(2, 2), /set handle_value, pdefs.data, data, /no_copy, /set end 'DELETE': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Delete the current data set' $ else graff_dsdel, pdefs 'DRAW': begin graff_draw, pdefs, event, track_flag if (not track_flag) then begin idraw_flag = (event.type eq 1) ichange = (event.type eq 1) endif end 'TEXT': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Toggle between drawing and text ' + $ 'modes' $ else begin if (event.value) then $ widget_control, pdefs.ids.draw, set_uvalue = 'WRITE' $ else widget_control, pdefs.ids.draw, set_uvalue = 'DRAW' ichange = 0b end 'WRITE': begin graff_write, pdefs, event, track_flag if (not track_flag) then begin idraw_flag = (event.type eq 1) ichange = (event.type eq 1) endif end 'MOTION': if (track_flag) then $ graff_msg, pdefs.ids.hlptxt, 'Toggle use of crosshairs and ' + $ 'cursor position monitor' $ else begin widget_control, pdefs.ids.draw, draw_motion_events = $ event.value ichange = 0b end 'AUTOSAVE': begin graff_save, pdefs, /auto ichange = 0b idraw_flag = 0 widget_control, event.id, timer = 300 end Else: graff_msg, pdefs.ids.message, 'Unknown UVALUE: '+object endcase if (idraw_flag) then plot_object, pdefs if (ichange) then begin pdefs.chflag = 1b pdefs.transient.changes = pdefs.transient.changes+1 if (pdefs.transient.changes gt 20) then graff_save, pdefs, /auto endif Miss_case: widget_control, base, set_uvalue = pdefs, /no_copy end pro Graffer, file, group=group, xsize=xsize, ysize=ysize, debug=debug, $ recover=recover common Psym_maps, psym_bm, psym_nos if (keyword_set(debug)) then begin qstate = !quiet !Quiet = 0 on_error, 0 ; stop at error endif else on_error, 2 ; Return to caller on error if ((!D.flags and 65536) eq 0) then begin print, "GRAFFER needs widgets; current device (", !D.name, $ ") does not support them." return endif if (n_elements(file) eq 0) then $ file = pickfile(/read, filter = '*.grf', title = 'Graffer Select') if (file eq '') then return ; Define the data control structure version = [1, 3] graff_init, pdefs, file, version = version graff_get, pdefs, file, /no_set, recover = recover pdefs.ids.graffer = widget_base(title = 'Graffer ' + $ 'V'+string(pdefs.version, $ format = "(I0,'.',I2.2)"), $ /row) base = widget_base(pdefs.ids.graffer, /column) cdbase = widget_base(base, /row) cbase = widget_base(cdbase, /column) ; Exit etc. ctlmenu = [{CW_PDMENU_S, flags:0, name:'Exit'}, $ {cw_pdmenu_s, 1, 'Hard Copy'}, $ {cw_pdmenu_s, 0, 'Quick'}, $ {cw_pdmenu_s, 2, 'Set up ...'}, $ {cw_pdmenu_s, 1, 'Save'}, $ {cw_pdmenu_s, 0, 'Save to current'}, $ {cw_pdmenu_s, 0, 'Save as ...'}, $ {cw_pdmenu_s, 3, 'Dump screen'}, $ {cw_pdmenu_s, 0, 'Gif'}, $ {cw_pdmenu_s, 0, 'Tiff'}, $ {cw_pdmenu_s, 2, 'Nrif'}, $ {cw_pdmenu_s, 3, 'Open'}, $ {cw_pdmenu_s, 0, 'Restore ...'}, $ {cw_pdmenu_s, 2, 'New ...'}] junk = cw_pdtmenu(cbase, ctlmenu, /return_full_name, uvalue = $ 'CONTROL', /track) pdefs.ids.name = graff_enter(cbase, /display, /text, value = $ pdefs.name, xsize = 30, label = "Name:") pdefs.ids.dir = graff_enter(cbase, /display, value = pdefs.dir, $ xsize = 30, label = 'Directory:') ; Plot Title/Subtitle tjb = widget_base(cbase, /column, /frame) junk = widget_label(tjb, value = 'General') pdefs.ids.title = graff_enter(tjb, /all_events, value = '', xsize = $ 25, uvalue = 'TITLE', label = 'Title:', $ /track) pdefs.ids.subtitle = graff_enter(tjb, /all_events, value = '', $ xsize = 25, uvalue = 'SUBTITLE', $ label = 'Subtitle:', /track) jb = widget_base(tjb, /row) pdefs.ids.charsize = graff_enter(jb, /all_events, value = 1.0, $ /float, xsize = 10, uvalue = $ 'CHARSIZE', label = 'Charsize:', $ format = "(F6.1)", /track) pdefs.ids.axthick = graff_enter(jb, /all_events, /int, value = 1, $ xsize = 2, uvalue = 'AXTHICK', label = $ 'Line width:', format = "(I0)", /track) ; X Axis controls tjb = widget_base(cbase, /column, /frame) junk = widget_label(tjb, value = 'X-Axis') ; Title pdefs.ids.xtitle = graff_enter(tjb, /all_events, value = '', xsize = $ 25, uvalue = 'XLAB', label = 'X ' + $ 'Label:', /track) ; Log/linear jb = widget_base(tjb, /row) pdefs.ids.xlog = cw_bbselector(jb, ['Linear', 'Log'], uvalue = 'XLOG', $ set_value = 0, label_left = 'X ' + $ 'Log/Lin:', /track) ; Exact or rounded axis range xstydesc = [{CW_PDMENU_S, flags:3, name:'X style'}, $ {cw_pdmenu_s, 1, 'Exact Range'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Extended Range'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Draw Axes'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Draw Box Axis'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 3, 'Minor Ticks'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}] junk = widget_label(jb, value = 'Style:') junk = cw_pdtmenu(jb, xstydesc, /return_full_name, uvalue = 'XSTY', $ /track) ; Minimum jb = widget_base(tjb, /row) pdefs.ids.xmin = graff_enter(jb, /float, /all_events, value = 0., $ xsize = 10, uvalue = 'XMIN', label = 'X ' + $ 'Min:', format = "(g10.3)", /track) ; Maximum pdefs.ids.xmax = graff_enter(jb, /float, /all_events, value = 0., $ xsize = 10, uvalue = 'XMAX', label = 'X ' + $ 'Max:', format = "(g10.3)", /track) ; Y Axis controls tjb = widget_base(cbase, /column, /frame) junk = widget_label(tjb, value = 'Y-Axis') ; Title pdefs.ids.ytitle = graff_enter(tjb, /all_events, value = '', xsize = $ 25, uvalue = 'YLAB', label = 'Y ' + $ 'Label:', /track) ; Log/linear jb = widget_base(tjb, /row) pdefs.ids.ylog = cw_bbselector(jb, ['Linear', 'Log'], uvalue = 'YLOG', $ set_value = 0, label_left = $ 'Y Log/Lin:', /track) ; Exact or rounded axis range ystydesc = [{CW_PDMENU_S, flags:3, name:'Y style'}, $ {cw_pdmenu_s, 1, 'Exact Range'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Extended Range'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Draw Axes'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 1, 'Draw Box Axis'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}, $ {cw_pdmenu_s, 3, 'Minor Ticks'}, $ {cw_pdmenu_s, 0, 'Off'}, $ {cw_pdmenu_s, 2, 'On'}] junk = widget_label(jb, value = 'Style:') junk = cw_pdtmenu(jb, ystydesc, /return_full_name, uvalue = 'YSTY', $ /track) ; Minimum jb = widget_base(tjb, /row) pdefs.ids.ymin = graff_enter(jb, /float, /all_events, value = 0., $ xsize = 10, uvalue = 'YMIN', label = 'Y ' + $ 'Min:', format = "(g10.3)", /track) ; Maximum pdefs.ids.ymax = graff_enter(jb, /float, /all_events, value = 0., $ xsize = 10, uvalue = 'YMAX', label = 'Y ' + $ 'Max:', format = "(g10.3)", /track) ; The draw screen and the plot type ; selections. if (not keyword_set(xsize)) then xwsize = 600 $ else xwsize = xsize > 600 if (not keyword_set(ysize)) then ywsize = 600 $ else ywsize = ysize > 600 if ((xwsize > ywsize) gt 600) then $ pdefs.ids.draw = widget_draw(cdbase, xsize = xwsize, x_scroll_size = $ 600, ysize = ywsize, y_scroll_size = 600, $ uvalue = 'DRAW', /button_event, $ /motion_event, /track) $ else $ pdefs.ids.draw = widget_draw(cdbase, xsize = xwsize, ysize = ywsize, $ uvalue = 'DRAW', /button_event, $ /motion_event, /track) ; Setting the properties for the ; current data set dsbase = widget_base(base, /row, /frame) ; Change Data Set tjb = widget_base(dsbase, /column) jb = widget_base(tjb, /row) junk = cw_btgroup(jb, 'Selection', label_left = 'Data set', uvalue = $ 'CSET', /track) ; Erase current jbb = widget_base(jb, /frame, /row) junk = widget_button(jbb, value = 'Erase', uvalue = 'ERASE', /track) junk = widget_button(jbb, value = 'Delete', uvalue = 'DELETE', /track) handle_value, pdefs.data, data, /no_copy pdefs.ids.cset = graff_enter(tjb, /all, xsize = 25, value = $ data(pdefs.cset).descript, format = $ "(A)", label = 'Data:', $ uvalue = 'DESC', /track) handle_value, pdefs.data, data, /no_copy, /set ; Current cursor position junk = cw_bbselector(tjb, ['Disabled', 'Enabled'], set_value = 1, uvalue $ = 'MOTION', label_left = 'Cursor tracing:', /track) jb = widget_base(tjb, /row) pdefs.ids.xcp = graff_enter(jb, /float, /display, xsize = 10, value = $ 0., label = 'X:', format = "(g10.3)") pdefs.ids.ycp = graff_enter(jb, /float, /display, xsize = 10, value = $ 0., label = 'Y:', format = "(g10.3)") ; Plotting symbols tjb = widget_base(dsbase, /column) jb = widget_base(tjb, /row) jjb = widget_base(jb, /column) if (n_elements(psym_bm) eq 0) then psym_bitmaps pdefs.ids.psym = cw_bbselector(jjb, psym_bm, uvalue = 'PSYM', $ return_uvalue = psym_nos, $ label_left = 'Plot Symbol:', /track) pdefs.ids.sort = cw_bbselector(jjb, ['Unsorted', 'Sorted'], uvalue = $ 'SORT', set_value = 0, label_left = $ 'Sort X-axis?:', /track) ; Change symbol size jjb = widget_base(jb, /column) pdefs.ids.symsize = graff_enter(jjb, /float, /all_ev, value = '1.0', $ uvalue = 'SSIZE', xsize = 5, label = $ 'Symbol size:', format = "(f5.1)", $ /track) ; Colour, linestyle, thickness etc. pdefs.ids.colour = graff_enter(jjb, /int, /all_ev, xsize = 2, value = $ 1, uvalue = 'COLOUR', label = $ 'Colour:', format = "(I2)", /track) jjb = widget_base(jb, /column) pdefs.ids.line = cw_bbselector(jjb, ['________', $ '........', $ '_ _ _ _ ', $ '_._._._.', $ '_..._...', $ '__ __ '], $ set_value = 0, uvalue = 'STYLE', $ label_left = 'Style:', /track) pdefs.ids.thick = graff_enter(jjb, /int, /all_ev, xsize = 2, value = $ 1, uvalue = 'THICK', format = "(I2)", $ label = 'Thickness:', /track) jjb = widget_base(jb, /column) ; Add a text string junk = cw_bbselector(jjb, ['Draw', 'Text'], uvalue = 'TEXT', set_value $ = 0, label_left = 'Draw/Text Mode:', /track) ; Plot a function or read data datopts = [{cw_pdmenu_s, flags:1, name:'XY data'}, $ {cw_pdmenu_s, 0, 'From file ...'}, $ {cw_pdmenu_s, 0, 'Edit values ...'}, $ {cw_pdmenu_s, 2, 'Top level variables ...'}, $ {cw_pdmenu_s, 3, 'Function'}, $ {cw_pdmenu_s, 0, 'y = f(x) ...'}, $ {cw_pdmenu_s, 0, 'x = f(y) ...'}, $ {cw_pdmenu_s, 2, 'x = f(t) & y = g(t) ...'}] junk = cw_pdtmenu(jjb, datopts, /return_full_name, uvalue = 'EDITOR', $ /track) ; Message box, only put it here ; because there's some space, give it ; a UVALUE so that we can use it with ; a timer event to control the autosave pdefs.ids.message = graff_enter(tjb, /display, xsize = 80, ysize = 2, $ value = '', label = 'Messages:', $ uvalue = 'AUTOSAVE') tmid = pdefs.ids.message pdefs.ids.hlptxt = graff_enter(tjb, /display, xsize = 80, ysize = 1, $ value = '', label = 'Function:') widget_control, pdefs.ids.graffer, /real widget_control, pdefs.ids.draw, get_value = windex wset, windex !P.multi = 0 ; Make sure 1 plot/page !P.font = -1 ; and Hershey fonts s_colours graff_set_vals, pdefs ; Set up the values of the text ; widgets etc. widget_control, base, set_uvalue = pdefs, /no_copy widget_control, tmid, timer = 300. xmanager, 'graff', base if (keyword_set(debug)) then !Quiet = qstate ; Restore message state end