editors/GraphicViewer.py
changeset 887 d3c6c4ab8b28
parent 814 5743cbdff669
child 902 ffa8ee5ee2fe
equal deleted inserted replaced
886:ace92afe9100 887:d3c6c4ab8b28
   163         self.Dragging = False
   163         self.Dragging = False
   164         
   164         
   165         # Initialize Viewer mode to Selection mode
   165         # Initialize Viewer mode to Selection mode
   166         self.Mode = MODE_SELECTION
   166         self.Mode = MODE_SELECTION
   167         
   167         
   168         self.Datas = []
   168         self.Data = numpy.array([]).reshape(0, 2)
   169         self.StartTick = 0
   169         self.StartTick = 0
   170         self.StartIdx = 0
   170         self.StartIdx = 0
   171         self.EndIdx = 0
   171         self.EndIdx = 0
   172         self.MinValue = None
   172         self.MinValue = None
   173         self.MaxValue = None
   173         self.MaxValue = None
   200             self.Mode = mode
   200             self.Mode = mode
   201         if self.Mode == MODE_MOTION:
   201         if self.Mode == MODE_MOTION:
   202             wx.CallAfter(self.Canvas.canvas.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
   202             wx.CallAfter(self.Canvas.canvas.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
   203         
   203         
   204     def ResetView(self, register=False):
   204     def ResetView(self, register=False):
   205         self.Datas = []
   205         self.Data = numpy.array([]).reshape(0, 2)
   206         self.StartTick = 0
   206         self.StartTick = 0
   207         self.StartIdx = 0
   207         self.StartIdx = 0
   208         self.EndIdx = 0
   208         self.EndIdx = 0
   209         self.MinValue = None
   209         self.MinValue = None
   210         self.MaxValue = None
   210         self.MaxValue = None
   220     def RefreshNewData(self, *args, **kwargs):
   220     def RefreshNewData(self, *args, **kwargs):
   221         self.RefreshView(*args, **kwargs)
   221         self.RefreshView(*args, **kwargs)
   222         DebugViewer.RefreshNewData(self)
   222         DebugViewer.RefreshNewData(self)
   223     
   223     
   224     def GetNearestData(self, tick, adjust):
   224     def GetNearestData(self, tick, adjust):
   225         ticks = numpy.array(zip(*self.Datas)[0])
   225         ticks = self.Data[:, 0]
   226         new_cursor = numpy.argmin(abs(ticks - tick))
   226         new_cursor = numpy.argmin(abs(ticks - tick))
   227         if adjust == -1 and ticks[new_cursor] > tick and new_cursor > 0:
   227         if adjust == -1 and ticks[new_cursor] > tick and new_cursor > 0:
   228             new_cursor -= 1
   228             new_cursor -= 1
   229         elif adjust == 1 and ticks[new_cursor] < tick and new_cursor < len(self.Datas):
   229         elif adjust == 1 and ticks[new_cursor] < tick and new_cursor < len(ticks):
   230             new_cursor += 1
   230             new_cursor += 1
   231         return new_cursor
   231         return new_cursor
   232     
   232     
   233     def GetBounds(self):
   233     def GetBounds(self):
   234         if self.StartIdx is None or self.EndIdx is None:
   234         if self.StartIdx is None or self.EndIdx is None:
   255             self.CanvasRange.SetStringSelection(TIME_RANGE_VALUES[0][0])
   255             self.CanvasRange.SetStringSelection(TIME_RANGE_VALUES[0][0])
   256             self.CurrentRange = TIME_RANGE_VALUES[0][1] / self.Ticktime
   256             self.CurrentRange = TIME_RANGE_VALUES[0][1] / self.Ticktime
   257         
   257         
   258     def RefreshView(self, force=False):
   258     def RefreshView(self, force=False):
   259         self.Freeze()
   259         self.Freeze()
   260         if force or not self.Fixed or (len(self.Datas) > 0 and self.StartTick + self.CurrentRange > self.Datas[-1][0]):
   260         if force or not self.Fixed or (len(self.Data) > 0 and self.StartTick + self.CurrentRange > self.Data[-1, 0]):
   261             if (self.MinValue is not None and 
   261             if (self.MinValue is not None and 
   262                 self.MaxValue is not None and 
   262                 self.MaxValue is not None and 
   263                 self.MinValue != self.MaxValue):
   263                 self.MinValue != self.MaxValue):
   264                 Yrange = float(self.MaxValue - self.MinValue) / self.CurrentZoom
   264                 Yrange = float(self.MaxValue - self.MinValue) / self.CurrentZoom
   265             else:
   265             else:
   266                 Yrange = 2. / self.CurrentZoom
   266                 Yrange = 2. / self.CurrentZoom
   267             
   267             
   268             if not force and not self.Fixed and len(self.Datas) > 0:
   268             if not force and not self.Fixed and len(self.Data) > 0:
   269                 self.YCenter = max(self.Datas[-1][1] - Yrange / 2, 
   269                 self.YCenter = max(self.Data[-1, 1] - Yrange / 2, 
   270                                min(self.YCenter, 
   270                                min(self.YCenter, 
   271                                    self.Datas[-1][1] + Yrange / 2))
   271                                    self.Data[-1, 1] + Yrange / 2))
   272             
   272             
   273             var_name = self.InstancePath.split(".")[-1]
   273             var_name = self.InstancePath.split(".")[-1]
   274             
   274             
   275             self.GetBounds()
   275             self.GetBounds()
   276             self.VariableGraphic = plot.PolyLine(self.Datas[self.StartIdx:self.EndIdx + 1], 
   276             self.VariableGraphic = plot.PolyLine(self.Data[self.StartIdx:self.EndIdx + 1], 
   277                                                  legend=var_name, colour=colours[0])
   277                                                  legend=var_name, colour=colours[0])
   278             self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], _("%s Graphics") % var_name, _("Tick"), _("Values"))
   278             self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], _("%s Graphics") % var_name, _("Tick"), _("Values"))
   279             self.Canvas.Draw(self.GraphicsObject, 
   279             self.Canvas.Draw(self.GraphicsObject, 
   280                              xAxis=(self.StartTick, self.StartTick + self.CurrentRange),
   280                              xAxis=(self.StartTick, self.StartTick + self.CurrentRange),
   281                              yAxis=(self.YCenter - Yrange * 1.1 / 2., self.YCenter + Yrange * 1.1 / 2.))
   281                              yAxis=(self.YCenter - Yrange * 1.1 / 2., self.YCenter + Yrange * 1.1 / 2.))
   294     def IsViewing(self, tagname):
   294     def IsViewing(self, tagname):
   295         return self.InstancePath == tagname
   295         return self.InstancePath == tagname
   296     
   296     
   297     def NewValue(self, tick, value, forced=False):
   297     def NewValue(self, tick, value, forced=False):
   298         value = {True:1., False:0.}.get(value, float(value))
   298         value = {True:1., False:0.}.get(value, float(value))
   299         self.Datas.append((float(tick), value))
   299         self.Data = numpy.append(self.Data, [[float(tick), value]], axis=0)
   300         if self.MinValue is None:
   300         if self.MinValue is None:
   301             self.MinValue = value
   301             self.MinValue = value
   302         else:
   302         else:
   303             self.MinValue = min(self.MinValue, value)
   303             self.MinValue = min(self.MinValue, value)
   304         if self.MaxValue is None:
   304         if self.MaxValue is None:
   305             self.MaxValue = value
   305             self.MaxValue = value
   306         else:
   306         else:
   307             self.MaxValue = max(self.MaxValue, value)
   307             self.MaxValue = max(self.MaxValue, value)
   308         if not self.Fixed or tick < self.StartTick + self.CurrentRange:
   308         if not self.Fixed or tick < self.StartTick + self.CurrentRange:
   309             self.GetBounds()
   309             self.GetBounds()
   310             while int(self.Datas[self.StartIdx][0]) < tick - self.CurrentRange:
   310             while int(self.Data[self.StartIdx, 0]) < tick - self.CurrentRange:
   311                 self.StartIdx += 1
   311                 self.StartIdx += 1
   312             self.EndIdx += 1
   312             self.EndIdx += 1
   313             self.StartTick = self.Datas[self.StartIdx][0]
   313             self.StartTick = self.Data[self.StartIdx, 0]
   314         self.NewDataAvailable()
   314         self.NewDataAvailable()
   315     
   315     
   316     def RefreshScrollBar(self):
   316     def RefreshScrollBar(self):
   317         if len(self.Datas) > 0:
   317         if len(self.Data) > 0:
   318             self.GetBounds()
   318             self.GetBounds()
   319             pos = int(self.Datas[self.StartIdx][0] - self.Datas[0][0])
   319             pos = int(self.Data[self.StartIdx, 0] - self.Data[0, 0])
   320             range = int(self.Datas[-1][0] - self.Datas[0][0])
   320             range = int(self.Data[-1, 0] - self.Data[0, 0])
   321         else:
   321         else:
   322             pos = 0
   322             pos = 0
   323             range = 0
   323             range = 0
   324         self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange)
   324         self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange)
   325 
   325 
   326     def RefreshRange(self):
   326     def RefreshRange(self):
   327         if len(self.Datas) > 0:
   327         if len(self.Data) > 0:
   328             if self.Fixed and self.Datas[-1][0] - self.Datas[0][0] < self.CurrentRange:
   328             if self.Fixed and self.Data[-1, 0] - self.Data[0, 0] < self.CurrentRange:
   329                 self.Fixed = False
   329                 self.Fixed = False
   330             self.ResetBounds()
   330             self.ResetBounds()
   331             if self.Fixed:
   331             if self.Fixed:
   332                 self.StartTick = min(self.StartTick, self.Datas[-1][0] - self.CurrentRange)
   332                 self.StartTick = min(self.StartTick, self.Data[-1, 0] - self.CurrentRange)
   333             else:
   333             else:
   334                 self.StartTick = max(self.Datas[0][0], self.Datas[-1][0] - self.CurrentRange)
   334                 self.StartTick = max(self.Data[0, 0], self.Data[-1, 0] - self.CurrentRange)
   335         self.RefreshView(True)
   335         self.RefreshView(True)
   336 
   336 
   337     def OnRangeChanged(self, event):
   337     def OnRangeChanged(self, event):
   338         try:
   338         try:
   339             if self.Ticktime == 0:
   339             if self.Ticktime == 0:
   349         self.CurrentZoom = ZOOM_VALUES[self.CanvasZoom.GetSelection()][1]
   349         self.CurrentZoom = ZOOM_VALUES[self.CanvasZoom.GetSelection()][1]
   350         wx.CallAfter(self.RefreshView, True)
   350         wx.CallAfter(self.RefreshView, True)
   351         event.Skip()
   351         event.Skip()
   352     
   352     
   353     def OnPositionChanging(self, event):
   353     def OnPositionChanging(self, event):
   354         if len(self.Datas) > 0:
   354         if len(self.Data) > 0:
   355             self.ResetBounds()
   355             self.ResetBounds()
   356             self.StartTick = self.Datas[0][0] + event.GetPosition()
   356             self.StartTick = self.Data[0, 0] + event.GetPosition()
   357             self.Fixed = True
   357             self.Fixed = True
   358             self.NewDataAvailable(True)
   358             self.NewDataAvailable(True)
   359         event.Skip()
   359         event.Skip()
   360 
   360 
   361     def OnResetButton(self, event):
   361     def OnResetButton(self, event):
   362         self.Fixed = False
   362         self.Fixed = False
   363         self.ResetView()
   363         self.ResetView()
   364         event.Skip()
   364         event.Skip()
   365 
   365 
   366     def OnCurrentButton(self, event):
   366     def OnCurrentButton(self, event):
   367         if len(self.Datas) > 0:
   367         if len(self.Data) > 0:
   368             self.ResetBounds()
   368             self.ResetBounds()
   369             self.StartTick = max(self.Datas[0][0], self.Datas[-1][0] - self.CurrentRange)
   369             self.StartTick = max(self.Data[0, 0], self.Data[-1, 0] - self.CurrentRange)
   370             self.Fixed = False
   370             self.Fixed = False
   371             self.NewDataAvailable(True)
   371             self.NewDataAvailable(True)
   372         event.Skip()
   372         event.Skip()
   373     
   373     
   374     def OnResetZoomOffsetButton(self, event):
   374     def OnResetZoomOffsetButton(self, event):
   375         if len(self.Datas) > 0:
   375         if len(self.Data) > 0:
   376             self.YCenter = (self.MaxValue + self.MinValue) / 2
   376             self.YCenter = (self.MaxValue + self.MinValue) / 2
   377         else:
   377         else:
   378             self.YCenter = 0.0
   378             self.YCenter = 0.0
   379         self.CurrentZoom = 1.0
   379         self.CurrentZoom = 1.0
   380         self.CanvasZoom.SetSelection(0)
   380         self.CanvasZoom.SetSelection(0)
   381         wx.CallAfter(self.RefreshView, True)
   381         wx.CallAfter(self.RefreshView, True)
   382         event.Skip()
   382         event.Skip()
   383     
   383     
   384     def OnExportGraphButtonClick(self, event):
   384     def OnExportGraphButtonClick(self, event):
   385         data_copy = self.Datas[:]
   385         data_copy = self.Data[:]
   386         text = "tick;%s;\n" % self.InstancePath
   386         text = "tick;%s;\n" % self.InstancePath
   387         for tick, value in data_copy:
   387         for tick, value in data_copy:
   388             text += "%d;%.3f;\n" % (tick, value)
   388             text += "%d;%.3f;\n" % (tick, value)
   389         self.ParentWindow.SetCopyBuffer(text)
   389         self.ParentWindow.SetCopyBuffer(text)
   390         event.Skip()
   390         event.Skip()
   391 
   391 
   392     def OnCanvasLeftDown(self, event):
   392     def OnCanvasLeftDown(self, event):
   393         self.Fixed = True
   393         self.Fixed = True
   394         self.Canvas.canvas.CaptureMouse()
   394         self.Canvas.canvas.CaptureMouse()
   395         if len(self.Datas) > 0:
   395         if len(self.Data) > 0:
   396             if self.Mode == MODE_SELECTION:
   396             if self.Mode == MODE_SELECTION:
   397                 self.Dragging = True
   397                 self.Dragging = True
   398                 pos = self.Canvas.PositionScreenToUser(event.GetPosition())
   398                 pos = self.Canvas.PositionScreenToUser(event.GetPosition())
   399                 self.CursorIdx = self.GetNearestData(pos[0], -1)
   399                 self.CursorIdx = self.GetNearestData(pos[0], -1)
   400                 self.RefreshCursor()
   400                 self.RefreshCursor()
   401             elif self.Mode == MODE_MOTION:
   401             elif self.Mode == MODE_MOTION:
   402                 self.GetBounds()
   402                 self.GetBounds()
   403                 self.CurrentMousePos = event.GetPosition()
   403                 self.CurrentMousePos = event.GetPosition()
   404                 self.CurrentMotionValue = self.Datas[self.StartIdx][0]
   404                 self.CurrentMotionValue = self.Data[self.StartIdx, 0]
   405         event.Skip()
   405         event.Skip()
   406     
   406     
   407     def OnCanvasLeftUp(self, event):
   407     def OnCanvasLeftUp(self, event):
   408         self.Dragging = False
   408         self.Dragging = False
   409         if self.Mode == MODE_MOTION:
   409         if self.Mode == MODE_MOTION:
   414         event.Skip()
   414         event.Skip()
   415     
   415     
   416     def OnCanvasMiddleDown(self, event):
   416     def OnCanvasMiddleDown(self, event):
   417         self.Fixed = True
   417         self.Fixed = True
   418         self.Canvas.canvas.CaptureMouse()
   418         self.Canvas.canvas.CaptureMouse()
   419         if len(self.Datas) > 0:
   419         if len(self.Data) > 0:
   420             self.GetBounds()
   420             self.GetBounds()
   421             self.CurrentMousePos = event.GetPosition()
   421             self.CurrentMousePos = event.GetPosition()
   422             self.CurrentMotionValue = self.Datas[self.StartIdx][0]
   422             self.CurrentMotionValue = self.Data[self.StartIdx, 0]
   423         event.Skip()
   423         event.Skip()
   424         
   424         
   425     def OnCanvasMiddleUp(self, event):
   425     def OnCanvasMiddleUp(self, event):
   426         self.CurrentMousePos = None
   426         self.CurrentMousePos = None
   427         self.CurrentMotionValue = None
   427         self.CurrentMotionValue = None
   433         if self.Mode == MODE_SELECTION and self.Dragging:
   433         if self.Mode == MODE_SELECTION and self.Dragging:
   434             pos = self.Canvas.PositionScreenToUser(event.GetPosition())
   434             pos = self.Canvas.PositionScreenToUser(event.GetPosition())
   435             graphics, xAxis, yAxis = self.Canvas.last_draw
   435             graphics, xAxis, yAxis = self.Canvas.last_draw
   436             self.CursorIdx = self.GetNearestData(max(xAxis[0], min(pos[0], xAxis[1])), -1)
   436             self.CursorIdx = self.GetNearestData(max(xAxis[0], min(pos[0], xAxis[1])), -1)
   437             self.RefreshCursor()
   437             self.RefreshCursor()
   438         elif self.CurrentMousePos is not None and len(self.Datas) > 0:
   438         elif self.CurrentMousePos is not None and len(self.Data) > 0:
   439             oldpos = self.Canvas.PositionScreenToUser(self.CurrentMousePos)
   439             oldpos = self.Canvas.PositionScreenToUser(self.CurrentMousePos)
   440             newpos = self.Canvas.PositionScreenToUser(event.GetPosition())
   440             newpos = self.Canvas.PositionScreenToUser(event.GetPosition())
   441             self.CurrentMotionValue += oldpos[0] - newpos[0]
   441             self.CurrentMotionValue += oldpos[0] - newpos[0]
   442             self.YCenter += oldpos[1] - newpos[1]
   442             self.YCenter += oldpos[1] - newpos[1]
   443             self.ResetBounds()
   443             self.ResetBounds()
   444             self.StartTick = max(self.Datas[0][0], min(self.CurrentMotionValue, self.Datas[-1][0] - self.CurrentRange))
   444             self.StartTick = max(self.Data[0, 0], min(self.CurrentMotionValue, self.Data[-1, 0] - self.CurrentRange))
   445             self.CurrentMousePos = event.GetPosition()
   445             self.CurrentMousePos = event.GetPosition()
   446             self.NewDataAvailable(True)
   446             self.NewDataAvailable(True)
   447         event.Skip()
   447         event.Skip()
   448 
   448 
   449     def OnCanvasMouseWheel(self, event):
   449     def OnCanvasMouseWheel(self, event):
   536             if self.LastCursor is not None:
   536             if self.LastCursor is not None:
   537                 self.DrawCursor(dc, *self.LastCursor)
   537                 self.DrawCursor(dc, *self.LastCursor)
   538             
   538             
   539             # Draw new time cursor
   539             # Draw new time cursor
   540             if self.CursorIdx is not None:
   540             if self.CursorIdx is not None:
   541                 self.LastCursor = self.Datas[self.CursorIdx]
   541                 self.LastCursor = self.Data[self.CursorIdx]
   542                 self.DrawCursor(dc, *self.LastCursor)
   542                 self.DrawCursor(dc, *self.LastCursor)