106 return lower - border, upper + border |
111 return lower - border, upper + border |
107 else: |
112 else: |
108 return plot.PlotCanvas._axisInterval(self.Canvas, spec, lower, upper) |
113 return plot.PlotCanvas._axisInterval(self.Canvas, spec, lower, upper) |
109 self.Canvas._axisInterval = _axisInterval |
114 self.Canvas._axisInterval = _axisInterval |
110 self.Canvas.SetYSpec('border') |
115 self.Canvas.SetYSpec('border') |
111 |
116 self.Canvas.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnCanvasLeftDown) |
|
117 self.Canvas.canvas.Bind(wx.EVT_LEFT_UP, self.OnCanvasLeftUp) |
|
118 self.Canvas.canvas.Bind(wx.EVT_MOTION, self.OnCanvasMotion) |
|
119 self.Canvas.canvas.Bind(wx.EVT_MOUSEWHEEL, self.OnCanvasMouseWheel) |
|
120 |
112 self.staticbox1 = wx.StaticText(id=ID_GRAPHICVIEWERSTATICTEXT1, |
121 self.staticbox1 = wx.StaticText(id=ID_GRAPHICVIEWERSTATICTEXT1, |
113 label=_('Range:'), name='staticText1', parent=self.Editor, |
122 label=_('Range:'), name='staticText1', parent=self.Editor, |
114 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
123 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
115 |
124 |
116 self.CanvasRange = wx.ComboBox(id=ID_GRAPHICVIEWERCANVASRANGE, |
125 self.CanvasRange = wx.ComboBox(id=ID_GRAPHICVIEWERCANVASRANGE, |
117 name='CanvasRange', parent=self.Editor, pos=wx.Point(0, 0), |
126 name='CanvasRange', parent=self.Editor, pos=wx.Point(0, 0), |
118 size=wx.Size(100, 28), style=wx.CB_READONLY) |
127 size=wx.Size(100, 28), style=wx.CB_READONLY) |
119 self.Bind(wx.EVT_COMBOBOX, self.OnRangeChanged, id=ID_GRAPHICVIEWERCANVASRANGE) |
128 self.Bind(wx.EVT_COMBOBOX, self.OnRangeChanged, id=ID_GRAPHICVIEWERCANVASRANGE) |
|
129 |
|
130 self.staticbox3 = wx.StaticText(id=ID_GRAPHICVIEWERSTATICTEXT3, |
|
131 label=_('Zoom:'), name='staticText3', parent=self.Editor, |
|
132 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
133 |
|
134 self.CanvasZoom = wx.ComboBox(id=ID_GRAPHICVIEWERCANVASZOOM, |
|
135 name='CanvasZoom', parent=self.Editor, pos=wx.Point(0, 0), |
|
136 size=wx.Size(70, 28), style=wx.CB_READONLY) |
|
137 self.Bind(wx.EVT_COMBOBOX, self.OnZoomChanged, id=ID_GRAPHICVIEWERCANVASZOOM) |
120 |
138 |
121 self.staticText2 = wx.StaticText(id=ID_GRAPHICVIEWERSTATICTEXT2, |
139 self.staticText2 = wx.StaticText(id=ID_GRAPHICVIEWERSTATICTEXT2, |
122 label=_('Position:'), name='staticText2', parent=self.Editor, |
140 label=_('Position:'), name='staticText2', parent=self.Editor, |
123 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
141 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
124 |
142 |
172 def GetTitle(self): |
208 def GetTitle(self): |
173 if len(self.InstancePath) > 15: |
209 if len(self.InstancePath) > 15: |
174 return "..." + self.InstancePath[-12:] |
210 return "..." + self.InstancePath[-12:] |
175 return self.InstancePath |
211 return self.InstancePath |
176 |
212 |
177 def ResetView(self): |
213 # Changes Viewer mode |
|
214 def SetMode(self, mode): |
|
215 if self.Mode != mode or mode == MODE_SELECTION: |
|
216 if self.Mode == MODE_MOTION: |
|
217 wx.CallAfter(self.Canvas.canvas.SetCursor, wx.NullCursor) |
|
218 self.Mode = mode |
|
219 if self.Mode == MODE_MOTION: |
|
220 wx.CallAfter(self.Canvas.canvas.SetCursor, wx.StockCursor(wx.CURSOR_HAND)) |
|
221 |
|
222 def ResetView(self, register=False): |
178 self.Datas = [] |
223 self.Datas = [] |
179 self.StartValue = 0 |
224 self.StartTick = 0 |
180 self.EndValue = 0 |
225 self.EndTick = 0 |
|
226 self.StartIdx = 0 |
|
227 self.EndIdx = 0 |
181 self.Fixed = False |
228 self.Fixed = False |
182 self.Ticktime = self.DataProducer.GetTicktime() |
229 self.Ticktime = self.DataProducer.GetTicktime() |
|
230 if register: |
|
231 self.AddDataConsumer(self.InstancePath.upper(), self) |
183 self.RefreshCanvasRange() |
232 self.RefreshCanvasRange() |
184 self.RefreshView() |
233 self.RefreshView() |
185 |
234 |
186 def RefreshNewData(self, *args, **kwargs): |
235 def RefreshNewData(self, *args, **kwargs): |
187 self.RefreshView(*args, **kwargs) |
236 self.RefreshView(*args, **kwargs) |
188 DebugViewer.RefreshNewData(self) |
237 DebugViewer.RefreshNewData(self) |
189 |
|
190 def RefreshCanvasRange(self): |
|
191 if self.Ticktime == 0 and self.RangeValues != RANGE_VALUES: |
|
192 self.RangeValues = RANGE_VALUES |
|
193 self.RangeValues_dict = dict(RANGE_VALUES) |
|
194 self.CanvasRange.Clear() |
|
195 for text, value in RANGE_VALUES: |
|
196 self.CanvasRange.Append(text) |
|
197 self.CanvasRange.SetStringSelection(RANGE_VALUES[0][0]) |
|
198 self.CurrentRange = RANGE_VALUES[0][1] |
|
199 elif self.RangeValues != TIME_RANGE_VALUES: |
|
200 self.RangeValues = TIME_RANGE_VALUES |
|
201 self.RangeValues_dict = dict(TIME_RANGE_VALUES) |
|
202 self.CanvasRange.Clear() |
|
203 for text, value in TIME_RANGE_VALUES: |
|
204 self.CanvasRange.Append(text) |
|
205 self.CanvasRange.SetStringSelection(TIME_RANGE_VALUES[0][0]) |
|
206 self.CurrentRange = TIME_RANGE_VALUES[0][1] / self.Ticktime |
|
207 |
|
208 def RefreshView(self, force=True): |
|
209 self.Freeze() |
|
210 if force or not self.Fixed: |
|
211 var_name = self.InstancePath.split(".")[-1] |
|
212 |
|
213 self.VariableGraphic = plot.PolyLine(self.Datas[self.StartValue:self.EndValue + 1], |
|
214 legend=var_name, colour=colours[0]) |
|
215 self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], _("%s Graphics") % var_name, _("Tick"), _("Values")) |
|
216 datas_length = len(self.Datas) |
|
217 if datas_length > 1: |
|
218 start = self.Datas[self.StartValue][0] |
|
219 else: |
|
220 start = 0. |
|
221 self.Canvas.Draw(self.GraphicsObject, xAxis=(start, start + self.CurrentRange)) |
|
222 self.RefreshScrollBar() |
|
223 self.Thaw() |
|
224 |
|
225 def GetInstancePath(self): |
|
226 return self.InstancePath |
|
227 |
|
228 def IsViewing(self, tagname): |
|
229 return self.InstancePath == tagname |
|
230 |
238 |
231 def GetNearestData(self, tick, adjust): |
239 def GetNearestData(self, tick, adjust): |
232 ticks = numpy.array(zip(*self.Datas)[0]) |
240 ticks = numpy.array(zip(*self.Datas)[0]) |
233 new_cursor = numpy.argmin(abs(ticks - tick)) |
241 new_cursor = numpy.argmin(abs(ticks - tick)) |
234 if adjust == -1 and ticks[new_cursor] > tick and new_cursor > 0: |
242 if adjust == -1 and ticks[new_cursor] > tick and new_cursor > 0: |
235 new_cursor -= 1 |
243 new_cursor -= 1 |
236 elif adjust == 1 and ticks[new_cursor] < tick and new_cursor < len(self.Datas): |
244 elif adjust == 1 and ticks[new_cursor] < tick and new_cursor < len(self.Datas): |
237 new_cursor += 1 |
245 new_cursor += 1 |
238 return new_cursor |
246 return new_cursor |
239 |
247 |
|
248 def GetBounds(self): |
|
249 if self.StartIdx is None or self.EndIdx is None: |
|
250 self.StartIdx = self.GetNearestData(self.StartTick, -1) |
|
251 self.EndIdx = self.GetNearestData(self.EndTick, 1) |
|
252 |
|
253 def ResetBounds(self): |
|
254 self.StartIdx = None |
|
255 self.EndIdx = None |
|
256 |
|
257 def RefreshCanvasRange(self): |
|
258 if self.Ticktime == 0 and self.RangeValues != RANGE_VALUES: |
|
259 self.RangeValues = RANGE_VALUES |
|
260 self.CanvasRange.Clear() |
|
261 for text, value in RANGE_VALUES: |
|
262 self.CanvasRange.Append(text) |
|
263 self.CanvasRange.SetStringSelection(RANGE_VALUES[0][0]) |
|
264 self.CurrentRange = RANGE_VALUES[0][1] |
|
265 elif self.RangeValues != TIME_RANGE_VALUES: |
|
266 self.RangeValues = TIME_RANGE_VALUES |
|
267 self.CanvasRange.Clear() |
|
268 for text, value in TIME_RANGE_VALUES: |
|
269 self.CanvasRange.Append(text) |
|
270 self.CanvasRange.SetStringSelection(TIME_RANGE_VALUES[0][0]) |
|
271 self.CurrentRange = TIME_RANGE_VALUES[0][1] / self.Ticktime |
|
272 |
|
273 def RefreshView(self, force=True): |
|
274 self.Freeze() |
|
275 if force or not self.Fixed: |
|
276 if (self.MinValue is not None and |
|
277 self.MaxValue is not None and |
|
278 self.MinValue != self.MaxValue): |
|
279 Yrange = float(self.MaxValue - self.MinValue) / self.CurrentZoom |
|
280 else: |
|
281 Yrange = 2. / self.CurrentZoom |
|
282 |
|
283 if not self.Fixed and len(self.Datas) > 0: |
|
284 self.YCenter = max(self.Datas[-1][1] - Yrange / 2, |
|
285 min(self.YCenter, |
|
286 self.Datas[-1][1] + Yrange / 2)) |
|
287 |
|
288 var_name = self.InstancePath.split(".")[-1] |
|
289 |
|
290 self.GetBounds() |
|
291 self.VariableGraphic = plot.PolyLine(self.Datas[self.StartIdx:self.EndIdx + 1], |
|
292 legend=var_name, colour=colours[0]) |
|
293 self.GraphicsObject = plot.PlotGraphics([self.VariableGraphic], _("%s Graphics") % var_name, _("Tick"), _("Values")) |
|
294 datas_length = len(self.Datas) |
|
295 if datas_length > 1: |
|
296 start = self.Datas[self.StartIdx][0] |
|
297 else: |
|
298 start = 0. |
|
299 self.Canvas.Draw(self.GraphicsObject, |
|
300 xAxis=(start, start + self.CurrentRange), |
|
301 yAxis=(self.YCenter - Yrange * 1.1 / 2, self.YCenter + Yrange * 1.1 / 2)) |
|
302 self.RefreshScrollBar() |
|
303 |
|
304 # Reset and draw cursor |
|
305 self.ResetLastCursor() |
|
306 self.RefreshCursor() |
|
307 |
|
308 self.Thaw() |
|
309 |
|
310 def GetInstancePath(self): |
|
311 return self.InstancePath |
|
312 |
|
313 def IsViewing(self, tagname): |
|
314 return self.InstancePath == tagname |
|
315 |
240 def NewValue(self, tick, value, forced=False): |
316 def NewValue(self, tick, value, forced=False): |
241 self.Datas.append((float(tick), {True:1., False:0.}.get(value, float(value)))) |
317 self.Datas.append((float(tick), {True:1., False:0.}.get(value, float(value)))) |
|
318 if self.MinValue is None: |
|
319 self.MinValue = value |
|
320 else: |
|
321 self.MinValue = min(self.MinValue, value) |
|
322 if self.MaxValue is None: |
|
323 self.MaxValue = value |
|
324 else: |
|
325 self.MaxValue = max(self.MaxValue, value) |
242 if not self.Fixed: |
326 if not self.Fixed: |
243 while int(self.Datas[self.StartValue][0]) < tick - self.CurrentRange: |
327 self.GetBounds() |
244 self.StartValue += 1 |
328 while int(self.Datas[self.StartIdx][0]) < tick - self.CurrentRange: |
245 self.EndValue += 1 |
329 self.StartIdx += 1 |
|
330 self.EndIdx += 1 |
|
331 self.StartTick = self.Datas[self.StartIdx][0] |
|
332 self.EndTick = self.StartTick + self.CurrentRange |
246 self.NewDataAvailable() |
333 self.NewDataAvailable() |
247 |
334 |
248 def RefreshScrollBar(self): |
335 def RefreshScrollBar(self): |
249 if len(self.Datas) > 0: |
336 if len(self.Datas) > 0: |
250 pos = int(self.Datas[self.StartValue][0] - self.Datas[0][0]) |
337 self.GetBounds() |
|
338 pos = int(self.Datas[self.StartIdx][0] - self.Datas[0][0]) |
251 range = int(self.Datas[-1][0] - self.Datas[0][0]) |
339 range = int(self.Datas[-1][0] - self.Datas[0][0]) |
252 else: |
340 else: |
253 pos = 0 |
341 pos = 0 |
254 range = 0 |
342 range = 0 |
255 self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange) |
343 self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange) |
256 |
344 |
257 def OnRangeChanged(self, event): |
345 def RefreshRange(self): |
258 old_range = self.CurrentRange |
|
259 try: |
|
260 if self.Ticktime == 0: |
|
261 self.CurrentRange = self.RangeValues_dict[self.CanvasRange.GetValue()] |
|
262 else: |
|
263 self.CurrentRange = self.RangeValues_dict[self.CanvasRange.GetValue()] / self.Ticktime |
|
264 except ValueError, e: |
|
265 self.CanvasRange.SetValue(str(self.CurrentRange)) |
|
266 if len(self.Datas) > 0: |
346 if len(self.Datas) > 0: |
267 if self.Fixed and self.Datas[-1][0] - self.Datas[0][0] < self.CurrentRange: |
347 if self.Fixed and self.Datas[-1][0] - self.Datas[0][0] < self.CurrentRange: |
268 self.Fixed = False |
348 self.Fixed = False |
|
349 self.ResetBounds() |
269 if self.Fixed: |
350 if self.Fixed: |
270 self.StartValue = min(self.StartValue, self.GetNearestData(self.Datas[-1][0] - self.CurrentRange, -1)) |
351 self.StartTick = min(self.StartTick, self.Datas[-1][0] - self.CurrentRange) |
271 self.EndValue = self.GetNearestData(self.StartValue + self.CurrentRange, 1) |
|
272 else: |
352 else: |
273 self.StartValue = self.GetNearestData(self.Datas[-1][0] - self.CurrentRange - 1, -1) |
353 self.StartTick = max(self.Datas[0][0], self.EndTick - self.CurrentRange - 1) |
274 self.EndValue = len(self.Datas) - 1 |
354 self.EndTick = self.StartTick + self.CurrentRange |
275 self.NewDataAvailable(True) |
355 self.NewDataAvailable(True) |
|
356 |
|
357 def OnRangeChanged(self, event): |
|
358 try: |
|
359 if self.Ticktime == 0: |
|
360 self.CurrentRange = self.RangeValues[self.CanvasRange.GetSelection()][1] |
|
361 else: |
|
362 self.CurrentRange = self.RangeValues[self.CanvasRange.GetSelection()][1] / self.Ticktime |
|
363 except ValueError, e: |
|
364 self.CanvasRange.SetValue(str(self.CurrentRange)) |
|
365 wx.CallAfter(self.RefreshRange) |
|
366 event.Skip() |
|
367 |
|
368 def OnZoomChanged(self, event): |
|
369 self.CurrentZoom = ZOOM_VALUES[self.CanvasZoom.GetSelection()][1] |
|
370 wx.CallAfter(self.NewDataAvailable, True) |
276 event.Skip() |
371 event.Skip() |
277 |
372 |
278 def OnPositionChanging(self, event): |
373 def OnPositionChanging(self, event): |
279 self.StartValue = self.GetNearestData(self.Datas[0][0] + event.GetPosition(), -1) |
374 self.ResetBounds() |
280 self.EndValue = self.GetNearestData(self.Datas[self.StartValue][0] + self.CurrentRange, 1) |
375 self.StartTick = self.Datas[0][0] + event.GetPosition() |
|
376 self.EndTick = self.StartTick + self.CurrentRange |
281 self.Fixed = True |
377 self.Fixed = True |
282 self.NewDataAvailable(True) |
378 self.NewDataAvailable(True) |
283 event.Skip() |
379 event.Skip() |
284 |
380 |
285 def OnResetButton(self, event): |
381 def OnResetButton(self, event): |
286 self.Fixed = False |
382 self.Fixed = False |
287 self.ResteView() |
383 self.ResetView() |
288 event.Skip() |
384 event.Skip() |
289 |
385 |
290 def OnCurrentButton(self, event): |
386 def OnCurrentButton(self, event): |
291 self.StartValue = self.GetNearestData(self.Datas[-1][0] - self.CurrentRange, -1) |
387 self.ResetBounds() |
292 self.EndValue = self.GetNearestData(self.Datas[self.StartValue][0] + self.CurrentRange, 1) |
388 self.StartTick = max(self.Datas[0][0], self.Datas[-1][0] - self.CurrentRange) |
|
389 self.EndTick = self.StartTick + self.CurrentRange |
293 self.Fixed = False |
390 self.Fixed = False |
294 self.NewDataAvailable(True) |
391 self.NewDataAvailable(True) |
295 event.Skip() |
392 event.Skip() |
296 |
393 |
|
394 def OnCanvasLeftDown(self, event): |
|
395 self.Fixed = True |
|
396 self.Canvas.canvas.CaptureMouse() |
|
397 if self.Mode == MODE_SELECTION: |
|
398 self.Dragging = True |
|
399 pos = self.Canvas.PositionScreenToUser(event.GetPosition()) |
|
400 self.CursorIdx = self.GetNearestData(pos[0], -1) |
|
401 self.RefreshCursor() |
|
402 elif self.Mode == MODE_MOTION: |
|
403 self.GetBounds() |
|
404 self.CurrentMousePos = event.GetPosition() |
|
405 self.CurrentMotionValue = self.Datas[self.StartIdx][0] |
|
406 event.Skip() |
|
407 |
|
408 def OnCanvasLeftUp(self, event): |
|
409 self.Dragging = False |
|
410 if self.Mode == MODE_MOTION: |
|
411 self.CurrentMousePos = None |
|
412 self.CurrentMotionValue = None |
|
413 if self.Canvas.canvas.HasCapture(): |
|
414 self.Canvas.canvas.ReleaseMouse() |
|
415 event.Skip() |
|
416 |
|
417 def OnCanvasMotion(self, event): |
|
418 if self.Mode == MODE_SELECTION and self.Dragging: |
|
419 pos = self.Canvas.PositionScreenToUser(event.GetPosition()) |
|
420 graphics, xAxis, yAxis = self.Canvas.last_draw |
|
421 self.CursorIdx = self.GetNearestData(max(xAxis[0], min(pos[0], xAxis[1])), -1) |
|
422 self.RefreshCursor() |
|
423 elif self.CurrentMousePos is not None: |
|
424 oldpos = self.Canvas.PositionScreenToUser(self.CurrentMousePos) |
|
425 newpos = self.Canvas.PositionScreenToUser(event.GetPosition()) |
|
426 self.CurrentMotionValue += oldpos[0] - newpos[0] |
|
427 self.YCenter += oldpos[1] - newpos[1] |
|
428 self.ResetBounds() |
|
429 self.StartTick = self.CurrentMotionValue |
|
430 self.EndTick = self.StartTick + self.CurrentRange |
|
431 self.CurrentMousePos = event.GetPosition() |
|
432 self.NewDataAvailable(True) |
|
433 event.Skip() |
|
434 |
|
435 def OnCanvasMouseWheel(self, event): |
|
436 if self.CurrentMousePos is None: |
|
437 rotation = event.GetWheelRotation() / event.GetWheelDelta() |
|
438 if event.ShiftDown(): |
|
439 current = self.CanvasRange.GetSelection() |
|
440 new = max(0, min(current - rotation, len(self.RangeValues) - 1)) |
|
441 if new != current: |
|
442 if self.Ticktime == 0: |
|
443 self.CurrentRange = self.RangeValues[new][1] |
|
444 else: |
|
445 self.CurrentRange = self.RangeValues[new][1] / self.Ticktime |
|
446 self.CanvasRange.SetStringSelection(self.RangeValues[new][0]) |
|
447 wx.CallAfter(self.RefreshRange) |
|
448 else: |
|
449 current = self.CanvasZoom.GetSelection() |
|
450 new = max(0, min(current - rotation, len(ZOOM_VALUES) - 1)) |
|
451 if new != current: |
|
452 self.CurrentZoom = ZOOM_VALUES[new][1] |
|
453 self.CanvasZoom.SetStringSelection(ZOOM_VALUES[new][0]) |
|
454 wx.CallAfter(self.NewDataAvailable, True) |
|
455 event.Skip() |
|
456 |
|
457 ## Reset the last cursor |
|
458 def ResetLastCursor(self): |
|
459 self.LastCursor = None |
|
460 |
|
461 ## Draw the cursor on graphic |
|
462 # @param dc The draw canvas |
|
463 # @param cursor The cursor parameters |
|
464 def DrawCursor(self, dc, cursor, value): |
|
465 if self.StartTick <= cursor <= self.EndTick: |
|
466 # Prepare temporary dc for drawing |
|
467 width = self.Canvas._Buffer.GetWidth() |
|
468 height = self.Canvas._Buffer.GetHeight() |
|
469 tmp_Buffer = wx.EmptyBitmap(width, height) |
|
470 dcs = wx.MemoryDC() |
|
471 dcs.SelectObject(tmp_Buffer) |
|
472 dcs.Clear() |
|
473 dcs.BeginDrawing() |
|
474 |
|
475 dcs.SetPen(wx.Pen(wx.RED)) |
|
476 dcs.SetBrush(wx.Brush(wx.RED, wx.SOLID)) |
|
477 dcs.SetFont(self.Canvas._getFont(self.Canvas._fontSizeAxis)) |
|
478 |
|
479 # Calculate clipping region |
|
480 graphics, xAxis, yAxis = self.Canvas.last_draw |
|
481 p1 = numpy.array([xAxis[0], yAxis[0]]) |
|
482 p2 = numpy.array([xAxis[1], yAxis[1]]) |
|
483 cx, cy, cwidth, cheight = self.Canvas._point2ClientCoord(p1, p2) |
|
484 |
|
485 px, py = self.Canvas.PositionUserToScreen((float(cursor), 0.)) |
|
486 |
|
487 # Draw line cross drawing for diaplaying time cursor |
|
488 dcs.DrawLine(px, cy + 1, px, cy + cheight - 1) |
|
489 |
|
490 text = "X:%d\nY:%f"%(cursor, value) |
|
491 w, h = dcs.GetTextExtent(text) |
|
492 # Draw time cursor date |
|
493 dcs.DrawText(text, min(px + 3, cx + cwidth - w), cy + 3) |
|
494 |
|
495 dcs.EndDrawing() |
|
496 |
|
497 #this will erase if called twice |
|
498 dc.Blit(0, 0, width, height, dcs, 0, 0, wx.EQUIV) #(NOT src) XOR dst |
|
499 |
|
500 ## Refresh the variable cursor. |
|
501 # @param dc The draw canvas |
|
502 def RefreshCursor(self, dc=None): |
|
503 if dc is None: |
|
504 dc = wx.BufferedDC(wx.ClientDC(self.Canvas.canvas), self.Canvas._Buffer) |
|
505 |
|
506 # Erase previous time cursor if drawn |
|
507 if self.LastCursor is not None: |
|
508 self.DrawCursor(dc, *self.LastCursor) |
|
509 |
|
510 # Draw new time cursor |
|
511 if self.CursorIdx is not None: |
|
512 self.LastCursor = self.Datas[self.CursorIdx] |
|
513 self.DrawCursor(dc, *self.LastCursor) |