4 # simple color editor which supports RGB, HSB and CYM color space
6 # Copyright (C) 1998 Takaaki Tateishi(ttate@jaist.ac.jp)
7 # last update: Thu Jun 18 06:32:35 JST 1998
13 # use TkVariable instance for the variable which is changed by Tk interpreter
15 $colorSpace = TkVariable.new(:rgb)
20 $color = "#ffff00000000"
21 $updating = TkVariable.new(0)
22 $autoUpdate = TkVariable.new(1)
23 $name = TkVariable.new($color)
24 $command = TkVariable.new("print(%%,\"\n\")")
25 # $command = TkVariable.new("")
26 $label1 = TkVariable.new("label1")
27 $label2 = TkVariable.new("label2")
28 $label3 = TkVariable.new("label3")
31 # setup the entry of the resourc database
32 if (TkVarAccess.new('tcl_platform')['platform'] == 'unix')
33 TkOptionDB.add('*Entry.background', 'white')
39 def rgbToHsv(red,green,blue)
69 gc = (max-green)/range
72 hue = 0.166667 * (bc - gc)
75 hue = 0.166667 * (2.0 + rc - bc)
77 hue = 0.166667 * (4.0 + gc - rc)
89 def hsbToRgb(hue,sat,value)
100 p = 65535.0 * value * (1.0 - sat)
101 q = 65535.0 * value * (1.0 - (sat * f))
102 t = 65535.0 * value * (1.0 - (sat * (1.0 - f)))
117 raise(eException,"i value #{i} is out of range")
125 Module.new.instance_eval{binding}
127 private :_null_binding
130 newCmd = $command.to_s.gsub("%%","\"#{$color}\"")
131 eval(newCmd, _null_binding)
136 if( $updating.to_i == 1 )
140 $master = :scale if $master == nil
142 scale1 = $root.middle.middle.scale1
143 scale2 = $root.middle.middle.scale2
144 scale3 = $root.middle.middle.scale3
146 case $colorSpace.value.intern
148 $red = (scale1.get * 65.535).to_i
149 $green = (scale2.get * 65.535).to_i
150 $blue = (scale3.get * 65.535).to_i
152 $red = (65535 - scale1.get * 65.535).to_i
153 $green = (65535 - scale2.get * 65.535).to_i
154 $blue = (65535 - scale3.get * 65.535).to_i
156 list = hsbToRgb(scale1.get / 1000.0,
163 raise(Exception,"unknown colorSpace")
165 $color = format("#%04x%04x%04x",$red.to_i,$green.to_i,$blue.to_i)
166 $name.value = $color if $master == :scale
167 $root.middle.right.set_color($color)
168 if( $autoUpdate.to_i == 1 )
172 $master = nil if $master == :scale
179 scale1 = $root.middle.middle.scale1
180 scale2 = $root.middle.middle.scale2
181 scale3 = $root.middle.middle.scale3
183 case $colorSpace.value.intern
185 scale1.set($red / 65.535)
186 scale2.set($green / 65.535)
187 scale3.set($blue / 65.535)
189 scale1.set((65535 - $red) / 65.535)
190 scale2.set((65535 - $green) / 65.535)
191 scale3.set((65535 - $blue) / 65.535)
193 list = rgbToHsv($red,$green,$blue)
194 scale1.set( list[0] * 1000.0 )
195 scale2.set( list[1] * 1000.0 )
196 scale3.set( list[2] * 1000.0 )
198 raise(Exception,"unknown colorSpace")
205 def tc_loadNamedColor(name)
207 $master = :name if $master == nil
209 list = TkWinfo.rgb($root.middle.right.swatch,name)
216 fmt = /#(.{1})(.{1})(.{1})/
219 fmt = /#(.{2})(.{2})(.{2})/
222 fmt = /#(.{3})(.{3})(.{3})/
225 fmt = /#(.{4})(.{4})(.{4})/
228 raise(eException,"syntax error in color name \"#{name}\"")
230 name.scan(fmt){|strlist|
231 if strlist.length != 3
232 raise(eException,"syntax error in color name \"#{name}\"")
234 $red = strlist[0].hex
235 $green = strlist[1].hex
236 $blue = strlist[2].hex
239 $green = $green << shift
240 $blue = $blue << shift
244 $color = format("#%04x%04x%04x",$red,$green,$blue)
245 $root.middle.right.set_color($color)
246 if $autoUpdate.to_i == 1
250 $master = nil if $master == :name
254 def changeColorSpace(space)
257 $label1.value = "Red"
258 $label2.value = "Green"
259 $label3.value = "Blue"
261 $label1.value = "Cyan"
262 $label2.value = "Magenta"
263 $label3.value = "Yellow"
265 $label1.value = "Hue"
266 $label2.value = "Saturation"
267 $label3.value = "Brightness"
275 class TkColorMenuFrame<TkFrame
276 def initialize(parent)
282 @file = TkMenubutton.new(self){|button|
285 @file_menu = TkMenu.new(button){
287 "label" => "RGB color space",
288 "variable" => $colorSpace,
291 "command" => proc{changeColorSpace(:rgb)}
293 "label" => "CMY color space",
294 "variable" => $colorSpace,
297 "command" => proc{changeColorSpace(:cmy)}
299 "label" => "HSB color space",
300 "variable" => $colorSpace,
303 "command" => proc{changeColorSpace(:hsb)}
306 "label" => "Automatic updates",
307 "variable" => $autoUpdate,
311 "label" => "Manual updates",
312 "variable" => $autoUpdate,
317 "label" => "Exit program",
319 "command" => proc{exit}
322 # assign File menu to File button
327 }.pack("side"=>"left")
335 class TkColorBotFrame<TkFrame
336 def initialize(parent)
341 @commandLabel = TkLabel.new(self,
343 @command = TkEntry.new(self,
346 "textvariable"=> $command,
347 "font"=> "-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
348 @update = TkButton.new(self,
350 "command"=> proc{doUpdate})
351 @commandLabel.pack("side"=>"left")
352 @update.pack("side"=>"right","pady"=>".1c","padx"=>".25c")
353 @command.pack("expand"=>"yes","fill"=>"x","ipadx"=>".25c")
360 # left side frame of middle level
361 class TkColorMiddleLeftFrame<TkFrame
362 def initialize(parent)
365 for i in ["/usr/local/lib/X11rgb.txt","/usr/lib/X11/rgb.txt",
366 "/X11/R5/lib/X11/rgb.txt","/X11/R4/lib/rgb/rgb.txt",
367 "/usr/openwin/lib/X11/rgb.txt"]
368 if !File.readable?(i)
372 @scroll = TkScrollbar.new(self,
373 "orient"=>"vertical",
376 @scroll.pack("side"=>"right","fill"=>"y")
377 @names = TkListbox.new(self,
380 "yscrollcommand"=> proc{|first,last| @scroll.set first,last},
383 "exportselection"=>"false")
384 @scroll.command(proc{|*args| @names.yview(*args)})
385 @names.bind("Double-1",proc{
386 tc_loadNamedColor(@names.get(@names.curselection))})
387 @names.pack("side"=>"left")
388 while (line = f.gets)
390 linelist = line.split(/[ \t]+/)
391 if linelist.length == 4
392 @names.insert("end",linelist[3])
404 # middle frame of middle level
405 class TkColorMiddleMiddleFrame<TkFrame
406 attr_reader :scale1, :scale2, :scale3
408 def initialize(parent)
411 @f1 = TkFrame.new(self)
412 @f2 = TkFrame.new(self)
413 @f3 = TkFrame.new(self)
414 @f4 = TkFrame.new(self)
416 for f in [@f1,@f2,@f3]
417 f.pack("side"=>"top","expand"=>"yes")
419 @f4.pack("side"=>"top","expand"=>"yes","fill"=>"x")
421 @label1 = TkLabel.new(self,"textvariable"=>$label1)
422 @scale1 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
423 "orient"=>"horizontal",
424 "command"=>proc{tc_scaleChanged})
425 @scale1.pack("side"=>"top","anchor"=>"w")
426 @label1.pack("side"=>"top","anchor"=>"w")
428 @label2 = TkLabel.new(self,"textvariable"=>$label2)
429 @scale2 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
430 "orient"=>"horizontal",
431 "command"=>proc{tc_scaleChanged})
432 @scale2.pack("side"=>"top","anchor"=>"w")
433 @label2.pack("side"=>"top","anchor"=>"w")
435 @label3 = TkLabel.new(self,"textvariable"=>$label3)
436 @scale3 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
437 "orient"=>"horizontal",
438 "command"=>proc{tc_scaleChanged})
439 @scale3.pack("side"=>"top","anchor"=>"w")
440 @label3.pack("side"=>"top","anchor"=>"w")
442 @nameLabel = TkLabel.new(self,"text"=>"Name:")
443 @name = TkEntry.new(self,"relief"=>"sunken","borderwidth"=>"2",
444 "textvariable"=>$name,"width"=>"10",
445 "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
446 @nameLabel.pack("side"=>"left")
447 @name.pack("side"=>"right", "expand"=>"1", "fill"=>"x")
448 @name.bind("Return",proc{tc_loadNamedColor $name.to_s})
455 class TkColorMiddleRightFrame<TkFrame
458 def initialize(parent)
460 @swatch = TkFrame.new(self, "width"=>"2c", "height"=>"5c",
461 "background"=>$color)
462 @value = TkLabel.new(self,
465 "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
466 @swatch.pack("side"=>"top","expand"=>"yes","fill"=>"both")
467 @value.pack("side"=>"bottom","pady"=>".25c")
473 @swatch["background"] = color
474 @value["text"] = color
481 class TkColorMiddleFrame<TkFrame
482 attr_reader :left, :middle, :right
484 def initialize(parent)
489 @left = TkColorMiddleLeftFrame.new(self)
490 @left.pack("side"=>"left","padx"=>".25c","pady"=>".25c")
492 @middle = TkColorMiddleMiddleFrame.new(self)
493 @middle.pack("side"=>"left","expand"=>"yes","fill"=>"y")
495 @right = TkColorMiddleRightFrame.new(self)
496 @right.pack("side"=>"left","padx"=>".25c","pady"=>".25c","anchor"=>"s")
504 attr_reader :menu, :bottom, :middle
506 def initialize(*args)
508 @menu = TkColorMenuFrame.new(self)
509 @menu.pack("side"=>"top", "fill"=>"x")
511 @bottom = TkColorBotFrame.new(self)
512 @bottom.pack("side"=>"bottom","fill"=>"x")
514 @middle = TkColorMiddleFrame.new(self)
515 @middle.pack("side"=>"top","fill"=>"both")
523 changeColorSpace :rgb