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

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

Fix wx2.8 issue with fonts

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