From: "David Herron" <david@twg.com>
Subject: Motif-like message/error/warning dialogs 
Sensitivity: Personal
Encoding:  32 TEXT , 293 TEXT , 4 TEXT 
Conversion: Prohibited
Organization: The Wollongong Group, Inc., Palo Alto, CA
Conversion-With-Loss: Prohibited
Date: Mon, 31 Aug 1992 20:50:29 GMT

Greetings!

I've written up some dialogs which do Motif-like simple message dialogs.
These are the kind to be used which

	notifying of error's, warning's, or general information

	asking questions

	doing a bit of long-term work

They include a little picture in the upper left corner to specify which
is which, a piece of text in the upper part, and 1-3 buttons in the
bottom (depending on what's needed).  It all works pretty well and has
a simple programming interface, but it isn't "right".

Current problems are:

- Modal only.
- Wrong sort of separation 'tween top & bottom.
- No keyboard driven focusing.
- The icons are probably 1/4 the size they should be.
- The `working' dialog is not useful since it doesn't return
  until a button's pressed.

But it serves my purposes (where I only need to put up notifications, and
ask questions).

BTW, there's a bunch of path names hard coded for bitmap's.  You'll
have to change these to reflect where the bitmaps are stored.

It's short enough to just attach here:


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	bitmap
#	msgdialog.tk
# This archive created: Mon Aug 31 13:42:28 1992
export PATH; PATH=/bin:$PATH
if test ! -d 'bitmap'
then
	echo shar: creating directory "'bitmap'"
	mkdir 'bitmap'
fi
echo shar: entering directory "'bitmap'"
cd 'bitmap'
echo shar: extracting "'error'" '(278 characters)'
if test -f 'error'
then
	echo shar: will not over-write existing file "'error'"
else
sed 's/^	X//' << \SHAR_EOF > 'error'
	X#define error_width 16
	X#define error_height 16
	Xstatic char error_bits[] = {
	X   0x00, 0x00, 0xe0, 0x01, 0xf8, 0x07, 0x3c, 0x0e, 0x3c, 0x0c, 0x7e, 0x18,
	X   0xe6, 0x18, 0xc6, 0x19, 0x86, 0x1f, 0x0c, 0x0f, 0x1c, 0x0f, 0xf8, 0x07,
	X   0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
SHAR_EOF
if test 278 -ne "`wc -c < 'error'`"
then
	echo shar: error transmitting "'error'" '(should have been 278 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'information'" '(296 characters)'
if test -f 'information'
then
	echo shar: will not over-write existing file "'information'"
else
sed 's/^	X//' << \SHAR_EOF > 'information'
	X#define information_width 16
	X#define information_height 16
	Xstatic char information_bits[] = {
	X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00,
	X   0xe0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
	X   0xe0, 0x01, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00};
SHAR_EOF
if test 296 -ne "`wc -c < 'information'`"
then
	echo shar: error transmitting "'information'" '(should have been 296 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'question'" '(287 characters)'
if test -f 'question'
then
	echo shar: will not over-write existing file "'question'"
else
sed 's/^	X//' << \SHAR_EOF > 'question'
	X#define question_width 16
	X#define question_height 16
	Xstatic char question_bits[] = {
	X   0xf8, 0x07, 0x54, 0x0d, 0xea, 0x1a, 0xf5, 0x35, 0xbb, 0x2b, 0x55, 0x37,
	X   0xab, 0x2b, 0xd5, 0x55, 0xeb, 0xea, 0xd5, 0x15, 0xea, 0x0a, 0xd4, 0x15,
	X   0xe8, 0x0a, 0x58, 0x01, 0xa8, 0x02, 0xfc, 0x07};
SHAR_EOF
if test 287 -ne "`wc -c < 'question'`"
then
	echo shar: error transmitting "'question'" '(should have been 287 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'warning'" '(284 characters)'
if test -f 'warning'
then
	echo shar: will not over-write existing file "'warning'"
else
sed 's/^	X//' << \SHAR_EOF > 'warning'
	X#define warning_width 16
	X#define warning_height 16
	Xstatic char warning_bits[] = {
	X   0x80, 0x03, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07,
	X   0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x01,
	X   0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x01};
SHAR_EOF
if test 284 -ne "`wc -c < 'warning'`"
then
	echo shar: error transmitting "'warning'" '(should have been 284 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'working'" '(284 characters)'
if test -f 'working'
then
	echo shar: will not over-write existing file "'working'"
else
sed 's/^	X//' << \SHAR_EOF > 'working'
	X#define working_width 16
	X#define working_height 16
	Xstatic char working_bits[] = {
	X   0xff, 0xff, 0x02, 0x40, 0xfa, 0x5f, 0x0a, 0x50, 0x92, 0x49, 0xe2, 0x47,
	X   0xc2, 0x43, 0x82, 0x41, 0x82, 0x41, 0xc2, 0x43, 0xa2, 0x45, 0xd2, 0x4b,
	X   0xea, 0x57, 0xfa, 0x5f, 0x02, 0x40, 0xff, 0xff};
SHAR_EOF
if test 284 -ne "`wc -c < 'working'`"
then
	echo shar: error transmitting "'working'" '(should have been 284 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'bitmap'"
cd ..
echo shar: extracting "'msgdialog.tk'" '(5739 characters)'
if test -f 'msgdialog.tk'
then
	echo shar: will not over-write existing file "'msgdialog.tk'"
else
sed 's/^	X//' << \SHAR_EOF > 'msgdialog.tk'
	X
	X# $Id: msgdialog.tk,v 1.4 1992/08/30 03:35:12 david Exp $
	X# msgdialog.tk - Tk procedures to do Motif-like implementations of
	X#	their dialogs derived from MessageBox.
	X#
	X# $Log: msgdialog.tk,v $
	X# Revision 1.4  1992/08/30  03:35:12  david
	X# Change aspect ratio so that it's wide enough to not wrap-around
	X# most things.
	X#
	X# Revision 1.3  1992/08/23  21:27:00  david
	X# Convert to style where the procedure waits for a button press.  We also
	X# issue a grab &c so that it's truly modal.
	X#
	X# Revision 1.2  1992/08/21  15:50:19  david
	X# Added concept of `parent' window in an attempt to locate the
	X# dialog in the center of its parent.
	X#
	X# Revision 1.1  1992/08/07  05:08:12  david
	X# Initial revision.
	X#
	X#
	X#
	X#
	X# USAGE:	DLG:<type> parent name message button_1 button_2 button_3
	X#
	X# parent	The name of the window to parent from
	X# name		The name to use for the toplevel of this dialog
	X# message	Message to print in the message area.
	X# button_{1,2,3} Text to put on each button.
	X#
	X#
	X#
	X# This starts a dialog of the type indicated in <type>.  It has [1..3]
	X# buttons, depending on how many (non-null) strings are passed.  It does
	X# a passive grab, to force the user to respond.  It waits until one of
	X# the buttons are pressed, then kills off the dialog and returns.  The
	X# return value is the number for the button which was pressed {1,2,3}.
	X#
	X# THIS FILE REQUIRES tk2.2 or greater.
	X
	Xproc DLG:information {parent w msg btn1 btn2 btn3} {
	X	return [DLG:build note "$parent" "$w" "$msg" "$btn1" "$btn2" "$btn3"]
	X}
	X
	Xproc DLG:warning {parent w msg btn1 btn2 btn3} {
	X	return [DLG:build warn "$parent" "$w" "$msg" "$btn1" "$btn2" "$btn3"]
	X}
	X
	Xproc DLG:error {parent w msg btn1 btn2 btn3} {
	X	return [DLG:build error "$parent" "$w" "$msg" "$btn1" "$btn2" "$btn3"]
	X}
	X
	Xproc DLG:question {parent w msg btn1 btn2 btn3} {
	X	return [DLG:build ask  "$parent" "$w" "$msg" "$btn1" "$btn2" "$btn3"]
	X}
	X
	Xproc DLG:working {parent w msg btn1 btn2 btn3} {
	X	return [DLG:build work "$parent" "$w" "$msg" "$btn1" "$btn2" "$btn3"]
	X}
	X
	Xproc DLG:build {type parent w msg btn1 btn2 btn3} {
	X	catch { destroy $w }
	X
	X	set done "DLG[set w]done"
	X	global $done
	X	set $done 0
	X
	X	set px [winfo x $parent]
	X	set py [winfo y $parent]
	X	set ph [winfo screenheight $parent]
	X	set pw [winfo screenwidth  $parent]
	X
	X	toplevel $w -class Dialog
	X	wm geometry $w +[expr $px+($pw/3)]+[expr $py+($ph/3)]
	X	wm minsize $w 1 1
	X
	X	# wm raise $parent	-- Motif does this but TK doesn't have the command.
	X
	X	frame $w.msg
	X	frame $w.cmds
	X	pack append $w \
	X		$w.msg  { top fill expand } \
	X		$w.cmds { top fill expand }
	X
	X	case $type {
	X	note	{ set iconfile @/home/david/tk-misc/bitmap/information }
	X	warn	{ set iconfile @/home/david/tk-misc/bitmap/warning     }
	X	error	{ set iconfile @/home/david/tk-misc/bitmap/error       }
	X	ask	{ set iconfile @/home/david/tk-misc/bitmap/question    }
	X	work	{ set iconfile @/home/david/tk-misc/bitmap/working     }
	X	}
	X
	X	label $w.msg.icon -bitmap $iconfile
	X	message $w.msg.msg  -text "$msg" -justify left -aspect 500
	X	pack append $w.msg \
	X		$w.msg.icon { left } \
	X		$w.msg.msg  { left fill expand }
	X
	X	# Do some cutesy stuff so the buttons are nicely framed.
	X	# We wouldn't have to use two frame's if one option on -relief
	X	# were "knurled" (or some such) to give a raised-edge feel.
	X
	X	frame $w.cmds.f -borderwidth 3 -relief raised
	X	pack append $w.cmds $w.cmds.f { fill expand }
	X	frame $w.cmds.f.f -borderwidth 3 -relief sunken
	X	pack append $w.cmds.f $w.cmds.f.f { fill expand }
	X
	X	# The extra frames below are to indicate current focus.  But we don't
	X	# have anything to handle keyboard focus.  Besides, the Motif
	X	# implementation uses a `knurled' look to the frame around buttons
	X	# in their standard dialogs and we must use two layers of frame to
	X	# implement that (see above).
	X	#
	X	# Also tried to set up stuff for keyboard focus, but it did a couple of
	X	# weird things and there isn't time to fix them now.  Keyboard focus
	X	# remained wherever the last `focus' command had gone, regardless of
	X	# where the pointer focus was.  This is a bug with the regular FOCUS
	X	# module as well.  The cure will be to watch Enter and Leave events
	X	# to know which window the pointer is in.  But this seems to be wrong
	X	# as well: What if the users configures their window manager for
	X	# a click-to-focus mode.  Won't we still get Enter&Leave events
	X	# regardless of where they've clicked-to-focus?
	X
	X	if {"$btn1" != ""} {
	X		frame $w.cmds.f.f.f1 -borderwidth 5 -relief flat
	X		button $w.cmds.f.f.f1.btn1 -text "[lindex $btn1 0]" \
	X				        -command "global $done; set $done 1"
	X		pack append $w.cmds.f.f    $w.cmds.f.f.f1      { left fillx expand }
	X		pack append $w.cmds.f.f.f1 $w.cmds.f.f.f1.btn1 { fill expand }
	X
	X		# DLG:keybindings $w.cmds.f.f.f1.btn1 "[lindex $btn1 1]"
	X	}
	X
	X	if {"$btn2" != ""} {
	X		frame $w.cmds.f.f.f2 -borderwidth 5 -relief flat
	X		button $w.cmds.f.f.f2.btn2 -text "[lindex $btn2 0]" \
	X					 -command "global $done; set $done 2"
	X		pack append $w.cmds.f.f    $w.cmds.f.f.f2      { left fillx expand }
	X		pack append $w.cmds.f.f.f2 $w.cmds.f.f.f2.btn2 { fill expand }
	X
	X		# DLG:keybindings $w.cmds.f.f.f2.btn2 "[lindex $btn2 1]"
	X	}
	X
	X	if {"$btn3" != ""} {
	X		frame $w.cmds.f.f.f3 -borderwidth 5 -relief flat
	X		button $w.cmds.f.f.f3.btn3 -text "[lindex $btn3 0]" \
	X				        -command "global $done; set $done 3"
	X		pack append $w.cmds.f.f    $w.cmds.f.f.f3      { left fillx expand }
	X		pack append $w.cmds.f.f.f3 $w.cmds.f.f.f3.btn3 { fill expand }
	X
	X		# DLG:keybindings $w.cmds.f.f.f3.btn3 "[lindex $btn3 1]"
	X	}
	X
	X	update
	X	grab $w
	X	tkwait variable $done
	X	grab
	X	destroy $w
	X
	X	return "[set $done]"
	X}
	X
	X# Future expansion: For when we are able to do keyboard focus and
	X# traversal in these things.
	X#proc DLG:keybindings { w cmd } {
	X#	bind $w <Key-space> "$cmd"
	X#	bind $w <Key-Return> "$cmd"
	X#}
	X
SHAR_EOF
if test 5739 -ne "`wc -c < 'msgdialog.tk'`"
then
	echo shar: error transmitting "'msgdialog.tk'" '(should have been 5739 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

<- David Herron <david@twg.com> (work) <david@davids.mmdf.com> (home)
<-
<- "ISO is really just another politically correct one-world fantasy
<-  of the U.N." -- Gordon McLachlan (LAN Computing, Aug 1992, p. 37)
Newsgroups: comp.lang.tcl