source: sasview/src/sans/guiframe/gui_statusbar.py @ eea3ffa

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 eea3ffa was caf273b, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Re #216 Fix toolbar issue.

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