Viewing contents of file '../idllib/contrib/buie/cw_pixed.pro'
;+
; NAME:
;    cw_pixed
; PURPOSE: (one line)
;    Pixel editor.
; DESCRIPTION:
;    This compound widget may be used to edit a grid of pixels in an array.
; Unless near the edge of the image, the grid is centered on (xpos, ypos).
; The left column and the bottom row display the y and x coordinates,
; respectively, for the grid. Xpos and ypos are enclosed in brackets,
; for identification.
; CATEGORY:
;    Compound Widgets
; CALLING SEQUENCE:
;    result = cw_pixed( parent, image, xpos, ypos )
; INPUTS:
;    parent      : The id of the parent widget.
;    image       : The array to be edited.
;    xpos, ypos  : The pixel at this location in the array, along with a
;                  collection of its neighbors, will be displayed as a grid of
;                  editable text widgets.
;
; OPTIONAL INPUT PARAMETERS:
;
; INPUT KEYWORD PARAMETERS:
;    GRIDSIZE = The size of the grid of surrounding pixels. Default
;               is 7 pixels (7X7 grid). Note: In order to maintain symmetry
;               about the center pixel, the grid size needs to be odd.
;               Therefore, even values will be increased by 1 pixel.
;
; OUTPUTS:
;    result : The id of the compound widget.
; COMMON BLOCKS:
;
; SIDE EFFECTS:
;    This compound widget generates events with the following structure:
;    { id:0L, top:0L, handler:0L, type:0, count:0, x:0, y:0, value:v }
;    where,
;       type    The event type (0=Done, 1=single pixel changed).
;       count   Specifies the number of elements in the remaining three tags
;       x and y Coordinates of changed pixel(s).
;       value   Value(s) for changed pixel(s).
;
;    The zero values in the above structure indicate the data types for the
; those tags, not the actual values. The 'value' tag will be the same type
; as the data in the array being edited.
;
; RESTRICTIONS:
;
; PROCEDURE:
;
; MODIFICATION HISTORY:
;    Written by Doug Loucks, Lowell Observatory, April 28, 1994.
; 95/10/31, MWB, Fixed widget layout problem caused by IDL v4.0 changes.
;-
; ------------------------------------------------------------------------------
; Procedure cw_pixed_eve
; Event handler.
; ------------------------------------------------------------------------------
FUNCTION cw_pixed_eve, event
WIDGET_CONTROL, event.id, GET_VALUE=value, GET_UVALUE=uvalue, /HOURGLASS

stash = WIDGET_INFO( event.handler, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY

out_event = 0

CASE event.id OF
   state.doneid : BEGIN
      child = WIDGET_INFO( event.top, /CHILD )
      WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
      WIDGET_CONTROL, event.top, MAP=0
      WIDGET_CONTROL, child, /DESTROY
      RETURN, 0
   END

   state.restoreid : BEGIN
      w = WHERE( state.chgdids GT 0, count )
      IF count GT 0 THEN BEGIN
         x = INTARR( count )
         y = INTARR( count )
         v = REPLICATE( state.tval, count )
         FOR j=0, count-1 DO BEGIN
            WIDGET_CONTROL, state.chgdids[w[j]], GET_UVALUE=uv
            x[j] = uv.x
            y[j] = uv.y
            v[j] = state.savgrid[ uv.x, uv.y ]
            text = STRING( v[j], FORMAT=state.fmt )
            WIDGET_CONTROL, state.chgdids[w[j]], SET_VALUE=text
            state.chgdids[ w[j] ] = 0
         ENDFOR
         out_event = { id:event.handler, top:event.top, handler:0L, type:1, $
            count:count, x:state.xset+x, y:state.yset+y, value:v }
      ENDIF
   END

   ELSE : BEGIN
      WIDGET_CONTROL, event.id, GET_VALUE=value, GET_UVALUE=uvalue
      x = uvalue.x
      y = uvalue.y
      state.grid[ x, y ] = value[0]
      out_event = { id:event.handler, top:event.top, handler:0L, type:1, $
      count:1, x:[state.xset+x], y:[state.yset+y], value:[state.tval] }
      state.chgdids[ x, y ] = event.id
      out_event.value = value[0]
   END
ENDCASE

WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

RETURN, out_event
END

; ------------------------------------------------------------------------------
; Procedure cw_pixed
; Compound Widget Pixel Editor.
; ------------------------------------------------------------------------------
FUNCTION cw_pixed, parent, image, xpos, ypos, GRIDSIZE=in_gridsize, $
         UVALUE=in_uvalue

stat = SIZE( image )
xsize = stat[1]
ysize = stat[2]
typecode = stat[3]

CASE typecode OF
   1 : BEGIN
      width = 4
      fmt   = '(I4)'
      tval  = 0B
   END

   2 : BEGIN
      width = 6
      fmt   = '(I6)'
      tval  = 0
   END

   3 : BEGIN
      width = 12
      fmt   = '(I12)'
      tval   = 0L
   END

   4 : BEGIN
      width = 12
      fmt   = '(G0.0)'
      tval  = 0.0
   END

   5 : BEGIN
      width = 14
      fmt   = '(G0.0)'
      tval  = 0.0
   END

   ELSE : BEGIN
      MESSAGE, 'Error. Typecode ' + STRING(typecode,FORMAT='(G0.0)') + $
               ' not supported', /INFO
      width = 12
      fmt   = '(G0.0)'
      tval  = 0.0
   END
ENDCASE

IF KEYWORD_SET( in_gridsize ) THEN gridsize=in_gridsize ELSE gridsize=7

IF (gridsize MOD 2) EQ 0 THEN gridsize=gridsize+1

hw = gridsize / 2
xset = xpos - hw
yset = ypos - hw
IF xset LT 0 THEN xset = 0
IF yset LT 0 THEN yset = 0
IF xset+gridsize GE xsize THEN xset=xsize-gridsize
IF yset+gridsize GE ysize THEN yset=ysize-gridsize

IF !order EQ 0 THEN BEGIN
   y1 = gridsize - 1
   y2 = 0
   dy = -1
ENDIF ELSE BEGIN
   y1 = 0
   y2 = gridsize - 1
   dy = 1
ENDELSE

state = { chgdids:LONARR(gridsize, gridsize), doneid:0L, $
          fmt:fmt, $
          grid:REPLICATE( tval, gridsize, gridsize ), gridsize:gridsize, $
          restoreid:0L, $
          savgrid:REPLICATE( tval, gridsize, gridsize ), $
          xset:xset, yset:yset, xpos:xpos, ypos:ypos, $
          xids:LONARR(gridsize,/NOZERO), yids:LONARR(gridsize,/NOZERO), $
          gridids:LONARR(gridsize, gridsize,/NOZERO), tval:tval }

state.grid    = image[xset:xset+gridsize-1, yset:yset+gridsize-1 ]
state.savgrid = image[xset:xset+gridsize-1, yset:yset+gridsize-1 ]

IF KEYWORD_SET( in_uvalue ) THEN BEGIN
   mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_FUNC='cw_pixed_eve', $
          UVALUE=in_uvalue )
