"""Widgets are different than actors in that they can interact with events.
To do so they need as input a vtkRenderWindowInteractor also known as iren.
"""
import numpy as np
import vtk
[docs]def slider(iren, ren, callback, min_value=0, max_value=255, value=125,
           label="Slider",
           right_normalized_pos=(0.9, 0.5),
           size=(50, 0),
           label_format="%0.0lf",
           color=(0.5, 0.5, 0.5),
           selected_color=(0.9, 0.2, 0.1)):
    """ A 2D slider widget
    Parameters
    ----------
    iren : vtkRenderWindowInteractor
        Used to process events and handle them to the slider. Can also be given
        by the attribute ``ShowManager.iren``.
    ren :  vtkRenderer or Renderer
        Used to update the slider's position when the window changes. Can also
        be given by the ``ShowManager.ren`` attribute.
    callback : function
        Function that has at least ``obj`` and ``event`` as parameters. It will
        be called when the slider's bar has changed.
    min_value : float
        Minimum value of slider.
    max_value : float
        Maximum value of slider.
    value :
        Default value of slider.
    label : str
        Slider's caption.
    right_normalized_pos : tuple
        2d tuple holding the normalized right (X, Y) position of the slider.
    size: tuple
        2d tuple holding the size of the slider in pixels.
    label_format: str
        Formating in which the slider's value will appear for example "%0.2lf"
        allows for 2 decimal values.
    Returns
    -------
    slider : SliderObject
        This object inherits from vtkSliderWidget and has additional method
        called ``place`` which allows to update the position of the slider
        when for example the window is resized.
    """
    slider_rep = vtk.vtkSliderRepresentation2D()
    slider_rep.SetMinimumValue(min_value)
    slider_rep.SetMaximumValue(max_value)
    slider_rep.SetValue(value)
    slider_rep.SetTitleText(label)
    slider_rep.GetPoint2Coordinate().SetCoordinateSystemToNormalizedDisplay()
    slider_rep.GetPoint2Coordinate().SetValue(*right_normalized_pos)
    coord2 = slider_rep.GetPoint2Coordinate().GetComputedDisplayValue(ren)
    slider_rep.GetPoint1Coordinate().SetCoordinateSystemToDisplay()
    slider_rep.GetPoint1Coordinate().SetValue(coord2[0] - size[0],
                                              coord2[1] - size[1])
    initial_window_size = ren.GetSize()
    length = 0.04
    width = 0.04
    cap_length = 0.01
    cap_width = 0.01
    tube_width = 0.005
    slider_rep.SetSliderLength(length)
    slider_rep.SetSliderWidth(width)
    slider_rep.SetEndCapLength(cap_length)
    slider_rep.SetEndCapWidth(cap_width)
    slider_rep.SetTubeWidth(tube_width)
    slider_rep.SetLabelFormat(label_format)
    slider_rep.GetLabelProperty().SetColor(*color)
    slider_rep.GetTubeProperty().SetColor(*color)
    slider_rep.GetCapProperty().SetColor(*color)
    slider_rep.GetTitleProperty().SetColor(*color)
    slider_rep.GetSelectedProperty().SetColor(*selected_color)
    slider_rep.GetSliderProperty().SetColor(*color)
    slider_rep.GetLabelProperty().SetShadow(0)
    slider_rep.GetTitleProperty().SetShadow(0)
    class SliderWidget(vtk.vtkSliderWidget):
        def place(self, ren):
            slider_rep = self.GetRepresentation()
            coord2_norm = slider_rep.GetPoint2Coordinate()
            coord2_norm.SetCoordinateSystemToNormalizedDisplay()
            coord2_norm.SetValue(*right_normalized_pos)
            coord2 = coord2_norm.GetComputedDisplayValue(ren)
            slider_rep.GetPoint1Coordinate().SetCoordinateSystemToDisplay()
            slider_rep.GetPoint1Coordinate().SetValue(coord2[0] - size[0],
                                                      coord2[1] - size[1])
            window_size = ren.GetSize()
            length = initial_window_size[0] * 0.04 / window_size[0]
            width = initial_window_size[1] * 0.04 / window_size[1]
            slider_rep.SetSliderLength(length)
            slider_rep.SetSliderWidth(width)
        def set_value(self, value):
            return self.GetSliderRepresentation().SetValue(value)
        def get_value(self):
            return self.GetSliderRepresentation().GetValue()
    slider = SliderWidget()
    slider.SetInteractor(iren)
    slider.SetRepresentation(slider_rep)
    slider.SetAnimationModeToAnimate()
    slider.KeyPressActivationOff()
    slider.AddObserver("InteractionEvent", callback)
    slider.SetEnabled(True)
    # Place widget after window resizing.
    def _place_widget(obj, event):
        slider.place(ren)
    iren.GetRenderWindow().AddObserver(
        vtk.vtkCommand.StartEvent, _place_widget)
    iren.GetRenderWindow().AddObserver(
        vtk.vtkCommand.ModifiedEvent, _place_widget)
    return slider 
