From 56c163cdd786ace50082b99c1af829618cea1350 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Sun, 20 Mar 2022 12:53:44 -0400 Subject: [PATCH] Make `ChartPlotWidget.default_view()` pin to L1 Instead of using a guess about how many x-indexes to reset the last datum in-view to, calculate and shift the latest index such that it's just before any L1 spread labels on the y-axis. This makes the view placement "widget aware" and gives a much more cross-display UX. Summary: - add `ChartPlotWidget.pre_l1_x()` which returns a `tuple` of x view-coord points for the absolute x-pos and length of any L1 line/labels - make `.default_view()` only shift to see the xlast just outside the l1 but keep whatever view range xfirst as the first datum in view - drop `LevelLine.right_point()` since this is now just a `.pre_l1_x()` call and can be retrieved from the line's internal chart ref - drop `._style.bars_from/to_..` vars since we aren't using hard coded offsets any more --- piker/ui/_anchors.py | 1 - piker/ui/_chart.py | 52 ++++++++++++++++++++++++++++++++++---------- piker/ui/_lines.py | 40 ++++++++++++---------------------- piker/ui/_style.py | 7 +++--- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/piker/ui/_anchors.py b/piker/ui/_anchors.py index e7b6d72b..2d4345e2 100644 --- a/piker/ui/_anchors.py +++ b/piker/ui/_anchors.py @@ -25,7 +25,6 @@ from PyQt5.QtCore import QPointF from PyQt5.QtWidgets import QGraphicsPathItem if TYPE_CHECKING: - from ._axes import PriceAxis from ._chart import ChartPlotWidget from ._label import Label diff --git a/piker/ui/_chart.py b/piker/ui/_chart.py index 553583d4..705e3c84 100644 --- a/piker/ui/_chart.py +++ b/piker/ui/_chart.py @@ -25,7 +25,7 @@ from PyQt5 import QtCore, QtWidgets from PyQt5.QtCore import ( Qt, QLineF, - QPointF, + # QPointF, ) from PyQt5.QtWidgets import ( QFrame, @@ -56,8 +56,6 @@ from ._style import ( CHART_MARGINS, _xaxis_at, _min_points_to_show, - _bars_from_right_in_follow_mode, - _bars_to_left_in_follow_mode, ) from ..data.feed import Feed from ..data._source import Symbol @@ -846,29 +844,62 @@ class ChartPlotWidget(pg.PlotWidget): QLineF(lbar, 0, rbar, 0) ).length() - def default_view( + def pre_l1_x( self, - index: int = -1, + view_coords: bool = False, - ) -> None: + ) -> tuple[float, float]: + ''' + Return the scene x-coord for the value just before + the L1 labels on the y-axis as well as the length + of that L1 label from the y-axis. + + ''' + l1_len = self._max_l1_line_len + 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 + line = view.mapToView( + QLineF(up_to_l1_sc, 0, ryaxis_x, 0) + ) + return line.x1(), line.length() + + def default_view(self) -> None: ''' Set the view box to the "default" startup view of the scene. ''' try: - xlast = self._arrays[self.name][index]['index'] + index = self._arrays[self.name]['index'] except IndexError: log.warning(f'array for {self.name} not loaded yet?') return - begin = xlast - 1000 - end = xlast + _bars_from_right_in_follow_mode + xfirst, xlast = index[0], index[-1] + view = self.view + 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) + + # print( + # f'view range: {vr}\n' + # f'xlast: {xlast}\n' + # f'marker pos: {marker_pos}\n' + # f'l1 len: {l1_len}\n' + # f'begin: {begin}\n' + # f'end: {end}\n' + # ) # remove any custom user yrange setttings if self._static_yrange == 'axis': self._static_yrange = None - view = self.view view.setXRange( min=begin, max=end, @@ -1228,7 +1259,6 @@ class ChartPlotWidget(pg.PlotWidget): ifirst = array[0]['index'] # slice data by offset from the first index # available in the passed datum set. - start = lbar - ifirst return array[lbar - ifirst:(rbar - ifirst) + 1] def maxmin( diff --git a/piker/ui/_lines.py b/piker/ui/_lines.py index d148049e..df29e350 100644 --- a/piker/ui/_lines.py +++ b/piker/ui/_lines.py @@ -20,7 +20,7 @@ Lines for orders, alerts, L2. """ from functools import partial from math import floor -from typing import Tuple, Optional, List, Callable +from typing import Optional, Callable import pyqtgraph as pg from pyqtgraph import Point, functions as fn @@ -32,7 +32,6 @@ from ._anchors import ( marker_right_points, vbr_left, right_axis, - # pp_tight_and_right, # wanna keep it straight in the long run gpath_pin, ) from ..calc import humanize @@ -104,8 +103,8 @@ class LevelLine(pg.InfiniteLine): # list of labels anchored at one of the 2 line endpoints # inside the viewbox - self._labels: List[Label] = [] - self._markers: List[(int, Label)] = [] + self._labels: list[Label] = [] + self._markers: list[(int, Label)] = [] # whenever this line is moved trigger label updates self.sigPositionChanged.connect(self.on_pos_change) @@ -124,7 +123,7 @@ class LevelLine(pg.InfiniteLine): self._y_incr_mult = 1 / chart.linked.symbol.tick_size self._right_end_sc: float = 0 - def txt_offsets(self) -> Tuple[int, int]: + def txt_offsets(self) -> tuple[int, int]: return 0, 0 @property @@ -315,17 +314,6 @@ class LevelLine(pg.InfiniteLine): # TODO: enter labels edit mode print(f'double click {ev}') - def right_point( - self, - ) -> float: - - chart = self._chart - l1_len = chart._max_l1_line_len - ryaxis = chart.getAxis('right') - up_to_l1_sc = ryaxis.pos().x() - l1_len - - return up_to_l1_sc - def paint( self, @@ -422,23 +410,23 @@ class LevelLine(pg.InfiniteLine): ) -> QtWidgets.QGraphicsPathItem: + self._marker = path + self._marker.setPen(self.currentPen) + self._marker.setBrush(fn.mkBrush(self.currentPen.color())) # add path to scene self.getViewBox().scene().addItem(path) - self._marker = path - - rsc = self.right_point() - - self._marker.setPen(self.currentPen) - self._marker.setBrush(fn.mkBrush(self.currentPen.color())) + # place to just-left of L1 labels + rsc = self._chart.pre_l1_x()[0] path.setPos(QPointF(rsc, self.scene_y())) return path def hoverEvent(self, ev): - """Mouse hover callback. + ''' + Mouse hover callback. - """ + ''' cur = self._chart.linked.cursor # hovered @@ -614,7 +602,8 @@ def order_line( **line_kwargs, ) -> LevelLine: - '''Convenience routine to add a line graphic representing an order + ''' + Convenience routine to add a line graphic representing an order execution submitted to the EMS via the chart's "order mode". ''' @@ -689,7 +678,6 @@ def order_line( return f'{account}: ' - label.fields = { 'size': size, 'size_digits': 0, diff --git a/piker/ui/_style.py b/piker/ui/_style.py index c60cb077..22731093 100644 --- a/piker/ui/_style.py +++ b/piker/ui/_style.py @@ -14,9 +14,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -""" +''' Qt UI styling. -""" + +''' from typing import Optional, Dict import math @@ -202,8 +203,6 @@ _xaxis_at = 'bottom' # charting config CHART_MARGINS = (0, 0, 2, 2) _min_points_to_show = 6 -_bars_to_left_in_follow_mode = int(61*6) -_bars_from_right_in_follow_mode = round(0.16 * _bars_to_left_in_follow_mode) _tina_mode = False