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