* configure.in, plugins/glade/plugin.c: Make it work with
[anjuta-git-plugin.git] / plugins / project-wizard / property.c
blobbfd2d0ac344fbb4ffdbef78b86a19dd6797586ed
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 property.c
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Project properties, used in middle pages
24 *---------------------------------------------------------------------------*/
26 #include <config.h>
28 #include "property.h"
30 #include <glib/gdir.h>
32 #include <gnome.h>
33 #include <libgnome/gnome-i18n.h>
35 #include <string.h>
36 #include <stdlib.h>
38 /*---------------------------------------------------------------------------*/
40 #define STRING_CHUNK_SIZE 256
42 /*---------------------------------------------------------------------------*/
44 struct _NPWPage
46 GNode* list;
47 GStringChunk* string_pool;
48 GMemChunk* data_pool;
49 GMemChunk* item_pool;
50 NPWValueHeap* value;
51 gchar* name;
52 gchar* label;
53 gchar* description;
56 struct _NPWProperty {
57 NPWPropertyType type;
58 NPWPropertyOptions options;
59 gchar* label;
60 gchar* description;
61 gchar* defvalue;
62 NPWValue* value;
63 GtkWidget* widget;
64 NPWPage* owner;
65 GSList* item;
68 struct _NPWItem {
69 const gchar* name;
70 const gchar* label;
73 static const gchar* NPWPropertyTypeString[] = {"hidden",
74 "boolean",
75 "integer",
76 "string",
77 "list",
78 "directory",
79 "file",
80 "icon"};
82 /* Property object
83 *---------------------------------------------------------------------------*/
85 static NPWPropertyType
86 npw_property_type_from_string (const gchar* type)
88 gint i;
90 for (i = 0; i < NPW_LAST_PROPERTY; i++)
92 if (strcmp (NPWPropertyTypeString[i], type) == 0)
94 return (NPWPropertyType)(i + 1);
98 return NPW_UNKNOWN_PROPERTY;
101 #if 0
102 static const gchar*
103 npw_property_string_from_type (NPWPropertyType type)
105 if ((type > 0) && (type < NPW_LAST_PROPERTY))
107 return NPWPropertyTypeString[type - 1];
110 return NULL;
112 #endif
114 NPWProperty*
115 npw_property_new (NPWPage* owner)
117 NPWProperty* this;
119 g_return_val_if_fail (owner, NULL);
121 this = g_chunk_new0(NPWProperty, owner->data_pool);
122 this->owner = owner;
123 this->type = NPW_UNKNOWN_PROPERTY;
124 this->item = NULL;
125 /* value is set to NULL */
126 g_node_append_data (owner->list, this);
128 return this;
131 void
132 npw_property_free (NPWProperty* this)
134 GNode* node;
136 if (this->item != NULL)
138 g_slist_free (this->item);
140 node = g_node_find_child (this->owner->list, G_TRAVERSE_ALL, this);
141 if (node != NULL)
143 g_node_destroy (node);
144 /* Memory allocated in string pool and data pool is not free */
148 void
149 npw_property_set_type (NPWProperty* this, NPWPropertyType type)
151 this->type = type;
154 void
155 npw_property_set_string_type (NPWProperty* this, const gchar* type)
157 npw_property_set_type (this, npw_property_type_from_string (type));
161 NPWPropertyType
162 npw_property_get_type (const NPWProperty* this)
164 return this->type;
167 void
168 npw_property_set_name (NPWProperty* this, const gchar* name)
170 this->value = npw_value_heap_find_value (this->owner->value, name);
173 const gchar*
174 npw_property_get_name (const NPWProperty* this)
176 return npw_value_heap_get_name (this->owner->value, this->value);
179 void
180 npw_property_set_label (NPWProperty* this, const gchar* label)
182 this->label = g_string_chunk_insert (this->owner->string_pool, label);
185 const gchar*
186 npw_property_get_label (const NPWProperty* this)
188 return this->label;
191 void
192 npw_property_set_description (NPWProperty* this, const gchar* description)
194 this->description = g_string_chunk_insert (this->owner->string_pool, description);
197 const gchar*
198 npw_property_get_description (const NPWProperty* this)
200 return this->description;
203 static void
204 cb_boolean_button_toggled (GtkButton *button, gpointer data)
206 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
207 gtk_button_set_label (button, _("Yes"));
208 else
209 gtk_button_set_label (button, _("No"));
212 GtkWidget*
213 npw_property_create_widget (NPWProperty* this)
215 GtkWidget* entry;
216 const gchar* value;
217 GValue val = {0};
219 value = npw_property_get_value (this);
220 switch (this->type)
222 case NPW_BOOLEAN_PROPERTY:
223 entry = gtk_toggle_button_new_with_label (_("No"));
224 g_signal_connect (G_OBJECT (entry), "toggled",
225 G_CALLBACK (cb_boolean_button_toggled), NULL);
226 if (value)
228 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry),
229 (gboolean)atoi (value));
231 break;
232 case NPW_INTEGER_PROPERTY:
233 entry = gtk_spin_button_new (NULL, 1, 0);
234 if (value)
236 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry), atoi (value));
238 break;
239 case NPW_STRING_PROPERTY:
240 entry = gtk_entry_new ();
241 if (value) gtk_entry_set_text (GTK_ENTRY (entry), value);
242 break;
243 case NPW_DIRECTORY_PROPERTY:
244 entry = gnome_file_entry_new (NULL, NULL);
245 g_value_init (&val, G_TYPE_BOOLEAN);
246 g_value_set_boolean (&val, TRUE);
247 g_object_set_property (G_OBJECT (entry), "use-filechooser", &val);
248 g_value_unset (&val);
249 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry), TRUE);
250 if (value) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry), value);
251 break;
252 case NPW_FILE_PROPERTY:
253 entry = gnome_file_entry_new (NULL, NULL);
254 g_value_init (&val, G_TYPE_BOOLEAN);
255 g_value_set_boolean (&val, TRUE);
256 g_object_set_property (G_OBJECT (entry), "use-filechooser", &val);
257 g_value_unset (&val);
258 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry), FALSE);
259 if (value) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry), value);
260 break;
261 case NPW_ICON_PROPERTY:
262 entry = gnome_icon_entry_new("icon_choice", _("Icon choice"));
263 if (value) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry), value);
264 break;
265 case NPW_LIST_PROPERTY:
267 GSList* node;
268 gboolean get_value = FALSE;
270 entry = gtk_combo_box_entry_new_text ();
271 for (node = this->item; node != NULL; node = node->next)
273 gtk_combo_box_append_text (GTK_COMBO_BOX (entry), _(((NPWItem *)node->data)->label));
274 if ((value != NULL) && !get_value && (strcmp (value, ((NPWItem *)node->data)->name) == 0))
276 value = _(((NPWItem *)node->data)->label);
277 get_value = TRUE;
280 if (!(this->options & NPW_EDITABLE_OPTION))
282 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry)->child), FALSE);
284 if (value) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry)->child), value);
285 break;
287 default:
288 return NULL;
290 this->widget = entry;
292 return entry;
295 void
296 npw_property_set_widget (NPWProperty* this, GtkWidget* widget)
298 this->widget = widget;
301 GtkWidget*
302 npw_property_get_widget (const NPWProperty* this)
304 return this->widget;
307 void
308 npw_property_set_default (NPWProperty* this, const gchar* value)
310 /* Check if the default property is valid */
311 if (value && (this->options & NPW_EXIST_SET_OPTION) && !(this->options & NPW_EXIST_OPTION))
313 /* a file or directory with the same name shouldn't exist */
314 if (g_file_test (value, G_FILE_TEST_EXISTS))
316 char* buffer;
317 guint i;
319 /* Allocate memory for the string and a decimal number */
320 buffer = g_new (char, strlen(value) + 8);
321 /* Give up after 1000000 tries */
322 for (i = 1; i < 1000000; i++)
324 sprintf(buffer,"%s%d",value, i);
325 if (!g_file_test (buffer, G_FILE_TEST_EXISTS)) break;
327 this->defvalue = g_string_chunk_insert (this->owner->string_pool, buffer);
328 g_free (buffer);
330 return;
333 /* This function could be used with value = defvalue to only check
334 * the default property */
335 if (this->defvalue != value)
337 this->defvalue = (value == NULL) ? NULL : g_string_chunk_insert (this->owner->string_pool, value);
341 static gboolean
342 npw_property_set_value_from_widget (NPWProperty* this, NPWValueTag tag)
344 gchar* alloc_value = NULL;
345 const gchar* value = NULL;
346 gboolean ok;
348 switch (this->type)
350 case NPW_INTEGER_PROPERTY:
351 alloc_value = g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget)));
352 value = alloc_value;
353 break;
354 case NPW_BOOLEAN_PROPERTY:
355 alloc_value = g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget)));
356 value = alloc_value;
357 break;
358 case NPW_STRING_PROPERTY:
359 value = gtk_entry_get_text (GTK_ENTRY (this->widget));
360 break;
361 case NPW_DIRECTORY_PROPERTY:
362 case NPW_FILE_PROPERTY:
363 alloc_value = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (this->widget), FALSE);
364 value = alloc_value;
365 break;
366 case NPW_ICON_PROPERTY:
367 alloc_value = gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget));
368 value = alloc_value;
369 break;
370 case NPW_LIST_PROPERTY:
372 GSList* node;
374 value = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget)->child));
375 for (node = this->item; node != NULL; node = node->next)
377 if (strcmp (value, _(((NPWItem *)node->data)->label)) == 0)
379 value = ((NPWItem *)node->data)->name;
380 break;
383 break;
385 default:
386 /* Hidden property */
387 value = this->defvalue;
388 break;
391 /* Check and mark default value (will not be saved) */
392 if ((value) && (this->defvalue) && (strcmp (value, this->defvalue) == 0))
394 tag |= NPW_DEFAULT_VALUE;
397 ok = npw_value_heap_set_value (this->owner->value, this->value, value, tag);
398 if (alloc_value != NULL) g_free (alloc_value);
400 return ok;
403 gboolean
404 npw_property_update_value_from_widget (NPWProperty* this)
406 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE);
409 gboolean
410 npw_property_save_value_from_widget (NPWProperty* this)
412 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE);
415 gboolean
416 npw_property_remove_value (NPWProperty* this)
418 return npw_value_heap_set_value (this->owner->value, this->value, NULL, NPW_EMPTY_VALUE);
421 const char*
422 npw_property_get_value (const NPWProperty* this)
424 NPWValueTag tag;
426 tag = npw_value_heap_get_tag (this->owner->value, this->value);
427 if ((tag == NPW_EMPTY_VALUE) || (tag & NPW_DEFAULT_VALUE))
429 return this->defvalue;
431 else
433 /* Only value entered by user could replace default value */
434 return npw_value_heap_get_value (this->owner->value, this->value);
438 gboolean
439 npw_property_add_list_item (NPWProperty* this, const gchar* name, const gchar* label)
441 NPWItem* item;
443 item = g_chunk_new (NPWItem, this->owner->item_pool);
444 item->name = g_string_chunk_insert (this->owner->string_pool, name);
445 item->label = g_string_chunk_insert (this->owner->string_pool, label);
447 this->item = g_slist_append (this->item, item);
449 return TRUE;
452 void
453 npw_property_set_mandatory_option (NPWProperty* this, gboolean value)
455 if (value)
457 this->options |= NPW_MANDATORY_OPTION;
459 else
461 this->options &= ~NPW_MANDATORY_OPTION;
465 void
466 npw_property_set_summary_option (NPWProperty* this, gboolean value)
468 if (value)
470 this->options |= NPW_SUMMARY_OPTION;
472 else
474 this->options &= ~NPW_SUMMARY_OPTION;
478 void
479 npw_property_set_editable_option (NPWProperty* this, gboolean value)
481 if (value)
483 this->options |= NPW_EDITABLE_OPTION;
485 else
487 this->options &= ~NPW_EDITABLE_OPTION;
491 NPWPropertyOptions
492 npw_property_get_options (const NPWProperty* this)
494 return this->options;
497 void
498 npw_property_set_exist_option (NPWProperty* this, NPWPropertyBooleanValue value)
500 switch (value)
502 case NPW_TRUE:
503 this->options |= NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION;
504 break;
505 case NPW_FALSE:
506 this->options &= ~NPW_EXIST_OPTION;
507 this->options |= NPW_EXIST_SET_OPTION;
508 npw_property_set_default (this, this->defvalue);
509 break;
510 case NPW_DEFAULT:
511 this->options &= ~(NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION);
512 break;
516 NPWPropertyBooleanValue
517 npw_property_get_exist_option (const NPWProperty* this)
519 return this->options & NPW_EXIST_SET_OPTION ? (this->options & NPW_EXIST_OPTION ? NPW_TRUE : NPW_FALSE) : NPW_DEFAULT;
522 /* Page object = list of properties
523 *---------------------------------------------------------------------------*/
525 NPWPage*
526 npw_page_new (NPWValueHeap* value)
528 NPWPage* this;
530 this = g_new0(NPWPage, 1);
531 this->string_pool = g_string_chunk_new (STRING_CHUNK_SIZE);
532 this->data_pool = g_mem_chunk_new ("property pool", sizeof (NPWProperty), STRING_CHUNK_SIZE * sizeof (NPWProperty) / 4, G_ALLOC_ONLY);
533 this->item_pool = g_mem_chunk_new ("item pool", sizeof (NPWItem), STRING_CHUNK_SIZE * sizeof (NPWItem) / 4, G_ALLOC_ONLY);
534 this->list = g_node_new (NULL);
535 this->value = value;
537 return this;
540 void
541 npw_page_free (NPWPage* this)
543 g_return_if_fail (this != NULL);
545 g_string_chunk_free (this->string_pool);
546 g_mem_chunk_destroy (this->data_pool);
547 g_mem_chunk_destroy (this->item_pool);
548 g_node_destroy (this->list);
549 g_free (this);
552 void
553 npw_page_set_name (NPWPage* this, const gchar* name)
555 this->name = g_string_chunk_insert (this->string_pool, name);
558 const gchar*
559 npw_page_get_name (const NPWPage* this)
561 return this->name;
564 void
565 npw_page_set_label (NPWPage* this, const gchar* label)
567 this->label = g_string_chunk_insert (this->string_pool, label);
570 const gchar*
571 npw_page_get_label (const NPWPage* this)
573 return this->label;
576 void
577 npw_page_set_description (NPWPage* this, const gchar* description)
579 this->description = g_string_chunk_insert (this->string_pool, description);
582 const gchar*
583 npw_page_get_description (const NPWPage* this)
585 return this->description;
588 typedef struct _PageForeachPropertyData
590 NPWPropertyForeachFunc func;
591 gpointer data;
592 } PageForeachPropertyData;
594 static void
595 cb_page_foreach_property (GNode* node, gpointer data)
597 PageForeachPropertyData* d = (PageForeachPropertyData *)data;
599 (d->func)((NPWProperty*)node->data, d->data);
602 void
603 npw_page_foreach_property (const NPWPage* this, NPWPropertyForeachFunc func, gpointer data)
605 PageForeachPropertyData d;
607 d.func = func;
608 d.data = data;
609 g_node_children_foreach (this->list, G_TRAVERSE_LEAFS, cb_page_foreach_property, &d);