# copyright (C) 1997-2006 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

# $Id: predtime.tcl,v 1.4 2006/01/28 19:16:59 jfontain Exp $


class predictor {

    class durationInput {

        proc durationInput {this parentPath args} composite {[new frame $parentPath] $args} {
            ::set path $widget::($this,path)
            composite::manage $this\
                [new spinbox $path\
                    -font $font::(mediumBold) -repeatinterval $global::spinBoxRepeatMilliseconds -width 4 -from 0 -to 9999\
                    -increment 1 -justify right -validate all -validatecommand {predictor::durationInput::validate 4 0 9999 %P}\
                ] days\
                [new spinbox $path\
                    -font $font::(mediumBold) -repeatinterval $global::spinBoxRepeatMilliseconds -width 2 -from 0 -to 23\
                    -increment 1 -justify right -validate all -validatecommand {predictor::durationInput::validate 2 0 23 %P}\
                ] hours\
                [new spinbox $path\
                    -font $font::(mediumBold) -repeatinterval $global::spinBoxRepeatMilliseconds -width 2 -from 0 -to 59\
                    -increment 1 -justify right -validate all -validatecommand {predictor::durationInput::validate 2 0 59 %P}\
                ] minutes\
                [new spinbox $path\
                    -font $font::(mediumBold) -repeatinterval $global::spinBoxRepeatMilliseconds -width 2 -from 0 -to 59\
                    -increment 1 -justify right -validate all -validatecommand {predictor::durationInput::validate 2 0 59 %P}\
                ] seconds
            pack\
                $composite::($this,days,path) [label $path.days -font $font::(mediumNormal) -text [mc days]]\
                $composite::($this,hours,path) [label $path.hours -font $font::(mediumNormal) -text [mc hours]]\
                $composite::($this,minutes,path) [label $path.minutes -font $font::(mediumNormal) -text [mc minutes]]\
                $composite::($this,seconds,path) [label $path.seconds -font $font::(mediumNormal) -text [mc seconds]]\
                -side left -fill x -expand 1
            composite::complete $this
        }

        proc ~durationInput {this} {}

        proc options {this} {
            return [list [list -state normal normal]]
        }

        proc set-state {this value} {
            switch $value {
                disabled - normal {}
                default {error "invalid state: $value"}
            }
            foreach unit {days hours minutes seconds} {
                $composite::($this,$unit,path) configure -state $value
            }
        }

        proc validate {width minimum maximum value {allowEmpty 1}} {
            # note: empty string must be allowed to allow keyboard deletion, replacement, ...
            ::set valid [expr {\
                ($allowEmpty && ($value eq "")) || (\
                    ([string length $value] <= $width) && [check31BitUnsignedInteger $value] &&\
                    ($value >= $minimum) && ($value <= $maximum)\
                )\
            }]
            if {!$valid} bell
            return $valid
        }

        proc valid {this} {
            foreach unit {days hours minutes seconds} {
                if {![check31BitUnsignedInteger [$composite::($this,$unit,path) get] 1]} {
                    focus $composite::($this,$unit,path)                                      ;# so that user can correct right away
                    return 0
                }
            }
            return 1
        }

        proc set {this seconds} {
            if {($seconds < 0) || ![string is integer $seconds]} {error "invalid duration in seconds: $seconds"}
            ::set value [expr {$seconds / 86400}]; ::set seconds [expr {$seconds % 86400}]
            $composite::($this,days,path) set $value
            ::set value [expr {$seconds / 3600}]; ::set seconds [expr {$seconds % 3600}]
            $composite::($this,hours,path) set $value
            ::set value [expr {$seconds / 60}]; ::set seconds [expr {$seconds % 60}]
            $composite::($this,minutes,path) set $value
            $composite::($this,seconds,path) set $seconds
            
        }

        proc get {this} {
            return [expr {
                ([$composite::($this,days,path) get] * 86400) + ([$composite::($this,hours,path) get] * 3600) +
                ([$composite::($this,minutes,path) get] * 60) + [$composite::($this,seconds,path) get]
            }]
        }

    }

}
