controls/LogViewer.py
changeset 983 7dd481eef3b5
parent 982 e3c264099bd0
child 984 2d03056993f6
equal deleted inserted replaced
982:e3c264099bd0 983:7dd481eef3b5
    32 from targets.typemapping import LogLevelsCount, LogLevels
    32 from targets.typemapping import LogLevelsCount, LogLevels
    33 from util.BitmapLibrary import GetBitmap
    33 from util.BitmapLibrary import GetBitmap
    34 
    34 
    35 THUMB_SIZE_RATIO = 1. / 8.
    35 THUMB_SIZE_RATIO = 1. / 8.
    36 
    36 
    37 class MyScrollBar(wx.Panel):
    37 class LogScrollBar(wx.Panel):
    38     
    38     
    39     def __init__(self, parent, size):
    39     def __init__(self, parent, size):
    40         wx.Panel.__init__(self, parent, size=size)
    40         wx.Panel.__init__(self, parent, size=size)
    41         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
    41         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
    42         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
    42         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
   151                          thumb_rect.width, thumb_rect.height)
   151                          thumb_rect.width, thumb_rect.height)
   152         
   152         
   153         dc.EndDrawing()
   153         dc.EndDrawing()
   154         event.Skip()
   154         event.Skip()
   155 
   155 
       
   156 BUTTON_SIZE = (30, 15)
       
   157 
       
   158 class LogButton():
       
   159     
       
   160     def __init__(self, label, callback):
       
   161         self.Position = wx.Point(0, 0)
       
   162         self.Size = wx.Size(*BUTTON_SIZE)
       
   163         if wx.Platform == '__WXMSW__':
       
   164             self.Font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier New')
       
   165         else:
       
   166             self.Font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier')
       
   167         self.Label = label
       
   168         self.Shown = True
       
   169         self.Callback = callback
       
   170     
       
   171     def __del__(self):
       
   172         self.callback = None
       
   173     
       
   174     def GetSize(self):
       
   175         return self.Size
       
   176     
       
   177     def SetPosition(self, x, y):
       
   178         self.Position = wx.Point(x, y)
       
   179     
       
   180     def HitTest(self, x, y):
       
   181         rect = wx.Rect(self.Position.x, self.Position.y, 
       
   182                        self.Size.width, self.Size.height)
       
   183         if rect.InsideXY(x, y):
       
   184             return True
       
   185         return False
       
   186     
       
   187     def ProcessCallback(self):
       
   188         if self.Callback is not None:
       
   189             wx.CallAfter(self.Callback)
       
   190             
       
   191     def Draw(self, dc):
       
   192         dc.SetPen(wx.TRANSPARENT_PEN)
       
   193         dc.SetBrush(wx.Brush(wx.NamedColour("LIGHT GREY")))
       
   194         
       
   195         dc.DrawRectangle(self.Position.x, self.Position.y, 
       
   196                          self.Size.width, self.Size.height)
       
   197         
       
   198         dc.SetFont(self.Font)
       
   199         
       
   200         w, h = dc.GetTextExtent(self.Label)
       
   201         dc.DrawText(self.Label, 
       
   202             self.Position.x + (self.Size.width - w) / 2, 
       
   203             self.Position.y + (self.Size.height - h) / 2)
       
   204 
   156 DATE_INFO_SIZE = 10
   205 DATE_INFO_SIZE = 10
   157 MESSAGE_INFO_SIZE = 30
   206 MESSAGE_INFO_SIZE = 30
   158 
   207 
   159 class LogMessage:
   208 class LogMessage:
   160     
   209     
   201 DAY = 24 * HOUR
   250 DAY = 24 * HOUR
   202 
   251 
   203 CHANGE_TIMESTAMP_BUTTONS = [(_("1d"), DAY),
   252 CHANGE_TIMESTAMP_BUTTONS = [(_("1d"), DAY),
   204                             (_("1h"), HOUR),
   253                             (_("1h"), HOUR),
   205                             (_("1m"), MINUTE)]
   254                             (_("1m"), MINUTE)]
   206 REVERSE_CHANGE_TIMESTAMP_BUTTONS = CHANGE_TIMESTAMP_BUTTONS[:]
       
   207 REVERSE_CHANGE_TIMESTAMP_BUTTONS.reverse()
       
   208 
   255 
   209 class LogViewer(DebugViewer, wx.Panel):
   256 class LogViewer(DebugViewer, wx.Panel):
   210     
   257     
   211     def __init__(self, parent, window):
   258     def __init__(self, parent, window):
   212         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
   259         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
   236               self.OnSearchMessageSearchButtonClick, self.SearchMessage)
   283               self.OnSearchMessageSearchButtonClick, self.SearchMessage)
   237         self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, 
   284         self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, 
   238               self.OnSearchMessageCancelButtonClick, self.SearchMessage)
   285               self.OnSearchMessageCancelButtonClick, self.SearchMessage)
   239         filter_sizer.AddWindow(self.SearchMessage, 3, flag=wx.GROW)
   286         filter_sizer.AddWindow(self.SearchMessage, 3, flag=wx.GROW)
   240         
   287         
   241         message_panel_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0)
   288         message_panel_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
   242         message_panel_sizer.AddGrowableCol(1)
   289         message_panel_sizer.AddGrowableCol(0)
   243         message_panel_sizer.AddGrowableRow(0)
   290         message_panel_sizer.AddGrowableRow(0)
   244         main_sizer.AddSizer(message_panel_sizer, border=5, flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
   291         main_sizer.AddSizer(message_panel_sizer, border=5, flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
   245         
       
   246         buttons_sizer = wx.BoxSizer(wx.VERTICAL)
       
   247         for label, callback in [("+" + text, self.GenerateOnDurationButton(duration)) 
       
   248                                 for text, duration in CHANGE_TIMESTAMP_BUTTONS] +\
       
   249                                [("-" + text, self.GenerateOnDurationButton(-duration)) 
       
   250                                 for text, duration in REVERSE_CHANGE_TIMESTAMP_BUTTONS]:
       
   251             button = wx.Button(self, label=label)
       
   252             self.Bind(wx.EVT_BUTTON, callback, button)
       
   253             buttons_sizer.AddWindow(button, 1, wx.ALIGN_CENTER_VERTICAL)
       
   254         message_panel_sizer.AddSizer(buttons_sizer, flag=wx.GROW)
       
   255         
   292         
   256         self.MessagePanel = wx.Panel(self)
   293         self.MessagePanel = wx.Panel(self)
   257         if wx.Platform == '__WXMSW__':
   294         if wx.Platform == '__WXMSW__':
   258             self.Font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier New')
   295             self.Font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier New')
   259         else:
   296         else:
   260             self.Font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier')    
   297             self.Font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName='Courier')
       
   298         self.MessagePanel.Bind(wx.EVT_LEFT_DOWN, self.OnMessagePanelLeftDown)
   261         self.MessagePanel.Bind(wx.EVT_MOUSEWHEEL, self.OnMessagePanelMouseWheel)
   299         self.MessagePanel.Bind(wx.EVT_MOUSEWHEEL, self.OnMessagePanelMouseWheel)
   262         self.MessagePanel.Bind(wx.EVT_PAINT, self.OnMessagePanelPaint)
   300         self.MessagePanel.Bind(wx.EVT_PAINT, self.OnMessagePanelPaint)
   263         self.MessagePanel.Bind(wx.EVT_SIZE, self.OnMessagePanelResize)
   301         self.MessagePanel.Bind(wx.EVT_SIZE, self.OnMessagePanelResize)
   264         message_panel_sizer.AddWindow(self.MessagePanel, flag=wx.GROW)
   302         message_panel_sizer.AddWindow(self.MessagePanel, flag=wx.GROW)
   265         
   303         
   266         self.MessageScrollBar = MyScrollBar(self, wx.Size(16, -1))
   304         self.MessageScrollBar = LogScrollBar(self, wx.Size(16, -1))
   267         message_panel_sizer.AddWindow(self.MessageScrollBar, flag=wx.GROW)
   305         message_panel_sizer.AddWindow(self.MessageScrollBar, flag=wx.GROW)
   268         
   306         
   269         self.SetSizer(main_sizer)
   307         self.SetSizer(main_sizer)
   270     
   308         
       
   309         self.LeftButtons = []
       
   310         for label, callback in [("+" + text, self.GenerateOnDurationButton(duration)) 
       
   311                                 for text, duration in CHANGE_TIMESTAMP_BUTTONS]:
       
   312             self.LeftButtons.append(LogButton(label, callback))
       
   313         
       
   314         self.RightButtons = []
       
   315         for label, callback in [("-" + text, self.GenerateOnDurationButton(-duration)) 
       
   316                                 for text, duration in CHANGE_TIMESTAMP_BUTTONS]:
       
   317             self.RightButtons.append(LogButton(label, callback))
       
   318         
   271         self.MessageFilter.SetSelection(0)
   319         self.MessageFilter.SetSelection(0)
   272         self.LogSource = None
   320         self.LogSource = None
   273         self.ResetLogMessages()
   321         self.ResetLogMessages()
   274         self.ParentWindow = window
   322         self.ParentWindow = window
   275     
   323     
   407     def RefreshView(self):
   455     def RefreshView(self):
   408         width, height = self.MessagePanel.GetClientSize()
   456         width, height = self.MessagePanel.GetClientSize()
   409         bitmap = wx.EmptyBitmap(width, height)
   457         bitmap = wx.EmptyBitmap(width, height)
   410         dc = wx.BufferedDC(wx.ClientDC(self.MessagePanel), bitmap)
   458         dc = wx.BufferedDC(wx.ClientDC(self.MessagePanel), bitmap)
   411         dc.Clear()
   459         dc.Clear()
   412         dc.SetFont(self.Font)
       
   413         dc.BeginDrawing()
   460         dc.BeginDrawing()
   414         
   461         
   415         if self.CurrentMessage is not None:
   462         if self.CurrentMessage is not None:
       
   463             
       
   464             for button in self.LeftButtons + self.RightButtons:
       
   465                 button.Draw(dc)
       
   466             
       
   467             dc.SetFont(self.Font)
       
   468             
   416             message_idx = self.CurrentMessage
   469             message_idx = self.CurrentMessage
   417             message = self.LogMessages[message_idx]
   470             message = self.LogMessages[message_idx]
   418             draw_date = True
   471             draw_date = True
   419             offset = 5
   472             offset = 5
   420             while offset < height and message is not None:
   473             while offset < height and message is not None:
   507         self.SearchMessage.SetValue("")
   560         self.SearchMessage.SetValue("")
   508         self.ResetMessagePanel()
   561         self.ResetMessagePanel()
   509         event.Skip()
   562         event.Skip()
   510     
   563     
   511     def GenerateOnDurationButton(self, duration):
   564     def GenerateOnDurationButton(self, duration):
   512         def OnDurationButton(event):
   565         def OnDurationButton():
   513             self.ScrollMessagePanelByTimestamp(duration)
   566             self.ScrollMessagePanelByTimestamp(duration)
   514             event.Skip()
       
   515         return OnDurationButton
   567         return OnDurationButton
       
   568     
       
   569     def OnMessagePanelLeftDown(self, event):
       
   570         if self.CurrentMessage is not None:
       
   571             posx, posy = event.GetPosition()
       
   572             for button in self.LeftButtons + self.RightButtons:
       
   573                 if button.HitTest(posx, posy):
       
   574                     button.ProcessCallback()
       
   575         event.Skip()
   516     
   576     
   517     def OnMessagePanelMouseWheel(self, event):
   577     def OnMessagePanelMouseWheel(self, event):
   518         self.ScrollMessagePanel(event.GetWheelRotation() / event.GetWheelDelta())
   578         self.ScrollMessagePanel(event.GetWheelRotation() / event.GetWheelDelta())
   519         event.Skip()
   579         event.Skip()
   520     
   580     
   521     def OnMessagePanelPaint(self, event):
   581     def OnMessagePanelPaint(self, event):
   522         self.RefreshView()
   582         self.RefreshView()
   523         event.Skip()
   583         event.Skip()
   524     
   584     
   525     def OnMessagePanelResize(self, event):
   585     def OnMessagePanelResize(self, event):
       
   586         if self.CurrentMessage is not None:
       
   587             width, height = self.MessagePanel.GetClientSize()
       
   588             offset = 2
       
   589             for button in self.LeftButtons:
       
   590                 button.SetPosition(offset, 2)
       
   591                 w, h = button.GetSize()
       
   592                 offset += w + 2
       
   593             offset = width - 2
       
   594             for button in self.RightButtons:
       
   595                 w, h = button.GetSize()
       
   596                 button.SetPosition(offset - w, 2)
       
   597                 offset -= w + 2
   526         if self.IsMessagePanelBottom():
   598         if self.IsMessagePanelBottom():
   527             self.ScrollToFirst()
   599             self.ScrollToFirst()
   528         else:
   600         else:
   529             self.RefreshView()
   601             self.RefreshView()
   530         event.Skip()
   602         event.Skip()