; $Id: cw_color_button.pro,v 1.16 2005/07/06 16:34:25 rdimeo Exp $
; +
; NAME:
;  CW_COLOR_BUTTON
;
; PURPOSE:
;  Compound widget that can be configured to have the same
;  functionality as a conventional WIDGET BUTTON and even extended
;  to have a light toggle functionality.  Programmer can display a
;  STOP sign by setting the STOP keyword.
;
;  See the program appended to the end of this code listing for
;  an example of how each of these modes work.
;
; CALLING SEQUENCE:
;  ID = CW_COLOR_BUTTON(   PARENT,                          $
;                          BUTTON_SIZE = button_size,       $
;                          STOP = stop,                     $
;                          PAUSE = pause,                   $
;                          BG_COLOR = bg_color,             $
;                          XOFFSET = xoffset,               $
;                          YOFFSET = yoffset,               $
;                          UNAME = uname,                   $
;                          UVALUE = uvalue,                 $
;                          XSIZE = xsize,                   $
;                          YSIZE = ysize,                   $
;                          ROW = row,                       $
;                          STATE = 0,                       $
;                          RADIO = radio                    )
;
;
; PARAMETERS:  (required)
;
;  PARENT:     widget ID of the parent of this compound widget
;
; KEYWORDS:    (optional)
;
;  BG_COLOR:   RGB triplet specifying the color of the background of
;              the LED.  The default is the color of the widget background.
;  STOP:       Set this keyword to display a "STOP" sign on the button.  This
;              functions only as a pushbutton (not a radio button).
;  PAUSE:      Set this keyword to display a "PAUSE/RESUME" sign on the button.
;              This functions only as a radio button.
;  BUTTON_SIZE:Diameter of the button in pixels.
;  XOFFSET:    The horizontal offset of the widget in units in pixels
;              relative to its parent.
;  YOFFSET:    The vertical offset of the widget in units in pixels
;              relative to its parent.
;  UNAME:      Set this keyword to a string that can be used to identify
;              the widget in your code.  You can associate a name with each
;              widget in a specific hierarchy, and then use that name to
;              query the widget hierarchy and get the correct widget ID.
;
;  UVALUE:     A user value to assign to the CW.  This value can be
;              of any type.
;  XSIZE:      Horizontal size of the draw widget (in pixels)
;  YSIZE:      Vertical size of the draw widget (in pixels)
;  EVENT_FUNC: Event function to be called when button is released.
;  EVENT_PRO:  Event procedure to be called when button is released.
;  ROW:        Set this keyword to arrange the label on the left of the button.  The
;              default is to place the label just above the button.
;  RADIO:      Set this keyword to allow the button to function as a "toggle".  This
;              keyword is not relevant if the button is a "STOP" sign.
;  STATE:      Initial state of the button (on or off) if it is a RADIO button.  Note
;              that STATE is only meaningful if the RADIO keyword is set.  This
;              keyword is not relevant if this is a "STOP" sign.
;
;  Note that both EVENT_FUNC and EVENT_PRO will use the following event structure
;  as an argument.
;
; EVENT STRUCTURE:
;  EVENT =  {  CW_COLOR_BUTTON_EVENT,     $
;              ID:0L,                     $
;              TOP:0L,                    $
;              HANDLER:0L,                $
;              SELECT:0B                  }
;
; SIDE EFFECTS:
;  -This widget generates button events upon button release only.
;  -This widget cannot be resized.
;  -If the RADIO keyword is set then the SELECT value in the event structure
;   is either 1 or 0 (set/unset respectively).
;  -If the RADIO button is not set then the SELECT value is always 1.
;
; COMMON BLOCKS:
;  None
;
; REQUIRED PROGRAMS:
;  SOURCEROOT.PRO (Can be downloaded from http://tinyurl.com/8l78c)
;
; REQUIRED RESOURCES:
;  BIG_STOP.PNG (Included in this standalone distribution and the DAVE distribution)
;  Stop sign image is from Traffic Signs & Decals web site....
;              http://parkingsignsbypac.safeshopper.com/
;  PAUSE.PNG and RESUME.PNG (Included in the standalone distribution and the
;     DAVE distribution.
;
; REQUIREMENTS:
;  IDL 6.0 and higher (due to use of ARRAY_INDICES)
;  24-Bit color required
;
; EXAMPLE USAGE: (appended to end of this file)
;  Compile this file then
;  IDL> CB_EXAMPLE
;
; AUTHOR:
;  Robert M. Dimeo, Ph.D.
;  NIST Center for Neutron Research
;  100 Bureau Drive
;  Mail Stop 8562
;  Gaithersburg, MD 20899
;  Phone: (301) 975-8135
;  E-mail: robert.dimeo@nist.gov
;  http://www.ncnr.nist.gov/staff/dimeo
;
; MODIFICATION HISTORY:
;  Written 5/20/05
;  -Cleaned up the button press/release handling in favor of
;   "release" events only (RMD-05/23/05)
;  -Added capability to display a "STOP" sign button(RMD-05/27/05)
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used or if the code in this file is
;  included in another product.
; -
; *************************************** ;
pro rmd_color_button::cleanup
ptr_free,self.on_ptr,self.off_ptr,self.storage
wdelete,self.winpix
end
; *************************************** ;
pro rmd_color_button::set_property, winpix = winpix,        $
                                    winvis = winvis,        $
                                    value = value,          $
                                    color = color,          $
                                    xoffset = xoffset,      $
                                    yoffset = yoffset,      $
                                    tooltip = tooltip,      $
                                    state = state

if n_elements(tooltip) ne 0 then begin
   self.tooltip = tooltip
   widget_control,self.win_id,tooltip = self.tooltip
endif
if n_elements(xoffset) ne 0 then self.xoffset = xoffset
if n_elements(yoffset) ne 0 then self.yoffset = yoffset
if n_elements(color) ne 0 then begin
   self.color = color
   ret = self->init_colors()
   if self.radio then begin
      if self.state then ret = self->on() else ret = self->off()
   endif else begin
      ret = self->on()
   endelse
endif
if n_elements(state) ne 0 then self.state = state
if self.state then ret = self->on() else ret = self->off()
if n_elements(winpix) ne 0 then self.winpix = winpix
if n_elements(winvis) ne 0 then self.winvis = winvis
if n_elements(value) ne 0 then self.label = value
end
; *************************************** ;
function rmd_color_button::toggle_state
if self.state eq 0B then self.state = 1B else self.state = 0B
if self.state then ret = self->on() else ret = self->off()
return,1B
end
; *************************************** ;
pro rmd_color_button::get_property, tlb = tlb,                 $
                                    win_id = win_id,           $
                                    winpix = winpix,           $
                                    winvis = winvis,           $
                                    xsize = xsize,             $
                                    ysize = ysize,             $
                                    value = value,             $
                                    uname = uname,             $
                                    xoffset = xoffset,         $
                                    yoffset = yoffset,         $
                                    label_id = label_id,       $
                                    event_func = event_func,   $
                                    event_pro = event_pro,     $
                                    state = state,             $
                                    radio = radio,             $
                                    tooltip = tooltip,         $
                                    uvalue = uvalue
xoffset = self.xoffset
yoffset = self.yoffset
tooltip = self.tooltip
radio = self.radio
state = self.state
event_pro = self.event_pro
event_func = self.event_func
label_id = self.label_id
uname = self.uname
uvalue = *self.storage
value = self.label
tlb = self.tlb
win_id = self.win_id
winpix = self.winpix
winvis = self.winvis
xsize = self.button_size
ysize = self.button_size
end
; *************************************** ;
function rmd_color_button::eventhandler,event
; Process the "internal" button events
if event.id eq self.win_id then begin
; Do not process right mouse button events
   if (event.press eq 4) or (event.release eq 4) then return,0
   if event.type eq 0 then begin ; button press in the window
      if self.radio then begin
         ; Toggle the button light [on <--> off]
         if event.press ne 4 then ret_val = self->toggle_state()
      endif else begin
         ; Turn the button light off momentarily
         if event.press ne 4 then ret_val = self->off()
      endelse
      return,0
   endif
   if event.release eq 1 then begin ; button release in the draw widget
      ; Turn the light back on
      if ~self.radio then ret_val = self->on()
   endif
endif

; Now process the "external" events
ev =  {  WIDGET_BUTTON,                   $
         id:self.tlb,                     $
         top:event.top,                   $
         handler:event.handler,           $
         select:self.state                }

if self.event_pro ne "" then begin
   call_procedure,self.event_pro,ev
   return,0
endif
if self.event_func ne "" then begin
   void = call_function(self.event_func,ev)
   return,0
endif

return,ev
end
; *************************************** ;
function rmd_color_button_event,event
stash = widget_info(widget_info(event.id,/parent),/child)
widget_control,stash,get_uvalue = the_object
the_event = the_object->eventhandler(event)
return,the_event
end
; *************************************** ;
pro rcb_kill_notify,id
widget_control,id,get_uvalue = the_object
obj_destroy,the_object
end
; *************************************** ;
function rmd_color_button::on
device,get_decomposed = dc
device,decomposed = 1
wset,self.winpix
tv,*self.on_ptr,/true
wset,self.winvis
device,copy = [0,0,self.button_size,self.button_size,0,0,self.winpix]
device,decomposed = dc
return,1B
end
; *************************************** ;
function rmd_color_button::off
device,get_decomposed = dc
device,decomposed = 1
wset,self.winpix
tv,*self.off_ptr,/true
wset,self.winvis
device,copy = [0,0,self.button_size,self.button_size,0,0,self.winpix]
device,decomposed = dc
return,1B
end
; *************************************** ;
function rmd_color_button::realize
device,get_decomposed = dc
device,decomposed = 1

self->get_property,xsize = xsize,ysize = ysize, $
   win_id = win_id,state = state,radio = radio
widget_control,win_id,get_value = winvis

if self.pause then begin
   s = size(*self.on_ptr)
   aspect = 1./(float(s[2])/float(s[3]))
   xsize = self.button_size
   ysize = self.button_size*aspect
endif else begin
   xsize = self.button_size
   ysize = self.button_size
endelse
widget_control,self.win_id,draw_xsize = xsize,draw_ysize = ysize
window,/free,/pixmap,xsize = xsize,ysize = ysize
self.winpix = !d.window
self.winvis = winvis
; Set the initial state of the button
if radio then begin
   ; Need the "STATE" variable setting
   if state then ret = self->on() else ret = self->off()
endif else begin
   ; The default is to keep the button "lit" if the RADIO keyword
   ; is not set.
   ret = self->on()
endelse
; Set the cursor to the standard arrow (on Windows) so that
; the user doesn't know that he/she's using a draw widget here
; (where it would turn into a cross-hairs).
device,/cursor_original
device,decomposed = dc
return,1B
end
; *************************************** ;
pro rcb_notify_realize,id
stash = widget_info(widget_info(id,/parent),/child)
widget_control,stash,get_uvalue = the_object
ret = the_object->realize()
end
; *************************************** ;
pro rcb_set_value,id,newvalue
stash = widget_info(id,/child)
widget_control,stash,get_uvalue = the_object
the_object->get_property,label_id = label_id
widget_control,label_id,set_value = newvalue
the_object->set_property,value = newvalue
end
; *************************************** ;
function rmd_color_button::get_value
if ~self.pause then                    $
   self->get_property,value = value    $
else begin
   if self.state then value = 'PAUSE'  $
      else value = 'RESUME'
endelse
return,value
end
; *************************************** ;
function rcb_get_value,id
widget_control,widget_info(id,/child),get_uvalue = o
return,o->get_value()
end
; *************************************** ;
function rmd_color_button::build_widgets
if self.label ne '' then begin
   if ~self.row then begin
      tlb = widget_base(self.parent,/col,uvalue = *self.storage,  $
         uname = self.uname,$
         pro_set_value = 'rcb_set_value',                         $
         func_get_value = 'rcb_get_value',/base_align_center,     $
         xoffset = self.xoffset,yoffset = self.yoffset            )
   endif else begin
      tlb = widget_base(self.parent,/row,uvalue = *self.storage,  $
         uname = self.uname,$
         pro_set_value = 'rcb_set_value',                         $
         func_get_value = 'rcb_get_value',/base_align_center,     $
         xoffset = self.xoffset,yoffset = self.yoffset            )
   endelse
endif else begin
      tlb = widget_base(self.parent,uvalue = *self.storage,       $
         uname = self.uname,$
         pro_set_value = 'rcb_set_value',                         $
         func_get_value = 'rcb_get_value',/base_align_center,     $
         xoffset = self.xoffset,yoffset = self.yoffset            )
endelse
self.tlb = tlb
self.label_id = widget_label(tlb,value = self.label,  $
   uvalue = self,kill_notify = 'RCB_KILL_NOTIFY',     $
   uname = 'RCB_STASH',/dynamic_resize                )
if self.tooltip eq '' then begin
   self.win_id = widget_draw(tlb,xsize = self.button_size, tooltip = self.tooltip,  $
      ysize = self.button_size,notify_realize = 'RCB_NOTIFY_REALIZE',   $
      /button_events,/align_center,event_func = 'RMD_COLOR_BUTTON_EVENT')
endif else begin
   self.win_id = widget_draw(tlb,xsize = self.button_size,  $
      ysize = self.button_size,notify_realize = 'RCB_NOTIFY_REALIZE',   $
      /button_events,/align_center,tooltip = self.tooltip,event_func = 'RMD_COLOR_BUTTON_EVENT')
endelse
return,1B
end
; *************************************** ;
function rmd_color_button::init_pause
base = widget_base()
gray = (widget_info(base,/system_colors)).face_3d
widget_control,base,/destroy
; Check to see if we're running from the DAVE software
; system.  If so then we can find the PAUSE/RESUME signs
; in the auxiliary directory.  If not then the assumption
; is that the file exists in the *same* directory as this
; module.
defsysv, '!DAVE_AUXILIARY_DIR', exists = exist
pause_filename = 'pause.png'
resume_filename = 'resume.png'
if ~exist then begin
   pause_file = sourceroot()+pause_filename
   resume_file = sourceroot()+resume_filename
endif else begin
   pause_file = !DAVE_AUXILIARY_DIR+pause_filename
   resume_file = !DAVE_AUXILIARY_DIR+resume_filename
endelse

pause_img = read_png(pause_file)
resume_img = read_png(resume_file)
pause_img_size = size(pause_img)
resume_img_size = size(resume_img)
pxsize = pause_img_size[2] & pysize = pause_img_size[3]
rxsize = resume_img_size[2] & rysize = resume_img_size[3]

img = pause_img
condition = (reform(img[0,*,*],pxsize,pysize) gt 250B) and   $
            (reform(img[1,*,*],pxsize,pysize) gt 250B) and   $
            (reform(img[2,*,*],pxsize,pysize) gt 250B)

gray_ind = where(condition,count)
gray_indices = array_indices(bytarr(pxsize,pysize),gray_ind)
sg = size(gray_indices)
for j = 0,sg[2]-1 do $
   for i = 0,2 do    $
      img[i,gray_indices[0,j],gray_indices[1,j]] = gray[i]

img_on = img

img = resume_img
condition = (reform(img[0,*,*],rxsize,rysize) gt 250B) and   $
            (reform(img[1,*,*],rxsize,rysize) gt 250B) and   $
            (reform(img[2,*,*],rxsize,rysize) gt 250B)

gray_ind = where(condition,count)
gray_indices = array_indices(bytarr(rxsize,rysize),gray_ind)
sg = size(gray_indices)
for j = 0,sg[2]-1 do $
   for i = 0,2 do    $
      img[i,gray_indices[0,j],gray_indices[1,j]] = gray[i]

condition1 =(reform(img[0,*,*],rxsize,rysize) gt 240B) and     $
            (reform(img[1,*,*],rxsize,rysize) lt 15B) and       $
            (reform(img[2,*,*],rxsize,rysize) lt 15B)
green_ind = where(condition1)
green_indices = array_indices(bytarr(rxsize,rysize),green_ind)
sg = size(green_indices)
green = [0B,255B,0B]
for j = 0,sg[2]-1 do $
   for i = 0,2 do    $
      img[i,green_indices[0,j],green_indices[1,j]] = green[i]

img_off = img
s = size(img)
aspect = 1./(float(s[2])/float(s[3]))

self.radio = 1B
img_on = congrid(img_on,3,self.button_size,self.button_size*aspect)
img_off = congrid(img_off,3,self.button_size,self.button_size*aspect)
*self.on_ptr = img_on
*self.off_ptr = img_off
return,1B
end
; *************************************** ;
function rmd_color_button::init_stop
base = widget_base()
gray = (widget_info(base,/system_colors)).face_3d
widget_control,base,/destroy
; Check to see if we're running from the DAVE software
; system.  If so then we can find the STOP sign in the
; auxiliary directory.  If not then the assumption is
; that the file exists in the *same* directory as this
; module.
defsysv, '!DAVE_AUXILIARY_DIR', exists = exist
filename = 'big_stop.png'
if ~exist then $
   stop_file = sourceroot()+filename      $
else  $
   stop_file = !DAVE_AUXILIARY_DIR+filename

if ~file_test(stop_file) then begin
   ; Since we cannot find the file at this point then
   ; we should replace the STOP sign with a red button
   ; of the same size.
   self.stop = 0B
   self.color = 'red'
   ret = self->init_colors()
   return,1B
endif
img = read_png(stop_file)
img_size = size(img)
xsize = img_size[2] & ysize = img_size[3]

xm = rebin(indgen(xsize),xsize,ysize,/sample)
ym = rebin(transpose(indgen(ysize)),xsize,ysize,/sample)

condition = (reform(img[0,*,*],xsize,ysize) lt 5B) and   $
            (reform(img[1,*,*],xsize,ysize) lt 5B) and   $
            (reform(img[2,*,*],xsize,ysize) lt 5B)

gray_ind = where(condition,count)
gray_indices = array_indices(bytarr(xsize,ysize),gray_ind)
sg = size(gray_indices)
for j = 0,sg[2]-1 do $
   for i = 0,2 do    $
      img[i,gray_indices[0,j],gray_indices[1,j]] = gray[i]

img_on = img
; Darken the STOP sign when it is "off"
limit = 100B & img_off = (img_on > limit)-limit
for j = 0,sg[2]-1 do $
   for i = 0,2 do    $
      img_off[i,gray_indices[0,j],gray_indices[1,j]] = gray[i]

self.radio = 0B
img_on = congrid(img_on,3,self.button_size,self.button_size,/minus_one)
img_off = congrid(img_off,3,self.button_size,self.button_size,/minus_one)
*self.on_ptr = img_on
*self.off_ptr = img_off

return,1B
end
; *************************************** ;
function rmd_color_button::init_colors
light = 255B & dark = 70B & button = 170B

case self.color of
'red':   $
   begin
      light = 255B & dark = 70B & button = 170B
      index = 0
      bcolor = (lcolor = (dcolor = bytarr(3)))
      bcolor[index] = button
      lcolor[index] = light
      dcolor[index] = dark
   end
'green': $
   begin
      light = 255B & dark = 70B & button = 170B
      index = 1
      bcolor = (lcolor = (dcolor = bytarr(3)))
      bcolor[index] = button
      lcolor[index] = light
      dcolor[index] = dark
   end
'blue':  $
   begin
      light = 255B & dark = 70B & button = 170B
      index = 2
      bcolor = (lcolor = (dcolor = bytarr(3)))
      bcolor[index] = button
      lcolor[index] = light
      dcolor[index] = dark
   end
'yellow':   $
   begin
      bcolor = [255B,255B,0B]
      lcolor = [255B,255B,204B]
      dcolor = [255B,153B,0B]
   end
'purple':   $
   begin
      bcolor = [204B,0B,204B]
      lcolor = [255B,102B,255B]
      dcolor = [0,0,51]
   end
else: $
   begin
      light = 255B & dark = 70B & button = 170B
      index = 1
      bcolor = (lcolor = (dcolor = bytarr(3)))
      bcolor[index] = button
      lcolor[index] = light
      dcolor[index] = dark
   end
endcase

radius = self.button_size/2.
t = 0.25*radius
angle = 45.0
xsize = (ysize = 2*radius)
base = widget_base()
bg_color = (widget_info(base,/system_colors)).face_3d
widget_control,base,/destroy

img1 = bytarr(3,xsize,ysize)

for i = 0,2 do img1[i,*,*] = bg_color[i]
img2 = img1
xc = (xsize-1)/2.  & yc = (ysize-1)/2.

xm = rebin(indgen(xsize),xsize,ysize,/sample)
ym = rebin(transpose(indgen(ysize)),xsize,ysize,/sample)
center = ((xm-xc)^2+(ym-yc)^2) le (radius-t)^2
center_indices = where(center,count,complement = outside)
perimeter = (((xm-xc)^2 + (ym-yc)^2) le radius^2) and $
            (((xm-xc)^2 + (ym-yc)^2) ge (radius-t)^2)
perimeter_indices = where(perimeter)

angle = !radeg * atan(ym-yc,xm-xc)
angle_cond = (angle le 45.0) and (angle ge -135.0) and perimeter
angle_indices = where(angle_cond)

center_ind = array_indices(bytarr(xsize,ysize),center_indices)
perimeter_ind = array_indices(bytarr(xsize,ysize),perimeter_indices)
angle_ind = array_indices(bytarr(xsize,ysize),angle_indices)

sc = size(center_ind)
sp = size(perimeter_ind)
sa = size(angle_ind)

for j = 0,sc[2]-1 do $
   for i = 0,2 do begin
      img1[i,center_ind[0,j],center_ind[1,j]] = bcolor[i]
      img2[i,center_ind[0,j],center_ind[1,j]] = dcolor[i]
   endfor
for j = 0,sp[2]-1 do $
   for i = 0,2 do begin
      img1[i,perimeter_ind[0,j],perimeter_ind[1,j]] = lcolor[i]
      img2[i,perimeter_ind[0,j],perimeter_ind[1,j]] = dcolor[i]
   endfor
for j = 0,sa[2]-1 do $
   for i = 0,2 do begin
      img1[i,angle_ind[0,j],angle_ind[1,j]] = dcolor[i]
      img2[i,angle_ind[0,j],angle_ind[1,j]] = bcolor[i]
   endfor

if ~self.radio then begin
   *self.on_ptr = img1
   *self.off_ptr = img2
endif else begin
   *self.on_ptr = img2
   *self.off_ptr = img1
endelse
return,1B
end
; *************************************** ;
function rmd_color_button::init,parent,               $
                           button_size = button_size, $
                           stop = stop,               $
                           pause = pause,             $
                           value = value,             $
                           uname = uname,             $
                           event_pro = event_pro,     $
                           event_func = event_func,   $
                           uvalue = uvalue,           $
                           red = red,                 $
                           green = green,             $
                           blue = blue,               $
                           yellow = yellow,           $
                           purple = purple,           $
                           tooltip = tooltip,         $
                           xoffset = xoffset,         $
                           yoffset = yoffset,         $
                           radio = radio,             $
                           bg_color = bg_color,       $
                           row = row,                 $
                           state = state

if n_elements(bg_color) eq 0 then begin
   base = widget_base()
   bg_color = (widget_info(base,/system_colors)).face_3d
   widget_control,base,/destroy
endif
self.stop = keyword_set(stop)
self.pause = keyword_set(pause)
self.bg_color = bg_color
if n_elements(state) eq 0 then state = 0B
self.state = state
self.row = keyword_set(row)
self.radio = keyword_set(radio)
if n_elements(xoffset) eq 0 then xoffset = 0L
if n_elements(yoffset) eq 0 then yoffset = 0L
self.xoffset = xoffset
self.yoffset = yoffset
if keyword_set(purple) then color = 'purple'
if keyword_set(red) then color = 'red'
if keyword_set(blue) then color = 'blue'
if keyword_set(green) then color = 'green'
if keyword_set(yellow) then color = 'yellow'
if ~keyword_set(red) and ~keyword_set(blue) and ~keyword_set(red) and $
   ~keyword_set(purple) and ~keyword_set(yellow) then color = 'green'
if n_elements(tooltip) eq 0 then tooltip = ''
if n_elements(button_size) eq 0 then button_size = 50
if n_elements(value) eq 0 then label = '' else label = value
if n_elements(uvalue) eq 0 then uvalue = ''
if n_elements(uname) eq 0 then uname = ''
if n_elements(event_pro) eq 0 then event_pro = ""
self.event_pro = event_pro
if n_elements(event_func) eq 0 then event_func = ""
self.event_func = event_func
self.color = color
self.label = label
self.uname = uname
self.storage = ptr_new(uvalue)
self.label = label
self.button_size = button_size
self.tooltip = tooltip
self.parent = parent
self.on_ptr = ptr_new(/allocate_heap)
self.off_ptr = ptr_new(/allocate_heap)
if self.stop then begin
   ret = self->init_stop()
   return,1B
endif
if self.pause then begin
   ret = self->init_pause()
   return,1B
endif
ret = self->init_colors()
return,1B
end
; *************************************** ;
pro rmd_color_button__define
void =   {  rmd_color_button,             $
            parent:0L,                    $
            stop:0B,                      $
            pause:0B,                     $
            tlb:0L,                       $
            bg_color:bytarr(3),           $
            xoffset:0L,                   $
            yoffset:0L,                   $
            label:'',                     $
            row:0B,                       $
            color:'',                     $
            event_func:'',                $
            event_pro:'',                 $
            label_id:0L,                  $
            state:0B,                     $
            win_id:0L,                    $
            winvis:0L,                    $
            winpix:0L,                    $
            button_size:0L,               $
            radio:0B,                     $
            mouse:0,                      $
            tooltip:'',                   $
            uname:'',                     $
            storage:ptr_new(),            $
            on_ptr:ptr_new(),             $
            off_ptr:ptr_new()             }

end
; *************************************** ;
function cw_color_button, parent,               $
                           obj_ref = obj_ref,   $
                           _EXTRA = extra
obj_ref = obj_new('rmd_color_button',parent,_Extra = extra)
ret = obj_ref->build_widgets()
obj_ref->get_property,tlb = tlb
return,tlb
end
; *************************************** ;
; *************************************** ;
pro cb_example_event,event
uname = widget_info(event.id,/uname)
case uname of
'RADIO1':   $
   begin
      widget_control,event.id,get_value = val
      if val eq 'Radio button (out)' then $
         newval = 'Radio button (in)'     $
      else  $
         newval = 'Radio button (out)'
      widget_control,event.id,set_value = newval
   end
'RADIO2':   $
   begin
      widget_control,event.id,get_value = val
      if val eq 'Radio button (out)' then $
         newval = 'Radio button (in) '     $
      else  $
         newval = 'Radio button (out)'
      widget_control,event.id,set_value = newval
   end
'QUIT':  $
   begin
      widget_control,event.top,/destroy
   end
'PAUSE': $
   begin
      widget_control,event.id,get_value = val
      print,'Button value: ',val
   end
else:
endcase
end
; ***************************************************** ;
pro cb_example
; This is an example usage of the colored widget button
; named RMD_COLOR_BUTTON.

tlb = widget_base(/col,title = 'Color button example',            $
   /tlb_frame_attr,/align_center)
col = widget_base(tlb,/col,/base_align_center,/align_center,/frame)
bsize = 30
void = cw_color_button(col,/row,value = 'Radio button (out)',     $
         uname = 'RADIO1',/radio,state = 0B,/green,button_size = bsize)
void = cw_color_button(col,/row,value = 'Radio button (in) ',      $
         uname = 'RADIO2',/radio,state = 1B,/green,button_size = bsize)

row = widget_base(tlb,/row,/base_align_center,/align_center,/frame)
tip = "Press me: I'm purple"
void = cw_color_button(row,/pause,tooltip = tip,button_size = 80,    $
   state = 0B,uname = 'PAUSE')
tip = 'Press to quit program'
void = cw_color_button(row,uname = 'QUIT',/stop,   $
   tooltip = tip,button_size = 50)
widget_control,tlb,/realize
xmanager,'cb_example',tlb,/no_block

end