Version 6 of ClrPick -A Colour Selection Megawidget

Updated 2005-10-31 00:16:29

WJG 30th October, 2005

There a number of colour pickers out there including the one shipped within the tcl/tk installation itself. However, I wanted something a little more polished and re-usable, hence ClrPick.

 ############################################ 
 # colourpicker.tcl
 # ------------------------
 # Written by: William J Giddings
 # 30th October, 2005
 ############################################ 
 # Description:
 # -----------
 # Select a colour from a predefined palette.
 # 
 # Proceedures:
 # -----------
 # clrpick::swatch {name clr h w}  create colour swatched for use in popupmenu and ClpPick widget.         
 # clrpick::popup {w}              display palette popup menu
 # clrpick::pick {w clr}           respond to popup menu choise
 # ClrPick {w clrw args }          create instance of ClrPick megawidget
 #
 # Note:
 # ----
 # Two buttons are held in a frame. 
 # The lower button displays a colour swatch of the active colour. Whereas
 # the upper button is used to apply the new colour.
 #
 ############################################

 set rundemo yes

 namespace eval clrpick {}

 # default settings
 # menu button swatch size
 set clrpick::height 14
 set clrpick::width 14
 # the colour palette
 set clrpick::palette "White white Grey grey Black Black Red red Orange orange Yellow yellow Green green Blue blue  Magenta magenta Violet violet Purple purple"
 # Alternatively:
 # set clrpick::palette "white #ffffff grey #dddddd black #000000 red #ff0000 green #00ff00 blue #0000ff"
 # the active colour
 set clrpick::clr white

 # icon for the apply button
 image create photo _clrpick -data R0lGODlhEgANAMIHAAAAAAAAgICAgAD/AMDAwNTQyP//AP///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABIADQAAAzFYutz+BcgJGxgY1HjU1RVwHIS3iSQRbFwagJBAyCoMAbMg2A9g6BKW72Dg3SisZCMBADs=

 #---------------
 # create colour swatches
 #---------------    
 proc clrpick::swatch {name clr h w} {
  set topBorderColor gray50
  set bottomBorderColor gray75
  image create photo swatch_$name -height $h -width $w
  swatch_$name put $topBorderColor -to 0 0 $w 1
  swatch_$name put $topBorderColor -to 0 1 1 $h
  swatch_$name put $bottomBorderColor -to 0 [expr $h -1] $h $h
  swatch_$name put $bottomBorderColor -to [expr $w -1] 1 $w $w
  swatch_$name put $clr -to 1 1 [expr $w - 1] [expr $h -1]
 }

 #---------------
 # show the popup menu
 #---------------
 proc clrpick::popup {w} {
  # create popupmen if one doesn't exist already
  if {![winfo exist .cp]} {
    set pathName .cp
    # create a popup menu, to be placed under the calling button
    menu $pathName -tearoff 0
    foreach {i j} $clrpick::palette {
      swatch $j $j $clrpick::height $clrpick::width
      $pathName add command \
        -compound left \
        -label $i \
        -image swatch_$j \
        -command "clrpick::pick $w $j"
    } 
  }
  # place picker window close to calling button 
  set x [winfo rootx $w]
  set y [expr [winfo rooty $w]+ [winfo height $w]]
  tk_popup .cp $x $y
 }

 #---------------
 # handle menu selection, set active colour and change widget swatch
 #---------------
 proc clrpick::pick {w clr} {
  swatch $w $clr [image height swatch_$w] [image width swatch_$w]
  $w configure -image swatch_$w
  set clrpick::clr $clr
 }

 #---------------
 # create new widget instance
 #---------------
 proc ClrPick {w clr args } {
  array set b1 "w 8 h 18"
  frame $w
  eval button $w.b1 $args 
  clrpick::swatch $w.b2 $clr $b1(w) $b1(h)
  button $w.b2 -image swatch_$w.b2 -command "clrpick::popup $w.b2" -relief flat -borderwidth 0 -relief flat
  pack $w.b1 $w.b2
  return $w
 }

 #---------------
 # the unbiqitous demo
 #---------------

 proc demo {} {
  catch {console show}
  ClrPick .cp1 $clrpick::clr -image _clrpick  -relief flat  -borderwidth 0 \
      -command {
        puts "Do something with colour \"$clrpick::clr\"."
        .txt configure -background $clrpick::clr
        }
  pack .cp1 -side top -anchor nw
  pack [text .txt] -fill both  

 }

 if {$rundemo} {demo}

RH 30. Oct 2005 Please take care of non windows users. There is no

 console show

on linux. A simple check would solve this

 if { $::tcl_platform(platform) eq "windows" } {
     console show
 }

MG Oct 31 2005 - This is nice, though it seems to behave a little differently than I would've expected. Selecting a new colour doesn't trigger the action associated with the top button (you have to select a new colour, then click the top buttom to perform the action). Also, in most applications I've scene which have colour-selectors like this, the buttons work the other way around - the large, main button (which is often on the left, instead of above) changes colour to show the most recent selected colour, and clicking it selects that colour again for the current window/selected text/etc. And then a smaller button to the right brings up the menu to select other colours. (I added a catch around the console show, incidently, after RH's comments above.)