diff options
Diffstat (limited to '')
-rw-r--r-- | app/widgets/gimpdynamicseditor.c | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/app/widgets/gimpdynamicseditor.c b/app/widgets/gimpdynamicseditor.c new file mode 100644 index 0000000..8a8a8a5 --- /dev/null +++ b/app/widgets/gimpdynamicseditor.c @@ -0,0 +1,453 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "libgimpconfig/gimpconfig.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "widgets-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpdynamics.h" + +#include "gimpdocked.h" +#include "gimpdynamicseditor.h" +#include "gimpdynamicsoutputeditor.h" +#include "gimpmenufactory.h" +#include "gimppropwidgets.h" + +#include "gimp-intl.h" + + +/* local function prototypes */ + +static void gimp_dynamics_editor_constructed (GObject *object); +static void gimp_dynamics_editor_finalize (GObject *object); + +static void gimp_dynamics_editor_set_data (GimpDataEditor *editor, + GimpData *data); + +static void gimp_dynamics_editor_notify_model (GimpDynamics *options, + const GParamSpec *pspec, + GimpDynamicsEditor *editor); +static void gimp_dynamics_editor_notify_data (GimpDynamics *options, + const GParamSpec *pspec, + GimpDynamicsEditor *editor); + +static void gimp_dynamics_editor_add_icon_editor (GimpDynamics *dynamics, + Gimp *gimp, + GtkWidget *vbox); + +static void gimp_dynamics_editor_add_output_row (GObject *config, + const gchar *row_label, + GtkTable *table, + gint row); + +static void gimp_dynamics_editor_init_output_editors (GimpDynamics *dynamics, + GtkWidget *view_selector, + GtkWidget *notebook, + GtkWidget *check_grid); + +static GtkWidget * dynamics_check_button_new (GObject *config, + const gchar *property_name, + GtkTable *table, + gint column, + gint row); + +static void gimp_dynamics_editor_view_changed (GtkComboBox *combo, + GtkWidget *notebook); + +G_DEFINE_TYPE_WITH_CODE (GimpDynamicsEditor, gimp_dynamics_editor, + GIMP_TYPE_DATA_EDITOR, + G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED, NULL)) + +#define parent_class gimp_dynamics_editor_parent_class + + +static void +gimp_dynamics_editor_class_init (GimpDynamicsEditorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpDataEditorClass *editor_class = GIMP_DATA_EDITOR_CLASS (klass); + + object_class->constructed = gimp_dynamics_editor_constructed; + object_class->finalize = gimp_dynamics_editor_finalize; + + editor_class->set_data = gimp_dynamics_editor_set_data; + editor_class->title = _("Paint Dynamics Editor"); +} + +static void +gimp_dynamics_editor_init (GimpDynamicsEditor *editor) +{ + GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor); + + editor->dynamics_model = g_object_new (GIMP_TYPE_DYNAMICS, NULL); + + g_signal_connect (editor->dynamics_model, "notify", + G_CALLBACK (gimp_dynamics_editor_notify_model), + editor); + + editor->view_selector = + gimp_enum_combo_box_new (GIMP_TYPE_DYNAMICS_OUTPUT_TYPE); + gtk_box_pack_start (GTK_BOX (data_editor), editor->view_selector, + FALSE, FALSE, 0); + gtk_widget_show (editor->view_selector); + + editor->notebook = gtk_notebook_new (); + gtk_notebook_set_show_border (GTK_NOTEBOOK (editor->notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (editor->notebook), FALSE); + gtk_box_pack_start (GTK_BOX (editor), editor->notebook, TRUE, TRUE, 0); + gtk_widget_show (editor->notebook); +} + +static void +gimp_dynamics_editor_constructed (GObject *object) +{ + GimpDataEditor *data_editor = GIMP_DATA_EDITOR (object); + GimpDynamicsEditor *editor = GIMP_DYNAMICS_EDITOR (object); + GimpDynamics *dynamics = editor->dynamics_model; + GtkWidget *input_labels[7]; + GtkWidget *vbox; + GtkWidget *icon_box; + GtkWidget *table; + gint n_inputs = G_N_ELEMENTS (input_labels); + gint i; + + G_OBJECT_CLASS (parent_class)->constructed (object); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_notebook_append_page (GTK_NOTEBOOK (editor->notebook), + vbox, NULL); + gtk_widget_show (vbox); + + icon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), icon_box, FALSE, FALSE, 0); + gtk_widget_show (icon_box); + + gimp_dynamics_editor_add_icon_editor (dynamics, + data_editor->context->gimp, + vbox); + + table = gtk_table_new (10, n_inputs + 2, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + gimp_dynamics_editor_init_output_editors (dynamics, + editor->view_selector, + editor->notebook, + table); + + input_labels[0] = gtk_label_new (_("Pressure")); + input_labels[1] = gtk_label_new (_("Velocity")); + input_labels[2] = gtk_label_new (_("Direction")); + input_labels[3] = gtk_label_new (_("Tilt")); + input_labels[4] = gtk_label_new (_("Wheel/Rotation")); + input_labels[5] = gtk_label_new (_("Random")); + input_labels[6] = gtk_label_new (_("Fade")); + + for (i = 0; i < n_inputs; i++) + { + gtk_label_set_angle (GTK_LABEL (input_labels[i]), 90); + gtk_label_set_yalign (GTK_LABEL (input_labels[i]), 1.0); + + gtk_table_attach (GTK_TABLE (table), input_labels[i], + i + 1, i + 2, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (input_labels[i]); + } + + gimp_int_combo_box_prepend (GIMP_INT_COMBO_BOX (editor->view_selector), + GIMP_INT_STORE_VALUE, -1, + GIMP_INT_STORE_LABEL, _("Mapping matrix"), + GIMP_INT_STORE_USER_DATA, vbox, + -1); + + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (editor->view_selector), -1); + + gimp_docked_set_show_button_bar (GIMP_DOCKED (object), FALSE); +} + +static void +gimp_dynamics_editor_finalize (GObject *object) +{ + GimpDynamicsEditor *editor = GIMP_DYNAMICS_EDITOR (object); + + g_clear_object (&editor->dynamics_model); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_dynamics_editor_set_data (GimpDataEditor *editor, + GimpData *data) +{ + GimpDynamicsEditor *dynamics_editor = GIMP_DYNAMICS_EDITOR (editor); + + if (editor->data) + g_signal_handlers_disconnect_by_func (editor->data, + gimp_dynamics_editor_notify_data, + editor); + + GIMP_DATA_EDITOR_CLASS (parent_class)->set_data (editor, data); + + if (editor->data) + { + g_signal_handlers_block_by_func (dynamics_editor->dynamics_model, + gimp_dynamics_editor_notify_model, + editor); + + gimp_config_copy (GIMP_CONFIG (editor->data), + GIMP_CONFIG (dynamics_editor->dynamics_model), + GIMP_CONFIG_PARAM_SERIALIZE); + + g_signal_handlers_unblock_by_func (dynamics_editor->dynamics_model, + gimp_dynamics_editor_notify_model, + editor); + + g_signal_connect (editor->data, "notify", + G_CALLBACK (gimp_dynamics_editor_notify_data), + editor); + } + + gtk_widget_set_sensitive (dynamics_editor->notebook, editor->data_editable); +} + + +/* public functions */ + +GtkWidget * +gimp_dynamics_editor_new (GimpContext *context, + GimpMenuFactory *menu_factory) +{ + g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + + return g_object_new (GIMP_TYPE_DYNAMICS_EDITOR, + "menu-factory", menu_factory, + "menu-identifier", "<DynamicsEditor>", + "ui-path", "/dynamics-editor-popup", + "data-factory", context->gimp->dynamics_factory, + "context", context, + "data", gimp_context_get_dynamics (context), + NULL); +} + + +/* private functions */ + +static void +gimp_dynamics_editor_notify_model (GimpDynamics *options, + const GParamSpec *pspec, + GimpDynamicsEditor *editor) +{ + GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor); + + if (data_editor->data) + { + g_signal_handlers_block_by_func (data_editor->data, + gimp_dynamics_editor_notify_data, + editor); + + gimp_config_copy (GIMP_CONFIG (editor->dynamics_model), + GIMP_CONFIG (data_editor->data), + GIMP_CONFIG_PARAM_SERIALIZE); + + g_signal_handlers_unblock_by_func (data_editor->data, + gimp_dynamics_editor_notify_data, + editor); + } +} + +static void +gimp_dynamics_editor_notify_data (GimpDynamics *options, + const GParamSpec *pspec, + GimpDynamicsEditor *editor) +{ + GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor); + + g_signal_handlers_block_by_func (editor->dynamics_model, + gimp_dynamics_editor_notify_model, + editor); + + gimp_config_copy (GIMP_CONFIG (data_editor->data), + GIMP_CONFIG (editor->dynamics_model), + GIMP_CONFIG_PARAM_SERIALIZE); + + g_signal_handlers_unblock_by_func (editor->dynamics_model, + gimp_dynamics_editor_notify_model, + editor); +} + +static void +gimp_dynamics_editor_add_icon_editor (GimpDynamics *dynamics, + Gimp *gimp, + GtkWidget *vbox) +{ + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *button; + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (_("Icon:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + button = gimp_prop_icon_picker_new (GIMP_VIEWABLE (dynamics), gimp); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); +} + +static void +gimp_dynamics_editor_add_output_row (GObject *config, + const gchar *row_label, + GtkTable *table, + gint row) +{ + GtkWidget *label; + gint column = 1; + + label = gtk_label_new (row_label); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + dynamics_check_button_new (config, "use-pressure", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-velocity", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-direction", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-tilt", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-wheel", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-random", + table, column, row); + column++; + + dynamics_check_button_new (config, "use-fade", + table, column, row); + column++; +} + +static GtkWidget * +dynamics_check_button_new (GObject *config, + const gchar *property_name, + GtkTable *table, + gint column, + gint row) +{ + GtkWidget *button; + + button = gimp_prop_check_button_new (config, property_name, NULL); + gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (button))); + gtk_table_attach (table, button, column, column + 1, row, row + 1, + GTK_SHRINK, GTK_SHRINK, 0, 0); + gtk_widget_show (button); + + return button; +} + +static void +gimp_dynamics_editor_init_output_editors (GimpDynamics *dynamics, + GtkWidget *view_selector, + GtkWidget *notebook, + GtkWidget *check_grid) +{ + GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (view_selector)); + GimpIntStore *list = GIMP_INT_STORE (model); + GtkTreeIter iter; + gboolean iter_valid; + gint i; + + for (iter_valid = gtk_tree_model_get_iter_first (model, &iter), i = 1; + iter_valid; + iter_valid = gtk_tree_model_iter_next (model, &iter), i++) + { + gint output_type; + gchar *label; + GimpDynamicsOutput *output; + GtkWidget *output_editor; + + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, + GIMP_INT_STORE_VALUE, &output_type, + GIMP_INT_STORE_LABEL, &label, + -1); + + output = gimp_dynamics_get_output (dynamics, output_type); + + output_editor = gimp_dynamics_output_editor_new (output); + + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), output_editor, NULL); + gtk_widget_show (output_editor); + + gtk_list_store_set (GTK_LIST_STORE (list), &iter, + GIMP_INT_STORE_USER_DATA, output_editor, + -1); + + gimp_dynamics_editor_add_output_row (G_OBJECT (output), + label, + GTK_TABLE (check_grid), + i); + + g_free (label); + } + + g_signal_connect (G_OBJECT (view_selector), "changed", + G_CALLBACK (gimp_dynamics_editor_view_changed), + notebook); +} + +static void +gimp_dynamics_editor_view_changed (GtkComboBox *combo, + GtkWidget *notebook) +{ + GtkTreeModel *model = gtk_combo_box_get_model (combo); + GtkTreeIter iter; + gpointer widget; + gint page; + + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter); + + gtk_tree_model_get (model, &iter, + GIMP_INT_STORE_USER_DATA, &widget, + -1); + page = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), widget); + + gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page); +} |