summaryrefslogtreecommitdiff
path: root/itcl/iwidgets/generic/timeentry.itk
diff options
context:
space:
mode:
Diffstat (limited to 'itcl/iwidgets/generic/timeentry.itk')
-rw-r--r--itcl/iwidgets/generic/timeentry.itk398
1 files changed, 398 insertions, 0 deletions
diff --git a/itcl/iwidgets/generic/timeentry.itk b/itcl/iwidgets/generic/timeentry.itk
new file mode 100644
index 00000000000..58a19ae090a
--- /dev/null
+++ b/itcl/iwidgets/generic/timeentry.itk
@@ -0,0 +1,398 @@
+#
+# Timeentry
+# ----------------------------------------------------------------------
+# Implements a quicken style time entry field with a popup clock
+# by combining the timefield and watch widgets together. This
+# allows a user to enter the time via the keyboard or by using the
+# mouse by selecting the watch icon which brings up a popup clock.
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 DSC Technologies Corporation
+# ======================================================================
+# Permission to use, copy, modify, distribute and license this software
+# and its documentation for any purpose, and without fee or written
+# agreement with DSC, is hereby granted, provided that the above copyright
+# notice appears in all copies and that both the copyright notice and
+# warranty disclaimer below appear in supporting documentation, and that
+# the names of DSC Technologies Corporation or DSC Communications
+# Corporation not be used in advertising or publicity pertaining to the
+# software without specific, written prior permission.
+#
+# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
+# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
+# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+# SUPPORT, UPTIMES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
+# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+# ======================================================================
+
+#
+# Usual options.
+#
+itk::usual Timeentry {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# TIMEENTRY
+# ------------------------------------------------------------------
+itcl::class iwidgets::Timeentry {
+ inherit iwidgets::Timefield
+
+ constructor {args} {}
+
+ itk_option define -grab grab Grab "global"
+ itk_option define -icon icon Icon {}
+ itk_option define -state state State normal
+ itk_option define -closetext closeText Text Close
+
+ #
+ # The watch widget isn't created until needed, yet we need
+ # its options to be available upon creation of a timeentry widget.
+ # So, we'll define them in these class now so they can just be
+ # propagated onto the watch later.
+ #
+ itk_option define -hourradius hourRadius Radius .50
+ itk_option define -hourcolor hourColor Color red
+
+ itk_option define -minuteradius minuteRadius Radius .80
+ itk_option define -minutecolor minuteColor Color yellow
+
+ itk_option define -pivotradius pivotRadius Radius .10
+ itk_option define -pivotcolor pivotColor Color white
+
+ itk_option define -secondradius secondRadius Radius .90
+ itk_option define -secondcolor secondColor Color black
+
+ itk_option define -clockcolor clockColor Color white
+ itk_option define -clockstipple clockStipple ClockStipple {}
+
+ itk_option define -tickcolor tickColor Color black
+
+ itk_option define -watchheight watchHeight Height 175
+ itk_option define -watchwidth watchWidth Width 155
+
+ protected {
+ method _getPopupTime {}
+ method _releaseGrab {}
+ method _popup {}
+ method _getDefaultIcon {}
+
+ common _defaultIcon ""
+ }
+}
+
+#
+# Provide a lowercased access method for the timeentry class.
+#
+proc ::iwidgets::timeentry {pathName args} {
+ uplevel ::iwidgets::Timeentry $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Timeentry.watchWidth 155 widgetDefault
+option add *Timeentry.watchHeight 175 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::constructor {args} {
+ #
+ # Create an icon label to act as a button to bring up the
+ # watch popup.
+ #
+ itk_component add iconbutton {
+ label $itk_interior.iconbutton -relief raised
+ } {
+ keep -borderwidth -cursor -foreground
+ }
+ grid $itk_component(iconbutton) -row 0 -column 0 -sticky ns
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -icon
+#
+# Specifies the clock icon image to be used in the time entry.
+# Should one not be provided, then a default pixmap will be used
+# if possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::icon {
+ if {$itk_option(-icon) == {}} {
+ $itk_component(iconbutton) configure -image [_getDefaultIcon]
+ } else {
+ if {[lsearch [image names] $itk_option(-icon)] == -1} {
+ error "bad icon option \"$itk_option(-icon)\":\
+ should be an existing image"
+ } else {
+ $itk_component(iconbutton) configure -image $itk_option(-icon)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -grab
+#
+# Specifies the grab level, local or global, to be obtained when
+# bringing up the popup watch. The default is global.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::grab {
+ switch -- $itk_option(-grab) {
+ "local" - "global" {}
+ default {
+ error "bad grab option \"$itk_option(-grab)\":\
+ should be local or global"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Specifies the state of the widget which may be disabled or
+# normal. A disabled state prevents selection of the time field
+# or time icon button.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::state {
+ switch -- $itk_option(-state) {
+ normal {
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+ }
+ disabled {
+ bind $itk_component(iconbutton) <Button-1> {}
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _getDefaultIcon
+#
+# This method is invoked uto retrieve the name of the default icon
+# image displayed in the icon button.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_getDefaultIcon {} {
+
+ if {[lsearch [image types] pixmap] != -1} {
+ set _defaultIcon [image create pixmap -data {
+ /* XPM */
+ static char *watch1a[] = {
+ /* width height num_colors chars_per_pixel */
+ " 20 20 8 1",
+ /* colors */
+ ". c #000000",
+ "# c #000099",
+ "a c #009999",
+ "b c #999999",
+ "c c #cccccc",
+ "d c #ffff00",
+ "e c #d9d9d9",
+ "f c #ffffff",
+ /* pixels */
+ "eeeeebbbcccccbbbeeee",
+ "eeeee...#####..beeee",
+ "eeeee#aacccccaabeeee",
+ "eeee#accccccccc##eee",
+ "eee#ccc#cc#ccdcff#ee",
+ "ee#accccccccccfcca#e",
+ "eeaccccccc.cccfcccae",
+ "eeac#cccfc.cccc##cae",
+ "e#cccccffc.cccccccc#",
+ "e#ccccfffc.cccccccc#",
+ "e#cc#ffcc......c#cc#",
+ "e#ccfffccc.cccccccc#",
+ "e#cffccfcc.cccccccc#",
+ "eeafdccfcccccccd#cae",
+ "eeafcffcccccccccccae",
+ "eee#fcc#cccccdccc#ee",
+ "eee#fcc#cc#cc#ccc#ee",
+ "eeee#accccccccc##eee",
+ "eeeee#aacccccaabeeee",
+ "eeeee...#####..beeee"
+ };
+ }]
+ } else {
+ set _defaultIcon [image create bitmap -data {
+ #define watch1a_width 20
+ #define watch1a_height 20
+ static char watch1a_bits[] = {
+ 0x40,0x40,0xf0,0xe0,0x7f,0xf0,0xe0,0xe0,0xf0,0x30,
+ 0x80,0xf1,0x88,0x04,0xf2,0x0c,0x00,0xf6,0x04,0x04,
+ 0xf4,0x94,0x84,0xf5,0x02,0x06,0xf8,0x02,0x0c,0xf8,
+ 0x12,0x7e,0xf9,0x02,0x04,0xf8,0x02,0x24,0xf8,0x04,
+ 0x00,0xf5,0x04,0x00,0xf4,0x88,0x02,0xf2,0x88,0x64,
+ 0xf2,0x30,0x80,0xf1,0xe0,0x60,0xf0,0xe0,0xff,0xf0};
+ }]
+ }
+
+ #
+ # Since this image will only need to be created once, we redefine
+ # this method to just return the image name for subsequent calls.
+ #
+ itcl::body ::iwidgets::Timeentry::_getDefaultIcon {} {
+ return $_defaultIcon
+ }
+
+ return $_defaultIcon
+}
+
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popup
+#
+# This method is invoked upon selection of the icon button. It
+# creates a watch widget within a toplevel popup, calculates
+# the position at which to display the watch, performs a grab
+# and displays the watch.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_popup {} {
+ #
+ # First, let's nullify the icon binding so that any another
+ # selections are ignored until were done with this one. Next,
+ # change the relief of the icon.
+ #
+ bind $itk_component(iconbutton) <Button-1> {}
+ $itk_component(iconbutton) configure -relief sunken
+
+ #
+ # Create a withdrawn toplevel widget and remove the window
+ # decoration via override redirect.
+ #
+ itk_component add -private popup {
+ toplevel $itk_interior.popup
+ }
+ $itk_component(popup) configure -borderwidth 2 -background black
+ wm withdraw $itk_component(popup)
+ wm overrideredirect $itk_component(popup) 1
+
+ #
+ # Add a binding to for Escape to always release the grab.
+ #
+ bind $itk_component(popup) <KeyPress-Escape> [itcl::code $this _releaseGrab]
+
+ #
+ # Create the watch widget.
+ #
+ itk_component add watch {
+ iwidgets::Watch $itk_component(popup).watch
+ } {
+ usual
+
+ rename -width -watchwidth watchWidth Width
+ rename -height -watchheight watchHeight Height
+
+ keep -hourradius -minuteradius -minutecolor -pivotradius -pivotcolor \
+ -secondradius -secondcolor -clockcolor -clockstipple -tickcolor
+ }
+ grid $itk_component(watch) -row 0 -column 0
+ $itk_component(watch) configure -cursor top_left_arrow
+
+ #
+ # Create a button widget so the user can say they are done.
+ #
+ itk_component add close {
+ button $itk_component(popup).close -command [itcl::code $this _getPopupTime]
+ } {
+ usual
+ rename -text -closetext closeText Text
+ }
+ grid $itk_component(close) -row 1 -column 0 -sticky ew
+ $itk_component(close) configure -cursor top_left_arrow
+
+ #
+ # The icon button will be used as the basis for the position of the
+ # popup on the screen. We'll always attempt to locate the popup
+ # off the lower right corner of the button. If that would put
+ # the popup off the screen, then we'll put above the upper left.
+ #
+ set rootx [winfo rootx $itk_component(iconbutton)]
+ set rooty [winfo rooty $itk_component(iconbutton)]
+ set popupwidth [cget -watchwidth]
+ set popupheight [expr {[cget -watchheight] + \
+ [winfo reqheight $itk_component(close)]}]
+
+ set popupx [expr {$rootx + 3 + \
+ [winfo width $itk_component(iconbutton)]}]
+ set popupy [expr {$rooty + 3 + \
+ [winfo height $itk_component(iconbutton)]}]
+
+ if {(($popupx + $popupwidth) > [winfo screenwidth .]) || \
+ (($popupy + $popupheight) > [winfo screenheight .])} {
+ set popupx [expr {$rootx - 3 - $popupwidth}]
+ set popupy [expr {$rooty - 3 - $popupheight}]
+ }
+
+ #
+ # Get the current time from the timefield widget and both
+ # show and select it on the watch.
+ #
+ $itk_component(watch) show [get]
+
+ #
+ # Display the popup at the calculated position.
+ #
+ wm geometry $itk_component(popup) +$popupx+$popupy
+ wm deiconify $itk_component(popup)
+ tkwait visibility $itk_component(popup)
+
+ #
+ # Perform either a local or global grab based on the -grab option.
+ #
+ if {$itk_option(-grab) == "local"} {
+ grab $itk_component(popup)
+ } else {
+ grab -global $itk_component(popup)
+ }
+
+ #
+ # Make sure the widget is above all others and give it focus.
+ #
+ raise $itk_component(popup)
+ focus $itk_component(watch)
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popupGetTime
+#
+# This method is the callback for selection of a time on the
+# watch. It releases the grab and sets the time in the
+# timefield widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_getPopupTime {} {
+ show [$itk_component(watch) get -clicks]
+ _releaseGrab
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _releaseGrab
+#
+# This method releases the grab, destroys the popup, changes the
+# relief of the button back to raised and reapplies the binding
+# to the icon button that engages the popup action.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_releaseGrab {} {
+ grab release $itk_component(popup)
+ $itk_component(iconbutton) configure -relief raised
+ destroy $itk_component(popup)
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+}