OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / sample / demos-en / tcolor
1 #!/usr/bin/env ruby
2 #
3 # tcolor --
4 #   simple color editor which supports RGB, HSB and CYM color space
5 #
6 # Copyright (C) 1998 Takaaki Tateishi(ttate@jaist.ac.jp)
7 # last update: Thu Jun 18 06:32:35 JST 1998
8 #
9
10 require "tk"
11
12
13 # use TkVariable instance for the variable which is changed by Tk interpreter
14
15 $colorSpace = TkVariable.new(:rgb)
16 $master = nil
17 $red = 65535
18 $green = 0
19 $blue = 0
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")
29
30
31 # setup the entry of the resourc database
32 if (TkVarAccess.new('tcl_platform')['platform'] == 'unix')
33   TkOptionDB.add('*Entry.background', 'white')
34 end
35
36
37 # methods for events
38
39 def rgbToHsv(red,green,blue)
40
41   if ( red > green )
42     max = red
43     min = green
44   else
45     max = green
46     min = red
47   end
48
49   if ( blue > max )
50     max = blue
51   else
52     if ( blue < min )
53       min = blue
54     end
55   end
56
57   range = max - min
58
59   if ( max == 0 )
60     sat = 0.0
61   else
62     sat = (max-min)/max
63   end
64
65   if ( sat == 0 )
66     hue = 0.0
67   else
68     rc = (max-red)/range
69     gc = (max-green)/range
70     bc = (max-blue)/range
71     if ( red == max )
72       hue = 0.166667 * (bc - gc)
73     else
74       if ( green == max )
75         hue = 0.166667 * (2.0 + rc - bc)
76       else
77         hue = 0.166667 * (4.0 + gc - rc)
78       end
79     end
80     if ( hue < 0.0 )
81       hue = hue + 1.0
82     end
83   end
84
85   [hue,sat,max/65535]
86 end
87
88
89 def hsbToRgb(hue,sat,value)
90   v = 65535.0 * value
91   if( sat == 0 )
92     ans = [v,v,v]
93   else
94     hue = hue*6.0
95     if ( hue >= 6 )
96       hue = 0.0
97     end
98     i = hue.to_i
99     f = hue - i
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)))
103     case i
104     when 0
105       ans = [v,t,p]
106     when 1
107       ans = [q,v,p]
108     when 2
109       ans = [p,v,t]
110     when 3
111       ans = [p,q,v]
112     when 4
113       ans = [t,p,v]
114     when 5
115       ans = [v,p,q]
116     else
117       raise(eException,"i value #{i} is out of range")
118     end
119   end
120   return ans
121 end
122
123
124 def _null_binding
125   Module.new.instance_eval{binding}
126 end
127 private :_null_binding
128
129 def doUpdate 
130   newCmd = $command.to_s.gsub("%%","\"#{$color}\"")
131   eval(newCmd, _null_binding)
132 end
133
134
135 def tc_scaleChanged
136   if( $updating.to_i == 1 )
137     return 
138   end
139
140   $master = :scale if $master == nil
141
142   scale1 = $root.middle.middle.scale1
143   scale2 = $root.middle.middle.scale2
144   scale3 = $root.middle.middle.scale3
145
146   case $colorSpace.value.intern
147   when :rgb
148     $red = (scale1.get * 65.535).to_i
149     $green = (scale2.get * 65.535).to_i
150     $blue = (scale3.get * 65.535).to_i
151   when :cmy
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        
155   when :hsb
156     list = hsbToRgb(scale1.get / 1000.0,
157                     scale2.get / 1000.0,
158                     scale3.get / 1000.0)
159     $red = list[0]
160     $green = list[1]
161     $blue = list[2]
162   else
163     raise(Exception,"unknown colorSpace")
164   end
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 )
169     doUpdate
170   end
171   Tk.update(true)
172   $master = nil if $master == :scale
173 end
174
175
176 def tc_setScales
177   $updating.value = 1
178
179   scale1 = $root.middle.middle.scale1
180   scale2 = $root.middle.middle.scale2
181   scale3 = $root.middle.middle.scale3
182   
183   case $colorSpace.value.intern
184   when :rgb
185     scale1.set($red / 65.535)
186     scale2.set($green / 65.535)
187     scale3.set($blue / 65.535)
188   when :cmy
189     scale1.set((65535 - $red) / 65.535)
190     scale2.set((65535 - $green) / 65.535)
191     scale3.set((65535 - $blue) / 65.535)
192   when :hsb
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 )
197   else
198     raise(Exception,"unknown colorSpace")
199   end
200
201   $updating.value = 0
202 end
203
204
205 def tc_loadNamedColor(name)
206   $name.value = name
207   $master = :name if $master == nil
208   if name[0,1] != "#" 
209     list = TkWinfo.rgb($root.middle.right.swatch,name)
210     $red = list[0]
211     $green = list[1]
212     $blue = list[2]
213   else
214     case name.length
215     when 4
216       fmt = /#(.{1})(.{1})(.{1})/
217       shift = 12
218     when 7
219       fmt = /#(.{2})(.{2})(.{2})/
220       shift = 8
221     when 10
222       fmt = /#(.{3})(.{3})(.{3})/
223       shift = 4
224     when 13
225       fmt = /#(.{4})(.{4})(.{4})/
226       shift = 0
227     else
228       raise(eException,"syntax error in color name \"#{name}\"")
229     end
230     name.scan(fmt){|strlist|
231       if strlist.length != 3
232         raise(eException,"syntax error in color name \"#{name}\"")
233       end
234       $red = strlist[0].hex
235       $green = strlist[1].hex
236       $blue = strlist[2].hex
237     }
238     $red = $red << shift
239     $green = $green << shift
240     $blue = $blue << shift
241   end
242   
243   tc_setScales
244   $color = format("#%04x%04x%04x",$red,$green,$blue)
245   $root.middle.right.set_color($color)
246   if $autoUpdate.to_i == 1
247     doUpdate
248   end
249   Tk.update(true)
250   $master = nil if $master == :name
251 end
252
253
254 def changeColorSpace(space)
255   case space
256   when :rgb
257     $label1.value = "Red"
258     $label2.value = "Green"
259     $label3.value = "Blue"
260   when :cmy
261     $label1.value = "Cyan"
262     $label2.value = "Magenta"
263     $label3.value = "Yellow"
264   when :hsb
265     $label1.value = "Hue"
266     $label2.value = "Saturation"
267     $label3.value = "Brightness"
268   end
269   tc_setScales
270 end
271
272
273 # menu
274
275 class TkColorMenuFrame<TkFrame
276   def initialize(parent)
277     super(parent,
278           "relief"=>"raised",
279           "borderwidth"=>"2")
280
281     # File menubutton
282     @file = TkMenubutton.new(self){|button|
283
284       # File menu
285       @file_menu = TkMenu.new(button){
286         add "radio",
287           "label" => "RGB color space",
288           "variable" => $colorSpace,
289           "value" => :rgb,
290           "underline" => "0",
291           "command" => proc{changeColorSpace(:rgb)}
292         add "radio",
293           "label" => "CMY color space",
294           "variable" => $colorSpace,
295           "value" => :cmy,
296           "underline" => "0",
297           "command" => proc{changeColorSpace(:cmy)}
298         add "radio",
299           "label" => "HSB color space",
300           "variable" => $colorSpace,
301           "value" => :hsb,
302           "underline" => "0",
303           "command" => proc{changeColorSpace(:hsb)}
304         add "separator"
305         add "radio",
306           "label" => "Automatic updates",
307           "variable" => $autoUpdate,
308           "value" => "1",
309           "underline" => "0"
310         add "radio",
311           "label" => "Manual updates",
312           "variable" => $autoUpdate,
313           "value" => "0",
314           "underline" => "0"
315         add "separator"
316         add "command",
317           "label" => "Exit program",
318           "underline" => "0",
319           "command" => proc{exit}
320       }
321       
322       # assign File menu to File button
323       menu @file_menu
324
325       text "File"
326       underline "0"
327     }.pack("side"=>"left")
328
329     self
330   end
331 end
332
333
334 # bottom frame
335 class TkColorBotFrame<TkFrame
336   def initialize(parent)
337     super(parent,
338           "relief"=> "raised",
339           "borderwidth"=> 2)
340
341     @commandLabel = TkLabel.new(self,
342                                 "text"=> "Command:")
343     @command = TkEntry.new(self,
344                            "relief"=> "sunken",
345                            "borderwidth"=> "2",
346                            "textvariable"=> $command,
347                            "font"=> "-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
348     @update = TkButton.new(self,
349                            "text"=> "Update",
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")
354
355     self
356   end
357 end    
358
359
360 # left side frame of middle level
361 class TkColorMiddleLeftFrame<TkFrame
362   def initialize(parent)
363     super(parent)
364
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)
369         next
370       end
371       f = File.open(i)
372       @scroll = TkScrollbar.new(self,
373                                 "orient"=>"vertical",
374                                 "relief"=>"sunken",
375                                 "borderwidth"=>"2")
376       @scroll.pack("side"=>"right","fill"=>"y")
377       @names = TkListbox.new(self,
378                              "width"=>"20",
379                              "height"=>"12",
380                              "yscrollcommand"=> proc{|first,last| @scroll.set first,last},
381                              "relief"=>"sunken",
382                              "borderwidth"=>"2",
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)
389         line.chop!
390         linelist = line.split(/[ \t]+/)
391         if linelist.length == 4
392           @names.insert("end",linelist[3])
393         end
394       end
395       f.close
396       break
397     end
398
399     self
400   end
401 end
402
403
404 # middle frame of middle level
405 class TkColorMiddleMiddleFrame<TkFrame
406   attr_reader :scale1, :scale2, :scale3
407
408   def initialize(parent)
409     super(parent)
410
411     @f1 = TkFrame.new(self)
412     @f2 = TkFrame.new(self)
413     @f3 = TkFrame.new(self)
414     @f4 = TkFrame.new(self)
415
416     for f in [@f1,@f2,@f3]
417       f.pack("side"=>"top","expand"=>"yes")
418     end
419     @f4.pack("side"=>"top","expand"=>"yes","fill"=>"x")
420
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")
427
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")
434
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")
441
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})
449
450     self
451   end
452 end
453
454
455 class TkColorMiddleRightFrame<TkFrame
456   attr_reader :swatch
457
458   def initialize(parent)
459     super(parent)
460     @swatch = TkFrame.new(self, "width"=>"2c", "height"=>"5c",
461                           "background"=>$color)
462     @value = TkLabel.new(self, 
463                          "text"=>$color,
464                          "width"=>"13",
465                          "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
466     @swatch.pack("side"=>"top","expand"=>"yes","fill"=>"both")
467     @value.pack("side"=>"bottom","pady"=>".25c")
468
469     self
470   end
471
472   def set_color(color)
473     @swatch["background"] = color
474     @value["text"] = color
475   end
476 end
477
478
479
480 # middle level frame
481 class TkColorMiddleFrame<TkFrame
482   attr_reader :left, :middle, :right
483
484   def initialize(parent)
485     super(parent,
486           "relief"=> "raised",
487           "borderwidth"=> "2")
488
489     @left = TkColorMiddleLeftFrame.new(self)
490     @left.pack("side"=>"left","padx"=>".25c","pady"=>".25c")
491
492     @middle = TkColorMiddleMiddleFrame.new(self)
493     @middle.pack("side"=>"left","expand"=>"yes","fill"=>"y")
494
495     @right = TkColorMiddleRightFrame.new(self)
496     @right.pack("side"=>"left","padx"=>".25c","pady"=>".25c","anchor"=>"s")
497
498     self
499   end
500 end
501
502
503 class TkColor<TkRoot
504   attr_reader :menu, :bottom, :middle
505
506   def initialize(*args)
507     super(*args)
508     @menu = TkColorMenuFrame.new(self)
509     @menu.pack("side"=>"top", "fill"=>"x")
510
511     @bottom = TkColorBotFrame.new(self)
512     @bottom.pack("side"=>"bottom","fill"=>"x")
513
514     @middle = TkColorMiddleFrame.new(self)
515     @middle.pack("side"=>"top","fill"=>"both")
516
517     self
518   end
519 end
520
521
522 $root = TkColor.new
523 changeColorSpace :rgb
524
525 # start eventloop
526 Tk.mainloop