;+
; NAME:
;	SMEI_SEQUENCE::SHOW
;
;
; PURPOSE:
;	Show a sequence of SMEI images, better version.
;
;
; CATEGORY:
;	SMEI_SEQUENCE
;
;
; CALLING SEQUENCE:
;	seqref->show[, image]
;
;
; OPTIONAL INPUTS:
;	image	int	The location of a single image to select. If
;			this is specified then that image will be the
;			first shown and the movie will be started in a
;			paused state.
;
;
; KEYWORD PARAMETERS:
;	delay	float	The wait between images
;	group	long	Widget ID of a group leader for the widget.
;
;
; MODIFICATION HISTORY:
;	Original: 11/12/02; SJT
;	Add image argument and send drag events from the slider:
;	19/12/02; SJT
;	Add reverse play and hiding options: 15/1/03; SJT
;	Handle 3-state grid setting: 17/6/03; SJT
;	Add ability to use a wheelmouse to scroll though a movie:
;	19/6/03; SJT
;	Extend wheel mouse to mark mode and flag mark mode with a
;	different cursor: 2/7/03; SJT
;	Rationalize and fix updates on option changes: 6/8/04; SJT
;	Add blinking capability im mark mode: 6/8/04; SJT
;	Print location stats on ctrl or shift click: 15/9/04; SJT
;	Add 3-state date settings: 3/6/05; SJT
;	Add support for masking flags: 23/10/07; SJT
;	Handle systems where wheel events are distinct from button
;	events: 10/12/07; SJT
;	Only show the masking option if it's applicable: 25/1/08; SJT
;	Added support for shifted rectangular maps: 23/11/09; SJT
;	Add keyboard events (only forward & back arrows so far):
;	26/5/10; SJT
;	Add control to enable/disable wrapping of scrolling at the
;	ends of the sequence: 20/7/10; SJT
;	Add support for showing the marked points and for tracing a
;	leading edge: 20/8/20; SJT
;	Add decimation to trace marking: 24/8/10; SJT
;	Space bar to stop/start: 18/10/11; SJT
;-

pro ss_add_controls, conbase, state

linear = !d.x_size ge 720

if linear then begin
    lf = string(10b)            ; A line feed
    jb = widget_base(conbase, $
                     /row)
    jbb = jb

    state.markbut = widget_button(jb, $
                                  value = 'Mark'+lf+'points', $
                                  uvalue = 'LOCATE')

    junk = widget_button(jb, $
                         value = 'Print', $
                         uvalue = 'PRINT')

    junk = widget_button(jb, $
                         value = 'Dump'+lf+'PNG', $
                         uvalue = 'PNG')

    state.hdrbut = widget_button(jb, $
                                 value = 'Show'+lf+'Header', $
                                 uvalue = 'HEADER', $
                                 sensitive = state.image -> get_header(/test))
endif else begin
    lf = ' '
    jb = widget_base(conbase, $
                     /col, $
                     /base_align_right)
endelse

nb = widget_base(jb, $
                 /row, $
                 /frame)

if state.original -> get_count() gt 1 then begin
    junk = widget_button(nb, $
                         value = '<<', $
                         uvalue = 'REVERSE')

    junk = widget_button(nb, $
                         value = '<-', $
                         uvalue = 'FIRST')

    junk = widget_button(nb, $
                         value = '<', $
                         uvalue = 'PREV')

    state.islide = widget_slider(nb, $
                                 minimum = 1, $
                                 maximum = state.original -> get_count(), $
                                 value = state.current+1, $
                                 uvalue = 'CHOOSE', $
                                 xsize = 150, $
                                 /drag)

    junk = widget_button(nb, $
                         value = '>', $
                         uvalue = 'NEXT')

    junk = widget_button(nb, $
                         value = '->', $
                         uvalue = 'LAST')

    junk = widget_button(nb, $
                         value = '>>', $
                         uvalue = 'PLAY')

    junk = widget_droplist(nb, $
                           title = 'End wrap', $
                           value = ["Off", "On"], $
                           uvalue = "WRAP")
    widget_control, junk, set_droplist_select = state.original -> get_roll()
