source: sasview/src/sans/guiframe/gui_statusbar.py @ 92c6c36

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 92c6c36 was 8001331, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Fix panel position on windows

  • Property mode set to 100644
File size: 14.1 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.status_color = wx.StaticText(self, id=wx.NewId(), label="   ", size=wx.Size(15,15))
136        self.status_color.SetBackgroundColour(GREEN)
137        self.status_color.SetForegroundColour(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, -1))
142        font = self.console_button.GetFont()
143        _, pixel_h = font.GetPixelSize()
144        font.SetPixelSize(wx.Size(0,int(pixel_h*0.9)))
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.status_color.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.status_color.SetBackgroundColour(GREEN)
216        self.status_color.SetForegroundColour(GREEN)
217
218        if self.frame is not None :
219            self.frame.set_message(status=text, event=event)
220       
221    def PopStatusText(self, *args, **kwds):
222        """
223        Override status bar
224        """
225        wxStatusB.PopStatusText(self, field=MSG_POSITION)
226       
227    def PushStatusText(self, *args, **kwds):
228        """
229        PushStatusText
230        """
231        text = "PushStatusText: What is this string?"
232        wxStatusB.PushStatusText(self, field=MSG_POSITION, string=text)
233       
234    def enable_clear_gauge(self):
235        """
236        clear the progress bar
237        """
238        flag = True
239        # Why we do this?
240        #if (self.nb_start <= self.nb_stop) or \
241        #    (self.nb_progress <= self.nb_stop):
242        #    flag = True
243        return flag
244   
245    def _on_time_stop(self, evt): 
246        """
247        Clear the progress bar
248       
249        :param evt: wx.EVT_TIMER
250 
251        """ 
252        count = 0
253        while(count <= 100):
254            count += 1
255        self.timer_stop.Stop() 
256        self.clear_gauge(msg="")
257        self.nb_progress = 0 
258        self.nb_start = 0 
259        self.nb_stop = 0
260       
261    def _on_time(self, evt): 
262        """
263        Update the progress bar while the timer is running
264       
265        :param evt: wx.EVT_TIMER
266 
267        """ 
268        # Check stop flag that can be set from non main thread
269        if self.timer.IsRunning(): 
270            self.gauge.Pulse()
271   
272    def clear_gauge(self, msg=""):
273        """
274        Hide the gauge
275        """
276        self.progress = 0
277        self.gauge.SetValue(0)
278        self.gauge.Hide() 
279         
280    def set_icon(self, event):
281        """
282        Display icons related to the type of message sent to the statusbar
283        when available. No icon is displayed if the message is empty
284        """
285        if hasattr(event, "status"):
286            status = str(event.status)
287            if status.strip() == "":
288                return
289        else:
290            return
291        if not hasattr(event, "info"):
292            return 
293       
294        # Get the size of the button images
295        height = STATUS_BAR_ICON_SIZE
296       
297        msg = event.info.lower()
298        if msg == "warning":
299            self.status_color.SetBackgroundColour(YELLOW)
300            self.status_color.SetForegroundColour(YELLOW)
301        elif msg == "error":
302            self.status_color.SetBackgroundColour(RED)
303            self.status_color.SetForegroundColour(RED)
304        else:
305            self.status_color.SetBackgroundColour(GREEN)
306            self.status_color.SetForegroundColour(GREEN)
307   
308    def set_dialog(self, event):
309        """
310        Display dialogbox
311        """
312        if not hasattr(event, "info"):
313            return 
314        msg = event.info.lower()
315        if msg == "error":
316            e_msg = "Error(s) Occurred:\n"
317            e_msg += event.status
318            wx.MessageBox(e_msg, style=wx.ICON_ERROR)
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    def set_gauge(self, event):
328        """
329        change the state of the gauge according the state of the current job
330        """
331        if not hasattr(event, "type"):
332            return
333        type = event.type
334        self.gauge.Show(True)
335        if type.lower() == "start":
336            self.nb_start += 1
337            #self.timer.Stop()
338            self.progress += 5
339            self.gauge.SetValue(int(self.progress)) 
340            self.progress += 5
341            if self.progress < self.gauge.GetRange() - 20:
342                self.gauge.SetValue(int(self.progress)) 
343        if type.lower() == "progress":
344            self.nb_progress += 1
345            self.timer.Start(1)
346            self.gauge.Pulse()
347        if type.lower() == "update":
348            self.progress += 5
349            if self.progress < self.gauge.GetRange()- 20:
350                self.gauge.SetValue(int(self.progress))   
351        if type.lower() == "stop":
352            self.nb_stop += 1
353            self.gauge.Show(True)
354            if self.enable_clear_gauge():
355                self.timer.Stop()
356                self.progress = 0
357                self.gauge.SetValue(100) 
358                self.timer_stop.Start(5) 
359                   
360    def set_status(self, event):
361        """
362        Update the status bar .
363       
364        :param type: type of message send.
365            type  must be in ["start","progress","update","stop"]
366        :param msg: the message itself  as string
367        :param thread: if updatting using a thread status
368       
369        """
370        self.set_message(event=event)
371        self.set_icon(event=event)
372        self.set_gauge(event=event)
373        # dialog on error
374        self.set_dialog(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.