|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | 5 | import math |
6 | | -from typing import TYPE_CHECKING |
| 6 | +from contextlib import contextmanager |
| 7 | +from typing import TYPE_CHECKING, Generator |
7 | 8 |
|
8 | 9 | from guidata.dataset import update_dataset |
9 | 10 | from guidata.utils.misc import assert_interfaces_valid |
|
28 | 29 | from plotpy.styles.base import ItemParameters |
29 | 30 |
|
30 | 31 |
|
| 32 | +@contextmanager |
| 33 | +def no_symbol_context( |
| 34 | + item: QwtPlotMarker, condition: bool |
| 35 | +) -> Generator[None, None, None]: |
| 36 | + """Context manager for temporarily changing a marker's symbol |
| 37 | +
|
| 38 | + Args: |
| 39 | + item: The marker object whose symbol might be changed |
| 40 | + condition: If True, the symbol will be changed to None temporarily |
| 41 | + """ |
| 42 | + old_symbol = None |
| 43 | + if condition: |
| 44 | + old_symbol = item.symbol() |
| 45 | + item.setSymbol(None) |
| 46 | + try: |
| 47 | + yield |
| 48 | + finally: |
| 49 | + if condition and old_symbol is not None: |
| 50 | + item.setSymbol(old_symbol) |
| 51 | + |
| 52 | + |
31 | 53 | class Marker(QwtPlotMarker): |
32 | 54 | """Marker shape |
33 | 55 |
|
@@ -137,7 +159,8 @@ def draw( |
137 | 159 | x, y = self.center_handle(self.xValue(), self.yValue()) |
138 | 160 | self.setValue(x, y) |
139 | 161 | self.update_label() |
140 | | - QwtPlotMarker.draw(self, painter, xMap, yMap, canvasRect) |
| 162 | + with no_symbol_context(self, not self.can_resize()): |
| 163 | + QwtPlotMarker.draw(self, painter, xMap, yMap, canvasRect) |
141 | 164 |
|
142 | 165 | # ------IBasePlotItem API---------------------------------------------------- |
143 | 166 | def get_icon_name(self) -> str: |
@@ -180,6 +203,14 @@ def set_movable(self, state: bool) -> None: |
180 | 203 | state: True if item is movable, False otherwise |
181 | 204 | """ |
182 | 205 | self._can_move = state |
| 206 | + # For a marker, setting the movable state to False means that, obviously, |
| 207 | + # it cannot be moved. However, due to the way the event system works, |
| 208 | + # the marker can still be moved by the user: it has to be not resizable |
| 209 | + # to prevent the user from moving it by dragging the handles, which is not |
| 210 | + # intuitive for a marker (from a user point of view, a marker is a point |
| 211 | + # or a line, not a shape with handles). |
| 212 | + # So, we set the resizable state to the same value as the movable state: |
| 213 | + self.set_resizable(state) |
183 | 214 |
|
184 | 215 | def set_rotatable(self, state: bool) -> None: |
185 | 216 | """Set item rotatable state |
|
0 commit comments