Skip to content

Commit eae35f7

Browse files
committed
Enhance marker item behavior: add context manager for symbol management and synchronize movable/resizable states
1 parent 43762ab commit eae35f7

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
* Edit tools (Edit data, center image position):
3838
* Exclude read-only items from the list of editable items
3939
* It is no longer possible to use those tools on read-only items
40+
* Marker items (markers, cursors):
41+
* Setting item movable state now also sets the resizable state:
42+
* The PlotPy event system won't prevent the user from moving the item by dragging the handles if the item is just not movable: it has to be not resizable, which is not intuitive.
43+
* This is now fixed
4044

4145
Other changes:
4246

plotpy/items/shape/marker.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from __future__ import annotations
44

55
import math
6-
from typing import TYPE_CHECKING
6+
from contextlib import contextmanager
7+
from typing import TYPE_CHECKING, Generator
78

89
from guidata.dataset import update_dataset
910
from guidata.utils.misc import assert_interfaces_valid
@@ -28,6 +29,27 @@
2829
from plotpy.styles.base import ItemParameters
2930

3031

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+
3153
class Marker(QwtPlotMarker):
3254
"""Marker shape
3355
@@ -137,7 +159,8 @@ def draw(
137159
x, y = self.center_handle(self.xValue(), self.yValue())
138160
self.setValue(x, y)
139161
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)
141164

142165
# ------IBasePlotItem API----------------------------------------------------
143166
def get_icon_name(self) -> str:
@@ -180,6 +203,14 @@ def set_movable(self, state: bool) -> None:
180203
state: True if item is movable, False otherwise
181204
"""
182205
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)
183214

184215
def set_rotatable(self, state: bool) -> None:
185216
"""Set item rotatable state

0 commit comments

Comments
 (0)