Extend level line interaction

Support tracking the mouse cursor using a new `on_tracked_sources()`
callback method. Make hovered highlight a bit thicker and highlight when
click-dragged. Add a delete method for removing from the scene along
with label.
basic_alerts
Tyler Goodlet 2021-01-03 10:43:53 -05:00
parent edbbcbf954
commit 14dad08d98
1 changed files with 90 additions and 13 deletions

View File

@ -33,8 +33,6 @@ from .._axes import YSticky
class LevelLabel(YSticky): class LevelLabel(YSticky):
line_pen = pg.mkPen(hcolor('bracket'))
_w_margin = 4 _w_margin = 4
_h_margin = 3 _h_margin = 3
level: float = 0 level: float = 0
@ -43,13 +41,15 @@ class LevelLabel(YSticky):
self, self,
chart, chart,
*args, *args,
color: str = 'bracket',
orient_v: str = 'bottom', orient_v: str = 'bottom',
orient_h: str = 'left', orient_h: str = 'left',
**kwargs **kwargs
) -> None: ) -> None:
super().__init__(chart, *args, **kwargs) super().__init__(chart, *args, **kwargs)
self._pen = self.line_pen # TODO: this is kinda cludgy
self._pen = self.pen = pg.mkPen(hcolor(color))
# orientation around axis options # orientation around axis options
self._orient_v = orient_v self._orient_v = orient_v
@ -77,7 +77,7 @@ class LevelLabel(YSticky):
br = self.boundingRect() br = self.boundingRect()
h, w = br.height(), br.width() h, w = br.height(), br.width()
# this triggers ``.pain()`` implicitly? # this triggers ``.paint()`` implicitly?
self.setPos(QPointF( self.setPos(QPointF(
self._h_shift * w - offset, self._h_shift * w - offset,
abs_pos.y() - (self._v_shift * h) - offset abs_pos.y() - (self._v_shift * h) - offset
@ -118,11 +118,10 @@ class LevelLabel(YSticky):
self.update() self.update()
def unhighlight(self): def unhighlight(self):
self._pen = self.line_pen self._pen = self.pen
self.update() self.update()
class L1Label(LevelLabel): class L1Label(LevelLabel):
size: float = 0 size: float = 0
@ -192,52 +191,124 @@ class L1Labels:
class LevelLine(pg.InfiniteLine): class LevelLine(pg.InfiniteLine):
# TODO: fill in these slots for orders
# .sigPositionChangeFinished.emit(self)
def __init__( def __init__(
self, self,
chart: 'ChartPlotWidget', # type: ignore # noqa
label: LevelLabel, label: LevelLabel,
highlight_color: str = 'default_light',
**kwargs, **kwargs,
) -> None: ) -> None:
self.label = label self.label = label
super().__init__(**kwargs) super().__init__(**kwargs)
self.sigPositionChanged.connect(self.set_level) self.sigPositionChanged.connect(self.set_level)
self._chart = chart
# use slightly thicker highlight # use slightly thicker highlight
self.setHoverPen( pen = pg.mkPen(hcolor(highlight_color))
color=(255, 0, 0), pen.setWidth(2)
width=self.pen.width() + 1 self.setHoverPen(pen)
) self._track_cursor: bool = False
def set_level(self, value: float) -> None: def set_level(self, value: float) -> None:
self.label.update_from_data(0, self.value()) self.label.update_from_data(0, self.value())
def on_tracked_source(
self,
x: int,
y: float
) -> None:
self.movable = True
self.setPos(y) # implictly calls ``.set_level()``
self.update()
def setMouseHover(self, hover: bool) -> None: def setMouseHover(self, hover: bool) -> None:
"""Mouse hover callback. """Mouse hover callback.
""" """
if self.mouseHovering == hover: if self.mouseHovering == hover:
return return
self.mouseHovering = hover self.mouseHovering = hover
chart = self._chart
if hover: if hover:
self.currentPen = self.hoverPen self.currentPen = self.hoverPen
self.label.highlight(self.hoverPen) self.label.highlight(self.hoverPen)
# add us to cursor state
chart._cursor.add_hovered(self)
# # hide y-crosshair
# chart._cursor.graphics[chart]['hl'].hide()
else: else:
self.currentPen = self.pen self.currentPen = self.pen
self.label.unhighlight() self.label.unhighlight()
chart._cursor._hovered.remove(self)
# highlight any attached label # highlight any attached label
# self.setCursor(QtCore.Qt.OpenHandCursor) # self.setCursor(QtCore.Qt.OpenHandCursor)
# self.setCursor(QtCore.Qt.DragMoveCursor) # self.setCursor(QtCore.Qt.DragMoveCursor)
self.update() self.update()
def mouseDragEvent(self, ev):
chart = self._chart
# hide y-crosshair
chart._cursor.graphics[chart]['hl'].hide()
# highlight
self.currentPen = self.hoverPen
self.label.highlight(self.hoverPen)
# normal tracking behavior
super().mouseDragEvent(ev)
# This is the final position in the drag
if ev.isFinish():
# show y-crosshair again
chart = self._chart
chart._cursor.graphics[chart]['hl'].show()
def mouseDoubleClickEvent(
self,
ev: QtGui.QMouseEvent,
) -> None:
print(f'double click {ev}')
# def mouseMoved(
# self,
# ev: Tuple[QtGui.QMouseEvent],
# ) -> None:
# pos = evt[0]
# print(pos)
def delete(self) -> None:
"""Remove this line from containing chart/view/scene.
"""
scene = self.scene()
if scene:
# self.label.parent.scene().removeItem(self.label)
scene.removeItem(self.label)
self._chart.plotItem.removeItem(self)
def level_line( def level_line(
chart: 'ChartPlogWidget', # noqa chart: 'ChartPlogWidget', # noqa
level: float, level: float,
digits: int = 1, digits: int = 1,
color: str = 'default',
# size 4 font on 4k screen scaled down, so small-ish. # size 4 font on 4k screen scaled down, so small-ish.
font_size_inches: float = _down_2_font_inches_we_like, font_size_inches: float = _down_2_font_inches_we_like,
@ -254,11 +325,13 @@ def level_line(
parent=chart.getAxis('right'), parent=chart.getAxis('right'),
# TODO: pass this from symbol data # TODO: pass this from symbol data
digits=digits, digits=digits,
opacity=1, opacity=0.666,
font_size_inches=font_size_inches, font_size_inches=font_size_inches,
color=color,
# TODO: make this take the view's bg pen # TODO: make this take the view's bg pen
bg_color='papas_special', bg_color='papas_special',
fg_color='default', fg_color=color,
**linelabelkwargs **linelabelkwargs
) )
label.update_from_data(0, level) label.update_from_data(0, level)
@ -267,12 +340,16 @@ def level_line(
label._size_br_from_str(label.label_str) label._size_br_from_str(label.label_str)
line = LevelLine( line = LevelLine(
chart,
label, label,
# lookup "highlight" equivalent
highlight_color=color + '_light',
movable=True, movable=True,
angle=0, angle=0,
) )
line.setValue(level) line.setValue(level)
line.setPen(pg.mkPen(hcolor('default'))) line.setPen(pg.mkPen(hcolor(color)))
# activate/draw label # activate/draw label
line.setValue(level) line.setValue(level)