Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | # Class to display messages in an information line. |
2 | ||
3 | import string | |
4 | import Tkinter | |
5 | import Pmw | |
6 | ||
7 | class 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 | ||
143 | Pmw.forwardmethods(MessageBar, Tkinter.Entry, '_messageBarEntry') |