# copyright (C) 1997-2001 Jean-Luc Fontaine (mailto:jfontain@free.fr)
# this program is free software: please read the COPYRIGHT file enclosed in this package or use the Help Copyright menu

set rcsId {$Id: config.tcl,v 2.16 2000/12/31 23:14:19 jfontain Exp $}


namespace eval configuration {

    variable container
    variable interface
    variable hierarchy {
        canvas canvas.size canvas.colors canvas.printing viewers viewers.colors viewers.graphs viewers.pies
        thresholds thresholds.email
    }
    variable configure {1 1 1 0 1 1 1 1 0 0}                                        ;# whether folder should appear when configuring
    variable helpMessage
    set helpMessage(preferences) "Preferences for the user: $::env(USER)"
    set helpMessage(configuration) {Configuration for the current view.}

    variable entryIcons                                                       ;# closed and opened folder icons for hierarchical box
    lappend entryIcons [image create photo -data {
        R0lGODlhEAANAPIAAAAAAH9/f7+/v///AP///wAAAAAAAAAAACH+JEZpbGUgd3JpdHRlbiBieSBBZG9iZSBQaG90b3Nob3CoIDUuMAAsAAAAABAADQAAAzNI
        Gsz6kAQxqAjxzcpvc1KWBUDYnRQZWmilYi37EmztlrAt43R8mzrO60P8lAiApHK5TAAAOw==
    }]
    lappend entryIcons [image create photo -data {
        R0lGODlhEAANAPIAAAAAAH9/f7+/v///////AAAAAAAAAAAAACH+JEZpbGUgd3JpdHRlbiBieSBBZG9iZSBQaG90b3Nob3CoIDUuMAAsAAAAABAADQAAAzk4
        Gsz6cIQ44xqCZCGbk4MmclAAgNs4ml7rEaxVAkKc3gTAnBO+sbyQT6M7gVQpk9HlAhgHzqhUmgAAOw==
    }]

    proc load {arrayList} {
        foreach {name value} $arrayList {
            set ::global::$name $value
        }
    }

    proc edit {preferencesMode} {                                                                        ;# preferences mode boolean
        variable hierarchy
        variable configure
        variable container
        variable interface
        variable tree
        variable preferences
        variable helpMessage
        variable dialog
        variable entryIcons

        set preferences $preferencesMode                                                                ;# store mode for sub sheets

        set objects {}                                                                  ;# to delete upon destruction of this folder

        set title {moodss: }
        if {$preferences} {
            append title Preferences
        } else {
            append title Configuration
        }
        set dialog [new dialogBox .grabber\
            -buttons hoc -default o -title $title -x [winfo pointerx .] -y [winfo pointery .]\
            -command configuration::done -helpcommand configuration::help -deletecommand {grab release .grabber} -die 0\
        ]
        grab .grabber                                                      ;# grab siblings such as help window so that it is usable
        lappend objects [linkedHelpWidgetTip $composite::($dialog,help,path)]

        set frame [frame $widget::($dialog,path).frame]

        set tree [blt::hierbox $frame.tree\
            -font $font::(mediumBold) -separator . -selectmode single -selectbackground lightgray -hideroot 1 -borderwidth 1\
            -highlightthickness 0 -takefocus 0 -width 150\
        ]
        set container [frame $frame.container -borderwidth 1 -relief sunken]

        set message [createMessage $container.message]
        if {$preferences} {
            $message configure -text $helpMessage(preferences)
        } else {
            $message configure -text $helpMessage(configuration)
        }
        pack $message -fill both -expand 1                                                   ;# initially display help message above

        bindtags $tree [list $tree [winfo toplevel $tree] all]                                              ;# ignore class bindtags
        $tree bind all <Double-ButtonPress-1> {}                                                           ;# and selection bindings
        $tree bind all <Shift-ButtonPress-1> {}
        $tree bind all <Control-ButtonPress-1> {}
        $tree bind all <B1-Motion> {}
        # only keep opening binding (no longer on double click)
        $tree bind all <ButtonRelease-1> "$tree toggle current; $tree toggle current"

        catch {unset interface(current)}                                                               ;# currently opened interface

        foreach entry $hierarchy specific $configure {
            if {!$preferences&&!$specific} continue
            set index [$tree insert end $entry]                                         ;# used generated tree index as unique index
            regsub -all {\.} $entry :: interface($index,class)
            $interface($index,class)::initialize
            $tree entry configure $index -opencommand "configuration::open $index" -icons $entryIcons
        }

        pack $tree -side left -fill y -padx 2
        pack $container -fill both -expand 1 -padx 2

        dialogBox::display $dialog $frame

        wm geometry $widget::($dialog,path) 500x300                                                        ;# maintain constant size

        bind $frame <Destroy> "delete $objects"                                      ;# delete objects not managed by the dialog box
    }