[docs]def text(iren, ren, callback, message="FURY",
         left_down_pos=(0.8, 0.5), right_top_pos=(0.9, 0.5),
         color=(1., .5, .0), opacity=1., border=False):
    """ 2D text that can be clicked and process events
    Parameters
    ----------
    iren : vtkRenderWindowInteractor
        Used to process events and handle them to the button. Can also be given
        by the attribute ``ShowManager.iren``.
    ren :  vtkRenderer or Renderer
        Used to update the slider's position when the window changes. Can also
        be given by the ``ShowManager.ren`` attribute.
    callback : function
        Function that has at least ``obj`` and ``event`` as parameters. It will
        be called when the button is pressed.
    message : str
        Message to be shown in the text widget
    left_down_pos : tuple
        Coordinates for left down corner of text. If float are provided,
        the normalized coordinate system is used, otherwise the coordinates
        represent pixel positions. Default is (0.8, 0.5).
    right_top_pos : tuple
        Coordinates for right top corner of text. If float are provided,
        the normalized coordinate system is used, otherwise the coordinates
        represent pixel positions. Default is (0.9, 0.5).
    color : tuple
        Foreground RGB color of text. Default is (1., .5, .0).
    opacity : float
        Takes values from 0 to 1. Default is 1.
    border : bool
        Show text border. Default is False.
    Returns
    -------
    text : TextWidget
        This object inherits from ``vtkTextWidget`` has an additional method
        called ``place`` which allows to update the position of the text if
        necessary.
    """
    # Create the TextActor
    text_actor = vtk.vtkTextActor()
    text_actor.SetInput(message)
    text_actor.GetTextProperty().SetColor(color)
    text_actor.GetTextProperty().SetOpacity(opacity)
    # Create the text representation. Used for positioning the text_actor
    text_rep = vtk.vtkTextRepresentation()
    text_rep.SetTextActor(text_actor)
    if border:
        text_rep.SetShowBorderToOn()
    else:
        text_rep.SetShowBorderToOff()
    class TextWidget(vtk.vtkTextWidget):
        def place(self, renderer):
            text_rep = self.GetRepresentation()
            position = text_rep.GetPositionCoordinate()
            position2 = text_rep.GetPosition2Coordinate()
            # The dtype of `left_down_pos` determines coordinate system type.
            if np.issubdtype(np.asarray(left_down_pos).dtype, np.integer):
                position.SetCoordinateSystemToDisplay()
            else:
                position.SetCoordinateSystemToNormalizedDisplay()
            # The dtype of `right_top_pos` determines coordinate system type.
            if np.issubdtype(np.asarray(right_top_pos).dtype, np.integer):
                position2.SetCoordinateSystemToDisplay()
            else:
                position2.SetCoordinateSystemToNormalizedDisplay()
            position.SetValue(*left_down_pos)
            position2.SetValue(*right_top_pos)
    text_widget = TextWidget()
    text_widget.SetRepresentation(text_rep)
    text_widget.SetInteractor(iren)
    text_widget.SelectableOn()
    text_widget.ResizableOff()
    text_widget.AddObserver(vtk.vtkCommand.WidgetActivateEvent, callback)
    # Place widget after window resizing.
    def _place_widget(obj, event):
        text_widget.place(ren)
    iren.GetRenderWindow().AddObserver(
        vtk.vtkCommand.StartEvent, _place_widget)
    iren.GetRenderWindow().AddObserver(
        vtk.vtkCommand.ModifiedEvent, _place_widget)
    text_widget.On()
    return text_widget