Viewing contents of file '../idllib/contrib/tappin/graffer/graffer.pro'
;+
; 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.
;	compact		input	0: Use the standard full-size layout
;				1: Use the compact overlayed layout
;				Not set: Use the full-sized layout if
;				it will fit on the screen, but use the
;				comapct form if it won't.
;	pop_menus	input	If set, then popup menus will spring
;				to the front every 2 seconds.
;
; History:
;	Original: 27/7/95; SJT
;		V2.00 - Start knocking ideas around, (1) break up the
;                       xsty and ysty tags of pdefs (which are horribly
;                       overloaded in V1.05) into structures.
;                       (2) Reform file into a TAG:VALUE format for
;                       greater flexibility.
;                     - Increase error bar possibilities
;                     - Upgrade function fitting routines
;                     - Rename some routines so that the first 8 chars
;                       are unique (for small-minded systems that only
;                       allow 8.3 filenames).
;                     - Add settings for POSITION (a precursor to
;                       multiple plots on one page?)
;                     - Start to farm out menu panels to procedures in
;                       order to facilitate keeping the standard &
;                       compact versions in step.
;                     - More farming out of bits of the menus
;                     - Modify compact format to put the graphics
;                       window in an independent base (suggestion from
;                       Phil Williams [Children's Hospital Medical
;                       Center, Cincinnati OH]) -- reviving the
;                       original intention of the compact mode.
;                     - Add support for 2-D datasets. Functions F(x,y)
;                       and Z datasets. Display by contours or as an
;                       "image". Also add options to re-order the
;                       datasets, and to write them to a file.
;                     - Add "resource='Graffer'" to all top-level
;                       widgets.
;		      - Make the colour selector in the text-editor
;                       widget into a pull-down like the one on the
;                       dataset menu.
;                     - Major improvements to PostScript options
;                       settings to allow offsets to be adjusted.
;		      - Add an on-line help system
;                     - Extensive changes to popups so that cancelled
;                       operations don't trigger redrawing or set the
;                       changed flag.
;                     - Add options to allow a dataset to be plotted
;                       "Unclipped"
;                     - Display index of current dataset as well as
;                       descriptor.
;                     - Add tracking events to the message box so that
;                       taking the cursor out of it clears the message.
;                     - Add support for Binary GRAFFER files and make
;                       autosave files always binary.
;                     - Improve file handling in several ways:
;                          1) Check if the agument to GRAFFER is a
;                             directory and if so then use it as a
;                             path in the picker.
;                          2) Don't try to find files in a
;                             non-existent or unscannable directory.
;                          3) Put up a prompt when "Save as" or "Open
;                             new" attempt to overwrite an existing
;                             file.
;                     - Solved problem of setting values in a "Stated"
;                       pulldown for the axis style settings. I think
;                       they now reflect correctly the settings of the
;                       current file.
;                     - Add code to allow draw window to popup as soon
;                       as it is entered in compact mode. Also force
;                       the two windows to be reasonably
;                       well-separated (>125 pixels if possible).
;                     - Start to move some of the event handling
;                       routines out.
;                     - Separate definition of symbol from joining
;                       method and provide extra symbols.
;                     - Move the restoration of the plot state to a
;                       "KILL_NOTIFY" procedure (keep the state in
;                       common block - not ideal). Also make the two
;                       windows of compact mode mutually destroy each
;                       other.
;                     - Make the generation code of GRAFFER into
;                       GRAFFER_ONE, thus eliminating a goto and
;                       saving some code duplication. Actually
;                       implement the GROUP key which always existed
;                       but doesn't appear to have been implemented.
;                     - Add new dataset property to define mouse
;                       editability (so that it is possible to shut
;                       out the possibility of accidentally changing a
;                       data set). Move that along with sorting &
;                       clipping into a "Extras" pulldown in the
;                       dataset menus. Also make the dataset selection
;                       menus into a 1-liner.
;                     - Modify fit dataset to make it safer and to
;                       return to "system" versions of routines.
;                     - Add a "changed" indicator in a suitable bit of
;                       unused space.
;                     - Fix compact mode event generation so that the
;                       menu panel auto-exposes properly?
;                     - Add a system for putting a key on the
;                       plot. Also in the process invent "Frame"
;                       coordinates (like normalized but measured
;                       relative to the corners of the axis box rather
;                       than the viewport). Make this system available
;                       for anchoring text as well.
;                     - Add "piecewise linear" fits to the "Fit
;                       dataset" options.
;                     - Add a CAPTURE_INPUT key to GRAFF_ENTER and use
;                       it in most input situations.
;                     - Extensive reconstruction of GR_PICKFILE to
;                       make it look & feel more like the rest of GRAFFER.
;                     - Improve the autosave facility in several ways:
;                        - Big operations (e.g. editing a dataset)
;                          count as more than one operation.
;                        - The handling of the files if improved so
;                          that a prompt is given if the requested
;                          operation isn't what GRAFFER thinks you
;                          should do.
;                        - The flagging of deleting the autosave file
;                          is fixed.
;		      - Add new key option.
;		      - Fix problem with unidentified tags in binary
;                       files.
;		Version 2.01:
;		      - Add space for a general comment on the plot.
;		      - Add GRAFF_PROPS to allow programs to set
;                       global values (e.g. axis ranges, titles etc.)
;		Version 2.02:
;		      - Make Ndata fields LONG.
;		      - Modify file picker to prevent duplicated
;                       directory name being returned in some cases.
;-

