Exemplo n.º 1
0
    def __init__(self, master, vtk_table, on_change_color_table=None):
        """Initialize the gradient editor window.

        Parameters
        ----------
        master
            Owning widget, for example a tk root object.
        VtkTable
            Instance of vtkLookupTable, designating the table which is
            to be edited.
        OnChangeColorTable
            Callback function taking no arguments. Called
            when the color table was changed and rendering is requested."""

        # Inner dimensions of the color control gui-elements in pixels.
        gradient_preview_width = 300
        gradient_preview_height = 50
        channel_function_width = gradient_preview_width
        channel_function_height = 80

        tk.Toplevel.__init__(self, master)
        self.title("Color Gradient Editor")
        self.minsize( gradient_preview_width+4, gradient_preview_height + 5 * \
                      channel_function_height + 50 )

        self.gradient_table = GradientTable(gradient_preview_width)
        self.vtk_color_table = vtk_table

        # create controls.
        self.gradient_control = GradientControl(self, self.gradient_table,
                                                gradient_preview_width,
                                                gradient_preview_height)
        self.gradient_control.grid(row=0, column=1, sticky="we")

        def on_gradient_table_changed(final_update):
            # update all function controls.
            self.function_control_rgb.update()
            for control in self.function_controls_hsv:
                control.update()
            # repaint the gradient display or the external windows only
            # when the instant*** options are set or when the update was final.
            if final_update or (1 == self.show_instant_gradients.get()):
                self.gradient_control.update()

            if final_update or (1 == self.show_instant_feedback.get()):
                self.gradient_table.store_to_vtk_lookup_table(
                    self.vtk_color_table)
                on_change_color_table()

        self.on_gradient_table_changed = on_gradient_table_changed

        self.function_control_rgb = FunctionControl(self, self.gradient_table,
                                                    "rgb",
                                                    channel_function_width,
                                                    channel_function_height,
                                                    on_gradient_table_changed)
        label = tk.Label(self, text="rgb")
        label.grid(row=1, column=0)
        self.function_control_rgb.grid(row=1, column=1, sticky="we")
        self.function_controls_hsv = []
        for it in [("hue", 2), ("sat", 3), ("val", 4), ("alp", 5)]:
            control = FunctionControl(self, self.gradient_table, it[0][0],
                                      channel_function_width,
                                      channel_function_height,
                                      on_gradient_table_changed)
            control.grid(row=it[1], column=1, sticky="we")
            self.function_controls_hsv.append(control)

            label = tk.Label(self, text=it[0])
            label.grid(row=it[1], column=0)

        # buttons and the instruction label get into an own subframe for
        # easier control.
        button_frame = tk.Frame(self)
        button_frame.grid(row=6, column=0, columnspan=2)

        ok_button = tk.Button(button_frame, text="ok", command=self.ok)
        ok_button.grid(row=0, column=1)
        #CancelButton = tk.Button(ButtonFrame, text="cancel", command=self.Cancel)
        #CancelButton.grid(row=0,column=2)
        spacer = tk.Frame(button_frame, width=10)
        spacer.grid(row=0, column=3)
        save_button = tk.Button(button_frame,
                                text="save",
                                command=self.save_gradient)
        save_button.grid(row=0, column=4)
        load_button = tk.Button(button_frame,
                                text="load",
                                command=self.load_gradient)
        load_button.grid(row=0, column=5)
        spacer = tk.Frame(button_frame, width=10)
        spacer.grid(row=0, column=6)
        label = tk.Label(button_frame, text="instant:")
        label.grid(row=0, column=7)

        # these two buttons control whether gradient and render target
        # updates are executed during movement of control points or
        # only at the end of such changes.
        self.show_instant_gradients = tk.IntVar()
        self.show_instant_gradients.set(
            1)  # enable instant gradients by default
        self.show_instant_feedback = tk.IntVar()
        self.show_instant_feedback.set(
            0)  # disable instant feedback by default
        instant_gradient_button = tk.Checkbutton(button_frame, text="grad")
        instant_gradient_button.grid(row=0, column=8)
        instant_gradient_button.configure(variable=self.show_instant_gradients)
        instant_feedback_button = tk.Checkbutton(button_frame, text="feed")
        instant_feedback_button.grid(row=0, column=9)
        instant_feedback_button.configure(variable=self.show_instant_feedback)

        instruction_label = tk.Label(
            button_frame,
            text="left button: move point; right click: toggle point")
        instruction_label.grid(column=0, columnspan=9, row=1)

        # insert a ratio button which decides whether the controls for nonlinear
        # scaling of the gradient are shown and activated.
        self.nonlinear_scaling_enabled = tk.IntVar()
        self.nonlinear_scaling_enabled.set(0)
        nonlinear_enabled_button = tk.Checkbutton(button_frame, text="nonlin")
        nonlinear_enabled_button.grid(column=9, row=1)
        nonlinear_enabled_button.configure(
            variable=self.nonlinear_scaling_enabled,
            command=self.nonlinear_scaling_option_changed)

        # the controls for the nonlinear scaling also get into an own frame.
        # this one can be shown or hidden when the "nonlin"-button is pressed
        nonlin_frame = tk.Frame(self)
        self.nonlin_frame = nonlin_frame

        label = tk.Label(nonlin_frame, text="f(x) =")
        label.grid(row=0, column=0)
        self.nonlinear_function_string = tk.StringVar()
        self.nonlinear_function_string.set("x**(4*a)")
        function_edit = tk.Entry(nonlin_frame,
                                 width=35,
                                 textvariable=self.nonlinear_function_string)
        function_edit.bind("<Return>", self.nonlinear_function_string_changed)
        function_edit.grid(row=0, column=1)

        label = tk.Label(nonlin_frame, text="param a:")
        label.grid(row=1, column=0)
        self.parameter_scale = tk.Scale(nonlin_frame,
                                        from_=0.0,
                                        to=1.0,
                                        resolution=0.001,
                                        length=250,
                                        orient="horizontal")
        self.parameter_scale.bind(
            "<ButtonRelease>", lambda event: self.
            nonlinear_parameter_scale_changed(final_update=True))
        self.parameter_scale.bind(
            "<Motion>", lambda event: self.nonlinear_parameter_scale_changed(
                final_update=False))
        self.parameter_scale.set(0.5)
        self.parameter_scale.grid(row=1, column=1)
        label = tk.Label(nonlin_frame, text= \
                "f(x) should map [0..1] to [0..1]. It rescales the gradient.")
        label.grid(column=0, columnspan=2, row=2)

        # finally, write the current gradient out into main program
        on_gradient_table_changed(final_update=True)
