/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * pikatooloptionseditor.c * Copyright (C) 2003 Michael Natterer * * 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 . */ #include "config.h" #include #include #include "libpikabase/pikabase.h" #include "libpikawidgets/pikawidgets.h" #include "widgets-types.h" #include "core/pika.h" #include "core/pikacontext.h" #include "core/pikalist.h" #include "core/pikatoolinfo.h" #include "core/pikatooloptions.h" #include "pikadnd.h" #include "pikadocked.h" #include "pikahelp-ids.h" #include "pikamenufactory.h" #include "pikapropwidgets.h" #include "pikaview.h" #include "pikaviewrenderer.h" #include "pikatooloptionseditor.h" #include "pikauimanager.h" #include "pikawidgets-utils.h" #include "pika-intl.h" enum { PROP_0, PROP_PIKA, }; struct _PikaToolOptionsEditorPrivate { Pika *pika; GtkWidget *scrolled_window; GtkWidget *options_vbox; GtkWidget *title_label; GtkWidget *save_button; GtkWidget *restore_button; GtkWidget *delete_button; GtkWidget *reset_button; PikaToolOptions *visible_tool_options; }; static void pika_tool_options_editor_docked_iface_init (PikaDockedInterface *iface); static void pika_tool_options_editor_constructed (GObject *object); static void pika_tool_options_editor_dispose (GObject *object); static void pika_tool_options_editor_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void pika_tool_options_editor_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static GtkWidget * pika_tool_options_editor_get_preview (PikaDocked *docked, PikaContext *context, GtkIconSize size); static gchar * pika_tool_options_editor_get_title (PikaDocked *docked); static gboolean pika_tool_options_editor_get_prefer_icon (PikaDocked *docked); static void pika_tool_options_editor_save_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor); static void pika_tool_options_editor_restore_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor); static void pika_tool_options_editor_delete_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor); static void pika_tool_options_editor_drop_tool (GtkWidget *widget, gint x, gint y, PikaViewable *viewable, gpointer data); static void pika_tool_options_editor_tool_changed (PikaContext *context, PikaToolInfo *tool_info, PikaToolOptionsEditor *editor); static void pika_tool_options_editor_presets_update (PikaToolOptionsEditor *editor); G_DEFINE_TYPE_WITH_CODE (PikaToolOptionsEditor, pika_tool_options_editor, PIKA_TYPE_EDITOR, G_ADD_PRIVATE (PikaToolOptionsEditor) G_IMPLEMENT_INTERFACE (PIKA_TYPE_DOCKED, pika_tool_options_editor_docked_iface_init)) #define parent_class pika_tool_options_editor_parent_class static void pika_tool_options_editor_class_init (PikaToolOptionsEditorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = pika_tool_options_editor_constructed; object_class->dispose = pika_tool_options_editor_dispose; object_class->set_property = pika_tool_options_editor_set_property; object_class->get_property = pika_tool_options_editor_get_property; g_object_class_install_property (object_class, PROP_PIKA, g_param_spec_object ("pika", NULL, NULL, PIKA_TYPE_PIKA, PIKA_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } static void pika_tool_options_editor_docked_iface_init (PikaDockedInterface *docked_iface) { docked_iface->get_preview = pika_tool_options_editor_get_preview; docked_iface->get_title = pika_tool_options_editor_get_title; docked_iface->get_prefer_icon = pika_tool_options_editor_get_prefer_icon; } static void pika_tool_options_editor_init (PikaToolOptionsEditor *editor) { GtkScrolledWindow *scrolled_window; editor->p = pika_tool_options_editor_get_instance_private (editor); gtk_widget_set_size_request (GTK_WIDGET (editor), -1, 200); pika_dnd_viewable_dest_add (GTK_WIDGET (editor), PIKA_TYPE_TOOL_INFO, pika_tool_options_editor_drop_tool, editor); /* The label containing the tool options title */ editor->p->title_label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (editor->p->title_label), 0.0); pika_label_set_attributes (GTK_LABEL (editor->p->title_label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); gtk_box_pack_start (GTK_BOX (editor), editor->p->title_label, FALSE, FALSE, 0); gtk_widget_show (editor->p->title_label); editor->p->scrolled_window = gtk_scrolled_window_new (NULL, NULL); scrolled_window = GTK_SCROLLED_WINDOW (editor->p->scrolled_window); gtk_scrolled_window_set_policy (scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_overlay_scrolling (scrolled_window, FALSE); gtk_box_pack_start (GTK_BOX (editor), editor->p->scrolled_window, TRUE, TRUE, 0); gtk_widget_show (editor->p->scrolled_window); /* The vbox containing the tool options */ editor->p->options_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (scrolled_window), editor->p->options_vbox); gtk_widget_show (editor->p->options_vbox); } static void pika_tool_options_editor_constructed (GObject *object) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (object); PikaContext *user_context; G_OBJECT_CLASS (parent_class)->constructed (object); editor->p->save_button = pika_editor_add_button (PIKA_EDITOR (editor), PIKA_ICON_DOCUMENT_SAVE, _("Save Tool Preset..."), PIKA_HELP_TOOL_OPTIONS_SAVE, G_CALLBACK (pika_tool_options_editor_save_clicked), NULL, G_OBJECT (editor)); editor->p->restore_button = pika_editor_add_button (PIKA_EDITOR (editor), PIKA_ICON_DOCUMENT_REVERT, _("Restore Tool Preset..."), PIKA_HELP_TOOL_OPTIONS_RESTORE, G_CALLBACK (pika_tool_options_editor_restore_clicked), NULL, G_OBJECT (editor)); editor->p->delete_button = pika_editor_add_button (PIKA_EDITOR (editor), PIKA_ICON_EDIT_DELETE, _("Delete Tool Preset..."), PIKA_HELP_TOOL_OPTIONS_DELETE, G_CALLBACK (pika_tool_options_editor_delete_clicked), NULL, G_OBJECT (editor)); editor->p->reset_button = pika_editor_add_action_button (PIKA_EDITOR (editor), "tool-options", "tool-options-reset", "tool-options-reset-all", GDK_SHIFT_MASK, NULL); user_context = pika_get_user_context (editor->p->pika); g_signal_connect_object (user_context, "tool-changed", G_CALLBACK (pika_tool_options_editor_tool_changed), editor, 0); pika_tool_options_editor_tool_changed (user_context, pika_context_get_tool (user_context), editor); } static void pika_tool_options_editor_dispose (GObject *object) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (object); if (editor->p->options_vbox) { GList *options; GList *list; options = gtk_container_get_children (GTK_CONTAINER (editor->p->options_vbox)); for (list = options; list; list = g_list_next (list)) { gtk_container_remove (GTK_CONTAINER (editor->p->options_vbox), GTK_WIDGET (list->data)); } g_list_free (options); editor->p->options_vbox = NULL; } G_OBJECT_CLASS (parent_class)->dispose (object); } static void pika_tool_options_editor_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (object); switch (property_id) { case PROP_PIKA: editor->p->pika = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_tool_options_editor_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (object); switch (property_id) { case PROP_PIKA: g_value_set_object (value, editor->p->pika); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GtkWidget * pika_tool_options_editor_get_preview (PikaDocked *docked, PikaContext *context, GtkIconSize size) { GtkWidget *view; gint width; gint height; gtk_icon_size_lookup (size, &width, &height); view = pika_prop_view_new (G_OBJECT (context), "tool", context, height); PIKA_VIEW (view)->renderer->size = -1; pika_view_renderer_set_size_full (PIKA_VIEW (view)->renderer, width, height, 0); return view; } static gchar * pika_tool_options_editor_get_title (PikaDocked *docked) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (docked); PikaContext *context; PikaToolInfo *tool_info; context = pika_get_user_context (editor->p->pika); tool_info = pika_context_get_tool (context); return tool_info ? g_strdup (tool_info->label) : NULL; } static gboolean pika_tool_options_editor_get_prefer_icon (PikaDocked *docked) { /* We support get_preview() for tab tyles, but we prefer to show our * icon */ return TRUE; } /* public functions */ GtkWidget * pika_tool_options_editor_new (Pika *pika, PikaMenuFactory *menu_factory) { g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL); g_return_val_if_fail (PIKA_IS_MENU_FACTORY (menu_factory), NULL); return g_object_new (PIKA_TYPE_TOOL_OPTIONS_EDITOR, "pika", pika, "menu-factory", menu_factory, "menu-identifier", "", "ui-path", "/tool-options-popup", NULL); } PikaToolOptions * pika_tool_options_editor_get_tool_options (PikaToolOptionsEditor *editor) { g_return_val_if_fail (PIKA_IS_TOOL_OPTIONS_EDITOR (editor), NULL); return editor->p->visible_tool_options; } /* private functions */ static void pika_tool_options_editor_menu_popup (PikaToolOptionsEditor *editor, GtkWidget *button, const gchar *path) { PikaEditor *pika_editor = PIKA_EDITOR (editor); pika_ui_manager_update (pika_editor_get_ui_manager (pika_editor), pika_editor_get_popup_data (pika_editor)); pika_ui_manager_ui_popup_at_widget (pika_editor_get_ui_manager (pika_editor), path, NULL, NULL, button, GDK_GRAVITY_WEST, GDK_GRAVITY_NORTH_EAST, NULL, NULL, NULL); } static void pika_tool_options_editor_save_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor) { if (gtk_widget_get_sensitive (editor->p->restore_button) /* evil but correct */) { pika_tool_options_editor_menu_popup (editor, widget, "/tool-options-popup/Tool Options Menu/Save Tool Preset"); } else { pika_ui_manager_activate_action (pika_editor_get_ui_manager (PIKA_EDITOR (editor)), "tool-options", "tool-options-save-new-preset"); } } static void pika_tool_options_editor_restore_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor) { pika_tool_options_editor_menu_popup (editor, widget, "/tool-options-popup/Tool Options Menu/Restore Tool Preset"); } static void pika_tool_options_editor_delete_clicked (GtkWidget *widget, PikaToolOptionsEditor *editor) { pika_tool_options_editor_menu_popup (editor, widget, "/tool-options-popup/Tool Options Menu/Delete Tool Preset"); } static void pika_tool_options_editor_drop_tool (GtkWidget *widget, gint x, gint y, PikaViewable *viewable, gpointer data) { PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (data); PikaContext *context; context = pika_get_user_context (editor->p->pika); pika_context_set_tool (context, PIKA_TOOL_INFO (viewable)); } static void pika_tool_options_editor_tool_changed (PikaContext *context, PikaToolInfo *tool_info, PikaToolOptionsEditor *editor) { PikaContainer *presets; GtkWidget *options_gui; if (tool_info && tool_info->tool_options == editor->p->visible_tool_options) return; if (editor->p->visible_tool_options) { presets = editor->p->visible_tool_options->tool_info->presets; if (presets) g_signal_handlers_disconnect_by_func (presets, pika_tool_options_editor_presets_update, editor); options_gui = pika_tools_get_tool_options_gui (editor->p->visible_tool_options); if (options_gui) gtk_widget_hide (options_gui); editor->p->visible_tool_options = NULL; } if (tool_info && tool_info->tool_options) { presets = tool_info->presets; if (presets) { g_signal_connect_object (presets, "add", G_CALLBACK (pika_tool_options_editor_presets_update), G_OBJECT (editor), G_CONNECT_SWAPPED); g_signal_connect_object (presets, "remove", G_CALLBACK (pika_tool_options_editor_presets_update), G_OBJECT (editor), G_CONNECT_SWAPPED); g_signal_connect_object (presets, "thaw", G_CALLBACK (pika_tool_options_editor_presets_update), G_OBJECT (editor), G_CONNECT_SWAPPED); } options_gui = pika_tools_get_tool_options_gui (tool_info->tool_options); if (! gtk_widget_get_parent (options_gui)) gtk_box_pack_start (GTK_BOX (editor->p->options_vbox), options_gui, FALSE, FALSE, 0); gtk_widget_show (options_gui); editor->p->visible_tool_options = tool_info->tool_options; pika_help_set_help_data (editor->p->scrolled_window, NULL, tool_info->help_id); pika_tool_options_editor_presets_update (editor); } if (editor->p->title_label != NULL) { gchar *title; title = pika_docked_get_title (PIKA_DOCKED (editor)); gtk_label_set_text (GTK_LABEL (editor->p->title_label), title); g_free (title); } pika_docked_title_changed (PIKA_DOCKED (editor)); } static void pika_tool_options_editor_presets_update (PikaToolOptionsEditor *editor) { PikaToolInfo *tool_info = editor->p->visible_tool_options->tool_info; gboolean save_sensitive = FALSE; gboolean restore_sensitive = FALSE; gboolean delete_sensitive = FALSE; gboolean reset_sensitive = FALSE; if (tool_info->presets) { save_sensitive = TRUE; reset_sensitive = TRUE; if (! pika_container_is_empty (tool_info->presets)) { restore_sensitive = TRUE; delete_sensitive = TRUE; } } gtk_widget_set_sensitive (editor->p->save_button, save_sensitive); gtk_widget_set_sensitive (editor->p->restore_button, restore_sensitive); gtk_widget_set_sensitive (editor->p->delete_button, delete_sensitive); gtk_widget_set_sensitive (editor->p->reset_button, reset_sensitive); }