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

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 9130227 was b716dd8, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

trying to improve the status bar

  • Property mode set to 100644
File size: 14.3 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        width, height = 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([width+4, -2, -1, width+15])
112        self.SetMinHeight(height)
113       
114        rect = self.GetFieldRect(ICON_POSITION)
115        if rect.height > height:
116            height = rect.GetHeight() 
117            width = rect.GetWidth()
118       
119        #display default message
120        self.msg_position = MSG_POSITION
121       
122        # Create progress bar
123        self.gauge = wx.Gauge(self, size=(width, height),
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=(width, height),
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 = (width, height))
138        self.bitmap_bt_console = wx.BitmapButton(self, -1, 
139                                 size=(width, height),
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            Place the various fields in their proper position
181        """
182        rect = self.GetFieldRect(GAUGE_POSITION)
183        self.gauge.SetPosition((rect.x, rect.y))
184        rect = self.GetFieldRect(ICON_POSITION)
185        self.bitmap_bt_warning.SetPosition((rect.x, rect.y))
186        rect = self.GetFieldRect(CONSOLE_POSITION)
187        self.bitmap_bt_console.SetPosition((rect.x, rect.y))
188        self.sizeChanged = False
189       
190    def OnIdle(self, event):
191        """
192        """
193        if self.sizeChanged:
194            self.reposition()
195           
196    def OnSize(self, evt):
197        """
198        """
199        self.reposition() 
200        self.sizeChanged = True
201       
202    def get_msg_position(self):
203        """
204        """
205        return self.msg_position
206   
207    def SetStatusText(self, text="", number=MSG_POSITION, event=None):
208        """
209        """
210        wxStatusB.SetStatusText(self, text, number)
211        self.list_msg.append(text)
212        icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)
213        self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
214     
215        if self.frame is not None :
216            self.frame.set_message(status=text, event=event)
217       
218    def PopStatusText(self, *args, **kwds):
219        """
220        Override status bar
221        """
222        wxStatusB.PopStatusText(self, field=MSG_POSITION)
223     
224    def PushStatusText(self, *args, **kwds):
225        """
226        """
227        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=string)
228       
229    def enable_clear_gauge(self):
230        """
231        clear the progress bar
232        """
233        flag = False
234        if (self.nb_start <= self.nb_stop) or \
235            (self.nb_progress <= self.nb_stop):
236            flag = True
237        return flag
238   
239    def _on_time_stop(self, evt): 
240        """
241        Clear the progress bar
242       
243        :param evt: wx.EVT_TIMER
244 
245        """ 
246        count = 0
247        while(count <= 100):
248            count += 1
249        self.timer_stop.Stop() 
250        self.clear_gauge(msg="")
251        self.nb_progress = 0 
252        self.nb_start = 0 
253        self.nb_stop = 0
254       
255    def _on_time(self, evt): 
256        """
257        Update the progress bar while the timer is running
258       
259        :param evt: wx.EVT_TIMER
260 
261        """ 
262        # Check stop flag that can be set from non main thread
263        if self.timer.IsRunning(): 
264            self.gauge.Pulse()
265   
266    def clear_gauge(self, msg=""):
267        """
268        Hide the gauge
269        """
270        self.progress = 0
271        self.gauge.SetValue(0)
272        self.gauge.Hide() 
273         
274    def set_icon(self, event):
275        """
276        Display icons related to the type of message sent to the statusbar
277        when available. No icon is displayed if the message is empty
278        """
279        if hasattr(event, "status"):
280            status = str(event.status)
281            if status.strip() == "":
282                return
283        else:
284            return
285        if not hasattr(event, "info"):
286            return 
287       
288        # Get the size of the button images
289        width, height = wx.ArtProvider.GetSizeHint(wx.ART_TOOLBAR)       
290
291        # Get the size of the field and choose the size of the
292        # image accordingly
293        rect = self.GetFieldRect(ICON_POSITION)
294        if rect.height > height:
295            height = rect.GetHeight()
296            width = rect.GetWidth()
297       
298        msg = event.info.lower()
299        if msg == "warning":
300            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR,
301                                                 size = (height,height))
302            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
303        elif msg == "error":
304            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR,
305                                                 size = (height,height))
306            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
307        else:
308            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
309                                                 wx.ART_TOOLBAR,
310                                                 size = (height,height))
311            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
312   
313    def set_message(self, event):
314        """
315        display received message on the statusbar
316        """
317        if hasattr(event, "status"):
318            self.SetStatusText(text=str(event.status), event=event)
319       
320 
321    def set_gauge(self, event):
322        """
323        change the state of the gauge according the state of the current job
324        """
325        if not hasattr(event, "type"):
326            return
327        type = event.type
328        self.gauge.Show(True)
329        if type.lower() == "start":
330            self.nb_start += 1
331            #self.timer.Stop()
332            self.progress += 10
333            self.gauge.SetValue(int(self.progress)) 
334            self.progress += 10
335            if self.progress < self.gauge.GetRange() - 20:
336                self.gauge.SetValue(int(self.progress)) 
337        if type.lower() == "progress":
338            self.nb_progress += 1
339            self.timer.Start(1)
340            self.gauge.Pulse()
341        if type.lower() == "update":
342            self.progress += 10
343            if self.progress < self.gauge.GetRange()- 20:
344                self.gauge.SetValue(int(self.progress))   
345        if type.lower() == "stop":
346            self.nb_stop += 1
347            self.gauge.Show(True)
348            if self.enable_clear_gauge():
349                self.timer.Stop()
350                self.progress = 0
351                self.gauge.SetValue(90) 
352                self.timer_stop.Start(3) 
353                   
354    def set_status(self, event):
355        """
356        Update the status bar .
357       
358        :param type: type of message send.
359            type  must be in ["start","progress","update","stop"]
360        :param msg: the message itself  as string
361        :param thread: if updatting using a thread status
362       
363        """
364        self.set_message(event=event)
365        self.set_icon(event=event)
366        self.set_gauge(event=event)
367   
368    def _onMonitor(self, event):
369        """
370        Pop up a frame with messages sent to the status bar
371        """
372        self.frame.Show(False)
373        self.frame.Show(True)
374       
375       
376class SPageStatusbar(wxStatusB):
377    def __init__(self, parent, timeout=None, *args, **kwds):
378        wxStatusB.__init__(self, parent, *args, **kwds)
379        self.SetFieldsCount(1) 
380        self.timeout = timeout
381        width, height = parent.GetSizeTuple()
382        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
383                              size=(width, height/10))
384        rect = self.GetFieldRect(0)
385        self.gauge.SetPosition((rect.x , rect.y ))
386        if self.timeout is not None:
387            self.gauge.SetRange(int(self.timeout))
388        self.timer = wx.Timer(self, -1) 
389        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
390        self.timer.Start(1)
391        self.pos = 0
392       
393    def _on_time(self, evt): 
394        """
395        Update the progress bar while the timer is running
396       
397        :param evt: wx.EVT_TIMER
398 
399        """ 
400        # Check stop flag that can be set from non main thread
401        if self.timeout is None and self.timer.IsRunning(): 
402            self.gauge.Pulse()
403           
404       
405if __name__ == "__main__":
406    app = wx.PySimpleApp()
407    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
408    #statusBar = StatusBar(frame, wx.ID_ANY)
409    statusBar = SPageStatusbar(frame)
410    frame.SetStatusBar(statusBar)
411    frame.Show(True)
412    #event = MessageEvent()
413    #event.type = "progress"
414    #event.status  = "statusbar...."
415    #event.info = "error"
416    #statusBar.set_status(event=event)
417    app.MainLoop()
418
Note: See TracBrowser for help on using the repository browser.