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.
history_view
Tyler Goodlet 2022-09-13 17:46:50 -04:00
parent 44c6f6dfda
commit e492e9ca0c
3 changed files with 58 additions and 14 deletions

View File

@ -208,15 +208,15 @@ class GodWidget(QWidget):
if not self.vbox.isEmpty(): if not self.vbox.isEmpty():
qframe = self.hist_linked.chart.qframe # XXX: seems to make switching slower?
if qframe.sidepane is self.search: # qframe = self.hist_linked.chart.qframe
qframe.hbox.removeWidget(self.search) # if qframe.sidepane is self.search:
# qframe.hbox.removeWidget(self.search)
for linked in [self.rt_linked, self.hist_linked]: for linked in [self.rt_linked, self.hist_linked]:
# XXX: this is CRITICAL especially with pixel buffer caching # XXX: this is CRITICAL especially with pixel buffer caching
linked.hide() linked.hide()
linked.unfocus() linked.unfocus()
# self.hist_linked.unfocus()
# XXX: pretty sure we don't need this # XXX: pretty sure we don't need this
# remove any existing plots? # remove any existing plots?
@ -271,12 +271,8 @@ class GodWidget(QWidget):
linked.graphics_cycle() linked.graphics_cycle()
await trio.sleep(0) 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 # resume feeds *after* rendering chart view asap
chart = linked.chart
if chart: if chart:
chart.resume_all_feeds() chart.resume_all_feeds()
@ -284,7 +280,7 @@ class GodWidget(QWidget):
# last had the xlast in view, if so then shift so it's # last had the xlast in view, if so then shift so it's
# still in view, if the user was viewing history then # still in view, if the user was viewing history then
# do nothing yah? # do nothing yah?
chart.default_view() # chart.default_view()
# if a history chart instance is already up then # if a history chart instance is already up then
# set the search widget as its sidepane. # set the search widget as its sidepane.
@ -292,6 +288,15 @@ class GodWidget(QWidget):
if hist_chart: if hist_chart:
hist_chart.qframe.set_sidepane(self.search) 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 # set window titlebar info
symbol = self.rt_linked.symbol symbol = self.rt_linked.symbol
if symbol is not None: if symbol is not None:

View File

@ -55,7 +55,10 @@ from ._forms import (
FieldsForm, FieldsForm,
mk_order_pane_layout, mk_order_pane_layout,
) )
from .order_mode import open_order_mode from .order_mode import (
open_order_mode,
OrderMode,
)
from .._profile import ( from .._profile import (
pg_profile_enabled, pg_profile_enabled,
ms_slower_then, ms_slower_then,
@ -1031,18 +1034,21 @@ async def display_symbol_data(
godwidget.resize_all() godwidget.resize_all()
mode: OrderMode
async with ( async with (
open_order_mode( open_order_mode(
feed, feed,
godwidget, godwidget,
fqsn, fqsn,
order_mode_started order_mode_started
) ) as mode
): ):
if not vlm_chart: if not vlm_chart:
# trigger another view reset if no sub-chart # trigger another view reset if no sub-chart
chart.default_view() chart.default_view()
rt_linked.mode = mode
# let Qt run to render all widgets and make sure the # let Qt run to render all widgets and make sure the
# sidepanes line up vertically. # sidepanes line up vertically.
await trio.sleep(0) await trio.sleep(0)

View File

@ -405,7 +405,7 @@ class SettingsPane:
self.pnl_label.format(pnl=pnl_value) self.pnl_label.format(pnl=pnl_value)
def position_line( def pp_line(
chart: ChartPlotWidget, # noqa chart: ChartPlotWidget, # noqa
size: float, size: float,
@ -461,6 +461,9 @@ def position_line(
marker.update() marker.update()
marker.show() marker.show()
line._marker = marker
line.track_marker_pos = True
# show position marker on view "edge" when out of view # show position marker on view "edge" when out of view
vb = line.getViewBox() vb = line.getViewBox()
vb.sigRangeChanged.connect(marker.position_in_view) vb.sigRangeChanged.connect(marker.position_in_view)
@ -548,7 +551,7 @@ class Nav(Struct):
# create and show a pp line if none yet exists # create and show a pp line if none yet exists
if line is None: if line is None:
arrow = self.level_markers[key] arrow = self.level_markers[key]
line = position_line( line = pp_line(
chart=chart, chart=chart,
level=price, level=price,
size=size, size=size,
@ -634,6 +637,18 @@ class Nav(Struct):
# labels # labels
level_marker.show() 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() pp_label.show()
size_label.show() size_label.show()
@ -767,6 +782,24 @@ class PositionTracker:
level=nav.level, level=nav.level,
on_paint=nav.update_graphics, 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 arrow.hide() # never show on startup
view.scene().addItem(arrow) view.scene().addItem(arrow)
nav.level_markers[key] = arrow nav.level_markers[key] = arrow