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
RevLine 
[010c251]1import wx
[804a7db]2import sys
[010c251]3from wx import StatusBar as wxStatusB
4from wx.lib import newevent
[2d98490]5import wx.richtext
[07dd0b4]6from sans.guiframe.gui_style import GUIFRAME_ICON
[caf273b]7
8# Number of fields on the status bar
[010c251]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
[caf273b]16STATUS_BAR_ICON_SIZE = 12
[2d98490]17CONSOLE_WIDTH = 500
[199fdec]18CONSOLE_HEIGHT = 300
[804a7db]19if sys.platform.count("win32") > 0:
20    FONT_VARIANT = 0
21else:
22    FONT_VARIANT = 1
[010c251]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)
[2d98490]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       
[010c251]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       
[2d98490]43    def set_message(self, status="", event=None):
[010c251]44        """
45        """
[2d98490]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,
[caf273b]51                                             wx.ART_TOOLBAR)
[2d98490]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,
[caf273b]57                                                     wx.ART_TOOLBAR)
[2d98490]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       
[010c251]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)
[804a7db]80        self.SetWindowVariant(FONT_VARIANT)
[010c251]81        self.panel = ConsolePanel(self)
82        self.panel.set_message(status=status)
[bfa73ca]83        wx.EVT_CLOSE(self, self.Close)
[783940c]84       
[010c251]85    def set_multiple_messages(self, messages=[]):
86        """
87        """
88        if messages:
89            for status in messages:
[2d98490]90                self.panel.set_message(status=status)
[010c251]91               
[2d98490]92    def set_message(self, status, event=None):
[bfa73ca]93        """
94        """
[2d98490]95        self.panel.set_message(status=str(status), event=event)
[bfa73ca]96       
97    def Close(self, event):
[010c251]98        """
99        """
[bfa73ca]100        self.Hide()
[010c251]101       
102class StatusBar(wxStatusB):
103    """
[6e4d543]104        Application status bar
[010c251]105    """
[6e4d543]106    def __init__(self, parent, id):
107        wxStatusB.__init__(self, parent, id)
[010c251]108        self.parent = parent
109        self.parent.SetStatusBarPane(MSG_POSITION)
[6e4d543]110
[010c251]111        #Layout of status bar
[caf273b]112        width = STATUS_BAR_ICON_SIZE
113        height = STATUS_BAR_ICON_SIZE
[010c251]114        self.SetFieldsCount(NB_FIELDS) 
[6e4d543]115        # Leave some space for the resize handle in the last field
[b716dd8]116        self.SetStatusWidths([width+4, -2, -1, width+15])
117        self.SetMinHeight(height)
[6e4d543]118       
[010c251]119        #display default message
120        self.msg_position = MSG_POSITION
[6e4d543]121       
122        # Create progress bar
[804a7db]123        gauge_width = 5 * width
124        self.gauge = wx.Gauge(self, size=(gauge_width, height),
[010c251]125                               style=wx.GA_HORIZONTAL)
126        self.gauge.Hide()
[6e4d543]127       
128        # Create status bar icon reflecting the type of status
129        # for the last message
[9690fbf]130        self.bitmap_bt_warning = \
131            wx.BitmapButton(self, -1,
[b716dd8]132                            size=(width, height),
[a781312]133                            style=wx.NO_BORDER)
[6e4d543]134               
135        # Create the button used to show the console dialog
[9690fbf]136        console_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, 
137                                               wx.ART_TOOLBAR,
[b716dd8]138                                               size = (width, height))
[010c251]139        self.bitmap_bt_console = wx.BitmapButton(self, -1, 
[b716dd8]140                                 size=(width, height),
[a781312]141                                 style=wx.NO_BORDER)
[010c251]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,
[caf273b]146                                    id=self.bitmap_bt_console.GetId())
[bfa73ca]147       
[010c251]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 = []
[bfa73ca]155        self.frame = Console(parent=self)
[07dd0b4]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
[bfa73ca]168        self.frame.set_multiple_messages(self.list_msg)
169        self.frame.Hide()
[caf273b]170        self.progress = 0
171        self.timer = wx.Timer(self, -1)
172        self.timer_stop = wx.Timer(self, -1)
[010c251]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        """
[b716dd8]181            Place the various fields in their proper position
[010c251]182        """
183        rect = self.GetFieldRect(GAUGE_POSITION)
[6e4d543]184        self.gauge.SetPosition((rect.x, rect.y))
[010c251]185        rect = self.GetFieldRect(ICON_POSITION)
[6e4d543]186        self.bitmap_bt_warning.SetPosition((rect.x, rect.y))
[010c251]187        rect = self.GetFieldRect(CONSOLE_POSITION)
[6e4d543]188        self.bitmap_bt_console.SetPosition((rect.x, rect.y))
[010c251]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   
[2d98490]208    def SetStatusText(self, text="", number=MSG_POSITION, event=None):
[010c251]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)
[caf273b]215
[bfa73ca]216        if self.frame is not None :
[2d98490]217            self.frame.set_message(status=text, event=event)
[bfa73ca]218       
[010c251]219    def PopStatusText(self, *args, **kwds):
220        """
221        Override status bar
222        """
223        wxStatusB.PopStatusText(self, field=MSG_POSITION)
[986da97]224       
[010c251]225    def PushStatusText(self, *args, **kwds):
226        """
[3fc01c5]227        PushStatusText
[010c251]228        """
[3fc01c5]229        text = "PushStatusText: What is this string?"
230        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=text)
[010c251]231       
232    def enable_clear_gauge(self):
233        """
234        clear the progress bar
235        """
[940aca7]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
[010c251]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        """
[2d98490]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
[010c251]282        """
[2d98490]283        if hasattr(event, "status"):
[07dd0b4]284            status = str(event.status)
[2d98490]285            if status.strip() == "":
286                return
287        else:
288            return
[010c251]289        if not hasattr(event, "info"):
290            return 
[6e4d543]291       
[b716dd8]292        # Get the size of the button images
[caf273b]293        height = STATUS_BAR_ICON_SIZE
[6e4d543]294       
[010c251]295        msg = event.info.lower()
296        if msg == "warning":
[6e4d543]297            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR,
298                                                 size = (height,height))
[010c251]299            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
[6e4d543]300        elif msg == "error":
301            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR,
302                                                 size = (height,height))
[010c251]303            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
[6e4d543]304        else:
[010c251]305            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
[6e4d543]306                                                 wx.ART_TOOLBAR,
307                                                 size = (height,height))
[010c251]308            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
309   
[7d89e50]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
[010c251]322    def set_message(self, event):
323        """
324        display received message on the statusbar
325        """
326        if hasattr(event, "status"):
[2d98490]327            self.SetStatusText(text=str(event.status), event=event)
[bfa73ca]328       
[010c251]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()
[804a7db]340            self.progress += 5
[010c251]341            self.gauge.SetValue(int(self.progress)) 
[804a7db]342            self.progress += 5
[010c251]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":
[804a7db]350            self.progress += 5
[010c251]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
[3c965fd]359                self.gauge.SetValue(100) 
[804a7db]360                self.timer_stop.Start(5) 
[010c251]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)
[7d89e50]375        # dialog on error
376        self.set_dialog(event=event)
377       
[010c251]378    def _onMonitor(self, event):
379        """
380        Pop up a frame with messages sent to the status bar
381        """
[96683dc]382        self.frame.Show(False)
[010c251]383        self.frame.Show(True)
384       
385       
[7a955a9]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
[43cc1ad2]391        width, height = parent.GetSizeTuple()
392        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
393                              size=(width, height/10))
[7a955a9]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       
[010c251]415if __name__ == "__main__":
416    app = wx.PySimpleApp()
417    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
[7a955a9]418    #statusBar = StatusBar(frame, wx.ID_ANY)
419    statusBar = SPageStatusbar(frame)
[010c251]420    frame.SetStatusBar(statusBar)
421    frame.Show(True)
[7a955a9]422    #event = MessageEvent()
423    #event.type = "progress"
424    #event.status  = "statusbar...."
425    #event.info = "error"
426    #statusBar.set_status(event=event)
[010c251]427    app.MainLoop()
428
Note: See TracBrowser for help on using the repository browser.