🟢 .gitignore
🛠️ piker/ui/_axes.py -> Enhance axis font and size handling 🛠️ piker/ui/_window.py -> Improve zoom key detection and event handling 🛠️ piker/ui/_window.py -> Update axes fonts and layout after zoom eventsmacos_fixes_2025
							parent
							
								
									ed3a8d81b1
								
							
						
					
					
						commit
						cd15f2ae76
					
				|  | @ -103,3 +103,4 @@ ENV/ | |||
| # mypy | ||||
| .mypy_cache/ | ||||
| .vscode/settings.json | ||||
| **/.DS_Store | ||||
|  |  | |||
|  | @ -75,6 +75,9 @@ class Axis(pg.AxisItem): | |||
|         self.pi = plotitem | ||||
|         self._dpi_font = _font | ||||
| 
 | ||||
|         # store for later recalculation on zoom | ||||
|         self._typical_max_str = typical_max_str | ||||
| 
 | ||||
|         self.setTickFont(_font.font) | ||||
|         font_size = self._dpi_font.font.pixelSize() | ||||
| 
 | ||||
|  | @ -156,6 +159,41 @@ class Axis(pg.AxisItem): | |||
|     def size_to_values(self) -> None: | ||||
|         pass | ||||
| 
 | ||||
|     def update_fonts(self, font: DpiAwareFont) -> None: | ||||
|         '''Update font and recalculate axis sizing after zoom change.''' | ||||
|         # IMPORTANT: tell Qt we're about to change geometry | ||||
|         self.prepareGeometryChange() | ||||
| 
 | ||||
|         self._dpi_font = font | ||||
|         self.setTickFont(font.font) | ||||
|         font_size = font.font.pixelSize() | ||||
| 
 | ||||
|         # recalculate text offset based on new font size | ||||
|         text_offset = None | ||||
|         if self.orientation in ('bottom',): | ||||
|             text_offset = floor(0.25 * font_size) | ||||
|         elif self.orientation in ('left', 'right'): | ||||
|             text_offset = floor(font_size / 2) | ||||
| 
 | ||||
|         if text_offset: | ||||
|             self.setStyle(tickTextOffset=text_offset) | ||||
| 
 | ||||
|         # recalculate bounding rect with new font | ||||
|         # Note: typical_max_str should be stored from init | ||||
|         if not hasattr(self, '_typical_max_str'): | ||||
|             self._typical_max_str = '100 000.000  '  # fallback default | ||||
|         self.typical_br = font._qfm.boundingRect(self._typical_max_str) | ||||
| 
 | ||||
|         # Update PyQtGraph's internal text size tracking | ||||
|         # This is critical - PyQtGraph uses these internally for auto-expand | ||||
|         if self.orientation in ['left', 'right']: | ||||
|             self.textWidth = self.typical_br.width() | ||||
|         else: | ||||
|             self.textHeight = self.typical_br.height() | ||||
| 
 | ||||
|         # resize axis to fit new font - this triggers PyQtGraph's auto-expand | ||||
|         self.size_to_values() | ||||
| 
 | ||||
|     def txt_offsets(self) -> tuple[int, int]: | ||||
|         return tuple(self.style['tickTextOffset']) | ||||
| 
 | ||||
|  | @ -256,7 +294,14 @@ class PriceAxis(Axis): | |||
|         self._min_tick = size | ||||
| 
 | ||||
|     def size_to_values(self) -> None: | ||||
|         self.setWidth(self.typical_br.width()) | ||||
|         # Call PyQtGraph's internal width update mechanism | ||||
|         # This respects autoExpandTextSpace and updates min/max constraints | ||||
|         self._updateWidth() | ||||
|         # tell Qt our preferred size changed so layout recalculates | ||||
|         self.updateGeometry() | ||||
|         # force parent plot item to recalculate its layout | ||||
|         if self.pi and hasattr(self.pi, 'updateGeometry'): | ||||
|             self.pi.updateGeometry() | ||||
| 
 | ||||
|     # XXX: drop for now since it just eats up h space | ||||
| 
 | ||||
|  | @ -300,7 +345,14 @@ class DynamicDateAxis(Axis): | |||
|     } | ||||
| 
 | ||||
|     def size_to_values(self) -> None: | ||||
|         self.setHeight(self.typical_br.height() + 1) | ||||
|         # Call PyQtGraph's internal height update mechanism | ||||
|         # This respects autoExpandTextSpace and updates min/max constraints | ||||
|         self._updateHeight() | ||||
|         # tell Qt our preferred size changed so layout recalculates | ||||
|         self.updateGeometry() | ||||
|         # force parent plot item to recalculate its layout | ||||
|         if self.pi and hasattr(self.pi, 'updateGeometry'): | ||||
|             self.pi.updateGeometry() | ||||
| 
 | ||||
