# gui/implementation/SwitchBox.tcl

    @implementation SwitchBox {
      - init {} {
          $super init
          $self hideBorder
          set imageOff [@imageCopy switchOff]
          set imageOn [@imageCopy switchOn]
          set callbacks(Change) {}
        }

      - items {} {
          return [fieldValueList fields]
        }
      - items: anItemsList {
          $self clear
          foreach item $anItemsList {
            $self add: $item
          }
        }

      - values {} {
          return [fieldValueList values]
        }
      - values: aValuesList {
          foreach value $aValuesList field [$self items] {
            $self valueOf: $field to: $value
          }
        }

      - list {} {
          return $fieldValueList
        }
      - list: aFieldValueList {
          foreach {field value} $aFieldValueList {
            $self add: $field withValue: $value
          }
        }

      - valueOf: anItem {
          return [fieldValueList get: $anItem]
        }
      - valueOf:to: {anItem boolean} {
          switch $boolean {
            0 { set img $imageOff }
            1 { set img $imageOn }
            default { return -code error "unknown boolean ($boolean)" }
          }
          fieldValueList set: $anItem to: $boolean
          "$frame.i$anItem" configure -image $img
          $self onChange
        }

      - switchOn: anItem {
          $self valueOf: $anItem to: 1
        }
      - switchOff: anItem {
          $self valueOf: $anItem to: 0
        }

      - toggle: anItem {
          if [fieldValueList get: $anItem] {
            $self switchOff: $anItem
          } else {
            $self switchOn: $anItem
          }
        }

      - add: anItem {
          $self add: $anItem withValue: 0
        }
      - add:withValue: {anItem boolean} {
          if [$self contains: $anItem] { return $self }
          fieldValueList add: [list $anItem 0]
          grid [label "$frame.l$anItem" -text $anItem -anchor e] \
            [label "$frame.i$anItem" -image $imageOff -bd 1 -relief raised] \
            -sticky ew
          bind "$frame.l$anItem" <ButtonPress-1> "$self toggle: \"$anItem\""
          bind "$frame.i$anItem" <ButtonPress-1> "$self toggle: \"$anItem\""
          bind "$frame.l$anItem" <ButtonRelease-1> "$self valueChangeFor: \"$anItem\""
          bind "$frame.i$anItem" <ButtonRelease-1> "$self valueChangeFor: \"$anItem\""
          eval bind \"$frame.l$anItem\" [@removeBindingsOnDestroyEvent]
          eval bind \"$frame.i$anItem\" [@removeBindingsOnDestroyEvent]
          $self valueOf: $anItem to: $boolean
        }
      - remove: anItem {
          if {![$self contains: $anItem]} { return $self }
          fieldValueList remove: $anItem
          catch {destroy "$frame.l$anItem" "$frame.i$anItem"}
        }
      - contains: anItem {
          return [fieldValueList contains: $anItem]
        }

      - onChange: aCallback {
          set callbacks(Change) $aCallback
        }
      - onChange {} {
          return $callbacks(Change)
        }
      - valueChangeFor: selection {
          if [string length $callbacks(Change)] {
            catch {eval $callbacks(Change)}
          }
        }

      - clear {} {
          foreach {field value} $fieldValueList {
            $self remove: $field
          }
        }
      - sort {} {
          foreach field [set fields [$self items]] {
            grid forget "$frame.l$field" "$frame.i$field"
          }
          fieldValueList sortByField
          foreach {field value} $fieldValueList {
            grid "$frame.l$field" "$frame.i$field" -sticky ew
          }
        }

      - loadFromFile: aFile {
          if [catch {set f [open $aFile r]} err] {
            return -code error "$self loadFromFile: $aFile ($err)"
          }
          while {[eof $f] == 0} {
            gets $f line
            if [string length $line] {
              if [regexp "," $line] {
                set field [lindex [split $line ,] 0]
                set value [lindex [split $line ,] 1]
                $self add: $field withValue: $value
              } else {
                $self add: $line
              }
            }
          }
          close $f
        }

      - dealloc {} {
          foreach {field value} $fieldValueList {
            catch {destroy "$frame.l$field" "$frame.i$field"}
          }
          return [$super dealloc]
        }
    }