41 from util.BitmapLibrary import GetBitmap |
41 from util.BitmapLibrary import GetBitmap |
42 |
42 |
43 from controls.DebugVariablePanel.DebugVariableItem import DebugVariableItem |
43 from controls.DebugVariablePanel.DebugVariableItem import DebugVariableItem |
44 from controls.DebugVariablePanel.DebugVariableTextViewer import DebugVariableTextViewer |
44 from controls.DebugVariablePanel.DebugVariableTextViewer import DebugVariableTextViewer |
45 from controls.DebugVariablePanel.DebugVariableGraphicViewer import * |
45 from controls.DebugVariablePanel.DebugVariableGraphicViewer import * |
|
46 from controls.DebugVariablePanel.RingBuffer import RingBuffer |
46 |
47 |
47 |
48 |
48 MILLISECOND = 1000000 # Number of nanosecond in a millisecond |
49 MILLISECOND = 1000000 # Number of nanosecond in a millisecond |
49 SECOND = 1000 * MILLISECOND # Number of nanosecond in a second |
50 SECOND = 1000 * MILLISECOND # Number of nanosecond in a second |
50 MINUTE = 60 * SECOND # Number of nanosecond in a minute |
51 MINUTE = 60 * SECOND # Number of nanosecond in a minute |
203 |
204 |
204 self.SetBackgroundColour(wx.WHITE) |
205 self.SetBackgroundColour(wx.WHITE) |
205 |
206 |
206 main_sizer = wx.BoxSizer(wx.VERTICAL) |
207 main_sizer = wx.BoxSizer(wx.VERTICAL) |
207 |
208 |
208 self.Ticks = numpy.array([]) # List of tick received |
209 self.Ticks = RingBuffer() # List of tick received |
209 self.StartTick = 0 # Tick starting range of data displayed |
210 self.StartTick = 0 # Tick starting range of data displayed |
210 self.Fixed = False # Flag that range of data is fixed |
211 self.Fixed = False # Flag that range of data is fixed |
211 self.CursorTick = None # Tick of cursor for displaying values |
212 self.CursorTick = None # Tick of cursor for displaying values |
212 |
213 |
213 self.DraggingAxesPanel = None |
214 self.DraggingAxesPanel = None |
342 # If tick given |
343 # If tick given |
343 if ticks is not None: |
344 if ticks is not None: |
344 tick = ticks[-1] |
345 tick = ticks[-1] |
345 |
346 |
346 # Save tick as start tick for range if data is still empty |
347 # Save tick as start tick for range if data is still empty |
347 if len(self.Ticks) == 0: |
348 if self.Ticks.count == 0: |
348 self.StartTick = ticks[0] |
349 self.StartTick = ticks[0] |
349 |
350 |
350 # Add tick to list of ticks received |
351 # Add tick to list of ticks received |
351 self.Ticks = numpy.append(self.Ticks, ticks) |
352 self.Ticks.append(ticks) |
352 |
353 |
353 # Update start tick for range if range follow ticks received |
354 # Update start tick for range if range follow ticks received |
354 if not self.Fixed or tick < self.StartTick + self.CurrentRange: |
355 if not self.Fixed or tick < self.StartTick + self.CurrentRange: |
355 self.StartTick = max(self.StartTick, tick - self.CurrentRange) |
356 self.StartTick = max(self.StartTick, tick - self.CurrentRange) |
356 |
357 |
357 # Force refresh if graph is fixed because range of data received |
358 # Force refresh if graph is fixed because range of data received |
358 # is too small to fill data range selected |
359 # is too small to fill data range selected |
359 if self.Fixed and \ |
360 if self.Fixed and \ |
360 self.Ticks[-1] - self.Ticks[0] < self.CurrentRange: |
361 self.Ticks.view[-1] - self.Ticks.view[0] < self.CurrentRange: |
361 self.Force = True |
362 self.Force = True |
362 |
363 |
363 self.HasNewData = False |
364 self.HasNewData = False |
364 self.RefreshView() |
365 self.RefreshView() |
365 |
366 |
383 self.Fixed = cursor_tick is not None |
384 self.Fixed = cursor_tick is not None |
384 self.UpdateCursorTick() |
385 self.UpdateCursorTick() |
385 |
386 |
386 def MoveCursorTick(self, move): |
387 def MoveCursorTick(self, move): |
387 if self.CursorTick is not None: |
388 if self.CursorTick is not None: |
388 cursor_tick = max(self.Ticks[0], |
389 cursor_tick = max(self.Ticks.view[0], |
389 min(self.CursorTick + move, self.Ticks[-1])) |
390 min(self.CursorTick + move, self.Ticks.view[-1])) |
390 cursor_tick_idx = numpy.argmin(numpy.abs(self.Ticks - cursor_tick)) |
391 cursor_tick_idx = np.searchsorted(self.Ticks.view, cursor_tick) |
391 if self.Ticks[cursor_tick_idx] == self.CursorTick: |
392 if self.Ticks.view[cursor_tick_idx] == self.CursorTick: |
392 cursor_tick_idx = max(0, |
393 cursor_tick_idx = max(0, |
393 min(cursor_tick_idx + abs(move) // move, |
394 min(cursor_tick_idx + abs(move) // move, |
394 len(self.Ticks) - 1)) |
395 self.Ticks.count - 1)) |
395 self.CursorTick = self.Ticks[cursor_tick_idx] |
396 self.CursorTick = self.Ticks.view[cursor_tick_idx] |
396 self.StartTick = max( |
397 self.StartTick = max( |
397 self.Ticks[numpy.argmin( |
398 self.Ticks.view[np.searchsorted(self.Ticks.view, self.CursorTick + self.CurrentRange)], |
398 numpy.abs(self.Ticks - self.CursorTick + self.CurrentRange))], |
|
399 min(self.StartTick, self.CursorTick)) |
399 min(self.StartTick, self.CursorTick)) |
400 self.RefreshCanvasPosition() |
400 self.RefreshCanvasPosition() |
401 self.UpdateCursorTick() |
401 self.UpdateCursorTick() |
402 |
402 |
403 def ResetCursorTick(self): |
403 def ResetCursorTick(self): |
545 else: |
545 else: |
546 panel.RefreshViewer() |
546 panel.RefreshViewer() |
547 |
547 |
548 if self.CursorTick is not None: |
548 if self.CursorTick is not None: |
549 tick = self.CursorTick |
549 tick = self.CursorTick |
550 elif len(self.Ticks) > 0: |
550 elif self.Ticks.count > 0: |
551 tick = self.Ticks[-1] |
551 tick = self.Ticks.view[-1] |
552 else: |
552 else: |
553 tick = None |
553 tick = None |
554 if tick is not None: |
554 if tick is not None: |
555 self.TickLabel.SetLabel(label=_("Tick: %d") % tick) |
555 self.TickLabel.SetLabel(label=_("Tick: %d") % tick) |
556 tick_duration = int(tick * self.Ticktime) |
556 tick_duration = int(tick * self.Ticktime) |
602 self.GraphicPanels = [] |
602 self.GraphicPanels = [] |
603 self.ResetVariableNameMask() |
603 self.ResetVariableNameMask() |
604 self.RefreshGraphicsSizer() |
604 self.RefreshGraphicsSizer() |
605 |
605 |
606 def SetCanvasPosition(self, tick): |
606 def SetCanvasPosition(self, tick): |
607 tick = max(self.Ticks[0], min(tick, self.Ticks[-1] - self.CurrentRange)) |
607 tick = max(self.Ticks.view[0], min(tick, self.Ticks.view[-1] - self.CurrentRange)) |
608 self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - tick))] |
608 self.StartTick = self.Ticks.view[np.searchsorted(self.Ticks.view, tick)] |
609 self.Fixed = True |
609 self.Fixed = True |
610 self.RefreshCanvasPosition() |
610 self.RefreshCanvasPosition() |
611 self.ForceRefresh() |
611 self.ForceRefresh() |
612 |
612 |
613 def RefreshCanvasPosition(self): |
613 def RefreshCanvasPosition(self): |
614 if len(self.Ticks) > 0: |
614 if len(self.Ticks.view) > 0: |
615 pos = int(self.StartTick - self.Ticks[0]) |
615 pos = int(self.StartTick - self.Ticks.view[0]) |
616 range = int(self.Ticks[-1] - self.Ticks[0]) |
616 range = int(self.Ticks.view[-1] - self.Ticks.view[0]) |
617 else: |
617 else: |
618 pos = 0 |
618 pos = 0 |
619 range = 0 |
619 range = 0 |
620 self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange) |
620 self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange) |
621 |
621 |
624 current_range_idx = self.CanvasRange.GetSelection() |
624 current_range_idx = self.CanvasRange.GetSelection() |
625 new_range_idx = max(0, min(current_range_idx + dir, len(self.RANGE_VALUES) - 1)) |
625 new_range_idx = max(0, min(current_range_idx + dir, len(self.RANGE_VALUES) - 1)) |
626 if new_range_idx != current_range_idx: |
626 if new_range_idx != current_range_idx: |
627 self.CanvasRange.SetSelection(new_range_idx) |
627 self.CanvasRange.SetSelection(new_range_idx) |
628 self.CurrentRange = self.RANGE_VALUES[new_range_idx][1] / self.Ticktime |
628 self.CurrentRange = self.RANGE_VALUES[new_range_idx][1] / self.Ticktime |
629 if len(self.Ticks) > 0: |
629 if self.Ticks.count > 0: |
630 if tick is None: |
630 if tick is None: |
631 tick = self.StartTick + self.CurrentRange / 2. |
631 tick = self.StartTick + self.CurrentRange / 2. |
632 new_start_tick = min(tick - (tick - self.StartTick) * self.CurrentRange / current_range, |
632 new_start_tick = min(tick - (tick - self.StartTick) * self.CurrentRange / current_range, |
633 self.Ticks[-1] - self.CurrentRange) |
633 self.Ticks.view[-1] - self.CurrentRange) |
634 self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - new_start_tick))] |
634 self.StartTick = self.Ticks.view[np.searchsorted(self.Ticks.view, - new_start_tick)] |
635 self.Fixed = new_start_tick < self.Ticks[-1] - self.CurrentRange |
635 self.Fixed = new_start_tick < self.Ticks.view[-1] - self.CurrentRange |
636 self.ForceRefresh() |
636 self.ForceRefresh() |
637 |
637 |
638 def RefreshRange(self): |
638 def RefreshRange(self): |
639 if len(self.Ticks) > 0: |
639 if self.Ticks.count > 0: |
640 if self.Fixed and self.Ticks[-1] - self.Ticks[0] < self.CurrentRange: |
640 if self.Fixed and self.Ticks.view[-1] - self.Ticks.view[0] < self.CurrentRange: |
641 self.Fixed = False |
641 self.Fixed = False |
642 if self.Fixed: |
642 if self.Fixed: |
643 self.StartTick = min(self.StartTick, self.Ticks[-1] - self.CurrentRange) |
643 self.StartTick = min(self.StartTick, self.Ticks.view[-1] - self.CurrentRange) |
644 else: |
644 else: |
645 self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange) |
645 self.StartTick = max(self.Ticks.view[0], self.Ticks.view[-1] - self.CurrentRange) |
646 self.ForceRefresh() |
646 self.ForceRefresh() |
647 |
647 |
648 def OnRangeChanged(self, event): |
648 def OnRangeChanged(self, event): |
649 try: |
649 try: |
650 self.CurrentRange = self.RANGE_VALUES[self.CanvasRange.GetSelection()][1] // self.Ticktime |
650 self.CurrentRange = self.RANGE_VALUES[self.CanvasRange.GetSelection()][1] // self.Ticktime |
652 self.CanvasRange.SetValue(str(self.CurrentRange)) |
652 self.CanvasRange.SetValue(str(self.CurrentRange)) |
653 wx.CallAfter(self.RefreshRange) |
653 wx.CallAfter(self.RefreshRange) |
654 event.Skip() |
654 event.Skip() |
655 |
655 |
656 def OnCurrentButton(self, event): |
656 def OnCurrentButton(self, event): |
657 if len(self.Ticks) > 0: |
657 if self.Ticks.count > 0: |
658 self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange) |
658 self.StartTick = max(self.Ticks.view[0], self.Ticks.view[-1] - self.CurrentRange) |
659 self.ResetCursorTick() |
659 self.ResetCursorTick() |
660 event.Skip() |
660 event.Skip() |
661 |
661 |
662 def CopyDataToClipboard(self, variables): |
662 def CopyDataToClipboard(self, variables): |
663 text = "tick;%s;\n" % ";".join([item.GetVariable() for item, data in variables]) |
663 text = "tick;%s;\n" % ";".join([item.GetVariable() for item, data in variables]) |
693 if item.IsNumVariable()] |
693 if item.IsNumVariable()] |
694 wx.CallAfter(self.CopyDataToClipboard, variables) |
694 wx.CallAfter(self.CopyDataToClipboard, variables) |
695 event.Skip() |
695 event.Skip() |
696 |
696 |
697 def OnPositionChanging(self, event): |
697 def OnPositionChanging(self, event): |
698 if len(self.Ticks) > 0: |
698 if self.Ticks.count > 0: |
699 self.StartTick = self.Ticks[0] + event.GetPosition() |
699 self.StartTick = self.Ticks.view[0] + event.GetPosition() |
700 self.Fixed = True |
700 self.Fixed = True |
701 self.ForceRefresh() |
701 self.ForceRefresh() |
702 event.Skip() |
702 event.Skip() |
703 |
703 |
704 def GetRange(self): |
704 def GetRange(self): |
906 panel.Destroy() |
906 panel.Destroy() |
907 self.RefreshGraphicsSizer() |
907 self.RefreshGraphicsSizer() |
908 self.ForceRefresh() |
908 self.ForceRefresh() |
909 |
909 |
910 def ResetGraphicsValues(self): |
910 def ResetGraphicsValues(self): |
911 self.Ticks = numpy.array([]) |
911 self.Ticks = RingBuffer() |
912 self.StartTick = 0 |
912 self.StartTick = 0 |
913 for panel in self.GraphicPanels: |
913 for panel in self.GraphicPanels: |
914 panel.ResetItemsData() |
914 panel.ResetItemsData() |
915 self.ResetCursorTick() |
915 self.ResetCursorTick() |
916 |
916 |