1#!/usr/bin/env ruby 2# -*- coding: utf-8 -*- 3# 4# tcolor -- 5# このスクリプトはRGB,HSB,CYM形式をサポートする 6# 簡易カラーエディタです。 7# 8# Copyright (C) 1998 Takaaki Tateishi(ttate@jaist.ac.jp) 9# last update: Thu Jun 18 06:32:35 JST 1998 10# 11 12# まずはtk.rbを読み込む。 13 14require "tk" 15 16 17# Tkによって変更される変数はTkVariableのインスタンスを使う。 18 19$colorSpace = TkVariable.new(:rgb) 20$master = nil 21$red = 65535 22$green = 0 23$blue = 0 24$color = "#ffff00000000" 25$updating = TkVariable.new(0) 26$autoUpdate = TkVariable.new(1) 27$name = TkVariable.new($color) 28$command = TkVariable.new("print(%%,\"\n\")") 29# $command = TkVariable.new("") 30$label1 = TkVariable.new("label1") 31$label2 = TkVariable.new("label2") 32$label3 = TkVariable.new("label3") 33 34 35# リソースデータベースの設定 36if (TkVarAccess.new('tcl_platform')['platform'] == 'unix') 37 TkOptionDB.add('*Entry.background', 'white') 38end 39 40 41# 各イベント用のメソッド 42 43def rgbToHsv(red,green,blue) 44 45 if ( red > green ) 46 max = red 47 min = green 48 else 49 max = green 50 min = red 51 end 52 53 if ( blue > max ) 54 max = blue 55 else 56 if ( blue < min ) 57 min = blue 58 end 59 end 60 61 range = max - min 62 63 if ( max == 0 ) 64 sat = 0.0 65 else 66 sat = (max-min)/max 67 end 68 69 if ( sat == 0 ) 70 hue = 0.0 71 else 72 rc = (max-red)/range 73 gc = (max-green)/range 74 bc = (max-blue)/range 75 if ( red == max ) 76 hue = 0.166667 * (bc - gc) 77 else 78 if ( green == max ) 79 hue = 0.166667 * (2.0 + rc - bc) 80 else 81 hue = 0.166667 * (4.0 + gc - rc) 82 end 83 end 84 if ( hue < 0.0 ) 85 hue = hue + 1.0 86 end 87 end 88 89 [hue,sat,max/65535] 90end 91 92 93def hsbToRgb(hue,sat,value) 94 v = 65535.0 * value 95 if( sat == 0 ) 96 ans = [v,v,v] 97 else 98 hue = hue*6.0 99 if ( hue >= 6 ) 100 hue = 0.0 101 end 102 i = hue.to_i 103 f = hue - i 104 p = 65535.0 * value * (1.0 - sat) 105 q = 65535.0 * value * (1.0 - (sat * f)) 106 t = 65535.0 * value * (1.0 - (sat * (1.0 - f))) 107 case i 108 when 0 109 ans = [v,t,p] 110 when 1 111 ans = [q,v,p] 112 when 2 113 ans = [p,v,t] 114 when 3 115 ans = [p,q,v] 116 when 4 117 ans = [t,p,v] 118 when 5 119 ans = [v,p,q] 120 else 121 raise(eException,"i value #{i} is out of range") 122 end 123 end 124 return ans 125end 126 127 128def _null_binding 129 Module.new.instance_eval{binding} 130end 131private :_null_binding 132 133def doUpdate 134 newCmd = $command.to_s.gsub("%%","\"#{$color}\"") 135 eval(newCmd, _null_binding) 136end 137 138 139def tc_scaleChanged 140 if( $updating.to_i == 1 ) 141 return 142 end 143 144 $master = :scale if $master == nil 145 146 scale1 = $root.middle.middle.scale1 147 scale2 = $root.middle.middle.scale2 148 scale3 = $root.middle.middle.scale3 149 150 case $colorSpace.value.intern 151 when :rgb 152 $red = (scale1.get * 65.535).to_i 153 $green = (scale2.get * 65.535).to_i 154 $blue = (scale3.get * 65.535).to_i 155 when :cmy 156 $red = (65535 - scale1.get * 65.535).to_i 157 $green = (65535 - scale2.get * 65.535).to_i 158 $blue = (65535 - scale3.get * 65.535).to_i 159 when :hsb 160 list = hsbToRgb(scale1.get / 1000.0, 161 scale2.get / 1000.0, 162 scale3.get / 1000.0) 163 $red = list[0] 164 $green = list[1] 165 $blue = list[2] 166 else 167 raise(Exception,"unknown colorSpace") 168 end 169 $color = format("#%04x%04x%04x",$red.to_i,$green.to_i,$blue.to_i) 170 $name.value = $color if $master == :scale 171 $root.middle.right.set_color($color) 172 if( $autoUpdate.to_i == 1 ) 173 doUpdate 174 end 175 Tk.update(true) 176 $master = nil if $master == :scale 177end 178 179 180def tc_setScales 181 $updating.value = 1 182 183 scale1 = $root.middle.middle.scale1 184 scale2 = $root.middle.middle.scale2 185 scale3 = $root.middle.middle.scale3 186 187 case $colorSpace.value.intern 188 when :rgb 189 scale1.set($red / 65.535) 190 scale2.set($green / 65.535) 191 scale3.set($blue / 65.535) 192 when :cmy 193 scale1.set((65535 - $red) / 65.535) 194 scale2.set((65535 - $green) / 65.535) 195 scale3.set((65535 - $blue) / 65.535) 196 when :hsb 197 list = rgbToHsv($red,$green,$blue) 198 scale1.set( list[0] * 1000.0 ) 199 scale2.set( list[1] * 1000.0 ) 200 scale3.set( list[2] * 1000.0 ) 201 else 202 raise(Exception,"unknown colorSpace") 203 end 204 205 $updating.value = 0 206end 207 208 209def tc_loadNamedColor(name) 210 $name.value = name 211 $master = :name if $master == nil 212 if name[0,1] != "#" 213 list = TkWinfo.rgb($root.middle.right.swatch,name) 214 $red = list[0] 215 $green = list[1] 216 $blue = list[2] 217 else 218 case name.length 219 when 4 220 fmt = /#(.{1})(.{1})(.{1})/ 221 shift = 12 222 when 7 223 fmt = /#(.{2})(.{2})(.{2})/ 224 shift = 8 225 when 10 226 fmt = /#(.{3})(.{3})(.{3})/ 227 shift = 4 228 when 13 229 fmt = /#(.{4})(.{4})(.{4})/ 230 shift = 0 231 else 232 raise(eException,"syntax error in color name \"#{name}\"") 233 end 234 name.scan(fmt){|strlist| 235 if strlist.length != 3 236 raise(eException,"syntax error in color name \"#{name}\"") 237 end 238 $red = strlist[0].hex 239 $green = strlist[1].hex 240 $blue = strlist[2].hex 241 } 242 $red = $red << shift 243 $green = $green << shift 244 $blue = $blue << shift 245 end 246 247 tc_setScales 248 $color = format("#%04x%04x%04x",$red,$green,$blue) 249 $root.middle.right.set_color($color) 250 if $autoUpdate.to_i == 1 251 doUpdate 252 end 253 Tk.update(true) 254 $master = nil if $master == :name 255end 256 257 258def changeColorSpace(space) 259 case space 260 when :rgb 261 $label1.value = "Red" 262 $label2.value = "Green" 263 $label3.value = "Blue" 264 when :cmy 265 $label1.value = "Cyan" 266 $label2.value = "Magenta" 267 $label3.value = "Yellow" 268 when :hsb 269 $label1.value = "Hue" 270 $label2.value = "Saturation" 271 $label3.value = "Brightness" 272 end 273 tc_setScales 274end 275 276 277 278 279 280# tcolor������������������ 281 282class TkColorMenuFrame<TkFrame 283 def initialize(parent) 284 super(parent, 285 "relief"=>"raised", 286 "borderwidth"=>"2") 287 288 # File������������������������������ 289 @file = TkMenubutton.new(self){|button| 290 291 # File��������������������� 292 @file_menu = TkMenu.new(button){ 293 add "radio", 294 "label" => "RGB color space", 295 "variable" => $colorSpace, 296 "value" => :rgb, 297 "underline" => "0", 298 "command" => proc{changeColorSpace(:rgb)} 299 add "radio", 300 "label" => "CMY color space", 301 "variable" => $colorSpace, 302 "value" => :cmy, 303 "underline" => "0", 304 "command" => proc{changeColorSpace(:cmy)} 305 add "radio", 306 "label" => "HSB color space", 307 "variable" => $colorSpace, 308 "value" => :hsb, 309 "underline" => "0", 310 "command" => proc{changeColorSpace(:hsb)} 311 add "separator" 312 add "radio", 313 "label" => "Automatic updates", 314 "variable" => $autoUpdate, 315 "value" => "1", 316 "underline" => "0" 317 add "radio", 318 "label" => "Manual updates", 319 "variable" => $autoUpdate, 320 "value" => "0", 321 "underline" => "0" 322 add "separator" 323 add "command", 324 "label" => "Exit program", 325 "underline" => "0", 326 "command" => proc{exit} 327 } 328 329 # File���������������File��������������������������� 330 menu @file_menu 331 332 text "File" 333 underline "0" 334 }.pack("side"=>"left") 335 336 self 337 end 338end 339 340 341# ������������������������������������������ 342class TkColorBotFrame<TkFrame 343 def initialize(parent) 344 super(parent, 345 "relief"=> "raised", 346 "borderwidth"=> 2) 347 348 @commandLabel = TkLabel.new(self, 349 "text"=> "Command:") 350 @command = TkEntry.new(self, 351 "relief"=> "sunken", 352 "borderwidth"=> "2", 353 "textvariable"=> $command, 354 "font"=> "-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*") 355 @update = TkButton.new(self, 356 "text"=> "Update", 357 "command"=> proc{doUpdate}) 358 @commandLabel.pack("side"=>"left") 359 @update.pack("side"=>"right","pady"=>".1c","padx"=>".25c") 360 @command.pack("expand"=>"yes","fill"=>"x","ipadx"=>".25c") 361 362 self 363 end 364end 365 366 367# ������������������������ 368class TkColorMiddleLeftFrame<TkFrame 369 def initialize(parent) 370 super(parent) 371 372 for i in ["/usr/local/lib/X11rgb.txt","/usr/lib/X11/rgb.txt", 373 "/X11/R5/lib/X11/rgb.txt","/X11/R4/lib/rgb/rgb.txt", 374 "/usr/openwin/lib/X11/rgb.txt"] 375 if !File.readable?(i) 376 next 377 end 378 f = File.open(i) 379 @scroll = TkScrollbar.new(self, 380 "orient"=>"vertical", 381 "relief"=>"sunken", 382 "borderwidth"=>"2") 383 @scroll.pack("side"=>"right","fill"=>"y") 384 @names = TkListbox.new(self, 385 "width"=>"20", 386 "height"=>"12", 387 "yscrollcommand"=> proc{|first,last| @scroll.set first,last}, 388 "relief"=>"sunken", 389 "borderwidth"=>"2", 390 "exportselection"=>"false") 391 @scroll.command(proc{|*args| @names.yview(*args)}) 392 @names.bind("Double-1",proc{ 393 tc_loadNamedColor(@names.get(@names.curselection))}) 394 @names.pack("side"=>"left") 395 while (line = f.gets) 396 line.chop! 397 linelist = line.split(/[ \t]+/) 398 if linelist.length == 4 399 @names.insert("end",linelist[3]) 400 end 401 end 402 f.close 403 break 404 end 405 406 self 407 end 408end 409 410 411# ��������������������������� 412class TkColorMiddleMiddleFrame<TkFrame 413 # @scale1,@scale2,@scale3������������������������������������������(������������) 414 attr_reader :scale1, :scale2, :scale3 415 416 def initialize(parent) 417 super(parent) 418 419 @f1 = TkFrame.new(self) 420 @f2 = TkFrame.new(self) 421 @f3 = TkFrame.new(self) 422 @f4 = TkFrame.new(self) 423 424 for f in [@f1,@f2,@f3] 425 f.pack("side"=>"top","expand"=>"yes") 426 end 427 @f4.pack("side"=>"top","expand"=>"yes","fill"=>"x") 428 429 @label1 = TkLabel.new(self,"textvariable"=>$label1) 430 @scale1 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c", 431 "orient"=>"horizontal", 432 "command"=>proc{tc_scaleChanged}) 433 @scale1.pack("side"=>"top","anchor"=>"w") 434 @label1.pack("side"=>"top","anchor"=>"w") 435 436 @label2 = TkLabel.new(self,"textvariable"=>$label2) 437 @scale2 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c", 438 "orient"=>"horizontal", 439 "command"=>proc{tc_scaleChanged}) 440 @scale2.pack("side"=>"top","anchor"=>"w") 441 @label2.pack("side"=>"top","anchor"=>"w") 442 443 @label3 = TkLabel.new(self,"textvariable"=>$label3) 444 @scale3 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c", 445 "orient"=>"horizontal", 446 "command"=>proc{tc_scaleChanged}) 447 @scale3.pack("side"=>"top","anchor"=>"w") 448 @label3.pack("side"=>"top","anchor"=>"w") 449 450 @nameLabel = TkLabel.new(self,"text"=>"Name:") 451 @name = TkEntry.new(self,"relief"=>"sunken","borderwidth"=>"2", 452 "textvariable"=>$name,"width"=>"10", 453 "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*") 454 @nameLabel.pack("side"=>"left") 455 @name.pack("side"=>"right", "expand"=>"1", "fill"=>"x") 456 @name.bind("Return",proc{tc_loadNamedColor $name.to_s}) 457 458 self 459 end 460end 461 462 463class TkColorMiddleRightFrame<TkFrame 464 attr_reader :swatch 465 466 def initialize(parent) 467 super(parent) 468 @swatch = TkFrame.new(self, "width"=>"2c", "height"=>"5c", 469 "background"=>$color) 470 @value = TkLabel.new(self, 471 "text"=>$color, 472 "width"=>"13", 473 "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*") 474 @swatch.pack("side"=>"top","expand"=>"yes","fill"=>"both") 475 @value.pack("side"=>"bottom","pady"=>".25c") 476 477 self 478 end 479 480 def set_color(color) 481 @swatch["background"] = color 482 @value["text"] = color 483 end 484end 485 486 487 488# ��������������������� 489class TkColorMiddleFrame<TkFrame 490 attr_reader :left, :middle, :right 491 492 def initialize(parent) 493 super(parent, 494 "relief"=> "raised", 495 "borderwidth"=> "2") 496 497 @left = TkColorMiddleLeftFrame.new(self) 498 @left.pack("side"=>"left","padx"=>".25c","pady"=>".25c") 499 500 @middle = TkColorMiddleMiddleFrame.new(self) 501 @middle.pack("side"=>"left","expand"=>"yes","fill"=>"y") 502 503 @right = TkColorMiddleRightFrame.new(self) 504 @right.pack("side"=>"left","padx"=>".25c","pady"=>".25c","anchor"=>"s") 505 506 self 507 end 508end 509 510 511class TkColor<TkRoot 512 attr_reader :menu, :bottom, :middle 513 514 def initialize(*args) 515 super(*args) 516 @menu = TkColorMenuFrame.new(self) 517 @menu.pack("side"=>"top", "fill"=>"x") 518 519 @bottom = TkColorBotFrame.new(self) 520 @bottom.pack("side"=>"bottom","fill"=>"x") 521 522 @middle = TkColorMiddleFrame.new(self) 523 @middle.pack("side"=>"top","fill"=>"both") 524 525 self 526 end 527end 528 529 530$root = TkColor.new 531 532# ������������������������������������������������ 533changeColorSpace :rgb 534Tk.mainloop 535