    proc open {index} {
        variable container
        variable interface

        # check validity before moving to next interface
        if {[info exists interface(current)]&&![$interface($interface(current),class)::check]} return
        eval destroy [winfo children $container]                                              ;# eventually remove current interface
        set frame [frame $container.frame]             ;# use a separate frame so that interfaces widget management cannot interfere
        pack $frame -fill both -expand 1
        $interface($index,class)::edit $frame
        set interface(current) $index
    }

    proc done {} {
        variable interface
        variable preferences
        variable variables
        variable dialog

        # check validity before closing
        if {[info exists interface(current)]&&![$interface($interface(current),class)::check]} return
        foreach name [array names interface *,class] {
            $interface($name)::apply                                                                             ;# apply new values
        }
        if {$preferences} {
            preferences::save $variables(1)
        }
        delete $dialog
    }

    proc help {} {
        variable interface
        variable preferences

        if {[info exists interface(current)]} {
            $interface($interface(current),class)::help
        } elseif {$preferences} {
            generalHelpWindow #core.preferences
        } else {
            generalHelpWindow #core.configuration
        }
    }

    proc createMessage {path args} {                  ;# create a generic message widget with eventual option / value pairs argument
        message $path -width [winfo screenwidth .] -font $font::(mediumNormal) -justify left
        eval $path configure $args
        return $path
    }

    proc initialize {name} {                  ;# for use by folder classes, in order to initialize local variables depending on mode
        variable preferences

        if {$preferences} {
            if {![info exists ::preferences::$name]} {                       ;# initialize from global value if rc file was not read
                set ::preferences::$name [set ::global::$name]
            }
            return [set ::preferences::$name]
        } else {
            return [set ::global::$name]
        }
    }

    proc apply {name value} {                    ;# for use by folder classes, in order to update global variables depending on mode
        variable preferences

        set namespaces ::global                                                                       ;# always update global values
        if {$preferences} {
            lappend namespaces ::preferences                                                           ;# and eventually preferences
        }
        foreach namespace $namespaces {
            if {![info exists ${namespace}::$name]||($value!=[set ${namespace}::$name])} {
                # update only when necessary in order not to activate a trace needlessly
                set ${namespace}::$name $value
            }
        }
    }

    proc variables {preferences} {                      ;# never access configuration variables directly: use this procedure instead
        variable variables

        return $variables($preferences)
    }

    namespace eval canvas {

        proc initialize {} {}

        proc edit {parentPath} {
            set message [configuration::createMessage $parentPath.message -text {Canvas configuration}]
            pack $message -fill both -expand 1                                               ;# initially display help message above
        }

        proc check {} {
            return 1                                                                                         ;# no data in this page
        }

        proc apply {} {}

        proc variables {} {return {}}

        proc help {} {
            generalHelpWindow #configuration.canvas
        }

        namespace eval size {                                                                                ;# start of canvas size

            proc variables {} {                                       ;# list of unqualified global variables handled by this folder
                return {canvasHeight canvasWidth}
            }

            proc initialize {} {
                variable height [configuration::initialize canvasHeight]
                variable width [configuration::initialize canvasWidth]
            }