|     def _indexes_to_timestrs( | ||||
|         self, | ||||
|  |  | |||
|  | @ -77,14 +77,19 @@ class GlobalZoomEventFilter(QObject): | |||
|             key = event.key() | ||||
|             mods = event.modifiers() | ||||
| 
 | ||||
|             # Check for Ctrl+Shift modifier combination | ||||
|             has_ctrl_shift = ( | ||||
|                 (mods & Qt.KeyboardModifier.ControlModifier) and | ||||
|                 (mods & Qt.KeyboardModifier.ShiftModifier) | ||||
|             ) | ||||
|             # Mask out the KeypadModifier which Qt sometimes adds | ||||
|             mods = mods & ~Qt.KeyboardModifier.KeypadModifier | ||||
| 
 | ||||
|             if has_ctrl_shift: | ||||
|                 # Zoom in: Ctrl+Shift+Plus or Ctrl+Shift+Equal | ||||
|             # Check if we have Ctrl+Shift (both required) | ||||
|             has_ctrl = bool(mods & Qt.KeyboardModifier.ControlModifier) | ||||
|             has_shift = bool(mods & Qt.KeyboardModifier.ShiftModifier) | ||||
| 
 | ||||
|             # Only handle UI zoom if BOTH Ctrl and Shift are pressed | ||||
|             # For Plus key: user presses Cmd+Shift+Equal (which makes Plus) | ||||
|             # For Minus key: user presses Cmd+Shift+Minus | ||||
|             if has_ctrl and has_shift: | ||||
|                 # Zoom in: Ctrl+Shift+Plus | ||||
|                 # Note: Plus key usually comes as Key_Equal with Shift modifier | ||||
|                 if key in (Qt.Key.Key_Plus, Qt.Key.Key_Equal): | ||||
|                     self.main_window.zoom_in() | ||||
|                     return True  # consume event | ||||
|  | @ -99,7 +104,10 @@ class GlobalZoomEventFilter(QObject): | |||
|                     self.main_window.reset_zoom() | ||||
|                     return True  # consume event | ||||
| 
 | ||||
|         # Pass through all other events | ||||
|             # Pass through if only Ctrl (no Shift) - this goes to chart zoom | ||||
|             # Pass through all other events too | ||||
|             return False | ||||
| 
 | ||||
|         return False | ||||
| 
 | ||||
| 
 | ||||
|  | @ -481,16 +489,25 @@ class MainWindow(QMainWindow): | |||
| 
 | ||||
|             # get main chart | ||||
|             chart = getattr(splits, 'chart', None) | ||||
|             if chart and hasattr(chart, 'view'): | ||||
|                 view = chart.view | ||||
|                 if hasattr(view, 'order_mode') and view.order_mode: | ||||
|                     order_mode = view.order_mode | ||||
|                     if hasattr(order_mode, 'pane') and order_mode.pane: | ||||
|                         order_mode.pane.update_fonts() | ||||
|             if chart: | ||||
|                 # update axes | ||||
|                 self._update_chart_axes(chart) | ||||
| 
 | ||||
|                 # update order pane | ||||
|                 if hasattr(chart, 'view'): | ||||
|                     view = chart.view | ||||
|                     if hasattr(view, 'order_mode') and view.order_mode: | ||||
|                         order_mode = view.order_mode | ||||
|                         if hasattr(order_mode, 'pane') and order_mode.pane: | ||||
|                             order_mode.pane.update_fonts() | ||||
| 
 | ||||
|             # also check subplots | ||||
|             subplots = getattr(splits, 'subplots', {}) | ||||
|             for name, subplot_chart in subplots.items(): | ||||
|                 # update subplot axes | ||||
|                 self._update_chart_axes(subplot_chart) | ||||
| 
 | ||||
|                 # update subplot order pane | ||||
|                 if hasattr(subplot_chart, 'view'): | ||||
|                     subplot_view = subplot_chart.view | ||||
|                     if hasattr(subplot_view, 'order_mode') and subplot_view.order_mode: | ||||
|  | @ -498,6 +515,35 @@ class MainWindow(QMainWindow): | |||
|                         if hasattr(subplot_order_mode, 'pane') and subplot_order_mode.pane: | ||||
|                             subplot_order_mode.pane.update_fonts() | ||||
| 
 | ||||
|             # resize all sidepanes to match main chart's sidepane width | ||||
|             # this ensures volume/subplot sidepanes match the main chart | ||||
|             if splits and hasattr(splits, 'resize_sidepanes'): | ||||
|                 splits.resize_sidepanes() | ||||
| 
 | ||||
|     def _update_chart_axes(self, chart) -> None: | ||||
|         '''Update axis fonts and sizing for a chart.''' | ||||
|         from . import _style | ||||
| 
 | ||||
|         # update price axis (right side) | ||||
|         if hasattr(chart, 'pi') and chart.pi: | ||||
|             plot_item = chart.pi | ||||
|             # get all axes from plot item | ||||
|             for axis_name in ['left', 'right', 'bottom', 'top']: | ||||
|                 axis = plot_item.getAxis(axis_name) | ||||
|                 if axis and hasattr(axis, 'update_fonts'): | ||||
|                     axis.update_fonts(_style._font) | ||||
| 
 | ||||
|             # force plot item to recalculate its entire layout | ||||
|             plot_item.updateGeometry() | ||||
| 
 | ||||
|             # force chart widget to update | ||||
|             if hasattr(chart, 'updateGeometry'): | ||||
|                 chart.updateGeometry() | ||||
| 
 | ||||
|             # trigger a full scene update | ||||
|             if hasattr(chart, 'update'): | ||||
|                 chart.update() | ||||
| 
 | ||||
|     def _refresh_widget_fonts(self, widget: QWidget) -> None: | ||||
|         ''' | ||||
|         Recursively update font sizes in all child widgets. | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue