FORWARD_FUNCTION cwimg_preview, cwimg_preview_event, $
	cwimg_preview_set_value, cwimg_preview_get_value

;;-----------------------------------------------------------------------------
;; PURPOSE:
;;	Creates a widget that shows a preview of a FITS image. This widget can
;;	either be embedded in an existing window by specifying parent, or
;;	can be a new window which apprears to the right of the window 
;;	containing the group_leader. If the preview is in a seperate window,
;;	resizing the window causes the image to shrink/expand
;;
;; CALLING SEQUENCE:
;;	ID = cwimg_preview(parent, UNAME=uname, UVALUE=uvalue, VALUE=value, $
;;		XSIZE=xsize, YSIZE=ysize, TITLE=title, RETAIN=retain, $
;;		ORDER=order, GROUP_LEADER=group_leader, /NO_COPY, $
;;		KILL_NOTIFY=kill_notify)
;;
;; REQUIRED INPUTS:
;;
;; OUTPUTS:
;;	The widget ID of the compound widget
;;
;; OPTIONAL INPUT KEYWORDS:
;;	parent - The parent of this widget. If not specified, a new window is
;;		created
;;	UNAME - User name
;;	UVALUE - User value
;;	VALUE - The image to display
;;	XSIZE - The display width of the image (default = 256)
;;	YSIZE - The display height of the image (default = 256)
;;	TITLE - Title for the new window if it is created
;;	RETAIN - Passed directly to the draw_widget function
;;	ORDER - Passed directly to the TV procedure
;;	GROUP_LEADER - The leader of the group this widget belongs to
;;	NO_COPY - If a copy of value and uvalue should be made on creation
;;	KILL_NOTIFY - Procedure to call when the widget is destroyed
;;
;; EVENTS PRODUCED:
;;	No event is returned
;;
;; EXAMPLE:
;;      IDL> preview = cwimg_preview(GROUP_LEADER=main)
;;
;; PROCEDURES USED (i.e. called directly!):
;;
;; MODIFICATION HISTORY:
;;   2004-07-30  M. Desnoyer    Created
;;
;;-----------------------------------------------------------------------------

;;---------------------------
;; Event Handler
;;---------------------------
PRO cwimg_preview_event, ev

;; Get the data we need from the object
draw = widget_info(ev.handler, /child)
widget_control, draw, get_uvalue=uval, /no_copy

type = tag_names(ev, /structure_name)
IF type EQ 'WIDGET_BASE' THEN BEGIN ;; Resize event

	;; Make sure we're allowed to resize
	IF uval.doResize EQ 0 THEN BEGIN
		GOTO, ret
	ENDIF

	;; Create a timer so that resizing doesn't occur too quickly
	widget_control, ev.ID, timer=0.05
	uval.doResize = 0

	;; Resize the draw area
	draw = widget_info(ev.handler, /child)
	widget_control, draw, get_value=drawWind, xsize=ev.x, ysize=ev.y
	
	;; Redraw the image
	curWind = !D.WINDOW
	stretch = congrid(uval.img, ev.x, ev.y)
	wset, drawWind
	tv, stretch, order=uval.order
	wset, curWind
ENDIF ELSE IF type EQ 'WIDGET_TIMER' THEN BEGIN
	uval.doResize = 1
ENDIF

ret: ;; Cleanup
widget_control, draw, set_uvalue=uval, /no_copy

RETURN
END

;;---------------------------
;; Set Value Handler
;;---------------------------
PRO cwimg_preview_set_value, id, value

;; Get the draw window
draw = widget_info(id, /child)

n = n_elements(value)
h = histogram(value, reverse=r)
tot = total(h, /cumulative, /nan)
mini = where(tot LT n/100)
maxi = where(tot GT n/100*99)
minScl = max(value[r[r[mini[0]:mini[n_elements(mini)-1]]]])
maxScl = min(value[r[r[maxi[0]:maxi[n_elements(maxi)-1]]]])
scaled = (value-minScl)*!D.TABLE_SIZE/(maxScl-minScl)

;; Set the value
widget_control, draw, set_uvalue={img:scaled,scl:[minScl,maxScl],doresize:1B}, $
	/no_copy

;; Get the window to resize
geom = widget_info(id, /geometry)
cwimg_preview_event, {WIDGET_BASE, ID:id, TOP:id, HANDLER:id, X:geom.xsize, $
	Y:geom.ysize}

RETURN
END

;;---------------------------
;; Get Value Handler
;;---------------------------
FUNCTION cwimg_preview_get_value, id, value

;; Get the internal values
draw = widget_info(id, /CHILD)
widget_control, draw, get_uvalue=vals, /no_copy

;; Convert the internal scaled version to original
out = vals.img*(scl[1]-sc[0])/255+scl[0]

;;Replace the internal values
widget_control, draw, set_uvalue=vals, /no_copy

RETURN, out
END

;;---------------------------
;; Handle color table changes
;;---------------------------
PRO cwimg_preview_refresh, id

;; Make sure we're in greater than 256 colors and need to redraw
Device, Get_visual_depth=visDep
IF visDep LE 8 THEN RETURN

device, decomposed=0

;; The data is the widget ID of the top level
geom = widget_info(id, /geometry)

;; Fake a resize event (which will cause the picture to be redrawn)
cwimg_preview_event, {WIDGET_BASE, ID:id, TOP:id, HANDLER:id, X:geom.xsize, $
	Y:geom.ysize}
END

;;---------------------------
;; Widget Creation Function
;;---------------------------
FUNCTION cwimg_preview, parent, UNAME=uname, UVALUE=uvalue, VALUE=value, $
	XSIZE=xsize, YSIZE=ysize, TITLE=title, RETAIN=retain, ORDER=order, $
	GROUP_LEADER=group_leader, NO_COPY=no_copy, KILL_NOTIFY=kill_notify

;; Default the keywords
IF NOT keyword_set(UVALUE) THEN uvalue=0
IF NOT keyword_set(UNAME) THEN uname='CWIMG_PREVIEW'
IF NOT keyword_set(VALUE) THEN value=0
IF NOT keyword_set(XSIZE) THEN xsize=256
IF NOT keyword_set(YSIZE) THEN ysize=256
IF NOT keyword_set(TITLE) THEN title='Image Preview'
IF NOT keyword_set(ORDER) THEN order=!order

;; Get the current window
curWind = !D.WINDOW

;; Figure out where the window should be placed
IF keyword_set(GROUP_LEADER) THEN BEGIN
	geom = widget_info(group_leader, /geometry)
	xoffset = geom.scr_xsize + geom.xoffset + geom.xpad
ENDIF

;; Create the widget 
IF n_params() EQ 0 THEN $
	base = widget_base( uname=uname, uvalue=uvalue, title=title, $
		group_leader=group_leader, no_copy=no_copy, $
		pro_set_value='cwimg_preview_set_value', xoffset=xoffset,$
		func_get_value='cwimg_preview_get_value', /tlb_size_events, $
		kill_notify=kill_notify) $
ELSE IF n_params() EQ 1 THEN $
	base = widget_base(parent, uname=uname, uvalue=uvalue, title=title, $
		group_leader=group_leader, no_copy=no_copy, $
		pro_set_value='cwimg_preview_set_value', xoffset=xoffset, $
		func_get_value='cwimg_preview_get_value', $
		kill_notify=kill_notify)$
ELSE message, 'Invalid number of parameters'

;; Remove the outlier values from the image
minScl = min(value,/nan)
maxScl = max(value,/nan)
scaled = (value-minScl)*!D.TABLE_SIZE/(maxScl-minScl)

;; Draw the image
stretch = congrid(scaled, xsize,ysize) 
draw = widget_draw(base, uvalue={img:scaled,scl:[minScl,maxScl],doresize:1B, $
	order:order}, /no_copy, retain=retain, xsize=xsize, ysize=ysize, $
	uname='draw')

;; Display the picture
widget_control, base, /realize
widget_control, draw, get_value=drawWind
wset, drawWind
tv, stretch, order=order

;; Set up the xmanager for the resize events
xmanager, 'CWIMG_PREVIEW', base, event_handler='cwimg_preview_event', $
	group_leader=group_leader, /NO_BLOCK

wset, curWind

RETURN, base

END