            proc edit {parentPath} {
                variable height
                variable width
                variable message

                set message [configuration::createMessage $parentPath.message -text {Enter size (in pixels):}]
                grid $message -sticky nsew -row 0 -column 0 -columnspan 100                                    ;# occupy whole width
                grid rowconfigure $parentPath 0 -weight 1

                grid columnconfigure $parentPath 0 -weight 1

                if {$::tcl_version<8.4} {
                    set widthEntry [new spinEntry $parentPath -font $font::(mediumBold) -width 4 -list {640 800 1024 1280 1600}]
                    spinEntry::set $widthEntry $width
                    grid $widget::($widthEntry,path) -row 1 -column 2
                    set path $composite::($widthEntry,entry,path)
                } else {                                                                            ;# use native widget if possible
                    set path [spinbox $parentPath.widthEntry -font $font::(mediumBold) -width 4 -values {640 800 1024 1280 1600}]
                    $path set $width
                    grid $path -row 1 -column 2
                }
                $path configure -textvariable configuration::canvas::size::width
                # filter on positive integers and limit entry length
                setupEntryValidation $path {{checkMaximumLength 4 %P} {checkUnsignedInteger %P}}
                grid [label $parentPath.width -font $font::(mediumBold) -text width:] -row 1 -column 1 -padx 2
                grid columnconfigure $parentPath 3 -weight 1

                if {$::tcl_version<8.4} {
                    set heightEntry [new spinEntry $parentPath -font $font::(mediumBold) -width 4 -list {400 480 600 768 1024 1280}]
                    spinEntry::set $heightEntry $height
                    grid $widget::($heightEntry,path) -row 1 -column 5
                    set path $composite::($heightEntry,entry,path)
                } else {                                                                            ;# use native widget if possible
                    set path\
                        [spinbox $parentPath.heightEntry -font $font::(mediumBold) -width 4 -values {400 480 600 768 1024 1280}]
                    $path set $height
                    grid $path -row 1 -column 5
                }
                $path configure -textvariable configuration::canvas::size::height
                # filter on positive integers and limit entry length
                setupEntryValidation $path {{checkMaximumLength 4 %P} {checkUnsignedInteger %P}}
                grid [label $parentPath.height -font $font::(mediumBold) -text height:] -row 1 -column 4 -padx 2
                grid columnconfigure $parentPath 6 -weight 1

                grid [button $parentPath.apply -text Apply -command configuration::canvas::size::apply]\
                    -row 2 -column 0 -columnspan 100
                grid rowconfigure $parentPath 2 -weight 1

                if {$::tcl_version<8.4} {
                    bind $message <Destroy> "delete $widthEntry $heightEntry"               ;# delete inner objects upon destruction
                }
            }

            proc check {} {
                variable height
                variable width
                variable message

                set valid 1
                foreach item {height width} {
                    if {[string length [set $item]]==0} {
                        set text "please set $item."
                        set valid 0
                        break
                    }
                    if {[set $item]==0} {                                           ;# cannot be negative because of input filtering
                        set text "$item cannot be set to 0."
                        set valid 0
                        break
                    }
                }
                if {!$valid} {
                    $message configure -font $::font::(mediumBold) -text $text
                    bell
                }
                return $valid
            }

            proc apply {} {
                variable height
                variable width

                if {![check]} return
                configuration::apply canvasHeight $height
                configuration::apply canvasWidth $width
            }

            proc help {} {
                generalHelpWindow #configuration.canvas.size
            }

        }                                                                                                      ;# end of canvas size

        namespace eval colors {                                                                            ;# start of canvas colors

            proc variables {} {
                return canvasBackground
            }

            proc initialize {} {
                variable background [configuration::initialize canvasBackground]
            }

