palette.tcl 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. # palette.tcl --
  2. #
  3. # This file contains procedures that change the color palette used
  4. # by Tk.
  5. #
  6. # Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7. #
  8. # See the file "license.terms" for information on usage and redistribution
  9. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10. #
  11. # ::tk_setPalette --
  12. # Changes the default color scheme for a Tk application by setting
  13. # default colors in the option database and by modifying all of the
  14. # color options for existing widgets that have the default value.
  15. #
  16. # Arguments:
  17. # The arguments consist of either a single color name, which
  18. # will be used as the new background color (all other colors will
  19. # be computed from this) or an even number of values consisting of
  20. # option names and values. The name for an option is the one used
  21. # for the option database, such as activeForeground, not -activeforeground.
  22. proc ::tk_setPalette {args} {
  23. if {[winfo depth .] == 1} {
  24. # Just return on monochrome displays, otherwise errors will occur
  25. return
  26. }
  27. # Create an array that has the complete new palette. If some colors
  28. # aren't specified, compute them from other colors that are specified.
  29. if {[llength $args] == 1} {
  30. set new(background) [lindex $args 0]
  31. } else {
  32. array set new $args
  33. }
  34. if {![info exists new(background)]} {
  35. error "must specify a background color"
  36. }
  37. set bg [winfo rgb . $new(background)]
  38. if {![info exists new(foreground)]} {
  39. # Note that the range of each value in the triple returned by
  40. # [winfo rgb] is 0-65535, and your eyes are more sensitive to
  41. # green than to red, and more to red than to blue.
  42. foreach {r g b} $bg {break}
  43. if {$r+1.5*$g+0.5*$b > 100000} {
  44. set new(foreground) black
  45. } else {
  46. set new(foreground) white
  47. }
  48. }
  49. lassign [winfo rgb . $new(foreground)] fg_r fg_g fg_b
  50. lassign $bg bg_r bg_g bg_b
  51. set darkerBg [format #%02x%02x%02x [expr {(9*$bg_r)/2560}] \
  52. [expr {(9*$bg_g)/2560}] [expr {(9*$bg_b)/2560}]]
  53. foreach i {activeForeground insertBackground selectForeground \
  54. highlightColor} {
  55. if {![info exists new($i)]} {
  56. set new($i) $new(foreground)
  57. }
  58. }
  59. if {![info exists new(disabledForeground)]} {
  60. set new(disabledForeground) [format #%02x%02x%02x \
  61. [expr {(3*$bg_r + $fg_r)/1024}] \
  62. [expr {(3*$bg_g + $fg_g)/1024}] \
  63. [expr {(3*$bg_b + $fg_b)/1024}]]
  64. }
  65. if {![info exists new(highlightBackground)]} {
  66. set new(highlightBackground) $new(background)
  67. }
  68. if {![info exists new(activeBackground)]} {
  69. # Pick a default active background that islighter than the
  70. # normal background. To do this, round each color component
  71. # up by 15% or 1/3 of the way to full white, whichever is
  72. # greater.
  73. foreach i {0 1 2} color $bg {
  74. set light($i) [expr {$color/256}]
  75. set inc1 [expr {($light($i)*15)/100}]
  76. set inc2 [expr {(255-$light($i))/3}]
  77. if {$inc1 > $inc2} {
  78. incr light($i) $inc1
  79. } else {
  80. incr light($i) $inc2
  81. }
  82. if {$light($i) > 255} {
  83. set light($i) 255
  84. }
  85. }
  86. set new(activeBackground) [format #%02x%02x%02x $light(0) \
  87. $light(1) $light(2)]
  88. }
  89. if {![info exists new(selectBackground)]} {
  90. set new(selectBackground) $darkerBg
  91. }
  92. if {![info exists new(troughColor)]} {
  93. set new(troughColor) $darkerBg
  94. }
  95. # let's make one of each of the widgets so we know what the
  96. # defaults are currently for this platform.
  97. toplevel .___tk_set_palette
  98. wm withdraw .___tk_set_palette
  99. foreach q {
  100. button canvas checkbutton entry frame label labelframe
  101. listbox menubutton menu message radiobutton scale scrollbar
  102. spinbox text
  103. } {
  104. $q .___tk_set_palette.$q
  105. }
  106. # Walk the widget hierarchy, recoloring all existing windows.
  107. # The option database must be set according to what we do here,
  108. # but it breaks things if we set things in the database while
  109. # we are changing colors...so, ::tk::RecolorTree now returns the
  110. # option database changes that need to be made, and they
  111. # need to be evalled here to take effect.
  112. # We have to walk the whole widget tree instead of just
  113. # relying on the widgets we've created above to do the work
  114. # because different extensions may provide other kinds
  115. # of widgets that we don't currently know about, so we'll
  116. # walk the whole hierarchy just in case.
  117. eval [tk::RecolorTree . new]
  118. destroy .___tk_set_palette
  119. # Change the option database so that future windows will get the
  120. # same colors.
  121. foreach option [array names new] {
  122. option add *$option $new($option) widgetDefault
  123. }
  124. # Save the options in the variable ::tk::Palette, for use the
  125. # next time we change the options.
  126. array set ::tk::Palette [array get new]
  127. }
  128. # ::tk::RecolorTree --
  129. # This procedure changes the colors in a window and all of its
  130. # descendants, according to information provided by the colors
  131. # argument. This looks at the defaults provided by the option
  132. # database, if it exists, and if not, then it looks at the default
  133. # value of the widget itself.
  134. #
  135. # Arguments:
  136. # w - The name of a window. This window and all its
  137. # descendants are recolored.
  138. # colors - The name of an array variable in the caller,
  139. # which contains color information. Each element
  140. # is named after a widget configuration option, and
  141. # each value is the value for that option.
  142. proc ::tk::RecolorTree {w colors} {
  143. upvar $colors c
  144. set result {}
  145. set prototype .___tk_set_palette.[string tolower [winfo class $w]]
  146. if {![winfo exists $prototype]} {
  147. unset prototype
  148. }
  149. foreach dbOption [array names c] {
  150. set option -[string tolower $dbOption]
  151. set class [string replace $dbOption 0 0 [string toupper \
  152. [string index $dbOption 0]]]
  153. if {![catch {$w configure $option} value]} {
  154. # if the option database has a preference for this
  155. # dbOption, then use it, otherwise use the defaults
  156. # for the widget.
  157. set defaultcolor [option get $w $dbOption $class]
  158. if {$defaultcolor eq "" || \
  159. ([info exists prototype] && \
  160. [$prototype cget $option] ne "$defaultcolor")} {
  161. set defaultcolor [lindex $value 3]
  162. }
  163. if {$defaultcolor ne ""} {
  164. set defaultcolor [winfo rgb . $defaultcolor]
  165. }
  166. set chosencolor [lindex $value 4]
  167. if {$chosencolor ne ""} {
  168. set chosencolor [winfo rgb . $chosencolor]
  169. }
  170. if {[string match $defaultcolor $chosencolor]} {
  171. # Change the option database so that future windows will get
  172. # the same colors.
  173. append result ";\noption add [list \
  174. *[winfo class $w].$dbOption $c($dbOption) 60]"
  175. $w configure $option $c($dbOption)
  176. }
  177. }
  178. }
  179. foreach child [winfo children $w] {
  180. append result ";\n[::tk::RecolorTree $child c]"
  181. }
  182. return $result
  183. }
  184. # ::tk::Darken --
  185. # Given a color name, computes a new color value that darkens (or
  186. # brightens) the given color by a given percent.
  187. #
  188. # Arguments:
  189. # color - Name of starting color.
  190. # perecent - Integer telling how much to brighten or darken as a
  191. # percent: 50 means darken by 50%, 110 means brighten
  192. # by 10%.
  193. proc ::tk::Darken {color percent} {
  194. foreach {red green blue} [winfo rgb . $color] {
  195. set red [expr {($red/256)*$percent/100}]
  196. set green [expr {($green/256)*$percent/100}]
  197. set blue [expr {($blue/256)*$percent/100}]
  198. break
  199. }
  200. if {$red > 255} {
  201. set red 255
  202. }
  203. if {$green > 255} {
  204. set green 255
  205. }
  206. if {$blue > 255} {
  207. set blue 255
  208. }
  209. return [format "#%02x%02x%02x" $red $green $blue]
  210. }
  211. # ::tk_bisque --
  212. # Reset the Tk color palette to the old "bisque" colors.
  213. #
  214. # Arguments:
  215. # None.
  216. proc ::tk_bisque {} {
  217. tk_setPalette activeBackground #e6ceb1 activeForeground black \
  218. background #ffe4c4 disabledForeground #b0b0b0 foreground black \
  219. highlightBackground #ffe4c4 highlightColor black \
  220. insertBackground black \
  221. selectBackground #e6ceb1 selectForeground black \
  222. troughColor #cdb79e
  223. }