Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
move events for transparent fill areas
  • Loading branch information
kushalkolar committed May 22, 2023
commit 9928dfac18173e950fa095aa5445ee439434ccca
28 changes: 21 additions & 7 deletions fastplotlib/graphics/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@


class _ImageHeatmapSelectorsMixin:
def add_linear_selector(self, selection: int = None, padding: float = 50, **kwargs) -> LinearSelector:
def add_linear_selector(self, selection: int = None, padding: float = None, **kwargs) -> LinearSelector:
"""
Adds a linear selector.

Parameters
----------
selection: int
selection: int, optional
initial position of the selector

padding: float
padding: float, optional
pad the length of the selector

kwargs
Expand All @@ -35,6 +35,12 @@ def add_linear_selector(self, selection: int = None, padding: float = 50, **kwar

"""

# default padding is 15% the height or width of the image
if "axis" in kwargs.keys():
axis = kwargs["axis"]
else:
axis = "x"

bounds_init, limits, size, origin, axis, end_points = self._get_linear_selector_init_args(padding, **kwargs)

if selection is None:
Expand All @@ -56,17 +62,17 @@ def add_linear_selector(self, selection: int = None, padding: float = 50, **kwar

return weakref.proxy(selector)

def add_linear_region_selector(self, padding: float = 100.0, **kwargs) -> LinearRegionSelector:
def add_linear_region_selector(self, padding: float = None, **kwargs) -> LinearRegionSelector:
"""
Add a :class:`.LinearRegionSelector`. Selectors are just ``Graphic`` objects, so you can manage,
remove, or delete them from a plot area just like any other ``Graphic``.

Parameters
----------
padding: float, default 100.0
padding: float, optional
Extends the linear selector along the y-axis to make it easier to interact with.

kwargs
kwargs, optional
passed to ``LinearRegionSelector``

Returns
Expand All @@ -85,13 +91,13 @@ def add_linear_region_selector(self, padding: float = 100.0, **kwargs) -> Linear
size=size,
origin=origin,
parent=weakref.proxy(self),
fill_color=(0, 0, 0.35, 0.2),
**kwargs
)

self._plot_area.add_graphic(selector, center=False)
# so that it is above this graphic
selector.position.set_z(self.position.z + 3)
selector.fill.material.color = (*selector.fill.material.color[:-1], 0.2)

# PlotArea manages this for garbage collection etc. just like all other Graphics
# so we should only work with a proxy on the user-end
Expand All @@ -107,6 +113,14 @@ def _get_linear_selector_init_args(self, padding: float, **kwargs):
else:
axis = "x"

if padding is None:
if axis == "x":
# based on number of rows
padding = int(data.shape[0] * 0.15)
elif axis == "y":
# based on number of columns
padding = int(data.shape[1] * 0.15)

if axis == "x":
offset = self.position.x
# x limits, number of columns
Expand Down
30 changes: 29 additions & 1 deletion fastplotlib/graphics/selectors/_base_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ def _add_plot_area_hook(self, plot_area):
# double-click to enable arrow-key moveable mode
wo.add_event_handler(self._toggle_arrow_key_moveable, "double_click")

for fill in self._fill:
if fill.material.color_is_transparent:
pfunc_fill = partial(self._check_fill_pointer_event, fill)
self._plot_area.renderer.add_event_handler(pfunc_fill, "pointer_down")

# when the pointer moves
self._plot_area.renderer.add_event_handler(self._move, "pointer_move")

Expand All @@ -129,14 +134,37 @@ def _add_plot_area_hook(self, plot_area):
self._plot_area.renderer.add_event_handler(self._key_up, "key_up")
self._plot_area.add_animations(self._key_hold)

def _check_fill_pointer_event(self, event_source: WorldObject, ev):
world_pos = self._plot_area.map_screen_to_world((ev.x, ev.y))
# outside viewport, ignore
# this shouldn't be possible since the event handler is registered to the fill mesh world object
# but I like sanity checks anyways
if world_pos is None:
return

bbox = event_source.get_world_bounding_box()

xmin, ymin, zmin = bbox[0]
xmax, ymax, zmax = bbox[1]

if not (xmin <= world_pos.x <= xmax):
return

if not (ymin <= world_pos.y <= ymax):
return

self._move_start(event_source, ev)

def _move_start(self, event_source: WorldObject, ev):
"""
Called on "pointer_down" events

Parameters
----------
event_source: WorldObject
event source, for example selection fill area ``Mesh`` an edge ``Line`` or vertex ``Points``
event source, for example selection fill area ``Mesh`` an edge ``Line`` or vertex ``Points``.
This helps keep the event source within the MoveInfo so that during "pointer_move" events (which are
from the renderer) we know the original source of the "move action".

ev: Event
pygfx ``Event``
Expand Down
2 changes: 1 addition & 1 deletion fastplotlib/graphics/selectors/_linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def __init__(

line_data = np.column_stack([xs, ys, zs])
else:
raise ValueError("`axis` must be one of 'v' or 'h'")
raise ValueError("`axis` must be one of 'x' or 'y'")

line_data = line_data.astype(np.float32)

Expand Down
4 changes: 3 additions & 1 deletion fastplotlib/graphics/selectors/_linear_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ def __init__(
pygfx.box_geometry(size, 1, 1),
pygfx.MeshBasicMaterial(color=pygfx.Color(fill_color))
)
else:
raise ValueError("`axis` must be one of 'x' or 'y'")

# the fill of the selection
self.fill = mesh
Expand Down Expand Up @@ -314,7 +316,7 @@ def __init__(
def bounds(self) -> LinearBoundsFeature:
"""
The current bounds of the selection in world space. These bounds will NOT necessarily correspond to the
indices of the data that are under the selection. Use ``get_selected_indices()` which maps from
indices of the data that are under the selection. Use ``get_selected_indices()`` which maps from
world space to data indices.
"""
return self._bounds
Expand Down