            proc edit {parentPath} {
                variable background
                variable colorViewer

                set message [configuration::createMessage $parentPath.message -text {Background color:}]
                grid $message -sticky nsew -row 0 -column 0 -columnspan 100                                    ;# occupy whole width
                grid rowconfigure $parentPath 0 -weight 1

                grid columnconfigure $parentPath 0 -weight 1

                set colorViewer\
                    [button $parentPath.choose -text Choose... -command "configuration::canvas::colors::choose $parentPath"]
                updateColorViewer
                grid $colorViewer -row 1 -column 1
                grid [button $parentPath.apply -text Apply -command configuration::canvas::colors::apply] -row 1 -column 2

                grid columnconfigure $parentPath 1 -weight 1
                grid columnconfigure $parentPath 2 -weight 1
                grid columnconfigure $parentPath 3 -weight 1

                grid rowconfigure $parentPath 2 -weight 1
            }

            proc check {} {
                return 1                                                                             ;# chosen color is always valid
            }

            proc apply {} {
                variable background

                if {![check]} return
                configuration::apply canvasBackground $background
            }

            proc updateColorViewer {} {
                variable colorViewer
                variable background

                foreach {red green blue} [winfo rgb $colorViewer $background] {}
                if {($red+$green+$blue)>=(32768*3)} {                                                            ;# light background
                    $colorViewer configure -foreground black
                } else {                                                                                          ;# dark background
                    $colorViewer configure -foreground white
                }
                $colorViewer configure -background $background
            }

            proc choose {parentPath} {
                variable background

                set choice [tk_chooseColor -initialcolor $background -title {Choose color:} -parent $parentPath]
                if {[string length $choice]>0} {
                    set background $choice
                    updateColorViewer
                }
            }

            proc help {} {
                generalHelpWindow #configuration.canvas.colors
            }

        }                                                                                                    ;# end of canvas colors

        namespace eval printing {                                                                        ;# start of canvas printing

            variable helpText {}

            proc variables {} {
                return {printToFile fileToPrintTo printCommand printOrientation printPalette printPaperSize}
            }

            proc initialize {} {
                variable toFile [configuration::initialize printToFile]
                variable printFile [configuration::initialize fileToPrintTo]
                variable command [configuration::initialize printCommand]
                variable orientation [configuration::initialize printOrientation]
                variable palette [configuration::initialize printPalette]
                variable size [configuration::initialize printPaperSize]
            }

            proc edit {parentPath} {
                variable helpText
                variable toFile
                variable printFile
                variable command
                variable orientation
                variable palette
                variable size

                set objects {}                                                          ;# to delete upon destruction of this folder

                set row 0
                set message [configuration::createMessage $parentPath.message -text {Printing setup:}]
                grid $message -sticky nsew -row $row -column 0 -columnspan 3                                   ;# occupy whole width
                grid rowconfigure $parentPath $row -weight 1

                incr row
                radiobutton $parentPath.toCommand -variable configuration::canvas::printing::toFile -value 0 -text Command:
                grid $parentPath.toCommand -row $row -column 0 -sticky w
                entry $parentPath.command -textvariable configuration::canvas::printing::command
                grid $parentPath.command -row $row -column 1 -columnspan 2 -sticky ew

                incr row
                radiobutton $parentPath.toFile -variable configuration::canvas::printing::toFile -value 1 -text {to File:}
                grid $parentPath.toFile -row $row -column 0 -sticky w
                entry $parentPath.file -textvariable configuration::canvas::printing::printFile
                grid $parentPath.file -row $row -column 1 -sticky ew
                button $parentPath.browse -text Browse... -command "configuration::canvas::printing::inquirePrintFile $parentPath"
                grid $parentPath.browse -row $row -column 2 -sticky ew
                if {$toFile} {
                    $parentPath.toFile invoke
                } else {
                    $parentPath.toCommand invoke
                }

                incr row
                grid [label $parentPath.orientation -text Orientation:] -row $row -column 0 -sticky w
                set entry\
                    [new comboEntry $parentPath -font $widget::option(entry,font) -list $global::printOrientations -editable 0]
                lappend objects $entry
                composite::configure $entry entry -textvariable configuration::canvas::printing::orientation
                composite::configure $entry button -listheight [llength $global::printOrientations]
                composite::configure $entry button scroll -selectmode single
                grid $widget::($entry,path) -row $row -column 1 -columnspan 2 -sticky ew

                incr row
                grid [label $parentPath.palette -text Palette:] -row $row -column 0 -sticky w
                set entry [new comboEntry $parentPath -font $widget::option(entry,font) -list $global::printPalettes -editable 0]
                lappend objects $entry
                composite::configure $entry entry -textvariable configuration::canvas::printing::palette
                composite::configure $entry button -listheight [llength $global::printPalettes]
                composite::configure $entry button scroll -selectmode single
                grid $widget::($entry,path) -row $row -column 1 -columnspan 2 -sticky ew

                incr row
                grid [label $parentPath.size -text {Paper size:}] -row $row -column 0 -sticky w
                set entry [new comboEntry $parentPath -font $widget::option(entry,font) -list $global::printPaperSizes -editable 0]
                lappend objects $entry
                composite::configure $entry entry -textvariable configuration::canvas::printing::size
                composite::configure $entry button -listheight [llength $global::printPaperSizes]
                composite::configure $entry button scroll -selectmode single
                grid $widget::($entry,path) -row $row -column 1 -columnspan 2 -sticky ew

                incr row
                set message [configuration::createMessage $parentPath.help -text $helpText]
                grid $message -sticky nsew -row $row -column 0 -columnspan 3
                grid rowconfigure $parentPath $row -weight 1

                bind $message <Destroy> "delete $objects"                                   ;# delete inner objects upon destruction
            }