endif

if ~linear then begin
    jbb = widget_base(jb, $
                     /row)
    state.markbut = widget_button(jbb, $
                                  value = 'Mark'+lf+'points', $
                                  uvalue = 'LOCATE')

    junk = widget_button(jbb, $
                         value = 'Print', $
                         uvalue = 'PRINT')

    junk = widget_button(jbb, $
                         value = 'Dump'+lf+'PNG', $
                         uvalue = 'PNG')

    state.hdrbut = widget_button(jbb, $
                                 value = 'Show'+lf+'Header', $
                                 uvalue = 'HEADER', $
                                 sensitive = state.image -> get_header(/test))
endif

state.hidid = widget_button(jbb, $
                            value = ' Hide ', $
                            uvalue = 'HIDE')

junk = widget_button(jbb, $
                     value = 'Show'+lf+'all', $
                     uvalue = 'SHOWALL')

junk = widget_button(jbb, $
                     value = 'Quit', $
                     uvalue = 'QUIT')

state.cbase = jb

end


pro ss_show_event, event

;	Event handler for widget-based show tool.

sbase =  widget_info(event.top, /child)
widget_control, sbase, get_uvalue = state
widget_control, event.id, get_uvalue = mnu

udflag = 0b

case mnu of
    "CANVAS": if (tag_names(event, /structure_name) eq $
                  'WIDGET_TIMER') then begin
        if state.sflag then begin ; Show next image
            repeat begin
                if state.direct gt 0 then begin
                    state.image = state.image -> get_next()
                    state.current = state.current+1
                    if not obj_valid(state.image) then begin
                        state.image = state.original -> get_first()
                        state.current = 0l
                    endif
                endif else begin
                    state.image = state.image -> get_prev()
                    state.current = state.current-1
                    if not obj_valid(state.image) then begin
                        state.image = state.original -> get_last()
                        state.current = state.original ->  $
                                        get_count()-1
                    endif
                endelse
            endrep until not state.image -> get_pflags(/skip) 
            state.image -> show, /nosave

            widget_control, event.id, timer = state.original -> get_delay()
        endif else if state.bflag then begin ; Flicker images
            if state.ashow then state.image -> show, /nosave $
            else state.alternate -> show, /nosave
            state.ashow xor= 1b
            widget_control, event.id, timer = state.original -> get_delay()
        endif 
    endif else if state.locmode eq 1 then begin ; locmode == 1 is the
                                ; point marking mode
        case event.type of
            0: begin
                acode = event.press ; 0=Mouse button press
                if state.loc_trace && acode eq 1 then begin
                    widget_control, event.id, /draw_motion_events
                    state.loc_count = 0
                endif
                iprint = 1
            end
            1: begin            ; Only disables trace mode
                if  state.loc_trace && event.release eq 1then $
                  widget_control, event.id, draw_motion_events = 0
                return
            end
            2: begin
                state.loc_count++
                if state.loc_count mod state.loc_decimate ne 0 then $
                  begin
                    widget_control, sbase, set_uvalue = state
                    return
                endif
                acode = 1
                iprint = 0
            end
            7: begin            ; 7=Wheel (acode
                                ; 8 & 16, correspond to the old
                                ; interpretation of wheel events as
                                ; buttons 4 & 5)
                if event.clicks gt 0 then acode = 8 $
                else acode = 16
            end
            6: begin            ; 6=Non-character key
                if event.release then return ; only do press events
                case event.key of
                    5: acode = 8 ; Back
                    6: acode = 16 ;Forward
                    else: return
                endcase
            end
            else: return
        endcase

        ismod = (event.modifiers and 3) ne 0 ; Control or shift
        case acode of
            1: begin            ; Mark a point
                state.bflag = 0b
                state.ashow = 0b
                loc = state.image -> get_locate(event.x, event.y, $
                                                print = iprint)
                if ptr_valid(state.loclist) then *state.loclist = $
                  [*state.loclist, loc] $
                else state.loclist = ptr_new(loc)
                if state.loc_mark ne 0 then plots, /dev, event.x, $
                  event.y, psym = state.loc_mark
            end
            2: begin            ; Suspend mark mode
                state.bflag = 0b
                state.ashow = 0b
                state.locmode = 0
                device, cursor_standard = 34 ; Standard X cursor
                widget_control, state.markbut, /sensitive
            end
            4: begin            ; Exit mark mode
                state.bflag = 0b
                state.ashow = 0b
                if ptr_valid(state.loclist) then $
                  state.original -> vmain, *state.loclist, default = $
                    'points', group = event.top
                state.locmode = 0
                device, cursor_standard = 34 ; Standard X cursor
                widget_control, state.markbut, /sensitive
                ptr_free, state.loclist
            end
            16: if ismod then begin ; Flicker with next image
                if state.original -> get_count() eq 1 then return
                state.alternate = state.image -> get_next()
                if not obj_valid(state.alternate) then begin
                    smei_msg, /alert, "This is the final image, using " + $
                              "previous not next"
                    state.alternate = state.image -> get_prev()
                endif
                state.bflag = 1b
                widget_control, event.id, timer = 0
            endif else begin    ; Advance to next image
                state.bflag = 0b
                state.ashow = 0b
                repeat begin
                    state.image = state.image -> get_next()
                    state.current = state.current+1
                    if not obj_valid(state.image) then begin
                        if ~state.original -> get_roll() then begin
                            state.image = state.original -> $
                              get_last(/noskip, index = index) 
                            state.current = index
                            break
                        endif
                        state.image = state.original -> get_first()
                        state.current = 0
                    endif
                endrep until not state.image -> get_pflags(/skip) 
                udflag = 1b
            end
            8: if ismod then begin ; Flicker with previous image
                if state.original -> get_count() eq 1 then return
                state.alternate = state.image -> get_prev()
                if not obj_valid(state.alternate) then begin
                    smei_msg, /alert, "This is the first image, using " + $
                              "next not previous"
                    state.alternate = state.image -> get_next()
                endif
                state.bflag = 1b
                widget_control, event.id, timer = 0
            endif else  begin   ; Go back to previous image
                state.bflag = 0b
                state.ashow = 0b
                repeat begin
                   state.image = state.image -> get_prev()
                    state.current = state.current-1
                    if not obj_valid(state.image) then begin
                        if ~state.original -> get_roll() then begin
                            state.image = state.original -> $
                              get_first(/noskip, index = index) 
                            state.current = index
                            break
                        endif
                        state.image = state.original -> get_last()
                        state.current = state.original -> get_count() - 1
                    endif
                endrep until not state.image -> get_pflags(/skip)
                udflag = 1b
            end
        endcase
    endif else begin            ; Normal display mode.
        case event.type of
            0: acode = event.press ; 0=Mouse button press
            7:  begin           ; 7=Wheel
                if event.clicks gt 0 then acode = 8 $
                else acode = 16
            end
            6: begin            ; 6=Non-character key
                if event.press then return ; only do release events
                                ; (some non char keys don't make a
                                ; press event, others do)
                case event.key of
                    5: acode = 8 ; Back
                    6: acode = 16 ;Forward
                    7: acode = 32 ; Up
                    8: acode = 64 ; Down
                    9: acode = 32 ; Page up=first
                    10: acode = 64 ; page down=last
                    else: return
                endcase
            end
            5: begin            ; Character key (only use space)
                if event.ch ne 32b || event.release eq 1b then return
                if state.sflag then begin
                    widget_control, state.paws, set_value = 'Resume'
                    state.sflag = 0b
                    ss_add_controls, sbase, state
                endif else begin
                    widget_control, state.paws, set_value = 'Pause'
                    state.sflag = 1b
                    widget_control, state.cbase, /destroy
                    state.cbase = 0l
                    state.islide = 0l
                    state.markbut = 0l
                    state.bflag = 0b
                    state.ashow = 0b
                    state.locmode = 0
                    device, cursor_standard = 34 ; Standard X cursor
                    widget_control, state.canvas, timer = 0
                endelse
                goto, tailpiece ; Only way to jump out of a case
            end
            else: return
        endcase
        ismod = (event.modifiers and 3) ne 0 ; Control or shift
        case acode of
            4: widget_displaycontextmenu, event.id, event.x, $
              event.y, state.context  
            16: if not state.sflag then begin ; Go to next unhidden
                                ; image if in paused state
                repeat begin
                    state.image = state.image -> get_next()
                    state.current = state.current+1
                    if not obj_valid(state.image) then begin
                        if ~state.original -> get_roll() then begin
                            state.image = state.original -> $
                              get_last(/noskip, index = index) 
                            state.current = index
                            break
                        endif
                        state.image = state.original -> get_first()
                        state.current = 0
                    endif
                endrep until not state.image -> get_pflags(/skip)
                udflag = 1b
            end
            8: if not state.sflag then begin ;Go to previous unhidden
                                ;image if in paused state.
                repeat begin
                    state.image = state.image -> get_prev()
                    state.current = state.current-1
                    if not obj_valid(state.image) then begin
                        if ~state.original -> get_roll() then begin
                            state.image = state.original -> $
                              get_first(/noskip, index = index) 
                            state.current = index
                            break
                        endif
                        state.image = state.original -> get_last()
                        state.current = state.original -> get_count() - 1
                    endif
                endrep until not state.image -> get_pflags(/skip)
                udflag = 1b
            end 
            2: if not state.sflag then begin ; Show zoomed area
                                ; around the click location (if paused)
                if widget_info(/valid, state.zoombase) then $
                  junk = show_zoomed(!d.window, event.x, event.y, $
                                     group = event.top, base = $
                                     state.zoombase) $
                else $
                  state.zoombase = show_zoomed(!d.window, event.x, $
                                               event.y, $ 
                                               group = event.top)
            endif

            1: if (event.modifiers and 3) ne 0 and not state.sflag then $
              junk = state.image -> get_locate(event.x, event.y, /print)

            32: begin           ; Go to first image (page-up key)
                state.image = state.original -> get_first()
                state.current = 0
                udflag = 1b
            end
            64: begin           ; Got last image (page down)
                state.image = state.original -> get_last()
                state.current = state.original -> get_count() - 1
                udflag = 1b
            end

            else:               ; Ignore releases
        endcase
    endelse
    
    "COLOUR": begin
        state.original -> set_colour_map, /menu, $
          group = event.top, redraw = redraw
        if redraw then udflag = 1b
    end
    "PAUSE": if state.sflag then begin
        widget_control, state.paws, set_value = 'Resume'
        state.sflag = 0b
        ss_add_controls, sbase, state
    endif else begin
        widget_control, state.paws, set_value = 'Pause'
        state.sflag = 1b
        widget_control, state.cbase, /destroy
        state.cbase = 0l
        state.islide = 0l
        state.markbut = 0l
        state.bflag = 0b
        state.ashow = 0b
        state.locmode = 0
        device, cursor_standard = 34 ; Standard X cursor
        widget_control, state.canvas, timer = 0
    endelse

    'PLAY': begin
        state.sflag = 1b
        state.direct = 1
        widget_control, state.cbase, /destroy
        widget_control, state.rev, set_value = 'Reverse'
        state.cbase = 0l
        state.islide = 0l
        state.bflag = 0b
        state.ashow = 0b
        state.locmode = 0
        state.markbut = 0l
        device, cursor_standard = 34 ; Standard X cursor
        widget_control, state.paws, set_value = 'Pause'
        widget_control, state.canvas, timer = 0
    end
    'REVERSE': begin
        state.sflag = 1b
        state.direct = -1
        widget_control, state.cbase, /destroy
        widget_control, state.rev, set_value = 'Forwards'
        state.cbase = 0l
        state.islide = 0l
        state.markbut = 0l
        state.bflag = 0b
        state.ashow = 0b
        state.locmode = 0
        device, cursor_standard = 34 ; Standard X cursor
        widget_control, state.paws, set_value = 'Pause'
        widget_control, state.canvas, timer = 0
    end

    'SWITCH': begin
        state.direct = -state.direct
        widget_control, state.rev, set_value = $
                        (['Reverse', 'Forwards'])[state.direct lt 0]
        if not state.sflag then begin
            state.sflag = 1b
            widget_control, state.cbase, /destroy
            state.cbase = 0l
            state.islide = 0l
            state.markbut = 0l
            state.bflag = 0b
            state.ashow = 0b
            state.locmode = 0
            device, cursor_standard = 34 ; Standard X cursor
            widget_control, state.paws, set_value = 'Pause'
            widget_control, state.canvas, timer = 0
        endif
    end
    
    'FAST': state.original -> set_delay, state.original -> get_delay()/2.
    'SLOW': state.original -> set_delay, state.original -> get_delay()*2.

    "NEXT": begin
        state.image = state.image -> get_next()
        state.current = state.current+1
        if not obj_valid(state.image) then begin
            if ~state.original -> get_roll() then begin
                state.image = state.original -> get_last()
                state.current--
            endif else begin
                state.image = state.original -> get_first()
                state.current = 0
            endelse
        endif
        udflag = 1b
    end
    "PREV": begin
        state.image = state.image -> get_prev()
        state.current = state.current-1
        if not obj_valid(state.image) then begin
            if ~state.original -> get_roll() then begin
                state.image = state.original -> get_first()
                state.current = 0
            endif else begin
                state.image = state.original -> get_last()
                state.current = state.original -> get_count() - 1
            endelse
        endif
        udflag = 1b
    end
    "FIRST": begin
        state.image = state.original -> get_first()
        state.current = 0
        udflag = 1b
    end
    "LAST": begin
        state.image = state.original -> get_last()
        state.current = state.original -> get_count() - 1
        udflag = 1b
    end
    
    'CHOOSE': if event.value-1 ne state.current then begin
        state.image = state.original -> get_image(event.value-1)
        state.current = event.value-1
        udflag = 1b
    end

    'WRAP': state.original -> set_roll, event.index

    'GRID0': begin
        igrid = state.original -> get_annotations(/grid)
        if igrid ne 0 then begin
            widget_control, state.gb[igrid], sensitive = 1
            state.original -> set_annotations, grid = 0
            widget_control, state.gb[0], sensitive = 0
            udflag = 1b
        endif
    end
    
    'GRID1':  begin
        igrid = state.original -> get_annotations(/grid)
        if igrid ne 1 then begin
            widget_control, state.gb[igrid], sensitive = 1
            state.original -> set_annotations, grid = 1
            widget_control, state.gb[1], sensitive = 0
            udflag = 1b
        endif
    end

    'GRID2':  begin
        igrid = state.original -> get_annotations(/grid)
        if igrid ne 2 then begin
            widget_control, state.gb[igrid], sensitive = 1
            state.original -> set_annotations, grid = 2
            widget_control, state.gb[2], sensitive = 0
            udflag = 1b
        endif
    end

    'GRID3':  begin
        igrid = state.original -> get_annotations(/grid)
        if igrid ne 3 then begin
            widget_control, state.gb[igrid], sensitive = 1
            state.original -> set_annotations, grid = 3
            widget_control, state.gb[3], sensitive = 0
            udflag = 1b
        endif
    end

    'GRID4':  begin
        igrid = state.original -> get_annotations(/grid)
        if igrid ne 4 then begin
            widget_control, state.gb[igrid], sensitive = 1
            state.original -> set_annotations, grid = 4
            widget_control, state.gb[4], sensitive = 0
            udflag = 1b
        endif
    end

    'SHIFT0': begin
        ishft = state.original -> get_shift(/raw)
        if ishft ne 0 then begin
            widget_control, state.sb[ishft], sensitive = 1
            state.original -> set_shift, 0
            widget_control, state.sb[0], sensitive = 0
            udflag = 1b
        endif
    end
    'SHIFT1': begin
        ishft = state.original -> get_shift(/raw)
        if ishft ne 1 then begin
            widget_control, state.sb[ishft], sensitive = 1
            state.original -> set_shift, 1
            widget_control, state.sb[1], sensitive = 0
            udflag = 1b
        endif
    end
    'SHIFT2': begin
        ishft = state.original -> get_shift(/raw)
        if ishft ne 2 then begin
            widget_control, state.sb[ishft], sensitive = 1
            state.original -> set_shift, 2
            widget_control, state.sb[2], sensitive = 0
            udflag = 1b
        endif
    end

    'SHIFT3': begin
        ishft = state.original -> get_shift(/raw)
        if ishft ne 3 then begin
            widget_control, state.sb[ishft], sensitive = 1
            state.original -> set_shift, 3
            widget_control, state.sb[3], sensitive = 0
            udflag = 1b
        endif
    end

    'DATE0': begin
        idate = state.original -> get_annotations(/date)
        if idate ne 0 then begin
            widget_control, state.df[idate], sensitive = 1
            state.original -> set_annotations, date = 0
            widget_control, state.df[0], sensitive = 0
            udflag = 1b
        endif
    end

    'DATE1': begin
        idate = state.original -> get_annotations(/date)
        if idate ne 1 then begin
            widget_control, state.df[idate], sensitive = 1
            state.original -> set_annotations, date = 1
            widget_control, state.df[1], sensitive = 0
            udflag = 1b
        endif
    end
    'DATE2': begin
        idate = state.original -> get_annotations(/date)
        if idate ne 2 then begin
            widget_control, state.df[idate], sensitive = 1
            state.original -> set_annotations, date = 2
            widget_control, state.df[2], sensitive = 0
            udflag = 1b
        endif
    end

    'FILE': begin
        state.original -> set_annotations, file = state.original ->  $
          get_annotations(/file) eq 0
        widget_control, event.id, $
                        set_value = (['Add filename', $
                                      'Drop filename'])(state.original->  $
                                                        get_annotations(/file))
        udflag = 1b
     end
    'IRANGE': begin
        state.original -> set_annotations, range = state.original ->  $
          get_annotations(/range) eq 0
        widget_control, event.id, $
                        set_value = (['Add range', $
                                      'Drop range'])(state.original ->  $
                                                    get_annotations(/range))
        udflag = 1b
     end
    
    'RANGE': begin
        state.original -> range_menu, group = event.top, /block
        udflag = 1b
    end

    'FLAGS': begin
        state.original -> flags_menu, group = event.top, /block
        udflag = 1b
    end

    'ZOOM': if state.original -> zoom_menu(group = event.top) then begin
        device, get_screen_size = ss
        sz = state.original -> get_biggest_image()*state.original ->  $
          get_zoom()
        if sz[0] gt 0.9*ss[0] or sz[1] gt 0.8*ss[1] then begin
            xss = 0.8*ss[0] < sz[0]
            yss = 0.75*ss[1] < sz[1]
        endif else begin
            xss = sz[0]
            yss = sz[1]
        endelse
        widget_control, state.canvas, draw_xsize = sz[0], $
          draw_ysize = sz[1], scr_xsize $
                        = xss+state.barsize[0], scr_ysize = $
                        yss+state.barsize[1]  
         udflag = 1b
     endif

    'PRINT': state.image -> print_menu, /block, group = event.top

    'PNG': begin
        pngfile = dialog_pickfile(dialog_parent = event.top, $
                                  filter = '*.png', $
                                  /overwrite_prompt, $
                                  /write)
        if pngfile ne '' then begin
            im = tvrd(true = 1)
            write_png, pngfile, im
        endif
    end

    'HEADER': state.image -> show_header, group = event.top

    'LOCATE': marker_menu, state, event.top

    'HIDE': begin
        state.image -> set_skip
        widget_control, event.id, $
                        set_value = ([' Hide ', 'Unhide']) $
                        [state.image -> get_pflags(/skip)] 
    end

    'SHOWALL': begin
        im = state.original -> get_first()
        while obj_valid(im) do begin
            im -> set_skip, 0
            im = im -> get_next()
        endwhile
    end

    "QUIT": begin
        widget_control, event.top, /destroy
        plot_env, /restore
        state.original -> set_window, state.std_window ; If we don't
                                ; do this, then trying to display an
                                ; image after exiting will crash.
    end