Exemplo n.º 2
0
    def __init__(self, master, vtk_table, on_change_color_table=None,
                 colors=None):
        """

        Parameters:
        -----------
        
        vtk_table : the `tvtk.LookupTable` or `tvtk.VolumeProperty` object
                    to set.
        
        on_change_color_table : A callback called when the color table
                                changes.
        
        colors : list of 'rgb', 'hsv', 'h', 's', 'v', 'a'
                 (Default : ['rgb', 'hsv', 'a'])

                 'rgb' creates one panel to edit Red, Green and Blue
                 colors.

                 'hsv' creates one panel to edit Hue, Saturation and
                 Value.

                 'h', 's', 'v', 'r', 'g', 'b', 'a' separately
                 specified creates different panels for each.
        """
        wx.Panel.__init__(self, master)

        if colors is None:
            colors = ['rgb', 'hsv', 'a']
        
        gradient_preview_width = 300
        gradient_preview_height = 50
        channel_function_width = gradient_preview_width
        channel_function_height = 80
        self.gradient_table = GradientTable(gradient_preview_width)
        self.vtk_color_table = vtk_table
        if isinstance(vtk_table, tvtk.LookupTable):
            self.vtk_table_is_lut = True
        else:
            # This is a tvtk.VolumeProperty
            self.vtk_table_is_lut = False
            # Initialize the editor with the volume property. 
            self.gradient_table.load_from_vtk_volume_prop(vtk_table)

        self.on_change_color_table = on_change_color_table

        # set up all the panels in a gridbagsizer (i.e. a big grid)
        # 6x2 size:  6 rows, 2 columns...
        sizer = wx.GridBagSizer(2, 2)

        # "Gradient Viewer" panel, in position (0,1) for sizer
        self.gradient_control = wxGradientControl(self,
                                                  self.gradient_table,
                                                  gradient_preview_width,
                                                  gradient_preview_height)
        tt = wx.ToolTip('Right click for menu')
        self.gradient_control.Bind(wx.EVT_CONTEXT_MENU, self.on_gradient_menu)
        self.gradient_control.SetToolTip(tt)
        sizer.Add(self.gradient_control, pos=(0,1))

        
        # Add the function controls:
        function_controls = []
        self.function_controls = function_controls

        tooltip_text = 'Left click: move control points\n'\
                       'Right click: add/remove control points'
        editor_data = {'rgb': ('', 'RGB'),
                       'hsv': ('Hue: Red; Saturation: Green; '\
                               'Value: Blue\n',                   
                               'HSV'
                               ),
                       'h': ('', 'HUE'),
                       's': ('', 'SAT'),
                       'v': ('', 'VAL'),
                       'r': ('', 'RED'),
                       'g': ('', 'GREEN'),
                       'b': ('', 'BLUE'),
                       'a': ('', 'ALPHA'),
                       }
        row = 1
        for color in colors:
            data = editor_data[color]
            control = wxFunctionControl(self, self.gradient_table, color,
                                        channel_function_width,
                                        channel_function_height)
            txt = data[0] + tooltip_text
            control.SetToolTip(wx.ToolTip(txt))
            # Add name of editor (to left side of editor)
            sizer.Add(wx.StaticText(self, -1, data[1]), pos=(row, 0),
                      flag=wx.ALIGN_CENTER|wx.ALL)
            # Add the "RGB" control point editor
            sizer.Add(control, pos=(row, 1))
            function_controls.append(control)
            row += 1

        # The status text.
        self.text = wx.StaticText(self, -1, 'status')
        sizer.Add(self.text, (row,0), (row,2))
        row += 1

        # set the appropriate sizer.
        sizer.SetSizeHints(self)
        self.SetSizerAndFit(sizer)