            proc inquirePrintFile {parentPath} {
                variable printFile

                set file [tk_getSaveFile\
                    -title {moodss: File to print to} -parent $parentPath -initialdir [pwd] -defaultextension .ps\
                    -filetypes {{Postscript .ps} {{All files} *}} -initialfile $printFile\
                ]
                if {[string length $file]>0} {                                                                      ;# not cancelled
                    set printFile $file
                }
            }

            proc check {} {
                return 1                                                                             ;# chosen color is always valid
            }

            proc apply {} {
                variable toFile
                variable printFile
                variable command
                variable orientation
                variable palette
                variable size

                configuration::apply printToFile $toFile
                configuration::apply fileToPrintTo $printFile
                configuration::apply printCommand $command
                configuration::apply printOrientation $orientation
                configuration::apply printPalette $palette
                configuration::apply printPaperSize $size
            }

            proc help {} {
                generalHelpWindow #preferences.canvas.printing
            }

        }                                                                                                  ;# end of canvas printing

    }                                                                                                               ;# end of canvas


    namespace eval viewers {

        proc initialize {} {}

        proc edit {parentPath} {
            set message [configuration::createMessage $parentPath.message -text {Viewers configuration}]
            pack $message -fill both -expand 1                                               ;# initially display help message above
        }

        proc check {} {
            return 1                                                                                         ;# no data in this page
        }

        proc apply {} {}

        proc variables {} {return {}}

        proc help {} {
            generalHelpWindow #configuration.viewers
        }

        namespace eval colors {                                                                           ;# start of viewers colors

            variable helpText {}

            proc variables {} {
                return viewerColors
            }

            proc initialize {} {
                variable colors [configuration::initialize viewerColors]
            }

            proc edit {parentPath} {
                variable helpText
                variable colorsFrame

                set message [configuration::createMessage $parentPath.message -text {Change colors:}]
                grid $message -sticky nsew -row 0 -column 0 -columnspan 100
                grid rowconfigure $parentPath 0 -weight 1

                grid columnconfigure $parentPath 0 -weight 1

                set colorsFrame [frame $parentPath.colors -borderwidth 1 -background black]
                refresh
                grid $colorsFrame -row 1 -column 0

                set message [configuration::createMessage $parentPath.help -text $helpText]
                grid $message -sticky nsew -row 2 -column 0 -columnspan 100
                grid rowconfigure $parentPath 2 -weight 1
            }

