From e492e9ca0c2b35f1fc3b9c0fda795bd2526ca7cd Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 13 Sep 2022 17:46:50 -0400 Subject: [PATCH] Fix pp arrow/label placement bugs - Every time a symbol is switched on chart we need to wait until the search bar sidepane has been added beside the slow chart before determining the offset for the pp line's arrow/labels; trigger this in `GodWidget.load_symbol()` -> required monkeypatching on a `.mode: OrderMode` to the `.rt_linked` for now.. - Drop the search pane widget removal from the current linked chart, seems faster? - On the slow chart override the `LevelMarker.scene_x()` callback to adjust for the case where no L1 labels are shown beside the y-axis. --- piker/ui/_chart.py | 25 +++++++++++++++---------- piker/ui/_display.py | 10 ++++++++-- piker/ui/_position.py | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/piker/ui/_chart.py b/piker/ui/_chart.py index eb76112f..8f2718ca 100644 --- a/piker/ui/_chart.py +++ b/piker/ui/_chart.py @@ -208,15 +208,15 @@ class GodWidget(QWidget): if not self.vbox.isEmpty(): - qframe = self.hist_linked.chart.qframe - if qframe.sidepane is self.search: - qframe.hbox.removeWidget(self.search) + # XXX: seems to make switching slower? + # qframe = self.hist_linked.chart.qframe + # if qframe.sidepane is self.search: + # qframe.hbox.removeWidget(self.search) for linked in [self.rt_linked, self.hist_linked]: # XXX: this is CRITICAL especially with pixel buffer caching linked.hide() linked.unfocus() - # self.hist_linked.unfocus() # XXX: pretty sure we don't need this # remove any existing plots? @@ -271,12 +271,8 @@ class GodWidget(QWidget): linked.graphics_cycle() await trio.sleep(0) - # XXX: since the pp config is a singleton widget we have to - # also switch it over to the new chart's interal-layout - # linked.chart.qframe.hbox.removeWidget(self.pp_pane) - chart = linked.chart - # resume feeds *after* rendering chart view asap + chart = linked.chart if chart: chart.resume_all_feeds() @@ -284,7 +280,7 @@ class GodWidget(QWidget): # last had the xlast in view, if so then shift so it's # still in view, if the user was viewing history then # do nothing yah? - chart.default_view() + # chart.default_view() # if a history chart instance is already up then # set the search widget as its sidepane. @@ -292,6 +288,15 @@ class GodWidget(QWidget): if hist_chart: hist_chart.qframe.set_sidepane(self.search) + # NOTE: this is really stupid/hard to follow. + # we have to reposition the active position nav + # **AFTER** applying the search bar as a sidepane + # to the newly switched to symbol. + await trio.sleep(0) + pp_nav = self.rt_linked.mode.current_pp.nav + pp_nav.show() + pp_nav.hide_info() + # set window titlebar info symbol = self.rt_linked.symbol if symbol is not None: diff --git a/piker/ui/_display.py b/piker/ui/_display.py index ada76f01..c4891c7e 100644 --- a/piker/ui/_display.py +++ b/piker/ui/_display.py @@ -55,7 +55,10 @@ from ._forms import ( FieldsForm, mk_order_pane_layout, ) -from .order_mode import open_order_mode +from .order_mode import ( + open_order_mode, + OrderMode, +) from .._profile import ( pg_profile_enabled, ms_slower_then, @@ -1031,18 +1034,21 @@ async def display_symbol_data( godwidget.resize_all() + mode: OrderMode async with ( open_order_mode( feed, godwidget, fqsn, order_mode_started - ) + ) as mode ): if not vlm_chart: # trigger another view reset if no sub-chart chart.default_view() + rt_linked.mode = mode + # let Qt run to render all widgets and make sure the # sidepanes line up vertically. await trio.sleep(0) diff --git a/piker/ui/_position.py b/piker/ui/_position.py index 01dcb1ca..9b9976ab 100644 --- a/piker/ui/_position.py +++ b/piker/ui/_position.py @@ -405,7 +405,7 @@ class SettingsPane: self.pnl_label.format(pnl=pnl_value) -def position_line( +def pp_line( chart: ChartPlotWidget, # noqa size: float, @@ -461,6 +461,9 @@ def position_line( marker.update() marker.show() + line._marker = marker + line.track_marker_pos = True + # show position marker on view "edge" when out of view vb = line.getViewBox() vb.sigRangeChanged.connect(marker.position_in_view) @@ -548,7 +551,7 @@ class Nav(Struct): # create and show a pp line if none yet exists if line is None: arrow = self.level_markers[key] - line = position_line( + line = pp_line( chart=chart, level=price, size=size, @@ -634,6 +637,18 @@ class Nav(Struct): # labels level_marker.show() + + # NOTE: be sure to re-trigger arrow/label placement in case + # a new sidepane or other widget (like the search bar) was + # dynamically swapped into the chart-row-widget-space in + # which case we want to reposition in the view but including + # the new x-distance added by that sidepane. See details in + # ``LevelMarker.position_in_view()`` but more less ``. + # ``ChartPlotWidget.self.marker_right_points()`` gets called + # which itself eventually calls `.getAxis.pos().x()` and + # it's THIS that needs to be called **AFTER** the sidepane + # has been added.. + level_marker.position_in_view() pp_label.show() size_label.show() @@ -767,6 +782,24 @@ class PositionTracker: level=nav.level, on_paint=nav.update_graphics, ) + + # TODO: we really need some kinda "spacing" manager for all + # this stuff... + def offset_from_yaxis() -> float: + ''' + If no L1 labels are present beside the x-axis place + the line label offset from the y-axis just enough to avoid + label overlap with any sticky labels. + + ''' + x = chart.marker_right_points()[1] + if chart._max_l1_line_len == 0: + mkw = pp_label.txt.boundingRect().width() + x -= 1.5 * mkw + + return x + + arrow.scene_x = offset_from_yaxis arrow.hide() # never show on startup view.scene().addItem(arrow) nav.level_markers[key] = arrow