Source code for fury.ui.containers

"""UI container module."""

import logging

import numpy as np

from fury.ui.core import UI, Anchor, Rectangle2D


[docs] class Panel2D(UI): """ A 2D UI Panel. Can contain one or more UI elements. Parameters ---------- size : (int, int) Size (width, height) in pixels of the panel. position : (float, float) Absolute coordinates (x, y) of the lower-left corner of the panel. color : (float, float, float) Must take values in [0, 1]. opacity : float Must take values in [0, 1]. align : [left, right] Alignment of the panel with respect to the overall screen. border_color : (float, float, float), optional RGB color of the border. Must take values in [0, 1]. border_width : float, optional Width of the border. has_border : bool, optional If the panel should have borders. Attributes ---------- alignment : [left, right] Alignment of the panel with respect to the overall screen. """
[docs] def __init__( self, size, *, position=(0, 0), color=(0.1, 0.1, 0.1), opacity=0.7, align="left", border_color=(1, 1, 1), border_width=0, has_border=False, ): """Initialize class instance.""" self.border_sides = ["left", "right", "top", "bottom"] self.border_coords = { "left": (0.0, 0.0), "right": (1.0, 0.0), "top": (0.0, 0.0), "bottom": (0.0, 1.0), } self.has_border = has_border self._border_color = border_color self._border_width = border_width super(Panel2D, self).__init__(position=position) self.resize(size) self.alignment = align self.color = color self.opacity = opacity self._drag_offset = None
def _setup(self): """ Set up this UI component. Create the background (Rectangle2D) of the panel and initialize the border elements (Rectangle2D). """ self._elements = [] self.element_offsets = [] self.background = Rectangle2D(size=(1, 1)) if self.has_border: self.borders = { "left": Rectangle2D(size=(1, 1)), "right": Rectangle2D(size=(1, 1)), "top": Rectangle2D(size=(1, 1)), "bottom": Rectangle2D(size=(1, 1)), } for key in self.borders.keys(): self.borders[key].color = self._border_color self.borders[ key ].on_left_mouse_button_pressed = self.left_button_pressed self.borders[ key ].on_left_mouse_button_dragged = self.left_button_dragged self.add_element( self.borders[key], self.border_coords[key], _is_internal=True ) self.add_element(self.background, (0, 0), _is_internal=True) self.background.on_left_mouse_button_pressed = self.left_button_pressed self.background.on_left_mouse_button_dragged = self.left_button_dragged def _get_actors(self): """ Get actors composing this UI component. Returns ------- list List of actors composing this UI component. """ actors = [] actors.extend(self.background.actors) if self.has_border: for border in self.borders.values(): actors.extend(border.actors) return actors def _get_size(self): """ Get the actual size of the panel. Returns ------- (float, float) The (width, height) size of the panel. """ return self.background.size
[docs] def resize(self, size): """ Set the panel size. Parameters ---------- size : (float, float) Panel size (width, height) in pixels. """ self.background.resize(size) if self.has_border: self.borders["left"].resize( (self._border_width, size[1] + self._border_width) ) self.borders["right"].resize( (self._border_width, size[1] + self._border_width) ) self.borders["top"].resize( (self.size[0] + self._border_width, self._border_width) ) self.borders["bottom"].resize( (self.size[0] + self._border_width, self._border_width) ) self.update_border_coords()
def _update_actors_position(self): """Update the position of the internal actors.""" coords = self.get_position() for element, offset in self.element_offsets: if element == self.background: element.z_order = self.z_order elif self.has_border and element in self.borders.values(): element.z_order = self.z_order + 1 else: element.z_order = self.z_order + 2 element.set_position(coords + offset)
[docs] def set_visibility(self, visibility): """ Set visibility of this UI component. Parameters ---------- visibility : bool If True, the panel and its elements will be visible. If False, it will be hidden. """ for element in self._elements: element.set_visibility(visibility)
@property def color(self): """ Get the background color of the panel. Returns ------- (float, float, float) RGB color of the panel background. """ return self.background.color @color.setter def color(self, color): """ Set the background color of the panel. Parameters ---------- color : (float, float, float) New RGB color of the panel background. Must take values in [0, 1]. """ self.background.color = color @property def opacity(self): """ Get the opacity of the panel. Returns ------- float Opacity value. """ return self.background.opacity @opacity.setter def opacity(self, opacity): """ Set the opacity of the panel. Parameters ---------- opacity : float New opacity value. """ self.background.opacity = opacity
[docs] def add_element(self, element, coords, *, anchor="position", _is_internal=False): """ Add a UI component to the panel. The coordinates represent an offset from the lower left corner of the panel. Parameters ---------- element : UI The UI item to be added. coords : (float, float) or (int, int) If float, normalized coordinates are assumed and they must be between [0,1]. If int, pixels coordinates are assumed and it must fit within the panel's size. anchor : str, optional Supported anchors are 'position' (top-left) and 'center'. _is_internal : bool, optional Flag used to distinguish between user-added elements and internal elements added by the Panel itself. Raises ------ ValueError If coordinates are normalized but outside the [0,1] range, or if an unknown anchor is provided. """ coords = np.array(coords) if np.issubdtype(coords.dtype, np.floating): if np.any(coords < 0) or np.any(coords > 1): raise ValueError("Normalized coordinates must be in [0,1].") coords = coords * self.size if anchor == "center": element.set_position( self.get_position() + coords, x_anchor=Anchor.CENTER, y_anchor=Anchor.CENTER, ) elif anchor == "position": element.set_position( self.get_position() + coords, ) else: msg = f"Unknown anchor {anchor}. Supported anchors are 'position' and \ 'center'." raise ValueError(msg) self._elements.append(element) if not _is_internal: self._children.append(element) offset = element.get_position() - self.get_position() self.element_offsets.append((element, offset))
[docs] def remove_element(self, element): """ Remove a UI component from the panel. Parameters ---------- element : UI The UI item to be removed. Raises ------ ValueError If the element is not found in the panel's elements list. """ idx = self._elements.index(element) del self._elements[idx] del self.element_offsets[idx] if element in self._children: self._children.remove(element)
[docs] def update_element(self, element, coords, *, anchor="position"): """ Update the position of a UI component in the panel. Parameters ---------- element : UI The UI item to be updated. coords : (float, float) or (int, int) New coordinates. If float, normalized coordinates are assumed and they must be between [0,1]. If int, pixel coordinates are assumed and it must fit within the panel's size. anchor : str, optional Supported anchors are 'position' (top-left) and 'center'. Raises ------ ValueError If coordinates are normalized but outside the [0,1] range, or if an unknown anchor is provided. """ self.remove_element(element) self.add_element(element, coords, anchor=anchor)
[docs] def left_button_pressed(self, event): """ Handle left mouse button press event for panel. Parameters ---------- event : PointerEvent The PyGfx pointer event object. """ click_pos = np.array([event.x, event.y]) self._drag_offset = click_pos - self.get_position()
[docs] def left_button_dragged(self, event): """ Handle left mouse button drag event for panel movement. Parameters ---------- event : PointerEvent The PyGfx pointer event object. """ if self._drag_offset is not None: click_position = np.array([event.x, event.y]) new_position = click_position - self._drag_offset self.set_position(new_position)
[docs] def re_align(self, window_size_change): """ Re-organise the elements in case the window size is changed. Parameters ---------- window_size_change : (int, int) New window size (width, height) in pixels. Raises ------ ValueError If alignment is not 'left' or 'right'. """ if self.alignment == "left": pass elif self.alignment == "right": self.set_position(window_size_change) else: msg = "You can only left-align or right-align objects in a panel." raise ValueError(msg)
[docs] def update_border_coords(self): """Update the coordinates of the borders.""" if not self.has_border: return for key in self.borders.keys(): self.update_element(self.borders[key], self.border_coords[key])
@property def border_color(self): """ Get the current color of all four borders. Returns ------- list A list containing the color (RGB tuple) of the left, right, top, and bottom borders, respectively. """ if not self.has_border: logging.warning("Border is not present, border color is not available.") return [] return [self.borders[side].color for side in self.border_sides] @border_color.setter def border_color(self, side_color): """ Set the color of a specific border. Parameters ---------- side_color : Iterable Iterable `[side, color]` containing the side (str) and color (RGB tuple). """ side, color = side_color if side.lower() not in ["left", "right", "top", "bottom"]: raise ValueError(f"{side} not a valid border side") if not self.has_border: logging.warning( "Border is not present, setting border color will be ignored." ) return self.borders[side].color = color @property def border_width(self): """ Get the current width/height of the borders. Returns ------- list A list containing the width (for left/right) and height (for top/bottom) of the borders. """ if not self.has_border: logging.warning("Border is not present, border width is not available.") return [] widths = [] for side in self.border_sides: if side in ["left", "right"]: widths.append(self.borders[side].width) elif side in ["top", "bottom"]: widths.append(self.borders[side].height) else: raise ValueError(f"{side} not a valid border side") return widths @border_width.setter def border_width(self, side_width): """ Set the width of a specific border. Parameters ---------- side_width : Iterable Iterable `[side, width]` containing the side (str) and the width (float). """ side, border_width = side_width if not self.has_border: logging.warning( "Border is not present, setting border width will be ignored." ) return if side.lower() in ["left", "right"]: self.borders[side].width = border_width elif side.lower() in ["top", "bottom"]: self.borders[side].height = border_width else: raise ValueError(f"{side} not a valid border side")
# class TabPanel2D(UI): # """Render content within a Tab. # Attributes # ---------- # content_panel: :class: 'Panel2D' # Hold all the content UI components. # text_block: :class: 'TextBlock2D' # Renders the title of the tab. # """ # @warn_on_args_to_kwargs() # def __init__( # self, # *, # position=(0, 0), # size=(100, 100), # title="New Tab", # color=(0.5, 0.5, 0.5), # content_panel=None, # ): # """Init class instance. # Parameters # ---------- # position : (float, float) # Absolute coordinates (x, y) of the lower-left corner of the # UI component # size : (int, int) # Width and height of the pixels of this UI component. # title : str # Renders the title for Tab panel. # color : list of 3 floats # Background color of tab panel. # content_panel : Panel2D # Panel consisting of the content UI elements. # """ # self.content_panel = content_panel # self.panel_size = size # self._text_size = (int(1.0 * size[0]), size[1]) # super(TabPanel2D, self).__init__() # self.title = title # self.panel.position = position # self.color = color # def _setup(self): # """Setup this UI component. # Create parent panel. # Create Text to hold tab information. # Create Button to close tab. # """ # self.panel = Panel2D(size=self.panel_size) # self.text_block = TextBlock2D(size=self._text_size, color=(0, 0, 0)) # self.panel.add_element(self.text_block, (0, 0)) # def _get_actors(self): # """Get the actors composing this UI component.""" # return self.panel.actors + self.content_panel.actors # def _add_to_scene(self, _scene): # """Add all subcomponents or VTK props that compose this UI component. # Parameters # ---------- # scene : scene # """ # self.panel.add_to_scene(_scene) # self.content_panel.add_to_scene(_scene) # def _set_position(self, _coords): # """Set the lower-left corner position of this UI component. # Parameters # ---------- # coords: (float, float) # Absolute pixel coordinates (x, y). # """ # self.panel.position = _coords # def _get_size(self): # return self.panel.size # def resize(self, size): # """Resize Tab panel. # Parameters # ---------- # size : (int, int) # New width and height in pixels. # """ # self._text_size = (int(0.7 * size[0]), size[1]) # self._button_size = (int(0.3 * size[0]), size[1]) # self.panel.resize(size) # self.text_block.resize(self._text_size) # @property # def color(self): # """Return the background color of tab panel.""" # return self.panel.color # @color.setter # def color(self, color): # """Set background color of tab panel. # Parameters # ---------- # color : list of 3 floats. # """ # self.panel.color = color # @property # def title(self): # """Return the title of tab panel.""" # return self.text_block.message # @title.setter # def title(self, text): # """Set the title of tab panel. # Parameters # ---------- # text : str # New title for tab panel. # """ # self.text_block.message = text # @property # def title_bold(self): # """Is the title of a tab panel bold.""" # return self.text_block.bold # @title_bold.setter # def title_bold(self, bold): # """Determine if the text title of a tab panel must be bold. # Parameters # ---------- # bold : bool # Bold property for a text title in a tab panel. # """ # self.text_block.bold = bold # @property # def title_color(self): # """Return the title color of tab panel.""" # return self.text_block.color # @title_color.setter # def title_color(self, color): # """Set the title color of tab panel. # Parameters # ---------- # color : tuple # New title color for tab panel. # """ # self.text_block.color = color # @property # def title_font_size(self): # """Return the title font size of tab panel.""" # return self.text_block.font_size # @title_font_size.setter # def title_font_size(self, font_size): # """Set the title font size of tab panel. # Parameters # ---------- # font_size : int # New title font size for tab panel. # """ # self.text_block.font_size = font_size # @property # def title_italic(self): # """Is the title of a tab panel italic.""" # return self.text_block.italic # @title_italic.setter # def title_italic(self, italic): # """Determine if the text title of a tab panel must be italic. # Parameters # ---------- # italic : bool # Italic property for a text title in a tab panel. # """ # self.text_block.italic = italic # @warn_on_args_to_kwargs() # def add_element(self, element, coords, *, anchor="position"): # """Add a UI component to the content panel. # The coordinates represent an offset from the lower left corner of the # panel. # Parameters # ---------- # element : UI # The UI item to be added. # coords : (float, float) or (int, int) # If float, normalized coordinates are assumed and they must be # between [0,1]. # If int, pixels coordinates are assumed and it must fit within the # panel's size. # """ # element.set_visibility(False) # self.content_panel.add_element(element, coords, anchor=anchor) # def remove_element(self, element): # """Remove a UI component from the content panel. # Parameters # ---------- # element : UI # The UI item to be removed. # """ # self.content_panel.remove_element(element) # @warn_on_args_to_kwargs() # def update_element(self, element, coords, *, anchor="position"): # """Update the position of a UI component in the content panel. # Parameters # ---------- # element : UI # The UI item to be updated. # coords : (float, float) or (int, int) # New coordinates. # If float, normalized coordinates are assumed and they must be # between [0,1]. # If int, pixels coordinates are assumed and it must fit within the # panel's size. # """ # self.content_panel.update_element(element, coords, anchor="position") # class TabUI(UI): # """UI element to add multiple panels within a single window. # Attributes # ---------- # tabs: :class: List of 'TabPanel2D' # Stores all the instances of 'TabPanel2D' that renders the contents. # """ # @warn_on_args_to_kwargs() # def __init__( # self, # *, # position=(0, 0), # size=(100, 100), # nb_tabs=1, # active_color=(1, 1, 1), # inactive_color=(0.5, 0.5, 0.5), # draggable=False, # startup_tab_id=None, # tab_bar_pos="top", # ): # """Init class instance. # Parameters # ---------- # position : (float, float) # Absolute coordinates (x, y) of the lower-left corner of this # UI component. # size : (int, int) # Width and height in pixels of this UI component. # nb_tabs : int # Number of tabs to be renders. # active_color : tuple of 3 floats. # Background color of active tab panel. # inactive_color : tuple of 3 floats. # Background color of inactive tab panels. # draggable : bool # Whether the UI element is draggable or not. # startup_tab_id : int, optional # Tab to be activated and uncollapsed on startup. # by default None is activated/ all collapsed. # tab_bar_pos : str, optional # Position of the Tab Bar in the panel # """ # self.tabs = [] # self.nb_tabs = nb_tabs # self.parent_size = size # self.content_size = (size[0], int(0.9 * size[1])) # self.draggable = draggable # self.active_color = active_color # self.inactive_color = inactive_color # self.active_tab_idx = startup_tab_id # self.collapsed = True # self.tab_bar_pos = tab_bar_pos # super(TabUI, self).__init__() # self.position = position # def _setup(self): # """Setup this UI component. # Create parent panel. # Create tab panels. # """ # self.parent_panel = Panel2D(self.parent_size, opacity=0.0) # # Offer some standard hooks to the user. # self.on_change = lambda ui: None # self.on_collapse = lambda ui: None # for _ in range(self.nb_tabs): # content_panel = Panel2D(size=self.content_size) # content_panel.set_visibility(False) # tab_panel = TabPanel2D(content_panel=content_panel) # self.tabs.append(tab_panel) # self.update_tabs() # if self.active_tab_idx is not None: # self.tabs[self.active_tab_idx].color = self.active_color # self.tabs[self.active_tab_idx].content_panel.set_visibility(True) # def _get_actors(self): # """Get the actors composing this UI component.""" # actors = [] # actors += self.parent_panel.actors # for tab_panel in self.tabs: # actors += tab_panel.actors # return actors # def _add_to_scene(self, _scene): # """Add all subcomponents or VTK props that compose this UI component. # Parameters # ---------- # scene : scene # """ # self.parent_panel.add_to_scene(_scene) # for tab_panel in self.tabs: # tab_panel.add_to_scene(_scene) # def _set_position(self, _coords): # """Set the lower-left corner position of this UI component. # Parameters # ---------- # coords: (float, float) # Absolute pixel coordinates (x, y). # """ # self.parent_panel.position = _coords # def _get_size(self): # return self.parent_panel.size # def update_tabs(self): # """Update position, size and callbacks for tab panels.""" # self.tab_panel_size = (self.size[0] // self.nb_tabs, int(0.1 * self.size[1])) # if self.tab_bar_pos.lower() not in ["top", "bottom"]: # warn("tab_bar_pos can only have value top/bottom", stacklevel=2) # self.tab_bar_pos = "top" # if self.tab_bar_pos.lower() == "top": # tab_panel_pos = [0.0, 0.9] # elif self.tab_bar_pos.lower() == "bottom": # tab_panel_pos = [0.0, 0.0] # for tab_panel in self.tabs: # tab_panel.resize(self.tab_panel_size) # tab_panel.content_panel.position = self.position # content_panel = tab_panel.content_panel # if self.draggable: # tab_panel.panel.background.on_left_mouse_button_pressed = ( # self.left_button_pressed # ) # content_panel.background.on_left_mouse_button_pressed = ( # self.left_button_pressed # ) # tab_panel.text_block.on_left_mouse_button_pressed = ( # self.left_button_pressed # ) # tab_panel.panel.background.on_left_mouse_button_dragged = ( # self.left_button_dragged # ) # content_panel.background.on_left_mouse_button_dragged = ( # self.left_button_dragged # ) # tab_panel.text_block.on_left_mouse_button_dragged = ( # self.left_button_dragged # ) # else: # tab_panel.panel.background.on_left_mouse_button_dragged = ( # lambda i_ren, _obj, _comp: i_ren.force_render # ) # content_panel.background.on_left_mouse_button_dragged = ( # lambda i_ren, _obj, _comp: i_ren.force_render # ) # tab_panel.text_block.on_left_mouse_button_clicked = # self.select_tab_callback # tab_panel.panel.background.on_left_mouse_button_clicked = ( # self.select_tab_callback # ) # tab_panel.text_block.on_right_mouse_button_clicked = self.collapse_tab_ui # tab_panel.panel.background.on_right_mouse_button_clicked = ( # self.collapse_tab_ui # ) # tab_panel.content_panel.resize(self.content_size) # self.parent_panel.add_element(tab_panel, tab_panel_pos) # if self.tab_bar_pos.lower() == "top": # self.parent_panel.add_element(tab_panel.content_panel, (0.0, 0.0)) # elif self.tab_bar_pos.lower() == "bottom": # self.parent_panel.add_element(tab_panel.content_panel, (0.0, 0.1)) # tab_panel_pos[0] += 1 / self.nb_tabs # def select_tab_callback(self, iren, _obj, _tab_comp): # """Handle events when a tab is selected.""" # for idx, tab_panel in enumerate(self.tabs): # if ( # tab_panel.text_block is not _tab_comp # and tab_panel.panel.background is not _tab_comp # ): # tab_panel.color = self.inactive_color # tab_panel.content_panel.set_visibility(False) # else: # current_visibility = tab_panel.content_panel.actors[0].GetVisibility() # if not current_visibility: # tab_panel.color = self.active_color # else: # tab_panel.color = self.inactive_color # tab_panel.content_panel.set_visibility(not current_visibility) # self.active_tab_idx = idx # self.collapsed = False # self.on_change(self) # iren.force_render() # iren.event.abort() # def collapse_tab_ui(self, iren, _obj, _tab_comp): # """Handle events when Tab UI is collapsed.""" # if self.active_tab_idx is not None: # active_tab_panel = self.tabs[self.active_tab_idx] # active_tab_panel.color = self.inactive_color # active_tab_panel.content_panel.set_visibility(False) # self.active_tab_idx = None # self.collapsed = True # self.on_collapse(self) # iren.force_render() # iren.event.abort() # @warn_on_args_to_kwargs() # def add_element(self, tab_idx, element, coords, *, anchor="position"): # """Add element to content panel after checking its existence.""" # if tab_idx < self.nb_tabs and tab_idx >= 0: # self.tabs[tab_idx].add_element(element, coords, anchor=anchor) # if tab_idx == self.active_tab_idx: # element.set_visibility(True) # else: # raise IndexError("Tab with index " "{} does not exist".format(tab_idx)) # def remove_element(self, tab_idx, element): # """Remove element from content panel after checking its existence.""" # if tab_idx < self.nb_tabs and tab_idx >= 0: # self.tabs[tab_idx].remove_element(element) # else: # raise IndexError("Tab with index " "{} does not exist".format(tab_idx)) # @warn_on_args_to_kwargs() # def update_element(self, tab_idx, element, coords, *, anchor="position"): # """Update element on content panel after checking its existence.""" # if tab_idx < self.nb_tabs and tab_idx >= 0: # self.tabs[tab_idx].update_element(element, coords, anchor=anchor) # else: # raise IndexError("Tab with index " "{} does not exist".format(tab_idx)) # def left_button_pressed(self, i_ren, _obj, _sub_component): # click_pos = np.array(i_ren.event.position) # self._click_position = click_pos # i_ren.event.abort() # Stop propagating the event. # def left_button_dragged(self, i_ren, _obj, _sub_component): # click_position = np.array(i_ren.event.position) # change = click_position - self._click_position # self.parent_panel.position += change # self._click_position = click_position # i_ren.force_render() # # class ImageContainer2D(UI): # # """A 2D container to hold an image. # # Currently Supports: # # - png and jpg/jpeg images # # Attributes # # ---------- # # size: (float, float) # # Image size (width, height) in pixels. # # img : ImageData # # The image loaded from the specified path. # # """ # # @warn_on_args_to_kwargs() # # def __init__(self, img_path, *, position=(0, 0), size=(100, 100)): # # """Init class instance. # # Parameters # # ---------- # # img_path : string # # URL or local path of the image # # position : (float, float), optional # # Absolute coordinates (x, y) of the lower-left corner of the image. # # size : (int, int), optional # # Width and height in pixels of the image. # # """ # # super(ImageContainer2D, self).__init__(position=position) # # self.img = load_image(img_path, as_vtktype=True) # # self.set_img(self.img) # # self.resize(size) # # def _get_size(self): # # lower_left_corner = self.texture_points.GetPoint(0) # # upper_right_corner = self.texture_points.GetPoint(2) # # size = np.array(upper_right_corner) - np.array(lower_left_corner) # # return abs(size[:2]) # # def _setup(self): # # """Setup this UI Component. # # Return an image as a 2D actor with a specific position. # # Returns # # ------- # # :class:`vtkTexturedActor2D` # # """ # # self.texture_polydata = PolyData() # # self.texture_points = Points() # # self.texture_points.SetNumberOfPoints(4) # # polys = CellArray() # # polys.InsertNextCell(4) # # polys.InsertCellPoint(0) # # polys.InsertCellPoint(1) # # polys.InsertCellPoint(2) # # polys.InsertCellPoint(3) # # self.texture_polydata.SetPolys(polys) # # tc = FloatArray() # # tc.SetNumberOfComponents(2) # # tc.SetNumberOfTuples(4) # # tc.InsertComponent(0, 0, 0.0) # # tc.InsertComponent(0, 1, 0.0) # # tc.InsertComponent(1, 0, 1.0) # # tc.InsertComponent(1, 1, 0.0) # # tc.InsertComponent(2, 0, 1.0) # # tc.InsertComponent(2, 1, 1.0) # # tc.InsertComponent(3, 0, 0.0) # # tc.InsertComponent(3, 1, 1.0) # # self.texture_polydata.GetPointData().SetTCoords(tc) # # texture_mapper = PolyDataMapper2D() # # texture_mapper = set_input(texture_mapper, self.texture_polydata) # # image = TexturedActor2D() # # image.SetMapper(texture_mapper) # # self.texture = Texture() # # image.SetTexture(self.texture) # # image_property = Property2D() # # image_property.SetOpacity(1.0) # # image.SetProperty(image_property) # # self.actor = image # # # Add default events listener to the VTK actor. # # self.handle_events(self.actor) # # def _get_actors(self): # # """Return the actors that compose this UI component.""" # # return [self.actor] # # def _add_to_scene(self, scene): # # """Add all subcomponents or VTK props that compose this UI component. # # Parameters # # ---------- # # scene : scene # # """ # # scene.add(self.actor) # # def resize(self, size): # # """Resize the image. # # Parameters # # ---------- # # size : (float, float) # # image size (width, height) in pixels. # # """ # # # Update actor. # # self.texture_points.SetPoint(0, 0, 0, 0.0) # # self.texture_points.SetPoint(1, size[0], 0, 0.0) # # self.texture_points.SetPoint(2, size[0], size[1], 0.0) # # self.texture_points.SetPoint(3, 0, size[1], 0.0) # # self.texture_polydata.SetPoints(self.texture_points) # # def _set_position(self, coords): # # """Set the lower-left corner position of this UI component. # # Parameters # # ---------- # # coords: (float, float) # # Absolute pixel coordinates (x, y). # # """ # # self.actor.SetPosition(*coords) # # def scale(self, factor): # # """Scale the image. # # Parameters # # ---------- # # factor : (float, float) # # Scaling factor (width, height) in pixels. # # """ # # self.resize(self.size * factor) # # def set_img(self, img): # # """Modify the image used by the vtkTexturedActor2D. # # Parameters # # ---------- # # img : imageData # # """ # # self.texture = set_input(self.texture, img) # # class GridUI(UI): # # """Add actors in a grid and interact with them individually.""" # # @warn_on_args_to_kwargs() # # def __init__( # # self, # # actors, # # *, # # captions=None, # # caption_offset=(0, -100, 0), # # cell_padding=0, # # cell_shape="rect", # # aspect_ratio=16 / 9.0, # # dim=None, # # rotation_speed=1, # # rotation_axis=(0, 1, 0), # # ): # # # TODO: add rotation axis None by default # # self.container = grid( # # actors, # # captions=captions, # # caption_offset=caption_offset, # # cell_padding=cell_padding, # # cell_shape=cell_shape, # # aspect_ratio=aspect_ratio, # # dim=dim, # # ) # # self._actors = [] # # self._actors_dict = {} # # self.rotation_speed = rotation_speed # # self.rotation_axis = rotation_axis # # for item in self.container._items: # # actor = item if captions is None else item._items[0] # # self._actors.append(actor) # # self._actors_dict[actor] = {"x": -np.inf, "y": -np.inf} # # super(GridUI, self).__init__(position=(0, 0, 0)) # # def _get_size(self): # # return # # @staticmethod # # def left_click_callback(istyle, _obj, _what): # # istyle.trackball_actor.OnLeftButtonDown() # # istyle.force_render() # # istyle.event.abort() # # @staticmethod # # def left_release_callback(istyle, _obj, _what): # # istyle.trackball_actor.OnLeftButtonUp() # # istyle.force_render() # # istyle.event.abort() # # @staticmethod # # def mouse_move_callback(istyle, _obj, _what): # # istyle.trackball_actor.OnMouseMove() # # istyle.force_render() # # istyle.event.abort() # # @staticmethod # # def left_click_callback2(istyle, obj, self): # # rx, ry, rz = self.rotation_axis # # clockwise_rotation = np.array([self.rotation_speed, rx, ry, rz]) # # rotate(obj, clockwise_rotation) # # istyle.force_render() # # istyle.event.abort() # # @staticmethod # # def left_release_callback2(istyle, _obj, _what): # # istyle.force_render() # # istyle.event.abort() # # @staticmethod # # def mouse_move_callback2(istyle, obj, self): # # if self._actors_dict[obj]["y"] == -np.inf: # # iren = istyle.GetInteractor() # # event_pos = iren.GetEventPosition() # # self._actors_dict[obj]["y"] = event_pos[1] # # else: # # iren = istyle.GetInteractor() # # event_pos = iren.GetEventPosition() # # rx, ry, rz = self.rotation_axis # # if event_pos[1] >= self._actors_dict[obj]["y"]: # # clockwise_rotation = np.array([-self.rotation_speed, rx, ry, rz]) # # rotate(obj, clockwise_rotation) # # else: # # anti_clockwise_rotation = np.array( # [self.rotation_speed, rx, ry, rz]) # # rotate(obj, anti_clockwise_rotation) # # self._actors_dict[obj]["y"] = event_pos[1] # # istyle.force_render() # # istyle.event.abort() # # ANTICLOCKWISE_ROTATION_Y = np.array([-10, 0, 1, 0]) # # CLOCKWISE_ROTATION_Y = np.array([10, 0, 1, 0]) # # ANTICLOCKWISE_ROTATION_X = np.array([-10, 1, 0, 0]) # # CLOCKWISE_ROTATION_X = np.array([10, 1, 0, 0]) # # def key_press_callback(self, istyle, obj, _what): # # has_changed = False # # if istyle.event.key == "Left": # # has_changed = True # # for a in self._actors: # # rotate(a, self.ANTICLOCKWISE_ROTATION_Y) # # elif istyle.event.key == "Right": # # has_changed = True # # for a in self._actors: # # rotate(a, self.CLOCKWISE_ROTATION_Y) # # elif istyle.event.key == "Up": # # has_changed = True # # for a in self._actors: # # rotate(a, self.ANTICLOCKWISE_ROTATION_X) # # elif istyle.event.key == "Down": # # has_changed = True # # for a in self._actors: # # rotate(a, self.CLOCKWISE_ROTATION_X) # # if has_changed: # # istyle.force_render() # # def _setup(self): # # """Set up this UI component and the events of its actor.""" # # # Add default events listener to the VTK actor. # # for actor in self._actors: # # # self.handle_events(actor) # # if self.rotation_axis is None: # # self.add_callback( # # actor, "LeftButtonPressEvent", self.left_click_callback # # ) # # self.add_callback( # # actor, "LeftButtonReleaseEvent", self.left_release_callback # # ) # # self.add_callback(actor, "MouseMoveEvent", self.mouse_move_callback) # # else: # # self.add_callback( # # actor, "LeftButtonPressEvent", self.left_click_callback2 # # ) # # # TODO: possibly add this too # # self.add_callback( # # actor, "LeftButtonReleaseEvent", self.left_release_callback2 # # ) # # self.add_callback( # actor, "MouseMoveEvent", self.mouse_move_callback2) # # # TODO: this is currently not running # # self.add_callback(actor, "KeyPressEvent", self.key_press_callback) # # # self.on_key_press = self.key_press_callback2 # # def _get_actors(self): # # """Get the actors composing this UI component.""" # # return self._actors # # def _add_to_scene(self, scene): # # """Add all subcomponents or VTK props that compose this UI component. # # Parameters # # ---------- # # scene : scene # # """ # # self.container.add_to_scene(scene) # # def resize(self, size): # # """Resize the button. # # Parameters # # ---------- # # size : (float, float) # # Button size (width, height) in pixels. # # """ # # # Update actor. # # pass # # def _set_position(self, coords): # # """Set the lower-left corner position of this UI component. # # Parameters # # ---------- # # coords: (float, float) # # Absolute pixel coordinates (x, y). # # """ # # # coords = (0, 0, 0) # # pass # # # self.actor.SetPosition(*coords) # # # self.container.SetPosition(*coords)