            proc refresh {} {
                variable colors
                variable colorsFrame

                eval destroy [winfo children $colorsFrame]                                     ;# eventually remove existing buttons
                set index 0
                foreach color $colors {
                    set button [button $colorsFrame.$index -background $color -activebackground $color -borderwidth 1]
                    $button configure -command "configuration::viewers::colors::choose $index"
                    pack $button -side left
                    incr index
                }
            }

            proc choose {index} {
                variable colors
                variable colorsFrame

                set button $colorsFrame.$index
                set background [tk_chooseColor -initialcolor [$button cget -background] -title {Choose color:} -parent $button]
                if {[string length $background]>0} {
                    $button configure -background $background
                    set colors [lreplace $colors $index $index $background]
                }
            }

            proc check {} {
                return 1
            }

            proc apply {} {
                variable colors
                variable colorsFrame

                if {![check]} return
                if {![info exists colorsFrame]} return                                 ;# nothing to do as folder was never accessed
                configuration::apply viewerColors $colors
            }

            proc help {} {
                generalHelpWindow #configuration.viewers.colors
            }

        }                                                                                                   ;# end of viewers colors

        namespace eval graphs {                                                                           ;# start of viewers graphs

            variable helpText {}

            proc variables {} {
                return graphNumberOfIntervals
            }

            proc initialize {} {
                variable numberOfSamples [configuration::initialize graphNumberOfIntervals]
            }

            proc edit {parentPath} {
                variable helpText
                variable numberOfSamples
                variable message

                set message [configuration::createMessage $parentPath.message -text "Enter number of samples\nfor data graphs:"]
                grid $message -sticky nsew -row 0 -column 0 -columnspan 100
                grid rowconfigure $parentPath 0 -weight 1

                grid columnconfigure $parentPath 0 -weight 1

                if {$::tcl_version<8.4} {
                    set entry [new spinEntry $parentPath -font $font::(mediumBold) -width 4 -list {20 50 100 150 200 300 500 1000}]
                    spinEntry::set $entry $numberOfSamples
                    grid $widget::($entry,path) -row 1 -column 2
                    set path $composite::($entry,entry,path)
                } else {                                                                            ;# use native widget if possible
                    set path [spinbox $parentPath.entry -font $font::(mediumBold) -width 4 -values {20 50 100 150 200 300 500 1000}]
                    $path set $numberOfSamples
                    grid $path -row 1 -column 2
                }
                $path configure -textvariable configuration::viewers::graphs::numberOfSamples
                # filter on positive integers and limit entry length
                setupEntryValidation $path {{checkMaximumLength 4 %P} {checkUnsignedInteger %P}}

                grid [label $parentPath.width -font $font::(mediumBold) -text samples:] -row 1 -column 1 -padx 2

                grid columnconfigure $parentPath 3 -weight 1

                set message [configuration::createMessage $parentPath.help -text $helpText]
                grid $message -sticky nsew -row 2 -column 0 -columnspan 100
                grid rowconfigure $parentPath 2 -weight 1

                if {$::tcl_version<8.4} {
                    bind $message <Destroy> "delete $entry"                                 ;# delete inner objects upon destruction
                }
            }

            proc check {} {
                variable numberOfSamples
                variable message

                set valid 1
                if {[string length $numberOfSamples]==0} {
                    set text {please set number of samples.}
                    set valid 0
                } elseif {$numberOfSamples==0} {                                    ;# cannot be negative because of input filtering
                    set text {number of samples cannot be set to 0.}
                    set valid 0
                }
                if {!$valid} {
                    $message configure -font $::font::(mediumBold) -text $text
                    bell
                }
                return $valid
            }

            proc apply {} {
                variable numberOfSamples

                if {![check]} return
                configuration::apply graphNumberOfIntervals $numberOfSamples
            }

            proc help {} {
                generalHelpWindow #configuration.viewers.graphs
            }

        }                                                                                                   ;# end of viewers graphs

        namespace eval pies {                                                                               ;# start of viewers pies

            variable helpText {}

            proc variables {} {
                return pieLabeler
            }

            proc initialize {} {
                variable labeler [configuration::initialize pieLabeler]
            }

            proc edit {parentPath} {
                variable helpText

                set message [configuration::createMessage $parentPath.message -text {Choose labeler type for data pies:}]
                grid $message -sticky nsew -row 0 -column 0 -columnspan 100
                grid rowconfigure $parentPath 0 -weight 1

                grid columnconfigure $parentPath 0 -weight 1

                set button [radiobutton $parentPath.box -variable ::configuration::viewers::pies::labeler -value box -text box]
                grid $button -row 1 -column 1
                set button [radiobutton $parentPath.peripheral\
                    -variable ::configuration::viewers::pies::labeler -value peripheral -text peripheral\
                ]
                grid $button -row 1 -column 2

                grid columnconfigure $parentPath 3 -weight 1

                set message [configuration::createMessage $parentPath.help -text $helpText]
                grid $message -sticky nsew -row 2 -column 0 -columnspan 100
                grid rowconfigure $parentPath 2 -weight 1
            }

            proc check {} {
                return 1                                                                            ;# simple choice so always valid
            }

            proc apply {} {
                variable labeler

                if {![check]} return
                configuration::apply pieLabeler $labeler
            }

            proc help {} {
                generalHelpWindow #configuration.viewers.pies
            }

        }                                                                                                     ;# end of viewers pies

    }                                                                                                              ;# end of viewers

    namespace eval thresholds {

        proc initialize {} {}

        proc edit {parentPath} {
            set message [configuration::createMessage $parentPath.message -text {Thresholds configuration}]
            pack $message -fill both -expand 1
        }

        proc check {} {
            return 1                                                                                         ;# no data in this page
        }

        proc apply {} {}

        proc variables {} {return {}}

        proc help {} {
            generalHelpWindow #preferences.thresholds
        }

        namespace eval email {                                                                          ;# start of thresholds email

            variable helpText {}

            proc variables {} {
                return {fromAddress smtpServers}
            }

            proc initialize {} {
                variable from [configuration::initialize fromAddress]
                variable servers [configuration::initialize smtpServers]
            }

            proc edit {parentPath} {
                set row 0
                set message [configuration::createMessage $parentPath.message -text {Mail settings:}]
                grid $message -sticky nsew -row $row -column 0 -columnspan 2                                   ;# occupy whole width
                grid rowconfigure $parentPath $row -weight 1
                incr row
                grid [label $parentPath.from -text {From address:}] -row $row -column 0 -sticky w
                entry $parentPath.address -textvariable configuration::thresholds::email::from
                grid $parentPath.address -row $row -column 1 -sticky ew
                incr row
                grid [label $parentPath.out -text {Outgoing mail SMTP server:}] -row $row -column 0 -sticky w
                entry $parentPath.server -textvariable configuration::thresholds::email::servers
                grid $parentPath.server -row $row -column 1 -sticky ew
                incr row
                grid rowconfigure $parentPath $row -weight 1
            }

            proc check {} {
                return 1                                                                            ;# simple choice so always valid
            }

            proc apply {} {
                variable from
                variable servers

                configuration::apply fromAddress $from
                configuration::apply smtpServers $servers
            }

            proc help {} {
                generalHelpWindow #preferences.thresholds.email
            }

        }                                                                                                     ;# end of viewers pies
    }

    # contruct configuration variables list which can be used at any time (i.e. when saving configuration to file)
    variable variables
    set variables(0) {}                                                                                         ;# for configuration
    set variables(1) {}                                                                                           ;# for preferences
    foreach entry $hierarchy specific $configure {
        regsub -all {\.} $entry :: class
        if {$specific} {
            set variables(0) [concat $variables(0) [${class}::variables]]
        }
        set variables(1) [concat $variables(1) [${class}::variables]]
    }

}
