mirror of
https://gitlab.gnome.org/GNOME/glade.git
synced 2025-11-13 00:05:39 -05:00
1016 lines
36 KiB
C
1016 lines
36 KiB
C
/*
|
|
* Copyright (C) 2008 Tristan Van Berkom.
|
|
*
|
|
* This library is free software; you can redistribute it and/or it
|
|
* under the terms of the GNU Lesser General Public License as
|
|
* published by the Free Software Foundation; either version 2.1 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Authors:
|
|
* Tristan Van Berkom <tvb@gnome.org>
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <gladeui/glade.h>
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n-lib.h>
|
|
#include <string.h>
|
|
|
|
#include "glade-icon-sources.h"
|
|
|
|
static GList *
|
|
icon_set_copy (GList * set)
|
|
{
|
|
GList *dup_set = NULL, *l;
|
|
GtkIconSource *source;
|
|
|
|
for (l = set; l; l = l->next)
|
|
{
|
|
source = gtk_icon_source_copy ((GtkIconSource *) l->data);
|
|
dup_set = g_list_prepend (dup_set, source);
|
|
}
|
|
return g_list_reverse (dup_set);
|
|
}
|
|
|
|
|
|
static void
|
|
icon_set_free (GList * list)
|
|
{
|
|
g_list_foreach (list, (GFunc) gtk_icon_source_free, NULL);
|
|
g_list_free (list);
|
|
}
|
|
|
|
|
|
GladeIconSources *
|
|
glade_icon_sources_new (void)
|
|
{
|
|
GladeIconSources *sources = g_new0 (GladeIconSources, 1);
|
|
|
|
sources->sources = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
(GDestroyNotify) g_free,
|
|
(GDestroyNotify) icon_set_free);
|
|
return sources;
|
|
}
|
|
|
|
|
|
static void
|
|
icon_sources_dup (gchar * icon_name, GList * set, GladeIconSources * dup)
|
|
{
|
|
GList *dup_set = icon_set_copy (set);
|
|
g_hash_table_insert (dup->sources, g_strdup (icon_name), dup_set);
|
|
}
|
|
|
|
GladeIconSources *
|
|
glade_icon_sources_copy (GladeIconSources * sources)
|
|
{
|
|
if (!sources)
|
|
return NULL;
|
|
|
|
GladeIconSources *dup = glade_icon_sources_new ();
|
|
|
|
g_hash_table_foreach (sources->sources, (GHFunc) icon_sources_dup, dup);
|
|
|
|
return dup;
|
|
}
|
|
|
|
void
|
|
glade_icon_sources_free (GladeIconSources * sources)
|
|
{
|
|
if (sources)
|
|
{
|
|
g_hash_table_destroy (sources->sources);
|
|
g_free (sources);
|
|
}
|
|
}
|
|
|
|
GType
|
|
glade_icon_sources_get_type (void)
|
|
{
|
|
static GType type_id = 0;
|
|
|
|
if (!type_id)
|
|
type_id = g_boxed_type_register_static
|
|
("GladeIconSources",
|
|
(GBoxedCopyFunc) glade_icon_sources_copy,
|
|
(GBoxedFreeFunc) glade_icon_sources_free);
|
|
return type_id;
|
|
}
|
|
|
|
/**************************** GladeEditorProperty *****************************/
|
|
enum
|
|
{
|
|
COLUMN_TEXT, /* Used for display/editing purposes */
|
|
COLUMN_TEXT_WEIGHT, /* Whether the text is bold (icon-name parent rows) */
|
|
COLUMN_TEXT_EDITABLE, /* parent icon-name displays are not editable */
|
|
COLUMN_ICON_NAME, /* store the icon name regardless */
|
|
COLUMN_LIST_INDEX, /* denotes the position in the GList of the actual property value (or -1) */
|
|
COLUMN_DIRECTION_ACTIVE,
|
|
COLUMN_DIRECTION,
|
|
COLUMN_SIZE_ACTIVE,
|
|
COLUMN_SIZE,
|
|
COLUMN_STATE_ACTIVE,
|
|
COLUMN_STATE,
|
|
NUM_COLUMNS
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
GladeEditorProperty parent_instance;
|
|
|
|
GtkTreeView *view;
|
|
GtkTreeStore *store;
|
|
GtkListStore *icon_names_store;
|
|
GtkTreeViewColumn *filename_column;
|
|
GtkWidget *combo;
|
|
} GladeEPropIconSources;
|
|
|
|
GLADE_MAKE_EPROP (GladeEPropIconSources, glade_eprop_icon_sources)
|
|
#define GLADE_EPROP_ICON_SOURCES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_EPROP_ICON_SOURCES, GladeEPropIconSources))
|
|
#define GLADE_EPROP_ICON_SOURCES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_EPROP_ICON_SOURCES, GladeEPropIconSourcesClass))
|
|
#define GLADE_IS_EPROP_ICON_SOURCES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_EPROP_ICON_SOURCES))
|
|
#define GLADE_IS_EPROP_ICON_SOURCES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_EPROP_ICON_SOURCES))
|
|
#define GLADE_EPROP_ICON_SOURCES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GLADE_EPROP_ICON_SOURCES, GladeEPropIconSourcesClass))
|
|
static void glade_eprop_icon_sources_finalize (GObject * object)
|
|
{
|
|
/* Chain up */
|
|
GObjectClass *parent_class =
|
|
g_type_class_peek_parent (G_OBJECT_GET_CLASS (object));
|
|
//GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (object);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
populate_store_foreach (const gchar * icon_name,
|
|
GList * sources, GladeEPropIconSources * eprop_sources)
|
|
{
|
|
GtkIconSource *source;
|
|
GtkTreeIter parent_iter, iter;
|
|
GList *l;
|
|
|
|
/* Update the comboboxentry's store here... */
|
|
gtk_list_store_append (eprop_sources->icon_names_store, &iter);
|
|
gtk_list_store_set (eprop_sources->icon_names_store, &iter, 0, icon_name, -1);
|
|
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (eprop_sources->combo), &iter);
|
|
|
|
/* Dont set COLUMN_ICON_NAME here */
|
|
gtk_tree_store_append (eprop_sources->store, &parent_iter, NULL);
|
|
gtk_tree_store_set (eprop_sources->store, &parent_iter,
|
|
COLUMN_TEXT, icon_name,
|
|
COLUMN_TEXT_EDITABLE, FALSE,
|
|
COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_BOLD, -1);
|
|
|
|
for (l = sources; l; l = l->next)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
gchar *str;
|
|
|
|
source = l->data;
|
|
pixbuf = gtk_icon_source_get_pixbuf (source);
|
|
str = g_object_get_data (G_OBJECT (pixbuf), "GladeFileName");
|
|
|
|
gtk_tree_store_append (eprop_sources->store, &iter, &parent_iter);
|
|
gtk_tree_store_set (eprop_sources->store, &iter,
|
|
COLUMN_ICON_NAME, icon_name,
|
|
COLUMN_LIST_INDEX, g_list_index (sources, source),
|
|
COLUMN_TEXT, str,
|
|
COLUMN_TEXT_EDITABLE, TRUE,
|
|
COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_NORMAL, -1);
|
|
|
|
if (!gtk_icon_source_get_direction_wildcarded (source))
|
|
{
|
|
GtkTextDirection direction = gtk_icon_source_get_direction (source);
|
|
str =
|
|
glade_utils_enum_string_from_value_displayable
|
|
(GTK_TYPE_TEXT_DIRECTION, direction);
|
|
gtk_tree_store_set (eprop_sources->store, &iter,
|
|
COLUMN_DIRECTION_ACTIVE, TRUE, COLUMN_DIRECTION,
|
|
str, -1);
|
|
g_free (str);
|
|
}
|
|
|
|
if (!gtk_icon_source_get_size_wildcarded (source))
|
|
{
|
|
GtkIconSize size = gtk_icon_source_get_size (source);
|
|
str =
|
|
glade_utils_enum_string_from_value_displayable
|
|
(GTK_TYPE_ICON_SIZE, size);
|
|
gtk_tree_store_set (eprop_sources->store, &iter, COLUMN_SIZE_ACTIVE,
|
|
TRUE, COLUMN_SIZE, str, -1);
|
|
g_free (str);
|
|
}
|
|
|
|
if (!gtk_icon_source_get_state_wildcarded (source))
|
|
{
|
|
GtkStateType state = gtk_icon_source_get_state (source);
|
|
str =
|
|
glade_utils_enum_string_from_value_displayable
|
|
(GTK_TYPE_STATE_TYPE, state);
|
|
gtk_tree_store_set (eprop_sources->store, &iter, COLUMN_STATE_ACTIVE,
|
|
TRUE, COLUMN_STATE, str, -1);
|
|
g_free (str);
|
|
}
|
|
|
|
if (!l->next)
|
|
{
|
|
GtkTreePath *path =
|
|
gtk_tree_model_get_path (GTK_TREE_MODEL (eprop_sources->store),
|
|
&iter);
|
|
gtk_tree_view_expand_to_path (GTK_TREE_VIEW (eprop_sources->view),
|
|
path);
|
|
gtk_tree_path_free (path);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
populate_store (GladeEPropIconSources * eprop_sources)
|
|
{
|
|
GladeIconSources *sources = NULL;
|
|
GladeProperty *property;
|
|
|
|
gtk_tree_store_clear (eprop_sources->store);
|
|
gtk_list_store_clear (eprop_sources->icon_names_store);
|
|
|
|
property = glade_editor_property_get_property (GLADE_EDITOR_PROPERTY (eprop_sources));
|
|
if (property)
|
|
return;
|
|
|
|
glade_property_get (property, &sources);
|
|
|
|
if (sources)
|
|
g_hash_table_foreach (sources->sources, (GHFunc) populate_store_foreach,
|
|
eprop_sources);
|
|
|
|
}
|
|
|
|
static void
|
|
glade_eprop_icon_sources_load (GladeEditorProperty * eprop,
|
|
GladeProperty * property)
|
|
{
|
|
GladeEditorPropertyClass *parent_class =
|
|
g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
|
|
/* Chain up in a clean state... */
|
|
parent_class->load (eprop, property);
|
|
|
|
populate_store (eprop_sources);
|
|
|
|
gtk_widget_queue_draw (GTK_WIDGET (eprop_sources->view));
|
|
}
|
|
|
|
static gboolean
|
|
reload_icon_sources_idle (GladeEditorProperty * eprop)
|
|
{
|
|
GladeProperty *property = glade_editor_property_get_property (eprop);
|
|
|
|
glade_editor_property_load (eprop, property);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
add_clicked (GtkWidget * button, GladeEPropIconSources * eprop_sources)
|
|
{
|
|
/* Remember to set focus on the cell and activate it ! */
|
|
GtkTreeIter *parent_iter = NULL, iter, new_parent_iter;
|
|
GtkTreePath *new_item_path;
|
|
gchar *icon_name;
|
|
gchar *selected_icon_name = NULL;
|
|
gint index;
|
|
|
|
if (gtk_combo_box_get_active_iter
|
|
(GTK_COMBO_BOX (eprop_sources->combo), &iter))
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->icon_names_store), &iter,
|
|
0, &selected_icon_name, -1);
|
|
|
|
if (!selected_icon_name)
|
|
return;
|
|
|
|
/* Find the right parent iter to add a child to... */
|
|
if (gtk_tree_model_get_iter_first
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter))
|
|
{
|
|
do
|
|
{
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_TEXT, &icon_name, -1);
|
|
|
|
if (icon_name && strcmp (icon_name, selected_icon_name) == 0)
|
|
parent_iter = gtk_tree_iter_copy (&iter);
|
|
|
|
g_free (icon_name);
|
|
|
|
}
|
|
while (parent_iter == NULL &&
|
|
gtk_tree_model_iter_next (GTK_TREE_MODEL (eprop_sources->store),
|
|
&iter));
|
|
}
|
|
|
|
/* check if we're already adding one here... */
|
|
if (parent_iter &&
|
|
gtk_tree_model_iter_children (GTK_TREE_MODEL (eprop_sources->store),
|
|
&iter, parent_iter))
|
|
{
|
|
do
|
|
{
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_LIST_INDEX, &index, -1);
|
|
|
|
/* Iter is set, expand and return. */
|
|
if (index < 0)
|
|
goto expand_to_path_and_focus;
|
|
|
|
}
|
|
while (gtk_tree_model_iter_next
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter));
|
|
}
|
|
|
|
|
|
if (!parent_iter)
|
|
{
|
|
/* Dont set COLUMN_ICON_NAME here */
|
|
gtk_tree_store_append (eprop_sources->store, &new_parent_iter, NULL);
|
|
gtk_tree_store_set (eprop_sources->store, &new_parent_iter,
|
|
COLUMN_TEXT, selected_icon_name,
|
|
COLUMN_TEXT_EDITABLE, FALSE,
|
|
COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_BOLD, -1);
|
|
parent_iter = gtk_tree_iter_copy (&new_parent_iter);
|
|
}
|
|
|
|
gtk_tree_store_append (eprop_sources->store, &iter, parent_iter);
|
|
gtk_tree_store_set (eprop_sources->store, &iter,
|
|
COLUMN_ICON_NAME, selected_icon_name,
|
|
COLUMN_TEXT_EDITABLE, TRUE,
|
|
COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_NORMAL,
|
|
COLUMN_LIST_INDEX, -1, -1);
|
|
|
|
/* By now iter is valid. */
|
|
expand_to_path_and_focus:
|
|
new_item_path =
|
|
gtk_tree_model_get_path (GTK_TREE_MODEL (eprop_sources->store), &iter);
|
|
|
|
gtk_widget_grab_focus (GTK_WIDGET (eprop_sources->view));
|
|
gtk_tree_view_expand_to_path (eprop_sources->view, new_item_path);
|
|
gtk_tree_view_set_cursor (eprop_sources->view, new_item_path,
|
|
eprop_sources->filename_column, TRUE);
|
|
|
|
g_free (selected_icon_name);
|
|
gtk_tree_iter_free (parent_iter);
|
|
}
|
|
|
|
static GtkIconSource *
|
|
get_icon_source (GladeIconSources * sources,
|
|
const gchar * icon_name, gint index)
|
|
{
|
|
GList *source_list = g_hash_table_lookup (sources->sources, icon_name);
|
|
|
|
if (source_list)
|
|
{
|
|
if (index < 0)
|
|
return NULL;
|
|
else
|
|
return (GtkIconSource *) g_list_nth_data (source_list, index);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
update_icon_sources (GladeEditorProperty * eprop,
|
|
GladeIconSources * icon_sources)
|
|
{
|
|
GValue value = { 0, };
|
|
|
|
g_value_init (&value, GLADE_TYPE_ICON_SOURCES);
|
|
g_value_take_boxed (&value, icon_sources);
|
|
glade_editor_property_commit (eprop, &value);
|
|
g_value_unset (&value);
|
|
}
|
|
|
|
static void
|
|
delete_clicked (GtkWidget * button, GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
GladeProperty *property = glade_editor_property_get_property (eprop);
|
|
GtkTreeIter iter;
|
|
GladeIconSources *icon_sources = NULL;
|
|
GList *list, *sources, *new_list_head;
|
|
gchar *icon_name;
|
|
gint index = 0;
|
|
|
|
/* NOTE: This will trigger row-deleted below... */
|
|
if (!gtk_tree_selection_get_selected
|
|
(gtk_tree_view_get_selection (eprop_sources->view), NULL, &iter))
|
|
return;
|
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_ICON_NAME, &icon_name,
|
|
COLUMN_LIST_INDEX, &index, -1);
|
|
|
|
/* Could be the user pressed add and then delete without touching the
|
|
* new item.
|
|
*/
|
|
if (index < 0)
|
|
{
|
|
g_idle_add ((GSourceFunc) reload_icon_sources_idle, eprop);
|
|
return;
|
|
}
|
|
|
|
glade_property_get (property, &icon_sources);
|
|
if (icon_sources)
|
|
{
|
|
icon_sources = glade_icon_sources_copy (icon_sources);
|
|
|
|
if ((sources =
|
|
g_hash_table_lookup (icon_sources->sources, icon_name)) != NULL)
|
|
{
|
|
new_list_head = icon_set_copy (sources);
|
|
|
|
list = g_list_nth (new_list_head, index);
|
|
new_list_head = g_list_remove_link (new_list_head, list);
|
|
|
|
gtk_icon_source_free ((GtkIconSource *) list->data);
|
|
g_list_free (list);
|
|
|
|
/* We copied all that above cause this will free the old list */
|
|
g_hash_table_insert (icon_sources->sources, g_strdup (icon_name),
|
|
new_list_head);
|
|
|
|
}
|
|
update_icon_sources (eprop, icon_sources);
|
|
}
|
|
g_free (icon_name);
|
|
}
|
|
|
|
static void
|
|
value_filename_edited (GtkCellRendererText * cell,
|
|
const gchar * path,
|
|
const gchar * new_text, GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
GladeProperty *property = glade_editor_property_get_property (eprop);
|
|
GtkTreeIter iter;
|
|
GladeIconSources *icon_sources = NULL;
|
|
GtkIconSource *source;
|
|
gchar *icon_name;
|
|
gint index = -1;
|
|
GValue *value;
|
|
GdkPixbuf *pixbuf;
|
|
GList *source_list;
|
|
|
|
if (!new_text || !new_text[0])
|
|
{
|
|
g_idle_add ((GSourceFunc) reload_icon_sources_idle, eprop);
|
|
return;
|
|
}
|
|
|
|
if (!gtk_tree_model_get_iter_from_string
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter, path))
|
|
return;
|
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_ICON_NAME, &icon_name,
|
|
COLUMN_LIST_INDEX, &index, -1);
|
|
|
|
/* get new pixbuf value... */
|
|
value = glade_utils_value_from_string (GDK_TYPE_PIXBUF, new_text,
|
|
glade_widget_get_project (glade_property_get_widget (property)),
|
|
glade_property_get_widget (property));
|
|
pixbuf = g_value_get_object (value);
|
|
|
|
|
|
glade_property_get (property, &icon_sources);
|
|
if (icon_sources)
|
|
{
|
|
icon_sources = glade_icon_sources_copy (icon_sources);
|
|
|
|
if (index >= 0 &&
|
|
(source = get_icon_source (icon_sources, icon_name, index)) != NULL)
|
|
gtk_icon_source_set_pixbuf (source, pixbuf);
|
|
else
|
|
{
|
|
|
|
source = gtk_icon_source_new ();
|
|
gtk_icon_source_set_pixbuf (source, pixbuf);
|
|
|
|
if ((source_list = g_hash_table_lookup (icon_sources->sources,
|
|
icon_name)) != NULL)
|
|
{
|
|
source_list = g_list_append (source_list, source);
|
|
}
|
|
else
|
|
{
|
|
source_list = g_list_prepend (NULL, source);
|
|
g_hash_table_insert (icon_sources->sources, g_strdup (icon_name),
|
|
source_list);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
icon_sources = glade_icon_sources_new ();
|
|
source = gtk_icon_source_new ();
|
|
gtk_icon_source_set_pixbuf (source, pixbuf);
|
|
|
|
source_list = g_list_prepend (NULL, source);
|
|
g_hash_table_insert (icon_sources->sources, g_strdup (icon_name),
|
|
source_list);
|
|
}
|
|
|
|
g_value_unset (value);
|
|
g_free (value);
|
|
|
|
update_icon_sources (eprop, icon_sources);
|
|
}
|
|
|
|
static void
|
|
value_attribute_toggled (GtkCellRendererToggle * cell_renderer,
|
|
gchar * path, GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
GladeProperty *property = glade_editor_property_get_property (eprop);
|
|
GtkTreeIter iter;
|
|
GladeIconSources *icon_sources = NULL;
|
|
GtkIconSource *source;
|
|
gchar *icon_name;
|
|
gint index, edit_column;
|
|
gboolean edit_column_active = FALSE;
|
|
|
|
if (!gtk_tree_model_get_iter_from_string
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter, path))
|
|
return;
|
|
|
|
edit_column =
|
|
GPOINTER_TO_INT (g_object_get_data
|
|
(G_OBJECT (cell_renderer), "attribute-column"));
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_ICON_NAME, &icon_name, COLUMN_LIST_INDEX, &index,
|
|
edit_column, &edit_column_active, -1);
|
|
|
|
glade_property_get (property, &icon_sources);
|
|
|
|
if (icon_sources)
|
|
icon_sources = glade_icon_sources_copy (icon_sources);
|
|
|
|
if (icon_sources &&
|
|
(source = get_icon_source (icon_sources, icon_name, index)) != NULL)
|
|
{
|
|
/* Note the reverse meaning of active toggles vs. wildcarded sources... */
|
|
switch (edit_column)
|
|
{
|
|
case COLUMN_DIRECTION_ACTIVE:
|
|
gtk_icon_source_set_direction_wildcarded (source,
|
|
edit_column_active);
|
|
break;
|
|
case COLUMN_SIZE_ACTIVE:
|
|
gtk_icon_source_set_size_wildcarded (source, edit_column_active);
|
|
break;
|
|
case COLUMN_STATE_ACTIVE:
|
|
gtk_icon_source_set_state_wildcarded (source, edit_column_active);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
update_icon_sources (eprop, icon_sources);
|
|
g_free (icon_name);
|
|
return;
|
|
}
|
|
|
|
if (icon_sources)
|
|
glade_icon_sources_free (icon_sources);
|
|
g_free (icon_name);
|
|
return;
|
|
}
|
|
|
|
static void
|
|
value_attribute_edited (GtkCellRendererText * cell,
|
|
const gchar * path,
|
|
const gchar * new_text, GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
GladeProperty *property = glade_editor_property_get_property (eprop);
|
|
GtkTreeIter iter;
|
|
GladeIconSources *icon_sources = NULL;
|
|
GtkIconSource *source;
|
|
gchar *icon_name;
|
|
gint index, edit_column;
|
|
|
|
if (!new_text || !new_text[0])
|
|
return;
|
|
|
|
if (!gtk_tree_model_get_iter_from_string
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter, path))
|
|
return;
|
|
|
|
edit_column =
|
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "attribute-column"));
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_ICON_NAME, &icon_name, COLUMN_LIST_INDEX, &index,
|
|
-1);
|
|
|
|
glade_property_get (property, &icon_sources);
|
|
|
|
if (icon_sources)
|
|
icon_sources = glade_icon_sources_copy (icon_sources);
|
|
|
|
if (icon_sources &&
|
|
(source = get_icon_source (icon_sources, icon_name, index)) != NULL)
|
|
{
|
|
GtkTextDirection direction;
|
|
GtkIconSize size;
|
|
GtkStateType state;
|
|
|
|
switch (edit_column)
|
|
{
|
|
case COLUMN_DIRECTION:
|
|
direction =
|
|
glade_utils_enum_value_from_string (GTK_TYPE_TEXT_DIRECTION,
|
|
new_text);
|
|
gtk_icon_source_set_direction (source, direction);
|
|
break;
|
|
case COLUMN_SIZE:
|
|
size =
|
|
glade_utils_enum_value_from_string (GTK_TYPE_ICON_SIZE,
|
|
new_text);
|
|
gtk_icon_source_set_size (source, size);
|
|
break;
|
|
case COLUMN_STATE:
|
|
state =
|
|
glade_utils_enum_value_from_string (GTK_TYPE_STATE_TYPE,
|
|
new_text);
|
|
gtk_icon_source_set_state (source, state);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
update_icon_sources (eprop, icon_sources);
|
|
g_free (icon_name);
|
|
return;
|
|
}
|
|
|
|
if (icon_sources)
|
|
glade_icon_sources_free (icon_sources);
|
|
g_free (icon_name);
|
|
return;
|
|
}
|
|
|
|
static gboolean
|
|
icon_sources_query_tooltip (GtkWidget * widget,
|
|
gint x,
|
|
gint y,
|
|
gboolean keyboard_mode,
|
|
GtkTooltip * tooltip,
|
|
GladeEPropIconSources * eprop_sources)
|
|
{
|
|
GtkTreePath *path = NULL;
|
|
GtkTreeIter iter;
|
|
GtkTreeViewColumn *column = NULL;
|
|
gint bin_x = x, bin_y = y, col;
|
|
gchar *icon_name = NULL;
|
|
gboolean show_now = FALSE;
|
|
|
|
if (keyboard_mode)
|
|
return FALSE;
|
|
|
|
gtk_tree_view_convert_widget_to_bin_window_coords (eprop_sources->view,
|
|
x, y, &bin_x, &bin_y);
|
|
|
|
if (gtk_tree_view_get_path_at_pos (eprop_sources->view,
|
|
bin_x, bin_y, &path, &column, NULL, NULL))
|
|
{
|
|
if (gtk_tree_model_get_iter
|
|
(GTK_TREE_MODEL (eprop_sources->store), &iter, path))
|
|
{
|
|
col =
|
|
GPOINTER_TO_INT (g_object_get_data
|
|
(G_OBJECT (column), "column-id"));
|
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
|
|
COLUMN_ICON_NAME, &icon_name, -1);
|
|
|
|
/* no tooltips on the parent rows */
|
|
if (icon_name)
|
|
{
|
|
gchar *tooltip_text = NULL;
|
|
show_now = TRUE;
|
|
|
|
switch (col)
|
|
{
|
|
case COLUMN_TEXT:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Enter a filename or a relative or full path for this "
|
|
"source of '%s' (Glade will only ever load them in "
|
|
"the runtime from your project directory)."),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_DIRECTION_ACTIVE:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set whether you want to specify a text direction "
|
|
"for this source of '%s'"),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_DIRECTION:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set the text direction for this source of '%s'"),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_SIZE_ACTIVE:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set whether you want to specify an icon size "
|
|
"for this source of '%s'"),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_SIZE:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set the icon size for this source of '%s'"),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_STATE_ACTIVE:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set whether you want to specify a state "
|
|
"for this source of '%s'"),
|
|
icon_name);
|
|
break;
|
|
case COLUMN_STATE:
|
|
tooltip_text =
|
|
g_strdup_printf (_
|
|
("Set the state for this source of '%s'"),
|
|
icon_name);
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
gtk_tooltip_set_text (tooltip, tooltip_text);
|
|
g_free (tooltip_text);
|
|
g_free (icon_name);
|
|
|
|
|
|
gtk_tree_view_set_tooltip_cell (eprop_sources->view,
|
|
tooltip, path, column, NULL);
|
|
|
|
}
|
|
}
|
|
gtk_tree_path_free (path);
|
|
}
|
|
return show_now;
|
|
}
|
|
|
|
|
|
static GtkTreeView *
|
|
build_view (GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
static GtkListStore *direction_store = NULL, *size_store =
|
|
NULL, *state_store = NULL;
|
|
GtkTreeView *view = (GtkTreeView *) gtk_tree_view_new ();
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeViewColumn *column;
|
|
|
|
if (!direction_store)
|
|
{
|
|
direction_store =
|
|
glade_utils_liststore_from_enum_type (GTK_TYPE_TEXT_DIRECTION, FALSE);
|
|
size_store =
|
|
glade_utils_liststore_from_enum_type (GTK_TYPE_ICON_SIZE, FALSE);
|
|
state_store =
|
|
glade_utils_liststore_from_enum_type (GTK_TYPE_STATE_TYPE, FALSE);
|
|
}
|
|
|
|
/* Filename / icon name column/renderer */
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL);
|
|
g_signal_connect (G_OBJECT (renderer), "edited",
|
|
G_CALLBACK (value_filename_edited), eprop);
|
|
|
|
eprop_sources->filename_column =
|
|
gtk_tree_view_column_new_with_attributes (_("File Name"), renderer,
|
|
"text", COLUMN_TEXT,
|
|
"weight", COLUMN_TEXT_WEIGHT,
|
|
"editable",
|
|
COLUMN_TEXT_EDITABLE, NULL);
|
|
gtk_tree_view_column_set_expand (eprop_sources->filename_column, TRUE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view),
|
|
eprop_sources->filename_column);
|
|
|
|
g_object_set_data (G_OBJECT (eprop_sources->filename_column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_TEXT));
|
|
|
|
/********************* Size *********************/
|
|
/* Attribute active portion */
|
|
renderer = gtk_cell_renderer_toggle_new ();
|
|
g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_SIZE_ACTIVE));
|
|
g_signal_connect (G_OBJECT (renderer), "toggled",
|
|
G_CALLBACK (value_attribute_toggled), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE, "active", COLUMN_SIZE_ACTIVE, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_SIZE_ACTIVE));
|
|
|
|
/* Attribute portion */
|
|
renderer = gtk_cell_renderer_combo_new ();
|
|
g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE,
|
|
"text-column", 0, "model", size_store, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_SIZE));
|
|
g_signal_connect (G_OBJECT (renderer), "edited",
|
|
G_CALLBACK (value_attribute_edited), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE,
|
|
"editable", COLUMN_SIZE_ACTIVE, "text", COLUMN_SIZE, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_SIZE));
|
|
|
|
|
|
/********************* State *********************/
|
|
/* Attribute active portion */
|
|
renderer = gtk_cell_renderer_toggle_new ();
|
|
g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_STATE_ACTIVE));
|
|
g_signal_connect (G_OBJECT (renderer), "toggled",
|
|
G_CALLBACK (value_attribute_toggled), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE, "active", COLUMN_STATE_ACTIVE, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_STATE_ACTIVE));
|
|
|
|
/* Attribute portion */
|
|
renderer = gtk_cell_renderer_combo_new ();
|
|
g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE,
|
|
"text-column", 0, "model", state_store, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_STATE));
|
|
g_signal_connect (G_OBJECT (renderer), "edited",
|
|
G_CALLBACK (value_attribute_edited), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE,
|
|
"editable", COLUMN_STATE_ACTIVE, "text", COLUMN_STATE, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_STATE));
|
|
|
|
|
|
/********************* Direction *********************/
|
|
/* Attribute active portion */
|
|
renderer = gtk_cell_renderer_toggle_new ();
|
|
g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_DIRECTION_ACTIVE));
|
|
g_signal_connect (G_OBJECT (renderer), "toggled",
|
|
G_CALLBACK (value_attribute_toggled), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE,
|
|
"active", COLUMN_DIRECTION_ACTIVE, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_DIRECTION_ACTIVE));
|
|
|
|
/* Attribute portion */
|
|
renderer = gtk_cell_renderer_combo_new ();
|
|
g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE,
|
|
"text-column", 0, "model", direction_store, NULL);
|
|
g_object_set_data (G_OBJECT (renderer), "attribute-column",
|
|
GINT_TO_POINTER (COLUMN_DIRECTION));
|
|
g_signal_connect (G_OBJECT (renderer), "edited",
|
|
G_CALLBACK (value_attribute_edited), eprop);
|
|
|
|
column = gtk_tree_view_column_new_with_attributes
|
|
("dummy", renderer,
|
|
"visible", COLUMN_TEXT_EDITABLE,
|
|
"editable", COLUMN_DIRECTION_ACTIVE, "text", COLUMN_DIRECTION, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
|
g_object_set_data (G_OBJECT (column), "column-id",
|
|
GINT_TO_POINTER (COLUMN_DIRECTION));
|
|
|
|
|
|
/* Connect ::query-tooltip here for fancy tooltips... */
|
|
g_object_set (G_OBJECT (view), "has-tooltip", TRUE, NULL);
|
|
g_signal_connect (G_OBJECT (view), "query-tooltip",
|
|
G_CALLBACK (icon_sources_query_tooltip), eprop);
|
|
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
|
|
gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (view), FALSE);
|
|
|
|
return view;
|
|
}
|
|
|
|
static void
|
|
icon_name_entry_activated (GtkEntry * entry,
|
|
GladeEPropIconSources * eprop_sources)
|
|
{
|
|
GtkTreeIter iter;
|
|
const gchar *text = gtk_entry_get_text (entry);
|
|
|
|
if (!text || !text[0])
|
|
return;
|
|
|
|
gtk_list_store_append (eprop_sources->icon_names_store, &iter);
|
|
gtk_list_store_set (eprop_sources->icon_names_store, &iter, 0, text, -1);
|
|
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (eprop_sources->combo), &iter);
|
|
}
|
|
|
|
static GtkWidget *
|
|
glade_eprop_icon_sources_create_input (GladeEditorProperty * eprop)
|
|
{
|
|
GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
|
|
GtkWidget *vbox, *hbox, *button, *swin;
|
|
|
|
vbox = gtk_vbox_new (FALSE, 2);
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
|
|
|
/* hbox with comboboxentry add/remove source buttons on the right... */
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
eprop_sources->icon_names_store = gtk_list_store_new (1, G_TYPE_STRING);
|
|
eprop_sources->combo = gtk_combo_box_new_with_entry ();
|
|
gtk_combo_box_set_model (GTK_COMBO_BOX (eprop_sources->combo),
|
|
GTK_TREE_MODEL (eprop_sources->icon_names_store));
|
|
g_signal_connect (G_OBJECT
|
|
(gtk_bin_get_child (GTK_BIN (eprop_sources->combo))),
|
|
"activate", G_CALLBACK (icon_name_entry_activated), eprop);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), eprop_sources->combo, TRUE, TRUE, 0);
|
|
button = gtk_button_new ();
|
|
gtk_button_set_image (GTK_BUTTON (button),
|
|
gtk_image_new_from_stock (GTK_STOCK_ADD,
|
|
GTK_ICON_SIZE_BUTTON));
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
|
g_signal_connect (G_OBJECT (button), "clicked",
|
|
G_CALLBACK (add_clicked), eprop_sources);
|
|
|
|
button = gtk_button_new ();
|
|
gtk_button_set_image (GTK_BUTTON (button),
|
|
gtk_image_new_from_stock (GTK_STOCK_REMOVE,
|
|
GTK_ICON_SIZE_BUTTON));
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
|
|
|
g_signal_connect (G_OBJECT (button), "clicked",
|
|
G_CALLBACK (delete_clicked), eprop_sources);
|
|
|
|
/* Pack treeview/swindow on the left... */
|
|
swin = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
|
|
GTK_SHADOW_IN);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
|
|
gtk_box_pack_start (GTK_BOX (vbox), swin, TRUE, TRUE, 0);
|
|
|
|
eprop_sources->view = build_view (eprop);
|
|
gtk_container_add (GTK_CONTAINER (swin), GTK_WIDGET (eprop_sources->view));
|
|
|
|
g_object_set (G_OBJECT (vbox), "height-request", 350, NULL);
|
|
|
|
eprop_sources->store = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, // COLUMN_TEXT
|
|
G_TYPE_INT, // COLUMN_TEXT_WEIGHT
|
|
G_TYPE_BOOLEAN, // COLUMN_TEXT_EDITABLE
|
|
G_TYPE_STRING, // COLUMN_ICON_NAME
|
|
G_TYPE_INT, // COLUMN_LIST_INDEX
|
|
G_TYPE_BOOLEAN, // COLUMN_DIRECTION_ACTIVE
|
|
G_TYPE_STRING, // COLUMN_DIRECTION
|
|
G_TYPE_BOOLEAN, // COLUMN_SIZE_ACTIVE
|
|
G_TYPE_STRING, // COLUMN_SIZE
|
|
G_TYPE_BOOLEAN, // COLUMN_STATE_ACTIVE,
|
|
G_TYPE_STRING); // COLUMN_STATE
|
|
|
|
gtk_tree_view_set_model (eprop_sources->view,
|
|
GTK_TREE_MODEL (eprop_sources->store));
|
|
g_object_unref (G_OBJECT (eprop_sources->store)); // <-- pass ownership here
|
|
|
|
gtk_widget_show_all (vbox);
|
|
return vbox;
|
|
}
|