source: sasview/sansguiframe/src/sans/guiframe/gui_statusbar.py @ 986da97

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 986da97 was 986da97, checked in by Jae Cho <jhjcho@…>, 12 years ago

Popup dialog on status event with error

  • Property mode set to 100644
File size: 14.7 KB
Line 
1import wx
2import sys
3from wx import StatusBar as wxStatusB
4from wx.lib import newevent
5import wx.richtext
6import time
7from sans.guiframe.gui_style import GUIFRAME_ICON
8#numner of fields of the status bar
9NB_FIELDS = 4
10#position of the status bar's fields
11ICON_POSITION = 0
12MSG_POSITION  = 1
13GAUGE_POSITION  = 2
14CONSOLE_POSITION  = 3
15BUTTON_SIZE = 40
16
17CONSOLE_WIDTH = 500
18CONSOLE_HEIGHT = 300
19if sys.platform.count("win32") > 0:
20    FONT_VARIANT = 0
21else:
22    FONT_VARIANT = 1
23
24class ConsolePanel(wx.Panel):
25    """
26    """
27    def __init__(self, parent, *args, **kwargs):
28        """
29        """
30        wx.Panel.__init__(self, parent=parent, *args, **kwargs)
31        self.parent = parent
32        self.sizer = wx.BoxSizer(wx.VERTICAL)
33       
34        self.msg_txt = wx.richtext.RichTextCtrl(self, size=(CONSOLE_WIDTH-40,
35                                                CONSOLE_HEIGHT-60),
36                                   style=wx.VSCROLL|wx.HSCROLL|wx.NO_BORDER)
37       
38        self.msg_txt.SetEditable(False)
39        self.msg_txt.SetValue('No message available')
40        self.sizer.Add(self.msg_txt, 1, wx.EXPAND|wx.ALL, 10)
41        self.SetSizer(self.sizer)
42       
43    def set_message(self, status="", event=None):
44        """
45        """
46        status = str(status)
47        if status.strip() == "":
48            return
49        color = (0, 0, 0) #black
50        icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
51                                                 wx.ART_TOOLBAR)
52        if hasattr(event, "info"):
53            icon_type = event.info.lower()
54            if icon_type == "warning":
55                color = (0, 0, 255) # blue
56                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING,
57                                                      wx.ART_TOOLBAR)
58            if icon_type == "error":
59                color = (255, 0, 0) # red
60                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, 
61                                                     wx.ART_TOOLBAR)
62            if icon_type == "info":
63                icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
64                                                     wx.ART_TOOLBAR)
65        self.msg_txt.Newline()
66        self.msg_txt.WriteBitmap(icon_bmp)
67        self.msg_txt.BeginTextColour(color)
68        self.msg_txt.WriteText("\t")
69        self.msg_txt.AppendText(status)
70        self.msg_txt.EndTextColour()
71       
72           
73       
74class Console(wx.Frame):
75    """
76    """
77    def __init__(self, parent=None, status="", *args, **kwds):
78        kwds["size"] = (CONSOLE_WIDTH, CONSOLE_HEIGHT)
79        kwds["title"] = "Console"
80        wx.Frame.__init__(self, parent=parent, *args, **kwds)
81        self.SetWindowVariant(FONT_VARIANT)
82        self.panel = ConsolePanel(self)
83        self.panel.set_message(status=status)
84        wx.EVT_CLOSE(self, self.Close)
85       
86       
87    def set_multiple_messages(self, messages=[]):
88        """
89        """
90        if messages:
91            for status in messages:
92                self.panel.set_message(status=status)
93               
94    def set_message(self, status, event=None):
95        """
96        """
97        self.panel.set_message(status=str(status), event=event)
98       
99    def Close(self, event):
100        """
101        """
102        self.Hide()
103       
104class StatusBar(wxStatusB):
105    """
106        Application status bar
107    """
108    def __init__(self, parent, id):
109        wxStatusB.__init__(self, parent, id)
110        self.parent = parent
111        self.parent.SetStatusBarPane(MSG_POSITION)
112
113        #Layout of status bar
114        width, height = wx.ArtProvider.GetSizeHint(wx.ART_TOOLBAR)       
115        self.SetFieldsCount(NB_FIELDS) 
116        # Leave some space for the resize handle in the last field
117        self.SetStatusWidths([width+4, -2, -1, width+15])
118        self.SetMinHeight(height)
119       
120        rect = self.GetFieldRect(ICON_POSITION)
121        if rect.height > height:
122            height = rect.GetHeight() 
123            width = rect.GetWidth()
124       
125        #display default message
126        self.msg_position = MSG_POSITION
127       
128        # Create progress bar
129        gauge_width = 5 * width
130        self.gauge = wx.Gauge(self, size=(gauge_width, height),
131                               style=wx.GA_HORIZONTAL)
132        self.gauge.Hide()
133       
134        # Create status bar icon reflecting the type of status
135        # for the last message
136        self.bitmap_bt_warning = \
137            wx.BitmapButton(self, -1,
138                            size=(width, height),
139                            style=wx.NO_BORDER)
140               
141        # Create the button used to show the console dialog
142        console_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, 
143                                               wx.ART_TOOLBAR,
144                                               size = (width, height))
145        self.bitmap_bt_console = wx.BitmapButton(self, -1, 
146                                 size=(width, height),
147                                 style=wx.NO_BORDER)
148        self.bitmap_bt_console.SetBitmapLabel(console_bmp)
149        console_hint = "History of status bar messages"
150        self.bitmap_bt_console.SetToolTipString(console_hint)
151        self.bitmap_bt_console.Bind(wx.EVT_BUTTON, self._onMonitor,
152                                            id=self.bitmap_bt_console.GetId())
153       
154        self.reposition()
155        ## Current progress value of the bar
156        self.nb_start = 0
157        self.nb_progress = 0
158        self.nb_stop = 0
159        self.frame = None
160        self.list_msg = []
161        self.frame = Console(parent=self)
162        if hasattr(self.frame, "IsIconized"):
163            if not self.frame.IsIconized():
164                try:
165                    icon = self.parent.GetIcon()
166                    self.frame.SetIcon(icon)
167                except:
168                    try:
169                        FRAME_ICON = wx.Icon(GUIFRAME_ICON.FRAME_ICON_PATH,
170                                              wx.BITMAP_TYPE_ICON)
171                        self.frame.SetIcon(FRAME_ICON)
172                    except:
173                        pass
174        self.frame.set_multiple_messages(self.list_msg)
175        self.frame.Hide()
176        self.progress = 0     
177        self.timer = wx.Timer(self, -1) 
178        self.timer_stop = wx.Timer(self, -1) 
179        self.thread = None
180        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
181        self.Bind(wx.EVT_TIMER, self._on_time_stop, self.timer_stop) 
182        self.Bind(wx.EVT_SIZE, self.OnSize)
183        self.Bind(wx.EVT_IDLE, self.OnIdle)
184       
185    def reposition(self):
186        """
187            Place the various fields in their proper position
188        """
189        rect = self.GetFieldRect(GAUGE_POSITION)
190        self.gauge.SetPosition((rect.x, rect.y))
191        rect = self.GetFieldRect(ICON_POSITION)
192        self.bitmap_bt_warning.SetPosition((rect.x, rect.y))
193        rect = self.GetFieldRect(CONSOLE_POSITION)
194        self.bitmap_bt_console.SetPosition((rect.x, rect.y))
195        self.sizeChanged = False
196       
197    def OnIdle(self, event):
198        """
199        """
200        if self.sizeChanged:
201            self.reposition()
202           
203    def OnSize(self, evt):
204        """
205        """
206        self.reposition() 
207        self.sizeChanged = True
208       
209    def get_msg_position(self):
210        """
211        """
212        return self.msg_position
213   
214    def SetStatusText(self, text="", number=MSG_POSITION, event=None):
215        """
216        """
217        wxStatusB.SetStatusText(self, text, number)
218        self.list_msg.append(text)
219        icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)
220        self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
221     
222        if self.frame is not None :
223            self.frame.set_message(status=text, event=event)
224       
225    def PopStatusText(self, *args, **kwds):
226        """
227        Override status bar
228        """
229        wxStatusB.PopStatusText(self, field=MSG_POSITION)
230       
231    def PushStatusText(self, *args, **kwds):
232        """
233        PushStatusText
234        """
235        text = "PushStatusText: What is this string?"
236        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=text)
237       
238    def enable_clear_gauge(self):
239        """
240        clear the progress bar
241        """
242        flag = True
243        # Why we do this?
244        #if (self.nb_start <= self.nb_stop) or \
245        #    (self.nb_progress <= self.nb_stop):
246        #    flag = True
247        return flag
248   
249    def _on_time_stop(self, evt): 
250        """
251        Clear the progress bar
252       
253        :param evt: wx.EVT_TIMER
254 
255        """ 
256        count = 0
257        while(count <= 100):
258            count += 1
259        self.timer_stop.Stop() 
260        self.clear_gauge(msg="")
261        self.nb_progress = 0 
262        self.nb_start = 0 
263        self.nb_stop = 0
264       
265    def _on_time(self, evt): 
266        """
267        Update the progress bar while the timer is running
268       
269        :param evt: wx.EVT_TIMER
270 
271        """ 
272        # Check stop flag that can be set from non main thread
273        if self.timer.IsRunning(): 
274            self.gauge.Pulse()
275   
276    def clear_gauge(self, msg=""):
277        """
278        Hide the gauge
279        """
280        self.progress = 0
281        self.gauge.SetValue(0)
282        self.gauge.Hide() 
283         
284    def set_icon(self, event):
285        """
286        Display icons related to the type of message sent to the statusbar
287        when available. No icon is displayed if the message is empty
288        """
289        if hasattr(event, "status"):
290            status = str(event.status)
291            if status.strip() == "":
292                return
293        else:
294            return
295        if not hasattr(event, "info"):
296            return 
297       
298        # Get the size of the button images
299        width, height = wx.ArtProvider.GetSizeHint(wx.ART_TOOLBAR)       
300
301        # Get the size of the field and choose the size of the
302        # image accordingly
303        rect = self.GetFieldRect(ICON_POSITION)
304        if rect.height > height:
305            height = rect.GetHeight()
306            width = rect.GetWidth()
307       
308        msg = event.info.lower()
309        if msg == "warning":
310            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR,
311                                                 size = (height,height))
312            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
313        elif msg == "error":
314            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR,
315                                                 size = (height,height))
316            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
317            e_msg = "Error(s) Occurred:\n"
318            e_msg += event.status
319            wx.MessageBox(e_msg, style=wx.ICON_ERROR)
320        else:
321            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
322                                                 wx.ART_TOOLBAR,
323                                                 size = (height,height))
324            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
325   
326    def set_message(self, event):
327        """
328        display received message on the statusbar
329        """
330        if hasattr(event, "status"):
331            self.SetStatusText(text=str(event.status), event=event)
332       
333 
334    def set_gauge(self, event):
335        """
336        change the state of the gauge according the state of the current job
337        """
338        if not hasattr(event, "type"):
339            return
340        type = event.type
341        self.gauge.Show(True)
342        if type.lower() == "start":
343            self.nb_start += 1
344            #self.timer.Stop()
345            self.progress += 5
346            self.gauge.SetValue(int(self.progress)) 
347            self.progress += 5
348            if self.progress < self.gauge.GetRange() - 20:
349                self.gauge.SetValue(int(self.progress)) 
350        if type.lower() == "progress":
351            self.nb_progress += 1
352            self.timer.Start(1)
353            self.gauge.Pulse()
354        if type.lower() == "update":
355            self.progress += 5
356            if self.progress < self.gauge.GetRange()- 20:
357                self.gauge.SetValue(int(self.progress))   
358        if type.lower() == "stop":
359            self.nb_stop += 1
360            self.gauge.Show(True)
361            if self.enable_clear_gauge():
362                self.timer.Stop()
363                self.progress = 0
364                self.gauge.SetValue(100) 
365                self.timer_stop.Start(5) 
366                   
367    def set_status(self, event):
368        """
369        Update the status bar .
370       
371        :param type: type of message send.
372            type  must be in ["start","progress","update","stop"]
373        :param msg: the message itself  as string
374        :param thread: if updatting using a thread status
375       
376        """
377        self.set_message(event=event)
378        self.set_icon(event=event)
379        self.set_gauge(event=event)
380   
381    def _onMonitor(self, event):
382        """
383        Pop up a frame with messages sent to the status bar
384        """
385        self.frame.Show(False)
386        self.frame.Show(True)
387       
388       
389class SPageStatusbar(wxStatusB):
390    def __init__(self, parent, timeout=None, *args, **kwds):
391        wxStatusB.__init__(self, parent, *args, **kwds)
392        self.SetFieldsCount(1) 
393        self.timeout = timeout
394        width, height = parent.GetSizeTuple()
395        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
396                              size=(width, height/10))
397        rect = self.GetFieldRect(0)
398        self.gauge.SetPosition((rect.x , rect.y ))
399        if self.timeout is not None:
400            self.gauge.SetRange(int(self.timeout))
401        self.timer = wx.Timer(self, -1) 
402        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
403        self.timer.Start(1)
404        self.pos = 0
405       
406    def _on_time(self, evt): 
407        """
408        Update the progress bar while the timer is running
409       
410        :param evt: wx.EVT_TIMER
411 
412        """ 
413        # Check stop flag that can be set from non main thread
414        if self.timeout is None and self.timer.IsRunning(): 
415            self.gauge.Pulse()
416           
417       
418if __name__ == "__main__":
419    app = wx.PySimpleApp()
420    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
421    #statusBar = StatusBar(frame, wx.ID_ANY)
422    statusBar = SPageStatusbar(frame)
423    frame.SetStatusBar(statusBar)
424    frame.Show(True)
425    #event = MessageEvent()
426    #event.type = "progress"
427    #event.status  = "statusbar...."
428    #event.info = "error"
429    #statusBar.set_status(event=event)
430    app.MainLoop()
431
Note: See TracBrowser for help on using the repository browser.