endcase

tailpiece:

if widget_info(/valid, sbase) then begin
    widget_control, sbase, set_uvalue = state
    if udflag then begin
        state.image -> show, /nosave
        if widget_info(/valid, state.islide) then widget_control, $
          state.islide, set_value = state.current+1
        if widget_info(/valid, state.hidid) then $
          widget_control, $
          state.hidid, set_value = $
          (['  Hide  ', 'Unhide'])[state.image ->  $
                                   get_pflags(/skip)]

        if widget_info(/valid, state.hdrbut) then $
          widget_control, state.hdrbut, sensitive = state.image ->  $
          get_header(/test)
    endif
endif

end

pro ss_show_kill, sbase

widget_control, sbase, get_uvalue = state
plot_env, /restore
state.original -> set_window, state.std_window ; If we don't
end

pro smei_sequence::show, image, delay = delay, group = group

wname = self -> get_name()
if wname eq '' then wname = "SMEI Display"

sz = self -> get_biggest_image()*self -> get_zoom()

if sz[0] eq 0 then begin
    smei_msg, /alert, "Can't show a sequence with no images"
    return
endif

if keyword_set(delay) then self -> set_delay, delay

base = widget_base(group = group, $
                   title = wname)
b1 = widget_base(base, $       ; This is mostly just to hook the state
                 /column, $     ; structure onto.
                 /base_align_left, $
                 kill_notify = 'ss_show_kill')

