1# Class to display messages in an information line.
2
3import string
4import Tkinter
5import Pmw
6
7class MessageBar(Pmw.MegaWidget):
8    def __init__(self, parent = None, **kw):
9
10	# Define the megawidget options.
11	INITOPT = Pmw.INITOPT
12	defaultMessageTypes = {
13			   # (priority, showtime, bells, logmessage)
14	    'systemerror'  : (5, 10, 2, 1),
15	    'usererror'    : (4, 5, 1, 0),
16	    'busy'         : (3, 0, 0, 0),
17	    'systemevent'  : (2, 5, 0, 0),
18	    'userevent'    : (2, 5, 0, 0),
19	    'help'         : (1, 5, 0, 0),
20	    'state'        : (0, 0, 0, 0),
21	}
22	optiondefs = (
23	    ('labelmargin',    0,                     INITOPT),
24	    ('labelpos',       None,                  INITOPT),
25	    ('messagetypes',   defaultMessageTypes,   INITOPT),
26	    ('silent',         0,                     None),
27	    ('sticky',         'ew',                  INITOPT),
28	)
29	self.defineoptions(kw, optiondefs)
30
31	# Initialise the base class (after defining the options).
32	Pmw.MegaWidget.__init__(self, parent)
33
34	# Create the components.
35	interior = self.interior()
36	self._messageBarEntry = self.createcomponent('entry',
37		(), None,
38		Tkinter.Entry, (interior,))
39
40        # Can't always use 'disabled', since this greys out text in Tk 8.4.2
41        try:
42            self._messageBarEntry.configure(state = 'readonly')
43        except Tkinter.TclError:
44            self._messageBarEntry.configure(state = 'disabled')
45
46	self._messageBarEntry.grid(column=2, row=2, sticky=self['sticky'])
47	interior.grid_columnconfigure(2, weight=1)
48	interior.grid_rowconfigure(2, weight=1)
49
50	self.createlabel(interior)
51
52	# Initialise instance variables.
53	self._numPriorities = 0
54	for info in self['messagetypes'].values():
55	    if self._numPriorities < info[0]:
56		self._numPriorities = info[0]
57
58	self._numPriorities = self._numPriorities + 1
59	self._timer = [None] * self._numPriorities
60	self._messagetext = [''] * self._numPriorities
61	self._activemessage = [0] * self._numPriorities
62
63	# Check keywords and initialise options.
64	self.initialiseoptions()
65
66    def destroy(self):
67	for timerId in self._timer:
68	    if timerId is not None:
69		self.after_cancel(timerId)
70	self._timer = [None] * self._numPriorities
71	Pmw.MegaWidget.destroy(self)
72
73    def message(self, type, text):
74        # Display a message in the message bar.
75
76	(priority, showtime, bells, logmessage) = self['messagetypes'][type]
77
78	if not self['silent']:
79	    for i in range(bells):
80		if i != 0:
81		    self.after(100)
82		self.bell()
83
84	self._activemessage[priority] = 1
85	if text is None:
86	    text = ''
87	self._messagetext[priority] = string.replace(text, '\n', ' ')
88	self._redisplayInfoMessage()
89
90	if logmessage:
91	    # Should log this text to a text widget.
92	    pass
93
94	if showtime > 0:
95	    if self._timer[priority] is not None:
96		self.after_cancel(self._timer[priority])
97
98	    # Define a callback to clear this message after a time.
99	    def _clearmessage(self=self, priority=priority):
100		self._clearActivemessage(priority)
101
102	    mseconds = int(showtime * 1000)
103	    self._timer[priority] = self.after(mseconds, _clearmessage)
104
105    def helpmessage(self, text):
106        if text is None:
107            self.resetmessages('help')
108        else:
109            self.message('help', text)
110
111    def resetmessages(self, type):
112	priority = self['messagetypes'][type][0]
113	self._clearActivemessage(priority)
114	for messagetype, info in self['messagetypes'].items():
115	    thisPriority = info[0]
116	    showtime = info[1]
117	    if thisPriority < priority and showtime != 0:
118		self._clearActivemessage(thisPriority)
119
120    def _clearActivemessage(self, priority):
121	self._activemessage[priority] = 0
122	if self._timer[priority] is not None:
123	    self.after_cancel(self._timer[priority])
124	    self._timer[priority] = None
125	self._redisplayInfoMessage()
126
127    def _redisplayInfoMessage(self):
128	text = ''
129        for priority in range(self._numPriorities - 1, -1, -1):
130	    if self._activemessage[priority]:
131		text = self._messagetext[priority]
132	        break
133	self._messageBarEntry.configure(state = 'normal')
134	self._messageBarEntry.delete(0, 'end')
135	self._messageBarEntry.insert('end', text)
136
137        # Can't always use 'disabled', since this greys out text in Tk 8.4.2
138        try:
139            self._messageBarEntry.configure(state = 'readonly')
140        except Tkinter.TclError:
141            self._messageBarEntry.configure(state = 'disabled')
142
143Pmw.forwardmethods(MessageBar, Tkinter.Entry, '_messageBarEntry')
144