Skip to content

Commit

Permalink
feat(interactive.colors): implement BetterColorBarItem limit editor
Browse files Browse the repository at this point in the history
A new context menu in `BetterColorBarItem`'s viewbox enables manually editing color limits.
  • Loading branch information
kmnhan committed Aug 21, 2024
1 parent 455dfd1 commit 7dd1477
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
68 changes: 68 additions & 0 deletions src/erlab/interactive/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,65 @@ def mouseDragEvent(self, ev) -> None:
self.sigRegionChanged.emit(self)


class _ColorBarLimitWidget(QtWidgets.QWidget):
def __init__(self, colorbar: BetterColorBarItem) -> None:
super().__init__()
self.setGeometry(QtCore.QRect(0, 640, 242, 182))
self.cb = colorbar

layout = QtWidgets.QFormLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setVerticalSpacing(0)
self.setLayout(layout)

self.max_spin = pg.SpinBox(dec=True, compactHeight=False, finite=False)
self.min_spin = pg.SpinBox(dec=True, compactHeight=False, finite=False)
self.rst_btn = QtWidgets.QPushButton("Reset")

self.max_spin.setObjectName("_vmax_spin")
self.min_spin.setObjectName("_vmin_spin")
self.rst_btn.setObjectName("_vlim_reset_btn")

layout.addRow("Max", self.max_spin)
layout.addRow("Min", self.min_spin)
layout.addRow(self.rst_btn)

self.cb._span.sigRegionChanged.connect(self.region_changed)
self.min_spin.sigValueChanged.connect(self.update_region)
self.max_spin.sigValueChanged.connect(self.update_region)
self.rst_btn.clicked.connect(self.reset)

def _set_spin_values(self, mn: float, mx: float) -> None:
self.max_spin.blockSignals(True)
self.min_spin.blockSignals(True)
self.max_spin.setValue(mx)
self.min_spin.setValue(mn)
self.max_spin.blockSignals(False)
self.min_spin.blockSignals(False)

@QtCore.Slot()
def region_changed(self):
mn, mx = self.cb._span.getRegion()
self._set_spin_values(mn, mx)

@QtCore.Slot()
def reset(self):
self._set_spin_values(-np.inf, np.inf)
self.update_region()

@QtCore.Slot()
def update_region(self):
# Trigger region change start and finish signals to simulate drag
self.cb._span.sigRegionChangeStarted.emit(self.cb._span)
self.cb.setSpanRegion((self.min_spin.value(), self.max_spin.value()))
self.cb._span.sigRegionChangeFinished.emit(self.cb._span)

def setVisible(self, visible: bool) -> None:
super().setVisible(visible)
if visible:
self.region_changed()

Check warning on line 375 in src/erlab/interactive/colors.py

View check run for this annotation

Codecov / codecov/patch

src/erlab/interactive/colors.py#L375

Added line #L375 was not covered by tests


class BetterColorBarItem(pg.PlotItem):
def __init__(
self,
Expand Down Expand Up @@ -361,6 +420,15 @@ def __init__(
self.setAutoLevels(autoLevels)
self._images: set[weakref.ref[BetterImageItem]] = set()
self._primary_image: weakref.ref[BetterImageItem] | None = None

# Add colorbar limit editor to context menu
self.vb.menu.addSeparator()
self._clim_menu: QtWidgets.QMenu = self.vb.menu.addMenu("Edit color limits")
clw = _ColorBarLimitWidget(self)
act = QtWidgets.QWidgetAction(self._clim_menu)
act.setDefaultWidget(clw)
self._clim_menu.addAction(act)

if image is not None:
self.setImageItem(image)
if limits is not None:
Expand Down
12 changes: 12 additions & 0 deletions tests/interactive/test_imagetool.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ def test_itool(qtbot):
win.slicer_area.lock_levels(True)
win.slicer_area.levels = (1.0, 23.0)
assert win.slicer_area._colorbar.cb._copy_limits() == str((1.0, 23.0))

# Test color limits editor
clw = win.slicer_area._colorbar.cb._clim_menu.actions()[0].defaultWidget()
assert clw.min_spin.value() == win.slicer_area.levels[0]
assert clw.max_spin.value() == win.slicer_area.levels[1]
clw.min_spin.setValue(1.0)
assert clw.min_spin.value() == 1.0
clw.max_spin.setValue(2.0)
assert clw.max_spin.value() == 2.0
clw.rst_btn.click()
assert win.slicer_area.levels == (0.0, 24.0)
win.slicer_area.levels = (1.0, 23.0)
win.slicer_area.lock_levels(False)

# Undo and redo
Expand Down

0 comments on commit 7dd1477

Please sign in to comment.