device, get_screen_size = ss

if sz[0] gt 0.9*ss[0] or sz[1] gt 0.8*ss[1] then begin
    xss = 0.8*ss[0] < sz[0]
    yss = 0.75*ss[1] < sz[1]
endif else begin
    xss = sz[0]
    yss = sz[1]
endelse
if float(!version.release) ge 6.2 then $
  canvas = widget_draw(b1, $
                       xsize = sz[0], $
                       ysize = sz[1], $
                       x_scroll_size = xss, $
                       y_scroll_size = yss, $
                       /scroll, $
                       uvalue = 'CANVAS', $
                       /button_events, $
                       /wheel_events, $
                       /keyboard_events) $
else canvas = widget_draw(b1, $
                          xsize = sz[0], $
                          ysize = sz[1], $
                          x_scroll_size = xss, $
                          y_scroll_size = yss, $
                          /scroll, $
                          uvalue = 'CANVAS', $
                          /button_events, $
                          /keyboard_events) 

context = widget_base(base, $
                      /context_menu)

paws = widget_button(context, $
                     value = 'Pause', $
                     uvalue = 'PAUSE')
rev = widget_button(context, $
                    value = 'Reverse', $
                    uvalue = 'SWITCH')

junk = widget_button(context, $
                     value = 'Change colours', $
                     uvalue = 'COLOUR')

