controls/DebugVariablePanel.py
changeset 928 a94e7fea7051
parent 927 bd3e5b65e8be
child 929 c562031146e4
equal deleted inserted replaced
927:bd3e5b65e8be 928:a94e7fea7051
    37     import matplotlib.pyplot
    37     import matplotlib.pyplot
    38     from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
    38     from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
    39     from matplotlib.backends.backend_wxagg import _convert_agg_to_wx_bitmap
    39     from matplotlib.backends.backend_wxagg import _convert_agg_to_wx_bitmap
    40     from matplotlib.backends.backend_agg import FigureCanvasAgg
    40     from matplotlib.backends.backend_agg import FigureCanvasAgg
    41     from mpl_toolkits.mplot3d import Axes3D
    41     from mpl_toolkits.mplot3d import Axes3D
       
    42     color_cycle = matplotlib.rcParams['axes.color_cycle']
    42     USE_MPL = True
    43     USE_MPL = True
    43 except:
    44 except:
    44     USE_MPL = False
    45     USE_MPL = False
    45 
    46 
    46 from graphics import DebugDataConsumer, DebugViewer, REFRESH_PERIOD
    47 from graphics import DebugDataConsumer, DebugViewer, REFRESH_PERIOD
   182         if self.Value != value:
   183         if self.Value != value:
   183             self.Value = value
   184             self.Value = value
   184             self.Parent.HasNewData = True
   185             self.Parent.HasNewData = True
   185             
   186             
   186     def GetValue(self, tick=None, raw=False):
   187     def GetValue(self, tick=None, raw=False):
   187         if tick is not None and self.IsNumVariable() and len(self.Data) > 0:
   188         if tick is not None and self.IsNumVariable():
   188             idx = numpy.argmin(abs(self.Data[:, 0] - tick))
   189             if len(self.Data) > 0:
   189             if self.VariableType in ["STRING", "WSTRING"]:
   190                 idx = numpy.argmin(abs(self.Data[:, 0] - tick))
   190                 value, forced = self.RawData[int(self.Data[idx, 2])]
   191                 if self.VariableType in ["STRING", "WSTRING"]:
   191                 if not raw:
   192                     value, forced = self.RawData[int(self.Data[idx, 2])]
   192                     if self.VariableType == "STRING":
   193                     if not raw:
   193                         value = "'%s'" % value
   194                         if self.VariableType == "STRING":
   194                     else:
   195                             value = "'%s'" % value
   195                         value = '"%s"' % value
   196                         else:
   196                 return value, forced
   197                             value = '"%s"' % value
   197             else:
   198                     return value, forced
   198                 value = self.Data[idx, 1]
   199                 else:
   199                 if not raw and isinstance(value, FloatType):
   200                     value = self.Data[idx, 1]
   200                     value = "%.6g" % value
   201                     if not raw and isinstance(value, FloatType):
   201                 return value, self.IsForced()
   202                         value = "%.6g" % value
       
   203                     return value, self.Data[idx, 2]
       
   204             return self.Value, self.IsForced()
   202         elif not raw:
   205         elif not raw:
   203             if self.VariableType == "STRING":
   206             if self.VariableType == "STRING":
   204                 return "'%s'" % self.Value
   207                 return "'%s'" % self.Value
   205             elif self.VariableType == "WSTRING":
   208             elif self.VariableType == "WSTRING":
   206                 return '"%s"' % self.Value
   209                 return '"%s"' % self.Value
   298     
   301     
   299     def __del__(self):
   302     def __del__(self):
   300         self.ParentWindow = None
   303         self.ParentWindow = None
   301         self.ParentControl = None
   304         self.ParentControl = None
   302     
   305     
       
   306     def OnDragOver(self, x, y, d):
       
   307         if self.ParentControl is not None:
       
   308             self.ParentControl.OnCanvasDragging(x, y)
       
   309         return wx.TextDropTarget.OnDragOver(self, x, y, d)
       
   310         
   303     def OnDropText(self, x, y, data):
   311     def OnDropText(self, x, y, data):
   304         message = None
   312         message = None
   305         try:
   313         try:
   306             values = eval(data)
   314             values = eval(data)
   307         except:
   315         except:
   347                             self.ParentWindow.InsertValue(values[0], target_idx, force=True)
   355                             self.ParentWindow.InsertValue(values[0], target_idx, force=True)
   348             elif len(values) > 2 and values[2] == "move":
   356             elif len(values) > 2 and values[2] == "move":
   349                 self.ParentWindow.MoveGraph(values[0])
   357                 self.ParentWindow.MoveGraph(values[0])
   350             else:
   358             else:
   351                 self.ParentWindow.InsertValue(values[0], force=True)
   359                 self.ParentWindow.InsertValue(values[0], force=True)
   352             
   360     
       
   361     def OnLeave(self):
       
   362         if self.ParentControl is not None:
       
   363             self.ParentControl.OnCanvasLeave()
       
   364         return wx.TextDropTarget.OnLeave(self)
       
   365         
   353     def ShowMessage(self, message):
   366     def ShowMessage(self, message):
   354         dialog = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   367         dialog = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   355         dialog.ShowModal()
   368         dialog.ShowModal()
   356         dialog.Destroy()
   369         dialog.Destroy()
   357 
   370 
   406             self.SetBackgroundColour(wx.WHITE)
   419             self.SetBackgroundColour(wx.WHITE)
   407             self.SetDropTarget(DebugVariableDropTarget(window, self))
   420             self.SetDropTarget(DebugVariableDropTarget(window, self))
   408             
   421             
   409             self.ParentWindow = window
   422             self.ParentWindow = window
   410             self.Items = items
   423             self.Items = items
   411             self.ResetVariableNameMask()
       
   412             
   424             
   413             self.MainSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
   425             self.MainSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
   414             self.AddViewer()
   426             self.AddViewer()
   415             self.AddButtons()
   427             self.AddButtons()
   416             self.MainSizer.AddGrowableCol(0)
   428             self.MainSizer.AddGrowableCol(0)
   438                 if self.GraphType == GRAPH_ORTHOGONAL:
   450                 if self.GraphType == GRAPH_ORTHOGONAL:
   439                     return tuple(variables)
   451                     return tuple(variables)
   440                 return variables
   452                 return variables
   441             return self.Items[0].GetVariable()
   453             return self.Items[0].GetVariable()
   442         
   454         
   443         def ResetVariableNameMask(self):
       
   444             if len(self.Items) > 1:
       
   445                 self.VariableNameMask = reduce(compute_mask,
       
   446                     [item.GetVariable().split('.') for item in self.Items])
       
   447             elif len(self.Items) > 0:
       
   448                 self.VariableNameMask = self.Items[0].GetVariable().split('.')[:-1] + ['*']
       
   449             else:
       
   450                 self.VariableNameMask = []
       
   451         
       
   452         def AddItem(self, item):
   455         def AddItem(self, item):
   453             self.Items.append(item)
   456             self.Items.append(item)
   454             self.ResetVariableNameMask()
   457             
   455     
       
   456         def RemoveItem(self, item):
   458         def RemoveItem(self, item):
   457             if item in self.Items:
   459             if item in self.Items:
   458                 self.Items.remove(item)
   460                 self.Items.remove(item)
   459             self.ResetVariableNameMask()
       
   460             
   461             
   461         def Clear(self):
   462         def Clear(self):
   462             for item in self.Items:
   463             for item in self.Items:
   463                 self.ParentWindow.RemoveDataConsumer(item)
   464                 self.ParentWindow.RemoveDataConsumer(item)
   464             self.Items = []
   465             self.Items = []
   465             self.ResetVariableNameMask()
   466             
   466         
       
   467         def IsEmpty(self):
   467         def IsEmpty(self):
   468             return len(self.Items) == 0
   468             return len(self.Items) == 0
   469         
   469         
   470         def UnregisterObsoleteData(self):
   470         def UnregisterObsoleteData(self):
   471             for item in self.Items[:]:
   471             for item in self.Items[:]:
   474                     self.ParentWindow.RemoveDataConsumer(item)
   474                     self.ParentWindow.RemoveDataConsumer(item)
   475                     self.RemoveItem(item)
   475                     self.RemoveItem(item)
   476                 else:
   476                 else:
   477                     self.ParentWindow.AddDataConsumer(iec_path, item)
   477                     self.ParentWindow.AddDataConsumer(iec_path, item)
   478                     item.RefreshVariableType()
   478                     item.RefreshVariableType()
   479             self.ResetVariableNameMask()
   479             
   480         
       
   481         def ResetData(self):
   480         def ResetData(self):
   482             for item in self.Items:
   481             for item in self.Items:
   483                 item.ResetData()
   482                 item.ResetData()
   484         
   483         
   485         def Refresh(self):
   484         def Refresh(self):
   491             else:
   490             else:
   492                 menu = wx.Menu(title='')
   491                 menu = wx.Menu(title='')
   493                 for item in self.Items:
   492                 for item in self.Items:
   494                     new_id = wx.NewId()
   493                     new_id = wx.NewId()
   495                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   494                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   496                         text=item.GetVariable(self.VariableNameMask))
   495                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   497                     self.Bind(wx.EVT_MENU, 
   496                     self.Bind(wx.EVT_MENU, 
   498                         self.GetForceVariableMenuFunction(item),
   497                         self.GetForceVariableMenuFunction(item),
   499                         id=new_id)
   498                         id=new_id)
   500                 self.PopupMenu(menu)
   499                 self.PopupMenu(menu)
   501             event.Skip()
   500             event.Skip()
   506             else:
   505             else:
   507                 menu = wx.Menu(title='')
   506                 menu = wx.Menu(title='')
   508                 for item in self.Items:
   507                 for item in self.Items:
   509                     new_id = wx.NewId()
   508                     new_id = wx.NewId()
   510                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   509                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   511                         text=item.GetVariable(self.VariableNameMask))
   510                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   512                     self.Bind(wx.EVT_MENU, 
   511                     self.Bind(wx.EVT_MENU, 
   513                         self.GetReleaseVariableMenuFunction(item),
   512                         self.GetReleaseVariableMenuFunction(item),
   514                         id=new_id)
   513                         id=new_id)
   515                 
   514                 
   516                 self.PopupMenu(menu)
   515                 self.PopupMenu(menu)
   522             else:
   521             else:
   523                 menu = wx.Menu(title='')
   522                 menu = wx.Menu(title='')
   524                 for item in self.Items:
   523                 for item in self.Items:
   525                     new_id = wx.NewId()
   524                     new_id = wx.NewId()
   526                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   525                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   527                         text=item.GetVariable(self.VariableNameMask))
   526                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   528                     self.Bind(wx.EVT_MENU, 
   527                     self.Bind(wx.EVT_MENU, 
   529                         self.GetDeleteValueMenuFunction(item),
   528                         self.GetDeleteValueMenuFunction(item),
   530                         id=new_id)
   529                         id=new_id)
   531                 
   530                 
   532                 new_id = wx.NewId()
   531                 new_id = wx.NewId()
   617                 mask.append(xp)
   616                 mask.append(xp)
   618             else:
   617             else:
   619                 mask.append("*")
   618                 mask.append("*")
   620         return mask
   619         return mask
   621     
   620     
       
   621     #CANVAS_HIGHLIGHT_TYPES
       
   622     [HIGHLIGHT_NONE,
       
   623      HIGHLIGHT_BEFORE,
       
   624      HIGHLIGHT_AFTER,
       
   625      HIGHLIGHT_LEFT,
       
   626      HIGHLIGHT_RIGHT] = range(5)
       
   627     
       
   628     HIGHLIGHT_PEN = wx.Pen(wx.Colour(0, 128, 255))
       
   629     HIGHLIGHT_BRUSH = wx.Brush(wx.Colour(0, 128, 255, 128))
       
   630     
   622     class DraggingFigureCanvas(FigureCanvas):
   631     class DraggingFigureCanvas(FigureCanvas):
   623         
   632         
   624         def __init__(self, parent, window, *args, **kwargs):
   633         def __init__(self, parent, window, *args, **kwargs):
   625             FigureCanvas.__init__(self, parent, *args, **kwargs)
   634             FigureCanvas.__init__(self, parent, *args, **kwargs)
   626             
   635             
   627             self.ParentWindow = window
   636             self.ParentWindow = window
   628             
   637             self.Highlight = HIGHLIGHT_NONE
       
   638         
       
   639         def SetHighlight(self, highlight):
       
   640             if self.Highlight != highlight:
       
   641                 self.Highlight = highlight
       
   642                 return True
       
   643             return False
       
   644         
       
   645         def GetAxesBoundingBox(self):
       
   646             width, height = self.GetSize()
       
   647             ax, ay, aw, ah = self.figure.gca().get_position().bounds
       
   648             return wx.Rect(ax * width, height - (ay + ah) * height - 1,
       
   649                            aw * width + 2, ah * height + 1)
       
   650         
   629         def draw(self, drawDC=None):
   651         def draw(self, drawDC=None):
   630             FigureCanvasAgg.draw(self)
   652             FigureCanvasAgg.draw(self)
   631     
   653     
   632             self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
   654             self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
       
   655             self.bitmap.UseAlpha() 
       
   656             width, height = self.GetSize()
       
   657             bbox = self.GetAxesBoundingBox()
       
   658             
       
   659             destDC = wx.MemoryDC()
       
   660             destDC.SelectObject(self.bitmap)
       
   661             
       
   662             destGC = wx.GCDC(destDC)
       
   663                     
       
   664             destGC.BeginDrawing()
       
   665             destGC.SetPen(HIGHLIGHT_PEN)
       
   666             destGC.SetBrush(HIGHLIGHT_BRUSH)
       
   667             if self.Highlight == HIGHLIGHT_BEFORE:
       
   668                 destGC.DrawLine(0, 0, width - 1, 0)
       
   669             elif self.Highlight == HIGHLIGHT_AFTER:
       
   670                 destGC.DrawLine(0, height - 1, width - 1, height - 1)
       
   671             elif self.Highlight == HIGHLIGHT_LEFT:
       
   672                 destGC.DrawRectangle(bbox.x, bbox.y, 
       
   673                                      bbox.width / 2, bbox.height)
       
   674             elif self.Highlight == HIGHLIGHT_RIGHT:
       
   675                 destGC.DrawRectangle(bbox.x + bbox.width / 2, bbox.y, 
       
   676                                      bbox.width / 2, bbox.height)
       
   677             
   633             if self.ParentWindow.IsDragging():
   678             if self.ParentWindow.IsDragging():
   634                 destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self.Parent)
   679                 destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self.Parent)
   635                 if destBBox.width > 0 and destBBox.height > 0:
   680                 if destBBox.width > 0 and destBBox.height > 0:
   636                     srcPanel = self.ParentWindow.DraggingAxesPanel
   681                     srcPanel = self.ParentWindow.DraggingAxesPanel
   637                     srcBBox = srcPanel.GetAxesBoundingBox()
   682                     srcBBox = srcPanel.GetAxesBoundingBox()
   647                     
   692                     
   648                     srcBmp = _convert_agg_to_wx_bitmap(srcPanel.Canvas.get_renderer(), None)
   693                     srcBmp = _convert_agg_to_wx_bitmap(srcPanel.Canvas.get_renderer(), None)
   649                     srcDC = wx.MemoryDC()
   694                     srcDC = wx.MemoryDC()
   650                     srcDC.SelectObject(srcBmp)
   695                     srcDC.SelectObject(srcBmp)
   651                     
   696                     
   652                     destDC = wx.MemoryDC()
   697                     destGC.Blit(destBBox.x, destBBox.y, 
   653                     destDC.SelectObject(self.bitmap)
       
   654                     
       
   655                     destDC.BeginDrawing()
       
   656                     destDC.Blit(destBBox.x, destBBox.y, 
       
   657                                 int(destBBox.width), int(destBBox.height), 
   698                                 int(destBBox.width), int(destBBox.height), 
   658                                 srcDC, srcX, srcY)
   699                                 srcDC, srcX, srcY)
   659                     destDC.EndDrawing()
       
   660                     
   700                     
       
   701             destGC.EndDrawing()
       
   702             
   661             self._isDrawn = True
   703             self._isDrawn = True
   662             self.gui_repaint(drawDC=drawDC)
   704             self.gui_repaint(drawDC=drawDC)
   663     
   705     
   664     class DebugVariableGraphic(DebugVariableViewer):
   706     class DebugVariableGraphic(DebugVariableViewer):
   665         
   707         
   666         def __init__(self, parent, window, items, graph_type):
   708         def __init__(self, parent, window, items, graph_type):
   667             DebugVariableViewer.__init__(self, parent, window, items)
   709             DebugVariableViewer.__init__(self, parent, window, items)
   668         
   710         
   669             self.GraphType = graph_type
   711             self.GraphType = graph_type
   670             self.CursorTick = None
   712             self.CursorTick = None
       
   713             self.MouseStartPos = None
       
   714             self.StartCursorTick = None
   671             
   715             
   672             self.ResetGraphics()
   716             self.ResetGraphics()
   673         
   717         
   674         def AddViewer(self):
   718         def AddViewer(self):
   675             self.Figure = matplotlib.figure.Figure(facecolor='w')
   719             self.Figure = matplotlib.figure.Figure(facecolor='w')
   676             
   720             
   677             self.Canvas = DraggingFigureCanvas(self, self.ParentWindow, -1, self.Figure)
   721             self.Canvas = DraggingFigureCanvas(self, self.ParentWindow, -1, self.Figure)
   678             self.Canvas.SetMinSize(wx.Size(200, 200))
   722             self.Canvas.SetMinSize(wx.Size(200, 200))
   679             self.Canvas.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
   723             self.Canvas.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
   680             self.Canvas.Bind(wx.EVT_LEFT_DOWN, self.OnCanvasLeftDown)
   724             self.Canvas.Bind(wx.EVT_LEFT_DOWN, self.OnCanvasLeftDown)
       
   725             self.Canvas.mpl_connect('button_press_event', self.OnCanvasButtonPressed)
   681             self.Canvas.mpl_connect('motion_notify_event', self.OnCanvasMotion)
   726             self.Canvas.mpl_connect('motion_notify_event', self.OnCanvasMotion)
   682             self.Canvas.mpl_connect('button_release_event', self.OnCanvasLeftUp)
   727             self.Canvas.mpl_connect('button_release_event', self.OnCanvasButtonReleased)
       
   728             self.Canvas.mpl_connect('scroll_event', self.OnCanvasScroll)
   683             
   729             
   684             self.MainSizer.AddWindow(self.Canvas, flag=wx.GROW)
   730             self.MainSizer.AddWindow(self.Canvas, flag=wx.GROW)
   685         
   731         
   686         def AddButtons(self):
   732         def AddButtons(self):
   687             button_sizer = wx.BoxSizer(wx.VERTICAL)
   733             button_sizer = wx.BoxSizer(wx.VERTICAL)
   701                 setattr(self, name, button)
   747                 setattr(self, name, button)
   702                 self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
   748                 self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
   703                 button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
   749                 button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
   704         
   750         
   705         def GetAxesBoundingBox(self, absolute=False):
   751         def GetAxesBoundingBox(self, absolute=False):
   706             width, height = self.Canvas.GetSize()
   752             bbox = self.Canvas.GetAxesBoundingBox()
   707             ax, ay, aw, ah = self.Axes.get_position().bounds
       
   708             bbox = wx.Rect(ax * width, height - (ay + ah) * height - 1,
       
   709                            aw * width + 2, ah * height + 1)
       
   710             if absolute:
   753             if absolute:
   711                 xw, yw = self.GetPosition()
   754                 xw, yw = self.GetPosition()
   712                 bbox.x += xw
   755                 bbox.x += xw
   713                 bbox.y += yw
   756                 bbox.y += yw
   714             return bbox
   757             return bbox
   715         
   758         
   716         def OnCanvasLeftDown(self, event):
   759         def OnCanvasLeftDown(self, event):
   717             x, y = event.GetPosition()
   760             if not self.Is3DCanvas():
   718             width, height = self.Canvas.GetSize()
   761                 x, y = event.GetPosition()
   719             if len(self.Items) == 1:
   762                 width, height = self.Canvas.GetSize()
   720                 rect = self.GetAxesBoundingBox()
   763                 rect = self.GetAxesBoundingBox()
   721                 if rect.InsideXY(x, y):
   764                 if rect.InsideXY(x, y):
   722                     xw, yw = self.GetPosition()
   765                     self.MouseStartPos = wx.Point(x, y)
   723                     self.ParentWindow.StartDragNDrop(self, x + xw, y + yw)
   766                 if self.Legend is not None:
   724                     return
   767                     item_idx = None
   725             elif self.Legend is not None:
   768                     for i, t in enumerate(self.Legend.get_texts()):
   726                 item_idx = None
   769                         (x0, y0), (x1, y1) = t.get_window_extent().get_points()
   727                 for i, t in enumerate(self.Legend.get_texts()):
   770                         rect = wx.Rect(x0, height - y1, x1 - x0, y1 - y0)
   728                     (x0, y0), (x1, y1) = t.get_window_extent().get_points()
   771                         if rect.InsideXY(x, y):
   729                     rect = wx.Rect(x0, height - y1, x1 - x0, y1 - y0)
   772                             item_idx = i
   730                     if rect.InsideXY(x, y):
   773                             break
   731                         item_idx = i
   774                     if item_idx is not None:
   732                         break
   775                         self.DoDragDrop(item_idx)
   733                 if item_idx is not None:
   776                         return
   734                     self.DoDragDrop(item_idx)
       
   735                     return
       
   736             event.Skip()
   777             event.Skip()
   737         
   778         
   738         def OnCanvasLeftUp(self, event):
   779         def OnCanvasButtonPressed(self, event):
       
   780             if not self.Is3DCanvas():
       
   781                 if event.button == 1:
       
   782                     self.HandleCursorMove(event)
       
   783                 elif event.button == 2 and self.GraphType == GRAPH_PARALLEL:
       
   784                     width, height = self.Canvas.GetSize()
       
   785                     start_tick, end_tick = self.ParentWindow.GetRange()
       
   786                     self.MouseStartPos = wx.Point(event.x, height - event.y)
       
   787                     self.StartCursorTick = start_tick
       
   788         
       
   789         def OnCanvasButtonReleased(self, event):
   739             if self.ParentWindow.IsDragging():
   790             if self.ParentWindow.IsDragging():
   740                 width, height = self.Canvas.GetSize()
   791                 width, height = self.Canvas.GetSize()
   741                 xw, yw = self.GetPosition()
   792                 xw, yw = self.GetPosition()
   742                 self.ParentWindow.StopDragNDrop(
   793                 self.ParentWindow.StopDragNDrop(
   743                     self.Items[0].GetVariable(),
   794                     self.Items[0].GetVariable(),
   744                     xw + event.x, 
   795                     xw + event.x, 
   745                     yw + height - event.y)
   796                     yw + height - event.y)
   746         
   797             else:
   747         def DoDragDrop(self, item_idx):
   798                 self.MouseStartPos = None
   748             self.ParentWindow.ResetCursorTickRatio()
   799                 self.StartCursorTick = None
   749             data = wx.TextDataObject(str((self.Items[item_idx].GetVariable(), "debug", "move")))
       
   750             dragSource = wx.DropSource(self.Canvas)
       
   751             dragSource.SetData(data)
       
   752             dragSource.DoDragDrop()
       
   753         
       
   754         def OnAxesMotion(self, event):
       
   755             if self.Is3DCanvas():
       
   756                 current_time = gettime()
       
   757                 if current_time - self.LastMotionTime > REFRESH_PERIOD:
       
   758                     self.LastMotionTime = current_time
       
   759                     Axes3D._on_move(self.Axes, event)
       
   760         
   800         
   761         def OnCanvasMotion(self, event):
   801         def OnCanvasMotion(self, event):
   762             if self.ParentWindow.IsDragging():
   802             if self.ParentWindow.IsDragging():
   763                 width, height = self.Canvas.GetSize()
   803                 width, height = self.Canvas.GetSize()
   764                 xw, yw = self.GetPosition()
   804                 xw, yw = self.GetPosition()
   765                 self.ParentWindow.MoveDragNDrop(
   805                 self.ParentWindow.MoveDragNDrop(
   766                     xw + event.x, 
   806                     xw + event.x, 
   767                     yw + height - event.y)
   807                     yw + height - event.y)
   768             elif not self.Is3DCanvas():
   808             elif not self.Is3DCanvas():
   769                 if event.inaxes == self.Axes:
   809                 if event.button == 1:
       
   810                     if event.inaxes == self.Axes:
       
   811                         if self.MouseStartPos is not None:
       
   812                             self.HandleCursorMove(event)
       
   813                     elif self.MouseStartPos is not None:
       
   814                         xw, yw = self.GetPosition()
       
   815                         width, height = self.Canvas.GetSize()
       
   816                         self.ParentWindow.StartDragNDrop(self, 
       
   817                             event.x + xw, height - event.y + yw, 
       
   818                             self.MouseStartPos.x + xw, self.MouseStartPos.y + yw)
       
   819                 elif event.button == 2 and self.GraphType == GRAPH_PARALLEL:
   770                     start_tick, end_tick = self.ParentWindow.GetRange()
   820                     start_tick, end_tick = self.ParentWindow.GetRange()
   771                     cursor_tick_ratio = None
   821                     rect = self.GetAxesBoundingBox()
   772                     if self.GraphType == GRAPH_ORTHOGONAL:
   822                     self.ParentWindow.SetCanvasPosition(
   773                         x_data = self.Items[0].GetData(start_tick, end_tick)
   823                         self.StartCursorTick + (self.MouseStartPos.x - event.x) *
   774                         y_data = self.Items[1].GetData(start_tick, end_tick)
   824                         (end_tick - start_tick) / rect.width)
   775                         if len(x_data) > 0 and len(y_data) > 0:
   825         
   776                             length = min(len(x_data), len(y_data))
   826         def OnCanvasDragging(self, x, y, refresh=True):
   777                             d = numpy.sqrt((x_data[:length,1]-event.xdata) ** 2 + (y_data[:length,1]-event.ydata) ** 2)
   827             width, height = self.Canvas.GetSize()
   778                             cursor_tick_ratio = float(x_data[numpy.argmin(d), 0] - start_tick) / (end_tick - start_tick)
   828             bbox = self.Canvas.GetAxesBoundingBox()
   779                     else:
   829             if bbox.InsideXY(x, y):
   780                         data = self.Items[0].GetData(start_tick, end_tick)
   830                 rect = wx.Rect(bbox.x, bbox.y, bbox.width / 2, bbox.height)
   781                         if len(data) > 0:
   831                 if rect.InsideXY(x, y):
   782                             x_min, x_max = self.Axes.get_xlim()
   832                     self.Canvas.SetHighlight(HIGHLIGHT_LEFT)
   783                             cursor_tick_ratio = float(event.xdata - x_min) / (x_max - x_min)
       
   784                     if cursor_tick_ratio is not None:
       
   785                         self.ParentWindow.SetCursorTickRatio(cursor_tick_ratio)
       
   786                 else:
   833                 else:
   787                     self.ParentWindow.ResetCursorTickRatio()
   834                     self.Canvas.SetHighlight(HIGHLIGHT_RIGHT)
       
   835             elif y < height / 2:
       
   836                 self.Canvas.SetHighlight(HIGHLIGHT_BEFORE)
       
   837             else:
       
   838                 self.Canvas.SetHighlight(HIGHLIGHT_AFTER)
       
   839             if refresh:
       
   840                 self.ParentWindow.ForceRefresh()
       
   841         
       
   842         def OnCanvasLeave(self, refresh=True):
       
   843             self.Canvas.SetHighlight(HIGHLIGHT_NONE)
       
   844             if refresh:
       
   845                 self.ParentWindow.ForceRefresh()
       
   846         
       
   847         def OnCanvasScroll(self, event):
       
   848             if event.inaxes is not None:
       
   849                 if self.GraphType == GRAPH_ORTHOGONAL:
       
   850                     start_tick, end_tick = self.ParentWindow.GetRange()
       
   851                     tick = (start_tick + end_tick) / 2.
       
   852                 else:
       
   853                     tick = event.xdata
       
   854                 self.ParentWindow.ChangeRange(int(-event.step) / 3, tick)
       
   855         
       
   856         def HandleCursorMove(self, event):
       
   857             start_tick, end_tick = self.ParentWindow.GetRange()
       
   858             cursor_tick = None
       
   859             if self.GraphType == GRAPH_ORTHOGONAL:
       
   860                 x_data = self.Items[0].GetData(start_tick, end_tick)
       
   861                 y_data = self.Items[1].GetData(start_tick, end_tick)
       
   862                 if len(x_data) > 0 and len(y_data) > 0:
       
   863                     length = min(len(x_data), len(y_data))
       
   864                     d = numpy.sqrt((x_data[:length,1]-event.xdata) ** 2 + (y_data[:length,1]-event.ydata) ** 2)
       
   865                     cursor_tick = x_data[numpy.argmin(d), 0]
       
   866             else:
       
   867                 data = self.Items[0].GetData(start_tick, end_tick)
       
   868                 if len(data) > 0:
       
   869                     cursor_tick = data[numpy.argmin(numpy.abs(data[:,0] - event.xdata)), 0]
       
   870             if cursor_tick is not None:
       
   871                 self.ParentWindow.SetCursorTick(cursor_tick)
       
   872         
       
   873         def DoDragDrop(self, item_idx):
       
   874             data = wx.TextDataObject(str((self.Items[item_idx].GetVariable(), "debug", "move")))
       
   875             dragSource = wx.DropSource(self.Canvas)
       
   876             dragSource.SetData(data)
       
   877             dragSource.DoDragDrop()
       
   878         
       
   879         def OnAxesMotion(self, event):
       
   880             if self.Is3DCanvas():
       
   881                 current_time = gettime()
       
   882                 if current_time - self.LastMotionTime > REFRESH_PERIOD:
       
   883                     self.LastMotionTime = current_time
       
   884                     Axes3D._on_move(self.Axes, event)
   788         
   885         
   789         def OnSplitButton(self, event):
   886         def OnSplitButton(self, event):
   790             if len(self.Items) == 2 or self.GraphType == GRAPH_ORTHOGONAL:
   887             if len(self.Items) == 2 or self.GraphType == GRAPH_ORTHOGONAL:
   791                 wx.CallAfter(self.ParentWindow.SplitGraphs, self)
   888                 wx.CallAfter(self.ParentWindow.SplitGraphs, self)
   792             else:
   889             else:
   793                 menu = wx.Menu(title='')
   890                 menu = wx.Menu(title='')
   794                 for item in self.Items:
   891                 for item in self.Items:
   795                     new_id = wx.NewId()
   892                     new_id = wx.NewId()
   796                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   893                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   797                         text=item.GetVariable(self.VariableNameMask))
   894                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   798                     self.Bind(wx.EVT_MENU, 
   895                     self.Bind(wx.EVT_MENU, 
   799                         self.GetSplitGraphMenuFunction(item),
   896                         self.GetSplitGraphMenuFunction(item),
   800                         id=new_id)
   897                         id=new_id)
   801                 
   898                 
   802                 new_id = wx.NewId()
   899                 new_id = wx.NewId()
   814                 self.LastMotionTime = gettime()
   911                 self.LastMotionTime = gettime()
   815                 setattr(self.Axes, "_on_move", self.OnAxesMotion)
   912                 setattr(self.Axes, "_on_move", self.OnAxesMotion)
   816                 self.Axes.mouse_init()
   913                 self.Axes.mouse_init()
   817             else:
   914             else:
   818                 self.Axes = self.Figure.gca()
   915                 self.Axes = self.Figure.gca()
       
   916                 self.Figure.subplotpars.update(top=0.95)
   819                 if self.GraphType == GRAPH_ORTHOGONAL:
   917                 if self.GraphType == GRAPH_ORTHOGONAL:
   820                     self.Figure.subplotpars.update(bottom=0.15)
   918                     self.Figure.subplotpars.update(bottom=0.15)
   821             self.Axes.set_title('.'.join(self.VariableNameMask))
       
   822             self.Plots = []
   919             self.Plots = []
   823             self.VLine = None
   920             self.VLine = None
   824             self.HLine = None
   921             self.HLine = None
   825             self.TickLabel = None
   922             self.Legend = None
       
   923             self.Labels = []
       
   924             if self.GraphType == GRAPH_PARALLEL:
       
   925                 num_item = len(self.Items)
       
   926                 for idx in xrange(num_item):
       
   927                     self.Labels.append(
       
   928                         self.Axes.text(0.95, 0.05 + (num_item - idx - 1) * 0.1, 
       
   929                                        "", size = 'large', 
       
   930                                        horizontalalignment='right',
       
   931                                        color = color_cycle[idx % len(color_cycle)],
       
   932                                        transform = self.Axes.transAxes))
   826             self.SplitButton.Enable(len(self.Items) > 1)
   933             self.SplitButton.Enable(len(self.Items) > 1)
   827         
   934         
   828         def AddItem(self, item):
   935         def AddItem(self, item):
   829             DebugVariableViewer.AddItem(self, item)
   936             DebugVariableViewer.AddItem(self, item)
   830             self.ResetGraphics()
   937             self.ResetGraphics()
   831             
   938             
   832         def RemoveItem(self, item):
   939         def RemoveItem(self, item):
   833             DebugVariableViewer.RemoveItem(self, item)
   940             DebugVariableViewer.RemoveItem(self, item)
   834             if not self.IsEmpty():
   941             if not self.IsEmpty():
   835                 self.ResetVariableNameMask()
       
   836                 self.ResetGraphics()
   942                 self.ResetGraphics()
   837         
   943         
   838         def UnregisterObsoleteData(self):
   944         def UnregisterObsoleteData(self):
   839             DebugVariableViewer.UnregisterObsoleteData(self)
   945             DebugVariableViewer.UnregisterObsoleteData(self)
   840             if not self.IsEmpty():
   946             if not self.IsEmpty():
   841                 self.ResetVariableNameMask()
       
   842                 self.ResetGraphics()
   947                 self.ResetGraphics()
   843         
   948         
   844         def Is3DCanvas(self):
   949         def Is3DCanvas(self):
   845             return self.GraphType == GRAPH_ORTHOGONAL and len(self.Items) == 3
   950             return self.GraphType == GRAPH_ORTHOGONAL and len(self.Items) == 3
   846         
   951         
   881                         y_center = 0.5
   986                         y_center = 0.5
   882                         y_range = 1.0
   987                         y_range = 1.0
   883                     x_min, x_max = start_tick, end_tick
   988                     x_min, x_max = start_tick, end_tick
   884                     y_min, y_max = y_center - y_range * 0.55, y_center + y_range * 0.55
   989                     y_min, y_max = y_center - y_range * 0.55, y_center + y_range * 0.55
   885                     
   990                     
   886                     if self.CursorTick is not None:
   991                     if self.CursorTick is not None and start_tick <= self.CursorTick <= end_tick:
   887                         if self.VLine is None:
   992                         if self.VLine is None:
   888                             self.VLine = self.Axes.axvline(self.CursorTick, color='r')
   993                             self.VLine = self.Axes.axvline(self.CursorTick, color='r')
   889                         else:
   994                         else:
   890                             self.VLine.set_xdata((self.CursorTick, self.CursorTick))
   995                             self.VLine.set_xdata((self.CursorTick, self.CursorTick))
   891                         self.VLine.set_visible(True)
   996                         self.VLine.set_visible(True)
   892                         tick_label = self.ParentWindow.GetTickLabel(self.CursorTick)
       
   893                         if self.TickLabel is None:
       
   894                             self.TickLabel = self.Axes.text(0.5, 0.05, tick_label, 
       
   895                                 size = 'small', transform = self.Axes.transAxes)
       
   896                         else:
       
   897                             self.TickLabel.set_text(tick_label)
       
   898                     else:
   997                     else:
   899                         if self.VLine is not None:
   998                         if self.VLine is not None:
   900                             self.VLine.set_visible(False)
   999                             self.VLine.set_visible(False)
   901                         if self.TickLabel is not None:
       
   902                             self.TickLabel.set_text("")
       
   903                 else:
  1000                 else:
   904                     min_start_tick = reduce(max, [item.GetData()[0, 0] 
  1001                     min_start_tick = reduce(max, [item.GetData()[0, 0] 
   905                                                   for item in self.Items
  1002                                                   for item in self.Items
   906                                                   if len(item.GetData()) > 0], 0)
  1003                                                   if len(item.GetData()) > 0], 0)
   907                     start_tick = max(start_tick, min_start_tick)
  1004                     start_tick = max(start_tick, min_start_tick)
   923                             else:
  1020                             else:
   924                                 self.Plots[0].set_data(
  1021                                 self.Plots[0].set_data(
   925                                     x_data[:, 1][:length], 
  1022                                     x_data[:, 1][:length], 
   926                                     y_data[:, 1][:length])
  1023                                     y_data[:, 1][:length])
   927                         
  1024                         
   928                         if self.CursorTick is not None:
  1025                         if self.CursorTick is not None and start_tick <= self.CursorTick <= end_tick:
   929                             if self.VLine is None:
  1026                             if self.VLine is None:
   930                                 self.VLine = self.Axes.axvline(x_cursor, color='r')
  1027                                 self.VLine = self.Axes.axvline(x_cursor, color='r')
   931                             else:
  1028                             else:
   932                                 self.VLine.set_xdata((x_cursor, x_cursor))
  1029                                 self.VLine.set_xdata((x_cursor, x_cursor))
   933                             if self.HLine is None:
  1030                             if self.HLine is None:
   934                                 self.HLine = self.Axes.axhline(y_cursor, color='r')
  1031                                 self.HLine = self.Axes.axhline(y_cursor, color='r')
   935                             else:
  1032                             else:
   936                                 self.HLine.set_ydata((y_cursor, y_cursor))
  1033                                 self.HLine.set_ydata((y_cursor, y_cursor))
   937                             self.VLine.set_visible(True)
  1034                             self.VLine.set_visible(True)
   938                             self.HLine.set_visible(True)
  1035                             self.HLine.set_visible(True)
   939                             tick_label = self.ParentWindow.GetTickLabel(self.CursorTick)
       
   940                             if self.TickLabel is None:
       
   941                                 self.TickLabel = self.Axes.text(0.05, 0.90, tick_label, 
       
   942                                     size = 'small', transform = self.Axes.transAxes)
       
   943                             else:
       
   944                                 self.TickLabel.set_text(tick_label)
       
   945                         else:
  1036                         else:
   946                             if self.VLine is not None:
  1037                             if self.VLine is not None:
   947                                 self.VLine.set_visible(False)
  1038                                 self.VLine.set_visible(False)
   948                             if self.HLine is not None:
  1039                             if self.HLine is not None:
   949                                 self.HLine.set_visible(False)
  1040                                 self.HLine.set_visible(False)
   950                             if self.TickLabel is not None:
       
   951                                 self.TickLabel.set_text("")
       
   952                     else:
  1041                     else:
   953                         while len(self.Axes.lines) > 0:
  1042                         while len(self.Axes.lines) > 0:
   954                             self.Axes.lines.pop()
  1043                             self.Axes.lines.pop()
   955                         z_data, z_min, z_max = OrthogonalData(self.Items[2], start_tick, end_tick)
  1044                         z_data, z_min, z_max = OrthogonalData(self.Items[2], start_tick, end_tick)
   956                         if self.CursorTick is not None:
  1045                         if self.CursorTick is not None:
   959                             length = min(length, len(z_data))
  1048                             length = min(length, len(z_data))
   960                             self.Axes.plot(x_data[:, 1][:length],
  1049                             self.Axes.plot(x_data[:, 1][:length],
   961                                            y_data[:, 1][:length],
  1050                                            y_data[:, 1][:length],
   962                                            zs = z_data[:, 1][:length])
  1051                                            zs = z_data[:, 1][:length])
   963                         self.Axes.set_zlim(z_min, z_max)
  1052                         self.Axes.set_zlim(z_min, z_max)
   964                         if self.CursorTick is not None:
  1053                         if self.CursorTick is not None and start_tick <= self.CursorTick <= end_tick:
   965                             for kwargs in [{"xs": numpy.array([x_min, x_max])},
  1054                             for kwargs in [{"xs": numpy.array([x_min, x_max])},
   966                                            {"ys": numpy.array([y_min, y_max])},
  1055                                            {"ys": numpy.array([y_min, y_max])},
   967                                            {"zs": numpy.array([z_min, z_max])}]:
  1056                                            {"zs": numpy.array([z_min, z_max])}]:
   968                                 for param, value in [("xs", numpy.array([x_cursor, x_cursor])),
  1057                                 for param, value in [("xs", numpy.array([x_cursor, x_cursor])),
   969                                                      ("ys", numpy.array([y_cursor, y_cursor])),
  1058                                                      ("ys", numpy.array([y_cursor, y_cursor])),
   973                                 self.Axes.plot(**kwargs)
  1062                                 self.Axes.plot(**kwargs)
   974                     
  1063                     
   975                 self.Axes.set_xlim(x_min, x_max)
  1064                 self.Axes.set_xlim(x_min, x_max)
   976                 self.Axes.set_ylim(y_min, y_max)
  1065                 self.Axes.set_ylim(y_min, y_max)
   977             
  1066             
       
  1067             variable_name_mask = self.ParentWindow.GetVariableNameMask()
   978             if self.CursorTick is not None:
  1068             if self.CursorTick is not None:
   979                 values, forced = apply(zip, [item.GetValue(self.CursorTick) for item in self.Items])
  1069                 values, forced = apply(zip, [item.GetValue(self.CursorTick) for item in self.Items])
   980             else:
  1070             else:
   981                 values, forced = apply(zip, [(item.GetValue(), item.IsForced()) for item in self.Items])
  1071                 values, forced = apply(zip, [(item.GetValue(), item.IsForced()) for item in self.Items])
   982             names = [item.GetVariable(self.VariableNameMask) for item in self.Items]
  1072             names = [item.GetVariable(variable_name_mask) for item in self.Items]
   983             labels = map(lambda x: "%s: %s" % x, zip(names, values))
  1073             labels = map(lambda x: "%s: %s" % x, zip(names, values))
   984             colors = map(lambda x: {True: 'b', False: 'k'}[x], forced)
  1074             colors = map(lambda x: {True: 'b', False: 'k'}[x], forced)
   985             if self.GraphType == GRAPH_PARALLEL:
  1075             if self.GraphType == GRAPH_PARALLEL:
   986                 self.Legend = self.Axes.legend(self.Plots, labels, 
  1076                 if self.Legend is None:
   987                     loc="upper left", frameon=False,
  1077                     self.Legend = self.Axes.legend(self.Plots, labels, 
   988                     prop={'size':'small'})
  1078                         loc="upper left", frameon=False, prop={'size':'small'}, 
       
  1079                         title = '.'.join(variable_name_mask))
       
  1080                     self.Legend.get_title().set_fontsize('small')
   989                 for t, color in zip(self.Legend.get_texts(), colors):
  1081                 for t, color in zip(self.Legend.get_texts(), colors):
   990                     t.set_color(color)
  1082                     t.set_color(color)
       
  1083                 for label, value in zip(self.Labels, values):
       
  1084                     label.set_text(value)
   991             else:
  1085             else:
   992                 self.Legend = None
  1086                 self.Legend = None
   993                 self.Axes.set_xlabel(labels[0], fontdict={'size':'small','color':colors[0]})
  1087                 self.Axes.set_xlabel(labels[0], fontdict={'size':'small','color':colors[0]})
   994                 self.Axes.set_ylabel(labels[1], fontdict={'size':'small','color':colors[1]})
  1088                 self.Axes.set_ylabel(labels[1], fontdict={'size':'small','color':colors[1]})
   995                 if len(labels) > 2:
  1089                 if len(labels) > 2:
  1006     
  1100     
  1007 class DebugVariablePanel(wx.Panel, DebugViewer):
  1101 class DebugVariablePanel(wx.Panel, DebugViewer):
  1008     
  1102     
  1009     def __init__(self, parent, producer, window):
  1103     def __init__(self, parent, producer, window):
  1010         wx.Panel.__init__(self, parent, style=wx.SP_3D|wx.TAB_TRAVERSAL)
  1104         wx.Panel.__init__(self, parent, style=wx.SP_3D|wx.TAB_TRAVERSAL)
       
  1105         self.SetBackgroundColour(wx.WHITE)
  1011         
  1106         
  1012         self.ParentWindow = window
  1107         self.ParentWindow = window
  1013         
  1108         
  1014         DebugViewer.__init__(self, producer, True)
  1109         DebugViewer.__init__(self, producer, True)
  1015         
  1110         
  1021             self.Ticks = numpy.array([])
  1116             self.Ticks = numpy.array([])
  1022             self.RangeValues = None
  1117             self.RangeValues = None
  1023             self.StartTick = 0
  1118             self.StartTick = 0
  1024             self.Fixed = False
  1119             self.Fixed = False
  1025             self.Force = False
  1120             self.Force = False
  1026             self.CursorTickRatio = None
  1121             self.CursorTick = None
  1027             self.DraggingAxesPanel = None
  1122             self.DraggingAxesPanel = None
  1028             self.DraggingAxesBoundingBox = None
  1123             self.DraggingAxesBoundingBox = None
  1029             self.DraggingAxesMousePos = None
  1124             self.DraggingAxesMousePos = None
       
  1125             self.VariableNameMask = None
  1030             
  1126             
  1031             self.GraphicPanels = []
  1127             self.GraphicPanels = []
  1032             
  1128             
  1033             graphics_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
  1129             graphics_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
  1034             main_sizer.AddSizer(graphics_button_sizer, border=5, flag=wx.GROW|wx.ALL)
  1130             main_sizer.AddSizer(graphics_button_sizer, border=5, flag=wx.GROW|wx.ALL)
  1065                   self.OnPositionChanging, self.CanvasPosition)
  1161                   self.OnPositionChanging, self.CanvasPosition)
  1066             self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEDOWN, 
  1162             self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEDOWN, 
  1067                   self.OnPositionChanging, self.CanvasPosition)
  1163                   self.OnPositionChanging, self.CanvasPosition)
  1068             main_sizer.AddWindow(self.CanvasPosition, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
  1164             main_sizer.AddWindow(self.CanvasPosition, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
  1069             
  1165             
       
  1166             self.TickSizer = wx.BoxSizer(wx.HORIZONTAL)
       
  1167             main_sizer.AddSizer(self.TickSizer, border=5, flag=wx.ALL|wx.GROW)
       
  1168             
       
  1169             self.TickLabel = wx.StaticText(self)
       
  1170             self.TickSizer.AddWindow(self.TickLabel, 1, border=5, flag=wx.RIGHT|wx.GROW)
       
  1171             
       
  1172             self.TickTimeLabel = wx.StaticText(self)
       
  1173             self.TickSizer.AddWindow(self.TickTimeLabel)
       
  1174             
  1070             self.GraphicsWindow = wx.ScrolledWindow(self, style=wx.HSCROLL|wx.VSCROLL)
  1175             self.GraphicsWindow = wx.ScrolledWindow(self, style=wx.HSCROLL|wx.VSCROLL)
       
  1176             self.GraphicsWindow.SetBackgroundColour(wx.WHITE)
  1071             self.GraphicsWindow.SetDropTarget(DebugVariableDropTarget(self))
  1177             self.GraphicsWindow.SetDropTarget(DebugVariableDropTarget(self))
  1072             self.GraphicsWindow.Bind(wx.EVT_SIZE, self.OnGraphicsWindowResize)
  1178             self.GraphicsWindow.Bind(wx.EVT_SIZE, self.OnGraphicsWindowResize)
  1073             main_sizer.AddWindow(self.GraphicsWindow, 1, flag=wx.GROW)
  1179             main_sizer.AddWindow(self.GraphicsWindow, 1, flag=wx.GROW)
  1074             
  1180             
  1075             self.GraphicsSizer = wx.BoxSizer(wx.VERTICAL)
  1181             self.GraphicsSizer = wx.BoxSizer(wx.VERTICAL)
  1165             if len(self.Ticks) == 0:
  1271             if len(self.Ticks) == 0:
  1166                 self.StartTick = tick 
  1272                 self.StartTick = tick 
  1167             self.Ticks = numpy.append(self.Ticks, [tick])
  1273             self.Ticks = numpy.append(self.Ticks, [tick])
  1168             if not self.Fixed or tick < self.StartTick + self.CurrentRange:
  1274             if not self.Fixed or tick < self.StartTick + self.CurrentRange:
  1169                 self.StartTick = max(self.StartTick, tick - self.CurrentRange)
  1275                 self.StartTick = max(self.StartTick, tick - self.CurrentRange)
  1170                 self.ResetCursorTick(False)
  1276             if self.Fixed and self.Ticks[-1] - self.Ticks[0] < self.CurrentRange:
       
  1277                 self.Force = True
  1171         DebugViewer.NewDataAvailable(self, tick, *args, **kwargs)
  1278         DebugViewer.NewDataAvailable(self, tick, *args, **kwargs)
  1172     
  1279     
  1173     def ForceRefresh(self):
  1280     def ForceRefresh(self):
  1174         self.Force = True
  1281         self.Force = True
  1175         wx.CallAfter(self.NewDataAvailable, None, True)
  1282         wx.CallAfter(self.NewDataAvailable, None, True)
  1181             self.GraphicsSizer.AddWindow(panel, flag=wx.GROW)
  1288             self.GraphicsSizer.AddWindow(panel, flag=wx.GROW)
  1182             
  1289             
  1183         self.GraphicsSizer.Layout()
  1290         self.GraphicsSizer.Layout()
  1184         self.RefreshGraphicsWindowScrollbars()
  1291         self.RefreshGraphicsWindowScrollbars()
  1185     
  1292     
  1186     def SetCursorTickRatio(self, cursor_tick_ratio):
  1293     def SetCanvasPosition(self, tick):
  1187         self.CursorTickRatio = cursor_tick_ratio
  1294         tick = max(self.Ticks[0], min(tick, self.Ticks[-1] - self.CurrentRange))
       
  1295         self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - tick))]
       
  1296         self.Fixed = True
       
  1297         self.RefreshCanvasPosition()
       
  1298         self.ForceRefresh()
       
  1299     
       
  1300     def SetCursorTick(self, cursor_tick):
       
  1301         self.CursorTick = cursor_tick
       
  1302         self.Fixed = True
  1188         self.ResetCursorTick() 
  1303         self.ResetCursorTick() 
  1189     
  1304     
  1190     def ResetCursorTickRatio(self):
  1305     def ResetCursorTick(self):
  1191         self.CursorTickRatio = None
  1306         self.CursorTick = None
  1192         self.ResetCursorTick()
  1307         self.ResetCursorTick()
  1193     
  1308     
  1194     def ResetCursorTick(self, force_refresh=True):
  1309     def ResetCursorTick(self):
  1195         if self.CursorTickRatio is not None and len(self.Ticks) > 0:
       
  1196             raw_tick = self.StartTick + self.CursorTickRatio * self.CurrentRange
       
  1197             cursor_tick = self.Ticks[numpy.argmin(abs(self.Ticks - raw_tick))]
       
  1198         else:
       
  1199             cursor_tick = None
       
  1200         for panel in self.GraphicPanels:
  1310         for panel in self.GraphicPanels:
  1201             if isinstance(panel, DebugVariableGraphic):
  1311             if isinstance(panel, DebugVariableGraphic):
  1202                 panel.SetCursorTick(cursor_tick)
  1312                 panel.SetCursorTick(self.CursorTick)
  1203         if force_refresh:
  1313         self.ForceRefresh()
  1204             self.ForceRefresh()
  1314     
  1205     
  1315     def StartDragNDrop(self, panel, x_mouse, y_mouse, x_mouse_start, y_mouse_start):
  1206     def GetTickLabel(self, tick):
       
  1207         label = "Tick: %d" % tick
       
  1208         if self.Ticktime > 0:
       
  1209             tick_duration = int(tick * self.Ticktime)
       
  1210             not_null = False
       
  1211             duration = ""
       
  1212             for value, format in [(tick_duration / DAY, "%dd"),
       
  1213                                   ((tick_duration % DAY) / HOUR, "%dh"),
       
  1214                                   ((tick_duration % HOUR) / MINUTE, "%dm"),
       
  1215                                   ((tick_duration % MINUTE) / SECOND, "%ds")]:
       
  1216                 
       
  1217                 if value > 0 or not_null:
       
  1218                     duration += format % value
       
  1219                     not_null = True
       
  1220             
       
  1221             duration += "%gms" % (float(tick_duration % SECOND) / MILLISECOND) 
       
  1222             label += "(%s)" % duration
       
  1223         return label
       
  1224     
       
  1225     def StartDragNDrop(self, panel, x_mouse, y_mouse):
       
  1226         self.DraggingAxesPanel = panel
  1316         self.DraggingAxesPanel = panel
  1227         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(absolute=True)
  1317         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(absolute=True)
  1228         self.DraggingAxesMousePos = wx.Point(
  1318         self.DraggingAxesMousePos = wx.Point(
  1229             x_mouse - self.DraggingAxesBoundingBox.x, 
  1319             x_mouse_start - self.DraggingAxesBoundingBox.x, 
  1230             y_mouse - self.DraggingAxesBoundingBox.y)
  1320             y_mouse_start - self.DraggingAxesBoundingBox.y)
  1231         self.ResetCursorTickRatio()
  1321         self.MoveDragNDrop(x_mouse, y_mouse)
  1232         
  1322         
  1233     def MoveDragNDrop(self, x_mouse, y_mouse):
  1323     def MoveDragNDrop(self, x_mouse, y_mouse):
  1234         self.DraggingAxesBoundingBox.x = x_mouse - self.DraggingAxesMousePos.x
  1324         self.DraggingAxesBoundingBox.x = x_mouse - self.DraggingAxesMousePos.x
  1235         self.DraggingAxesBoundingBox.y = y_mouse - self.DraggingAxesMousePos.y
  1325         self.DraggingAxesBoundingBox.y = y_mouse - self.DraggingAxesMousePos.y
       
  1326         for panel in self.GraphicPanels:
       
  1327             x, y = panel.GetPosition()
       
  1328             width, height = panel.Canvas.GetSize()
       
  1329             rect = wx.Rect(x, y, width, height)
       
  1330             if rect.InsideXY(x_mouse, y_mouse):
       
  1331                 panel.OnCanvasDragging(x_mouse - x, y_mouse - y, False)
       
  1332             else:
       
  1333                 panel.OnCanvasLeave(False)
  1236         self.ForceRefresh()
  1334         self.ForceRefresh()
  1237     
  1335     
  1238     def IsDragging(self):
  1336     def IsDragging(self):
  1239         return self.DraggingAxesPanel is not None
  1337         return self.DraggingAxesPanel is not None
  1240     
  1338     
  1250     def StopDragNDrop(self, variable, x_mouse, y_mouse):
  1348     def StopDragNDrop(self, variable, x_mouse, y_mouse):
  1251         self.DraggingAxesPanel = None
  1349         self.DraggingAxesPanel = None
  1252         self.DraggingAxesBoundingBox = None
  1350         self.DraggingAxesBoundingBox = None
  1253         self.DraggingAxesMousePos = None
  1351         self.DraggingAxesMousePos = None
  1254         for idx, panel in enumerate(self.GraphicPanels):
  1352         for idx, panel in enumerate(self.GraphicPanels):
       
  1353             panel.OnCanvasLeave(False)
  1255             xw, yw = panel.GetPosition()
  1354             xw, yw = panel.GetPosition()
  1256             width, height = panel.Canvas.GetSize()
  1355             width, height = panel.Canvas.GetSize()
  1257             bbox = wx.Rect(xw, yw, width, height)
  1356             bbox = wx.Rect(xw, yw, width, height)
  1258             if bbox.InsideXY(x_mouse, y_mouse):
  1357             if bbox.InsideXY(x_mouse, y_mouse):
  1259                 merge_type = GRAPH_PARALLEL
  1358                 merge_type = GRAPH_PARALLEL
  1289             for panel in self.GraphicPanels:
  1388             for panel in self.GraphicPanels:
  1290                 if isinstance(panel, DebugVariableGraphic):
  1389                 if isinstance(panel, DebugVariableGraphic):
  1291                     panel.Refresh(refresh_graphics)
  1390                     panel.Refresh(refresh_graphics)
  1292                 else:
  1391                 else:
  1293                     panel.Refresh()
  1392                     panel.Refresh()
  1294         
  1393             
       
  1394             if self.CursorTick is not None:
       
  1395                 tick = self.CursorTick
       
  1396             elif len(self.Ticks) > 0:
       
  1397                 tick = self.Ticks[-1]
       
  1398             else:
       
  1399                 tick = None
       
  1400             if tick is not None:
       
  1401                 self.TickLabel.SetLabel("Tick: %d" % tick)
       
  1402                 if self.Ticktime > 0:
       
  1403                     tick_duration = int(tick * self.Ticktime)
       
  1404                     not_null = False
       
  1405                     duration = ""
       
  1406                     for value, format in [(tick_duration / DAY, "%dd"),
       
  1407                                           ((tick_duration % DAY) / HOUR, "%dh"),
       
  1408                                           ((tick_duration % HOUR) / MINUTE, "%dm"),
       
  1409                                           ((tick_duration % MINUTE) / SECOND, "%ds")]:
       
  1410                         
       
  1411                         if value > 0 or not_null:
       
  1412                             duration += format % value
       
  1413                             not_null = True
       
  1414                     
       
  1415                     duration += "%gms" % (float(tick_duration % SECOND) / MILLISECOND) 
       
  1416                     self.TickTimeLabel.SetLabel("t: %s" % duration)
       
  1417                 else:
       
  1418                     self.TickTimeLabel.SetLabel("")
       
  1419             else:
       
  1420                 self.TickLabel.SetLabel("")
       
  1421                 self.TickTimeLabel.SetLabel("")
       
  1422             self.TickSizer.Layout()
  1295         else:
  1423         else:
  1296             self.Freeze()
  1424             self.Freeze()
  1297             
  1425             
  1298             if only_values:
  1426             if only_values:
  1299                 for col in xrange(self.Table.GetNumberCols()):
  1427                 for col in xrange(self.Table.GetNumberCols()):
  1318                     if panel.Canvas.HasCapture():
  1446                     if panel.Canvas.HasCapture():
  1319                         panel.Canvas.ReleaseMouse()
  1447                         panel.Canvas.ReleaseMouse()
  1320                     self.GraphicPanels.remove(panel)
  1448                     self.GraphicPanels.remove(panel)
  1321                     panel.Destroy()
  1449                     panel.Destroy()
  1322             
  1450             
       
  1451             self.ResetVariableNameMask()
  1323             self.RefreshGraphicsSizer()
  1452             self.RefreshGraphicsSizer()
  1324             self.ForceRefresh()
  1453             self.ForceRefresh()
  1325             
  1454             
  1326         else:
  1455         else:
  1327             items = [(idx, item) for idx, item in enumerate(self.Table.GetData())]
  1456             items = [(idx, item) for idx, item in enumerate(self.Table.GetData())]
  1344         if USE_MPL:
  1473         if USE_MPL:
  1345             self.Fixed = False
  1474             self.Fixed = False
  1346             for panel in self.GraphicPanels:
  1475             for panel in self.GraphicPanels:
  1347                 panel.Destroy()
  1476                 panel.Destroy()
  1348             self.GraphicPanels = []
  1477             self.GraphicPanels = []
       
  1478             self.ResetVariableNameMask()
  1349             self.RefreshGraphicsSizer()
  1479             self.RefreshGraphicsSizer()
  1350         else:
  1480         else:
  1351             self.Table.Empty()
  1481             self.Table.Empty()
  1352             self.Freeze()
  1482             self.Freeze()
  1353             self.Table.ResetView(self.VariablesGrid)
  1483             self.Table.ResetView(self.VariablesGrid)
  1427             self.PopupMenu(menu)
  1557             self.PopupMenu(menu)
  1428             
  1558             
  1429             menu.Destroy()
  1559             menu.Destroy()
  1430         event.Skip()
  1560         event.Skip()
  1431     
  1561     
       
  1562     def ChangeRange(self, dir, tick):
       
  1563         current_range = self.CurrentRange
       
  1564         current_range_idx = self.CanvasRange.GetSelection()
       
  1565         new_range_idx = max(0, min(current_range_idx + dir, len(self.RangeValues) - 1))
       
  1566         if new_range_idx != current_range_idx:
       
  1567             self.CanvasRange.SetSelection(new_range_idx)
       
  1568             if self.Ticktime == 0:
       
  1569                 self.CurrentRange = self.RangeValues[new_range_idx][1]
       
  1570             else:
       
  1571                 self.CurrentRange = self.RangeValues[new_range_idx][1] / self.Ticktime
       
  1572             if len(self.Ticks) > 0:
       
  1573                 new_start_tick = tick - (tick - self.StartTick) * self.CurrentRange / current_range 
       
  1574                 self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - new_start_tick))]
       
  1575                 self.Fixed = self.StartTick < self.Ticks[-1] - self.CurrentRange
       
  1576             self.ForceRefresh()
       
  1577     
  1432     def RefreshRange(self):
  1578     def RefreshRange(self):
  1433         if len(self.Ticks) > 0:
  1579         if len(self.Ticks) > 0:
  1434             if self.Fixed and self.Ticks[-1] - self.Ticks[0] < self.CurrentRange:
  1580             if self.Fixed and self.Ticks[-1] - self.Ticks[0] < self.CurrentRange:
  1435                 self.Fixed = False
  1581                 self.Fixed = False
  1436             if self.Fixed:
  1582             if self.Fixed:
  1456 
  1602 
  1457     def OnCurrentButton(self, event):
  1603     def OnCurrentButton(self, event):
  1458         if len(self.Ticks) > 0:
  1604         if len(self.Ticks) > 0:
  1459             self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange)
  1605             self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange)
  1460             self.Fixed = False
  1606             self.Fixed = False
  1461             self.ForceRefresh()
  1607             self.CursorTick = None
       
  1608             self.ResetCursorTick()
  1462         event.Skip()
  1609         event.Skip()
  1463     
  1610     
  1464     def CopyDataToClipboard(self, variables):
  1611     def CopyDataToClipboard(self, variables):
  1465         text = "tick;%s;\n" % ";".join([item.GetVariable() for item, data in variables])
  1612         text = "tick;%s;\n" % ";".join([item.GetVariable() for item, data in variables])
  1466         next_tick = NextTick(variables)
  1613         next_tick = NextTick(variables)
  1513     def GetViewerIndex(self, viewer):
  1660     def GetViewerIndex(self, viewer):
  1514         if viewer in self.GraphicPanels:
  1661         if viewer in self.GraphicPanels:
  1515             return self.GraphicPanels.index(viewer)
  1662             return self.GraphicPanels.index(viewer)
  1516         return None
  1663         return None
  1517     
  1664     
       
  1665     def ResetVariableNameMask(self):
       
  1666         items = []
       
  1667         for panel in self.GraphicPanels:
       
  1668             items.extend(panel.GetItems())
       
  1669         if len(items) > 1:
       
  1670             self.VariableNameMask = reduce(compute_mask,
       
  1671                 [item.GetVariable().split('.') for item in items])
       
  1672         elif len(items) > 0:
       
  1673             self.VariableNameMask = items[0].GetVariable().split('.')[:-1] + ['*']
       
  1674         else:
       
  1675             self.VariableNameMask = []
       
  1676             
       
  1677     def GetVariableNameMask(self):
       
  1678         return self.VariableNameMask
       
  1679     
  1518     def InsertValue(self, iec_path, idx = None, force=False):
  1680     def InsertValue(self, iec_path, idx = None, force=False):
  1519         if USE_MPL:
  1681         if USE_MPL:
  1520             for panel in self.GraphicPanels:
  1682             for panel in self.GraphicPanels:
  1521                 if panel.GetItem(iec_path) is not None:
  1683                 if panel.GetItem(iec_path) is not None:
  1522                     return
  1684                     return
  1533         if result is not None or force:
  1695         if result is not None or force:
  1534             
  1696             
  1535             if USE_MPL:
  1697             if USE_MPL:
  1536                 if item.IsNumVariable():
  1698                 if item.IsNumVariable():
  1537                     panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1699                     panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
       
  1700                     if self.CursorTick is not None:
       
  1701                         panel.SetCursorTick(self.CursorTick)
  1538                 else:
  1702                 else:
  1539                     panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1703                     panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1540                 if idx is not None:
  1704                 if idx is not None:
  1541                     self.GraphicPanels.insert(idx, panel)
  1705                     self.GraphicPanels.insert(idx, panel)
  1542                 else:
  1706                 else:
  1543                     self.GraphicPanels.append(panel)
  1707                     self.GraphicPanels.append(panel)
       
  1708                 self.ResetVariableNameMask()
  1544                 self.RefreshGraphicsSizer()
  1709                 self.RefreshGraphicsSizer()
  1545             else:
  1710             else:
  1546                 self.Table.InsertItem(idx, item)
  1711                 self.Table.InsertItem(idx, item)
  1547             
  1712             
  1548             self.ForceRefresh()
  1713             self.ForceRefresh()
  1564                     source_panel.Canvas.ReleaseMouse()
  1729                     source_panel.Canvas.ReleaseMouse()
  1565                 self.GraphicPanels.remove(source_panel)
  1730                 self.GraphicPanels.remove(source_panel)
  1566                 source_panel.Destroy()
  1731                 source_panel.Destroy()
  1567             
  1732             
  1568             panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1733             panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
       
  1734             if self.CursorTick is not None:
       
  1735                 panel.SetCursorTick(self.CursorTick)
  1569             self.GraphicPanels.insert(idx, panel)
  1736             self.GraphicPanels.insert(idx, panel)
       
  1737             self.ResetVariableNameMask()
  1570             self.RefreshGraphicsSizer()
  1738             self.RefreshGraphicsSizer()
  1571             self.ForceRefresh()
  1739             self.ForceRefresh()
  1572     
  1740     
  1573     def SplitGraphs(self, source_panel, item=None):
  1741     def SplitGraphs(self, source_panel, item=None):
  1574         source_idx = self.GetViewerIndex(source_panel)
  1742         source_idx = self.GetViewerIndex(source_panel)
  1578                 source_items = source_panel.GetItems()
  1746                 source_items = source_panel.GetItems()
  1579                 while len(source_items) > 1:
  1747                 while len(source_items) > 1:
  1580                     item = source_items.pop(-1)
  1748                     item = source_items.pop(-1)
  1581                     if item.IsNumVariable():
  1749                     if item.IsNumVariable():
  1582                         panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1750                         panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
       
  1751                         if self.CursorTick is not None:
       
  1752                             panel.SetCursorTick(self.CursorTick)
  1583                     else:
  1753                     else:
  1584                         panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1754                         panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1585                     self.GraphicPanels.insert(source_idx + 1, panel)
  1755                     self.GraphicPanels.insert(source_idx + 1, panel)
  1586                 if isinstance(source_panel, DebugVariableGraphic):
  1756                 if isinstance(source_panel, DebugVariableGraphic):
  1587                     source_panel.GraphType = GRAPH_PARALLEL
  1757                     source_panel.GraphType = GRAPH_PARALLEL
  1589                     
  1759                     
  1590             else:
  1760             else:
  1591                 source_panel.RemoveItem(item)
  1761                 source_panel.RemoveItem(item)
  1592                 if item.IsNumVariable():
  1762                 if item.IsNumVariable():
  1593                     panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1763                     panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
       
  1764                     if self.CursorTick is not None:
       
  1765                         panel.SetCursorTick(self.CursorTick)
  1594                 else:
  1766                 else:
  1595                     panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1767                     panel = DebugVariableText(self.GraphicsWindow, self, [item])
  1596                 self.GraphicPanels.insert(source_idx + 1, panel)
  1768                 self.GraphicPanels.insert(source_idx + 1, panel)
  1597             
  1769             
       
  1770             self.ResetVariableNameMask()
  1598             self.RefreshGraphicsSizer()
  1771             self.RefreshGraphicsSizer()
  1599             self.ForceRefresh()
  1772             self.ForceRefresh()
  1600     
  1773     
  1601     def MergeGraphs(self, source, target_idx, merge_type, force=False):
  1774     def MergeGraphs(self, source, target_idx, merge_type, force=False):
  1602         source_item = None
  1775         source_item = None
  1632                         
  1805                         
  1633                 target_panel.AddItem(source_item)
  1806                 target_panel.AddItem(source_item)
  1634                 target_panel.GraphType = merge_type
  1807                 target_panel.GraphType = merge_type
  1635                 target_panel.ResetGraphics()
  1808                 target_panel.ResetGraphics()
  1636                 
  1809                 
       
  1810                 self.ResetVariableNameMask()
  1637                 self.RefreshGraphicsSizer()
  1811                 self.RefreshGraphicsSizer()
  1638                 self.ForceRefresh()
  1812                 self.ForceRefresh()
  1639     
  1813     
  1640     def DeleteValue(self, source_panel, item=None):
  1814     def DeleteValue(self, source_panel, item=None):
  1641         source_idx = self.GetViewerIndex(source_panel)
  1815         source_idx = self.GetViewerIndex(source_panel)
  1643             
  1817             
  1644             if item is None:
  1818             if item is None:
  1645                 source_panel.Clear()
  1819                 source_panel.Clear()
  1646                 source_panel.Destroy()
  1820                 source_panel.Destroy()
  1647                 self.GraphicPanels.remove(source_panel)
  1821                 self.GraphicPanels.remove(source_panel)
       
  1822                 self.ResetVariableNameMask()
  1648                 self.RefreshGraphicsSizer()
  1823                 self.RefreshGraphicsSizer()
  1649             else:
  1824             else:
  1650                 source_panel.RemoveItem(item)
  1825                 source_panel.RemoveItem(item)
  1651                 if source_panel.IsEmpty():
  1826                 if source_panel.IsEmpty():
  1652                     source_panel.Destroy()
  1827                     source_panel.Destroy()
  1653                     self.GraphicPanels.remove(source_panel)
  1828                     self.GraphicPanels.remove(source_panel)
       
  1829                     self.ResetVariableNameMask()
  1654                     self.RefreshGraphicsSizer()
  1830                     self.RefreshGraphicsSizer()
  1655             self.ForceRefresh()
  1831             self.ForceRefresh()
  1656     
  1832     
  1657     def GetDebugVariables(self):
  1833     def GetDebugVariables(self):
  1658         if USE_MPL:
  1834         if USE_MPL:
  1676                     elif isinstance(variable, TupleType) and len(items) <= 3:
  1852                     elif isinstance(variable, TupleType) and len(items) <= 3:
  1677                         panel = DebugVariableGraphic(self.GraphicsWindow, self, items, GRAPH_ORTHOGONAL)
  1853                         panel = DebugVariableGraphic(self.GraphicsWindow, self, items, GRAPH_ORTHOGONAL)
  1678                     else:
  1854                     else:
  1679                         continue
  1855                         continue
  1680                     self.GraphicPanels.append(panel)
  1856                     self.GraphicPanels.append(panel)
       
  1857                     self.ResetVariableNameMask()
  1681                     self.RefreshGraphicsSizer()
  1858                     self.RefreshGraphicsSizer()
  1682                 else:
  1859                 else:
  1683                     self.InsertValue(variable, force=True)
  1860                     self.InsertValue(variable, force=True)
  1684             self.ForceRefresh()
  1861             self.ForceRefresh()
  1685         else:
  1862         else: