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

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 225ed2d was 940aca7, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Merge 2.1.1 into trunk

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