junk = widget_button(context, $
                     value = 'Faster', $
                     uvalue = 'FAST')

junk = widget_button(context, $
                     value = 'Slower', $
                     uvalue = 'SLOW')

gmb = widget_button(context, $
                    value = 'Grid', $
                    menu = 2)
gb = lonarr(5)
gb[0] = widget_button(gmb, $
                      value = 'None', $
                      uvalue = 'GRID0')
gb[1] = widget_button(gmb, $
                      value = 'Lat & Long', $
                      uvalue = 'GRID1')
gb[2] = widget_button(gmb, $
                      value = 'Elong & PA', $
                      uvalue = 'GRID2')
gb[3] = widget_button(gmb, $
                      value = 'L & L (Labelled)', $
                      uvalue = 'GRID3')
gb[4] = widget_button(gmb, $
                      value = 'E & P (Labelled)', $
                      uvalue = 'GRID4')

igrid = self ->  get_annotations(/grid)
widget_control, gb[igrid], sensitive = 0

sb = lonarr(4)
if self -> get_projection() eq 2 then begin
    smb = widget_button(context, $
                       value = 'Centre', $
                       menu = 2)
    
    sb[0] = widget_button(smb, $
                         value = 'North', $
                         uvalue = 'SHIFT0')
    sb[1] = widget_button(smb, $
                         value = 'East', $
                         uvalue = 'SHIFT1')
    sb[2] = widget_button(smb, $
                         value = 'South', $
                         uvalue = 'SHIFT2')
    sb[3] = widget_button(smb, $
                         value = 'West', $
                         uvalue = 'SHIFT3')
    ishft = self -> get_shift(/raw)
    widget_control, sb[ishft], sensitive = 0
