source: sasview/src/sans/guiframe/gui_statusbar.py @ 30fbe6d

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

tweak button

  • Property mode set to 100644
File size: 14.2 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        self.bitmap_bt_warning.SetForegroundColour(GREEN)
139
140        # Create the button used to show the console dialog
141        self.console_button = wx.Button(self, wx.NewId(), "Console", 
142                                 size=(console_btn_width, -1))
143        font = self.console_button.GetFont()
144        _, pixel_h = font.GetPixelSize()
145        font.SetPixelSize(wx.Size(0,int(pixel_h*0.9)))
146        self.console_button.SetFont(font)
147        self.console_button.SetToolTipString("History of status bar messages")
148        self.console_button.Bind(wx.EVT_BUTTON, self._onMonitor,
149                                id=self.console_button.GetId())
150       
151        self.reposition()
152        ## Current progress value of the bar
153        self.nb_start = 0
154        self.nb_progress = 0
155        self.nb_stop = 0
156        self.frame = None
157        self.list_msg = []
158        self.frame = Console(parent=self)
159        if hasattr(self.frame, "IsIconized"):
160            if not self.frame.IsIconized():
161                try:
162                    icon = self.parent.GetIcon()
163                    self.frame.SetIcon(icon)
164                except:
165                    try:
166                        FRAME_ICON = wx.Icon(GUIFRAME_ICON.FRAME_ICON_PATH,
167                                              wx.BITMAP_TYPE_ICON)
168                        self.frame.SetIcon(FRAME_ICON)
169                    except:
170                        pass
171        self.frame.set_multiple_messages(self.list_msg)
172        self.frame.Hide()
173        self.progress = 0
174        self.timer = wx.Timer(self, -1)
175        self.timer_stop = wx.Timer(self, -1)
176        self.thread = None
177        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
178        self.Bind(wx.EVT_TIMER, self._on_time_stop, self.timer_stop) 
179        self.Bind(wx.EVT_SIZE, self.OnSize)
180        self.Bind(wx.EVT_IDLE, self.OnIdle)
181       
182    def reposition(self):
183        """
184            Place the various fields in their proper position
185        """
186        rect = self.GetFieldRect(GAUGE_POSITION)
187        self.gauge.SetPosition((rect.x, rect.y))
188        rect = self.GetFieldRect(ICON_POSITION)
189        self.bitmap_bt_warning.SetPosition((rect.x, rect.y))
190        rect = self.GetFieldRect(CONSOLE_POSITION)
191        self.console_button.SetPosition((rect.x, rect.y))
192        self.sizeChanged = False
193       
194    def OnIdle(self, event):
195        """
196        """
197        if self.sizeChanged:
198            self.reposition()
199           
200    def OnSize(self, evt):
201        """
202        """
203        self.reposition() 
204        self.sizeChanged = True
205       
206    def get_msg_position(self):
207        """
208        """
209        return self.msg_position
210   
211    def SetStatusText(self, text="", number=MSG_POSITION, event=None):
212        """
213        """
214        wxStatusB.SetStatusText(self, text, number)
215        self.list_msg.append(text)
216        self.bitmap_bt_warning.SetBackgroundColour(GREEN)
217        self.bitmap_bt_warning.SetForegroundColour(GREEN)
218
219        if self.frame is not None :
220            self.frame.set_message(status=text, event=event)
221       
222    def PopStatusText(self, *args, **kwds):
223        """
224        Override status bar
225        """
226        wxStatusB.PopStatusText(self, field=MSG_POSITION)
227       
228    def PushStatusText(self, *args, **kwds):
229        """
230        PushStatusText
231        """
232        text = "PushStatusText: What is this string?"
233        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=text)
234       
235    def enable_clear_gauge(self):
236        """
237        clear the progress bar
238        """
239        flag = True
240        # Why we do this?
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        height = STATUS_BAR_ICON_SIZE
297       
298        msg = event.info.lower()
299        if msg == "warning":
300            self.bitmap_bt_warning.SetBackgroundColour(YELLOW)
301            self.bitmap_bt_warning.SetForegroundColour(YELLOW)
302        elif msg == "error":
303            self.bitmap_bt_warning.SetBackgroundColour(RED)
304            self.bitmap_bt_warning.SetForegroundColour(RED)
305        else:
306            self.bitmap_bt_warning.SetBackgroundColour(GREEN)
307            self.bitmap_bt_warning.SetForegroundColour(GREEN)
308   
309    def set_dialog(self, event):
310        """
311        Display dialogbox
312        """
313        if not hasattr(event, "info"):
314            return 
315        msg = event.info.lower()
316        if msg == "error":
317            e_msg = "Error(s) Occurred:\n"
318            e_msg += event.status
319            wx.MessageBox(e_msg, style=wx.ICON_ERROR)
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    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(100) 
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        # dialog on error
375        self.set_dialog(event=event)
376       
377    def _onMonitor(self, event):
378        """
379        Pop up a frame with messages sent to the status bar
380        """
381        self.frame.Show(False)
382        self.frame.Show(True)
383       
384       
385class SPageStatusbar(wxStatusB):
386    def __init__(self, parent, timeout=None, *args, **kwds):
387        wxStatusB.__init__(self, parent, *args, **kwds)
388        self.SetFieldsCount(1) 
389        self.timeout = timeout
390        width, height = parent.GetSizeTuple()
391        self.gauge = wx.Gauge(self, style=wx.GA_HORIZONTAL, 
392                              size=(width, height/10))
393        rect = self.GetFieldRect(0)
394        self.gauge.SetPosition((rect.x , rect.y ))
395        if self.timeout is not None:
396            self.gauge.SetRange(int(self.timeout))
397        self.timer = wx.Timer(self, -1) 
398        self.Bind(wx.EVT_TIMER, self._on_time, self.timer) 
399        self.timer.Start(1)
400        self.pos = 0
401       
402    def _on_time(self, evt): 
403        """
404        Update the progress bar while the timer is running
405       
406        :param evt: wx.EVT_TIMER
407 
408        """ 
409        # Check stop flag that can be set from non main thread
410        if self.timeout is None and self.timer.IsRunning(): 
411            self.gauge.Pulse()
412           
413       
414if __name__ == "__main__":
415    app = wx.PySimpleApp()
416    frame = wx.Frame(None, wx.ID_ANY, 'test frame')
417    #statusBar = StatusBar(frame, wx.ID_ANY)
418    statusBar = SPageStatusbar(frame)
419    frame.SetStatusBar(statusBar)
420    frame.Show(True)
421    #event = MessageEvent()
422    #event.type = "progress"
423    #event.status  = "statusbar...."
424    #event.info = "error"
425    #statusBar.set_status(event=event)
426    app.MainLoop()
427
Note: See TracBrowser for help on using the repository browser.