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

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 804a7db was 804a7db, checked in by Jae Cho <jhjcho@…>, 12 years ago

try to fix status bar gauge appearance

  • 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 = 50
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 = False
241        if (self.nb_start <= self.nb_stop) or \
242            (self.nb_progress <= self.nb_stop):
243            flag = True
244        return flag
245   
246    def _on_time_stop(self, evt): 
247        """
248        Clear the progress bar
249       
250        :param evt: wx.EVT_TIMER
251 
252        """ 
253        count = 0
254        while(count <= 100):
255            count += 1
256        self.timer_stop.Stop() 
257        self.clear_gauge(msg="")
258        self.nb_progress = 0 
259        self.nb_start = 0 
260        self.nb_stop = 0
261       
262    def _on_time(self, evt): 
263        """
264        Update the progress bar while the timer is running
265       
266        :param evt: wx.EVT_TIMER
267 
268        """ 
269        # Check stop flag that can be set from non main thread
270        if self.timer.IsRunning(): 
271            self.gauge.Pulse()
272   
273    def clear_gauge(self, msg=""):
274        """
275        Hide the gauge
276        """
277        self.progress = 0
278        self.gauge.SetValue(0)
279        self.gauge.Hide() 
280         
281    def set_icon(self, event):
282        """
283        Display icons related to the type of message sent to the statusbar
284        when available. No icon is displayed if the message is empty
285        """
286        if hasattr(event, "status"):
287            status = str(event.status)
288            if status.strip() == "":
289                return
290        else:
291            return
292        if not hasattr(event, "info"):
293            return 
294       
295        # Get the size of the button images
296        width, height = wx.ArtProvider.GetSizeHint(wx.ART_TOOLBAR)       
297
298        # Get the size of the field and choose the size of the
299        # image accordingly
300        rect = self.GetFieldRect(ICON_POSITION)
301        if rect.height > height:
302            height = rect.GetHeight()
303            width = rect.GetWidth()
304       
305        msg = event.info.lower()
306        if msg == "warning":
307            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR,
308                                                 size = (height,height))
309            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
310        elif msg == "error":
311            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR,
312                                                 size = (height,height))
313            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
314        else:
315            icon_bmp =  wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
316                                                 wx.ART_TOOLBAR,
317                                                 size = (height,height))
318            self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
319   
320    def set_message(self, event):
321        """
322        display received message on the statusbar
323        """
324        if hasattr(event, "status"):
325            self.SetStatusText(text=str(event.status), event=event)
326       
327 
328    def set_gauge(self, event):
329        """
330        change the state of the gauge according the state of the current job
331        """
332        if not hasattr(event, "type"):
333            return
334        type = event.type
335        self.gauge.Show(True)
336        if type.lower() == "start":
337            self.nb_start += 1
338            #self.timer.Stop()
339            self.progress += 5
340            self.gauge.SetValue(int(self.progress)) 
341            self.progress += 5
342            if self.progress < self.gauge.GetRange() - 20:
343                self.gauge.SetValue(int(self.progress)) 
344        if type.lower() == "progress":
345            self.nb_progress += 1
346            self.timer.Start(1)
347            self.gauge.Pulse()
348        if type.lower() == "update":
349            self.progress += 5
350            if self.progress < self.gauge.GetRange()- 20:
351                self.gauge.SetValue(int(self.progress))   
352        if type.lower() == "stop":
353            self.nb_stop += 1
354            self.gauge.Show(True)
355            if self.enable_clear_gauge():
356                self.timer.Stop()
357                self.progress = 0
358                self.gauge.SetValue(90) 
359                self.timer_stop.Start(5) 
360                   
361    def set_status(self, event):
362        """
363        Update the status bar .
364       
365        :param type: type of message send.
366            type  must be in ["start","progress","update","stop"]
367        :param msg: the message itself  as string
368        :param thread: if updatting using a thread status
369       
370        """
371        self.set_message(event=event)
372        self.set_icon(event=event)
373        self.set_gauge(event=event)
374   
375    def _onMonitor(self, event):
376        """
377        Pop up a frame with messages sent to the status bar
378        """
379        self.frame.Show(False)
380        self.frame.Show(True)
381       
382       
383class SPageStatusbar(wxStatusB):
384    def __init__(self, parent, timeout=None, *args, **kwds):
385        wxStatusB.__init__(self, parent, *args, **kwds)
386        self.SetFieldsCount(1) 
387        self.timeout = timeout
388        width, height = parent.GetSizeTuple()
389        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
390                              size=(width, height/10))
391        rect = self.GetFieldRect(0)
392        self.gauge.SetPosition((rect.x , rect.y ))
393        if self.timeout is not None:
394            self.gauge.SetRange(int(self.timeout))
395        self.timer = wx.Timer(self, -1) 
396        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
397        self.timer.Start(1)
398        self.pos = 0
399       
400    def _on_time(self, evt): 
401        """
402        Update the progress bar while the timer is running
403       
404        :param evt: wx.EVT_TIMER
405 
406        """ 
407        # Check stop flag that can be set from non main thread
408        if self.timeout is None and self.timer.IsRunning(): 
409            self.gauge.Pulse()
410           
411       
412if __name__ == "__main__":
413    app = wx.PySimpleApp()
414    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
415    #statusBar = StatusBar(frame, wx.ID_ANY)
416    statusBar = SPageStatusbar(frame)
417    frame.SetStatusBar(statusBar)
418    frame.Show(True)
419    #event = MessageEvent()
420    #event.type = "progress"
421    #event.status  = "statusbar...."
422    #event.info = "error"
423    #statusBar.set_status(event=event)
424    app.MainLoop()
425
Note: See TracBrowser for help on using the repository browser.