ENDIF ELSE BEGIN
   mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_FUNC='cw_pixed_eve' )
ENDELSE

f = '(G0.0)'

wb = WIDGET_BASE( mainbase, ROW=1 )
state.doneid = WIDGET_BUTTON( wb, VALUE='Done' )

state.restoreid = WIDGET_BUTTON( wb, VALUE='Restore Initial Values' )

cba = WIDGET_BASE( mainbase, COLUMN=gridsize+1, /FRAME )

FOR j=y1, y2, dy DO BEGIN
   text = STRING( yset+j, FORMAT=f )
   mark = (yset+j) EQ ypos
   IF mark THEN text = '[' + text + ']'
   state.yids[j] = WIDGET_LABEL( cba, VALUE=text )
ENDFOR
w0 = WIDGET_LABEL( cba, VALUE='    ' )

FOR i=0, gridsize-1 DO BEGIN
   FOR j=y1, y2, dy DO BEGIN
      text = STRING( image[xset+i, yset+j], FORMAT=f )
      w0 = WIDGET_TEXT( cba, VALUE=text, UVALUE={x:i, y:j}, XSIZE=width, /EDIT )
      state.gridids[i,j] = w0
   ENDFOR
   text = STRING( xset+i, FORMAT=f )
   mark = (xset+i) EQ xpos
   IF mark THEN text = '[' + text + ']'
   state.xids[i] = WIDGET_LABEL( cba, VALUE=text )
ENDFOR

;
; scan through all the items in this base and find the max x and y sizes.
max_xs=0
max_ys=0
t_b = WIDGET_INFO(cba, /CHILD)  ; gets first child
WHILE (t_b NE 0L) DO BEGIN
   geo = WIDGET_INFO(t_b, /GEOMETRY)
   max_xs=max([max_xs,geo.scr_xsize])
   max_ys=max([max_ys,geo.scr_ysize])
   t_b = WIDGET_INFO(t_b, /SIBLING) ; gets next child (0=no more)
ENDWHILE

t_b = WIDGET_INFO(cba, /CHILD)
WHILE (t_b NE 0L) DO BEGIN
   WIDGET_CONTROL, t_b, SCR_XSIZE=max_xs, SCR_YSIZE=max_ys
   t_b = WIDGET_INFO(t_b, /SIBLING)
ENDWHILE

; -----------------------------
m = MEDIAN( state.grid )

xp = xpos - xset
yp = ypos - yset

x = INDGEN( gridsize )
ya = state.grid[ xp, * ]
yb = state.grid[ *, yp ]
w = WHERE( x NE xp, count )
coeff1 = goodpoly( x[w]+xpos, ya[w], 1, 3.0, yfit )
coeff2 = goodpoly( x[w]+ypos, yb[w], 1, 3.0, yfit )

ny1 = POLY( xpos, coeff1 )
ny2 = POLY( ypos, coeff2 )

text = STRING( 'Grid Median: ', m, '   Linear Interpolation, Row:  ', ny2, $
       '   Column: ', ny1, FORMAT='(A,G0.0,A,G0.0,A,G0.0)' )
w0 = WIDGET_LABEL( mainbase, VALUE=text )
; -----------------------------

stash = WIDGET_INFO( mainbase, /CHILD )

WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

RETURN, mainbase

END