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

Reply via email to