diff options
Diffstat (limited to '')
-rw-r--r-- | app/widgets/gimpdevicestatus.c | 586 |
1 files changed, 586 insertions, 0 deletions
diff --git a/app/widgets/gimpdevicestatus.c b/app/widgets/gimpdevicestatus.c new file mode 100644 index 0000000..3354504 --- /dev/null +++ b/app/widgets/gimpdevicestatus.c @@ -0,0 +1,586 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis + * + * gimpdevicestatus.c + * Copyright (C) 2003 Michael Natterer <mitch@gimp.org> + * + * 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" + +#undef GSEAL_ENABLE + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "widgets-types.h" + +#include "config/gimpguiconfig.h" + +#include "core/gimp.h" +#include "core/gimpbrush.h" +#include "core/gimpcontext.h" +#include "core/gimpdatafactory.h" +#include "core/gimpgradient.h" +#include "core/gimplist.h" +#include "core/gimppattern.h" +#include "core/gimptoolinfo.h" + +#include "gimpdnd.h" +#include "gimpdeviceinfo.h" +#include "gimpdevicemanager.h" +#include "gimpdevices.h" +#include "gimpdevicestatus.h" +#include "gimpdialogfactory.h" +#include "gimppropwidgets.h" +#include "gimpview.h" +#include "gimpwidgets-utils.h" +#include "gimpwindowstrategy.h" + +#include "gimp-intl.h" + + +#define CELL_SIZE 20 /* The size of the view cells */ + + +enum +{ + PROP_0, + PROP_GIMP +}; + + +struct _GimpDeviceStatusEntry +{ + GimpDeviceInfo *device_info; + GimpContext *context; + GimpToolOptions *tool_options; + + GtkWidget *ebox; + GtkWidget *options_hbox; + GtkWidget *tool; + GtkWidget *foreground; + GtkWidget *foreground_none; + GtkWidget *background; + GtkWidget *background_none; + GtkWidget *brush; + GtkWidget *brush_none; + GtkWidget *pattern; + GtkWidget *pattern_none; + GtkWidget *gradient; + GtkWidget *gradient_none; +}; + + +static void gimp_device_status_constructed (GObject *object); +static void gimp_device_status_dispose (GObject *object); +static void gimp_device_status_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void gimp_device_status_device_add (GimpContainer *devices, + GimpDeviceInfo *device_info, + GimpDeviceStatus *status); +static void gimp_device_status_device_remove (GimpContainer *devices, + GimpDeviceInfo *device_info, + GimpDeviceStatus *status); + +static void gimp_device_status_notify_device (GimpDeviceManager *manager, + const GParamSpec *pspec, + GimpDeviceStatus *status); +static void gimp_device_status_config_notify (GimpGuiConfig *config, + const GParamSpec *pspec, + GimpDeviceStatus *status); +static void gimp_device_status_notify_info (GimpDeviceInfo *device_info, + const GParamSpec *pspec, + GimpDeviceStatusEntry *entry); +static void gimp_device_status_save_clicked (GtkWidget *button, + GimpDeviceStatus *status); +static void gimp_device_status_view_clicked (GtkWidget *widget, + GdkModifierType state, + const gchar *identifier); + + +G_DEFINE_TYPE (GimpDeviceStatus, gimp_device_status, GIMP_TYPE_EDITOR) + +#define parent_class gimp_device_status_parent_class + + +static void +gimp_device_status_class_init (GimpDeviceStatusClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = gimp_device_status_constructed; + object_class->dispose = gimp_device_status_dispose; + object_class->set_property = gimp_device_status_set_property; + + g_object_class_install_property (object_class, PROP_GIMP, + g_param_spec_object ("gimp", NULL, NULL, + GIMP_TYPE_GIMP, + GIMP_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gimp_device_status_init (GimpDeviceStatus *status) +{ + status->gimp = NULL; + status->current_device = NULL; + + status->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_set_border_width (GTK_CONTAINER (status->vbox), 2); + gtk_box_pack_start (GTK_BOX (status), status->vbox, TRUE, TRUE, 0); + gtk_widget_show (status->vbox); + + status->save_button = + gimp_editor_add_button (GIMP_EDITOR (status), GIMP_ICON_DOCUMENT_SAVE, + _("Save device status"), NULL, + G_CALLBACK (gimp_device_status_save_clicked), + NULL, + status); +} + +static void +gimp_device_status_constructed (GObject *object) +{ + GimpDeviceStatus *status = GIMP_DEVICE_STATUS (object); + GimpContainer *devices; + GList *list; + + G_OBJECT_CLASS (parent_class)->constructed (object); + + gimp_assert (GIMP_IS_GIMP (status->gimp)); + + devices = GIMP_CONTAINER (gimp_devices_get_manager (status->gimp)); + + for (list = GIMP_LIST (devices)->queue->head; list; list = list->next) + gimp_device_status_device_add (devices, list->data, status); + + g_signal_connect_object (devices, "add", + G_CALLBACK (gimp_device_status_device_add), + status, 0); + g_signal_connect_object (devices, "remove", + G_CALLBACK (gimp_device_status_device_remove), + status, 0); + + g_signal_connect (devices, "notify::current-device", + G_CALLBACK (gimp_device_status_notify_device), + status); + + gimp_device_status_notify_device (GIMP_DEVICE_MANAGER (devices), NULL, status); + + g_signal_connect_object (status->gimp->config, "notify::devices-share-tool", + G_CALLBACK (gimp_device_status_config_notify), + status, 0); + + gimp_device_status_config_notify (GIMP_GUI_CONFIG (status->gimp->config), + NULL, status); +} + +static void +gimp_device_status_dispose (GObject *object) +{ + GimpDeviceStatus *status = GIMP_DEVICE_STATUS (object); + + if (status->devices) + { + GList *list; + + for (list = status->devices; list; list = list->next) + { + GimpDeviceStatusEntry *entry = list->data; + + g_signal_handlers_disconnect_by_func (entry->device_info, + gimp_device_status_notify_info, + entry); + + g_object_unref (entry->context); + g_slice_free (GimpDeviceStatusEntry, entry); + } + + g_list_free (status->devices); + status->devices = NULL; + + g_signal_handlers_disconnect_by_func (gimp_devices_get_manager (status->gimp), + gimp_device_status_notify_device, + status); + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_device_status_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpDeviceStatus *status = GIMP_DEVICE_STATUS (object); + + switch (property_id) + { + case PROP_GIMP: + status->gimp = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +pack_prop_widget (GtkBox *hbox, + GtkWidget *widget, + GtkWidget **none_widget) +{ + GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_group, widget); + gtk_widget_show (widget); + + *none_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (hbox), *none_widget, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_group, *none_widget); + + g_object_unref (size_group); +} + +static void +gimp_device_status_device_add (GimpContainer *devices, + GimpDeviceInfo *device_info, + GimpDeviceStatus *status) +{ + GimpDeviceStatusEntry *entry; + GClosure *closure; + GParamSpec *pspec; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + gchar *name; + + entry = g_slice_new0 (GimpDeviceStatusEntry); + + status->devices = g_list_prepend (status->devices, entry); + + entry->device_info = device_info; + entry->context = gimp_context_new (GIMP_TOOL_PRESET (device_info)->gimp, + gimp_object_get_name (device_info), + NULL); + + gimp_context_define_properties (entry->context, + GIMP_CONTEXT_PROP_MASK_TOOL | + GIMP_CONTEXT_PROP_MASK_FOREGROUND | + GIMP_CONTEXT_PROP_MASK_BACKGROUND | + GIMP_CONTEXT_PROP_MASK_BRUSH | + GIMP_CONTEXT_PROP_MASK_PATTERN | + GIMP_CONTEXT_PROP_MASK_GRADIENT, + FALSE); + + closure = g_cclosure_new (G_CALLBACK (gimp_device_status_notify_info), + entry, NULL); + g_object_watch_closure (G_OBJECT (status), closure); + g_signal_connect_closure (device_info, "notify", closure, + FALSE); + + entry->ebox = gtk_event_box_new (); + gtk_box_pack_start (GTK_BOX (status->vbox), entry->ebox, + FALSE, FALSE, 0); + gtk_widget_show (entry->ebox); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); + gtk_container_add (GTK_CONTAINER (entry->ebox), vbox); + gtk_widget_show (vbox); + + /* the device name */ + + if (device_info->display == NULL || + device_info->display == gdk_display_get_default ()) + name = g_strdup (gimp_object_get_name (device_info)); + else + name = g_strdup_printf ("%s (%s)", + gimp_object_get_name (device_info), + gdk_display_get_name (device_info->display)); + + label = gtk_label_new (name); + g_free (name); + + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); + gimp_label_set_attributes (GTK_LABEL (label), + PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, + -1); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* the row of properties */ + + hbox = entry->options_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + /* the tool */ + + entry->tool = gimp_prop_view_new (G_OBJECT (entry->context), "tool", + entry->context, CELL_SIZE); + gtk_box_pack_start (GTK_BOX (hbox), entry->tool, FALSE, FALSE, 0); + gtk_widget_show (entry->tool); + + /* the foreground color */ + + entry->foreground = gimp_prop_color_area_new (G_OBJECT (entry->context), + "foreground", + CELL_SIZE, CELL_SIZE, + GIMP_COLOR_AREA_FLAT); + gtk_widget_add_events (entry->foreground, + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + pack_prop_widget (GTK_BOX (hbox), entry->foreground, &entry->foreground_none); + + /* the background color */ + + entry->background = gimp_prop_color_area_new (G_OBJECT (entry->context), + "background", + CELL_SIZE, CELL_SIZE, + GIMP_COLOR_AREA_FLAT); + gtk_widget_add_events (entry->background, + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + pack_prop_widget (GTK_BOX (hbox), entry->background, &entry->background_none); + + /* the brush */ + + entry->brush = gimp_prop_view_new (G_OBJECT (entry->context), "brush", + entry->context, CELL_SIZE); + GIMP_VIEW (entry->brush)->clickable = TRUE; + GIMP_VIEW (entry->brush)->show_popup = TRUE; + pack_prop_widget (GTK_BOX (hbox), entry->brush, &entry->brush_none); + + g_signal_connect (entry->brush, "clicked", + G_CALLBACK (gimp_device_status_view_clicked), + "gimp-brush-grid|gimp-brush-list"); + + /* the pattern */ + + entry->pattern = gimp_prop_view_new (G_OBJECT (entry->context), "pattern", + entry->context, CELL_SIZE); + GIMP_VIEW (entry->pattern)->clickable = TRUE; + GIMP_VIEW (entry->pattern)->show_popup = TRUE; + pack_prop_widget (GTK_BOX (hbox), entry->pattern, &entry->pattern_none); + + g_signal_connect (entry->pattern, "clicked", + G_CALLBACK (gimp_device_status_view_clicked), + "gimp-pattern-grid|gimp-pattern-list"); + + /* the gradient */ + + entry->gradient = gimp_prop_view_new (G_OBJECT (entry->context), "gradient", + entry->context, 2 * CELL_SIZE); + GIMP_VIEW (entry->gradient)->clickable = TRUE; + GIMP_VIEW (entry->gradient)->show_popup = TRUE; + pack_prop_widget (GTK_BOX (hbox), entry->gradient, &entry->gradient_none); + + g_signal_connect (entry->gradient, "clicked", + G_CALLBACK (gimp_device_status_view_clicked), + "gimp-gradient-list|gimp-gradient-grid"); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (device_info), + "tool-options"); + gimp_device_status_notify_info (device_info, pspec, entry); +} + +static void +gimp_device_status_device_remove (GimpContainer *devices, + GimpDeviceInfo *device_info, + GimpDeviceStatus *status) +{ + GList *list; + + for (list = status->devices; list; list = list->next) + { + GimpDeviceStatusEntry *entry = list->data; + + if (entry->device_info == device_info) + { + status->devices = g_list_remove (status->devices, entry); + + g_signal_handlers_disconnect_by_func (entry->device_info, + gimp_device_status_notify_info, + entry); + + g_object_unref (entry->context); + g_slice_free (GimpDeviceStatusEntry, entry); + + return; + } + } +} + +GtkWidget * +gimp_device_status_new (Gimp *gimp) +{ + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + + return g_object_new (GIMP_TYPE_DEVICE_STATUS, + "gimp", gimp, + NULL); +} + + +/* private functions */ + +static void +gimp_device_status_notify_device (GimpDeviceManager *manager, + const GParamSpec *pspec, + GimpDeviceStatus *status) +{ + GList *list; + + status->current_device = gimp_device_manager_get_current_device (manager); + + for (list = status->devices; list; list = list->next) + { + GimpDeviceStatusEntry *entry = list->data; + + gtk_widget_set_state (entry->ebox, + entry->device_info == status->current_device ? + GTK_STATE_SELECTED : GTK_STATE_NORMAL); + } +} + +static void +gimp_device_status_config_notify (GimpGuiConfig *config, + const GParamSpec *pspec, + GimpDeviceStatus *status) +{ + gboolean show_options; + GList *list; + + show_options = ! GIMP_GUI_CONFIG (status->gimp->config)->devices_share_tool; + + for (list = status->devices; list; list = list->next) + { + GimpDeviceStatusEntry *entry = list->data; + + gtk_widget_set_visible (entry->options_hbox, show_options); + } +} + +static void +toggle_prop_visible (GtkWidget *widget, + GtkWidget *widget_none, + gboolean available) +{ + gtk_widget_set_visible (widget, available); + gtk_widget_set_visible (widget_none, ! available); +} + +static void +gimp_device_status_notify_info (GimpDeviceInfo *device_info, + const GParamSpec *pspec, + GimpDeviceStatusEntry *entry) +{ + GimpToolOptions *tool_options = GIMP_TOOL_PRESET (device_info)->tool_options; + + if (tool_options != entry->tool_options) + { + GimpContextPropMask serialize_props; + + entry->tool_options = tool_options; + gimp_context_set_parent (entry->context, GIMP_CONTEXT (tool_options)); + + serialize_props = + gimp_context_get_serialize_properties (GIMP_CONTEXT (tool_options)); + + toggle_prop_visible (entry->foreground, + entry->foreground_none, + serialize_props & GIMP_CONTEXT_PROP_MASK_FOREGROUND); + + toggle_prop_visible (entry->background, + entry->background_none, + serialize_props & GIMP_CONTEXT_PROP_MASK_BACKGROUND); + + toggle_prop_visible (entry->brush, + entry->brush_none, + serialize_props & GIMP_CONTEXT_PROP_MASK_BRUSH); + + toggle_prop_visible (entry->pattern, + entry->pattern_none, + serialize_props & GIMP_CONTEXT_PROP_MASK_PATTERN); + + toggle_prop_visible (entry->gradient, + entry->gradient_none, + serialize_props & GIMP_CONTEXT_PROP_MASK_GRADIENT); + } + + if (! gimp_device_info_get_device (device_info, NULL) || + gimp_device_info_get_mode (device_info) == GDK_MODE_DISABLED) + { + gtk_widget_hide (entry->ebox); + } + else + { + gtk_widget_show (entry->ebox); + } + + if (! strcmp (pspec->name, "tool-options")) + { + GimpRGB color; + guchar r, g, b; + gchar buf[64]; + + gimp_context_get_foreground (entry->context, &color); + gimp_rgb_get_uchar (&color, &r, &g, &b); + g_snprintf (buf, sizeof (buf), _("Foreground: %d, %d, %d"), r, g, b); + gimp_help_set_help_data (entry->foreground, buf, NULL); + + gimp_context_get_background (entry->context, &color); + gimp_rgb_get_uchar (&color, &r, &g, &b); + g_snprintf (buf, sizeof (buf), _("Background: %d, %d, %d"), r, g, b); + gimp_help_set_help_data (entry->background, buf, NULL); + } +} + +static void +gimp_device_status_save_clicked (GtkWidget *button, + GimpDeviceStatus *status) +{ + gimp_devices_save (status->gimp, TRUE); +} + +static void +gimp_device_status_view_clicked (GtkWidget *widget, + GdkModifierType state, + const gchar *identifier) +{ + GimpDeviceStatus *status; + GimpDialogFactory *dialog_factory; + + status = GIMP_DEVICE_STATUS (gtk_widget_get_ancestor (widget, + GIMP_TYPE_DEVICE_STATUS)); + dialog_factory = gimp_dialog_factory_get_singleton (); + + gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (status->gimp)), + status->gimp, + dialog_factory, + gtk_widget_get_screen (widget), + gimp_widget_get_monitor (widget), + identifier); +} |