Version 0 of Color palettes for ttk

Updated 2013-05-28 22:10:48 by bll

Color palettes for ttk

colorTheme::createPalette uses the tk_setPalette algorithms to create a color palette. This routine could use some work by a color expert as some of the color choices could use a little more contrast.

The background color must be passed as an argument, and any of the other colors may be preset in the colors array.

The basic colors are: background, foreground, activeBackground, disabledForeground, selectForeground, selectBackground, troughColor, textColor, textBackground, fieldBackground and indicatorColor.

Additional colors are: activeForeground, arrowColor, disabledBackground, insertBackground, readonlyBackground, readonlyForeground, disabledFieldBackground, readonlyFieldBackground, indicatorSelectColor, indicatorPressedColor, comboboxListBackground, comboboxListForeground, notebooktabSelectBackground, inactiveSelectBackground, textSelectBackground and textSelectForeground.

colorTheme::createBisquePalette creates the old bisque color palette.

colorTheme::setColors sets the colors of all widgets, including non-ttk widgets, using the color palette supplied to it.


package require Tk

namespace eval colorTheme {

  # checkbutton: indicatorOn defaults to true, so this is normally drawn:
  #     {-selectcolor selectColor}
  # radiobutton: indicatorOn defaults to true, so this is normally drawn:
  #     {-selectcolor selectColor}

