create collate_key on demand
[wxWidgets.git] / src / gtk / treeentry_gtk.c
1 /* ///////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/treeentry_gtk.c
3 // Purpose: GtkTreeEntry implementation
4 // Author: Ryan Norton
5 // Id: $Id$
6 // Copyright: (c) 2006 Ryan Norton
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////// */
9
10 #ifdef __VMS
11 #include <types.h>
12 typedef pid_t GPid;
13 #define G_GNUC_INTERNAL
14 #define GSEAL(x) x
15 #endif
16
17 #include "wx/gtk/treeentry_gtk.h"
18
19 /*
20 GtkTreeEntry
21
22 The main reason for this class is to have a holder for both a string
23 and userdata for us to use in wxListXXX classes.
24
25 This is transformable to a string for the Gtk implementations,
26 and the string passed in is duplicated and freed upon destruction.
27
28 As mentioned the real magic here is the transforming it to a string
29 which lets us use it as a entry in a GtkTreeView/GtkListStore
30 and still display it. Otherwise we would need to implement our
31 own model etc..
32 */
33
34 /* forwards */
35 static void gtk_tree_entry_class_init(void* g_class, void* class_data);
36 static void gtk_tree_entry_init (GTypeInstance* instance, gpointer g_class);
37 static void gtk_tree_entry_string_transform_func(const GValue *src_value,
38 GValue *dest_value);
39 static void gtk_tree_entry_dispose(GObject* obj);
40
41 static GObjectClass* parent_class;
42
43 /* public */
44 GtkTreeEntry*
45 gtk_tree_entry_new()
46 {
47 return GTK_TREE_ENTRY(g_object_new(GTK_TYPE_TREE_ENTRY, NULL));
48 }
49
50 GType
51 gtk_tree_entry_get_type ()
52 {
53 static GType tree_entry_type = 0;
54
55 if (!tree_entry_type)
56 {
57 const GTypeInfo tree_entry_info =
58 {
59 sizeof (GtkTreeEntryClass),
60 NULL, /* base_init */
61 NULL, /* base_finalize */
62 gtk_tree_entry_class_init,
63 NULL, /* class_finalize */
64 NULL, /* class_data */
65 sizeof (GtkTreeEntry),
66 16, /* n_preallocs */
67 (GInstanceInitFunc) gtk_tree_entry_init, /*instance_init*/
68 NULL /* value_table */
69 };
70 tree_entry_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeEntry",
71 &tree_entry_info,
72 (GTypeFlags)0);
73 g_value_register_transform_func(tree_entry_type, G_TYPE_STRING,
74 gtk_tree_entry_string_transform_func);
75 }
76
77 return tree_entry_type;
78 }
79
80 gchar* gtk_tree_entry_get_collate_key (GtkTreeEntry* entry)
81 {
82 if (entry->collate_key == NULL)
83 {
84 char* temp = g_utf8_casefold(entry->label, -1);
85 entry->collate_key = g_utf8_collate_key(temp, -1);
86 g_free(temp);
87 }
88 return entry->collate_key;
89 }
90
91 gchar* gtk_tree_entry_get_label (GtkTreeEntry* entry)
92 {
93 g_assert(GTK_IS_TREE_ENTRY(entry));
94 return entry->label;
95 }
96
97 gpointer gtk_tree_entry_get_userdata (GtkTreeEntry* entry)
98 {
99 g_assert(GTK_IS_TREE_ENTRY(entry));
100 return entry->userdata;
101 }
102
103 void gtk_tree_entry_set_label (GtkTreeEntry* entry, const gchar* label)
104 {
105 g_assert(GTK_IS_TREE_ENTRY(entry));
106
107 /* free previous if it exists */
108 if(entry->label)
109 {
110 g_free(entry->label);
111 g_free(entry->collate_key);
112 }
113
114 entry->label = g_strdup(label);
115 entry->collate_key = NULL;
116 }
117
118 void gtk_tree_entry_set_userdata (GtkTreeEntry* entry, gpointer userdata)
119 {
120 g_assert(GTK_IS_TREE_ENTRY(entry));
121 entry->userdata = userdata;
122 }
123
124 void gtk_tree_entry_set_destroy_func (GtkTreeEntry* entry,
125 GtkTreeEntryDestroy destroy_func,
126 gpointer destroy_func_data)
127 {
128 g_assert(GTK_IS_TREE_ENTRY(entry));
129 entry->destroy_func = destroy_func;
130 entry->destroy_func_data = destroy_func_data;
131 }
132
133 /* private */
134 static void gtk_tree_entry_class_init(void* g_class, void* class_data)
135 {
136 GObjectClass* gobject_class = G_OBJECT_CLASS(g_class);
137 gobject_class->dispose = gtk_tree_entry_dispose;
138 parent_class = G_OBJECT_CLASS(g_type_class_peek_parent(g_class));
139 }
140
141 static void gtk_tree_entry_init (GTypeInstance* instance, gpointer g_class)
142 {
143 GtkTreeEntry* entry = (GtkTreeEntry*) instance;
144
145 /* clear */
146 entry->label = NULL;
147 entry->collate_key = NULL;
148 entry->userdata = NULL;
149 entry->destroy_func_data = NULL;
150 entry->destroy_func = NULL;
151 }
152
153 static void gtk_tree_entry_string_transform_func(const GValue *src_value,
154 GValue *dest_value)
155 {
156 GtkTreeEntry *entry;
157 void* src_ptr = g_value_peek_pointer(src_value);
158
159 /* Make sure src is a treeentry and dest can hold a string */
160 g_assert(GTK_IS_TREE_ENTRY(src_ptr));
161 g_assert(G_VALUE_HOLDS(dest_value, G_TYPE_STRING));
162
163 entry = GTK_TREE_ENTRY(src_ptr);
164 g_value_set_string(dest_value, entry->label);
165 }
166
167 static void gtk_tree_entry_dispose(GObject* obj)
168 {
169 GtkTreeEntry *entry;
170
171 g_assert(GTK_IS_TREE_ENTRY(obj));
172
173 entry = GTK_TREE_ENTRY(obj);
174
175 /* free label if it exists */
176 if(entry->label)
177 {
178 g_free(entry->label);
179 g_free(entry->collate_key);
180 entry->label = NULL;
181 entry->collate_key = NULL;
182 }
183
184 /* call destroy callback if it exists */
185 if(entry->destroy_func)
186 {
187 (*entry->destroy_func) (entry, entry->destroy_func_data);
188 entry->destroy_func = NULL;
189 entry->destroy_func_data = NULL;
190 }
191
192 /* clear userdata */
193 entry->userdata = NULL;
194
195 parent_class->dispose(obj);
196 }