endif

dfb = widget_button(context, $
                    value = 'Date format', $
                    menu = 2)

df = lonarr(3)
df[0] = widget_button(dfb, $
                      value = 'None', $
                      uvalue = 'DATE0')
df[1] = widget_button(dfb, $
                      value = 'Year-Day', $
                      uvalue = 'DATE1')
df[2] = widget_button(dfb, $
                      value = 'Y-M-D', $
                      uvalue = 'DATE2')

idate = self -> get_annotations(/date)
widget_control, df[idate], sensitive = 0

junk = widget_button(context, $
                     value = (['Add filename', $
                               'Drop filename'])(self ->  $ $
                                                 get_annotations(/file)), $
                     uvalue = 'FILE')

junk = widget_button(context, $
                     value = (['Add range', $
                               'Drop range'])(self ->  $ $
                                              get_annotations(/range)), $
                     uvalue = 'IRANGE')

junk = widget_button(context, $
                     value = 'Adjust range...', $
                     uvalue = 'RANGE')

junk = widget_button(context, $
                     value = 'Set zoom...', $
                     uvalue = 'ZOOM')

if self -> get_pipe_level() ge 2 then $
  junk = widget_button(context, $
                       value = "Masking ...", $
                       uvalue = 'FLAGS')

junk = widget_button(context, $
                     value = 'Show all', $
                     uvalue = 'SHOWALL')

junk = widget_button(context, $
                     value = 'Quit', $
                     uvalue = 'QUIT')

widget_control, base, /real

widget_control, canvas, get_value = wid
std_window = self -> get_window()

self -> set_window, wid
wset, wid

wg = widget_info(canvas, /geometry)

bars = [wg.scr_xsize-xss, wg.scr_ysize-yss]

self -> mk_pixmap

if n_elements(image) eq 0 then begin
    im = self -> get_first()
    sflag = 1b
    current = 0
endif else begin
    im = self -> get_image(image-1)
    if not obj_valid(im) then begin
        smei_msg, /alert, ['The requested image could not be ' + $
                           'accessed', $
                           'Using first image']
        im = self -> get_first()
    endif
    sflag = 0b
    current = image-1
endelse

state = {ss_show_state, $
         original: self, $
         image: im, $
         current: current, $
         alternate: obj_new(), $
         context: context, $
         std_window: std_window, $
         sflag: sflag, $
         canvas: canvas, $
         markbut: 0l, $
         hdrbut: 0l, $
         cbase: 0l, $
         islide: 0l, $
         paws: paws, $
         rev: rev, $
         direct: 1, $
         hidid: 0l, $
         loclist: ptr_new(), $
         locmode: 0, $
         loc_mark: 0, $
         loc_index: 0, $
         loc_trace: 0b, $
         loc_decimate: 5, $
         loc_count: 0, $
         gb: gb, $
         sb: sb, $
         df: df, $
         barsize: bars, $
         zoombase: 0l, $
         bflag: 0b, $
         ashow: 0b}

if not sflag then ss_add_controls, b1, state

widget_control, b1, set_uvalue = state

plot_env, /save

im -> show, /nosave

widget_control, canvas, timer = self -> get_delay()

xmanager, 'ss_show', base, /no_block

end      
