PRO qLine_Event, event

@compile_opt.pro        ; On error, return to caller

widget_control, event.top, get_uvalue=state, /no_copy

CASE event.id OF                                ; ID of widget that generated the message

event.top           : qLine_Kill, state, event      ; WIDGET_KILL_REQUEST from top level widget

state.wid_done      : qLine_Kill , state, event     ; Message from 'Done' widget


; If the draw widget needs to be redrawn (e.g, when the window size is changed,
; this is done by sending an event to state.wid_top. qLine_XBase redraws the draw
; widget; then passes the event to the state_wid_xbase widget (see below).

state.wid_top       : BEGIN

    qLine_XBase, state
    widget_control, state.wid_xbase, send_event=event

END

; If the draw widget is OK, but the curve (Y-base) widgets need to be updated
; (for instance when a new data file is read; see qLine_Read), this is done by
; sending an event to state.wid_xbase. After redrawing the widgets, the curves
; are redrawn.

state.wid_xbase     : BEGIN

    qLine_YBase, state, event
    qLine_Curve, state

END

state.wid_print     : qLine_Print, state, event
state.wid_read      : qLine_Read , state
state.wid_write     : qLine_Write, state

; After a change of window size the whole widget needs to be redrawn

state.wid_xysize[0] : widget_control, state.wid_top , send_event=qLine_Structure(state)
state.wid_xysize[1] : widget_control, state.wid_top , send_event=qLine_Structure(state)

state.wid_margin[0] : qLine_Curve, state        ; Change x-margin[0]
state.wid_margin[1] : qLine_Curve, state        ; Change x-margin[1]
state.wid_chars     : qLine_Curve, state        ; Change character size
state.wid_title     : qLine_Curve, state        ; Change main plot title

state.wid_draw      : IF qLine_FitDraw(state, event) THEN qLine_Curve, state
                                                ; Change time
state.wid_ymd       : BEGIN

    widget_control, state.wid_ymd   , set_uvalue=event.select
    widget_control, state.wid_ydoy  , set_uvalue=0, set_button=0
    widget_control, state.wid_degree, set_uvalue=replicate(BadValue(0.0),2)

    qLine_Curve, state

END

state.wid_ydoy      : BEGIN

    widget_control, state.wid_ydoy  , set_uvalue=event.select
    widget_control, state.wid_ymd   , set_uvalue=0, set_button=0
    widget_control, state.wid_degree, set_uvalue=replicate(BadValue(0.0),2)

    qLine_Curve, state

END

qLine_YAction(state.wid_sequence, event, iy): IF qLine_Sequence(state, iy) THEN qLine_Curve, state

qLine_YAction(state.wid_isx , event, iy): IF qLine_IsX (state, event, iy) THEN qLine_Curve, state

qLine_YAction(state.wid_skip, event, iy): IF qLine_Skip(state, event, iy) THEN qLine_Curve, state

qLine_YAction(state.wid_fit , event, iy): IF qLine_Fit(state, event, iy) THEN qLine_Curve, state

qLine_YAction(state.wid_newyaxis, event, iy): IF qLine_NewYAxis(state, event, iy) THEN qLine_Curve, state

qLine_YAction(state.wid_ymin   , event, iy): qLine_Curve, state

qLine_YAction(state.wid_ymax   , event, iy): qLine_Curve, state

qLine_YAction(state.wid_exact  , event, iy, /onoff): qLine_Curve, state

qLine_YAction(state.wid_ynozero, event, iy, /onoff): qLine_Curve, state

qLine_YAction(state.wid_ylog   , event, iy, /onoff): qLine_Curve, state


qLine_YAction(state.wid_use_sigma, event, iy, /onoff): qLine_Curve, state

qLine_YAction(state.wid_sigma_index, event, iy): BEGIN

    widget_control, state.wid_sigma_index[iy], get_value=sigma_index
    widget_control, state.wid_use_sigma  [iy], sensitive=sigma_index NE 0

    qLine_Curve, state

END

qLine_YAction(state.wid_linestyle, event, iy): qLine_Curve, state

qLine_YAction(state.wid_ytitle   , event, iy): qLine_Curve, state

ELSE: BEGIN
    print, 'qLine: unexpected event'
    print, tag_names(event, /structure_name)
    print, event
END

ENDCASE


IF widget_info(event.top, /valid_id) THEN   $
    widget_control, event.top, set_uvalue=state, /no_copy

RETURN  &  END





PRO qLine, group=group, x, y, use_index=use_index, isx=isx, time=time, xysize=xysize,   $
    charsize    = charsize  ,   $
    title       = title     ,   $
    xmargin     = xmargin   ,   $

    nmax        = nmax      ,   $

    sequence    = sequence  ,   $
    skip        = skip      ,   $
    newyaxis    = newyaxis  ,   $
    exact       = exact     ,   $
    ynozero     = ynozero   ,   $
    ylog        = ylog      ,   $
    linestyle   = linestyle ,   $
    ytitle      = ytitle    ,   $
    use_sigma   = use_sigma ,   $
    sigma_index = sigma_index,  $
    plotstr     = plotstr   ,   $
    yrange      = yrange

@compile_opt.pro        ; On error, return to caller

InitVar, nmax, 10
InitVar, use_index, /key

state = {STATE_QPLOT,           $
    wid_top         : 0L,           $
    wid_done        : 0L,           $
    wid_print       : 0L,           $
    wid_read        : 0L,           $
    wid_write       : 0L,           $

    wid_xysize      : [0L,0L],      $
    wid_margin      : [0L,0L],      $
    wid_chars       : 0L,           $
    wid_title       : 0L,           $

    wid_ymd         : 0L,           $
    wid_ydoy        : 0L,           $
    wid_degree      : 0L,           $
    wid_scalefit    : 0L,           $
    wid_badvalue    : 0L,           $

    wid_xbase       : 0L,           $
    wid_ybase       : 0L,           $
    wid_draw        : 0L,           $

    wid_sequence    : lonarr(nmax), $
    wid_isx         : lonarr(nmax), $
    wid_ymin        : lonarr(nmax), $
    wid_ymax        : lonarr(nmax), $

    wid_skip        : lonarr(nmax), $
    wid_newyaxis    : lonarr(nmax), $

    wid_exact       : lonarr(nmax), $
    wid_ynozero     : lonarr(nmax), $
    wid_ylog        : lonarr(nmax), $
    wid_linestyle   : lonarr(nmax), $

    wid_ytitle      : lonarr(nmax), $
    wid_use_sigma   : lonarr(nmax), $
    wid_fit         : lonarr(nmax), $

    wid_sigma_index : lonarr(nmax), $

    nmax            : nmax,         $
    n               : 0,            $
    y               : ptr_new(/allocate_heap),  $
    t               : ptr_new(/allocate_heap),  $
    plotstr         : ptr_new(/allocate_heap)   $
}

IF IsTime(time) THEN (*state.t) = time
IF IsType(plotstr, /defined) THEN (*state.plotstr) = plotstr

InitVar, xysize  , [600, 360]
InitVar, xmargin , [ 10,   5]
InitVar, charsize, 1.0

CASE IsType(x, /defined) OR use_index OF
0: n_curves = 0
1: BEGIN
    sz = size(x)

    n_points = sz[sz[0]]                ; Last dimension of x
    n_curves = sz[sz[0]+2]/n_points

    yy = reform(x, n_curves, n_points)

    CASE use_index OF
    0: IF IsType(y,/defined) THEN yy = [yy, reform(y, n_elements(y)/n_points, n_points)]
    1: IF use_index THEN yy = [reform(lindgen(n_points),1,n_points),reform(x, n_elements(x)/n_points, n_points)]
    ENDCASE

    n_curves = n_elements(yy)/n_points
    *state.y = yy
END
ENDCASE

InitVar, isx, 0
isx = (isx > 0) < (n_curves-1)

state.n = n_curves

base = widget_base(title='qLine', /column, /tlb_kill_request)

state.wid_top = widget_base(base, /column)

    dummy = widget_base(state.wid_top, /row)
        state.wid_done  = widget_button(dummy, value=filepath(root=getenv('SSW_SMEI_UCSD'),subdir='image','done.ico'),/bitmap)
        state.wid_print = widget_button(dummy, value='Print')
        state.wid_read  = widget_button(dummy, value='Read')
        state.wid_write = widget_button(dummy, value='Write')

        state.wid_xysize[0] = cw_field(dummy, value=xysize[0], /integer, title='size', /row, xsize=3, /return_ev)
        state.wid_xysize[1] = cw_field(dummy, value=xysize[1], /integer, title='x'   , /row, xsize=3, /return_ev)

        state.wid_margin[0] = cw_field(dummy, value=xmargin[0], /integer, title='margin', /row, xsize=3, /return_ev)
        state.wid_margin[1] = cw_field(dummy, value=xmargin[1], /integer, title='--',     /row, xsize=3, /return_ev)

        state.wid_chars = cw_field(dummy, value=charsize, /float , title='charsize', /row, xsize=2 , /return_ev)
        state.wid_title = cw_field(dummy, value=title   , /string, title='title'   , /row, xsize=20, /return_ev)

; If curve data are available, then complete the widget before realizing it.

IF n_curves NE 0 THEN BEGIN

    ; 'base' is the id of the base widget. This is used as the parent.
    ; 'xysize' is the size of the draw widget, and needs to be specified explicitly even though the values have
    ;   already been stored in the value fields of state.wid_xysize (these values apparently become accessible only
    ;   after the widget has been realized??)

    qLine_XBase, state, xysize=xysize

    ; Set up a structure with all information about the curves.
    ; The /noplot keyword suppresses a call to qLine_Curve (plotting can be done only after realizing the widget??)

    sequence = indgen(n_curves)

    ymin = fltarr(n_curves)
    FOR i=0,n_curves-1 DO ymin[i] = min(yy[i,*], /nan)
    ymax = fltarr(n_curves)
    FOR i=0,n_curves-1 DO ymax[i] = max(yy[i,*], /nan)

    IF IsType(yrange,/defined) THEN BEGIN
        n = n_elements(yrange)/2
        ymin[0:n-1] = yrange[0,*]
        ymax[0:n-1] = yrange[1,*]
    ENDIF

    event = qLine_Structure(isx=isx, nmax=state.nmax, sequence=sequence,        $
            ymin=ymin, ymax=ymax, exact=exact, ynozero=ynozero, ylog=ylog,      $
            newyaxis=newyaxis, skip=skip, linestyle=linestyle, ytitle=ytitle,   $
            use_sigma=use_sigma, sigma_index=sigma_index)

    qLine_YBase, state, event

ENDIF

widget_control, base, set_uvalue=state, no_copy=n_curves EQ 0
widget_control, base, /realize

; Now that the widget is realized we can plot the curves

IF n_curves NE 0 THEN qLine_Curve, state

xmanager, 'qLine', base, group=Group, /no_block, event_handler='qLine_Event'

RETURN  &  END