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