  set widgets {
    button {
        info { isttk false classname Button }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
          {-disabledforeground disabledForeground}
        }
      }
    TButton {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground
            readonly readonlyBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground
            readonly readonlyForeground}
        }
      }
    checkbutton {
        info { isttk false classname Checkbutton }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-disabledforeground disabledForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TCheckbutton {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active   activeForeground
            disabled disabledForeground}
          {-indicatorcolor      indicatorColor}
          {map -indicatorcolor
            pressed  indicatorPressedColor
            selected indicatorSelectColor}
        }
      }
    TCombobox {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
          {option *TCombobox*Listbox.background comboboxListBackground}
          {option *TCombobox*Listbox.foreground comboboxListForeground}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
          {-fieldbackground fieldBackground}
          {map -fieldbackground
            disabled disabledFieldBackground
            readonly readonlyFieldBackground}
        }
      }
    entry {
        info { isttk false classname Entry }
        colors {
          {-background fieldBackground}
          {-foreground foreground}
          {-disabledbackground disabledBackground}
          {-disabledforeground disabledForeground}
          {-readonlybackground readonlyBackground}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TEntry {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
          {-fieldbackground fieldBackground}
          {map -fieldbackground
            disabled disabledFieldBackground
            readonly readonlyFieldBackground}
        }
      }
    frame {
        info { isttk false classname Frame }
        colors {
          {-background background}
        }
      }
    TFrame {
        info { isttk true }
        colors {
          {-background background}
        }
      }
    label {
        info { isttk false classname Label }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-disabledforeground disabledForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TLabel {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            disabled background}
          {-foreground foreground}
          {map -foreground
            disabled disabledForeground}
        }
      }
    labelframe {
        info { isttk false classname Labelframe }
        colors {
          {-foreground foreground}
          {-background background}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TLabelframe {
        info { isttk true }
        colors {
          {-background background}
        }
      }
    TLabelframe.Label {
        info { isttk true }
        colors {
          {-background background}
          {-foreground foreground}
        }
      }
    listbox {
        info { isttk false classname Listbox }
        colors {
          {-foreground foreground}
          {-background fieldBackground}
          {-disabledforeground disabledForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
        }
      }
    menu {
        info { isttk false classname Menu }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-disabledforeground disabledForeground}
          {-selectcolor selectColor}
        }
      }
    menubutton {
        info { isttk false classname Menubutton }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-disabledforeground disabledForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TMenubutton {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
        }
      }
    TNotebook {
        info { isttk true }
        colors {
          {-background background}
        }
      }
    TNotebook.Tab {
        info { isttk true}
        colors {
          {-background troughColor}
          {map -background
            active   activeBackground
            disabled disabledBackground
            selected notebooktabSelectBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
        }
      }
    TPanedwindow {
        info { isttk true  }
        colors {
          {-background background}
        }
      }
    panedwindow {
        info { isttk false classname Panedwindow }
        colors {
          {-background background}
        }
      }
    TProgressbar {
        info { isttk true  }
        colors {
          {-background  selectBackground}
          {-troughcolor troughColor}
        }
      }
    radiobutton {
        info { isttk false classname Radiobutton }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-activeforeground activeForeground}
          {-disabledforeground disabledForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TRadiobutton {
        info { isttk true  }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground
            readonly readonlyBackground}
          {-foreground foreground}
          {map -foreground
            active   activeForeground
            disabled disabledForeground
            readonly readonlyForeground}
          {-indicatorcolor indicatorColor}
          {map -indicatorcolor
            pressed  indicatorPressedColor
            selected indicatorSelectColor}
        }
      }
    scale {
        info { isttk false classname Scale }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
          {-troughcolor troughColor}
        }
      }
    TScale {
        info { isttk true  }
        colors {
          {-background background}
          {-troughcolor troughColor}
          {map -background \
              active activeBackground}
         }
      }
    scrollbar {
        info { isttk false classname Scrollbar }
        colors {
          {-background background}
          {-activebackground activeBackground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
          {-troughcolor troughColor}
        }
      }
    TScrollbar {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
          {-troughcolor troughColor}
          {-arrowcolor arrowColor}
          {map -arrowcolor
            disabled disabledForeground}
        }
      }
    TSeparator {
        info { isttk true }
        colors {
          {-background background}
        }
      }
    TSizegrip {
        info { isttk true }
        colors {
          {-background background}
        }
      }
    spinbox {
        info { isttk false classname Spinbox }
        colors {
          {-background background}
          {-foreground foreground}
          {-activebackground activeBackground}
          {-disabledbackground disabledBackground}
          {-disabledforeground foreground}
          {-buttonbackground background}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
          {-highlightbackground highlightBackground}
          {-highlightcolor highlightColor}
        }
      }
    TSpinbox {
        info { isttk true }
        colors {
          {-background background}
          {map -background
            active   activeBackground
            disabled disabledBackground}
          {-foreground foreground}
          {map -foreground
            active activeForeground
            disabled disabledForeground}
          {-selectbackground selectBackground}
          {-selectforeground selectForeground}
          {-fieldbackground textBackground}
          {map -fieldbackground
            readonly    readonlyFieldBackground
            disabled    disabledFieldBackground}
          {-arrowcolor arrowColor}
          {map -arrowcolor
            disabled disabledForeground}
        }
      }
    text {
        info { isttk false classname Text }
        colors {
          {-background textBackground}
          {-foreground foreground}
          {-selectforeground textSelectForeground}
          {-selectbackground textSelectBackground}
          {-inactiveselectbackground inactiveSelectBackground}
          {-insertbackground insertBackground}
        }
      }
    Treeview {
        info { isttk true }
        colors {
          {-background textBackground}
          {map -background
            selected selectBackground}
          {-foreground textColor}
          {map -foreground
            selected selectForeground}
          {-fieldbackground fieldBackground}
        }
      }
    Heading {
        info { isttk true }
        colors {
          {-background background}
          {-foreground foreground}
        }
      }
  }

  proc _wlist {{W .}} {
    set list [list $W]
    foreach w [winfo children $W] {
      set list [concat $list [_wlist $w]]
    }
    return $list
  }

  proc createPalette { background colorsv} {
    upvar $colorsv colors

    if { $background == "default" } {
      # colors from library/ttk/defaults.tcl
      # basic colors
      set colors(background) {#d9d9d9}         ; # -frame
      set colors(foreground) black             ; # -foreground
      set colors(activeBackground) {#ececec}   ; # -activebg
      set colors(disabledForeground) {#a3a3a3} ; # -disabledfg
      set colors(selectForeground) white       ; # -selectfg
      set colors(selectBackground) {#4a6984}   ; # -selectbg
      set colors(troughColor) {#c3c3c3}        ; # -darker
      set colors(textColor) black              ; # -text
      set colors(textBackground) white         ; # -window
      set colors(fieldBackground) white
      set colors(indicatorColor) white
      # other colors
      set colors(activeForeground) $colors(foreground)
      set colors(arrowColor) $colors(disabledForeground)
      set colors(disabledBackground) $colors(background)
      set colors(insertBackground) $colors(background)
      set colors(readonlyBackground) $colors(background)
      set colors(readonlyForeground) $colors(foreground)
      set colors(disabledFieldBackground) $colors(background)
      set colors(readonlyFieldBackground) $colors(background)
      set colors(indicatorSelectColor) $colors(selectBackground) ; # -indicator
      set colors(indicatorPressedColor) $colors(activeBackground)
      set colors(comboboxListBackground) $colors(fieldBackground)
      set colors(comboboxListForeground) $colors(foreground)
      set colors(notebooktabSelectBackground) $colors(background)
      set colors(inactiveSelectBackground) $colors(troughColor)
      set colors(textSelectBackground) $colors(troughColor)
      set colors(textSelectForeground) $colors(foreground)
    }

    if { $background != "default" } {
      # this code is from tk_setPalette
      set colors(background) $background
      lassign [winfo rgb . $background] bg_r bg_g bg_b

      if { ! [info exists colors(foreground)] } {
        if {$bg_r + 1.5 * $bg_g + 0.5 * $bg_b > 100000} {
          set colors(foreground) black
        } else {
          set colors(foreground) white
        }
      }
      lassign [winfo rgb . $colors(foreground)] fg_r fg_g fg_b

      if { ! [info exists colors(troughColor)] } {
        set colors(troughColor) [format #%02x%02x%02x \
            [expr {(9 * $bg_r) / 2560}] \
            [expr {(9 * $bg_g) / 2560}] \
            [expr {(9 * $bg_b) / 2560}] ]
      }

      foreach k {activeForeground readonlyForeground \
          comboboxListForeground textSelectForeground} {
        if {! [info exists colors($k)]} {
          set colors($k) $colors(foreground)
        }
      }

      if {! [info exists colors(disabledForeground)]} {
        set colors(disabledForeground) [format #%02x%02x%02x \
            [expr {(3 * $bg_r + $fg_r) / 1024}] \
            [expr {(3 * $bg_g + $fg_g) / 1024}] \
            [expr {(3 * $bg_b + $fg_b) / 1024}] ]
      }
      if {! [info exists colors(arrowColor)]} {
        set colors(arrowColor) $colors(disabledForeground)
      }

      if {! [info exists colors(activeBackground)]} {
        # Pick a default active background that islighter than the
        # normal background.  To do this, round each color component
        # up by 15% or 1/3 of the way to full white, whichever is
        # greater.

        foreach i {0 1 2} color [list $bg_r $bg_g $bg_b] {
          set light($i) [expr {$color / 256}]
          set inc1 [expr {($light($i) * 15) / 100}]
          set inc2 [expr {(255 - $light($i)) / 3}]
          if {$inc1 > $inc2} {
            incr light($i) $inc1
          } else {
            incr light($i) $inc2
          }
          if {$light($i) > 255} {
            set light($i) 255
          }
        }
        set colors(activeBackground) [format #%02x%02x%02x \
            $light(0) $light(1) $light(2)]
      }

      foreach k {indicatorPressedColor} {
        if {! [info exists colors($k)]} {
          set colors($k) $colors(activeBackground)
        }
      }

      foreach k {disabledBackground readonlyBackground insertBackground \
            disabledFieldBackground readonlyFieldBackground \
            notebooktabSelectBackground} {
        if {! [info exists colors($k)]} {
          set colors($k) $colors(background)
        }
      }

      foreach k {selectBackground indicatorSelectColor \
          inactiveSelectBackground textSelectBackground} {
        if {! [info exists colors($k)]} {
          set colors($k) $colors(troughColor)
        }
      }

      # this may not be the best thing to do for
      # textColor/textBackground with dark themes.
      set tcol white
      set tcolb black
      if { $colors(foreground) == "white" } {
        set tcol black
        set tcolb white
      }
      foreach {k} {selectForeground fieldBackground \
          indicatorColor textBackground} {
        if {! [info exists colors($k)]} {
          set colors($k) $tcol
        }
      }
      if {! [info exists colors(textColor)]} {
        set colors(textColor) $tcolb
      }
      if {! [info exists colors(comboboxListBackground)]} {
        set colors(comboboxListBackground) $colors(textBackground)
      }
    }

    # older names for backwards compatibility to old tk
    set colors(highlightColor) $colors(foreground)
    set colors(highlightBackground) $colors(background)
    set colors(selectColor) $colors(indicatorSelectColor)
  }

  proc createBisquePalette { colorsv } {
    upvar $colorsv colors
    array set colors [list activeBackground #e6ceb1 activeForeground black \
        background #ffe4c4 disabledForeground #b0b0b0 foreground black \
        highlightBackground #ffe4c4 highlightColor black \
        insertBackground black \
        selectBackground #e6ceb1 selectForeground black \
        troughColor #cdb79e]
    createPalette $colors(background) colors
  }

  proc setColors { colorsv } {
    upvar $colorsv colors
    variable widgets

    set hasttk false
    if { ! [catch {ttk::style theme use}] } {
      set hasttk true
    }

    foreach {w} [_wlist] {
      if { [string equal [winfo toplevel $w] $w] } {
        lappend toplevels $w
      }
      set cls [winfo class $w]
      lappend windowlist $w $cls
    }

    set regexlist {}
    foreach {k v} [array get colors] {
      lappend regexlist " $k" " $v"
    }

    dict for {widget wdict} $widgets {
      array set info [dict get $wdict info]
      if { ! $hasttk && $info(isttk) } {
        continue
      }
      if { ! [dict exists $wdict colors] } {
        continue
      }
      foreach col [dict get $wdict colors] {
        foreach {pat repl} $regexlist {
          regsub -all $pat $col $repl col
        }
        if { $info(isttk) } {
          set t [lindex $col 0]
          if { $t == "option" } {
            eval option add [lrange $col 1 end]
          } elseif { $t == "map" } {
            set t [lindex $col 1]
            set l [lrange $col 2 end]
            eval ttk::style map ${widget} $t [list $l]
          } else {
            eval ttk::style configure ${widget} $col
          }
        } else {
          foreach {w cls} $windowlist {
            if { $info(classname) == $cls } {
              eval $w configure $col
            }
          }
        } ; # else not ttk
      } ; # for each color value for the widget
    } ; # for each widget type

    foreach {t} $toplevels {
      $t configure -background $colors(background)
    }
  }

}

See also: Changing Widget Colors