source: sasview/sansguiframe/src/sans/guiframe/gui_statusbar.py @ 0ea247e

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 0ea247e was a781312, checked in by Mathieu Doucet <doucetm@…>, 12 years ago

trying to improve the status bar

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