54 RANGE_VALUES = map(lambda x: (str(x), x), [25 * 2 ** i for i in xrange(6)]) |
54 RANGE_VALUES = map(lambda x: (str(x), x), [25 * 2 ** i for i in xrange(6)]) |
55 TIME_RANGE_VALUES = [("%ds" % i, i * SECOND) for i in (1, 2, 5, 10, 20, 30)] + \ |
55 TIME_RANGE_VALUES = [("%ds" % i, i * SECOND) for i in (1, 2, 5, 10, 20, 30)] + \ |
56 [("%dm" % i, i * MINUTE) for i in (1, 2, 5, 10, 20, 30)] + \ |
56 [("%dm" % i, i * MINUTE) for i in (1, 2, 5, 10, 20, 30)] + \ |
57 [("%dh" % i, i * HOUR) for i in (1, 2, 3, 6, 12, 24)] |
57 [("%dh" % i, i * HOUR) for i in (1, 2, 3, 6, 12, 24)] |
58 |
58 |
|
59 GRAPH_PARALLEL, GRAPH_ORTHOGONAL = range(2) |
|
60 |
59 def AppendMenu(parent, help, id, kind, text): |
61 def AppendMenu(parent, help, id, kind, text): |
60 parent.Append(help=help, id=id, kind=kind, text=text) |
62 parent.Append(help=help, id=id, kind=kind, text=text) |
61 |
63 |
62 def GetDebugVariablesTableColnames(): |
64 def GetDebugVariablesTableColnames(): |
63 _ = lambda x : x |
65 _ = lambda x : x |
64 cols = [_("Variable"), _("Value")] |
66 return [_("Variable"), _("Value")] |
65 if USE_MPL: |
67 |
66 cols.append(_("3DAxis")) |
|
67 return cols |
|
68 |
|
69 class VariableTableItem(DebugDataConsumer): |
68 class VariableTableItem(DebugDataConsumer): |
70 |
69 |
71 def __init__(self, parent, variable): |
70 def __init__(self, parent, variable): |
72 DebugDataConsumer.__init__(self) |
71 DebugDataConsumer.__init__(self) |
73 self.Parent = parent |
72 self.Parent = parent |
74 self.Variable = variable |
73 self.Variable = variable |
75 self.RefreshVariableType() |
74 self.RefreshVariableType() |
76 self.Value = "" |
75 self.Value = "" |
77 self.Axis3D = False |
76 |
78 |
|
79 def __del__(self): |
77 def __del__(self): |
80 self.Parent = None |
78 self.Parent = None |
81 |
79 |
82 def SetVariable(self, variable): |
80 def SetVariable(self, variable): |
83 if self.Parent and self.Variable != variable: |
81 if self.Parent and self.Variable != variable: |
200 if row < self.GetNumberRows(): |
189 if row < self.GetNumberRows(): |
201 if colname == "Variable": |
190 if colname == "Variable": |
202 return self.data[row].GetVariable() |
191 return self.data[row].GetVariable() |
203 elif colname == "Value": |
192 elif colname == "Value": |
204 return self.data[row].GetValue() |
193 return self.data[row].GetValue() |
205 elif colname == "3DAxis": |
|
206 return self.data[row].GetAxis3D() |
|
207 return "" |
194 return "" |
208 |
195 |
209 def SetValueByName(self, row, colname, value): |
196 def SetValueByName(self, row, colname, value): |
210 if row < self.GetNumberRows(): |
197 if row < self.GetNumberRows(): |
211 if colname == "Variable": |
198 if colname == "Variable": |
212 self.data[row].SetVariable(value) |
199 self.data[row].SetVariable(value) |
213 elif colname == "Value": |
200 elif colname == "Value": |
214 self.data[row].SetValue(value) |
201 self.data[row].SetValue(value) |
215 elif colname == "3DAxis": |
|
216 self.data[row].SetAxis3D(value) |
|
217 |
202 |
218 def IsForced(self, row): |
203 def IsForced(self, row): |
219 if row < self.GetNumberRows(): |
204 if row < self.GetNumberRows(): |
220 return self.data[row].IsForced() |
205 return self.data[row].IsForced() |
221 return False |
206 return False |
234 """ |
219 """ |
235 |
220 |
236 for row in range(self.GetNumberRows()): |
221 for row in range(self.GetNumberRows()): |
237 for col in range(self.GetNumberCols()): |
222 for col in range(self.GetNumberCols()): |
238 colname = self.GetColLabelValue(col, False) |
223 colname = self.GetColLabelValue(col, False) |
239 if colname == "3DAxis": |
224 if colname == "Value": |
240 if self.IsNumVariable(row): |
225 if self.IsForced(row): |
241 grid.SetCellRenderer(row, col, wx.grid.GridCellBoolRenderer()) |
226 grid.SetCellTextColour(row, col, wx.BLUE) |
242 grid.SetCellEditor(row, col, wx.grid.GridCellBoolEditor()) |
|
243 grid.SetReadOnly(row, col, False) |
|
244 else: |
227 else: |
245 grid.SetReadOnly(row, col, True) |
228 grid.SetCellTextColour(row, col, wx.BLACK) |
246 else: |
229 grid.SetReadOnly(row, col, True) |
247 if colname == "Value": |
|
248 if self.IsForced(row): |
|
249 grid.SetCellTextColour(row, col, wx.BLUE) |
|
250 else: |
|
251 grid.SetCellTextColour(row, col, wx.BLACK) |
|
252 grid.SetReadOnly(row, col, True) |
|
253 self.ResizeRow(grid, row) |
230 self.ResizeRow(grid, row) |
254 |
231 |
255 def AppendItem(self, data): |
232 def AppendItem(self, data): |
256 self.data.append(data) |
233 self.data.append(data) |
257 |
234 |
267 def GetItem(self, idx): |
244 def GetItem(self, idx): |
268 return self.data[idx] |
245 return self.data[idx] |
269 |
246 |
270 class DebugVariableDropTarget(wx.TextDropTarget): |
247 class DebugVariableDropTarget(wx.TextDropTarget): |
271 |
248 |
272 def __init__(self, parent): |
249 def __init__(self, parent, control): |
273 wx.TextDropTarget.__init__(self) |
250 wx.TextDropTarget.__init__(self) |
274 self.ParentWindow = parent |
251 self.ParentWindow = parent |
|
252 self.ParentControl = control |
275 |
253 |
276 def OnDropText(self, x, y, data): |
254 def OnDropText(self, x, y, data): |
277 x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y) |
|
278 row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize()) |
|
279 if row == wx.NOT_FOUND: |
|
280 row = self.ParentWindow.Table.GetNumberRows() |
|
281 message = None |
255 message = None |
282 try: |
256 try: |
283 values = eval(data) |
257 values = eval(data) |
284 except: |
258 except: |
285 message = _("Invalid value \"%s\" for debug variable")%data |
259 message = _("Invalid value \"%s\" for debug variable")%data |
286 values = None |
260 values = None |
287 if not isinstance(values, TupleType): |
261 if not isinstance(values, TupleType): |
288 message = _("Invalid value \"%s\" for debug variable")%data |
262 message = _("Invalid value \"%s\" for debug variable")%data |
289 values = None |
263 values = None |
290 if values is not None and values[1] == "debug": |
264 |
291 self.ParentWindow.InsertValue(values[0], row) |
|
292 if message is not None: |
265 if message is not None: |
293 wx.CallAfter(self.ShowMessage, message) |
266 wx.CallAfter(self.ShowMessage, message) |
|
267 elif values is not None and values[1] == "debug": |
|
268 if self.ParentControl == self.ParentWindow.VariablesGrid: |
|
269 x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y) |
|
270 row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize()) |
|
271 if row == wx.NOT_FOUND: |
|
272 row = self.ParentWindow.Table.GetNumberRows() |
|
273 self.ParentWindow.InsertValue(values[0], row, force=True) |
|
274 else: |
|
275 x, y = self.ParentWindow.GraphicsCanvasWindow.CalcUnscrolledPosition(x, y) |
|
276 width, height = self.ParentWindow.GraphicsCanvas.GetSize() |
|
277 target = None |
|
278 merge_type = GRAPH_PARALLEL |
|
279 for infos in self.ParentWindow.GraphicsAxes: |
|
280 ax, ay, aw, ah = infos["axes"].get_position().bounds |
|
281 rect = wx.Rect(ax * width, height - (ay + ah) * height, |
|
282 aw * width, ah * height) |
|
283 if rect.InsideXY(x, y): |
|
284 target = infos |
|
285 merge_rect = wx.Rect(ax * width, height - (ay + ah) * height, |
|
286 aw * width / 2., ah * height) |
|
287 if merge_rect.InsideXY(x, y): |
|
288 merge_type = GRAPH_ORTHOGONAL |
|
289 break |
|
290 self.ParentWindow.MergeGraphs(values[0], target, merge_type, force=True) |
294 |
291 |
295 def ShowMessage(self, message): |
292 def ShowMessage(self, message): |
296 dialog = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
293 dialog = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
297 dialog.ShowModal() |
294 dialog.ShowModal() |
298 dialog.Destroy() |
295 dialog.Destroy() |
341 button.SetToolTipString(help) |
349 button.SetToolTipString(help) |
342 setattr(self, name, button) |
350 setattr(self, name, button) |
343 button_sizer.AddWindow(button, border=5, flag=wx.LEFT) |
351 button_sizer.AddWindow(button, border=5, flag=wx.LEFT) |
344 |
352 |
345 self.VariablesGrid = CustomGrid(self.MainPanel, size=wx.Size(-1, 150), style=wx.VSCROLL) |
353 self.VariablesGrid = CustomGrid(self.MainPanel, size=wx.Size(-1, 150), style=wx.VSCROLL) |
346 self.VariablesGrid.SetDropTarget(DebugVariableDropTarget(self)) |
354 self.VariablesGrid.SetDropTarget(DebugVariableDropTarget(self, self.VariablesGrid)) |
347 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, |
355 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, |
348 self.OnVariablesGridCellRightClick) |
356 self.OnVariablesGridCellRightClick) |
349 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, |
357 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, |
350 self.OnVariablesGridCellLeftClick) |
358 self.OnVariablesGridCellLeftClick) |
351 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, |
|
352 self.OnVariablesGridCellChange) |
|
353 main_panel_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW) |
359 main_panel_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW) |
354 |
360 |
355 self.MainPanel.SetSizer(main_panel_sizer) |
361 self.MainPanel.SetSizer(main_panel_sizer) |
356 |
362 |
357 self.HasNewData = False |
363 self.HasNewData = False |
526 |
532 |
527 self.RefreshScrollBar() |
533 self.RefreshScrollBar() |
528 |
534 |
529 self.Thaw() |
535 self.Thaw() |
530 |
536 |
531 if USE_MPL and (not self.Fixed or self.Force): |
537 if USE_MPL: |
532 self.Force = False |
538 |
533 |
539 if not self.Fixed or self.Force: |
534 # Refresh graphics |
540 self.Force = False |
535 start_tick, end_tick = self.StartTick, self.StartTick + self.CurrentRange |
541 |
|
542 # Refresh graphics |
|
543 start_tick, end_tick = self.StartTick, self.StartTick + self.CurrentRange |
|
544 for infos in self.GraphicsAxes: |
|
545 |
|
546 if infos["type"] == GRAPH_PARALLEL: |
|
547 min_value = max_value = None |
|
548 |
|
549 for idx, item in enumerate(infos["items"]): |
|
550 data = item.GetData(start_tick, end_tick) |
|
551 if data is not None: |
|
552 item_min_value, item_max_value = item.GetRange() |
|
553 if min_value is None: |
|
554 min_value = item_min_value |
|
555 elif item_min_value is not None: |
|
556 min_value = min(min_value, item_min_value) |
|
557 if max_value is None: |
|
558 max_value = item_max_value |
|
559 elif item_max_value is not None: |
|
560 max_value = max(max_value, item_max_value) |
|
561 |
|
562 if len(infos["plots"]) <= idx: |
|
563 infos["plots"].append( |
|
564 infos["axes"].plot(data[:, 0], data[:, 1])[0]) |
|
565 else: |
|
566 infos["plots"][idx].set_data(data[:, 0], data[:, 1]) |
|
567 |
|
568 if min_value is not None and max_value is not None: |
|
569 y_center = (min_value + max_value) / 2. |
|
570 y_range = max(1.0, max_value - min_value) |
|
571 else: |
|
572 y_center = 0.5 |
|
573 y_range = 1.0 |
|
574 x_min, x_max = start_tick, end_tick |
|
575 y_min, y_max = y_center - y_range * 0.55, y_center + y_range * 0.55 |
|
576 |
|
577 else: |
|
578 min_start_tick = reduce(max, [item.GetData()[0, 0] |
|
579 for item in infos["items"] |
|
580 if len(item.GetData()) > 0], 0) |
|
581 start_tick = max(self.StartTick, min_start_tick) |
|
582 end_tick = max(self.StartTick + self.CurrentRange, min_start_tick) |
|
583 x_data, x_min, x_max = OrthogonalData(infos["items"][0], start_tick, end_tick) |
|
584 y_data, y_min, y_max = OrthogonalData(infos["items"][1], start_tick, end_tick) |
|
585 length = 0 |
|
586 if x_data is not None and y_data is not None: |
|
587 length = min(len(x_data), len(y_data)) |
|
588 if len(infos["items"]) < 3: |
|
589 if x_data is not None and y_data is not None: |
|
590 if len(infos["plots"]) == 0: |
|
591 infos["plots"].append( |
|
592 infos["axes"].plot(x_data[:, 1][:length], |
|
593 y_data[:, 1][:length])[0]) |
|
594 else: |
|
595 infos["plots"][0].set_data( |
|
596 x_data[:, 1][:length], |
|
597 y_data[:, 1][:length]) |
|
598 else: |
|
599 while len(infos["axes"].lines) > 0: |
|
600 infos["axes"].lines.pop() |
|
601 z_data, z_min, z_max = OrthogonalData(infos["items"][2], start_tick, end_tick) |
|
602 if x_data is not None and y_data is not None and z_data is not None: |
|
603 length = min(length, len(z_data)) |
|
604 infos["axes"].plot(x_data[:, 1][:length], |
|
605 y_data[:, 1][:length], |
|
606 zs = z_data[:, 1][:length]) |
|
607 infos["axes"].set_zlim(z_min, z_max) |
|
608 |
|
609 infos["axes"].set_xlim(x_min, x_max) |
|
610 infos["axes"].set_ylim(y_min, y_max) |
|
611 |
|
612 plot2d = plot3d = 0 |
536 for infos in self.GraphicsAxes: |
613 for infos in self.GraphicsAxes: |
537 min_value = max_value = None |
614 labels = ["%s: %s" % (item.GetVariable(), item.GetValue()) |
538 |
615 for item in infos["items"]] |
539 for idx, item in enumerate(infos["items"]): |
616 if infos["type"] == GRAPH_PARALLEL: |
540 data = item.GetData(start_tick, end_tick) |
617 infos["axes"].legend(infos["plots"], labels, |
541 if data is not None: |
618 loc="upper left", frameon=False, |
542 item_min_value, item_max_value = item.GetRange() |
619 prop={'size':'small'}) |
543 if min_value is None: |
620 plot2d += 1 |
544 min_value = item_min_value |
|
545 elif item_min_value is not None: |
|
546 min_value = min(min_value, item_min_value) |
|
547 if max_value is None: |
|
548 max_value = item_max_value |
|
549 elif item_max_value is not None: |
|
550 max_value = max(max_value, item_max_value) |
|
551 |
|
552 if len(infos["plots"]) <= idx: |
|
553 infos["plots"].append(infos["axes"].plot(data[:, 0], data[:, 1])[0]) |
|
554 else: |
|
555 infos["plots"][idx].set_data(data[:, 0], data[:, 1]) |
|
556 |
|
557 if min_value is not None and max_value is not None: |
|
558 y_center = (min_value + max_value) / 2. |
|
559 y_range = max(1.0, max_value - min_value) |
|
560 else: |
621 else: |
561 y_center = 0.5 |
622 infos["axes"].set_xlabel(labels[0], fontdict={'size':'small'}) |
562 y_range = 1.0 |
623 infos["axes"].set_ylabel(labels[1], fontdict={'size':'small'}) |
563 infos["axes"].set_xlim(start_tick, end_tick) |
624 if len(labels) > 2: |
564 infos["axes"].set_ylim(y_center - y_range * 0.55, y_center + y_range * 0.55) |
625 infos["axes"].set_zlabel(labels[2], fontdict={'size':'small'}) |
565 |
626 plot3d += 1 |
566 if len(self.GraphicsAxes) > 0: |
627 else: |
|
628 plot2d += 1 |
|
629 |
|
630 if plot2d > 0: |
567 self.GraphicsCanvas.draw() |
631 self.GraphicsCanvas.draw() |
568 |
632 if plot3d > 0: |
569 # Refresh 3D graphics |
|
570 while len(self.Graphics3DAxes.lines) > 0: |
|
571 self.Graphics3DAxes.lines.pop() |
|
572 if self.Axis3DValues is not None: |
|
573 axis = self.Axis3DValues[0] |
|
574 start_tick = max(self.StartTick, self.Axis3DValues[1]) |
|
575 end_tick = max(self.StartTick + self.CurrentRange, self.Axis3DValues[1]) |
|
576 xyz_data = [axe.GetData(start_tick, end_tick)[:, 1] for axe in axis] |
|
577 length = reduce(min, [len(data) for data in xyz_data]) |
|
578 self.Graphics3DAxes.plot(xyz_data[0][:length], |
|
579 xyz_data[1][:length], |
|
580 zs = xyz_data[2][:length]) |
|
581 self.Graphics3DCanvas.draw() |
633 self.Graphics3DCanvas.draw() |
582 |
634 |
583 def UnregisterObsoleteData(self): |
635 def UnregisterObsoleteData(self): |
584 items = [(idx, item) for idx, item in enumerate(self.Table.GetData())] |
636 items = [(idx, item) for idx, item in enumerate(self.Table.GetData())] |
585 items.reverse() |
637 items.reverse() |
772 self.Table.InsertItem(idx, item) |
818 self.Table.InsertItem(idx, item) |
773 if item.IsNumVariable(): |
819 if item.IsNumVariable(): |
774 self.GraphicsAxes.append({ |
820 self.GraphicsAxes.append({ |
775 "items": [item], |
821 "items": [item], |
776 "axes": None, |
822 "axes": None, |
777 "type": "y", |
823 "type": GRAPH_PARALLEL, |
778 "plots": []}) |
824 "plots": []}) |
779 item.SetAxis3D(int(axis3D)) |
|
780 self.ResetGraphics() |
825 self.ResetGraphics() |
781 self.RefreshGrid() |
826 self.RefreshGrid() |
|
827 |
|
828 def MergeGraphs(self, source, target_infos, merge_type, force=False): |
|
829 source_item = None |
|
830 for item in self.Table.GetData(): |
|
831 if item.GetVariable() == source: |
|
832 source_item = item |
|
833 if source_item is None: |
|
834 item = VariableTableItem(self, source) |
|
835 if item.IsNumVariable(): |
|
836 result = self.AddDataConsumer(source.upper(), item) |
|
837 if result is not None or force: |
|
838 self.Table.InsertItem(self.Table.GetNumberRows(), item) |
|
839 source_item = item |
|
840 if source_item is not None: |
|
841 source_infos = None |
|
842 for infos in self.GraphicsAxes: |
|
843 if source_item in infos["items"]: |
|
844 source_infos = infos |
|
845 break |
|
846 if target_infos is None and source_infos is None: |
|
847 self.GraphicsAxes.append({ |
|
848 "items": [source_item], |
|
849 "axes": None, |
|
850 "type": GRAPH_PARALLEL, |
|
851 "plots": []}) |
|
852 |
|
853 self.ResetGraphics() |
|
854 self.RefreshGrid() |
|
855 |
|
856 elif target_infos is not None: |
|
857 if (merge_type == GRAPH_PARALLEL and target_infos["type"] != merge_type or |
|
858 merge_type == GRAPH_ORTHOGONAL and |
|
859 (target_infos["type"] == GRAPH_PARALLEL and len(target_infos["items"]) > 1 or |
|
860 target_infos["type"] == GRAPH_ORTHOGONAL and len(target_infos["items"]) >= 3)): |
|
861 return |
|
862 |
|
863 if source_infos is not None: |
|
864 source_infos["items"].remove(source_item) |
|
865 if len(source_infos["items"]) == 0: |
|
866 self.GraphicsAxes.remove(source_infos) |
|
867 |
|
868 target_infos["items"].append(source_item) |
|
869 target_infos["type"] = merge_type |
|
870 |
|
871 self.ResetGraphics() |
|
872 self.RefreshGrid() |
782 |
873 |
783 def GetDebugVariables(self): |
874 def GetDebugVariables(self): |
784 return [item.GetVariable() for item in self.Table.GetData()] |
875 return [item.GetVariable() for item in self.Table.GetData()] |
785 |
876 |
786 def GetAxis3D(self): |
877 def OnGraphicsCanvasClick(self, event): |
787 return [item.GetVariable() for item in self.Table.GetData() if item.GetAxis3D()] |
878 for infos in self.GraphicsAxes: |
|
879 if infos["axes"] == event.inaxes: |
|
880 if len(infos["items"]) == 1: |
|
881 data = wx.TextDataObject(str((infos["items"][0].GetVariable(), "debug"))) |
|
882 dragSource = wx.DropSource(self.GraphicsCanvas) |
|
883 dragSource.SetData(data) |
|
884 dragSource.DoDragDrop() |
|
885 if self.GraphicsCanvas.HasCapture(): |
|
886 self.GraphicsCanvas.ReleaseMouse() |
|
887 break |
788 |
888 |
789 def ResetGraphicsValues(self): |
889 def ResetGraphicsValues(self): |
790 self.Ticks = numpy.array([]) |
890 self.Ticks = numpy.array([]) |
791 self.StartTick = 0 |
891 self.StartTick = 0 |
792 for item in self.Table.GetData(): |
892 for item in self.Table.GetData(): |
794 |
894 |
795 def ResetGraphics(self): |
895 def ResetGraphics(self): |
796 if USE_MPL: |
896 if USE_MPL: |
797 self.GraphicsFigure.clear() |
897 self.GraphicsFigure.clear() |
798 |
898 |
799 axes_num = len(self.GraphicsAxes) |
899 axes_num = 0 |
800 for idx in xrange(axes_num): |
900 for infos in self.GraphicsAxes: |
801 if idx == 0: |
901 if infos["type"] != GRAPH_ORTHOGONAL or len(infos["items"]) < 3: |
802 axes = self.GraphicsFigure.add_subplot(axes_num, 1, idx + 1) |
902 axes_num += 1 |
|
903 if axes_num == len(self.GraphicsAxes): |
|
904 self.Graphics3DCanvas.Hide() |
|
905 else: |
|
906 self.Graphics3DCanvas.Show() |
|
907 self.GraphicsPanelSizer.Layout() |
|
908 idx = 1 |
|
909 for infos in self.GraphicsAxes: |
|
910 if infos["type"] != GRAPH_ORTHOGONAL or len(infos["items"]) < 3: |
|
911 axes = self.GraphicsFigure.add_subplot(axes_num, 1, idx) |
|
912 infos["axes"] = axes |
803 else: |
913 else: |
804 axes = self.GraphicsFigure.add_subplot(axes_num, 1, idx + 1, sharex=self.GraphicsAxes[0]["axes"]) |
914 infos["axes"] = self.Graphics3DAxes |
805 self.GraphicsAxes[idx]["axes"] = axes |
915 infos["plots"] = [] |
806 self.GraphicsAxes[idx]["plots"] = [] |
916 idx += 1 |
807 |
|
808 self.RefreshGraphicsCanvasWindowScrollbars() |
917 self.RefreshGraphicsCanvasWindowScrollbars() |
809 self.GraphicsCanvas.draw() |
918 self.GraphicsCanvas.draw() |
810 |
|
811 self.Reset3DGraphics() |
|
812 |
|
813 def Reset3DGraphics(self): |
|
814 self.Axis3DValues = None |
|
815 axis = [item for item in self.Table.GetData() if item.GetAxis3D()] |
|
816 if len(axis) == 3: |
|
817 max_tick = None |
|
818 xaxis, yaxis, zaxis = [item.GetData() for item in axis] |
|
819 if len(xaxis) > 0 and len(yaxis) > 0 and len(zaxis) > 0: |
|
820 max_tick = max(xaxis[0, 0], yaxis[0, 0], zaxis[0, 0]) |
|
821 if max_tick is not None: |
|
822 self.Axis3DValues = (axis, max_tick) |
|
823 else: |
|
824 self.Axis3DValues = (axis, 0) |
|
825 self.Graphics3DCanvas.Show() |
|
826 else: |
|
827 self.Graphics3DCanvas.Hide() |
|
828 self.GraphicsPanelSizer.Layout() |
|
829 |
919 |
830 def OnGraphics3DMotion(self, event): |
920 def OnGraphics3DMotion(self, event): |
831 current_time = gettime() |
921 current_time = gettime() |
832 if current_time - self.LastMotionTime > REFRESH_PERIOD: |
922 if current_time - self.LastMotionTime > REFRESH_PERIOD: |
833 self.LastMotionTime = current_time |
923 self.LastMotionTime = current_time |
834 Axes3D._on_move(self.Graphics3DAxes, event) |
924 Axes3D._on_move(self.Graphics3DAxes, event) |
835 |
925 |
836 def RefreshGraphicsCanvasWindowScrollbars(self): |
926 def RefreshGraphicsCanvasWindowScrollbars(self): |
837 xstart, ystart = self.GraphicsCanvasWindow.GetViewStart() |
927 xstart, ystart = self.GraphicsCanvasWindow.GetViewStart() |
838 window_size = self.GraphicsCanvasWindow.GetClientSize() |
928 window_size = self.GraphicsCanvasWindow.GetClientSize() |
839 vwidth, vheight = (window_size[0], (len(self.GraphicsAxes) + 1) * 50) |
929 vwidth, vheight = (window_size[0], (len(self.GraphicsAxes) + 1) * 100) |
840 self.GraphicsCanvas.SetMinSize(wx.Size(vwidth, vheight)) |
930 self.GraphicsCanvas.SetMinSize(wx.Size(vwidth, vheight)) |
841 posx = max(0, min(xstart, (vwidth - window_size[0]) / SCROLLBAR_UNIT)) |
931 posx = max(0, min(xstart, (vwidth - window_size[0]) / SCROLLBAR_UNIT)) |
842 posy = max(0, min(ystart, (vheight - window_size[1]) / SCROLLBAR_UNIT)) |
932 posy = max(0, min(ystart, (vheight - window_size[1]) / SCROLLBAR_UNIT)) |
843 self.GraphicsCanvasWindow.Scroll(posx, posy) |
933 self.GraphicsCanvasWindow.Scroll(posx, posy) |
844 self.GraphicsCanvasWindow.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |
934 self.GraphicsCanvasWindow.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |