Remove `LevelLine.add_label()`, add dynamic pp marker label
							parent
							
								
									62517c1662
								
							
						
					
					
						commit
						791fd23524
					
				| 
						 | 
					@ -36,12 +36,6 @@ from ._style import hcolor, _font
 | 
				
			||||||
# https://stackoverflow.com/questions/26156486/determine-bounding-rect-of-line-in-qt
 | 
					# https://stackoverflow.com/questions/26156486/determine-bounding-rect-of-line-in-qt
 | 
				
			||||||
class LevelLine(pg.InfiniteLine):
 | 
					class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # TODO: fill in these slots for orders
 | 
					 | 
				
			||||||
    # available parent signals
 | 
					 | 
				
			||||||
    # sigDragged(self)
 | 
					 | 
				
			||||||
    # sigPositionChangeFinished(self)
 | 
					 | 
				
			||||||
    # sigPositionChanged(self)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(
 | 
					    def __init__(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        chart: 'ChartPlotWidget',  # type: ignore # noqa
 | 
					        chart: 'ChartPlotWidget',  # type: ignore # noqa
 | 
				
			||||||
| 
						 | 
					@ -63,6 +57,9 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ) -> None:
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: at this point it's probably not worth the inheritance
 | 
				
			||||||
 | 
					        # any more since  we've reimplemented ``.pain()`` among other
 | 
				
			||||||
 | 
					        # things..
 | 
				
			||||||
        super().__init__(
 | 
					        super().__init__(
 | 
				
			||||||
            movable=movable,
 | 
					            movable=movable,
 | 
				
			||||||
            angle=0,
 | 
					            angle=0,
 | 
				
			||||||
| 
						 | 
					@ -97,7 +94,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # list of labels anchored at one of the 2 line endpoints
 | 
					        # list of labels anchored at one of the 2 line endpoints
 | 
				
			||||||
        # inside the viewbox
 | 
					        # inside the viewbox
 | 
				
			||||||
        self._labels: List[(int, Label)] = []
 | 
					        self._labels: List[Label] = []
 | 
				
			||||||
        self._markers: List[(int, Label)] = []
 | 
					        self._markers: List[(int, Label)] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # whenever this line is moved trigger label updates
 | 
					        # whenever this line is moved trigger label updates
 | 
				
			||||||
| 
						 | 
					@ -143,52 +140,6 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
        hoverpen.setWidth(2)
 | 
					        hoverpen.setWidth(2)
 | 
				
			||||||
        self.hoverPen = hoverpen
 | 
					        self.hoverPen = hoverpen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_label(
 | 
					 | 
				
			||||||
        self,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # by default we only display the line's level value
 | 
					 | 
				
			||||||
        # in the label
 | 
					 | 
				
			||||||
        fmt_str: str = (
 | 
					 | 
				
			||||||
            '{level:,.{level_digits}f}'
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        side: str = 'right',
 | 
					 | 
				
			||||||
        side_of_axis: str = 'left',
 | 
					 | 
				
			||||||
        x_offset: float = 0,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        color: str = None,
 | 
					 | 
				
			||||||
        bg_color: str = None,
 | 
					 | 
				
			||||||
        avoid_book: bool = True,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        **label_kwargs,
 | 
					 | 
				
			||||||
    ) -> Label:
 | 
					 | 
				
			||||||
        """Add a ``LevelLabel`` anchored at one of the line endpoints in view.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        label = Label(
 | 
					 | 
				
			||||||
            view=self.getViewBox(),
 | 
					 | 
				
			||||||
            fmt_str=fmt_str,
 | 
					 | 
				
			||||||
            color=self.color,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # set anchor callback
 | 
					 | 
				
			||||||
        if side == 'right':
 | 
					 | 
				
			||||||
            label.set_x_anchor_func(
 | 
					 | 
				
			||||||
                right_axis(
 | 
					 | 
				
			||||||
                    self._chart,
 | 
					 | 
				
			||||||
                    label,
 | 
					 | 
				
			||||||
                    side=side_of_axis,
 | 
					 | 
				
			||||||
                    offset=x_offset,
 | 
					 | 
				
			||||||
                    avoid_book=avoid_book,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        elif side == 'left':
 | 
					 | 
				
			||||||
            label.set_x_anchor_func(vbr_left(label))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self._labels.append((side, label))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return label
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def on_pos_change(
 | 
					    def on_pos_change(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        line: 'LevelLine',  # noqa
 | 
					        line: 'LevelLine',  # noqa
 | 
				
			||||||
| 
						 | 
					@ -201,9 +152,11 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
    def update_labels(
 | 
					    def update_labels(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        fields_data: dict,
 | 
					        fields_data: dict,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ) -> None:
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for at, label in self._labels:
 | 
					        for label in self._labels:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            label.color = self.color
 | 
					            label.color = self.color
 | 
				
			||||||
            # print(f'color is {self.color}')
 | 
					            # print(f'color is {self.color}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -211,18 +164,18 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            level = fields_data.get('level')
 | 
					            level = fields_data.get('level')
 | 
				
			||||||
            if level:
 | 
					            if level:
 | 
				
			||||||
                label.set_view_y(level)
 | 
					                label.set_view_pos(y=level)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            label.render()
 | 
					            label.render()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.update()
 | 
					        self.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hide_labels(self) -> None:
 | 
					    def hide_labels(self) -> None:
 | 
				
			||||||
        for at, label in self._labels:
 | 
					        for label in self._labels:
 | 
				
			||||||
            label.hide()
 | 
					            label.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def show_labels(self) -> None:
 | 
					    def show_labels(self) -> None:
 | 
				
			||||||
        for at, label in self._labels:
 | 
					        for label in self._labels:
 | 
				
			||||||
            label.show()
 | 
					            label.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_level(
 | 
					    def set_level(
 | 
				
			||||||
| 
						 | 
					@ -316,9 +269,10 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        scene = self.scene()
 | 
					        scene = self.scene()
 | 
				
			||||||
        if scene:
 | 
					        if scene:
 | 
				
			||||||
            for at, label in self._labels:
 | 
					            for label in self._labels:
 | 
				
			||||||
                label.delete()
 | 
					                label.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # gc managed labels?
 | 
				
			||||||
            self._labels.clear()
 | 
					            self._labels.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self._marker:
 | 
					            if self._marker:
 | 
				
			||||||
| 
						 | 
					@ -406,6 +360,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
            self._marker.setPos(
 | 
					            self._marker.setPos(
 | 
				
			||||||
                QPointF(marker_right, self.scene_y())
 | 
					                QPointF(marker_right, self.scene_y())
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            self._marker.label.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif not self.use_marker_margin:
 | 
					        elif not self.use_marker_margin:
 | 
				
			||||||
            # basically means **don't** shorten the line with normally
 | 
					            # basically means **don't** shorten the line with normally
 | 
				
			||||||
| 
						 | 
					@ -439,7 +394,8 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
    def add_marker(
 | 
					    def add_marker(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        path: QtWidgets.QGraphicsPathItem,
 | 
					        path: QtWidgets.QGraphicsPathItem,
 | 
				
			||||||
    ) -> None:
 | 
					
 | 
				
			||||||
 | 
					    ) -> QtWidgets.QGraphicsPathItem:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # add path to scene
 | 
					        # add path to scene
 | 
				
			||||||
        self.getViewBox().scene().addItem(path)
 | 
					        self.getViewBox().scene().addItem(path)
 | 
				
			||||||
| 
						 | 
					@ -453,6 +409,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
        # y_in_sc = chart._vb.mapFromView(Point(0, self.value())).y()
 | 
					        # y_in_sc = chart._vb.mapFromView(Point(0, self.value())).y()
 | 
				
			||||||
        path.setPos(QPointF(rsc, self.scene_y()))
 | 
					        path.setPos(QPointF(rsc, self.scene_y()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return path
 | 
				
			||||||
        # self.update()
 | 
					        # self.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hoverEvent(self, ev):
 | 
					    def hoverEvent(self, ev):
 | 
				
			||||||
| 
						 | 
					@ -471,6 +428,9 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
            if self._moh:
 | 
					            if self._moh:
 | 
				
			||||||
                self.show_markers = True
 | 
					                self.show_markers = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if self._marker:
 | 
				
			||||||
 | 
					                    self._marker.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # highlight if so configured
 | 
					            # highlight if so configured
 | 
				
			||||||
            if self._hoh:
 | 
					            if self._hoh:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -514,11 +474,14 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
            if self._moh:
 | 
					            if self._moh:
 | 
				
			||||||
                self.show_markers = False
 | 
					                self.show_markers = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if self._marker:
 | 
				
			||||||
 | 
					                    self._marker.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self not in cur._trackers:
 | 
					            if self not in cur._trackers:
 | 
				
			||||||
                cur.show_xhair(y_label_level=self.value())
 | 
					                cur.show_xhair(y_label_level=self.value())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not self._always_show_labels:
 | 
					            if not self._always_show_labels:
 | 
				
			||||||
                for at, label in self._labels:
 | 
					                for label in self._labels:
 | 
				
			||||||
                    label.hide()
 | 
					                    label.hide()
 | 
				
			||||||
                    label.txt.update()
 | 
					                    label.txt.update()
 | 
				
			||||||
                    # label.unhighlight()
 | 
					                    # label.unhighlight()
 | 
				
			||||||
| 
						 | 
					@ -531,24 +494,19 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
def level_line(
 | 
					def level_line(
 | 
				
			||||||
    chart: 'ChartPlotWidget',  # noqa
 | 
					    chart: 'ChartPlotWidget',  # noqa
 | 
				
			||||||
    level: float,
 | 
					    level: float,
 | 
				
			||||||
    color: str = 'default',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # whether or not the line placed in view should highlight
 | 
					 | 
				
			||||||
    # when moused over (aka "hovered")
 | 
					 | 
				
			||||||
    hl_on_hover: bool = True,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # line style
 | 
					    # line style
 | 
				
			||||||
    dotted: bool = False,
 | 
					    dotted: bool = False,
 | 
				
			||||||
 | 
					    color: str = 'default',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # ux
 | 
				
			||||||
 | 
					    hl_on_hover: bool = True,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # label fields and options
 | 
					    # label fields and options
 | 
				
			||||||
    digits: int = 1,
 | 
					    digits: int = 1,
 | 
				
			||||||
 | 
					 | 
				
			||||||
    always_show_labels: bool = False,
 | 
					    always_show_labels: bool = False,
 | 
				
			||||||
 | 
					 | 
				
			||||||
    add_label: bool = True,
 | 
					    add_label: bool = True,
 | 
				
			||||||
 | 
					 | 
				
			||||||
    orient_v: str = 'bottom',
 | 
					    orient_v: str = 'bottom',
 | 
				
			||||||
 | 
					 | 
				
			||||||
    **kwargs,
 | 
					    **kwargs,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
) -> LevelLine:
 | 
					) -> LevelLine:
 | 
				
			||||||
| 
						 | 
					@ -580,14 +538,31 @@ def level_line(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if add_label:
 | 
					    if add_label:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        label = line.add_label(
 | 
					        label = Label(
 | 
				
			||||||
            side='right',
 | 
					
 | 
				
			||||||
            opacity=1,
 | 
					            view=line.getViewBox(),
 | 
				
			||||||
            x_offset=0,
 | 
					
 | 
				
			||||||
 | 
					            # by default we only display the line's level value
 | 
				
			||||||
 | 
					            # in the label
 | 
				
			||||||
 | 
					            fmt_str=('{level:,.{level_digits}f}'),
 | 
				
			||||||
 | 
					            color=color,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # anchor to right side (of view ) label
 | 
				
			||||||
 | 
					        label.set_x_anchor_func(
 | 
				
			||||||
 | 
					            right_axis(
 | 
				
			||||||
 | 
					                chart,
 | 
				
			||||||
 | 
					                label,
 | 
				
			||||||
 | 
					                side='left',  # side of axis
 | 
				
			||||||
 | 
					                offset=0,
 | 
				
			||||||
                avoid_book=False,
 | 
					                avoid_book=False,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        label.orient_v = orient_v
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # add to label set which will be updated on level changes
 | 
				
			||||||
 | 
					        line._labels.append(label)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        label.orient_v = orient_v
 | 
				
			||||||
        line.update_labels({'level': level, 'level_digits': 2})
 | 
					        line.update_labels({'level': level, 'level_digits': 2})
 | 
				
			||||||
        label.render()
 | 
					        label.render()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -600,6 +575,7 @@ def level_line(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def order_line(
 | 
					def order_line(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chart,
 | 
					    chart,
 | 
				
			||||||
    level: float,
 | 
					    level: float,
 | 
				
			||||||
    level_digits: float,
 | 
					    level_digits: float,
 | 
				
			||||||
| 
						 | 
					@ -651,7 +627,8 @@ def order_line(
 | 
				
			||||||
        # resetting the graphics item transform intermittently
 | 
					        # resetting the graphics item transform intermittently
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # XXX: this is our new approach but seems slower?
 | 
					        # XXX: this is our new approach but seems slower?
 | 
				
			||||||
        # line.add_marker(mk_marker(marker_style, marker_size))
 | 
					        # path = line.add_marker(mk_marker(marker_style, marker_size))
 | 
				
			||||||
 | 
					        # assert line._marker == path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert not line.markers
 | 
					        assert not line.markers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -672,14 +649,22 @@ def order_line(
 | 
				
			||||||
    orient_v = 'top' if action == 'sell' else 'bottom'
 | 
					    orient_v = 'top' if action == 'sell' else 'bottom'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if action == 'alert':
 | 
					    if action == 'alert':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        llabel = Label(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            view=line.getViewBox(),
 | 
				
			||||||
 | 
					            color=line.color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # completely different labelling for alerts
 | 
					            # completely different labelling for alerts
 | 
				
			||||||
        fmt_str = 'alert => {level}'
 | 
					            fmt_str='alert => {level}',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # for now, we're just duplicating the label contents i guess..
 | 
					        # for now, we're just duplicating the label contents i guess..
 | 
				
			||||||
        llabel = line.add_label(
 | 
					        line._labels.append(llabel)
 | 
				
			||||||
            side='left',
 | 
					
 | 
				
			||||||
            fmt_str=fmt_str,
 | 
					        # anchor to left side of view / line
 | 
				
			||||||
        )
 | 
					        llabel.set_x_anchor_func(vbr_left(llabel))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        llabel.fields = {
 | 
					        llabel.fields = {
 | 
				
			||||||
            'level': level,
 | 
					            'level': level,
 | 
				
			||||||
            'level_digits': level_digits,
 | 
					            'level_digits': level_digits,
 | 
				
			||||||
| 
						 | 
					@ -689,31 +674,30 @@ def order_line(
 | 
				
			||||||
        llabel.show()
 | 
					        llabel.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # # left side label
 | 
					 | 
				
			||||||
        # llabel = line.add_label(
 | 
					 | 
				
			||||||
        #     side='left',
 | 
					 | 
				
			||||||
        #     fmt_str=' {exec_type}-{order_type}:\n ${$value}',
 | 
					 | 
				
			||||||
        # )
 | 
					 | 
				
			||||||
        # llabel.fields = {
 | 
					 | 
				
			||||||
        #     'order_type': order_type,
 | 
					 | 
				
			||||||
        #     'level': level,
 | 
					 | 
				
			||||||
        #     '$value': lambda f: f['level'] * f['size'],
 | 
					 | 
				
			||||||
        #     'size': size,
 | 
					 | 
				
			||||||
        #     'exec_type': exec_type,
 | 
					 | 
				
			||||||
        # }
 | 
					 | 
				
			||||||
        # llabel.orient_v = orient_v
 | 
					 | 
				
			||||||
        # llabel.render()
 | 
					 | 
				
			||||||
        # llabel.show()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # right before L1 label
 | 
					        rlabel = Label(
 | 
				
			||||||
        rlabel = line.add_label(
 | 
					
 | 
				
			||||||
            side='right',
 | 
					            view=line.getViewBox(),
 | 
				
			||||||
            side_of_axis='left',
 | 
					
 | 
				
			||||||
            x_offset=4*marker_size,
 | 
					            # display the order pos size
 | 
				
			||||||
            fmt_str=(
 | 
					            fmt_str=('{size:.{size_digits}f} '),
 | 
				
			||||||
                '{size:.{size_digits}f} '
 | 
					            color=line.color,
 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # set anchor callback
 | 
				
			||||||
 | 
					        # right side label by default
 | 
				
			||||||
 | 
					        rlabel.set_x_anchor_func(
 | 
				
			||||||
 | 
					            right_axis(
 | 
				
			||||||
 | 
					                chart,
 | 
				
			||||||
 | 
					                rlabel,
 | 
				
			||||||
 | 
					                side='left',  # side of axis
 | 
				
			||||||
 | 
					                offset=4*marker_size,
 | 
				
			||||||
 | 
					                avoid_book=True,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        line._labels.append(rlabel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rlabel.fields = {
 | 
					        rlabel.fields = {
 | 
				
			||||||
            'size': size,
 | 
					            'size': size,
 | 
				
			||||||
            'size_digits': size_digits,
 | 
					            'size_digits': size_digits,
 | 
				
			||||||
| 
						 | 
					@ -742,69 +726,23 @@ def position_line(
 | 
				
			||||||
    execution submitted to the EMS via the chart's "order mode".
 | 
					    execution submitted to the EMS via the chart's "order mode".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    hcolor = 'default_light'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    line = level_line(
 | 
					    line = level_line(
 | 
				
			||||||
        chart,
 | 
					        chart,
 | 
				
			||||||
        level,
 | 
					        level,
 | 
				
			||||||
        color='default_light',
 | 
					        color=hcolor,
 | 
				
			||||||
        add_label=False,
 | 
					        add_label=False,
 | 
				
			||||||
        hl_on_hover=False,
 | 
					        hl_on_hover=False,
 | 
				
			||||||
        movable=False,
 | 
					        movable=False,
 | 
				
			||||||
        always_show_labels=False,
 | 
					 | 
				
			||||||
        hide_xhair_on_hover=False,
 | 
					        hide_xhair_on_hover=False,
 | 
				
			||||||
        use_marker_margin=True,
 | 
					        use_marker_margin=True,
 | 
				
			||||||
 | 
					        only_show_markers_on_hover=False,
 | 
				
			||||||
 | 
					        always_show_labels=True,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    #  hide position marker when out of view (for now)
 | 
					    #  hide position marker when out of view (for now)
 | 
				
			||||||
    vb = line.getViewBox()
 | 
					    vb = line.getViewBox()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_pp_nav(chartview):
 | 
					 | 
				
			||||||
        vr = vb.state['viewRange']
 | 
					 | 
				
			||||||
        ymn, ymx = vr[1]
 | 
					 | 
				
			||||||
        level = line.value()
 | 
					 | 
				
			||||||
        path = line._marker
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # provide "nav hub" like indicator for where
 | 
					 | 
				
			||||||
        # the position is on the y-dimension
 | 
					 | 
				
			||||||
        # print(path._height)
 | 
					 | 
				
			||||||
        # print(vb.shape())
 | 
					 | 
				
			||||||
        # print(vb.boundingRect())
 | 
					 | 
				
			||||||
        # print(vb.height())
 | 
					 | 
				
			||||||
        _, marker_right, _ = line.marker_right_points()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if level > ymx:  # pin to top of view
 | 
					 | 
				
			||||||
            path.setPos(
 | 
					 | 
				
			||||||
                QPointF(
 | 
					 | 
				
			||||||
                    marker_right,
 | 
					 | 
				
			||||||
                    2 + path._height,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        elif level < ymn:  # pin to bottom of view
 | 
					 | 
				
			||||||
            path.setPos(
 | 
					 | 
				
			||||||
                QPointF(
 | 
					 | 
				
			||||||
                    marker_right,
 | 
					 | 
				
			||||||
                    vb.height() - 16 + path._height,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # pp line is viewable so show marker
 | 
					 | 
				
			||||||
            line._marker.show()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vb.sigYRangeChanged.connect(update_pp_nav)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    rlabel = line.add_label(
 | 
					 | 
				
			||||||
        side='right',
 | 
					 | 
				
			||||||
        fmt_str='{direction}: {size} -> ${$:.2f}',
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    rlabel.fields = {
 | 
					 | 
				
			||||||
        'direction': 'long' if size > 0 else 'short',
 | 
					 | 
				
			||||||
        '$': size * level,
 | 
					 | 
				
			||||||
        'size': size,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rlabel.orient_v = orient_v
 | 
					 | 
				
			||||||
    rlabel.render()
 | 
					 | 
				
			||||||
    rlabel.show()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # arrow marker
 | 
					    # arrow marker
 | 
				
			||||||
    # scale marker size with dpi-aware font size
 | 
					    # scale marker size with dpi-aware font size
 | 
				
			||||||
    font_size = _font.font.pixelSize()
 | 
					    font_size = _font.font.pixelSize()
 | 
				
			||||||
| 
						 | 
					@ -819,8 +757,40 @@ def position_line(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    arrow_path = mk_marker(style, size=arrow_size)
 | 
					    arrow_path = mk_marker(style, size=arrow_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    path_br = arrow_path.mapToScene(
 | 
				
			||||||
 | 
					        arrow_path.path()
 | 
				
			||||||
 | 
					    ).boundingRect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # monkey-cache height for sizing on pp nav-hub
 | 
					    # monkey-cache height for sizing on pp nav-hub
 | 
				
			||||||
    arrow_path._height = arrow_path.boundingRect().height()
 | 
					    arrow_path._height = path_br.height()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arrow_path._width = path_br.width()
 | 
				
			||||||
 | 
					    # wp = QPointF(w, w)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    marker_label = Label(
 | 
				
			||||||
 | 
					        view=vb,
 | 
				
			||||||
 | 
					        fmt_str='pp',
 | 
				
			||||||
 | 
					        color=hcolor,
 | 
				
			||||||
 | 
					        update_on_range_change=False,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    arrow_path.label = marker_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # def arrow_br():
 | 
				
			||||||
 | 
					    #     # get actual arrow graphics path
 | 
				
			||||||
 | 
					    #     path_br = arrow_path.mapToScene(
 | 
				
			||||||
 | 
					    #         arrow_path.path()
 | 
				
			||||||
 | 
					    #     ).boundingRect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #     # vb.locate(arrow_path)  #, children=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #     return path_br.bottomRight() - QPointF(0, marker_label.h / 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # marker_label.scene_anchor = arrow_br
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line._labels.append(marker_label)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    marker_label.render()
 | 
				
			||||||
 | 
					    marker_label.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # XXX: uses new marker drawing approach
 | 
					    # XXX: uses new marker drawing approach
 | 
				
			||||||
    line.add_marker(arrow_path)
 | 
					    line.add_marker(arrow_path)
 | 
				
			||||||
| 
						 | 
					@ -829,4 +799,56 @@ def position_line(
 | 
				
			||||||
    # sanity check
 | 
					    # sanity check
 | 
				
			||||||
    line.update_labels({'level': level})
 | 
					    line.update_labels({'level': level})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_pp_nav(chartview):
 | 
				
			||||||
 | 
					        '''Show a pp off-screen indicator when order mode is activated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        vr = vb.state['viewRange']
 | 
				
			||||||
 | 
					        ymn, ymx = vr[1]
 | 
				
			||||||
 | 
					        level = line.value()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        path = line._marker
 | 
				
			||||||
 | 
					        label = path.label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # get actual arrow-marker graphics path
 | 
				
			||||||
 | 
					        path_br = path.mapToScene(
 | 
				
			||||||
 | 
					            path.path()
 | 
				
			||||||
 | 
					        ).boundingRect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # provide "nav hub" like indicator for where
 | 
				
			||||||
 | 
					        # the position is on the y-dimension
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _, marker_right, _ = line.marker_right_points()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if level > ymx:  # pin to top of view
 | 
				
			||||||
 | 
					            path.setPos(
 | 
				
			||||||
 | 
					                QPointF(
 | 
				
			||||||
 | 
					                    marker_right,
 | 
				
			||||||
 | 
					                    path._height/3,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif level < ymn:  # pin to bottom of view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            path.setPos(
 | 
				
			||||||
 | 
					                QPointF(
 | 
				
			||||||
 | 
					                    marker_right,
 | 
				
			||||||
 | 
					                    vb.height() - 4/3*path._height,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # adjust marker labels to be above bottom of view
 | 
				
			||||||
 | 
					            label.txt.setPos(path_br.topRight() - QPointF(0, label.h / 2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # pp line is viewable so show marker normally
 | 
				
			||||||
 | 
					            line._marker.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # place label at bottom right of pp marker
 | 
				
			||||||
 | 
					            label.txt.setPos(path_br.bottomRight() - QPointF(0, label.h / 2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        line.show_labels()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vb.sigRangeChanged.connect(update_pp_nav)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return line
 | 
					    return line
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue