From 4c03f0156cbca3223a0d66dfb7104c907f2302bd Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Mon, 31 May 2004 17:53:25 +0000 Subject: [PATCH] app/widgets/Makefile.am app/widgets/widgets-types.h added new widget 2004-05-31 Sven Neumann * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpcontainerentry.[ch]: added new widget GimpContainerEntry, a GtkEntry with completion that implements the GimpContainerView interface. * app/tools/gimptextoptions.c (gimp_text_options_gui): added a GimpContainerEntry to select the font. --- ChangeLog | 11 + app/tools/gimptextoptions.c | 21 +- app/widgets/Makefile.am | 2 + app/widgets/gimpcontainerentry.c | 461 +++++++++++++++++++++++++++++++ app/widgets/gimpcontainerentry.h | 58 ++++ app/widgets/widgets-types.h | 1 + 6 files changed, 548 insertions(+), 6 deletions(-) create mode 100644 app/widgets/gimpcontainerentry.c create mode 100644 app/widgets/gimpcontainerentry.h diff --git a/ChangeLog b/ChangeLog index b57590410b..172a404dc6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-05-31 Sven Neumann + + * app/widgets/Makefile.am + * app/widgets/widgets-types.h + * app/widgets/gimpcontainerentry.[ch]: added new widget + GimpContainerEntry, a GtkEntry with completion that implements the + GimpContainerView interface. + + * app/tools/gimptextoptions.c (gimp_text_options_gui): added a + GimpContainerEntry to select the font. + 2004-05-31 Sven Neumann * app/Makefile.am diff --git a/app/tools/gimptextoptions.c b/app/tools/gimptextoptions.c index 82b07dd0c1..194a8194b0 100644 --- a/app/tools/gimptextoptions.c +++ b/app/tools/gimptextoptions.c @@ -38,6 +38,7 @@ #include "text/gimptext.h" #include "widgets/gimpcolorpanel.h" +#include "widgets/gimpcontainerentry.h" #include "widgets/gimpdialogfactory.h" #include "widgets/gimppropwidgets.h" #include "widgets/gimptexteditor.h" @@ -396,6 +397,7 @@ gimp_text_options_gui (GimpToolOptions *tool_options) GObject *config; GtkWidget *vbox; GtkWidget *table; + GtkWidget *hbox; GtkWidget *button; GimpDialogFactory *dialog_factory; GtkWidget *auto_button; @@ -417,6 +419,11 @@ gimp_text_options_gui (GimpToolOptions *tool_options) gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); gtk_widget_show (table); + hbox = gtk_hbox_new (FALSE, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, row++, + _("_Font:"), 0.0, 0.5, + hbox, 2, FALSE); + button = gimp_viewable_button_new (GIMP_CONTEXT (options)->gimp->fonts, GIMP_CONTEXT (options), GIMP_PREVIEW_SIZE_SMALL, 1, @@ -424,20 +431,22 @@ gimp_text_options_gui (GimpToolOptions *tool_options) "gimp-font-list|gimp-font-grid", GIMP_STOCK_FONT, _("Open the font selection dialog")); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); - gimp_table_attach_aligned (GTK_TABLE (table), 0, row++, - _("_Font:"), 0.0, 0.5, - button, 2, TRUE); + entry = gimp_container_entry_new (GIMP_CONTEXT (options)->gimp->fonts, + GIMP_CONTEXT (options), + GIMP_PREVIEW_SIZE_SMALL, 1); + gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); + gtk_widget_show (entry); entry = gimp_prop_size_entry_new (config, "font-size", "font-size-unit", "%a", GIMP_SIZE_ENTRY_UPDATE_SIZE, 72.0); - gimp_table_attach_aligned (GTK_TABLE (table), 0, row, + gimp_table_attach_aligned (GTK_TABLE (table), 0, row++, _("_Size:"), 0.0, 0.5, entry, 2, FALSE); - gtk_widget_show (entry); - row++; options->size_entry = GIMP_SIZE_ENTRY (entry); diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am index 6970a42940..2550328802 100644 --- a/app/widgets/Makefile.am +++ b/app/widgets/Makefile.am @@ -57,6 +57,8 @@ libappwidgets_a_sources = \ gimpcontainercombobox.h \ gimpcontainereditor.c \ gimpcontainereditor.h \ + gimpcontainerentry.c \ + gimpcontainerentry.h \ gimpcontainergridview.c \ gimpcontainergridview.h \ gimpcontainerpopup.c \ diff --git a/app/widgets/gimpcontainerentry.c b/app/widgets/gimpcontainerentry.c new file mode 100644 index 0000000000..955328f488 --- /dev/null +++ b/app/widgets/gimpcontainerentry.c @@ -0,0 +1,461 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcontainerentry.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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#include "widgets-types.h" + +#include "core/gimpcontainer.h" +#include "core/gimpcontext.h" +#include "core/gimpviewable.h" + +#include "gimpcellrendererviewable.h" +#include "gimpcontainerentry.h" +#include "gimpcontainerview.h" +#include "gimppreviewrenderer.h" + + +#define gimp_container_entry_get_model(entry) \ + gtk_entry_completion_get_model (gtk_entry_get_completion (GTK_ENTRY (entry))) + + +enum +{ + COLUMN_RENDERER, + COLUMN_NAME, + NUM_COLUMNS +}; + + +static void gimp_container_entry_class_init (GimpContainerEntryClass *klass); +static void gimp_container_entry_init (GimpContainerEntry *view); + +static void gimp_container_entry_view_iface_init (GimpContainerViewInterface *view_iface); + +static gpointer gimp_container_entry_insert_item (GimpContainerView *view, + GimpViewable *viewable, + gint index); +static void gimp_container_entry_remove_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data); +static void gimp_container_entry_reorder_item (GimpContainerView *view, + GimpViewable *viewable, + gint new_index, + gpointer insert_data); +static void gimp_container_entry_rename_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data); +static gboolean gimp_container_entry_select_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data); +static void gimp_container_entry_clear_items (GimpContainerView *view); +static void gimp_container_entry_set_preview_size (GimpContainerView *view); + +static void gimp_container_entry_changed (GtkEntry *entry, + GimpContainerView *view); +static void gimp_container_entry_renderer_update (GimpPreviewRenderer *renderer, + GimpContainerView *view); + + +static GtkEntryClass *parent_class = NULL; +static GimpContainerViewInterface *parent_view_iface = NULL; + + +GType +gimp_container_entry_get_type (void) +{ + static GType view_type = 0; + + if (! view_type) + { + static const GTypeInfo view_info = + { + sizeof (GimpContainerEntryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gimp_container_entry_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpContainerEntry), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_container_entry_init, + }; + + static const GInterfaceInfo view_iface_info = + { + (GInterfaceInitFunc) gimp_container_entry_view_iface_init, + NULL, /* iface_finalize */ + NULL /* iface_data */ + }; + + view_type = g_type_register_static (GTK_TYPE_ENTRY, + "GimpContainerEntry", + &view_info, 0); + + g_type_add_interface_static (view_type, GIMP_TYPE_CONTAINER_VIEW, + &view_iface_info); + } + + return view_type; +} + +static void +gimp_container_entry_class_init (GimpContainerEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = gimp_container_view_set_property; + object_class->get_property = gimp_container_view_get_property; + + g_object_class_override_property (object_class, + GIMP_CONTAINER_VIEW_PROP_CONTAINER, + "container"); + g_object_class_override_property (object_class, + GIMP_CONTAINER_VIEW_PROP_CONTEXT, + "context"); + g_object_class_override_property (object_class, + GIMP_CONTAINER_VIEW_PROP_REORDERABLE, + "reorderable"); + g_object_class_override_property (object_class, + GIMP_CONTAINER_VIEW_PROP_PREVIEW_SIZE, + "preview-size"); + g_object_class_override_property (object_class, + GIMP_CONTAINER_VIEW_PROP_PREVIEW_BORDER_WIDTH, + "preview-border-width"); +} + +static void +gimp_container_entry_init (GimpContainerEntry *entry) +{ + GtkEntryCompletion *comp; + GtkListStore *store; + GtkCellRenderer *cell; + + comp = gtk_entry_completion_new (); + + store = gtk_list_store_new (NUM_COLUMNS, + GIMP_TYPE_PREVIEW_RENDERER, + G_TYPE_STRING); + + gtk_entry_completion_set_model (comp, GTK_TREE_MODEL (store)); + g_object_unref (store); + + gtk_entry_set_completion (GTK_ENTRY (entry), comp); + g_object_unref (comp); + + /* FIXME: This can be done better with GTK+ 2.6. */ + + cell = gimp_cell_renderer_viewable_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp), cell, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comp), cell, + "renderer", COLUMN_RENDERER, + NULL); + + gtk_entry_completion_set_text_column (comp, COLUMN_NAME); + + g_signal_connect (entry, "changed", + G_CALLBACK (gimp_container_entry_changed), + entry); +} + +static void +gimp_container_entry_view_iface_init (GimpContainerViewInterface *view_iface) +{ + parent_view_iface = g_type_interface_peek_parent (view_iface); + + if (! parent_view_iface) + parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW); + + view_iface->insert_item = gimp_container_entry_insert_item; + view_iface->remove_item = gimp_container_entry_remove_item; + view_iface->reorder_item = gimp_container_entry_reorder_item; + view_iface->rename_item = gimp_container_entry_rename_item; + view_iface->select_item = gimp_container_entry_select_item; + view_iface->clear_items = gimp_container_entry_clear_items; + view_iface->set_preview_size = gimp_container_entry_set_preview_size; + + view_iface->insert_data_free = (GDestroyNotify) g_free; + +} + +GtkWidget * +gimp_container_entry_new (GimpContainer *container, + GimpContext *context, + gint preview_size, + gint preview_border_width) +{ + GtkWidget *entry; + GimpContainerView *view; + + g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container), + NULL); + g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL); + + entry = g_object_new (GIMP_TYPE_CONTAINER_ENTRY, NULL); + + view = GIMP_CONTAINER_VIEW (entry); + + gimp_container_view_set_preview_size (view, + preview_size, preview_border_width); + + if (container) + gimp_container_view_set_container (view, container); + + if (context) + gimp_container_view_set_context (view, context); + + return entry; +} + +static void +gimp_container_entry_set (GimpContainerEntry *entry, + GtkTreeIter *iter, + GimpViewable *viewable) +{ + GimpContainerView *view = GIMP_CONTAINER_VIEW (entry); + GtkTreeModel *model = gimp_container_entry_get_model (entry); + GimpPreviewRenderer *renderer; + gchar *name; + gint preview_size; + gint border_width; + + preview_size = gimp_container_view_get_preview_size (view, &border_width); + + name = gimp_viewable_get_description (viewable, NULL); + + renderer = gimp_preview_renderer_new (G_TYPE_FROM_INSTANCE (viewable), + preview_size, border_width, + FALSE); + gimp_preview_renderer_set_viewable (renderer, viewable); + gimp_preview_renderer_remove_idle (renderer); + + g_signal_connect (renderer, "update", + G_CALLBACK (gimp_container_entry_renderer_update), + view); + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + COLUMN_RENDERER, renderer, + COLUMN_NAME, name, + -1); + + g_object_unref (renderer); + g_free (name); +} + +/* GimpContainerView methods */ + +static gpointer +gimp_container_entry_insert_item (GimpContainerView *view, + GimpViewable *viewable, + gint index) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + GtkTreeIter *iter; + + iter = g_new0 (GtkTreeIter, 1); + + if (index == -1) + gtk_list_store_append (GTK_LIST_STORE (model), iter); + else + gtk_list_store_insert (GTK_LIST_STORE (model), iter, index); + + gimp_container_entry_set (GIMP_CONTAINER_ENTRY (view), iter, viewable); + + return (gpointer) iter; +} + +static void +gimp_container_entry_remove_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + GtkTreeIter *iter = insert_data; + + if (iter) + gtk_list_store_remove (GTK_LIST_STORE (model), iter); +} + +static void +gimp_container_entry_reorder_item (GimpContainerView *view, + GimpViewable *viewable, + gint new_index, + gpointer insert_data) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + GimpContainer *container = gimp_container_view_get_container (view); + GtkTreeIter *iter = insert_data; + + if (!iter) + return; + + if (new_index == -1 || new_index == container->num_children - 1) + { + gtk_list_store_move_before (GTK_LIST_STORE (model), iter, NULL); + } + else if (new_index == 0) + { + gtk_list_store_move_after (GTK_LIST_STORE (model), iter, NULL); + } + else + { + GtkTreePath *path; + gint old_index; + + path = gtk_tree_model_get_path (model, iter); + old_index = gtk_tree_path_get_indices (path)[0]; + gtk_tree_path_free (path); + + if (new_index != old_index) + { + GtkTreeIter place; + + path = gtk_tree_path_new_from_indices (new_index, -1); + gtk_tree_model_get_iter (model, &place, path); + gtk_tree_path_free (path); + + if (new_index > old_index) + gtk_list_store_move_after (GTK_LIST_STORE (model), iter, &place); + else + gtk_list_store_move_before (GTK_LIST_STORE (model), iter, &place); + } + } +} + +static void +gimp_container_entry_rename_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + GtkTreeIter *iter = insert_data; + + if (iter) + { + gchar *name = gimp_viewable_get_description (viewable, NULL); + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + COLUMN_NAME, name, + -1); + + g_free (name); + } +} + +static gboolean +gimp_container_entry_select_item (GimpContainerView *view, + GimpViewable *viewable, + gpointer insert_data) +{ + GtkEntry *entry = GTK_ENTRY (view); + GtkTreeIter *iter = insert_data; + + g_signal_handlers_block_by_func (entry, + gimp_container_entry_changed, + view); + + gtk_entry_set_text (entry, + iter ? + gimp_object_get_name (GIMP_OBJECT (viewable)) : ""); + + g_signal_handlers_unblock_by_func (entry, + gimp_container_entry_changed, + view); + + return TRUE; +} + +static void +gimp_container_entry_clear_items (GimpContainerView *view) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + + gtk_list_store_clear (GTK_LIST_STORE (model)); + + parent_view_iface->clear_items (view); +} + +static void +gimp_container_entry_set_preview_size (GimpContainerView *view) +{ + GtkTreeModel *model = gimp_container_entry_get_model (view); + GtkTreeIter iter; + gboolean iter_valid; + gint preview_size; + gint border_width; + + preview_size = gimp_container_view_get_preview_size (view, &border_width); + + for (iter_valid = gtk_tree_model_get_iter_first (model, &iter); + iter_valid; + iter_valid = gtk_tree_model_iter_next (model, &iter)) + { + GimpPreviewRenderer *renderer; + + gtk_tree_model_get (model, &iter, + COLUMN_RENDERER, &renderer, + -1); + + gimp_preview_renderer_set_size (renderer, preview_size, border_width); + g_object_unref (renderer); + } +} + +static void +gimp_container_entry_changed (GtkEntry *entry, + GimpContainerView *view) +{ + GimpContainer *container = gimp_container_view_get_container (view); + GimpObject *object; + const gchar *text; + + if (! container) + return; + + text = gtk_entry_get_text (entry); + + object = gimp_container_get_child_by_name (container, text); + + if (object) + gimp_container_view_item_selected (view, GIMP_VIEWABLE (object)); +} + +static void +gimp_container_entry_renderer_update (GimpPreviewRenderer *renderer, + GimpContainerView *view) +{ + GtkTreeIter *iter = gimp_container_view_lookup (view, renderer->viewable); + + if (iter) + { + GtkTreeModel *model = gimp_container_entry_get_model (view); + GtkTreePath *path = gtk_tree_model_get_path (model, iter); + + gtk_tree_model_row_changed (model, path, iter); + gtk_tree_path_free (path); + } +} diff --git a/app/widgets/gimpcontainerentry.h b/app/widgets/gimpcontainerentry.h new file mode 100644 index 0000000000..0a6446664a --- /dev/null +++ b/app/widgets/gimpcontainerentry.h @@ -0,0 +1,58 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcontainerentry.h + * Copyright (C) 2004 Sven Neumann + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_CONTAINER_ENTRY_H__ +#define __GIMP_CONTAINER_ENTRY_H__ + + +#include + + +#define GIMP_TYPE_CONTAINER_ENTRY (gimp_container_entry_get_type ()) +#define GIMP_CONTAINER_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CONTAINER_ENTRY, GimpContainerEntry)) +#define GIMP_CONTAINER_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CONTAINER_ENTRY, GimpContainerEntryClass)) +#define GIMP_IS_CONTAINER_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CONTAINER_ENTRY)) +#define GIMP_IS_CONTAINER_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CONTAINER_ENTRY)) +#define GIMP_CONTAINER_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CONTAINER_ENTRY, GimpContainerEntryClass)) + + +typedef struct _GimpContainerEntryClass GimpContainerEntryClass; + +struct _GimpContainerEntry +{ + GtkEntry parent_instance; +}; + +struct _GimpContainerEntryClass +{ + GtkEntryClass parent_class; +}; + + +GType gimp_container_entry_get_type (void) G_GNUC_CONST; + +GtkWidget * gimp_container_entry_new (GimpContainer *container, + GimpContext *context, + gint preview_size, + gint preview_border_width); + + +#endif /* __GIMP_CONTAINER_ENTRY_H__ */ diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index 2fbb53f06b..5074344828 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -86,6 +86,7 @@ typedef struct _GimpUndoEditor GimpUndoEditor; typedef struct _GimpContainerView GimpContainerView; /* dummy typedef */ typedef struct _GimpContainerBox GimpContainerBox; typedef struct _GimpContainerComboBox GimpContainerComboBox; +typedef struct _GimpContainerEntry GimpContainerEntry; typedef struct _GimpContainerGridView GimpContainerGridView; typedef struct _GimpContainerTreeView GimpContainerTreeView;