Even more correct "default view" snap-to-pp-marker
This makes the `'r'` hotkey snap the last bar to the middle of the pp line arrow marker no matter the zoom level. Now we also boot with approximately the most number of x units on screen that keep the bars graphics drawn in full (just before downsampling to a line). Moved some internals around to get this all in place, - drop `_anchors.marker_right_points()` and move it to a chart method. - change `.pre_l1_x()` -> `.pre_l1_xs()` and just have it return the two view-mapped x values from the former method.mkts_backup
							parent
							
								
									4af941566a
								
							
						
					
					
						commit
						3b96b52474
					
				| 
						 | 
					@ -29,34 +29,6 @@ if TYPE_CHECKING:
 | 
				
			||||||
    from ._label import Label
 | 
					    from ._label import Label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def marker_right_points(
 | 
					 | 
				
			||||||
    chart: ChartPlotWidget,  # noqa
 | 
					 | 
				
			||||||
    marker_size: int = 20,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
) -> (float, float, float):
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
    Return x-dimension, y-axis-aware, level-line marker oriented scene
 | 
					 | 
				
			||||||
    values.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    X values correspond to set the end of a level line, end of
 | 
					 | 
				
			||||||
    a paried level line marker, and the right most side of the "right"
 | 
					 | 
				
			||||||
    axis respectively.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
    # TODO: compute some sensible maximum value here
 | 
					 | 
				
			||||||
    # and use a humanized scheme to limit to that length.
 | 
					 | 
				
			||||||
    l1_len = chart._max_l1_line_len
 | 
					 | 
				
			||||||
    ryaxis = chart.getAxis('right')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    r_axis_x = ryaxis.pos().x()
 | 
					 | 
				
			||||||
    up_to_l1_sc = r_axis_x - l1_len - 10
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    marker_right = up_to_l1_sc - (1.375 * 2 * marker_size)
 | 
					 | 
				
			||||||
    line_end = marker_right - (6/16 * marker_size)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return line_end, marker_right, r_axis_x
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def vbr_left(
 | 
					def vbr_left(
 | 
				
			||||||
    label: Label,
 | 
					    label: Label,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,8 +26,6 @@ from PyQt5.QtWidgets import QGraphicsPathItem
 | 
				
			||||||
from pyqtgraph import Point, functions as fn, Color
 | 
					from pyqtgraph import Point, functions as fn, Color
 | 
				
			||||||
import numpy as np
 | 
					import numpy as np
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ._anchors import marker_right_points
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def mk_marker_path(
 | 
					def mk_marker_path(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,7 +114,7 @@ class LevelMarker(QGraphicsPathItem):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.get_level = get_level
 | 
					        self.get_level = get_level
 | 
				
			||||||
        self._on_paint = on_paint
 | 
					        self._on_paint = on_paint
 | 
				
			||||||
        self.scene_x = lambda: marker_right_points(chart)[1]
 | 
					        self.scene_x = lambda: chart.marker_right_points()[1]
 | 
				
			||||||
        self.level: float = 0
 | 
					        self.level: float = 0
 | 
				
			||||||
        self.keep_in_view = keep_in_view
 | 
					        self.keep_in_view = keep_in_view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,7 +167,7 @@ class LevelMarker(QGraphicsPathItem):
 | 
				
			||||||
        vr = view.state['viewRange']
 | 
					        vr = view.state['viewRange']
 | 
				
			||||||
        ymn, ymx = vr[1]
 | 
					        ymn, ymx = vr[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # _, marker_right, _ = marker_right_points(line._chart)
 | 
					        # _, marker_right, _ = line._chart.marker_right_points()
 | 
				
			||||||
        x = self.scene_x()
 | 
					        x = self.scene_x()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.style == '>|':  # short style, points "down-to" line
 | 
					        if self.style == '>|':  # short style, points "down-to" line
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -844,31 +844,52 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
            QLineF(lbar, 0, rbar, 0)
 | 
					            QLineF(lbar, 0, rbar, 0)
 | 
				
			||||||
        ).length()
 | 
					        ).length()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pre_l1_x(
 | 
					    def pre_l1_xs(self) -> tuple[float, float]:
 | 
				
			||||||
        self,
 | 
					 | 
				
			||||||
        view_coords: bool = False,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ) -> tuple[float, float]:
 | 
					 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        Return the scene x-coord for the value just before
 | 
					        Return the view x-coord for the value just before
 | 
				
			||||||
        the L1 labels on the y-axis as well as the length
 | 
					        the L1 labels on the y-axis as well as the length
 | 
				
			||||||
        of that L1 label from the y-axis.
 | 
					        of that L1 label from the y-axis.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        l1_len = self._max_l1_line_len
 | 
					        line_end, marker_right, yaxis_x = self.marker_right_points()
 | 
				
			||||||
        ryaxis = self.getAxis('right')
 | 
					 | 
				
			||||||
        ryaxis_x = ryaxis.pos().x()
 | 
					 | 
				
			||||||
        up_to_l1_sc = ryaxis_x - l1_len
 | 
					 | 
				
			||||||
        if not view_coords:
 | 
					 | 
				
			||||||
            return up_to_l1_sc, l1_len
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
        view = self.view
 | 
					        view = self.view
 | 
				
			||||||
        line = view.mapToView(
 | 
					        line = view.mapToView(
 | 
				
			||||||
                QLineF(up_to_l1_sc, 0, ryaxis_x, 0)
 | 
					            QLineF(line_end, 0, yaxis_x, 0)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return line.x1(), line.length()
 | 
					        return line.x1(), line.length()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def default_view(self) -> None:
 | 
					    def marker_right_points(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        marker_size: int = 20,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ) -> (float, float, float):
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        Return x-dimension, y-axis-aware, level-line marker oriented scene
 | 
				
			||||||
 | 
					        values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        X values correspond to set the end of a level line, end of
 | 
				
			||||||
 | 
					        a paried level line marker, and the right most side of the "right"
 | 
				
			||||||
 | 
					        axis respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        # TODO: compute some sensible maximum value here
 | 
				
			||||||
 | 
					        # and use a humanized scheme to limit to that length.
 | 
				
			||||||
 | 
					        l1_len = self._max_l1_line_len
 | 
				
			||||||
 | 
					        ryaxis = self.getAxis('right')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r_axis_x = ryaxis.pos().x()
 | 
				
			||||||
 | 
					        up_to_l1_sc = r_axis_x - l1_len - 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        marker_right = up_to_l1_sc - (1.375 * 2 * marker_size)
 | 
				
			||||||
 | 
					        line_end = marker_right - (6/16 * marker_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return line_end, marker_right, r_axis_x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def default_view(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        steps_on_screen: Optional[int] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        Set the view box to the "default" startup view of the scene.
 | 
					        Set the view box to the "default" startup view of the scene.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -880,15 +901,25 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        xfirst, xlast = index[0], index[-1]
 | 
					        xfirst, xlast = index[0], index[-1]
 | 
				
			||||||
        view = self.view
 | 
					        brange = l, lbar, rbar, r = self.bars_range()
 | 
				
			||||||
        vr = view.viewRange()
 | 
					 | 
				
			||||||
        marker_pos, l1_len = self.pre_l1_x(view_coords=True)
 | 
					 | 
				
			||||||
        end = xlast + l1_len
 | 
					 | 
				
			||||||
        xl = vr[0][0]
 | 
					 | 
				
			||||||
        begin = max(xl, xfirst)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        marker_pos, l1_len = self.pre_l1_xs()
 | 
				
			||||||
 | 
					        end = xlast + l1_len
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					            rbar < 0
 | 
				
			||||||
 | 
					            or l < xfirst
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            # set fixed bars count on screen that approx includes as
 | 
				
			||||||
 | 
					            # many bars as possible before a downsample line is shown.
 | 
				
			||||||
 | 
					            begin = xlast - round(6116 / 6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            begin = end - (r - l)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # for debugging
 | 
				
			||||||
        # print(
 | 
					        # print(
 | 
				
			||||||
        #     f'view range: {vr}\n'
 | 
					        #     f'bars range: {brange}\n'
 | 
				
			||||||
        #     f'xlast: {xlast}\n'
 | 
					        #     f'xlast: {xlast}\n'
 | 
				
			||||||
        #     f'marker pos: {marker_pos}\n'
 | 
					        #     f'marker pos: {marker_pos}\n'
 | 
				
			||||||
        #     f'l1 len: {l1_len}\n'
 | 
					        #     f'l1 len: {l1_len}\n'
 | 
				
			||||||
| 
						 | 
					@ -900,6 +931,7 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
        if self._static_yrange == 'axis':
 | 
					        if self._static_yrange == 'axis':
 | 
				
			||||||
            self._static_yrange = None
 | 
					            self._static_yrange = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        view = self.view
 | 
				
			||||||
        view.setXRange(
 | 
					        view.setXRange(
 | 
				
			||||||
            min=begin,
 | 
					            min=begin,
 | 
				
			||||||
            max=end,
 | 
					            max=end,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,6 @@ from PyQt5.QtCore import QPointF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ._annotate import qgo_draw_markers, LevelMarker
 | 
					from ._annotate import qgo_draw_markers, LevelMarker
 | 
				
			||||||
from ._anchors import (
 | 
					from ._anchors import (
 | 
				
			||||||
    marker_right_points,
 | 
					 | 
				
			||||||
    vbr_left,
 | 
					    vbr_left,
 | 
				
			||||||
    right_axis,
 | 
					    right_axis,
 | 
				
			||||||
    gpath_pin,
 | 
					    gpath_pin,
 | 
				
			||||||
| 
						 | 
					@ -333,7 +332,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
        vb_left, vb_right = self._endPoints
 | 
					        vb_left, vb_right = self._endPoints
 | 
				
			||||||
        vb = self.getViewBox()
 | 
					        vb = self.getViewBox()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        line_end, marker_right, r_axis_x = marker_right_points(self._chart)
 | 
					        line_end, marker_right, r_axis_x = self._chart.marker_right_points()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.show_markers and self.markers:
 | 
					        if self.show_markers and self.markers:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -399,7 +398,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
    def scene_endpoint(self) -> QPointF:
 | 
					    def scene_endpoint(self) -> QPointF:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not self._right_end_sc:
 | 
					        if not self._right_end_sc:
 | 
				
			||||||
            line_end, _, _ = marker_right_points(self._chart)
 | 
					            line_end, _, _ = self._chart.marker_right_points()
 | 
				
			||||||
            self._right_end_sc = line_end - 10
 | 
					            self._right_end_sc = line_end - 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return QPointF(self._right_end_sc, self.scene_y())
 | 
					        return QPointF(self._right_end_sc, self.scene_y())
 | 
				
			||||||
| 
						 | 
					@ -417,7 +416,7 @@ class LevelLine(pg.InfiniteLine):
 | 
				
			||||||
        self.getViewBox().scene().addItem(path)
 | 
					        self.getViewBox().scene().addItem(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # place to just-left of L1 labels
 | 
					        # place to just-left of L1 labels
 | 
				
			||||||
        rsc = self._chart.pre_l1_x()[0]
 | 
					        rsc = self._chart.pre_l1_xs()[0]
 | 
				
			||||||
        path.setPos(QPointF(rsc, self.scene_y()))
 | 
					        path.setPos(QPointF(rsc, self.scene_y()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return path
 | 
					        return path
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue