Enlightenment CVS committal Author : moom Project : e17 Module : libs/etk
Dir : e17/libs/etk/src/lib Modified Files: etk_combobox.c etk_combobox.h Log Message: * [Combobox] More work on the combobox =================================================================== RCS file: /cvs/e/e17/libs/etk/src/lib/etk_combobox.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -3 -r1.37 -r1.38 --- etk_combobox.c 8 Mar 2007 18:16:01 -0000 1.37 +++ etk_combobox.c 9 Mar 2007 00:49:27 -0000 1.38 @@ -12,6 +12,8 @@ #include "etk_signal_callback.h" #include "etk_utils.h" +/*TODO/FIXME: what if the theme item border are smaller/bigger than usual?!?! (important!!) */ + /** * @addtogroup Etk_Combobox * @{ @@ -36,7 +38,9 @@ static void _etk_combobox_destructor(Etk_Combobox *combobox); static void _etk_combobox_property_set(Etk_Object *object, int property_id, Etk_Property_Value *value); static void _etk_combobox_property_get(Etk_Object *object, int property_id, Etk_Property_Value *value); +static void _etk_combobox_item_constructor(Etk_Combobox_Item *item); static void _etk_combobox_item_destructor(Etk_Combobox_Item *item); +static void _etk_combobox_item_destroyed_cb(Etk_Object *object, void *data); static void _etk_combobox_size_request(Etk_Widget *widget, Etk_Size *size); static void _etk_combobox_size_allocate(Etk_Widget *widget, Etk_Geometry geometry); static void _etk_combobox_window_size_request(Etk_Widget *widget, Etk_Size *size); @@ -55,6 +59,7 @@ static void _etk_combobox_item_leave_cb(Etk_Object *object, void *data); static void _etk_combobox_item_mouse_up_cb(Etk_Object *object, Etk_Event_Mouse_Up *event, void *data); static void _etk_combobox_selected_item_set(Etk_Combobox *combobox, Etk_Combobox_Item *item); +static void _etk_combobox_item_cells_render(Etk_Combobox *combobox, Etk_Widget **cells, Etk_Geometry geometry, Etk_Bool ignore_other); static Etk_Signal *_etk_combobox_signals[ETK_COMBOBOX_NUM_SIGNALS]; @@ -105,7 +110,7 @@ if (!combobox_item_type) { combobox_item_type = etk_type_new("Etk_Combobox_Item", ETK_WIDGET_TYPE, sizeof(Etk_Combobox_Item), - NULL, ETK_DESTRUCTOR(_etk_combobox_item_destructor)); + ETK_CONSTRUCTOR(_etk_combobox_item_constructor), ETK_DESTRUCTOR(_etk_combobox_item_destructor)); } return combobox_item_type; @@ -206,8 +211,7 @@ */ void etk_combobox_build(Etk_Combobox *combobox) { - int i, j; - int num_children = 0; + int i; if (!combobox || combobox->built) return; @@ -219,37 +223,28 @@ etk_object_data_set(ETK_OBJECT(combobox->active_item_widget), "_Etk_Combobox_Window::Combobox", combobox); etk_container_add(ETK_CONTAINER(combobox->button), combobox->active_item_widget); - for (i = 0; i < combobox->num_cols; i++) - { - if (combobox->cols[i]->type != ETK_COMBOBOX_OTHER) - num_children++; - } - /* Build the active-item's children */ - if (num_children > 0) + if (combobox->num_cols > 0) { - combobox->active_item_children = malloc(num_children * sizeof(Etk_Widget *)); - for (i = 0, j = 0; i < combobox->num_cols; i++) + combobox->active_item_children = malloc(combobox->num_cols * sizeof(Etk_Widget *)); + for (i = 0; i < combobox->num_cols; i++) { - if (combobox->cols[i]->type == ETK_COMBOBOX_OTHER) - continue; - switch (combobox->cols[i]->type) { case ETK_COMBOBOX_LABEL: - combobox->active_item_children[j] = etk_label_new(NULL); - etk_widget_theme_parent_set(combobox->active_item_children[j], combobox->button); + combobox->active_item_children[i] = etk_label_new(NULL); + etk_widget_theme_parent_set(combobox->active_item_children[i], combobox->button); break; case ETK_COMBOBOX_IMAGE: - combobox->active_item_children[j] = etk_image_new(); + combobox->active_item_children[i] = etk_image_new(); break; default: + combobox->active_item_children[i] = NULL; break; } - etk_widget_parent_set(combobox->active_item_children[j], combobox->active_item_widget); - etk_widget_internal_set(combobox->active_item_children[j], ETK_TRUE); - etk_widget_show(combobox->active_item_children[j]); - j++; + etk_widget_internal_set(combobox->active_item_children[i], ETK_TRUE); + etk_widget_parent_set(combobox->active_item_children[i], combobox->active_item_widget); + etk_widget_show(combobox->active_item_children[i]); } } else @@ -352,7 +347,8 @@ * - If the type of the corresponding column is ETK_COMBOBOX_IMAGE, the argument must be an "Etk_Image *" @n * - If the type of the corresponding column is ETK_COMBOBOX_OTHER, the argument must be an "Etk_Widget *" * @return Returns the new item - * @note Unlike other widgets, the new item will be automatically shown, so you won't have to call etk_widget_show() + * @note Unlike other widgets, the new item and its children will be automatically shown, so you won't have + * to call etk_widget_show() */ Etk_Combobox_Item *etk_combobox_item_insert_valist(Etk_Combobox *combobox, Etk_Combobox_Item *after, va_list args) { @@ -376,7 +372,6 @@ item = ETK_COMBOBOX_ITEM(etk_widget_new(ETK_COMBOBOX_ITEM_TYPE, "theme_group", "item", "theme_parent", combobox, "visible", ETK_TRUE, NULL)); item->combobox = combobox; - item->data_free_cb = NULL; item->prev = after; item->next = after ? after->next : NULL; @@ -397,15 +392,19 @@ { case ETK_COMBOBOX_LABEL: item->widgets[i] = etk_label_new(va_arg(args, char *)); + etk_widget_pass_mouse_events_set(item->widgets[i], ETK_TRUE); break; case ETK_COMBOBOX_IMAGE: + item->widgets[i] = ETK_WIDGET(va_arg(args, Etk_Widget *)); + etk_widget_pass_mouse_events_set(item->widgets[i], ETK_TRUE); + break; case ETK_COMBOBOX_OTHER: - item->widgets[i] = va_arg(args, Etk_Widget *); + item->widgets[i] = ETK_WIDGET(va_arg(args, Etk_Widget *)); + break; default: break; } etk_widget_parent_set(item->widgets[i], ETK_WIDGET(item)); - etk_widget_pass_mouse_events_set(item->widgets[i], ETK_TRUE); etk_widget_show(item->widgets[i]); } @@ -426,34 +425,8 @@ * @param item the item to remove from its combobox * @note You can also call etk_object_destroy() to remove an item from a combobox, it has the same effect */ -/* TODO: destroyed_cb instead of destructor?? */ void etk_combobox_item_remove(Etk_Combobox_Item *item) { - Etk_Combobox *combobox; - - if (!item || !(combobox = item->combobox)) - return; - - if (item->combobox->selected_item == item) - _etk_combobox_selected_item_set(item->combobox, NULL); - if (item->combobox->active_item == item) - etk_combobox_active_item_set(item->combobox, NULL); - - if (item->data && item->data_free_cb) - item->data_free_cb(item->data); - free(item->widgets); - - if (item->prev) - item->prev->next = item->next; - if (item->next) - item->next->prev = item->prev; - if (combobox->first_item == item) - combobox->first_item = NULL; - if (combobox->last_item == item) - combobox->last_item = NULL; - - /* We set "item->combobox" to NULL to prevent the destructor from calling etk_combobox_item_remove() again */ - item->combobox = NULL; etk_object_destroy(ETK_OBJECT(item)); } @@ -477,35 +450,34 @@ */ void etk_combobox_active_item_set(Etk_Combobox *combobox, Etk_Combobox_Item *item) { - if (!combobox || (item && item->combobox != combobox)) + int i; + + if (!combobox) + return; + if ((item && item->combobox != combobox) || !combobox->built) + { + ETK_WARNING("Unable to change the active-item of the combobox. The specified item does not belong " + "to the combobox or the combobox is not built yet."); return; + } /* Changes the children of the active-item widget */ - if (combobox->built) + for (i = 0; i < combobox->num_cols; i++) { - int i, j; - - for (i = 0, j = 0; i < combobox->num_cols; i++) + switch (combobox->cols[i]->type) { - if (combobox->cols[i]->type == ETK_COMBOBOX_OTHER) - continue; - - switch (combobox->cols[i]->type) - { - case ETK_COMBOBOX_LABEL: - etk_label_set(ETK_LABEL(combobox->active_item_children[j]), - item ? etk_label_get(ETK_LABEL(item->widgets[i])) : NULL); - break; - case ETK_COMBOBOX_IMAGE: - if (item) - etk_image_copy(ETK_IMAGE(combobox->active_item_children[j]), ETK_IMAGE(item->widgets[i])); - else - etk_image_set_from_file(ETK_IMAGE(combobox->active_item_children[j]), NULL, NULL); - break; - default: - break; - } - j++; + case ETK_COMBOBOX_LABEL: + etk_label_set(ETK_LABEL(combobox->active_item_children[i]), + item ? etk_label_get(ETK_LABEL(item->widgets[i])) : NULL); + break; + case ETK_COMBOBOX_IMAGE: + if (item) + etk_image_copy(ETK_IMAGE(combobox->active_item_children[i]), ETK_IMAGE(item->widgets[i])); + else + etk_image_set_from_file(ETK_IMAGE(combobox->active_item_children[i]), NULL, NULL); + break; + default: + break; } } @@ -784,12 +756,57 @@ } } +/* Initializes the combobox item */ +static void _etk_combobox_item_constructor(Etk_Combobox_Item *item) +{ + if (!item) + return; + + item->combobox = NULL; + item->prev = NULL; + item->next = NULL; + item->widgets = NULL; + item->data = NULL; + item->data_free_cb = NULL; + + etk_signal_connect("destroyed", ETK_OBJECT(item), ETK_CALLBACK(_etk_combobox_item_destroyed_cb), NULL); +} + /* Destroys the combobox item */ static void _etk_combobox_item_destructor(Etk_Combobox_Item *item) { if (!item) return; - etk_combobox_item_remove(item); + + if (item->data && item->data_free_cb) + item->data_free_cb(item->data); + free(item->widgets); +} + +/* Called when a combobox-item is destroyed. We use this function and not the destructor because + * the destructor is not called immediately after the etk_object_destroy() call, but we want to remove the item + * immediately from the combobox (the destructor is still used the free the memory though) */ +static void _etk_combobox_item_destroyed_cb(Etk_Object *object, void *data) +{ + Etk_Combobox_Item *item; + Etk_Combobox *combobox; + + if (!(item = ETK_COMBOBOX_ITEM(object)) || !(combobox = item->combobox)) + return; + + if (item->combobox->selected_item == item) + _etk_combobox_selected_item_set(item->combobox, NULL); + if (item->combobox->active_item == item) + etk_combobox_active_item_set(item->combobox, NULL); + + if (item->prev) + item->prev->next = item->next; + if (item->next) + item->next->prev = item->prev; + if (combobox->first_item == item) + combobox->first_item = item->next; + if (combobox->last_item == item) + combobox->last_item = item->prev; } /* Calculates the ideal size of the combobox */ @@ -858,65 +875,16 @@ } } -/*TODO: what if the theme item border are smaller/bigger than usual?!?! (important!!) */ - /* Resizes the combobox item to the allocated geometry */ static void _etk_combobox_item_size_allocate(Etk_Widget *widget, Etk_Geometry geometry) { Etk_Combobox_Item *item; Etk_Combobox *combobox; - Etk_Geometry col_geometry; - Etk_Geometry child_geometry; - int num_expandable_cols = 0; - int expandable_width = 0; - int total_width = 0; - int i; if (!(item = ETK_COMBOBOX_ITEM(widget)) || !(combobox = item->combobox)) return; - for (i = 0; i < combobox->num_cols; i++) - { - if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) - { - num_expandable_cols++; - expandable_width += combobox->cols[i]->width; - } - total_width += combobox->cols[i]->width; - } - - col_geometry.x = geometry.x; - col_geometry.y = geometry.y; - col_geometry.h = geometry.h; - for (i = 0; i < combobox->num_cols; i++) - { - if (num_expandable_cols == 0) - { - if (i != combobox->num_cols - 1) - col_geometry.w = combobox->cols[i]->width; - else - col_geometry.w = geometry.w - (col_geometry.x - geometry.x); - } - else - { - if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) - { - col_geometry.w = (combobox->cols[i]->width / (float)expandable_width) * - (geometry.w - (total_width - expandable_width)); - } - else - col_geometry.w = combobox->cols[i]->width; - } - - if (item->widgets[i]) - { - memcpy(&child_geometry, &col_geometry, sizeof(Etk_Geometry)); - etk_container_child_space_fill(item->widgets[i], &child_geometry, - combobox->cols[i]->fill_policy & ETK_COMBOBOX_FILL, ETK_TRUE, combobox->cols[i]->align, 0.5); - etk_widget_size_allocate(item->widgets[i], child_geometry); - } - col_geometry.x += col_geometry.w; - } + _etk_combobox_item_cells_render(combobox, item->widgets, geometry, ETK_FALSE); } /* Calculates the ideal size of the active item of the combobox (the item in the combobox button */ @@ -939,75 +907,17 @@ } } -/* TODO: can we factorize with above function? */ /* Resizes the active item of the combobox to the allocated geometry */ static void _etk_combobox_active_item_size_allocate(Etk_Widget *widget, Etk_Geometry geometry) { Etk_Combobox *combobox; - Etk_Geometry col_geometry; - Etk_Geometry child_geometry; - int num_expandable_cols = 0; - int num_children = 0; - int expandable_width = 0; - int total_width = 0; - int i, j; if (!widget) return; if (!(combobox = ETK_COMBOBOX(etk_object_data_get(ETK_OBJECT(widget), "_Etk_Combobox_Window::Combobox")))) return; - for (i = 0; i < combobox->num_cols; i++) - { - if (combobox->cols[i]->type == ETK_COMBOBOX_OTHER) - continue; - - num_children++; - if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) - { - num_expandable_cols++; - expandable_width += combobox->cols[i]->width; - } - total_width += combobox->cols[i]->width; - } - - col_geometry.x = geometry.x; - col_geometry.y = geometry.y; - col_geometry.h = geometry.h; - for (i = 0, j = 0; i < combobox->num_cols; i++) - { - if (combobox->cols[i]->type == ETK_COMBOBOX_OTHER) - continue; - - if (num_expandable_cols == 0) - { - if (j != num_children - 1) - col_geometry.w = combobox->cols[i]->width; - else - col_geometry.w = geometry.w - (col_geometry.x - geometry.x); - } - else - { - if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) - { - col_geometry.w = (combobox->cols[i]->width / (float)expandable_width) * - (geometry.w - (total_width - expandable_width)); - } - else - col_geometry.w = combobox->cols[i]->width; - } - - if (combobox->active_item_children && combobox->active_item_children[j]) - { - memcpy(&child_geometry, &col_geometry, sizeof(Etk_Geometry)); - etk_container_child_space_fill(combobox->active_item_children[j], &child_geometry, - combobox->cols[i]->fill_policy & ETK_COMBOBOX_FILL, ETK_TRUE, combobox->cols[i]->align, 0.5); - etk_widget_size_allocate(combobox->active_item_children[j], child_geometry); - } - - col_geometry.x += col_geometry.w; - j++; - } + _etk_combobox_item_cells_render(combobox, combobox->active_item_children, geometry, ETK_TRUE); } /************************** @@ -1208,6 +1118,68 @@ } } +/* Renders the different cells of a combobox item */ +static void _etk_combobox_item_cells_render(Etk_Combobox *combobox, Etk_Widget **cells, Etk_Geometry geometry, Etk_Bool ignore_other) +{ + Etk_Geometry col_geometry; + Etk_Geometry child_geometry; + int num_expandable_cols = 0; + int expandable_width = 0; + int total_width = 0; + int last_col = 0; + int i; + + for (i = 0; i < combobox->num_cols; i++) + { + if (ignore_other && (combobox->cols[i]->type == ETK_COMBOBOX_OTHER)) + continue; + + if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) + { + num_expandable_cols++; + expandable_width += combobox->cols[i]->width; + } + total_width += combobox->cols[i]->width; + last_col = i; + } + + col_geometry.x = geometry.x; + col_geometry.y = geometry.y; + col_geometry.h = geometry.h; + for (i = 0; i < combobox->num_cols; i++) + { + if (ignore_other && (combobox->cols[i]->type == ETK_COMBOBOX_OTHER)) + continue; + + if (num_expandable_cols == 0) + { + if (i == last_col) + col_geometry.w = geometry.w - (col_geometry.x - geometry.x); + else + col_geometry.w = combobox->cols[i]->width; + } + else + { + if (combobox->cols[i]->fill_policy & ETK_COMBOBOX_EXPAND) + { + col_geometry.w = (combobox->cols[i]->width / (float)expandable_width) * + (geometry.w - (total_width - expandable_width)); + } + else + col_geometry.w = combobox->cols[i]->width; + } + + if (cells[i]) + { + child_geometry = col_geometry; + etk_container_child_space_fill(cells[i], &child_geometry, + combobox->cols[i]->fill_policy & ETK_COMBOBOX_FILL, ETK_TRUE, combobox->cols[i]->align, 0.5); + etk_widget_size_allocate(cells[i], child_geometry); + } + col_geometry.x += col_geometry.w; + } +} + /** @} */ /************************** @@ -1227,18 +1199,19 @@ * and no columns can be added anymore to the combobox once it is built. @n * Items can be added to the combobox with etk_combobox_item_prepend() and etk_combobox_item_append(). * The parameters of those functions depend on the type of widget of the column. @n @n - * Here is a simple example, where we create a combobox with two columns (one for the icon, one for the label), and - * then, we add two items to it: + * Here is a simple example, where we create a combobox with three columns (one for the icon, one for the label and + * one with a checkbox), and then, we add two items to it: * @code * Etk_Combobox *combobox; * * combobox = ETK_COMBOBOX(etk_combobox_new()); - * etk_combobox_column_add(combobox, ETK_COMBOBOX_IMAGE, 24, ETK_FALSE, ETK_FALSE, ETK_FALSE, 0.0, 0.5); - * etk_combobox_column_add(combobox, ETK_COMBOBOX_LABEL, 75, ETK_TRUE, ETK_FALSE, ETK_FALSE, 0.0, 0.5); + * etk_combobox_column_add(combobox, ETK_COMBOBOX_IMAGE, 24, ETK_COMBOBOX_NONE, 0.0); + * etk_combobox_column_add(combobox, ETK_COMBOBOX_LABEL, 75, ETK_COMBOBOX_EXPAND, 0.0); + * etk_combobox_column_add(combobox, ETK_COMBOBOX_OTHER, 32, ETK_COMBOBOX_OTHER, 1.0); * etk_combobox_build(combobox); * - * etk_combobox_item_append(combobox, image1, "item 1"); - * etk_combobox_item_append(combobox, image2, "item 2"); + * etk_combobox_item_append(combobox, image1, "item 1", checkbox1); + * etk_combobox_item_append(combobox, image2, "item 2", checkbox1); * @endcode @n * * \par Object Hierarchy: =================================================================== RCS file: /cvs/e/e17/libs/etk/src/lib/etk_combobox.h,v retrieving revision 1.15 retrieving revision 1.16 diff -u -3 -r1.15 -r1.16 --- etk_combobox.h 8 Mar 2007 18:16:01 -0000 1.15 +++ etk_combobox.h 9 Mar 2007 00:49:27 -0000 1.16 @@ -10,6 +10,7 @@ * - Combobox item separator! * - selected/unselected signal for items * - Should items could have children (i.e sub-windows) ? + * - make sure the items' children are not reparented */ /** ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs