controls/DebugVariablePanel.py
changeset 925 5f9dd88a605b
parent 924 5f2cc382be8c
child 927 bd3e5b65e8be
equal deleted inserted replaced
924:5f2cc382be8c 925:5f9dd88a605b
    34 try:
    34 try:
    35     import matplotlib
    35     import matplotlib
    36     matplotlib.use('WX')
    36     matplotlib.use('WX')
    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
       
    40     from matplotlib.backends.backend_agg import FigureCanvasAgg
    39     from mpl_toolkits.mplot3d import Axes3D
    41     from mpl_toolkits.mplot3d import Axes3D
    40     USE_MPL = True
    42     USE_MPL = True
    41 except:
    43 except:
    42     USE_MPL = False
    44     USE_MPL = False
    43 
    45 
   328                     if len(values) > 2 and values[2] == "move":
   330                     if len(values) > 2 and values[2] == "move":
   329                         self.ParentWindow.MoveGraph(values[0], target_idx)
   331                         self.ParentWindow.MoveGraph(values[0], target_idx)
   330                     else:
   332                     else:
   331                         self.ParentWindow.InsertValue(values[0], target_idx, force=True)
   333                         self.ParentWindow.InsertValue(values[0], target_idx, force=True)
   332                 else:
   334                 else:
   333                     ax, ay, aw, ah = self.ParentControl.Axes.get_position().bounds
   335                     rect = self.ParentControl.GetAxesBoundingBox()
   334                     rect = wx.Rect(ax * width, height - (ay + ah) * height,
       
   335                                    aw * width, ah * height)
       
   336                     if rect.InsideXY(x, y):
   336                     if rect.InsideXY(x, y):
   337                         merge_rect = wx.Rect(ax * width, height - (ay + ah) * height,
   337                         merge_rect = wx.Rect(rect.x, rect.y, rect.width / 2., rect.height)
   338                                              aw * width / 2., ah * height)
       
   339                         if merge_rect.InsideXY(x, y):
   338                         if merge_rect.InsideXY(x, y):
   340                             merge_type = GRAPH_ORTHOGONAL
   339                             merge_type = GRAPH_ORTHOGONAL
   341                         wx.CallAfter(self.ParentWindow.MergeGraphs, values[0], target_idx, merge_type, force=True)
   340                         wx.CallAfter(self.ParentWindow.MergeGraphs, values[0], target_idx, merge_type, force=True)
   342                     else:
   341                     else:
   343                         if y > height / 2:
   342                         if y > height / 2:
   617             if xp == yp:
   616             if xp == yp:
   618                 mask.append(xp)
   617                 mask.append(xp)
   619             else:
   618             else:
   620                 mask.append("*")
   619                 mask.append("*")
   621         return mask
   620         return mask
   622         
   621     
       
   622     class DraggingFigureCanvas(FigureCanvas):
       
   623         
       
   624         def __init__(self, parent, window, *args, **kwargs):
       
   625             FigureCanvas.__init__(self, parent, *args, **kwargs)
       
   626             
       
   627             self.ParentWindow = window
       
   628             
       
   629         def draw(self, drawDC=None):
       
   630             FigureCanvasAgg.draw(self)
       
   631     
       
   632             self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
       
   633             if self.ParentWindow.IsDragging():
       
   634                 destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self.Parent)
       
   635                 if destBBox.width > 0 and destBBox.height > 0:
       
   636                     srcPanel = self.ParentWindow.DraggingAxesPanel
       
   637                     srcBBox = srcPanel.GetAxesBoundingBox()
       
   638                     
       
   639                     if destBBox.x == 0:
       
   640                         srcX = srcBBox.x + srcBBox.width - destBBox.width
       
   641                     else:
       
   642                         srcX = srcBBox.x
       
   643                     if destBBox.y == 0:
       
   644                         srcY = srcBBox.y + srcBBox.height - destBBox.height
       
   645                     else:
       
   646                         srcY = srcBBox.y
       
   647                     
       
   648                     srcBmp = _convert_agg_to_wx_bitmap(srcPanel.Canvas.get_renderer(), None)
       
   649                     srcDC = wx.MemoryDC()
       
   650                     srcDC.SelectObject(srcBmp)
       
   651                     
       
   652                     destDC = wx.MemoryDC()
       
   653                     destDC.SelectObject(self.bitmap)
       
   654                     
       
   655                     destDC.BeginDrawing()
       
   656                     destDC.Blit(destBBox.x, destBBox.y, 
       
   657                                 int(destBBox.width), int(destBBox.height), 
       
   658                                 srcDC, srcX, srcY)
       
   659                     destDC.EndDrawing()
       
   660                     
       
   661             self._isDrawn = True
       
   662             self.gui_repaint(drawDC=drawDC)
       
   663     
   623     class DebugVariableGraphic(DebugVariableViewer):
   664     class DebugVariableGraphic(DebugVariableViewer):
   624         
   665         
   625         def __init__(self, parent, window, items, graph_type):
   666         def __init__(self, parent, window, items, graph_type):
   626             DebugVariableViewer.__init__(self, parent, window, items)
   667             DebugVariableViewer.__init__(self, parent, window, items)
   627         
   668         
   631             self.ResetGraphics()
   672             self.ResetGraphics()
   632         
   673         
   633         def AddViewer(self):
   674         def AddViewer(self):
   634             self.Figure = matplotlib.figure.Figure(facecolor='w')
   675             self.Figure = matplotlib.figure.Figure(facecolor='w')
   635             
   676             
   636             self.Canvas = FigureCanvas(self, -1, self.Figure)
   677             self.Canvas = DraggingFigureCanvas(self, self.ParentWindow, -1, self.Figure)
   637             self.Canvas.SetMinSize(wx.Size(200, 200))
   678             self.Canvas.SetMinSize(wx.Size(200, 200))
   638             self.Canvas.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
   679             self.Canvas.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
       
   680             self.Canvas.Bind(wx.EVT_LEFT_DOWN, self.OnCanvasLeftDown)
   639             self.Canvas.mpl_connect('motion_notify_event', self.OnCanvasMotion)
   681             self.Canvas.mpl_connect('motion_notify_event', self.OnCanvasMotion)
   640             self.Canvas.Bind(wx.EVT_LEFT_DOWN, self.OnCanvasClick)
   682             self.Canvas.mpl_connect('button_release_event', self.OnCanvasLeftUp)
   641             
   683             
   642             self.MainSizer.AddWindow(self.Canvas, flag=wx.GROW)
   684             self.MainSizer.AddWindow(self.Canvas, flag=wx.GROW)
   643         
   685         
   644         def AddButtons(self):
   686         def AddButtons(self):
   645             button_sizer = wx.BoxSizer(wx.VERTICAL)
   687             button_sizer = wx.BoxSizer(wx.VERTICAL)
   657                       size=wx.Size(28, 28), style=wx.NO_BORDER)
   699                       size=wx.Size(28, 28), style=wx.NO_BORDER)
   658                 button.SetToolTipString(help)
   700                 button.SetToolTipString(help)
   659                 setattr(self, name, button)
   701                 setattr(self, name, button)
   660                 self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
   702                 self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
   661                 button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
   703                 button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
   662     
   704         
   663         def OnCanvasClick(self, event):
   705         def GetAxesBoundingBox(self, absolute=False):
       
   706             width, height = self.Canvas.GetSize()
       
   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:
       
   711                 xw, yw = self.GetPosition()
       
   712                 bbox.x += xw
       
   713                 bbox.y += yw
       
   714             return bbox
       
   715         
       
   716         def OnCanvasLeftDown(self, event):
   664             x, y = event.GetPosition()
   717             x, y = event.GetPosition()
   665             width, height = self.Canvas.GetSize()
   718             width, height = self.Canvas.GetSize()
   666             if len(self.Items) == 1:
   719             if len(self.Items) == 1:
   667                 ax, ay, aw, ah = self.Axes.get_position().bounds
   720                 rect = self.GetAxesBoundingBox()
   668                 rect = wx.Rect(ax * width, height - (ay + ah) * height,
       
   669                                aw * width, ah * height)
       
   670                 if rect.InsideXY(x, y):
   721                 if rect.InsideXY(x, y):
   671                     self.DoDragDrop(0)
   722                     xw, yw = self.GetPosition()
       
   723                     self.ParentWindow.StartDragNDrop(self, x + xw, y + yw)
   672                     return
   724                     return
   673             elif self.Legend is not None:
   725             elif self.Legend is not None:
   674                 item_idx = None
   726                 item_idx = None
   675                 for i, t in enumerate(self.Legend.get_texts()):
   727                 for i, t in enumerate(self.Legend.get_texts()):
   676                     (x0, y0), (x1, y1) = t.get_window_extent().get_points()
   728                     (x0, y0), (x1, y1) = t.get_window_extent().get_points()
   681                 if item_idx is not None:
   733                 if item_idx is not None:
   682                     self.DoDragDrop(item_idx)
   734                     self.DoDragDrop(item_idx)
   683                     return
   735                     return
   684             event.Skip()
   736             event.Skip()
   685         
   737         
       
   738         def OnCanvasLeftUp(self, event):
       
   739             if self.ParentWindow.IsDragging():
       
   740                 width, height = self.Canvas.GetSize()
       
   741                 xw, yw = self.GetPosition()
       
   742                 self.ParentWindow.StopDragNDrop(
       
   743                     self.Items[0].GetVariable(),
       
   744                     xw + event.x, 
       
   745                     yw + height - event.y)
       
   746         
   686         def DoDragDrop(self, item_idx):
   747         def DoDragDrop(self, item_idx):
   687             self.ParentWindow.ResetCursorTickRatio()
   748             self.ParentWindow.ResetCursorTickRatio()
   688             data = wx.TextDataObject(str((self.Items[item_idx].GetVariable(), "debug", "move")))
   749             data = wx.TextDataObject(str((self.Items[item_idx].GetVariable(), "debug", "move")))
   689             dragSource = wx.DropSource(self.Canvas)
   750             dragSource = wx.DropSource(self.Canvas)
   690             dragSource.SetData(data)
   751             dragSource.SetData(data)
   696                 if current_time - self.LastMotionTime > REFRESH_PERIOD:
   757                 if current_time - self.LastMotionTime > REFRESH_PERIOD:
   697                     self.LastMotionTime = current_time
   758                     self.LastMotionTime = current_time
   698                     Axes3D._on_move(self.Axes, event)
   759                     Axes3D._on_move(self.Axes, event)
   699         
   760         
   700         def OnCanvasMotion(self, event):
   761         def OnCanvasMotion(self, event):
   701             if not self.Is3DCanvas():
   762             if self.ParentWindow.IsDragging():
       
   763                 width, height = self.Canvas.GetSize()
       
   764                 xw, yw = self.GetPosition()
       
   765                 self.ParentWindow.MoveDragNDrop(
       
   766                     xw + event.x, 
       
   767                     yw + height - event.y)
       
   768             elif not self.Is3DCanvas():
   702                 if event.inaxes == self.Axes:
   769                 if event.inaxes == self.Axes:
   703                     start_tick, end_tick = self.ParentWindow.GetRange()
   770                     start_tick, end_tick = self.ParentWindow.GetRange()
   704                     cursor_tick_ratio = None
   771                     cursor_tick_ratio = None
   705                     if self.GraphType == GRAPH_ORTHOGONAL:
   772                     if self.GraphType == GRAPH_ORTHOGONAL:
   706                         x_data = self.Items[0].GetData(start_tick, end_tick)
   773                         x_data = self.Items[0].GetData(start_tick, end_tick)
   954             self.Ticks = numpy.array([])
  1021             self.Ticks = numpy.array([])
   955             self.RangeValues = None
  1022             self.RangeValues = None
   956             self.StartTick = 0
  1023             self.StartTick = 0
   957             self.Fixed = False
  1024             self.Fixed = False
   958             self.Force = False
  1025             self.Force = False
       
  1026             self.CursorTickRatio = None
       
  1027             self.DraggingAxesPanel = None
       
  1028             self.DraggingAxesBoundingBox = None
       
  1029             self.DraggingAxesMousePos = None
   959             
  1030             
   960             self.GraphicPanels = []
  1031             self.GraphicPanels = []
   961             
  1032             
   962             graphics_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
  1033             graphics_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
   963             main_sizer.AddSizer(graphics_button_sizer, border=5, flag=wx.GROW|wx.ALL)
  1034             main_sizer.AddSizer(graphics_button_sizer, border=5, flag=wx.GROW|wx.ALL)
  1003             
  1074             
  1004             self.GraphicsSizer = wx.BoxSizer(wx.VERTICAL)
  1075             self.GraphicsSizer = wx.BoxSizer(wx.VERTICAL)
  1005             self.GraphicsWindow.SetSizer(self.GraphicsSizer)
  1076             self.GraphicsWindow.SetSizer(self.GraphicsSizer)
  1006             
  1077             
  1007             self.RefreshCanvasRange()
  1078             self.RefreshCanvasRange()
  1008             self.CursorTickRatio = None
       
  1009             
  1079             
  1010         else:
  1080         else:
  1011             main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
  1081             main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
  1012             main_sizer.AddGrowableCol(0)
  1082             main_sizer.AddGrowableCol(0)
  1013             main_sizer.AddGrowableRow(1)
  1083             main_sizer.AddGrowableRow(1)
  1147                     not_null = True
  1217                     not_null = True
  1148             
  1218             
  1149             duration += "%gms" % (float(tick_duration % SECOND) / MILLISECOND) 
  1219             duration += "%gms" % (float(tick_duration % SECOND) / MILLISECOND) 
  1150             label += "(%s)" % duration
  1220             label += "(%s)" % duration
  1151         return label
  1221         return label
       
  1222     
       
  1223     def StartDragNDrop(self, panel, x_mouse, y_mouse):
       
  1224         self.DraggingAxesPanel = panel
       
  1225         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(absolute=True)
       
  1226         self.DraggingAxesMousePos = wx.Point(
       
  1227             x_mouse - self.DraggingAxesBoundingBox.x, 
       
  1228             y_mouse - self.DraggingAxesBoundingBox.y)
       
  1229         self.ResetCursorTickRatio()
       
  1230         
       
  1231     def MoveDragNDrop(self, x_mouse, y_mouse):
       
  1232         self.DraggingAxesBoundingBox.x = x_mouse - self.DraggingAxesMousePos.x
       
  1233         self.DraggingAxesBoundingBox.y = y_mouse - self.DraggingAxesMousePos.y
       
  1234         self.ForceRefresh()
       
  1235     
       
  1236     def IsDragging(self):
       
  1237         return self.DraggingAxesPanel is not None
       
  1238     
       
  1239     def GetDraggingAxesClippingRegion(self, panel):
       
  1240         x, y = panel.GetPosition()
       
  1241         width, height = panel.Canvas.GetSize()
       
  1242         bbox = wx.Rect(x, y, width, height)
       
  1243         bbox = bbox.Intersect(self.DraggingAxesBoundingBox)
       
  1244         bbox.x -= x
       
  1245         bbox.y -= y
       
  1246         return bbox
       
  1247     
       
  1248     def StopDragNDrop(self, variable, x_mouse, y_mouse):
       
  1249         self.DraggingAxesPanel = None
       
  1250         self.DraggingAxesBoundingBox = None
       
  1251         self.DraggingAxesMousePos = None
       
  1252         for idx, panel in enumerate(self.GraphicPanels):
       
  1253             xw, yw = panel.GetPosition()
       
  1254             width, height = panel.Canvas.GetSize()
       
  1255             bbox = wx.Rect(xw, yw, width, height)
       
  1256             if bbox.InsideXY(x_mouse, y_mouse):
       
  1257                 merge_type = GRAPH_PARALLEL
       
  1258                 if panel.Is3DCanvas():
       
  1259                     if y_mouse > yw + height / 2:
       
  1260                         idx += 1
       
  1261                     wx.CallAfter(self.MoveGraph, variable, idx)
       
  1262                     return
       
  1263                 else:
       
  1264                     rect = panel.GetAxesBoundingBox(True)
       
  1265                     if rect.InsideXY(x_mouse, y_mouse):
       
  1266                         merge_rect = wx.Rect(rect.x, rect.y, rect.width / 2., rect.height)
       
  1267                         if merge_rect.InsideXY(x_mouse, y_mouse):
       
  1268                             merge_type = GRAPH_ORTHOGONAL
       
  1269                         wx.CallAfter(self.MergeGraphs, variable, idx, merge_type, force=True)
       
  1270                     else:
       
  1271                         if y_mouse > yw + height / 2:
       
  1272                             idx += 1
       
  1273                         wx.CallAfter(self.MoveGraph, variable, idx)
       
  1274                 break
       
  1275         self.ForceRefresh()
  1152     
  1276     
  1153     def RefreshView(self, only_values=False):
  1277     def RefreshView(self, only_values=False):
  1154         if USE_MPL:
  1278         if USE_MPL:
  1155             self.RefreshCanvasPosition()
  1279             self.RefreshCanvasPosition()
  1156             
  1280