Viewing contents of file '../idllib/contrib/fanning/chgcolor.pro'
;+
; NAME:
; CHGCOLOR
;
; PURPOSE:
; The purpose of this routine is to allow the user to change
; the color at a particular color index. The user is able to
; mix their own color by manipulating red, green, and blue
; sliders. This routine is ideal for changing axes or background
; colors of a plot, for example. The routine works on 8-bit,
; 16-bit, and 24-bit displays.
;
; AUTHOR:
; FANNING SOFTWARE CONSULTING
; David Fanning, Ph.D.
; 2642 Bradbury Court
; Fort Collins, CO 80521 USA
; Phone: 970-221-0438
; E-mail: davidf@dfanning.com
; Coyote's Guide to IDL Programming: http://www.dfanning.com
;
; CATEGORY:
; Widgets, Colors.
;
; CALLING SEQUENCE:
; CHGCOLOR, index
;
; REQUIRED INPUTS:
; INDEX: The color index to be changed. It must be a value
; between 0 and 255.
;
; KEYWORD PARAMETERS:
;
; LABEL: Text that goes next to the color window. The default is
; "Resulting Color".
;
; GROUP_LEADER: The group leader for this program. When the group leader
; is destroyed, this program will be destroyed.
;
; NOTIFYID: A a 2 column by n row array that contains the IDs of widgets
; that should be notified when CHGCOLOR changes a color. The first
; column of the array contains widgets that should be notified. The
; second column contains IDs of widgets that are at the top of the
; hierarch in which the corresponding widgets in the first column
; are located. (The purpose of the top widget IDs is to make it
; possible for the widget in the first column to get the "info"
; structure of the widget program.) An CHGCOLOR_LOAD event will be
; sent to the widget identified in the first column. The event
; structure is defined like this:
;
; event = {CHGCOLOR_LOAD, ID:0L, TOP:0L, HANDLER:0L, $
; r:(!D.N_COLORS < 256), g:(!D.N_COLORS < 256), b:(!D.N_COLORS < 256)}
;
; The ID field will be filled out with NOTIFYID(0, n) and the TOP
; field will be filled out with NOTIFYID(1, n).
;
; TITLE: This is the window title. It is "Modify Drawing Color" by
; default. The program is registered with the name "chgcolor " plus
; the TITLE string. The register name is checked before the widgets
; are defined. This gives you the opportunity to have multiple copies
; of CHGCOLOR operating simultaneously. (For example, one will change
; the background color and one will change the plotting color.)
;
; XOFFSET: This is the X offset of the program on the display. The
; program will be placed approximately in the middle of the display
; by default.
;
; YOFFSET: This is the Y offset of the program on the display. The
; program will be placed approximately in the middle of the display
; by default.
;
; COMMON BLOCKS:
; None.
;
; SIDE EFFECTS:
; Color at the specified index is changed. Events are sent to widgets
; if the NOTIFYID keyword is used.
;
; RESTRICTIONS:
; None.
;
; EXAMPLE:
; To change the background color of a plot, type:
;
; CHGCOLOR, !P.Background
;
; To see a more complete example, look at the program SLICE
; in the Coyote Software Library:
;
; ftp://ftp.frii.com/pub/dfanning/outgoing/idl_examples
;
; MODIFICATION HISTORY:
; Written by David Fanning, 23 April 97.
; 12 May 97, Fixed a bug in the way colors were loaded when
; a tracking event occurred. DWF
; 13 May 97, Added a JUST_REGISTER keyword and set it up for
; running in IDL 5.0 as a non-blocking widget.
; 27 Sept 98. Fixed problems caused by IDL 5.1 color changes.
; 27 Sept 98. Removed JUST_REGISTER keyword. Made widget non-blocking.
; 03 Nov 98. Modified layout and added slider ganging. DWF.
;-
PRO CHGCOLOR_GANG, event
WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
CASE info.gang OF
0: info.gang = 1
1: info.gang = 0
ENDCASE
WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
END ; of CHGCOLOR_GANG event handler *************************************
PRO CHGCOLOR_SLIDERS, event
WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
; If sliders are ganged, move all of them.
IF info.gang THEN BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=thisValue
WIDGET_CONTROL, info.redID, SET_VALUE=thisValue
WIDGET_CONTROL, info.greenID, SET_VALUE=thisValue
WIDGET_CONTROL, info.blueID, SET_VALUE=thisValue
ENDIF
; Get the values from the sliders and load them.
WIDGET_CONTROL, info.redID, GET_VALUE=rThis
WIDGET_CONTROL, info.greenID, GET_VALUE=gThis
WIDGET_CONTROL, info.blueID, GET_VALUE=bThis
TVLCT, rThis, gThis, bThis, info.index
TVLCT, r, g, b, /Get
Device, Get_Visual_Depth=thisDepth
IF thisDepth GT 8 THEN BEGIN
WSET, info.wid
TV, info.colorimage
ENDIF
; 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 = { CHGCOLOR_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
; Make REVERT button sensitive.
WIDGET_CONTROL, info.original, SENSITIVE=1
WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
END ; of CHGCOLOR_SLIDERS event handler *********************
PRO CHGCOLOR_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
; Load the current color on the sliders.
WIDGET_CONTROL, info.redID, GET_VALUE=rThis
WIDGET_CONTROL, info.greenID, GET_VALUE=gThis
WIDGET_CONTROL, info.blueID, GET_VALUE=bThis
TVLCT, rThis, gThis, bThis, info.index
; Put the info structure back in storage location.
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ; ******************************************************************
PRO CHGCOLOR_QUIT, event
WIDGET_CONTROL, event.top, /DESTROY
END ; of CHGCOLOR_QUIT event handler ***********************************
PRO CHGCOLOR_ORIGINAL, event
WIDGET_CONTROL, event.top, GET_UVALUE=info, /NO_COPY
; Load original color.
TVLCT, info.rThis, info.gThis, info.bThis, info.index
TVLCT, r, g, b, /Get
Device, Get_Visual_Depth=thisDepth
IF thisDepth GT 8 THEN BEGIN
WSET, info.wid
TV, info.colorimage
ENDIF
; 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 = { CHGCOLOR_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
; Update the sliders.
WIDGET_CONTROL, info.redID, SET_VALUE=info.rThis
WIDGET_CONTROL, info.greenID, SET_VALUE=info.gThis
WIDGET_CONTROL, info.blueID, SET_VALUE=info.bThis
; Make REVERT button insensitive.
WIDGET_CONTROL, info.original, SENSITIVE=0
WIDGET_CONTROL, event.top, SET_UVALUE=info, /NO_COPY
END ; of CHGCOLOR_ORIGINAL event handler ******************************
PRO CHGCOLOR, index, LABEL=labeltext, GROUP_LEADER=group, $
XOFFSET=xoffset, YOFFSET=yoffset, TITLE=title, NOTIFYID=notifyid, $
JUST_REGISTER=just_register
; Procedure to change the color of a specified index.
ON_ERROR, 1
np = N_PARAMS()
IF np EQ 0 THEN MESSAGE, 'Must pass a color index as argument.'
IF index LT 0 OR index GT 255 THEN $
MESSAGE, 'Color index parameter must be in range 0-255.'
IF N_ELEMENTS(labeltext) EQ 0 THEN labeltext = 'Resulting Color'
IF N_ELEMENTS(title) EQ 0 THEN title = 'Modify Drawing Color'
IF N_ELEMENTS(notifyID) EQ 0 THEN notifyid = [-1L, -1L]
registerTitle = 'chgcolor ' + title
; 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 - 75
IF N_ELEMENTS(yoffset) EQ 0 THEN yoffset = yCenter - 50
; Get the current color.
TVLCT, r, g, b, /GET
rThis = r(index)
gThis = g(index)
bThis = b(index)
; Make sure only one program with this register title on display.
IF XREGISTERED(registerTitle) THEN RETURN
tlb = WIDGET_BASE(COLUMN=1, TLB_FRAME_ATTR=1, BASE_ALIGN_CENTER=1,$
XOFFSET=xoffset, YOFFSET=yoffset, TITLE=title, TRACKING=1)
colorbase = WIDGET_BASE(COLUMN=1, tlb,SCR_XSIZE=256, /FRAME)
label = WIDGET_LABEL(colorbase, VALUE=labeltext, ALIGN_CENTER=1)
drawID = WIDGET_DRAW(colorbase, XSIZE=50, YSIZE=30, ALIGN_CENTER=1)
sliderbase = WIDGET_BASE(tlb, COLUMN=1, FRAME=1, BASE_ALIGN_CENTER=1, $
EVENT_PRO='CHGCOLOR_SLIDERS')
label = WIDGET_LABEL(sliderbase, VALUE='Mix Primary Colors')
redID = WIDGET_SLIDER(sliderbase, SCR_XSIZE=250, VALUE=rThis, $
MAX=255, MIN=0, Title='Red')
greenID = WIDGET_SLIDER(sliderbase, SCR_XSIZE=250, VALUE=gThis, $
MAX=255, MIN=0, Title='Green')
blueID = WIDGET_SLIDER(sliderbase, SCR_XSIZE=250, VALUE=bThis, $
MAX=255, MIN=0, Title='Blue')
exbutbase = WIDGET_BASE(sliderbase, SCR_XSIZE=250, /NonExclusive)
exbutton = WIDGET_BUTTON(exbutbase, Value='Gang Sliders', $
EVENT_PRO='CHGCOLOR_GANG', ALIGN_CENTER=1)
buttonbase = WIDGET_BASE(tlb, ROW=1, Align_Center=1)
original = WIDGET_BUTTON(buttonbase, VALUE='Cancel', $
EVENT_PRO='CHGCOLOR_ORIGINAL')
quitter = WIDGET_BUTTON(buttonbase, VALUE='Accept', $
EVENT_PRO='CHGCOLOR_QUIT')
WIDGET_CONTROL, tlb, /REALIZE
WIDGET_CONTROL, original, SENSITIVE=0
WIDGET_CONTROL, drawID, GET_VALUE=wid
WSET, wid
; Draw the color in the draw widget.
colorimage = REPLICATE(1B, 50, 30) * BYTE(index)
TV, colorimage
info = { wid:wid, $ ; Draw widget window index number.
redID:redID, $ ; ID of red slider.
greenID:greenID, $ ; ID of green slider.
blueID:blueID, $ ; ID of blue slider.
notifyID:notifyID, $ ; Widgets to notify of color change.
original:original, $ ; ID of the "Revert" button.
colorimage:colorimage, $
index:index, $ ; Index of color you want to change.
gang:0, $ ; Flag to indicate if sliders are ganged.
rThis:rthis, $ ; Current red value of indexed color.
gThis:gThis, $ ; Current green value of indexed color.
bThis:bThis} ; Current blue value of indexed color.
WIDGET_CONTROL, tlb, SET_UVALUE=info, /NO_COPY
XMANAGER, registerTitle, tlb, GROUP_LEADER=group, $
EVENT_HANDLER='CHGCOLOR_PROTECT_COLORS', /NO_BLOCK
END