Viewing contents of file '../idllib/contrib/fanning/icon_ex.pro'
;+
; FUNCTION NAME:
;
; ICON_BUTTON
;
; PURPOSE:
;
; This is a compound widget to put up a small button with an image on it.
; It is implemented as a draw widget, but acts like a button. The event
; structure that is returned is a WIDGET_BUTTON event structure for a
; SELECT event.
;
; MAJOR TOPICS:
;
; Widget Programming
;
; FUNCTION:
;
; Used almost identically to WIDGET_BUTTON.
;
; CALLING SEQUENCE:
;
; buttonID = ICON_BUTTON(parent, Value='icon_button', Image=image)
;
; POSITIONAL PARAMETERS:
;
; parent -- The identifier of the parent widget.
;
; KEYWORD PARAMETERS:
;
; BOTTOM -- The starting color index of the image colors.
;
; COLORINDEX -- A four-element array that gives the color indicies for the button
; colors. COLORINDEX(0) is the button outline color. COLORINDEX(1) is the dark
; edge color. COLORINDEX(2) is the light edge color.
; COLORINDEX(3) is the button highlight color.
;
; EVENT_FUNC -- The name of an event handler function for this button.
;
; EVENT_PRO -- The name of an event handler procedure for this button.
;
; IMAGE -- The 2D array to use as the icon display.
;
; NCOLORS -- The number of colors to use for the image display.
;
; VALUE -- The value of the icon. (Used to make it look like a button.)
;
; UVALUE -- A user value. Used in the normal way.
;
; XOFFSET -- The X offset of the icon on the display.
;
; YOFFSET -- The Y offset of the icon on the display.
;
; XSIZE -- This is the XSIZE of the icon.
;
; YSIZE -- This is the YSIZE of the icon.
;
; EXAMPLE:
;
; To make an icon button out of the CTSCAN.DAT image, do this:
;
; Load colors for the icon button's boundaries.
;
; TVLCT, [255, 70, 150, 255], [255, 70, 150, 255], $
; [255, 70, 150, 255], 200
;
; Read image data.
;
; ctscan = GetImage()
;
; Build widgets.
;
; base = Widget_Base()
; icon = Icon_Button(base, ColorIndex=Indgen(4)+200, $
; Value='icon_button', Image=ctscan, NColors=200, Bottom=0)
; Widget_Control, base, /Realize
;
; MAJOR FUNCTIONS and PROCEDURES:
;
; None.
;
; EVENT STRUCTURE:
;
; event = {WIDGET_BUTTON, ID:0L, TOP:0L, HANDLER:0L, SELECT:1}
;
; MODIFICATION HISTORY:
;
; Written by: David Fanning, August 1996.
; Given to attendees of IDL training courses.
;-
PRO XColors_Set, info
TVLCT, r, g, b, /Get
r(info.bottom:info.currentbottom) = info.bottomcolor(0)
g(info.bottom:info.currentbottom) = info.bottomcolor(1)
b(info.bottom:info.currentbottom) = info.bottomcolor(2)
r(info.currenttop:info.top) = info.topcolor(0)
g(info.currenttop:info.top) = info.topcolor(1)
b(info.currenttop:info.top) = info.topcolor(2)
red = info.r
green = info.g
blue = info.b
number = (info.currenttop-info.currentbottom) + 1
gamma = info.gamma
index = Findgen(info.ncolors)
distribution = index^gamma
index = Round(distribution * (info.ncolors-1) / Max(distribution))
IF info.reverse EQ 0 THEN BEGIN
r(info.currentbottom:info.currenttop) = Congrid(red(index), number)
g(info.currentbottom:info.currenttop) = Congrid(green(index), number)
b(info.currentbottom:info.currenttop) = Congrid(blue(index), number )
ENDIF ELSE BEGIN
r(info.currentbottom:info.currenttop) = $
Reverse(Congrid(red(index), number))
g(info.currentbottom:info.currenttop) = $
Reverse(Congrid(green(index), number))
b(info.currentbottom:info.currenttop) = $
Reverse(Congrid(blue(index), number))
ENDELSE
TVLct, r, g, b
WSet, info.windowindex
TV, info.colorimage
; Are there widgets to notify?
s = SIZE(info.notifyID)
IF s(0) EQ 1 THEN count = 0 ELSE count = s(2)-1
FOR j=0,count DO BEGIN
colorEvent = { XCOLORS_LOAD, $
ID:info.notifyID(0,j), $
TOP:info.notifyID(1,j), $
HANDLER:0L, $
R:r, $
G:g, $
B:b }
IF Widget_Info(info.notifyID(0,j), /Valid_ID) THEN $
Widget_Control, info.notifyID(0,j), Send_Event=colorEvent
ENDFOR
END ; ***************************************************************
PRO XCOLORS_GAMMA_SLIDER, event
; Get the info structure from storage location.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Get the gamma value from the slider.
Widget_Control, event.id, Get_Value=gamma
gamma = 10^((gamma/50.0) - 1)
info.gamma = gamma
; Update the gamma label.
Widget_Control, info.gammaID, Set_Value=String(gamma, Format='(F6.3)')
; Make a pseudo structure.
IF info.currentBottom GT info.currentTop THEN $
pseudo = {currenttop:info.currentbottom, currentbottom:info.currenttop, $
reverse:1, bottomcolor:info.topcolor, topcolor:info.bottomcolor, $
gamma:info.gamma, top:info.top, bottom:info.bottom, $
ncolors:info.ncolors, r:info.r, g:info.g, b:info.b, $
notifyID:info.notifyID, colorimage:info.colorimage, $
windowindex:info.windowindex} $
ELSE $
pseudo = {currenttop:info.currenttop, currentbottom:info.currentbottom, $
reverse:0, bottomcolor:info.bottomcolor, topcolor:info.topcolor, $
gamma:info.gamma, top:info.top, bottom:info.bottom, $
ncolors:info.ncolors, r:info.r, g:info.g, b:info.b, $
notifyID:info.notifyID, colorimage:info.colorimage, $
windowindex:info.windowindex}
; Load the colors.
XColors_Set, pseudo
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ************************************************************************
PRO XCOLORS_COLORTABLE, event
; Get the info structure from storage location.
Widget_Control, event.top, Get_UValue=info, /No_Copy
LoadCt, event.index, File=info.file, /Silent, $
NColors=info.ncolors, Bottom=info.bottom
TVLct, r, g, b, /Get
info.r = r(info.bottom:info.top)
info.g = g(info.bottom:info.top)
info.b = b(info.bottom:info.top)
info.topcolor = [r(info.top), g(info.top), b(info.top)]
info.bottomcolor = [r(info.bottom), g(info.bottom), b(info.bottom)]
; Update the slider positions and values.
Widget_Control, info.botSlider, Set_Value=0
Widget_Control, info.topSlider, Set_Value=info.ncolors-1
Widget_Control, info.gammaSlider, Set_Value=50
Widget_Control, info.gammaID, Set_Value=String(1.0, Format='(F6.3)')
info.currentBottom = info.bottom
info.currentTop = info.top
info.gamma = 1.0
; Create a pseudo structure.
pseudo = {currenttop:info.currenttop, currentbottom:info.currentbottom, $
reverse:info.reverse, windowindex:info.windowindex, $
bottomcolor:info.bottomcolor, topcolor:info.topcolor, gamma:info.gamma, $
top:info.top, bottom:info.bottom, ncolors:info.ncolors, r:info.r, $
g:info.g, b:info.b, notifyID:info.notifyID, colorimage:info.colorimage}
; Update the colors.
XColors_Set, pseudo
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ************************************************************************
PRO XCOLORS_BOTTOM_SLIDER, event
; Get the info structure from storage location.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Update the current bottom value of the slider.
info.currentBottom = info.bottom + event.value
; Error handling. Is currentBottom = currentTop?
IF info.currentBottom EQ info.currentTop THEN BEGIN
info.currentBottom = info.currentTop
Widget_Control, info.botSlider, Set_Value=(info.currentBottom-info.bottom)
ENDIF
; Error handling. Is currentBottom > currentTop?
IF info.currentBottom GT info.currentTop THEN BEGIN
bottom = info.currentTop
top = info.currentBottom
bottomcolor = info.topColor
topcolor = info.bottomColor
reverse = 1
ENDIF ELSE BEGIN
bottom = info.currentBottom
top = info.currentTop
bottomcolor = info.bottomColor
topcolor = info.topColor
reverse = 0
ENDELSE
; Create a pseudo structure.
pseudo = {currenttop:top, currentbottom:bottom, reverse:reverse, $
bottomcolor:bottomcolor, topcolor:topcolor, gamma:info.gamma, $
top:info.top, bottom:info.bottom, ncolors:info.ncolors, r:info.r, $
g:info.g, b:info.b, notifyID:info.notifyID, colorimage:info.colorimage, $
windowindex:info.windowindex}
; Update the colors.
XColors_Set, pseudo
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ************************************************************************
PRO XCOLORS_PROTECT_COLORS, event
; Get the info structure from storage location.
IF event.enter NE 1 THEN RETURN
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Create a pseudo structure.
pseudo = {currenttop:info.currenttop, currentbottom:info.currentbottom, $
reverse:info.reverse, $
bottomcolor:info.bottomcolor, topcolor:info.topcolor, gamma:info.gamma, $
top:info.top, bottom:info.bottom, ncolors:info.ncolors, r:info.r, $
g:info.g, b:info.b, notifyID:info.notifyID, colorimage:info.colorimage, $
windowindex:info.windowindex}
; Update the colors.
XColors_Set, pseudo
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ************************************************************************
PRO XCOLORS_TOP_SLIDER, event
; Get the info structure from storage location.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Update the current top value of the slider.
info.currentTop = info.bottom + event.value
; Error handling. Is currentBottom = currentTop?
IF info.currentBottom EQ info.currentTop THEN BEGIN
info.currentBottom = (info.currentTop - 1) > 0
thisValue = (info.currentBottom-info.bottom)
IF thisValue LT 0 THEN BEGIN
thisValue = 0
info.currentBottom = info.bottom
ENDIF
Widget_Control, info.botSlider, Set_Value=thisValue
ENDIF
; Error handling. Is currentBottom > currentTop?
IF info.currentBottom GT info.currentTop THEN BEGIN
bottom = info.currentTop
top = info.currentBottom
bottomcolor = info.topColor
topcolor = info.bottomColor
reverse = 1
ENDIF ELSE BEGIN
bottom = info.currentBottom
top = info.currentTop
bottomcolor = info.bottomColor
topcolor = info.topColor
reverse = 0
ENDELSE
; Create a pseudo structure.
pseudo = {currenttop:top, currentbottom:bottom, reverse:reverse, $
bottomcolor:bottomcolor, topcolor:topcolor, gamma:info.gamma, $
top:info.top, bottom:info.bottom, ncolors:info.ncolors, r:info.r, $
g:info.g, b:info.b, notifyID:info.notifyID, colorimage:info.colorimage, $
windowindex:info.windowindex}
; Update the colors.
XColors_Set, pseudo
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ************************************************************************
PRO XCOLORS_CANCEL, event
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Create a pseudo structure.
pseudo = {currenttop:info.currenttop, currentbottom:info.currentbottom, $
reverse:info.reverse, windowindex:info.windowindex, $
bottomcolor:info.bottomcolor, topcolor:info.topcolor, gamma:info.gamma, $
top:info.top, bottom:info.bottom, ncolors:info.ncolors, r:info.rstart, $
g:info.gstart, b:info.bstart, notifyID:info.notifyID, colorimage:info.colorimage}
; Update the colors.
XColors_Set, pseudo
Widget_Control, event.top, /Destroy
END ; ************************************************************************
PRO XCOLORS_DISMISS, event
Widget_Control, event.top, /Destroy
END ; ************************************************************************
PRO XCOLORS, NColors=ncolors, Bottom=bottom, Title=title, File=file, $
Group=group, XOffset=xoffset, YOffset=yoffset, Just_Reg=jregister, $
NotifyID=notifyID
; This is a procedure to load color tables into a
; restricted color range of the physical color table.
; It is a highly simplified version of XLoadCT.
On_Error, 1
; Make sure colors are initiated.
thisWindow = !D.Window
Window, /Pixmap, /Free, XSize=10, YSize=10
WDelete, !D.Window
IF thisWindow GE 0 THEN WSet, thisWindow
; Check keyword parameters. Define defaults.
IF N_Elements(ncolors) EQ 0 THEN ncolors = 256 < !D.N_Colors
IF N_Elements(bottom) EQ 0 THEN bottom = 0
top = bottom + (ncolors-1)
IF N_Elements(title) EQ 0 THEN title = 'Load Color Tables'
IF N_ELements(file) EQ 0 THEN $
file = Filepath(SubDir=['resource','colors'], 'colors1.tbl')
IF N_Elements(notifyID) EQ 0 THEN notifyID = [-1L, -1L]
; Find the center of the display.
DEVICE, GET_SCREEN_SIZE=screenSize
xCenter = FIX(screenSize(0) / 2.0)
yCenter = FIX(screenSize(1) / 2.0)
IF N_ELEMENTS(xoffset) EQ 0 THEN xoffset = xCenter - 150
IF N_ELEMENTS(yoffset) EQ 0 THEN yoffset = yCenter - 200
IF N_Elements(xoffset) EQ 0 THEN xoffset = 100
IF N_Elements(yoffset) EQ 0 THEN yoffset = 100
registerName = 'XCOLORS:' + title
; Only one XCOLORS with this title.
IF XRegistered(registerName) THEN RETURN
; Create the top-level base. No resizing.
tlb = Widget_Base(Column=1, Title=title, TLB_Frame_Attr=1, $
XOffSet=xoffset, YOffSet=yoffset, Base_Align_Center=1, Tracking=1)
; Create a draw widget to display the current colors.
draw = Widget_Draw(tlb, XSize=256, YSize=40, Tracking=1)
; Create sliders to control stretchs and gamma correction.
sliderbase = Widget_Base(tlb, Column=1, Frame=1)
botSlider = Widget_Slider(sliderbase, Value=0, Min=0, $
Max=ncolors-1, XSize=256, /Drag, Event_Pro='XColors_Bottom_Slider', $
Title='Stretch Bottom')
topSlider = Widget_Slider(sliderbase, Value=ncolors-1, Min=0, $
Max=ncolors-1, XSize=256, /Drag, Event_Pro='XColors_Top_Slider', $
Title='Stretch Top')
gammaID = Widget_Label(sliderbase, Value=String(1.0, Format='(F6.3)'))
gammaSlider = Widget_Slider(sliderbase, Value=50.0, Min=0, Max=100, $
/Drag, XSize=256, /Suppress_Value, Event_Pro='XColors_Gamma_Slider', $
Title='Gamma Correction')
; Get the colortable names for the list widget.
colorNames=''
LoadCt, Get_Names=colorNames
FOR j=0,N_Elements(colorNames)-1 DO $
colorNames(j) = StrTrim(j,2) + ' - ' + colorNames(j)
filebase = Widget_Base(tlb, Column=1, /Frame)
listlabel = Widget_Label(filebase, Value='Select Color Table...')
list = Widget_List(filebase, Value=colorNames, YSize=8, Scr_XSize=256, $
Event_Pro='XColors_ColorTable')
; Dialog Buttons
dialogbase = WIDGET_BASE(tlb, Row=1)
cancel = Widget_Button(dialogbase, Value='Cancel', $
Event_Pro='XColors_Cancel', UVALUE='CANCEL')
dismiss = Widget_Button(dialogbase, Value='Accept', $
Event_Pro='XColors_Dismiss', UVALUE='ACCEPT')
Widget_Control, tlb, /Realize
; Get window index number of the draw widget.
Widget_Control, draw, Get_Value=windowIndex
WSet, windowIndex
; Put a picture of the color table in the window.
colorImage = BIndgen(256,40)
colorRow = BIndgen(ncolors)
colorRow = Congrid(colorRow, 256)
FOR j=0,39 DO colorImage(*,j) = colorRow
colorImage = BytScl(colorImage, Top=ncolors-1) + bottom
Tv, colorImage
; Get the colors that make up the current color table
; in the range that this program deals with.
TVLCT, rr, gg, bb, /Get
r = rr(bottom:top)
g = gg(bottom:top)
b = bb(bottom:top)
topColor = [rr(top), gg(top), bb(top)]
bottomColor = [rr(bottom), gg(bottom), bb(bottom)]
; Create an info structure to hold information to run the program.
info = { windowIndex:windowIndex, $ ; The WID of the draw widget.
botSlider:botSlider, $ ; The widget ID of the bottom slider.
currentBottom:bottom, $ ; The current bottom slider value.
currentTop:top, $ ; The current top slider value.
topSlider:topSlider, $ ; The widget ID of the top slider.
gammaSlider:gammaSlider, $ ; The widget ID of the gamma slider.
gammaID:gammaID, $ ; The widget ID of the gamma label
ncolors:ncolors, $ ; The number of colors we are using.
gamma:1.0, $ ; The current gamma value.
file:file, $ ; The name of the color table file.
bottom:bottom, $ ; The bottom color index.
top:top, $ ; The top color index.
topcolor:topColor, $ ; The top color in this color table.
bottomcolor:bottomColor, $ ; The bottom color in this color table.
reverse:0, $ ; A reverse color table flag.
notifyID:notifyID, $ ; Notification widget IDs.
r:r, $ ; The red color vector.
g:g, $ ; The green color vector.
b:b, $ ; The blue color vector.
rstart:r, $ ; The original red color vector.
gstart:g, $ ; The original green color vector.
bstart:b, $ ; The original blue color vector.
colorimage:colorimage } ; The color table image.
; Store the info structure in the user value of the top-level base.
Widget_Control, tlb, Set_UValue=info, /No_Copy
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' THEN $
XManager, registerName, tlb, Group=group, Just_Reg=Keyword_Set(jregister), $
/No_Block, Event_Handler='XCOLORS_PROTECT_COLORS' ELSE $
XManager, registerName, tlb, Group=group, Just_Reg=Keyword_Set(jregister), $
Event_Handler='XCOLORS_PROTECT_COLORS'
END ; ************************************************************************
PRO INTEGER_ONLY, event
; This event handler for text widgets only allows integers to be entered
; in the text widget. A maximum of four digits are allowed.
; Deal with simple one-character insertion events.
IF event.type EQ 0 THEN BEGIN
; Get the current text in the widget and find its length.
Widget_Control, event.id, Get_Value=text
text = text(0)
length = StrLen(text)
; Only react if the insertion character is a number and there
; are less than four characters already in the widget.
IF Byte(event.ch) GE 48B AND Byte(event.ch) LE 57B $
AND length LT 4 THEN BEGIN
; Get the current text selection.
selection = Widget_Info(event.id, /Text_Select)
; Insert the character at the proper location.
Widget_Control, event.id, /Use_Text_Select, Set_Value=String(event.ch)
; Update the current insertion point in the text widget.
Widget_Control, event.id, Set_Text_Select=event.offset + 1
ENDIF
ENDIF ; of insertion event
; Deal with deletion events.
IF event.type EQ 2 THEN BEGIN
; Get the current text in widget.
Widget_Control, event.id, Get_Value=text
text = text(0)
length = StrLen(text)
; Put it back with the deletion subtracted.
Widget_Control, event.id, Set_Value=StrMid(text, 0, length-event.length)
; Reset the text insertion point in the text widget.
Widget_Control, event.id, Set_Text_Select=event.offset
ENDIF
END ; of INTEGER_ONLY event handler *****************************************
PRO NULL_EVENTS, event
; The purpose of this event handler is to do nothing
;and ignore all events that come to it.
END ; of NULL_EVENTS event handler *******************************************
PRO GETIMAGE_EVENT, event
; The only events that can come here are button events.
; Get the info structure out of the user value of the top-level base.
Widget_Control, event.top, Get_UValue=info
; There may be errors we can't anticipate. Catch them here, alert the
; user as to what the error was, and exit the event handler without
; doing any damage.
Catch, error
IF error NE 0 THEN BEGIN
ok = Widget_Message(!Err_String)
RETURN
ENDIF
; Which button caused this event?
Widget_Control, event.id, Get_Value=buttonValue
CASE buttonValue OF
'Pick Filename': BEGIN
; Start in the directory listed in the directory text widget.
; Convert the text value to a scalar.
Widget_Control, info.dirnameID, Get_Value=startDirectory
startDirectory = startDirectory(0)
; If this directory doesn't exist, use the current directory.
test = Findfile(startDirectory, Count=foundfile)
IF foundfile NE 1 THEN CD, Current=startDirectory
; Use PICKFILE to pick a name.
pick = Pickfile(Path=startDirectory, /NoConfirm, $
Get_Path=path, Filter='*.dat')
; Set the directory text widget with the name of the directory.
; Make sure the user didn't cancel out of PICKFILE.
IF pick NE '' THEN BEGIN
; Find the lengths of the PICK and the PATH.
pathLen = StrLen(path)
picklen = StrLen(pick)
; Shorten the PATH to take off last file separator.
path = StrMid(path,0,pathLen-1)
; Put the PATH in the directory location.
Widget_Control, info.dirnameID, Set_Value=path
; Set the filename text widget with the name of the file.
filename = StrMid(pick, pathlen, picklen-pathlen)
Widget_Control, info.filenameID, Set_Value=filename
ENDIF
END ; of the Pick Filename button case
'Cancel': BEGIN
; Have to exit here gracefully. Null filename means "CANCEL".
formdata = {filename:''}
Handle_Value, info.ptrToFormData, formdata, /Set
; Out of here!
Widget_Control, event.top, /Destroy
END ; of the Cancel button case
'Accept': BEGIN ; Gather the form information.
; Put the directory and filename together to make a path.
Widget_Control, info.dirnameID, Get_Value=directory
Widget_Control, info.filenameID, Get_Value=file
filename = Filepath(Root_Dir=directory(0),file(0))
; Get the size and header info. Remember these are STRINGS!
Widget_Control, info.headerID, Get_Value=header
Widget_Control, info.xsizeID, Get_Value=xsize
Widget_Control, info.ysizeID, Get_Value=ysize
Widget_Control, info.frameID, Get_Value=frames
header = Fix(header(0))
xsize = Fix(xsize(0))
ysize = Fix(ysize(0))
frames = Fix(frames(0))
; Get the data type from the droplist widget.
listIndex = Widget_Info(info.droplistID, /Droplist_Select)
datatype = info.datatypes(listIndex)
; Get the format index from the formatlist widget.
formatIndex = Widget_Info(info.formatlistID, /Droplist_Select)
; Create the formdata structure from the information you collected.
formdata = {header:header, xsize:xsize, ysize:ysize, frames:frames, $
filename:filename, datatype:datatype, formatIndex:formatIndex}
; Store the formdata in the pointer location.
Handle_Value, info.ptrToFormData, formdata, /Set
; Out of here!
Widget_Control, event.top, /Destroy
END ; of the Accept button case
ENDCASE
END ; of GETIMAGE_EVENT event handler ***************************************
FUNCTION GETIMAGE, filename, Directory=directory, XSize=xsize, YSize=ysize, $
Frames=frames, Header=header, XDR=xdr, XOffSet=xoffset, YOffSet=yoffset
; This is a function to specify the size, data type, and header information
; about an image that you would like to read. It reads the data and returns
; it as the result of the function. If an error occurs, the function returns
; a 0.
; Check for parameters and keywords.
IF N_Params() EQ 0 THEN filename='ctscan.dat'
; If DIRECTORY keyword is not used, use the "coyote" directory.
; If that is not found, use the current directory.
IF N_Elements(directory) EQ 0 THEN BEGIN
startDirectory = Coyote()
IF startDirectory EQ '' THEN CD, Current=startDirectory
ENDIF ELSE startDirectory = directory
; Check for size and header keywords. These probably come in as
; numbers and you need strings to put them into text widgets.
IF N_Elements(xsize) EQ 0 THEN xsize='256' ELSE xsize=StrTrim(xsize,2)
IF N_Elements(ysize) EQ 0 THEN ysize='256' ELSE ysize=StrTrim(ysize,2)
IF N_Elements(frames) EQ 0 THEN frames='0' ELSE frames=StrTrim(frames,2)
IF N_Elements(header) EQ 0 THEN header='0' ELSE header=StrTrim(header,2)
; Find the center of the display.
Device, Get_Screen_Size=screenSize
xCenter = Fix(screenSize(0) / 2.0)
yCenter = Fix(screenSize(1) / 2.0)
IF N_Elements(xoffset) EQ 0 THEN xoffset = xCenter - 275
IF N_Elements(yoffset) EQ 0 THEN yoffset = yCenter - 150
; Create a top-level base. The fake TLB is used with IDL 5.
; This is probably not a good idea in general, but I am doing
; it to maintain IDL 4 compatibility.
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' THEN BEGIN
fakeTLB = Widget_Base()
tlb = Widget_Base(Column=1, Title='Read Image Data', XOffSet=xoffset, $
YOffSet=yoffset, /Modal, Group_Leader=fakeTLB)
ENDIF ELSE BEGIN
tlb = Widget_Base(Column=1, Title='Read Image Data', XOffSet=xoffset, $
YOffSet=yoffset)
ENDELSE
; Create the directory widgets.
dirnamebase = Widget_Base(tlb, Row=1)
dirnamelabel = Widget_Label(dirnamebase, Value='Directory:')
dirnameID = Widget_Text(dirnamebase, Value=startDirectory, /Editable, $
Event_Pro='NULL_EVENTS', XSize=Fix(2.0*StrLen(startDirectory) > 50))
; Create the filename widgets.
filenamebase = Widget_Base(tlb, Row=1)
filenamelabel = Widget_Label(filenamebase, Value='Filename:')
filenameID = Widget_Text(filenamebase, Value=filename, /Editable, $
Event_Pro='NULL_EVENTS', XSize=2*StrLen(filename) > 20)
; Create a button to allow user to pick a filename.
pickbutton = Widget_Button(filenamebase, Value='Pick Filename')
; Create a droplist widget to select file data types.
database = Widget_Base(tlb, Row=1)
datatypes = ['Byte', 'Integer', 'Long', 'Float']
droplistID = Widget_Droplist(database, Value=datatypes, $
Title='Data Type: ', Event_Pro='NULL_EVENTS')
; Create a droplist widget to select file formats.
formatlistID = Widget_Droplist(database, Value=['None', 'XDR'], $
Title='File Format: ', Event_Pro='NULL_EVENTS')
; Create a text widget to accept a header size.
headlabel = Widget_Label(database, Value='Header Size:')
headerID = Widget_Text(database, Value=header, All_Events=1, Editable=0, $
Event_Pro='INTEGER_ONLY', XSize=8)
; Create widgets to gather the required file sizes.
sizebase = Widget_Base(tlb, Row=1)
xlabel = Widget_Label(sizebase, Value='X Size:')
xsizeID = Widget_Text(sizebase, Value=xsize, All_Events=1, Editable=0, $
Event_Pro='INTEGER_ONLY', XSize=8)
ylabel = Widget_Label(sizebase, Value='Y Size:')
ysizeID = Widget_Text(sizebase, Value=ysize, All_Events=1, Editable=0, $
Event_Pro='INTEGER_ONLY', XSize=8)
zlabel = Widget_Label(sizebase, Value='Frames:')
frameID = Widget_Text(sizebase, Value=frames, All_Events=1, Editable=0, $
Event_Pro='INTEGER_ONLY', XSize=8)
; Create cancel and accept buttons.
cancelbase = Widget_Base(tlb, Column=2, Frame=1)
cancel = Widget_Button(cancelbase, Value='Cancel')
accept = Widget_Button(cancelbase, Value='Accept')
; Realize the program.
Widget_Control, tlb, /Realize
; Create a pointer to store the information collected from the form.
ptrToFormData = Handle_Create()
; Set the correct file format in the format droplist widget.
Widget_Control, formatlistID, Set_Droplist_Select=Keyword_Set(xdr)
; Set the text insertion point at the end of the filename text widget.
tip = [StrLen(filename),0]
Widget_Control, filenameID, Input_Focus=1
Widget_Control, filenameID, Set_Text_Select=tip
; Create an info structure with program information.
info = { filenameID:filenameID, $
dirnameID:dirnameID, $
xsizeID:xsizeID, $
ysizeID:ysizeID, $
frameID:frameID, $
headerID:headerID, $
droplistID:droplistID, $
formatlistID:formatlistID, $
datatypes:datatypes, $
ptrToFormData:ptrToFormData}
; Store the info structure in the user value of the top-level base.
Widget_Control, tlb, Set_UValue=info
; The form will be a MODAL widget. This means we STOP at the
; following XManager call until the widget is destroyed.
thisRelease = StrMid(!Version.Release, 0, 1)
IF thisRelease EQ '5' THEN $
XManager, 'getimage', tlb, Event_Handler='GETIMAGE_EVENT', /No_Block ELSE $
XManager, 'getimage', tlb, Event_Handler='GETIMAGE_EVENT', /Modal
; Get the form data that was collected by the form.
Handle_Value, ptrToFormData, formdata
; If there is nothing here. Free the pointer and return.
IF N_Elements(formdata) EQ 0 THEN BEGIN
Handle_Free, ptrToFormData
RETURN, 0
ENDIF
; Did the user cancel out of the form? If so, return a 0.
IF formdata.filename EQ '' THEN BEGIN
Handle_Free, ptrToFormData
RETURN, 0
ENDIF
; Make the proper sized image array. Check for success.
image = 0
IF STRUPCASE(formdata.datatype) EQ 'INTEGER' THEN formdata.datatype = 'INT'
IF formdata.frames EQ 0 THEN $
command = 'image = Make_Array(formdata.xsize, formdata.ysize, ' + $
formdata.datatype + '=1)' ELSE $
command = 'image = Make_Array(formdata.xsize, ' + $
'formdata.ysize, formdata.frames, ' + formdata.datatype + '=1)'
check = Execute(command)
IF check EQ 0 THEN BEGIN
ok = Widget_Message("Problem making image array. Returning 0.")
RETURN, 0
ENDIF
; We can have all kinds of trouble reading data. Let's catch all
; input and output errors and alert user without crashing the program!
Catch, error
IF error NE 0 THEN BEGIN
; If we can't read the file for some reason, let the user know
; why, free the pointer and its information, check the logical
; unit number back in if it is checked out, and return a 0.
ok = Widget_Message(!Err_String)
Handle_Free, ptrToFormData
IF N_ELements(lun) NE 0 THEN Free_Lun, lun
RETURN, 0
ENDIF
; Read the data file.
IF formdata.header GT 0 THEN header = BytArr(formdata.header)
Get_Lun, lun
OpenR, lun, formdata.filename, XDR=formdata.formatIndex
IF formdata.header EQ 0 THEN ReadU, lun, image $
ELSE ReadU, lun, header, image
Free_Lun, lun
; Free the pointer.
Handle_Free, ptrToFormData
; Free up the fake TLB, if necessary.
IF N_Elements(fakeTLB) NE 0 THEN Widget_Control, fakeTLB, /Destroy
RETURN, image
END ; of GETIMAGE program ***************************************************
FUNCTION TYPEVAR, variable
; Use SIZE function to get variable info.
varInfo = Size(variable)
; The next to last element in varInfo has the data type.
typeIndex = varInfo(varInfo(0) + 1)
dataTypes = ['UNDEFINED', 'BYTE', 'INTEGER', 'LONG', 'FLOATING', $
'DOUBLE', 'COMPLEX', 'STRING', 'STRUCTURE', 'DCOMPLEX']
thisType = dataTypes(typeIndex)
RETURN, thisType
END ; *******************************************************************
FUNCTION ICON_BUTTON_EVENTS, event
; Get the info structure.
child = WIDGET_INFO(event.handler, /Child)
WIDGET_CONTROL, child, Get_UValue=info, /No_Copy
; Is this a button press event?
IF event.type EQ 0 THEN BEGIN
temp = info.index(1)
info.index(1) = info.index(2)
info.index(2) = temp
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
ICON_BUTTON_REALIZE, event.handler
RETURN, 0
ENDIF
; Pretend this is a button event. Make up a BUTTON event structure.
returnEvent = {WIDGET_BUTTON, ID:event.handler, TOP:event.top, HANDLER:0L, SELECT:1}
temp = info.index(1)
info.index(1) = info.index(2)
info.index(2) = temp
WIDGET_CONTROL, child, Set_UValue=info
ICON_BUTTON_REALIZE, event.handler
; If there is alternate event handler, send event to it.
IF (info.altPro NE '') THEN BEGIN
Call_Procedure, info.altPro, returnEvent
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
RETURN, 0
ENDIF
IF (info.altFunc NE '') THEN BEGIN
result = CALL_FUNCTION(info.altFunc, returnEvent)
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
RETURN, 0
ENDIF
; Send it to the regular event handler.
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
RETURN, returnEvent
END ; *******************************************************************
PRO ICON_BUTTON_SET, id, thisValue
; (No error checking!) You can pass in a button value
; directly as a string, or you can pass a button value
; and an image for the icon as a structure defined like
; this: struct = {value:'', image:yourImage}
child = WIDGET_INFO(id, /Child)
WIDGET_CONTROL, child, Get_UValue=info, /No_Copy
IF TYPEVAR(thisValue) EQ 'STRUCTURE' THEN BEGIN
info.value = thisValue.value
icon = CONGRID(thisValue.image, info.xsize-10, info.ysize-10)
icon = BYTSCL(icon, TOP=info.ncolors-1) + BYTE(info.bottom)
info.icon = icon
ENDIF ELSE info.value = thisValue
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
; Rebuild the button in the draw widget.
ICON_BUTTON_REALIZE, id
END ; *******************************************************************
FUNCTION ICON_BUTTON_GET, id
; The value of the button is the value text.
child = WIDGET_INFO(id, /Child)
WIDGET_CONTROL, child, Get_UValue=info, /No_Copy
retvalue = info.value
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
RETURN, retvalue
END ; *******************************************************************
PRO ICON_BUTTON_REALIZE, id
; This is where the button is drawn in the draw widget.
child = WIDGET_INFO(id, /Child)
WIDGET_CONTROL, child, Get_UValue=info, /No_Copy
; Make a pixmap window to draw into.
oldID = !D.Window
Window, /Free, XSize=info.xsize, YSize=info.ysize, /Pixmap
pixID = !D.Window
; Draw the button.
x1 = 5
x2 = info.xsize - 6
y1 = 5
y2 = info.ysize - 6
xs = info.xsize
ys = info.ysize
buttonx = [x1, x1, x2, x2, x1]
buttony = [y1, y2, y2, y1, y1]
lightx = [0, 0, xs, x2, x1, x1, 0]
lighty = [0, ys-1, ys-1, y2, y2, y1,0]
darkx = [0, x1, x2, x2, xs-1, xs-1, 0]
darky = [0, y1, y1, y2, ys-1, 0, 0]
POLYFILL, darkx, darky, Color=info.index(1), /Device
POLYFILL, lightx, lighty, Color=info.index(2), /Device
TV, info.icon, 5, 5
PLOTS, buttonx, buttony, Color=info.index(3), /Device
PLOTS, [0, x1], [0, y1], Color=info.index(3), /Device
PLOTS, [x1, 0], [y2, ys], Color=info.index(3), /Device
PLOTS, [x2, xs], [y2, ys], Color=info.index(3), /Device
PLOTS, [x2, xs], [y1, 0], Color=info.index(3), /Device
PLOTS, [0, xs-1, xs-1, 0, 0], [0, 0, ys-1, ys-1, 0], Color=info.index(0), /Device
; Make the draw widget the current graphics window.
WIDGET_CONTROL, info.drawID, Get_Value=wid
info.wid = wid
WSET, wid
; Copy the pixmap window and delete it.
WAIT, 0.1
DEVICE, COPY=[0, 0, info.xsize, info.ysize, 0, 0, pixID]
WDELETE, pixID
WSET, oldID
WIDGET_CONTROL, child, Set_UValue=info, /No_Copy
END ; *******************************************************************
FUNCTION ICON_BUTTON, parent, ColorIndex=index, XSize=xsize, $
YSize=ysize, Value=value, UValue=uvalue, YOffset=yoffset, $
Event_Pro=newprocedure, Event_Func=newfunction, XOffset=xoffset, $
NColors=ncolors, Bottom=bottom, Image=image
ON_ERROR, 1
; Check for keywords and assign defaults if necessary.
IF N_PARAMS() NE 1 THEN MESSAGE, 'Must pass parent ID as argument.'
IF N_ELEMENTS(image) EQ 0 THEN image = DIST(256)
IF N_ELEMENTS(value) EQ '' THEN value = 'BUTTON VALUE'
IF N_ELEMENTS(yoffset) EQ 0 THEN yoffset = 0
IF N_ELEMENTS(xoffset) EQ 0 THEN xoffset = 0
IF N_ELEMENTS(uvalue) EQ 0 THEN uvalue = 'ICON BUTTON'
IF N_ELEMENTS(newprocedure) EQ 0 THEN newprocedure = ''
IF N_ELEMENTS(ncolors) EQ 0 THEN ncolors = !D.N_Colors - 4
IF N_ELEMENTS(bottom) EQ 0 THEN bottom = 0
IF N_ELEMENTS(newfunction) EQ 0 THEN newfunction = ''
IF N_ELEMENTS(xsize) EQ 0 THEN xsize = 40
IF N_ELEMENTS(ysize) EQ 0 THEN ysize = 40
IF N_ELEMENTS(index) EQ 0 THEN BEGIN
index = INDGEN(4) + ncolors
TVLCT, [255, 70, 150, 255], [255, 70, 150, 255], $
[255, 70, 150, 255], ncolors
ENDIF
; Make the icon from the image data.
icon = CONGRID(image, xsize-10, ysize-10)
icon = BYTSCL(icon, TOP=ncolors-1) + BYTE(bottom)
cw_tlb = WIDGET_BASE(parent, UValue=uvalue, Event_Func='ICON_BUTTON_EVENTS', $
Notify_Realize='ICON_BUTTON_REALIZE', Pro_Set_Value='ICON_BUTTON_SET', $
Func_Get_Value='ICON_BUTTON_GET', XOffset=xoffset, YOffset=yoffset)
drawID = WIDGET_DRAW(cw_tlb, XSize=xsize, YSize=ysize, Button_Events=1)
info = { drawID:drawID, $ ; Draw widget ID.
wid:-1, $ ; Window index number of draw widget.
xsize:xsize, $ ; XSIZE of draw widget.
ysize:ysize, $ ; YSIZE of draw widget.
ncolors:ncolors, $ ; The number of colors for the image icon.
bottom:bottom, $ The starting index of the image icon colors.
icon:icon, $ ; The image that is the button icon.
value:value, $ ; The pseudo button "value".
altPro:newprocedure, $ ; The name of an alternate procedure to send event to.
altFunc:newfunction, $ ; The name of an alternate function to send event to.
index:index} ; The index array that specifies button colors values.
WIDGET_CONTROL, drawID, Set_UValue=info, /No_Copy
returnEvent = {WIDGET_BUTTON, ID:-1L, TOP:-1L, HANDLER:0-1L, SELECT:-1}
RETURN, cw_tlb
END ; *******************************************************************
PRO MakeIcon_Event, event
; Get the ID of the real application.
Widget_Control, event.top, Get_UValue=mapID
; Map the real application and destroy this icon.
Widget_Control, event.top, /Destroy
Widget_Control, mapID, Map=1
END ; ***************************************************************
PRO MakeIcon, image, mapID, NColors=ncolors, Bottom=bottom
; A procedure to make an icon out of an application.
; image -- The image that goes on the icon. It can be any size.
; mapID -- The ID of the top-level base of the application to be
; iconified.
; ncolors -- The number of colors used for the icon.
; bottom -- The starting color index of the colors.
; Check for default values of keywords.
IF N_Elements(ncolors) EQ 0 THEN ncolors=!D.N_Colors-1
IF N_Elements(bottom) EQ 0 THEN bottom=0
; Unmap the application.
Widget_Control, mapID, Map=0
; Get the display size.
Device, Get_Screen_Size=srcSize
; Create the widgets. Use the compound widget ICON_BUTTON to
; create the icon.
tlb = Widget_Base(UValue=mapID, XOffset=20, YOffset=srcSize(1) - 60, $
TLB_Frame_Attr=11, Title='Icon')
button = Icon_Button(tlb, Image=image, NColors=ncolors, Bottom=bottom)
Widget_Control, tlb, /Realize
XManager, 'makeicon', tlb
END ; ***************************************************************
PRO Example_Quit, event
Widget_Control, event.top, /Destroy
END ; ***************************************************************
PRO Example_Iconify, event
; Iconify the application.
Widget_Control, event.top, Get_UValue=info, /No_Copy
MakeIcon, info.currentImage, event.top, NColors=info.currentColors, $
Bottom=info.currentBottom
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example_Controls, event
; Map the control droplist widget in the window.
Widget_Control, event.top, Get_UValue=info, /No_Copy
Widget_Control, info.controlID, Map=1
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example_Droplist_Events, event
; Respond to the droplist events. Unmap controls after
; each event.
Widget_Control, event.top, Get_UValue=info, /No_Copy
Widget_Control, event.id, Get_UValue=choices
; Draw into display window.
WSet, info.wid
CASE choices(event.index) OF
'Sobel': BEGIN
data = Sobel(info.currentImage)
data = BytScl(data, Top=info.currentColors-1) + Byte(info.currentBottom)
TV, data
END
'Roberts': BEGIN
data = Roberts(info.currentImage)
data = BytScl(data, Top=info.currentColors-1) + Byte(info.currentBottom)
TV, data
END
'Median': BEGIN
data = Median(info.currentImage, 5)
data = BytScl(data, Top=info.currentColors-1) + Byte(info.currentBottom)
TV, data
END
'Smooth 5': BEGIN
data = Smooth(info.currentImage, 5)
data = BytScl(data, Top=info.currentColors-1) + Byte(info.currentBottom)
TV, data
END
'Original': TV, info.currentImage
ENDCASE
; Unmap controls in display window.
Widget_Control, info.controlID, Map=0
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example_Load, event
; Load a new image. Requires the training program GETIMAGE.PRO.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Let user select image file.
image = GetImage()
; Anything go wrong reading the data? If "yes", out of here!
s = Size(image)
IF s(0) NE 2 THEN BEGIN
Widget_Control, event.top, Set_UValue=info, /No_Copy
RETURN
ENDIF
; Update the icon for the new image.
Widget_Control, info.id, Set_Value={value:'newimage', image:image}
; Make the display window active.
WSet, info.wid
; Display the new image after sizing and scaling.
data = Congrid(image, 350, 350)
data = BytScl(data, Top=info.currentColors) + Byte(info.currentBottom)
TV, data
; Update info structure with new image.
info.currentImage = data
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example_Colors, event
; Load colors for images. Requires training program XCOLORS.PRO.
Widget_Control, event.top, Get_UValue=info, /No_Copy
XColors, NColors=info.currentColors, Bottom=info.currentBottom
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example_Icon_Events, event
; Handles events from the image icons. Get information.
Widget_Control, event.top, Get_UValue=info, /No_Copy
Widget_Control, event.id, Get_UValue=buttonUValue, /No_Copy
; Display the icon image.
TV, buttonUValue.image
; Update the info structure.
info.currentImage = buttonUValue.image
info.currentColors = buttonUValue.ncolors
info.currentBottom = buttonUValue.bottom
info.id = event.id
Widget_Control, event.id, Set_UValue=buttonUValue, /No_Copy
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ***************************************************************
PRO Example
; An example program for placing free-form buttons on interface.
ON_ERROR, 1
tlb = Widget_Base(Title='Free-Form Button Example', Column=1)
; Create the button panel.
buttonbase = Widget_Base(tlb, Row=1)
quitter = Widget_Button(buttonbase, Value='Quit', $
Event_Pro='Example_Quit')
iconify = Widget_Button(buttonbase, Value='Iconify', $
Event_Pro='Example_Iconify')
loader = Widget_Button(buttonbase, Value='Load', $
Event_Pro='Example_Load')
controls = Widget_Button(buttonbase, Value='Controls', $
Event_Pro='Example_Controls')
colors = Widget_Button(buttonbase, Value='Colors', $
Event_Pro='Example_Colors')
; Create draw base as a bulletin board base.
drawbase = Widget_Base(tlb)
; Create the control panel droplist widget.
controlbase = Widget_Base(drawbase, XOffSet=10, YOffset=300, Map=0)
values = ['Sobel', 'Roberts', 'Median', 'Smooth 5', 'Original']
controls = Widget_DropList(controlbase, Value=values, UValue=values, $
Event_Pro='Example_Droplist_Events')
; Load the files for the various icons. These should be in the
; EXAMPLES/DATA directory of the main IDL distribution. Build
; icons as you go with the compound widget ICON_BUTTON. Store
; icon information in the button's user value.
CATCH, thisError
IF thisError NE 0 THEN BEGIN
ok = Widget_Message(['Problem reading data. Check image location', $
'Should be: !DIR/examples/data'])
RETURN
ENDIF
file = Filepath(Subdir=['examples', 'data'], 'cereb.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(512,512)
ReadU, lun, image
image = BytScl(Congrid(image, 350, 350), Top=39)
LoadCT, 3, NColors=40, Bottom=0
Free_Lun, lun
button = Icon_Button(drawbase, Image=image, Value='cereb.dat', $
XOffset=375, YOffset=15, NColors=40, $
ColorIndex=Indgen(4) + 200, Bottom=0)
uval = {image:image, ncolors:40, bottom:0, id:button}
Widget_Control, button, Set_UValue=uval
currentID = button
file = Filepath(Subdir=['examples', 'data'], 'galaxy.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(256,256)
ReadU, lun, image
image = BytScl(Congrid(image, 350, 350), Top=39) + 40B
LoadCT, 26, NColors=40, Bottom=40
Free_Lun, lun
button = Icon_Button(drawbase, Image=image, Value='galaxy.dat', $
XOffset=375, YOffset=85, NColors=40, $
ColorIndex=Indgen(4) + 200, Bottom=40)
uval = {image:image, ncolors:40, bottom:40, id:button}
Widget_Control, button, Set_UValue=uval
file = Filepath(Subdir=['examples', 'data'], 'people.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(192,192)
ReadU, lun, image
image = BytScl(Congrid(image, 350, 350), Top=39) + 80B
LoadCT, 0, NColors=40, Bottom=80
Free_Lun, lun
button = Icon_Button(drawbase, Image=image, Value='people.dat', $
XOffset=375, YOffset=155, NColors=40, $
ColorIndex=Indgen(4) + 200, Bottom=80)
uval = {image:image, ncolors:40, bottom:80, id:button}
Widget_Control, button, Set_UValue=uval
file = Filepath(Subdir=['examples', 'data'], 'abnorm.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(64,64)
ReadU, lun, image
image = BytScl(Congrid(image, 350, 350), Top=39) + 120B
LoadCT, 11, NColors=40, Bottom=120
Free_Lun, lun
button = Icon_Button(drawbase, Image=image, Value='abnorm.dat', $
XOffset=375, YOffset=225, NColors=40, $
ColorIndex=Indgen(4) + 200, Bottom=120)
uval = {image:image, ncolors:40, bottom:120, id:button}
Widget_Control, button, Set_UValue=uval
file = Filepath(Subdir=['examples', 'data'], 'worldelv.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(360,360)
ReadU, lun, image
image = BytScl(Congrid(image, 350, 350), Top=39) + 160B
LoadCT, 4, NColors=40, Bottom=160
Free_Lun, lun
button = Icon_Button(drawbase, Image=image, Value='worldelv.dat', $
XOffset=375, YOffset=295, NColors=40, $
ColorIndex=Indgen(4) + 200, Bottom=160)
uval = {image:image, ncolors:40, bottom:160, id:button}
Widget_Control, button, Set_UValue=uval
drawID = Widget_Draw(drawbase, XSize=450, YSize=350)
file = Filepath(Subdir=['examples', 'data'], 'cereb.dat')
OpenR, lun, file, /Get_Lun
image = Bytarr(512,512)
ReadU, lun, image
Free_Lun, lun
image = Congrid(image, 350,350)
; Cancel error handling.
Catch, /Cancel
; Load colors for the icon button's boundaries.
TVLCT, [255, 70, 150, 255], [255, 70, 150, 255], $
[255, 70, 150, 255], 200
Widget_Control, tlb, /Realize
Widget_Control, drawID, Get_Value=wid
WSet, wid
image = BytScl(image, Top=39)
TV, image
info = { wid:wid, $ ; Window index number of display.
currentImage:image, $ ; The current image on display.
currentColors:40, $ ; Number of colors used by current image.
currentBottom:0, $ ; Index where current colors are loaded.
id:currentID, $ ; Icon button ID.
controlID:controlbase } ; ID of control base for mapping controls.
Widget_Control, tlb, Set_UValue=info, /No_Copy
XManager, 'example', tlb, Event_Handler='Example_Icon_Events'
END ; ***********************************************************************