controls/DebugVariablePanel.py
changeset 943 da7f80e04a54
parent 938 ef1bfe848bf9
child 945 c1159acb0886
equal deleted inserted replaced
942:2ba9d7e3be72 943:da7f80e04a54
   304         self.ParentWindow = None
   304         self.ParentWindow = None
   305         self.ParentControl = None
   305         self.ParentControl = None
   306     
   306     
   307     def OnDragOver(self, x, y, d):
   307     def OnDragOver(self, x, y, d):
   308         if self.ParentControl is not None:
   308         if self.ParentControl is not None:
   309             self.ParentControl.OnCanvasMouseDragging(x, y)
   309             self.ParentControl.OnMouseDragging(x, y)
   310         else:
   310         else:
   311             self.ParentWindow.RefreshHighlight(x, y)
   311             self.ParentWindow.RefreshHighlight(x, y)
   312         return wx.TextDropTarget.OnDragOver(self, x, y, d)
   312         return wx.TextDropTarget.OnDragOver(self, x, y, d)
   313         
   313         
   314     def OnDropText(self, x, y, data):
   314     def OnDropText(self, x, y, data):
   330                 row = self.ParentControl.YToRow(y - self.ParentControl.GetColLabelSize())
   330                 row = self.ParentControl.YToRow(y - self.ParentControl.GetColLabelSize())
   331                 if row == wx.NOT_FOUND:
   331                 if row == wx.NOT_FOUND:
   332                     row = self.ParentWindow.Table.GetNumberRows()
   332                     row = self.ParentWindow.Table.GetNumberRows()
   333                 self.ParentWindow.InsertValue(values[0], row, force=True)
   333                 self.ParentWindow.InsertValue(values[0], row, force=True)
   334             elif self.ParentControl is not None:
   334             elif self.ParentControl is not None:
   335                 width, height = self.ParentControl.Canvas.GetSize()
   335                 width, height = self.ParentControl.GetSize()
   336                 target_idx = self.ParentControl.GetIndex()
   336                 target_idx = self.ParentControl.GetIndex()
   337                 merge_type = GRAPH_PARALLEL
   337                 merge_type = GRAPH_PARALLEL
   338                 if self.ParentControl.Is3DCanvas():
   338                 if self.ParentControl.Is3DCanvas():
   339                     if y > height / 2:
   339                     if y > height / 2:
   340                         target_idx += 1
   340                         target_idx += 1
   397         else:
   397         else:
   398             center = 0.5
   398             center = 0.5
   399             range = 1.0
   399             range = 1.0
   400         return data, center - range * 0.55, center + range * 0.55
   400         return data, center - range * 0.55, center + range * 0.55
   401     
   401     
   402     class DebugVariableViewer(wx.Panel):
   402     class DebugVariableViewer:
   403         
   403         
   404         def AddViewer(self):
   404         def __init__(self, window, items=[]):
   405             pass
       
   406         
       
   407         def AddButtons(self):
       
   408             pass
       
   409         
       
   410         def __init__(self, parent, window, items=[]):
       
   411             wx.Panel.__init__(self, parent)
       
   412             self.SetBackgroundColour(wx.WHITE)
       
   413             self.SetDropTarget(DebugVariableDropTarget(window, self))
       
   414             
       
   415             self.ParentWindow = window
   405             self.ParentWindow = window
   416             self.Items = items
   406             self.Items = items
   417             
   407             
       
   408             self.Highlight = HIGHLIGHT_NONE
       
   409             self.Buttons = []
       
   410         
   418         def __del__(self):
   411         def __del__(self):
   419             self.ParentWindow = None
   412             self.ParentWindow = None
   420             
   413         
   421         def GetIndex(self):
   414         def GetIndex(self):
   422             return self.ParentWindow.GetViewerIndex(self)
   415             return self.ParentWindow.GetViewerIndex(self)
   423         
   416         
   424         def GetItem(self, variable):
   417         def GetItem(self, variable):
   425             for item in self.Items:
   418             for item in self.Items:
   465             
   458             
   466         def ResetData(self):
   459         def ResetData(self):
   467             for item in self.Items:
   460             for item in self.Items:
   468                 item.ResetData()
   461                 item.ResetData()
   469         
   462         
   470         def Refresh(self):
   463         def RefreshViewer(self):
   471             pass
   464             pass
   472     
   465         
   473         def OnForceButton(self, event):
   466         def SetHighlight(self, highlight):
   474             if len(self.Items) == 1:
   467             if self.Highlight != highlight:
   475                 wx.CallAfter(self.ForceValue, self.Items[0])
   468                 self.Highlight = highlight
   476             else:
   469                 return True
   477                 menu = wx.Menu(title='')
   470             return False
   478                 for item in self.Items:
   471         
   479                     new_id = wx.NewId()
   472         def GetButtons(self):
   480                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   473             return self.Buttons
   481                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   474         
   482                     self.Bind(wx.EVT_MENU, 
   475         def HandleButtons(self, x, y):
   483                         self.GetForceVariableMenuFunction(item),
   476             for button in self.GetButtons():
   484                         id=new_id)
   477                 if button.HitTest(x, y):
   485                 self.PopupMenu(menu)
   478                     button.ProcessCallback()
       
   479                     return True
       
   480             return False
       
   481         
       
   482         def IsOverButton(self, x, y):
       
   483             for button in self.GetButtons():
       
   484                 if button.HitTest(x, y):
       
   485                     return True
       
   486             return False
       
   487         
       
   488         def ShowButtons(self, show):
       
   489             for button in self.Buttons:
       
   490                 if show:
       
   491                     button.Show()
       
   492                 else:
       
   493                     button.Hide()
       
   494             self.RefreshButtonsState()
       
   495             self.ParentWindow.ForceRefresh()
       
   496         
       
   497         def RefreshButtonsState(self, refresh_positions=False):
       
   498             if self:
       
   499                 width, height = self.GetSize()
       
   500                 if refresh_positions:
       
   501                     offset = 0
       
   502                     buttons = self.Buttons[:]
       
   503                     buttons.reverse()
       
   504                     for button in buttons:
       
   505                         if button.IsShown() and button.IsEnabled():
       
   506                             w, h = button.GetSize()
       
   507                             button.SetPosition(width - 5 - w - offset, 5)
       
   508                             offset += w + 2
       
   509                     self.ParentWindow.ForceRefresh()
       
   510         
       
   511         def DrawCommonElements(self, dc, buttons=None):
       
   512             width, height = self.GetSize()
       
   513             
       
   514             dc.SetPen(HIGHLIGHT_DROP_PEN)
       
   515             dc.SetBrush(HIGHLIGHT_DROP_BRUSH)
       
   516             if self.Highlight in [HIGHLIGHT_BEFORE]:
       
   517                 dc.DrawLine(0, 1, width - 1, 1)
       
   518             elif self.Highlight in [HIGHLIGHT_AFTER]:
       
   519                 dc.DrawLine(0, height - 1, width - 1, height - 1)
       
   520             
       
   521             if buttons is None:
       
   522                 buttons = self.Buttons
       
   523             for button in buttons:
       
   524                 button.Draw(dc)
       
   525                 
       
   526             if self.ParentWindow.IsDragging():
       
   527                 destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self)
       
   528                 srcPos = self.ParentWindow.GetDraggingAxesPosition(self)
       
   529                 if destBBox.width > 0 and destBBox.height > 0:
       
   530                     srcPanel = self.ParentWindow.DraggingAxesPanel
       
   531                     srcBBox = srcPanel.GetAxesBoundingBox()
       
   532                     
       
   533                     if destBBox.x == 0:
       
   534                         srcX = srcBBox.x - srcPos.x
       
   535                     else:
       
   536                         srcX = srcBBox.x
       
   537                     if destBBox.y == 0:
       
   538                         srcY = srcBBox.y - srcPos.y
       
   539                     else:
       
   540                         srcY = srcBBox.y
       
   541                     
       
   542                     srcBmp = _convert_agg_to_wx_bitmap(srcPanel.get_renderer(), None)
       
   543                     srcDC = wx.MemoryDC()
       
   544                     srcDC.SelectObject(srcBmp)
       
   545                     
       
   546                     dc.Blit(destBBox.x, destBBox.y, 
       
   547                             int(destBBox.width), int(destBBox.height), 
       
   548                             srcDC, srcX, srcY)
       
   549         
       
   550         def OnEnter(self, event):
       
   551             self.ShowButtons(True)
   486             event.Skip()
   552             event.Skip()
   487         
   553             
   488         def OnReleaseButton(self, event):
   554         def OnLeave(self, event):
   489             if len(self.Items) == 1:
   555             if self.Highlight != HIGHLIGHT_RESIZE or self.CanvasStartSize is None:
   490                 wx.CallAfter(self.ReleaseValue, self.Items[0])
   556                 x, y = event.GetPosition()
   491             else:
   557                 width, height = self.GetSize()
   492                 menu = wx.Menu(title='')
   558                 if (x <= 0 or x >= width - 1 or
   493                 for item in self.Items:
   559                     y <= 0 or y >= height - 1):
   494                     new_id = wx.NewId()
   560                     self.ShowButtons(False)
   495                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
       
   496                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
       
   497                     self.Bind(wx.EVT_MENU, 
       
   498                         self.GetReleaseVariableMenuFunction(item),
       
   499                         id=new_id)
       
   500                 
       
   501                 self.PopupMenu(menu)
       
   502             event.Skip()
   561             event.Skip()
   503         
   562         
   504         def OnDeleteButton(self, event):
   563         def OnCloseButton(self):
   505             if len(self.Items) == 1:
   564             wx.CallAfter(self.ParentWindow.DeleteValue, self)
   506                 wx.CallAfter(self.ParentWindow.DeleteValue, self, self.Items[0])
   565         
   507             else:
   566         def OnForceButton(self):
   508                 menu = wx.Menu(title='')
   567             wx.CallAfter(self.ForceValue, self.Items[0])
   509                 for item in self.Items:
   568             
   510                     new_id = wx.NewId()
   569         def OnReleaseButton(self):
   511                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, 
   570             wx.CallAfter(self.ReleaseValue, self.Items[0])
   512                         text=item.GetVariable(self.ParentWindow.GetVariableNameMask()))
   571         
   513                     self.Bind(wx.EVT_MENU, 
   572         def OnResizeWindow(self, event):
   514                         self.GetDeleteValueMenuFunction(item),
   573             wx.CallAfter(self.RefreshButtonsState, True)
   515                         id=new_id)
       
   516                 
       
   517                 new_id = wx.NewId()
       
   518                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("All"))
       
   519                 self.Bind(wx.EVT_MENU, self.OnDeleteAllValuesMenu, id=new_id)
       
   520                 
       
   521                 self.PopupMenu(menu)
       
   522             event.Skip()
   574             event.Skip()
   523     
   575         
   524         def GetForceVariableMenuFunction(self, item):
   576         def OnMouseDragging(self, x, y):
   525             def ForceVariableFunction(event):
   577             xw, yw = self.GetPosition()
   526                 self.ForceValue(item)
   578             self.ParentWindow.RefreshHighlight(x + xw, y + yw)
   527             return ForceVariableFunction
   579         
   528         
   580         def OnDragging(self, x, y):
   529         def GetReleaseVariableMenuFunction(self, item):
   581             width, height = self.GetSize()
   530             def ReleaseVariableFunction(event):
   582             if y < height / 2:
   531                 self.ReleaseValue(item)
   583                 if self.ParentWindow.IsViewerFirst(self):
   532             return ReleaseVariableFunction
   584                     self.SetHighlight(HIGHLIGHT_BEFORE)
   533         
   585                 else:
   534         def GetDeleteValueMenuFunction(self, item):
   586                     self.SetHighlight(HIGHLIGHT_NONE)
   535             def DeleteValueFunction(event):
   587                     self.ParentWindow.HighlightPreviousViewer(self)
   536                 self.ParentWindow.DeleteValue(self, item)
   588             else:
   537             return DeleteValueFunction
   589                 self.SetHighlight(HIGHLIGHT_AFTER)
       
   590         
       
   591         def OnResize(self, event):
       
   592             wx.CallAfter(self.RefreshButtonsState, True)
       
   593             event.Skip()
   538         
   594         
   539         def ForceValue(self, item):
   595         def ForceValue(self, item):
   540             iec_path = item.GetVariable().upper()
   596             iec_path = item.GetVariable().upper()
   541             iec_type = self.ParentWindow.GetDataType(iec_path)
   597             iec_type = self.ParentWindow.GetDataType(iec_path)
   542             if iec_type is not None:
   598             if iec_type is not None:
   545                     self.ParentWindow.ForceDataValue(iec_path, dialog.GetValue())
   601                     self.ParentWindow.ForceDataValue(iec_path, dialog.GetValue())
   546         
   602         
   547         def ReleaseValue(self, item):
   603         def ReleaseValue(self, item):
   548             iec_path = item.GetVariable().upper()
   604             iec_path = item.GetVariable().upper()
   549             self.ParentWindow.ReleaseDataValue(iec_path)
   605             self.ParentWindow.ReleaseDataValue(iec_path)
   550         
   606     
   551         def OnDeleteAllValuesMenu(self, event):
   607     
   552             wx.CallAfter(self.ParentWindow.DeleteValue, self)
   608     class DebugVariableText(DebugVariableViewer, wx.Panel):
   553         
       
   554     class DebugVariableText(DebugVariableViewer):
       
   555         
   609         
   556         def __init__(self, parent, window, items=[]):
   610         def __init__(self, parent, window, items=[]):
   557             DebugVariableViewer.__init__(self, parent, window, items)
   611             DebugVariableViewer.__init__(self, window, items)
   558         
   612             
   559             main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
   613             wx.Panel.__init__(self, parent)
   560             main_sizer.AddGrowableCol(0)
   614             self.SetBackgroundColour(wx.WHITE)
   561             
   615             self.SetDropTarget(DebugVariableDropTarget(window, self))
   562             viewer_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
   616             self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
   563             viewer_sizer.AddGrowableCol(0)
   617             self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
   564             main_sizer.AddSizer(viewer_sizer, border=5, 
   618             self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
   565                 flag=wx.ALL|wx.GROW|wx.ALIGN_CENTER_VERTICAL)
   619             self.Bind(wx.EVT_SIZE, self.OnResize)
   566             
   620             self.Bind(wx.EVT_PAINT, self.OnPaint)
   567             variable_name_label = wx.TextCtrl(self, size=wx.Size(0, -1),
   621             
   568                 value=self.Items[0].GetVariable(), style=wx.TE_READONLY|wx.TE_RIGHT|wx.NO_BORDER)
   622             self.SetMinSize(wx.Size(0, 25))
   569             variable_name_label.SetSelection(variable_name_label.GetLastPosition(), -1)
   623             
   570             viewer_sizer.AddWindow(variable_name_label, flag=wx.GROW)
   624             self.Buttons.append(
   571             
   625                 GraphButton(0, 0, GetBitmap("force"), self.OnForceButton))
   572             self.ValueLabel = wx.TextCtrl(self,
   626             self.Buttons.append(
   573                 size=wx.Size(100, -1), style=wx.TE_READONLY|wx.TE_RIGHT|wx.NO_BORDER)
   627                 GraphButton(0, 0, GetBitmap("release"), self.OnReleaseButton))
   574             viewer_sizer.AddWindow(self.ValueLabel, 
   628             self.Buttons.append(
   575                 border=5, flag=wx.LEFT)
   629                 GraphButton(0, 0, GetBitmap("delete_graph"), self.OnCloseButton))
   576             
   630             
   577             button_sizer = wx.BoxSizer(wx.HORIZONTAL)
   631             self.ShowButtons(False)
   578             self.MainSizer.AddSizer(button_sizer, border=5, 
   632             
   579                 flag=wx.TOP|wx.BOTTOM|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
   633         def RefreshViewer(self):
   580             
   634             width, height = self.GetSize()
   581             buttons = [
   635             bitmap = wx.EmptyBitmap(width, height)
   582                 ("ForceButton", "force", _("Force value")),
   636             
   583                 ("ReleaseButton", "release", _("Release value")),
   637             dc = wx.BufferedPaintDC(self, bitmap)
   584                 ("DeleteButton", "delete_graph", _("Remove debug variable"))]
   638             dc.Clear()
   585             
   639             dc.BeginDrawing()
   586             for name, bitmap, help in buttons:
   640             
   587                 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), 
   641             gc = wx.GCDC(dc)
   588                       size=wx.Size(20, 20), style=wx.NO_BORDER)
   642             
   589                 button.SetToolTipString(help)
   643             item_name = self.Items[0].GetVariable(self.ParentWindow.GetVariableNameMask())
   590                 setattr(self, name, button)
   644             w, h = gc.GetTextExtent(item_name)
   591                 self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
   645             gc.DrawText(item_name, 10, (height - h) / 2)
   592                 button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
   646             
   593             
       
   594             self.SetSizer(main_sizer)
       
   595     
       
   596         def Refresh(self):
       
   597             self.ValueLabel.ChangeValue(self.Items[0].GetValue())
       
   598             if self.Items[0].IsForced():
   647             if self.Items[0].IsForced():
   599                 self.ValueLabel.SetForegroundColour(wx.BLUE)
   648                 gc.SetTextForeground(wx.BLUE)
   600             else:
   649                 self.Buttons[0].Disable()
   601                 self.ValueLabel.SetForegroundColour(wx.BLACK)
   650                 self.Buttons[1].Enable()
   602             self.ValueLabel.SetSelection(self.ValueLabel.GetLastPosition(), -1)
   651             else:
       
   652                 self.Buttons[1].Disable()
       
   653                 self.Buttons[0].Enable()
       
   654             self.RefreshButtonsState(True)
       
   655             
       
   656             item_value = self.Items[0].GetValue()
       
   657             w, h = gc.GetTextExtent(item_value)
       
   658             gc.DrawText(item_value, width - 40 - w, (height - h) / 2)
       
   659             
       
   660             self.DrawCommonElements(gc)
       
   661             
       
   662             gc.EndDrawing()
       
   663         
       
   664         def OnLeftUp(self, event):
       
   665             x, y = event.GetPosition()
       
   666             wx.CallAfter(self.HandleButtons, x, y)
       
   667             event.Skip()
       
   668         
       
   669         def OnPaint(self, event):
       
   670             self.RefreshViewer()
       
   671             event.Skip()
   603     
   672     
   604     def compute_mask(x, y):
   673     def compute_mask(x, y):
   605         mask = []
   674         mask = []
   606         for xp, yp in zip(x, y):
   675         for xp, yp in zip(x, y):
   607             if xp == yp:
   676             if xp == yp:
   682                 
   751                 
   683         def Draw(self, dc):
   752         def Draw(self, dc):
   684             if self.Shown and self.Enabled:
   753             if self.Shown and self.Enabled:
   685                 dc.DrawBitmap(self.Bitmap, self.Position.x, self.Position.y, True)
   754                 dc.DrawBitmap(self.Bitmap, self.Position.x, self.Position.y, True)
   686     
   755     
   687     class DraggingFigureCanvas(FigureCanvas):
   756     class DebugVariableGraphic(DebugVariableViewer, FigureCanvas):
   688         
   757         
   689         def __init__(self, parent, window, *args, **kwargs):
   758         def __init__(self, parent, window, items, graph_type):
   690             FigureCanvas.__init__(self, parent, *args, **kwargs)
   759             DebugVariableViewer.__init__(self, window, items)
   691             self.SetBackgroundColour(wx.WHITE)
   760             
   692             self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
       
   693             self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
       
   694             self.Bind(wx.EVT_SIZE, self.OnResizeWindow)
       
   695             
       
   696             self.ParentWindow = window
       
   697             self.Highlight = HIGHLIGHT_NONE
       
   698             self.CanvasSize = SIZE_MAXI
   761             self.CanvasSize = SIZE_MAXI
   699             
   762             self.GraphType = graph_type
   700             self.Buttons = []
   763             self.CursorTick = None
       
   764             self.MouseStartPos = None
       
   765             self.StartCursorTick = None
       
   766             self.CanvasStartSize = None
   701             self.ContextualButtons = []
   767             self.ContextualButtons = []
   702             self.ContextualButtonsItem = None
   768             self.ContextualButtonsItem = None
       
   769             
       
   770             self.Figure = matplotlib.figure.Figure(facecolor='w')
       
   771             self.Figure.subplotpars.update(top=0.95, left=0.1, bottom=0.1, right=0.95)
       
   772             
       
   773             FigureCanvas.__init__(self, parent, -1, self.Figure)
       
   774             self.SetBackgroundColour(wx.WHITE)
       
   775             self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
       
   776             self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
       
   777             self.Bind(wx.EVT_SIZE, self.OnResize)
       
   778             
       
   779             self.SetMinSize(wx.Size(200, 200))
       
   780             self.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
       
   781             self.mpl_connect('button_press_event', self.OnCanvasButtonPressed)
       
   782             self.mpl_connect('motion_notify_event', self.OnCanvasMotion)
       
   783             self.mpl_connect('button_release_event', self.OnCanvasButtonReleased)
       
   784             self.mpl_connect('scroll_event', self.OnCanvasScroll)
   703             
   785             
   704             for size, bitmap in zip([SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI],
   786             for size, bitmap in zip([SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI],
   705                                     ["minimize_graph", "middle_graph", "maximize_graph"]):
   787                                     ["minimize_graph", "middle_graph", "maximize_graph"]):
   706                 self.Buttons.append(GraphButton(0, 0, GetBitmap(bitmap), self.GetOnChangeSizeButton(size)))
   788                 self.Buttons.append(GraphButton(0, 0, GetBitmap(bitmap), self.GetOnChangeSizeButton(size)))
   707             self.Buttons.append(
   789             self.Buttons.append(
   708                 GraphButton(0, 0, GetBitmap("export_graph_mini"), self.OnExportGraphButton))
   790                 GraphButton(0, 0, GetBitmap("export_graph_mini"), self.OnExportGraphButton))
   709             self.Buttons.append(
   791             self.Buttons.append(
   710                 GraphButton(0, 0, GetBitmap("delete_graph"), self.OnCloseButton))
   792                 GraphButton(0, 0, GetBitmap("delete_graph"), self.OnCloseButton))
   711             
   793             
       
   794             self.ResetGraphics()
       
   795             self.RefreshLabelsPosition(200)
   712             self.ShowButtons(False)
   796             self.ShowButtons(False)
   713             
       
   714         def SetHighlight(self, highlight):
       
   715             if self.Highlight != highlight:
       
   716                 self.Highlight = highlight
       
   717                 return True
       
   718             return False
       
   719         
       
   720         def GetAxesBoundingBox(self):
       
   721             width, height = self.GetSize()
       
   722             ax, ay, aw, ah = self.figure.gca().get_position().bounds
       
   723             return wx.Rect(ax * width, height - (ay + ah) * height - 1,
       
   724                            aw * width + 2, ah * height + 1)
       
   725         
   797         
   726         def draw(self, drawDC=None):
   798         def draw(self, drawDC=None):
   727             FigureCanvasAgg.draw(self)
   799             FigureCanvasAgg.draw(self)
   728     
   800     
   729             self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
   801             self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
   742                 destGC.SetBrush(HIGHLIGHT_RESIZE_BRUSH)
   814                 destGC.SetBrush(HIGHLIGHT_RESIZE_BRUSH)
   743                 destGC.DrawRectangle(0, height - 5, width, 5)
   815                 destGC.DrawRectangle(0, height - 5, width, 5)
   744             else:
   816             else:
   745                 destGC.SetPen(HIGHLIGHT_DROP_PEN)
   817                 destGC.SetPen(HIGHLIGHT_DROP_PEN)
   746                 destGC.SetBrush(HIGHLIGHT_DROP_BRUSH)
   818                 destGC.SetBrush(HIGHLIGHT_DROP_BRUSH)
   747                 if self.Highlight in [HIGHLIGHT_BEFORE]:
   819                 if self.Highlight == HIGHLIGHT_LEFT:
   748                     destGC.DrawLine(0, 1, width - 1, 1)
       
   749                 elif self.Highlight in [HIGHLIGHT_AFTER]:
       
   750                     destGC.DrawLine(0, height - 1, width - 1, height - 1)
       
   751                 elif self.Highlight == HIGHLIGHT_LEFT:
       
   752                     destGC.DrawRectangle(bbox.x, bbox.y, 
   820                     destGC.DrawRectangle(bbox.x, bbox.y, 
   753                                          bbox.width / 2, bbox.height)
   821                                          bbox.width / 2, bbox.height)
   754                 elif self.Highlight == HIGHLIGHT_RIGHT:
   822                 elif self.Highlight == HIGHLIGHT_RIGHT:
   755                     destGC.DrawRectangle(bbox.x + bbox.width / 2, bbox.y, 
   823                     destGC.DrawRectangle(bbox.x + bbox.width / 2, bbox.y, 
   756                                          bbox.width / 2, bbox.height)
   824                                          bbox.width / 2, bbox.height)
   757             
   825             
   758             for button in self.Buttons + self.ContextualButtons:
   826             self.DrawCommonElements(destGC, self.Buttons + self.ContextualButtons)
   759                 button.Draw(destGC)
   827             
   760             
       
   761             if self.ParentWindow.IsDragging():
       
   762                 destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self.Parent)
       
   763                 if destBBox.width > 0 and destBBox.height > 0:
       
   764                     srcPanel = self.ParentWindow.DraggingAxesPanel
       
   765                     srcBBox = srcPanel.GetAxesBoundingBox()
       
   766                     
       
   767                     if destBBox.x == 0:
       
   768                         srcX = srcBBox.x + srcBBox.width - destBBox.width
       
   769                     else:
       
   770                         srcX = srcBBox.x
       
   771                     if destBBox.y == 0:
       
   772                         srcY = srcBBox.y + srcBBox.height - destBBox.height
       
   773                     else:
       
   774                         srcY = srcBBox.y
       
   775                     
       
   776                     srcBmp = _convert_agg_to_wx_bitmap(srcPanel.Canvas.get_renderer(), None)
       
   777                     srcDC = wx.MemoryDC()
       
   778                     srcDC.SelectObject(srcBmp)
       
   779                     
       
   780                     destGC.Blit(destBBox.x, destBBox.y, 
       
   781                                 int(destBBox.width), int(destBBox.height), 
       
   782                                 srcDC, srcX, srcY)
       
   783                     
       
   784             destGC.EndDrawing()
   828             destGC.EndDrawing()
   785             
   829             
   786             self._isDrawn = True
   830             self._isDrawn = True
   787             self.gui_repaint(drawDC=drawDC)
   831             self.gui_repaint(drawDC=drawDC)
   788         
   832         
   789         def HandleButtons(self, x, y):
   833         def GetButtons(self):
   790             for button in self.Buttons + self.ContextualButtons:
   834             return self.Buttons + self.ContextualButtons
   791                 if button.HitTest(x, y):
       
   792                     button.ProcessCallback()
       
   793                     return True
       
   794             return False
       
   795         
   835         
   796         def PopupContextualButtons(self, item, rect, style=wx.RIGHT):
   836         def PopupContextualButtons(self, item, rect, style=wx.RIGHT):
   797             if self.ContextualButtonsItem is not None and item != self.ContextualButtonsItem:
   837             if self.ContextualButtonsItem is not None and item != self.ContextualButtonsItem:
   798                 self.DismissContextualButtons()
   838                 self.DismissContextualButtons()
   799             
   839             
   838             if self.ContextualButtonsItem is not None:
   878             if self.ContextualButtonsItem is not None:
   839                 self.ContextualButtonsItem = None
   879                 self.ContextualButtonsItem = None
   840                 self.ContextualButtons = []
   880                 self.ContextualButtons = []
   841                 self.ParentWindow.ForceRefresh()
   881                 self.ParentWindow.ForceRefresh()
   842         
   882         
   843         def IsOverButton(self, x, y):
       
   844             for button in self.Buttons + self.ContextualButtons:
       
   845                 if button.HitTest(x, y):
       
   846                     return True
       
   847             return False
       
   848         
       
   849         def IsOverContextualButton(self, x, y):
   883         def IsOverContextualButton(self, x, y):
   850             for button in self.ContextualButtons:
   884             for button in self.ContextualButtons:
   851                 if button.HitTest(x, y):
   885                 if button.HitTest(x, y):
   852                     return True
   886                     return True
   853             return False
   887             return False
   854         
   888         
   855         def SetMinSize(self, size):
   889         def SetMinSize(self, size):
   856             wx.Window.SetMinSize(self, size)
   890             wx.Window.SetMinSize(self, size)
   857             wx.CallAfter(self.RefreshButtonsState)
   891             wx.CallAfter(self.RefreshButtonsState)
   858                 
       
   859         def ShowButtons(self, show):
       
   860             for button in self.Buttons:
       
   861                 if show:
       
   862                     button.Show()
       
   863                 else:
       
   864                     button.Hide()
       
   865             self.RefreshButtonsState()
       
   866             self.ParentWindow.ForceRefresh()
       
   867         
       
   868         def OnEnterWindow(self, event):
       
   869             self.ShowButtons(True)
       
   870             event.Skip()
       
   871             
       
   872         def OnLeaveWindow(self, event):
       
   873             if self.Highlight != HIGHLIGHT_RESIZE or self.Parent.CanvasStartSize is None:
       
   874                 x, y = event.GetPosition()
       
   875                 width, height = self.GetSize()
       
   876                 if (x <= 0 or x >= width - 1 or
       
   877                     y <= 0 or y >= height - 1):
       
   878                     self.ShowButtons(False)
       
   879             event.Skip()
       
   880         
   892         
   881         def GetOnChangeSizeButton(self, size):
   893         def GetOnChangeSizeButton(self, size):
   882             def OnChangeSizeButton():
   894             def OnChangeSizeButton():
   883                 self.CanvasSize = size
   895                 self.CanvasSize = size
   884                 self.Parent.SetCanvasSize(200, self.CanvasSize)
   896                 self.SetCanvasSize(200, self.CanvasSize)
   885             return OnChangeSizeButton
   897             return OnChangeSizeButton
   886         
   898         
   887         def OnExportGraphButton(self):
   899         def OnExportGraphButton(self):
   888             self.Parent.ExportGraph()
   900             self.ExportGraph()
   889         
       
   890         def OnCloseButton(self):
       
   891             self.ParentWindow.DeleteValue(self.Parent)
       
   892         
   901         
   893         def OnForceButton(self):
   902         def OnForceButton(self):
   894             wx.CallAfter(self.Parent.ForceValue, 
   903             wx.CallAfter(self.ForceValue, 
   895                          self.ContextualButtonsItem)
   904                          self.ContextualButtonsItem)
   896             self.DismissContextualButtons()
   905             self.DismissContextualButtons()
   897             
   906             
   898         def OnReleaseButton(self):
   907         def OnReleaseButton(self):
   899             wx.CallAfter(self.Parent.ReleaseValue, 
   908             wx.CallAfter(self.ReleaseValue, 
   900                          self.ContextualButtonsItem)
   909                          self.ContextualButtonsItem)
   901             self.DismissContextualButtons()
   910             self.DismissContextualButtons()
   902         
   911         
   903         def OnExportItemGraphButton(self):
   912         def OnExportItemGraphButton(self):
   904             wx.CallAfter(self.Parent.ExportGraph, 
   913             wx.CallAfter(self.ExportGraph, 
   905                          self.ContextualButtonsItem)
   914                          self.ContextualButtonsItem)
   906             self.DismissContextualButtons()
   915             self.DismissContextualButtons()
   907             
   916             
   908         def OnRemoveItemButton(self):            
   917         def OnRemoveItemButton(self):            
   909             wx.CallAfter(self.ParentWindow.DeleteValue, self.Parent, 
   918             wx.CallAfter(self.ParentWindow.DeleteValue, self, 
   910                          self.ContextualButtonsItem)
   919                          self.ContextualButtonsItem)
   911             self.DismissContextualButtons()
   920             self.DismissContextualButtons()
   912         
   921         
   913         def RefreshButtonsState(self, refresh_positions=False):
   922         def RefreshButtonsState(self, refresh_positions=False):
   914             if self:
   923             if self:
   915                 width, height = self.GetSize()
   924                 width, height = self.GetSize()
   916                 min_width, min_height = self.Parent.GetCanvasMinSize()
   925                 min_width, min_height = self.GetCanvasMinSize()
   917                 for button, size in zip(self.Buttons, 
   926                 for button, size in zip(self.Buttons, 
   918                                         [min_height, SIZE_MIDDLE, SIZE_MAXI]):
   927                                         [min_height, SIZE_MIDDLE, SIZE_MAXI]):
   919                     if size == height and button.IsEnabled():
   928                     if size == height and button.IsEnabled():
   920                         button.Disable()
   929                         button.Disable()
   921                         refresh_positions = True
   930                         refresh_positions = True
   931                             w, h = button.GetSize()
   940                             w, h = button.GetSize()
   932                             button.SetPosition(width - 5 - w - offset, 5)
   941                             button.SetPosition(width - 5 - w - offset, 5)
   933                             offset += w + 2
   942                             offset += w + 2
   934                     self.ParentWindow.ForceRefresh()
   943                     self.ParentWindow.ForceRefresh()
   935         
   944         
   936         def OnResizeWindow(self, event):
       
   937             wx.CallAfter(self.RefreshButtonsState, True)
       
   938             event.Skip()
       
   939     
       
   940     class DebugVariableGraphic(DebugVariableViewer):
       
   941         
       
   942         def __init__(self, parent, window, items, graph_type):
       
   943             DebugVariableViewer.__init__(self, parent, window, items)
       
   944         
       
   945             self.GraphType = graph_type
       
   946             self.CursorTick = None
       
   947             self.MouseStartPos = None
       
   948             self.StartCursorTick = None
       
   949             self.CanvasStartSize = None
       
   950             
       
   951             main_sizer = wx.BoxSizer(wx.VERTICAL)
       
   952             
       
   953             self.Figure = matplotlib.figure.Figure(facecolor='w')
       
   954             self.Figure.subplotpars.update(top=0.95, left=0.1, bottom=0.1, right=0.95)
       
   955             
       
   956             self.Canvas = DraggingFigureCanvas(self, self.ParentWindow, -1, self.Figure)
       
   957             self.Canvas.SetMinSize(wx.Size(200, 200))
       
   958             self.Canvas.SetDropTarget(DebugVariableDropTarget(self.ParentWindow, self))
       
   959             self.Canvas.mpl_connect('button_press_event', self.OnCanvasButtonPressed)
       
   960             self.Canvas.mpl_connect('motion_notify_event', self.OnCanvasMotion)
       
   961             self.Canvas.mpl_connect('button_release_event', self.OnCanvasButtonReleased)
       
   962             self.Canvas.mpl_connect('scroll_event', self.OnCanvasScroll)
       
   963             self.Canvas.Bind(wx.EVT_LEAVE_WINDOW, self.OnCanvasLeave)
       
   964             
       
   965             main_sizer.AddWindow(self.Canvas, 1, flag=wx.GROW)
       
   966             self.SetSizer(main_sizer)
       
   967             
       
   968             self.ResetGraphics()
       
   969             self.RefreshLabelsPosition(200)
       
   970         
       
   971         def RefreshLabelsPosition(self, height):
   945         def RefreshLabelsPosition(self, height):
   972             canvas_ratio = 1. / height
   946             canvas_ratio = 1. / height
   973             graph_ratio = 1. / ((1.0 - (CANVAS_BORDER[0] + CANVAS_BORDER[1]) * canvas_ratio) * height)
   947             graph_ratio = 1. / ((1.0 - (CANVAS_BORDER[0] + CANVAS_BORDER[1]) * canvas_ratio) * height)
   974             
   948             
   975             self.Figure.subplotpars.update(
   949             self.Figure.subplotpars.update(
  1000                            CANVAS_BORDER[0] + CANVAS_BORDER[1] + 
   974                            CANVAS_BORDER[0] + CANVAS_BORDER[1] + 
  1001                            2 * CANVAS_PADDING + VALUE_LABEL_HEIGHT * len(self.Items))
   975                            2 * CANVAS_PADDING + VALUE_LABEL_HEIGHT * len(self.Items))
  1002         
   976         
  1003         def SetCanvasSize(self, width, height):
   977         def SetCanvasSize(self, width, height):
  1004             height = max(height, self.GetCanvasMinSize()[1])
   978             height = max(height, self.GetCanvasMinSize()[1])
  1005             self.Canvas.SetMinSize(wx.Size(width, height))
   979             self.SetMinSize(wx.Size(width, height))
  1006             self.RefreshLabelsPosition(height)
   980             self.RefreshLabelsPosition(height)
  1007             self.ParentWindow.RefreshGraphicsSizer()
   981             self.ParentWindow.RefreshGraphicsSizer()
  1008             
   982             
  1009         def GetAxesBoundingBox(self, absolute=False):
   983         def GetAxesBoundingBox(self, absolute=False):
  1010             bbox = self.Canvas.GetAxesBoundingBox()
   984             width, height = self.GetSize()
       
   985             ax, ay, aw, ah = self.figure.gca().get_position().bounds
       
   986             bbox = wx.Rect(ax * width, height - (ay + ah) * height - 1,
       
   987                            aw * width + 2, ah * height + 1)
  1011             if absolute:
   988             if absolute:
  1012                 xw, yw = self.GetPosition()
   989                 xw, yw = self.GetPosition()
  1013                 bbox.x += xw
   990                 bbox.x += xw
  1014                 bbox.y += yw
   991                 bbox.y += yw
  1015             return bbox
   992             return bbox
  1016         
   993         
  1017         def OnCanvasButtonPressed(self, event):
   994         def OnCanvasButtonPressed(self, event):
  1018             width, height = self.Canvas.GetSize()
   995             width, height = self.GetSize()
  1019             x, y = event.x, height - event.y
   996             x, y = event.x, height - event.y
  1020             if not self.Canvas.IsOverButton(x, y):
   997             if not self.IsOverButton(x, y):
  1021                 if event.inaxes == self.Axes:
   998                 if event.inaxes == self.Axes:
  1022                     item_idx = None
   999                     item_idx = None
  1023                     for i, t in ([pair for pair in enumerate(self.AxesLabels)] + 
  1000                     for i, t in ([pair for pair in enumerate(self.AxesLabels)] + 
  1024                                  [pair for pair in enumerate(self.Labels)]):
  1001                                  [pair for pair in enumerate(self.Labels)]):
  1025                         (x0, y0), (x1, y1) = t.get_window_extent().get_points()
  1002                         (x0, y0), (x1, y1) = t.get_window_extent().get_points()
  1026                         rect = wx.Rect(x0, height - y1, x1 - x0, y1 - y0)
  1003                         rect = wx.Rect(x0, height - y1, x1 - x0, y1 - y0)
  1027                         if rect.InsideXY(x, y):
  1004                         if rect.InsideXY(x, y):
  1028                             item_idx = i
  1005                             item_idx = i
  1029                             break
  1006                             break
  1030                     if item_idx is not None:
  1007                     if item_idx is not None:
  1031                         self.Canvas.ShowButtons(False)
  1008                         self.ShowButtons(False)
  1032                         self.Canvas.DismissContextualButtons()
  1009                         self.DismissContextualButtons()
  1033                         xw, yw = self.GetPosition()
  1010                         xw, yw = self.GetPosition()
  1034                         self.ParentWindow.StartDragNDrop(self, 
  1011                         self.ParentWindow.StartDragNDrop(self, 
  1035                             self.Items[item_idx], x + xw, y + yw, x + xw, y + yw)
  1012                             self.Items[item_idx], x + xw, y + yw, x + xw, y + yw)
  1036                     elif not self.Is3DCanvas():
  1013                     elif not self.Is3DCanvas():
  1037                         self.MouseStartPos = wx.Point(x, y)
  1014                         self.MouseStartPos = wx.Point(x, y)
  1038                         if event.button == 1 and event.inaxes == self.Axes:
  1015                         if event.button == 1 and event.inaxes == self.Axes:
  1039                             self.StartCursorTick = self.CursorTick
  1016                             self.StartCursorTick = self.CursorTick
  1040                             self.HandleCursorMove(event)
  1017                             self.HandleCursorMove(event)
  1041                         elif event.button == 2 and self.GraphType == GRAPH_PARALLEL:
  1018                         elif event.button == 2 and self.GraphType == GRAPH_PARALLEL:
  1042                             width, height = self.Canvas.GetSize()
  1019                             width, height = self.GetSize()
  1043                             start_tick, end_tick = self.ParentWindow.GetRange()
  1020                             start_tick, end_tick = self.ParentWindow.GetRange()
  1044                             self.StartCursorTick = start_tick
  1021                             self.StartCursorTick = start_tick
  1045                 
  1022                 
  1046                 elif event.button == 1 and event.y <= 5:
  1023                 elif event.button == 1 and event.y <= 5:
  1047                     self.MouseStartPos = wx.Point(x, y)
  1024                     self.MouseStartPos = wx.Point(x, y)
  1048                     self.CanvasStartSize = self.Canvas.GetSize()
  1025                     self.CanvasStartSize = self.GetSize()
  1049         
  1026         
  1050         def OnCanvasButtonReleased(self, event):
  1027         def OnCanvasButtonReleased(self, event):
  1051             if self.ParentWindow.IsDragging():
  1028             if self.ParentWindow.IsDragging():
  1052                 width, height = self.Canvas.GetSize()
  1029                 width, height = self.GetSize()
  1053                 xw, yw = self.GetPosition()
  1030                 xw, yw = self.GetPosition()
  1054                 self.ParentWindow.StopDragNDrop(
  1031                 self.ParentWindow.StopDragNDrop(
  1055                     self.ParentWindow.DraggingAxesPanel.Items[0].GetVariable(),
  1032                     self.ParentWindow.DraggingAxesPanel.Items[0].GetVariable(),
  1056                     xw + event.x, 
  1033                     xw + event.x, 
  1057                     yw + height - event.y)
  1034                     yw + height - event.y)
  1058             else:
  1035             else:
  1059                 self.MouseStartPos = None
  1036                 self.MouseStartPos = None
  1060                 self.StartCursorTick = None
  1037                 self.StartCursorTick = None
  1061                 self.CanvasStartSize = None
  1038                 self.CanvasStartSize = None
  1062                 width, height = self.Canvas.GetSize()
  1039                 width, height = self.GetSize()
  1063                 self.Canvas.HandleButtons(event.x, height - event.y)
  1040                 self.HandleButtons(event.x, height - event.y)
  1064                 if event.y > 5 and self.Canvas.SetHighlight(HIGHLIGHT_NONE):
  1041                 if event.y > 5 and self.SetHighlight(HIGHLIGHT_NONE):
  1065                     self.Canvas.SetCursor(wx.NullCursor)
  1042                     self.SetCursor(wx.NullCursor)
  1066                     self.ParentWindow.ForceRefresh()
  1043                     self.ParentWindow.ForceRefresh()
  1067         
  1044         
  1068         def OnCanvasMotion(self, event):
  1045         def OnCanvasMotion(self, event):
  1069             width, height = self.Canvas.GetSize()
  1046             width, height = self.GetSize()
  1070             if self.ParentWindow.IsDragging():
  1047             if self.ParentWindow.IsDragging():
  1071                 xw, yw = self.GetPosition()
  1048                 xw, yw = self.GetPosition()
  1072                 self.ParentWindow.MoveDragNDrop(
  1049                 self.ParentWindow.MoveDragNDrop(
  1073                     xw + event.x, 
  1050                     xw + event.x, 
  1074                     yw + height - event.y)
  1051                     yw + height - event.y)
  1091                         self.ParentWindow.SetCanvasPosition(
  1068                         self.ParentWindow.SetCanvasPosition(
  1092                             self.StartCursorTick + (self.MouseStartPos.x - event.x) *
  1069                             self.StartCursorTick + (self.MouseStartPos.x - event.x) *
  1093                             (end_tick - start_tick) / rect.width)    
  1070                             (end_tick - start_tick) / rect.width)    
  1094                 
  1071                 
  1095                 if event.button == 1 and self.CanvasStartSize is not None:
  1072                 if event.button == 1 and self.CanvasStartSize is not None:
  1096                     width, height = self.Canvas.GetSize()
  1073                     width, height = self.GetSize()
  1097                     self.SetCanvasSize(width, 
  1074                     self.SetCanvasSize(width, 
  1098                         self.CanvasStartSize.height + height - event.y - self.MouseStartPos.y)
  1075                         self.CanvasStartSize.height + height - event.y - self.MouseStartPos.y)
  1099                     
  1076                     
  1100                 elif event.button in [None, "up", "down"]:
  1077                 elif event.button in [None, "up", "down"]:
  1101                     if self.GraphType == GRAPH_PARALLEL:
  1078                     if self.GraphType == GRAPH_PARALLEL:
  1114                         if rect.InsideXY(event.x, height - event.y):
  1091                         if rect.InsideXY(event.x, height - event.y):
  1115                             item_idx = i
  1092                             item_idx = i
  1116                             item_style = style
  1093                             item_style = style
  1117                             break
  1094                             break
  1118                     if item_idx is not None:
  1095                     if item_idx is not None:
  1119                         self.Canvas.PopupContextualButtons(self.Items[item_idx], rect, item_style)
  1096                         self.PopupContextualButtons(self.Items[item_idx], rect, item_style)
  1120                         return 
  1097                         return 
  1121                     if not self.Canvas.IsOverContextualButton(event.x, height - event.y):
  1098                     if not self.IsOverContextualButton(event.x, height - event.y):
  1122                         self.Canvas.DismissContextualButtons()
  1099                         self.DismissContextualButtons()
  1123                     
  1100                     
  1124                     if event.y <= 5:
  1101                     if event.y <= 5:
  1125                         if self.Canvas.SetHighlight(HIGHLIGHT_RESIZE):
  1102                         if self.SetHighlight(HIGHLIGHT_RESIZE):
  1126                             self.Canvas.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
  1103                             self.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
  1127                             self.ParentWindow.ForceRefresh()
  1104                             self.ParentWindow.ForceRefresh()
  1128                     else:
  1105                     else:
  1129                         if self.Canvas.SetHighlight(HIGHLIGHT_NONE):
  1106                         if self.SetHighlight(HIGHLIGHT_NONE):
  1130                             self.Canvas.SetCursor(wx.NullCursor)
  1107                             self.SetCursor(wx.NullCursor)
  1131                             self.ParentWindow.ForceRefresh()
  1108                             self.ParentWindow.ForceRefresh()
  1132         
       
  1133         def OnCanvasMouseDragging(self, x, y):
       
  1134             xw, yw = self.GetPosition()
       
  1135             self.ParentWindow.RefreshHighlight(x + xw, y + yw)
       
  1136         
       
  1137         def OnCanvasDragging(self, x, y):
       
  1138             width, height = self.Canvas.GetSize()
       
  1139             bbox = self.Canvas.GetAxesBoundingBox()
       
  1140             if bbox.InsideXY(x, y) and not self.Is3DCanvas():
       
  1141                 rect = wx.Rect(bbox.x, bbox.y, bbox.width / 2, bbox.height)
       
  1142                 if rect.InsideXY(x, y):
       
  1143                     self.Canvas.SetHighlight(HIGHLIGHT_LEFT)
       
  1144                 else:
       
  1145                     self.Canvas.SetHighlight(HIGHLIGHT_RIGHT)
       
  1146             elif y < height / 2:
       
  1147                 if self.ParentWindow.IsViewerFirst(self):
       
  1148                     self.Canvas.SetHighlight(HIGHLIGHT_BEFORE)
       
  1149                 else:
       
  1150                     self.Canvas.SetHighlight(HIGHLIGHT_NONE)
       
  1151                     self.ParentWindow.HighlightPreviousViewer(self)
       
  1152             else:
       
  1153                 self.Canvas.SetHighlight(HIGHLIGHT_AFTER)
       
  1154         
  1109         
  1155         def OnCanvasScroll(self, event):
  1110         def OnCanvasScroll(self, event):
  1156             if event.inaxes is not None:
  1111             if event.inaxes is not None:
  1157                 if self.GraphType == GRAPH_ORTHOGONAL:
  1112                 if self.GraphType == GRAPH_ORTHOGONAL:
  1158                     start_tick, end_tick = self.ParentWindow.GetRange()
  1113                     start_tick, end_tick = self.ParentWindow.GetRange()
  1159                     tick = (start_tick + end_tick) / 2.
  1114                     tick = (start_tick + end_tick) / 2.
  1160                 else:
  1115                 else:
  1161                     tick = event.xdata
  1116                     tick = event.xdata
  1162                 self.ParentWindow.ChangeRange(int(-event.step) / 3, tick)
  1117                 self.ParentWindow.ChangeRange(int(-event.step) / 3, tick)
  1163         
  1118         
  1164         def OnCanvasLeave(self, event):
  1119         def OnDragging(self, x, y):
  1165             if self.CanvasStartSize is None and self.Canvas.SetHighlight(HIGHLIGHT_NONE):
  1120             width, height = self.GetSize()
  1166                 self.Canvas.SetCursor(wx.NullCursor)
  1121             bbox = self.GetAxesBoundingBox()
       
  1122             if bbox.InsideXY(x, y) and not self.Is3DCanvas():
       
  1123                 rect = wx.Rect(bbox.x, bbox.y, bbox.width / 2, bbox.height)
       
  1124                 if rect.InsideXY(x, y):
       
  1125                     self.SetHighlight(HIGHLIGHT_LEFT)
       
  1126                 else:
       
  1127                     self.SetHighlight(HIGHLIGHT_RIGHT)
       
  1128             elif y < height / 2:
       
  1129                 if self.ParentWindow.IsViewerFirst(self):
       
  1130                     self.SetHighlight(HIGHLIGHT_BEFORE)
       
  1131                 else:
       
  1132                     self.SetHighlight(HIGHLIGHT_NONE)
       
  1133                     self.ParentWindow.HighlightPreviousViewer(self)
       
  1134             else:
       
  1135                 self.SetHighlight(HIGHLIGHT_AFTER)
       
  1136         
       
  1137         def OnLeave(self, event):
       
  1138             if self.CanvasStartSize is None and self.SetHighlight(HIGHLIGHT_NONE):
       
  1139                 self.SetCursor(wx.NullCursor)
  1167                 self.ParentWindow.ForceRefresh()
  1140                 self.ParentWindow.ForceRefresh()
  1168             event.Skip()
  1141             DebugVariableViewer.OnLeave(self, event)
  1169         
       
  1170         def HighlightCanvas(self, highlight):
       
  1171             self.Canvas.SetHighlight(highlight)
       
  1172         
  1142         
  1173         def HandleCursorMove(self, event):
  1143         def HandleCursorMove(self, event):
  1174             start_tick, end_tick = self.ParentWindow.GetRange()
  1144             start_tick, end_tick = self.ParentWindow.GetRange()
  1175             cursor_tick = None
  1145             cursor_tick = None
  1176             if self.GraphType == GRAPH_ORTHOGONAL:
  1146             if self.GraphType == GRAPH_ORTHOGONAL:
  1251                 self.Labels.append(
  1221                 self.Labels.append(
  1252                     self.Axes.text(0, 0, "", size='large',
  1222                     self.Axes.text(0, 0, "", size='large',
  1253                                    rotation='vertical',
  1223                                    rotation='vertical',
  1254                                    verticalalignment='top',
  1224                                    verticalalignment='top',
  1255                                    transform=self.Axes.transAxes))
  1225                                    transform=self.Axes.transAxes))
  1256             width, height = self.Canvas.GetSize()
  1226             width, height = self.GetSize()
  1257             self.RefreshLabelsPosition(height)
  1227             self.RefreshLabelsPosition(height)
  1258             
  1228             
  1259         def AddItem(self, item):
  1229         def AddItem(self, item):
  1260             DebugVariableViewer.AddItem(self, item)
  1230             DebugVariableViewer.AddItem(self, item)
  1261             self.ResetGraphics()
  1231             self.ResetGraphics()
  1276             return self.GraphType == GRAPH_ORTHOGONAL and len(self.Items) == 3
  1246             return self.GraphType == GRAPH_ORTHOGONAL and len(self.Items) == 3
  1277         
  1247         
  1278         def SetCursorTick(self, cursor_tick):
  1248         def SetCursorTick(self, cursor_tick):
  1279             self.CursorTick = cursor_tick
  1249             self.CursorTick = cursor_tick
  1280             
  1250             
  1281         def Refresh(self, refresh_graphics=True):
  1251         def RefreshViewer(self, refresh_graphics=True):
  1282             
  1252             
  1283             if refresh_graphics:
  1253             if refresh_graphics:
  1284                 start_tick, end_tick = self.ParentWindow.GetRange()
  1254                 start_tick, end_tick = self.ParentWindow.GetRange()
  1285                 
  1255                 
  1286                 if self.GraphType == GRAPH_PARALLEL:    
  1256                 if self.GraphType == GRAPH_PARALLEL:    
  1407                     label.set_text(text)
  1377                     label.set_text(text)
  1408             for label, value, style in zip(self.Labels, values, styles):
  1378             for label, value, style in zip(self.Labels, values, styles):
  1409                 label.set_text(value)
  1379                 label.set_text(value)
  1410                 label.set_style(style)
  1380                 label.set_style(style)
  1411             
  1381             
  1412             self.Canvas.draw()
  1382             self.draw()
  1413     
  1383     
  1414         def ExportGraph(self, item=None):
  1384         def ExportGraph(self, item=None):
  1415             if item is not None:
  1385             if item is not None:
  1416                 variables = [(item, [entry for entry in item.GetData()])]
  1386                 variables = [(item, [entry for entry in item.GetData()])]
  1417             else:
  1387             else:
  1638     def StartDragNDrop(self, panel, item, x_mouse, y_mouse, x_mouse_start, y_mouse_start):
  1608     def StartDragNDrop(self, panel, item, x_mouse, y_mouse, x_mouse_start, y_mouse_start):
  1639         if len(panel.GetItems()) > 1:
  1609         if len(panel.GetItems()) > 1:
  1640             self.DraggingAxesPanel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1610             self.DraggingAxesPanel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  1641             self.DraggingAxesPanel.SetCursorTick(self.CursorTick)
  1611             self.DraggingAxesPanel.SetCursorTick(self.CursorTick)
  1642             width, height = panel.GetSize()
  1612             width, height = panel.GetSize()
  1643             self.DraggingAxesPanel.SetMinSize(wx.Size(width, height))
  1613             self.DraggingAxesPanel.SetSize(wx.Size(width, height))
  1644             self.DraggingAxesPanel.SetPosition(wx.Point(0, -height))
  1614             self.DraggingAxesPanel.SetPosition(wx.Point(0, -height))
  1645         else:
  1615         else:
  1646             self.DraggingAxesPanel = panel
  1616             self.DraggingAxesPanel = panel
  1647         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(absolute=True)
  1617         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(absolute=True)
  1648         self.DraggingAxesMousePos = wx.Point(
  1618         self.DraggingAxesMousePos = wx.Point(
  1656         self.RefreshHighlight(x_mouse, y_mouse)
  1626         self.RefreshHighlight(x_mouse, y_mouse)
  1657     
  1627     
  1658     def RefreshHighlight(self, x_mouse, y_mouse):
  1628     def RefreshHighlight(self, x_mouse, y_mouse):
  1659         for idx, panel in enumerate(self.GraphicPanels):
  1629         for idx, panel in enumerate(self.GraphicPanels):
  1660             x, y = panel.GetPosition()
  1630             x, y = panel.GetPosition()
  1661             width, height = panel.Canvas.GetSize()
  1631             width, height = panel.GetSize()
  1662             rect = wx.Rect(x, y, width, height)
  1632             rect = wx.Rect(x, y, width, height)
  1663             if (rect.InsideXY(x_mouse, y_mouse) or 
  1633             if (rect.InsideXY(x_mouse, y_mouse) or 
  1664                 idx == 0 and y_mouse < 0 or
  1634                 idx == 0 and y_mouse < 0 or
  1665                 idx == len(self.GraphicPanels) - 1 and y_mouse > panel.GetPosition()[1]):
  1635                 idx == len(self.GraphicPanels) - 1 and y_mouse > panel.GetPosition()[1]):
  1666                 panel.OnCanvasDragging(x_mouse - x, y_mouse - y)
  1636                 panel.OnDragging(x_mouse - x, y_mouse - y)
  1667             else:
  1637             else:
  1668                 panel.HighlightCanvas(HIGHLIGHT_NONE)
  1638                 panel.SetHighlight(HIGHLIGHT_NONE)
  1669         self.ForceRefresh()
  1639         self.ForceRefresh()
  1670     
  1640     
  1671     def ResetHighlight(self):
  1641     def ResetHighlight(self):
  1672         for panel in self.GraphicPanels:
  1642         for panel in self.GraphicPanels:
  1673             panel.HighlightCanvas(HIGHLIGHT_NONE)
  1643             panel.SetHighlight(HIGHLIGHT_NONE)
  1674         self.ForceRefresh()
  1644         self.ForceRefresh()
  1675     
  1645     
  1676     def IsDragging(self):
  1646     def IsDragging(self):
  1677         return self.DraggingAxesPanel is not None
  1647         return self.DraggingAxesPanel is not None
  1678     
  1648     
  1679     def GetDraggingAxesClippingRegion(self, panel):
  1649     def GetDraggingAxesClippingRegion(self, panel):
  1680         x, y = panel.GetPosition()
  1650         x, y = panel.GetPosition()
  1681         width, height = panel.Canvas.GetSize()
  1651         width, height = panel.GetSize()
  1682         bbox = wx.Rect(x, y, width, height)
  1652         bbox = wx.Rect(x, y, width, height)
  1683         bbox = bbox.Intersect(self.DraggingAxesBoundingBox)
  1653         bbox = bbox.Intersect(self.DraggingAxesBoundingBox)
  1684         bbox.x -= x
  1654         bbox.x -= x
  1685         bbox.y -= y
  1655         bbox.y -= y
  1686         return bbox
  1656         return bbox
  1687     
  1657     
       
  1658     def GetDraggingAxesPosition(self, panel):
       
  1659         x, y = panel.GetPosition()
       
  1660         return wx.Point(self.DraggingAxesBoundingBox.x - x,
       
  1661                         self.DraggingAxesBoundingBox.y - y)
       
  1662     
  1688     def StopDragNDrop(self, variable, x_mouse, y_mouse):
  1663     def StopDragNDrop(self, variable, x_mouse, y_mouse):
       
  1664         if self.DraggingAxesPanel not in self.GraphicPanels:
       
  1665             self.DraggingAxesPanel.Destroy()
  1689         self.DraggingAxesPanel = None
  1666         self.DraggingAxesPanel = None
  1690         self.DraggingAxesBoundingBox = None
  1667         self.DraggingAxesBoundingBox = None
  1691         self.DraggingAxesMousePos = None
  1668         self.DraggingAxesMousePos = None
  1692         for idx, panel in enumerate(self.GraphicPanels):
  1669         for idx, panel in enumerate(self.GraphicPanels):
  1693             panel.HighlightCanvas(HIGHLIGHT_NONE)
  1670             panel.SetHighlight(HIGHLIGHT_NONE)
  1694             xw, yw = panel.GetPosition()
  1671             xw, yw = panel.GetPosition()
  1695             width, height = panel.Canvas.GetSize()
  1672             width, height = panel.GetSize()
  1696             bbox = wx.Rect(xw, yw, width, height)
  1673             bbox = wx.Rect(xw, yw, width, height)
  1697             if bbox.InsideXY(x_mouse, y_mouse):
  1674             if bbox.InsideXY(x_mouse, y_mouse):
  1698                 panel.Canvas.ShowButtons(True)
  1675                 panel.ShowButtons(True)
  1699                 merge_type = GRAPH_PARALLEL
  1676                 merge_type = GRAPH_PARALLEL
  1700                 if panel.Is3DCanvas():
  1677                 if isinstance(panel, DebugVariableText) or panel.Is3DCanvas():
  1701                     if y_mouse > yw + height / 2:
  1678                     if y_mouse > yw + height / 2:
  1702                         idx += 1
  1679                         idx += 1
  1703                     wx.CallAfter(self.MoveGraph, variable, idx)
  1680                     wx.CallAfter(self.MoveGraph, variable, idx)
  1704                 else:
  1681                 else:
  1705                     rect = panel.GetAxesBoundingBox(True)
  1682                     rect = panel.GetAxesBoundingBox(True)
  1731             dc.BeginDrawing()
  1708             dc.BeginDrawing()
  1732             if self.DraggingAxesPanel is not None:
  1709             if self.DraggingAxesPanel is not None:
  1733                 destBBox = self.DraggingAxesBoundingBox
  1710                 destBBox = self.DraggingAxesBoundingBox
  1734                 srcBBox = self.DraggingAxesPanel.GetAxesBoundingBox()
  1711                 srcBBox = self.DraggingAxesPanel.GetAxesBoundingBox()
  1735                 
  1712                 
  1736                 srcBmp = _convert_agg_to_wx_bitmap(self.DraggingAxesPanel.Canvas.get_renderer(), None)
  1713                 srcBmp = _convert_agg_to_wx_bitmap(self.DraggingAxesPanel.get_renderer(), None)
  1737                 srcDC = wx.MemoryDC()
  1714                 srcDC = wx.MemoryDC()
  1738                 srcDC.SelectObject(srcBmp)
  1715                 srcDC.SelectObject(srcBmp)
  1739                     
  1716                     
  1740                 dc.Blit(destBBox.x, destBBox.y, 
  1717                 dc.Blit(destBBox.x, destBBox.y, 
  1741                         int(destBBox.width), int(destBBox.height), 
  1718                         int(destBBox.width), int(destBBox.height), 
  1747                 refresh_graphics = True
  1724                 refresh_graphics = True
  1748             else:
  1725             else:
  1749                 refresh_graphics = False
  1726                 refresh_graphics = False
  1750             
  1727             
  1751             if self.DraggingAxesPanel is not None and self.DraggingAxesPanel not in self.GraphicPanels:
  1728             if self.DraggingAxesPanel is not None and self.DraggingAxesPanel not in self.GraphicPanels:
  1752                 self.DraggingAxesPanel.Refresh(refresh_graphics)
  1729                 self.DraggingAxesPanel.RefreshViewer(refresh_graphics)
  1753             for panel in self.GraphicPanels:
  1730             for panel in self.GraphicPanels:
  1754                 if isinstance(panel, DebugVariableGraphic):
  1731                 if isinstance(panel, DebugVariableGraphic):
  1755                     panel.Refresh(refresh_graphics)
  1732                     panel.RefreshViewer(refresh_graphics)
  1756                 else:
  1733                 else:
  1757                     panel.Refresh()
  1734                     panel.RefreshViewer()
  1758             
  1735             
  1759             if self.CursorTick is not None:
  1736             if self.CursorTick is not None:
  1760                 tick = self.CursorTick
  1737                 tick = self.CursorTick
  1761             elif len(self.Ticks) > 0:
  1738             elif len(self.Ticks) > 0:
  1762                 tick = self.Ticks[-1]
  1739                 tick = self.Ticks[-1]
  1806                 self.RefreshCanvasRange()
  1783                 self.RefreshCanvasRange()
  1807             
  1784             
  1808             for panel in self.GraphicPanels:
  1785             for panel in self.GraphicPanels:
  1809                 panel.UnregisterObsoleteData()
  1786                 panel.UnregisterObsoleteData()
  1810                 if panel.IsEmpty():
  1787                 if panel.IsEmpty():
  1811                     if panel.Canvas.HasCapture():
  1788                     if panel.HasCapture():
  1812                         panel.Canvas.ReleaseMouse()
  1789                         panel.ReleaseMouse()
  1813                     self.GraphicPanels.remove(panel)
  1790                     self.GraphicPanels.remove(panel)
  1814                     panel.Destroy()
  1791                     panel.Destroy()
  1815             
  1792             
  1816             self.ResetVariableNameMask()
  1793             self.ResetVariableNameMask()
  1817             self.RefreshGraphicsSizer()
  1794             self.RefreshGraphicsSizer()
  2035         if self.IsViewerFirst(viewer):
  2012         if self.IsViewerFirst(viewer):
  2036             return
  2013             return
  2037         idx = self.GetViewerIndex(viewer)
  2014         idx = self.GetViewerIndex(viewer)
  2038         if idx is None:
  2015         if idx is None:
  2039             return
  2016             return
  2040         self.GraphicPanels[idx-1].HighlightCanvas(HIGHLIGHT_AFTER)
  2017         self.GraphicPanels[idx-1].SetHighlight(HIGHLIGHT_AFTER)
  2041     
  2018     
  2042     def ResetVariableNameMask(self):
  2019     def ResetVariableNameMask(self):
  2043         items = []
  2020         items = []
  2044         for panel in self.GraphicPanels:
  2021         for panel in self.GraphicPanels:
  2045             items.extend(panel.GetItems())
  2022             items.extend(panel.GetItems())
  2102                 source_panel = panel
  2079                 source_panel = panel
  2103                 break
  2080                 break
  2104         if source_panel is not None:
  2081         if source_panel is not None:
  2105             source_panel.RemoveItem(item)
  2082             source_panel.RemoveItem(item)
  2106             if source_panel.IsEmpty():
  2083             if source_panel.IsEmpty():
  2107                 if source_panel.Canvas.HasCapture():
  2084                 if source_panel.HasCapture():
  2108                     source_panel.Canvas.ReleaseMouse()
  2085                     source_panel.ReleaseMouse()
  2109                 self.GraphicPanels.remove(source_panel)
  2086                 self.GraphicPanels.remove(source_panel)
  2110                 source_panel.Destroy()
  2087                 source_panel.Destroy()
  2111             
  2088             
  2112             panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  2089             panel = DebugVariableGraphic(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
  2113             if self.CursorTick is not None:
  2090             if self.CursorTick is not None:
  2142                     return
  2119                     return
  2143                 
  2120                 
  2144                 if source_panel is not None:
  2121                 if source_panel is not None:
  2145                     source_panel.RemoveItem(source_item)
  2122                     source_panel.RemoveItem(source_item)
  2146                     if source_panel.IsEmpty():
  2123                     if source_panel.IsEmpty():
  2147                         if source_panel.Canvas.HasCapture():
  2124                         if source_panel.HasCapture():
  2148                             source_panel.Canvas.ReleaseMouse()
  2125                             source_panel.ReleaseMouse()
  2149                         self.GraphicPanels.remove(source_panel)
  2126                         self.GraphicPanels.remove(source_panel)
  2150                         source_panel.Destroy()
  2127                         source_panel.Destroy()
  2151             elif (merge_type != graph_type and len(target_panel.Items) == 2):
  2128             elif (merge_type != graph_type and len(target_panel.Items) == 2):
  2152                 target_panel.RemoveItem(source_item)
  2129                 target_panel.RemoveItem(source_item)
  2153             else:
  2130             else: