diff options
Diffstat (limited to 'silx/gui/plot/items/roi.py')
-rw-r--r-- | silx/gui/plot/items/roi.py | 200 |
1 files changed, 121 insertions, 79 deletions
diff --git a/silx/gui/plot/items/roi.py b/silx/gui/plot/items/roi.py index 65831be..dcad943 100644 --- a/silx/gui/plot/items/roi.py +++ b/silx/gui/plot/items/roi.py @@ -1,7 +1,7 @@ # coding: utf-8 # /*########################################################################## # -# Copyright (c) 2018 European Synchrotron Radiation Facility +# Copyright (c) 2018-2019 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -40,12 +40,51 @@ from ....utils.weakref import WeakList from ... import qt from .. import items from ...colors import rgba +import silx.utils.deprecation +from silx.utils.proxy import docstring logger = logging.getLogger(__name__) -class RegionOfInterest(qt.QObject): +class _RegionOfInterestBase(qt.QObject): + """Base class of 1D and 2D region of interest + + :param QObject parent: See QObject + :param str name: The name of the ROI + """ + + sigItemChanged = qt.Signal(object) + """Signal emitted when item has changed. + + It provides a flag describing which property of the item has changed. + See :class:`ItemChangedType` for flags description. + """ + + def __init__(self, parent=None, name=''): + qt.QObject.__init__(self) + self.__name = str(name) + + def getName(self): + """Returns the name of the ROI + + :return: name of the region of interest + :rtype: str + """ + return self.__name + + def setName(self, name): + """Set the name of the ROI + + :param str name: name of the region of interest + """ + name = str(name) + if self.__name != name: + self.__name = name + self.sigItemChanged.emit(items.ItemChangedType.NAME) + + +class RegionOfInterest(_RegionOfInterestBase): """Object describing a region of interest in a plot. :param QObject parent: @@ -55,7 +94,7 @@ class RegionOfInterest(qt.QObject): _kind = None """Label for this kind of ROI. - Should be setted by inherited classes to custom the ROI manager widget. + Should be set by inherited classes to custom the ROI manager widget. """ sigRegionChanged = qt.Signal() @@ -65,15 +104,20 @@ class RegionOfInterest(qt.QObject): # Avoid circular dependancy from ..tools import roi as roi_tools assert parent is None or isinstance(parent, roi_tools.RegionOfInterestManager) - qt.QObject.__init__(self, parent) + _RegionOfInterestBase.__init__(self, parent, '') self._color = rgba('red') self._items = WeakList() self._editAnchors = WeakList() self._points = None - self._label = '' self._labelItem = None self._editable = False self._visible = True + self.sigItemChanged.connect(self.__itemChanged) + + def __itemChanged(self, event): + """Handle name change""" + if event == items.ItemChangedType.NAME: + self._updateLabelItem(self.getName()) def __del__(self): # Clean-up plot items @@ -140,22 +184,27 @@ class RegionOfInterest(qt.QObject): if isinstance(item, items.ColorMixIn): item.setColor(rgbaColor) + self.sigItemChanged.emit(items.ItemChangedType.COLOR) + + @silx.utils.deprecation.deprecated(reason='API modification', + replacement='getName()', + since_version=0.12) def getLabel(self): """Returns the label displayed for this ROI. :rtype: str """ - return self._label + return self.getName() + @silx.utils.deprecation.deprecated(reason='API modification', + replacement='setName(name)', + since_version=0.12) def setLabel(self, label): """Set the label displayed with this ROI. :param str label: The text label to display """ - label = str(label) - if label != self._label: - self._label = label - self._updateLabelItem(label) + self.setName(name=label) def isEditable(self): """Returns whether the ROI is editable by the user or not. @@ -176,6 +225,7 @@ class RegionOfInterest(qt.QObject): # Recreate plot items # This can be avoided once marker.setDraggable is public self._createPlotItems() + self.sigItemChanged.emit(items.ItemChangedType.EDITABLE) def isVisible(self): """Returns whether the ROI is visible in the plot. @@ -197,13 +247,13 @@ class RegionOfInterest(qt.QObject): hide it. """ visible = bool(visible) - if self._visible == visible: - return - self._visible = visible - if self._labelItem is not None: - self._labelItem.setVisible(visible) - for item in self._items + self._editAnchors: - item.setVisible(visible) + if self._visible != visible: + self._visible = visible + if self._labelItem is not None: + self._labelItem.setVisible(visible) + for item in self._items + self._editAnchors: + item.setVisible(visible) + self.sigItemChanged.emit(items.ItemChangedType.VISIBLE) def _getControlPoints(self): """Returns the current ROI control points. @@ -371,7 +421,7 @@ class RegionOfInterest(qt.QObject): markerPos = self._getLabelPosition() marker = items.Marker() marker.setPosition(*markerPos) - marker.setText(self.getLabel()) + marker.setText(self.getName()) marker.setColor(rgba(self.getColor())) marker.setSymbol('') marker._setDraggable(False) @@ -465,6 +515,12 @@ class PointROI(RegionOfInterest, items.SymbolMixIn): _plotShape = "point" """Plot shape which is used for the first interaction""" + _DEFAULT_SYMBOL = '+' + """Default symbol of the PointROI + + It overwrite the `SymbolMixIn` class attribte. + """ + def __init__(self, parent=None): items.SymbolMixIn.__init__(self) RegionOfInterest.__init__(self, parent=parent) @@ -488,31 +544,31 @@ class PointROI(RegionOfInterest, items.SymbolMixIn): return None def _updateLabelItem(self, label): - if self.isEditable(): - item = self._editAnchors[0] - else: + self._items[0].setText(label) + + def _updateShape(self): + if len(self._items) > 0: + controlPoints = self._getControlPoints() item = self._items[0] - item.setText(label) + item.setPosition(*controlPoints[0]) + + def __positionChanged(self, event): + """Handle position changed events of the marker""" + if event is items.ItemChangedType.POSITION: + marker = self.sender() + if isinstance(marker, items.Marker): + self.setPosition(marker.getPosition()) def _createShapeItems(self, points): - if self.isEditable(): - return [] marker = items.Marker() marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) - marker.setColor(rgba(self.getColor())) + marker.setText(self.getName()) marker.setSymbol(self.getSymbol()) marker.setSymbolSize(self.getSymbolSize()) - marker._setDraggable(False) - return [marker] - - def _createAnchorItems(self, points): - marker = items.Marker() - marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) + marker.setColor(rgba(self.getColor())) marker._setDraggable(self.isEditable()) - marker.setSymbol(self.getSymbol()) - marker.setSymbolSize(self.getSymbolSize()) + if self.isEditable(): + marker.sigItemChanged.connect(self.__positionChanged) return [marker] def __str__(self): @@ -672,38 +728,31 @@ class HorizontalLineROI(RegionOfInterest, items.LineMixIn): return None def _updateLabelItem(self, label): - if self.isEditable(): - item = self._editAnchors[0] - else: - item = self._items[0] - item.setText(label) + self._items[0].setText(label) def _updateShape(self): - if not self.isEditable(): - if len(self._items) > 0: - controlPoints = self._getControlPoints() - item = self._items[0] - item.setPosition(*controlPoints[0]) + if len(self._items) > 0: + controlPoints = self._getControlPoints() + item = self._items[0] + item.setPosition(*controlPoints[0]) + + def __positionChanged(self, event): + """Handle position changed events of the marker""" + if event is items.ItemChangedType.POSITION: + marker = self.sender() + if isinstance(marker, items.YMarker): + self.setPosition(marker.getYPosition()) def _createShapeItems(self, points): - if self.isEditable(): - return [] marker = items.YMarker() marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) + marker.setText(self.getName()) marker.setColor(rgba(self.getColor())) - marker._setDraggable(False) marker.setLineWidth(self.getLineWidth()) marker.setLineStyle(self.getLineStyle()) - return [marker] - - def _createAnchorItems(self, points): - marker = items.YMarker() - marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) marker._setDraggable(self.isEditable()) - marker.setLineWidth(self.getLineWidth()) - marker.setLineStyle(self.getLineStyle()) + if self.isEditable(): + marker.sigItemChanged.connect(self.__positionChanged) return [marker] def __str__(self): @@ -749,38 +798,31 @@ class VerticalLineROI(RegionOfInterest, items.LineMixIn): return None def _updateLabelItem(self, label): - if self.isEditable(): - item = self._editAnchors[0] - else: - item = self._items[0] - item.setText(label) + self._items[0].setText(label) def _updateShape(self): - if not self.isEditable(): - if len(self._items) > 0: - controlPoints = self._getControlPoints() - item = self._items[0] - item.setPosition(*controlPoints[0]) + if len(self._items) > 0: + controlPoints = self._getControlPoints() + item = self._items[0] + item.setPosition(*controlPoints[0]) + + def __positionChanged(self, event): + """Handle position changed events of the marker""" + if event is items.ItemChangedType.POSITION: + marker = self.sender() + if isinstance(marker, items.XMarker): + self.setPosition(marker.getXPosition()) def _createShapeItems(self, points): - if self.isEditable(): - return [] marker = items.XMarker() marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) + marker.setText(self.getName()) marker.setColor(rgba(self.getColor())) - marker._setDraggable(False) marker.setLineWidth(self.getLineWidth()) marker.setLineStyle(self.getLineStyle()) - return [marker] - - def _createAnchorItems(self, points): - marker = items.XMarker() - marker.setPosition(points[0][0], points[0][1]) - marker.setText(self.getLabel()) marker._setDraggable(self.isEditable()) - marker.setLineWidth(self.getLineWidth()) - marker.setLineStyle(self.getLineStyle()) + if self.isEditable(): + marker.sigItemChanged.connect(self.__positionChanged) return [marker] def __str__(self): |