pro Graff_event, event


base = widget_info(/child, event.top)
widget_control, base, get_uvalue = pdefs, /no_copy

sp = size(pdefs)
if (sp(sp(0)+1) eq 3) then begin
    widget_control, base, set_uvalue = pdefs
    base = widget_info(/child, pdefs)
    widget_control, base, get_uvalue = pdefs, /no_copy
end else if (sp(sp(0)+1) ne 8) then begin
    message, /continue, "** O U C H ** Corrupted internal data - " + $
      "bailing out"
    widget_control, event.top, /destroy
    return
endif

if (base ne event.id) then widget_control, event.id, get_uvalue = object $ 
else object = 'SHOWC'

idraw_flag = 1
ichange = 1b
track_flag = strpos(tag_names(event, /struct), 'TRACK') ne -1
nch = 1

if (track_flag) then begin
    idraw_flag = 0
    ichange = 0b
    
    if (event.enter eq 0) then begin
        graff_msg, pdefs.ids.hlptxt, ''
        case object of          ; Special actions for exit events
            'AUTOSAVE': graff_msg, pdefs.ids.message, ''
            'SHOWC': pdefs.transient.showid = pdefs.ids.graffer2
            'SHOWD': pdefs.transient.showid = pdefs.ids.graffer
            Else:
        endcase
        goto, miss_case
    endif
endif

case object of
    'SHOWC': if (pdefs.transient.showid eq event.top) then begin
        widget_control, event.top, /show
        pdefs.transient.showid= 0l
        idraw_flag = 0
        ichange = 0b
    endif
    'SHOWD': if (pdefs.transient.showid eq event.top) then begin
        widget_control, event.top, /show
        pdefs.transient.showid = 0l
        idraw_flag = 0
        ichange = 0b
    endif
    
        
    '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 = pdefs.key.use
;        if (event.cr) then grf_focus_enter, pdefs.ids.symsize
    end
        
    'TEXT': if (track_flag) then begin
        graff_msg, pdefs.ids.hlptxt, 'Toggle between drawing and text ' + $
          'modes'
    endif else begin
        gr_td_mode, event.value, pdefs
        ichange = 0b
        idraw_flag = 0b
    end    
    
    'QSAVE': if (track_flag) then $
      graff_msg, pdefs.ids.hlptxt, 'Save plot to currently selected ' + $
      'filename in binary form' $
    else begin
        gr_bin_save, pdefs
        ichange = 0b
        idraw_flag = 0
    end
    
    'DRAW': begin               ; Draw widget in graph mode
        if (track_flag and $
            widget_info(pdefs.ids.graffer2, /valid) and  $
            pdefs.transient.showid eq event.top) then begin
            widget_control, event.top, /show
            pdefs.transient.showid = 0l
        endif
        ichange = graff_draw(pdefs, event, track_flag)
        idraw_flag = ichange
        if (ichange) then nch = 21
    end
    
    'WRITE': begin              ; Draw widget in text mode
        if (track_flag and $
            widget_info(pdefs.ids.graffer2, /valid) and  $
            pdefs.transient.showid eq event.top) then begin
            widget_control, event.top, /show
            pdefs.transient.showid = 0l
        endif
        ichange = graff_write(pdefs, event, track_flag)
        idraw_flag = ichange
        if (ichange) then nch = 21
    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': if (not track_flag) then begin
        gr_bin_save, pdefs, /auto
        ichange = 0b
        idraw_flag = 0
        widget_control, event.id, timer = pdefs.opts.auto_delay
    end
    
    Else: begin
        graff_msg, pdefs.ids.message, 'Unknown UVALUE: '+object
        help, /structure, event
        ichange = 0b
        idraw_flag = 0
    end
