Updated Spanish translation
[anjuta-git-plugin.git] / plugins / project-wizard / property.c
blobbc12bd4cdb845efe297f8986616a5dae972f84df
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[] = {
74 "hidden",
75 "boolean",
76 "integer",
77 "string",
78 "list",
79 "directory",
80 "file",
81 "icon"
84 /* Property object
85 *---------------------------------------------------------------------------*/
87 static NPWPropertyType
88 npw_property_type_from_string (const gchar* type)
90 gint i;
92 for (i = 0; i < NPW_LAST_PROPERTY; i++)
94 if (strcmp (NPWPropertyTypeString[i], type) == 0)
96 return (NPWPropertyType)(i + 1);
100 return NPW_UNKNOWN_PROPERTY;
103 #if 0
104 static const gchar*
105 npw_property_string_from_type (NPWPropertyType type)
107 if ((type > 0) && (type < NPW_LAST_PROPERTY))
109 return NPWPropertyTypeString[type - 1];
112 return NULL;
114 #endif
116 NPWProperty*
117 npw_property_new (NPWPage* owner)
119 NPWProperty* this;
121 g_return_val_if_fail (owner, NULL);
123 this = g_chunk_new0(NPWProperty, owner->data_pool);
124 this->owner = owner;
125 this->type = NPW_UNKNOWN_PROPERTY;
126 this->item = NULL;
127 /* value is set to NULL */
128 g_node_append_data (owner->list, this);
130 return this;
133 void
134 npw_property_free (NPWProperty* this)
136 GNode* node;
138 if (this->item != NULL)
140 g_slist_free (this->item);
142 node = g_node_find_child (this->owner->list, G_TRAVERSE_ALL, this);
143 if (node != NULL)
145 g_node_destroy (node);
146 /* Memory allocated in string pool and data pool is not free */
150 void
151 npw_property_set_type (NPWProperty* this, NPWPropertyType type)
153 this->type = type;
156 void
157 npw_property_set_string_type (NPWProperty* this, const gchar* type)
159 npw_property_set_type (this, npw_property_type_from_string (type));
163 NPWPropertyType
164 npw_property_get_type (const NPWProperty* this)
166 return this->type;
169 void
170 npw_property_set_name (NPWProperty* this, const gchar* name)
172 this->value = npw_value_heap_find_value (this->owner->value, name);
175 const gchar*
176 npw_property_get_name (const NPWProperty* this)
178 return npw_value_heap_get_name (this->owner->value, this->value);
181 void
182 npw_property_set_label (NPWProperty* this, const gchar* label)
184 this->label = g_string_chunk_insert (this->owner->string_pool, label);
187 const gchar*
188 npw_property_get_label (const NPWProperty* this)
190 return this->label;
193 void
194 npw_property_set_description (NPWProperty* this, const gchar* description)
196 this->description = g_string_chunk_insert (this->owner->string_pool, description);
199 const gchar*
200 npw_property_get_description (const NPWProperty* this)
202 return this->description;
205 static void
206 cb_boolean_button_toggled (GtkButton *button, gpointer data)
208 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
209 gtk_button_set_label (button, _("Yes"));
210 else
211 gtk_button_set_label (button, _("No"));
214 GtkWidget*
215 npw_property_create_widget (NPWProperty* this)
217 GtkWidget* entry;
218 const gchar* value;
219 GValue val = {0};
221 value = npw_property_get_value (this);
222 switch (this->type)
224 case NPW_BOOLEAN_PROPERTY:
225 entry = gtk_toggle_button_new_with_label (_("No"));
226 g_signal_connect (G_OBJECT (entry), "toggled",
227 G_CALLBACK (cb_boolean_button_toggled), NULL);
228 if (value)
230 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry),
231 (gboolean)atoi (value));
233 break;
234 case NPW_INTEGER_PROPERTY:
235 entry = gtk_spin_button_new (NULL, 1, 0);
236 if (value)
238 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry), atoi (value));
240 break;
241 case NPW_STRING_PROPERTY:
242 entry = gtk_entry_new ();
243 if (value) gtk_entry_set_text (GTK_ENTRY (entry), value);
244 break;
245 case NPW_DIRECTORY_PROPERTY:
246 entry = gnome_file_entry_new (NULL, NULL);
247 g_value_init (&val, G_TYPE_BOOLEAN);
248 g_value_set_boolean (&val, TRUE);
249 g_object_set_property (G_OBJECT (entry), "use-filechooser", &val);
250 g_value_unset (&val);
251 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry), TRUE);
252 if (value) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry), value);
253 break;
254 case NPW_FILE_PROPERTY:
255 entry = gnome_file_entry_new (NULL, NULL);
256 g_value_init (&val, G_TYPE_BOOLEAN);
257 g_value_set_boolean (&val, TRUE);
258 g_object_set_property (G_OBJECT (entry), "use-filechooser", &val);
259 g_value_unset (&val);
260 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry), FALSE);
261 if (value) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry), value);
262 break;
263 case NPW_ICON_PROPERTY:
264 entry = gnome_icon_entry_new("icon_choice", _("Icon choice"));
265 if (value) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry), value);
266 break;
267 case NPW_LIST_PROPERTY:
269 GSList* node;
270 gboolean get_value = FALSE;
272 entry = gtk_combo_box_entry_new_text ();
273 for (node = this->item; node != NULL; node = node->next)
275 gtk_combo_box_append_text (GTK_COMBO_BOX (entry), _(((NPWItem *)node->data)->label));
276 if ((value != NULL) && !get_value && (strcmp (value, ((NPWItem *)node->data)->name) == 0))
278 value = _(((NPWItem *)node->data)->label);
279 get_value = TRUE;
282 if (!(this->options & NPW_EDITABLE_OPTION))
284 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry)->child), FALSE);
286 if (value) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry)->child), value);
287 break;
289 default:
290 return NULL;
292 this->widget = entry;
294 return entry;
297 void
298 npw_property_set_widget (NPWProperty* this, GtkWidget* widget)
300 this->widget = widget;
303 GtkWidget*
304 npw_property_get_widget (const NPWProperty* this)
306 return this->widget;
309 void
310 npw_property_set_default (NPWProperty* this, const gchar* value)
312 /* Check if the default property is valid */
313 if (value && (this->options & NPW_EXIST_SET_OPTION) && !(this->options & NPW_EXIST_OPTION))
315 /* a file or directory with the same name shouldn't exist */
316 if (g_file_test (value, G_FILE_TEST_EXISTS))
318 char* buffer;
319 guint i;
321 /* Allocate memory for the string and a decimal number */
322 buffer = g_new (char, strlen(value) + 8);
323 /* Give up after 1000000 tries */
324 for (i = 1; i < 1000000; i++)
326 sprintf(buffer,"%s%d",value, i);
327 if (!g_file_test (buffer, G_FILE_TEST_EXISTS)) break;
329 this->defvalue = g_string_chunk_insert (this->owner->string_pool, buffer);
330 g_free (buffer);
332 return;
335 /* This function could be used with value = defvalue to only check
336 * the default property */
337 if (this->defvalue != value)
339 this->defvalue = (value == NULL) ? NULL : g_string_chunk_insert (this->owner->string_pool, value);
343 static gboolean
344 npw_property_set_value_from_widget (NPWProperty* this, NPWValueTag tag)
346 gchar* alloc_value = NULL;
347 const gchar* value = NULL;
348 gboolean ok;
350 switch (this->type)
352 case NPW_INTEGER_PROPERTY:
353 alloc_value = g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget)));
354 value = alloc_value;
355 break;
356 case NPW_BOOLEAN_PROPERTY:
357 alloc_value = g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget)));
358 value = alloc_value;
359 break;
360 case NPW_STRING_PROPERTY:
361 value = gtk_entry_get_text (GTK_ENTRY (this->widget));
362 break;
363 case NPW_DIRECTORY_PROPERTY:
364 case NPW_FILE_PROPERTY:
365 alloc_value = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (this->widget), FALSE);
366 value = alloc_value;
367 break;
368 case NPW_ICON_PROPERTY:
369 alloc_value = gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget));
370 value = alloc_value;
371 break;
372 case NPW_LIST_PROPERTY:
374 GSList* node;
376 value = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget)->child));
377 for (node = this->item; node != NULL; node = node->next)
379 if (strcmp (value, _(((NPWItem *)node->data)->label)) == 0)
381 value = ((NPWItem *)node->data)->name;
382 break;
385 break;
387 default:
388 /* Hidden property */
389 value = this->defvalue;
390 break;
393 /* Check and mark default value (will not be saved) */
394 if ((value) && (this->defvalue) && (strcmp (value, this->defvalue) == 0))
396 tag |= NPW_DEFAULT_VALUE;
399 ok = npw_value_heap_set_value (this->owner->value, this->value, value, tag);
400 if (alloc_value != NULL) g_free (alloc_value);
402 return ok;
405 gboolean
406 npw_property_update_value_from_widget (NPWProperty* this)
408 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE);
411 gboolean
412 npw_property_save_value_from_widget (NPWProperty* this)
414 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE);
417 gboolean
418 npw_property_remove_value (NPWProperty* this)
420 return npw_value_heap_set_value (this->owner->value, this->value, NULL, NPW_EMPTY_VALUE);
423 const char*
424 npw_property_get_value (const NPWProperty* this)
426 NPWValueTag tag;
428 tag = npw_value_heap_get_tag (this->owner->value, this->value);
429 if ((tag == NPW_EMPTY_VALUE) || (tag & NPW_DEFAULT_VALUE))
431 return this->defvalue;
433 else
435 /* Only value entered by user could replace default value */
436 return npw_value_heap_get_value (this->owner->value, this->value);
440 gboolean
441 npw_property_add_list_item (NPWProperty* this, const gchar* name, const gchar* label)
443 NPWItem* item;
445 item = g_chunk_new (NPWItem, this->owner->item_pool);
446 item->name = g_string_chunk_insert (this->owner->string_pool, name);
447 item->label = g_string_chunk_insert (this->owner->string_pool, label);
449 this->item = g_slist_append (this->item, item);
451 return TRUE;
454 void
455 npw_property_set_mandatory_option (NPWProperty* this, gboolean value)
457 if (value)
459 this->options |= NPW_MANDATORY_OPTION;
461 else
463 this->options &= ~NPW_MANDATORY_OPTION;
467 void
468 npw_property_set_summary_option (NPWProperty* this, gboolean value)
470 if (value)
472 this->options |= NPW_SUMMARY_OPTION;
474 else
476 this->options &= ~NPW_SUMMARY_OPTION;
480 void
481 npw_property_set_editable_option (NPWProperty* this, gboolean value)
483 if (value)
485 this->options |= NPW_EDITABLE_OPTION;
487 else
489 this->options &= ~NPW_EDITABLE_OPTION;
493 NPWPropertyOptions
494 npw_property_get_options (const NPWProperty* this)
496 return this->options;
499 void
500 npw_property_set_exist_option (NPWProperty* this, NPWPropertyBooleanValue value)
502 switch (value)
504 case NPW_TRUE:
505 this->options |= NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION;
506 break;
507 case NPW_FALSE:
508 this->options &= ~NPW_EXIST_OPTION;
509 this->options |= NPW_EXIST_SET_OPTION;
510 npw_property_set_default (this, this->defvalue);
511 break;
512 case NPW_DEFAULT:
513 this->options &= ~(NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION);
514 break;
518 NPWPropertyBooleanValue
519 npw_property_get_exist_option (const NPWProperty* this)
521 return this->options & NPW_EXIST_SET_OPTION ? (this->options & NPW_EXIST_OPTION ? NPW_TRUE : NPW_FALSE) : NPW_DEFAULT;
524 /* Page object = list of properties
525 *---------------------------------------------------------------------------*/
527 NPWPage*
528 npw_page_new (NPWValueHeap* value)
530 NPWPage* this;
532 this = g_new0(NPWPage, 1);
533 this->string_pool = g_string_chunk_new (STRING_CHUNK_SIZE);
534 this->data_pool = g_mem_chunk_new ("property pool", sizeof (NPWProperty), STRING_CHUNK_SIZE * sizeof (NPWProperty) / 4, G_ALLOC_ONLY);
535 this->item_pool = g_mem_chunk_new ("item pool", sizeof (NPWItem), STRING_CHUNK_SIZE * sizeof (NPWItem) / 4, G_ALLOC_ONLY);
536 this->list = g_node_new (NULL);
537 this->value = value;
539 return this;
542 void
543 npw_page_free (NPWPage* this)
545 g_return_if_fail (this != NULL);
547 g_string_chunk_free (this->string_pool);
548 g_mem_chunk_destroy (this->data_pool);
549 g_mem_chunk_destroy (this->item_pool);
550 g_node_destroy (this->list);
551 g_free (this);
554 void
555 npw_page_set_name (NPWPage* this, const gchar* name)
557 this->name = g_string_chunk_insert (this->string_pool, name);
560 const gchar*
561 npw_page_get_name (const NPWPage* this)
563 return this->name;
566 void
567 npw_page_set_label (NPWPage* this, const gchar* label)
569 this->label = g_string_chunk_insert (this->string_pool, label);
572 const gchar*
573 npw_page_get_label (const NPWPage* this)
575 return this->label;
578 void
579 npw_page_set_description (NPWPage* this, const gchar* description)
581 this->description = g_string_chunk_insert (this->string_pool, description);
584 const gchar*
585 npw_page_get_description (const NPWPage* this)
587 return this->description;
590 typedef struct _PageForeachPropertyData
592 NPWPropertyForeachFunc func;
593 gpointer data;
594 } PageForeachPropertyData;
596 static void
597 cb_page_foreach_property (GNode* node, gpointer data)
599 PageForeachPropertyData* d = (PageForeachPropertyData *)data;
601 (d->func)((NPWProperty*)node->data, d->data);
604 void
605 npw_page_foreach_property (const NPWPage* this, NPWPropertyForeachFunc func, gpointer data)
607 PageForeachPropertyData d;
609 d.func = func;
610 d.data = data;
611 g_node_children_foreach (this->list, G_TRAVERSE_LEAFS, cb_page_foreach_property, &d);