endcase

if (idraw_flag and (pdefs.opts.update eq 0)) then gr_plot_object, pdefs
if (ichange) then begin
    pdefs.chflag = 1b
    pdefs.transient.changes = pdefs.transient.changes+nch
    if (pdefs.transient.changes gt 20) then begin
        gr_bin_save, pdefs, /auto
        if (pdefs.opts.update eq 1) then gr_plot_object, pdefs
    endif
endif
widget_control, pdefs.ids.chtick, map = pdefs.chflag

Miss_case:

widget_control, base, set_uvalue = pdefs, /no_copy

end


pro Graffer, file, group=group, xsize=xsize, ysize=ysize, debug=debug, $
             recover=recover, compact=compact, pop_menus=pop_menus

common Gr_psym_maps, psym_bm
common Gr_entry_state, pstate, xstate, ystate, zstate, qstate, rstate, $
  gstate, bstate, gdstate


if ((!D.flags and 65536) eq 0) then begin
    print, "GRAFFER needs widgets; current device (", !D.name, $
      ") does not support them."
    return
endif


    
;	Save the plotting system variables
    
gdstate = !D.name
pstate = !P
xstate = !X
ystate = !Y
zstate = !Z                     ; Not touched at present in graffer
                                ; but if & when GRAFFER for surfaces is
                                ; done then it may be
tvlct, rstate, gstate, bstate, /get
qstate = !Quiet
    

if (keyword_set(debug)) then begin
    !Quiet = 0 
    on_error, 0                 ; stop at error
endif else on_error, 2          ; Return to caller on error
    
!P.multi = 0                    ; Clear plot positioning settings.
!P.region = 0
!P.position = 0
!P.font = -1

if (n_elements(file) eq 0) then $
  file = gr_pickfile(/read, filter = '*.grf', $
                     title = 'Graffer Select') $
else if (gr_isadir(file)) then begin
    file = gr_get_full_dir(file)
    file = gr_pickfile(/read, filter = '*.grf', $
                       title = 'Graffer Select', path = file)
endif else if ((strpos(file, '*') > strpos(file, '?')) ne -1) then begin
    f = file
    gr_split_dir, f, dir
    dir = gr_get_full_dir(dir)
    file = gr_pickfile(/read, filter = f, title = 'Graffer Select', $
                       path = dir)
endif

if (file eq '') then return

;	Define the data control structure

version = [2, 02]

graff_init, pdefs, file, version = version

pdefs.popflag = keyword_set(pop_menus)

igot = graff_get(pdefs, file, /no_set, recover = recover, /no_warn)

gr_disp_man, /initialize  ; Initialize the online help system

;	If the screen is too small for the whole widget, or if the
;	user has explicitly asked for a compact plot widget, then use
;	the GRAFFER_TWO procedure to define the layout (N.B. This
;	still uses the same handler which has been compiled here.)

device, get_screen_size = scrs

if (n_elements(compact) eq 0) then  $
  compact = scrs(0) lt 1000 or scrs(1) lt 900

Start_make:

if (compact) then $
  graff_two, pdefs, base, group = group, xsize = xsize, ysize = ysize $
else begin
    graff_one, pdefs, base, group = group, xsize = xsize, ysize = ysize
    
                                ; Make sure it does actually fit.
    
    widget_control, pdefs.ids.graffer, tlb_get_size = grsize
    if (grsize(0) gt scrs(0)-30 or $
        grsize(1) gt scrs(1)-40) then begin 
        compact = 1
        goto, start_make
    endif
endelse

; gr_check_box, pdefs.ids.chtick

widget_control, pdefs.ids.draw, get_value = windex
wset, windex
pdefs.ids.windex = windex

graff_colours, pdefs

graff_set_vals, pdefs           ; Set up the values of the text
                                ; widgets etc.

tmid = pdefs.ids.message

auto_delay = pdefs.opts.auto_delay

widget_control, base, set_uvalue = pdefs, /no_copy

widget_control, tmid, timer = auto_delay

xmanager, 'graff', base

end