Enlightenment CVS committal

Author  : moom16
Project : e17
Module  : proto

Dir     : e17/proto/etk/src/lib


Modified Files:
        etk_tree.c etk_tree.h 


Log Message:
* Adds a lot of function to the tree API
* Adds signals to know when a tree row is selected, collapsed, expanded, 
...


===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_tree.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -3 -r1.4 -r1.5
--- etk_tree.c  23 Oct 2005 08:05:35 -0000      1.4
+++ etk_tree.c  23 Oct 2005 22:05:38 -0000      1.5
@@ -17,6 +17,8 @@
  * @{
  */
 
+#define ETK_TREE_MIN_HEADER_WIDTH 10
+
 #define ETK_TREE_GRID_TYPE       (_etk_grid_type_get())
 #define ETK_TREE_GRID(obj)       (ETK_OBJECT_CAST((obj), ETK_TREE_GRID_TYPE, 
Etk_grid))
 #define ETK_IS_TREE_GRID(obj)    (ETK_OBJECT_CHECK_TYPE((obj), 
ETK_TREE_GRID_TYPE))
@@ -42,6 +44,17 @@
    Etk_Tree_Item_Object *objects;
 } Etk_Tree_Item_Objects;
 
+enum _Etk_Tree_Signal_Id
+{
+   ETK_TREE_ROW_SELECTED_SIGNAL,
+   ETK_TREE_ROW_UNSELECTED_SIGNAL,
+   ETK_TREE_ROW_EXPANDED_SIGNAL,
+   ETK_TREE_ROW_COLLAPSED_SIGNAL,
+   ETK_TREE_SELECT_ALL_SIGNAL,
+   ETK_TREE_UNSELECT_ALL_SIGNAL,
+   ETK_TREE_NUM_SIGNALS
+};
+
 enum _Etk_Tree_Property_Id
 {
    ETK_TREE_MODE_PROPERTY,
@@ -49,6 +62,19 @@
    ETK_TREE_HEADERS_VISIBLE_PROPERTY
 };
 
+enum _Etk_Tree_Col_Property_Id
+{
+   ETK_TREE_COL_TITLE_PROPERTY,
+   ETK_TREE_COL_TYPE_PROPERTY,
+   ETK_TREE_COL_WIDTH_PROPERTY,
+   ETK_TREE_COL_MIN_WIDTH_PROPERTY,
+   ETK_TREE_COL_VISIBLE_WIDTH_PROPERTY,
+   ETK_TREE_COL_VISIBLE_PROPERTY,
+   ETK_TREE_COL_RESIZABLE_PROPERTY,
+   ETK_TREE_COL_PLACE_PROPERTY,
+   ETK_TREE_COL_XALIGN_PROPERTY
+};
+
 static Etk_Type *_etk_grid_type_get();
 static void _etk_grid_constructor(Etk_grid *grid);
 static void _etk_grid_move_resize(Etk_Widget *widget, int x, int y, int w, int 
h);
@@ -61,6 +87,11 @@
 static void _etk_tree_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
 static void _etk_tree_size_allocate(Etk_Widget *widget, Etk_Geometry geometry);
 
+static void _etk_tree_col_constructor(Etk_Tree_Col *tree_col);
+static void _etk_tree_col_destructor(Etk_Tree_Col *tree_col);
+static void _etk_tree_col_property_set(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
+static void _etk_tree_col_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
+
 static void _etk_tree_expander_clicked_cb(void *data, Evas *e, Evas_Object 
*obj, void *event_info);
 static void _etk_tree_row_pressed_cb(void *data, Evas *e, Evas_Object *obj, 
void *event_info);
 static void _etk_tree_header_mouse_down_cb(Etk_Object *object, void *event, 
void *data);
@@ -80,9 +111,10 @@
 static void _etk_tree_col_realize(Etk_Tree *tree, int col_nth);
 static Etk_Tree_Col *etk_tree_col_to_resize_get(Etk_Tree_Col *col, int x);
 
-static void _etk_tree_node_unselect_all(Etk_Tree_Node *node);
 static void _etk_tree_node_select(Etk_Tree *tree, Etk_Tree_Node *node, 
Evas_Modifier *modifiers);
 
+static Etk_Signal *_etk_tree_signals[ETK_TREE_NUM_SIGNALS];
+
 /**************************
  *
  * Implementation
@@ -101,6 +133,13 @@
    {
       tree_type = etk_type_new("Etk_Tree", ETK_CONTAINER_TYPE, 
sizeof(Etk_Tree), ETK_CONSTRUCTOR(_etk_tree_constructor), 
ETK_DESTRUCTOR(_etk_tree_destructor), NULL);
 
+      _etk_tree_signals[ETK_TREE_ROW_SELECTED_SIGNAL] = 
etk_signal_new("row_selected", tree_type, -1, etk_marshaller_VOID__POINTER, 
NULL, NULL);
+      _etk_tree_signals[ETK_TREE_ROW_UNSELECTED_SIGNAL] = 
etk_signal_new("row_unselected", tree_type, -1, etk_marshaller_VOID__POINTER, 
NULL, NULL);
+      _etk_tree_signals[ETK_TREE_ROW_EXPANDED_SIGNAL] = 
etk_signal_new("row_expaned", tree_type, -1, etk_marshaller_VOID__POINTER, 
NULL, NULL);
+      _etk_tree_signals[ETK_TREE_ROW_COLLAPSED_SIGNAL] = 
etk_signal_new("row_collapsed", tree_type, -1, etk_marshaller_VOID__POINTER, 
NULL, NULL);
+      _etk_tree_signals[ETK_TREE_SELECT_ALL_SIGNAL] = 
etk_signal_new("select_all", tree_type, -1, etk_marshaller_VOID__VOID, NULL, 
NULL);
+      _etk_tree_signals[ETK_TREE_UNSELECT_ALL_SIGNAL] = 
etk_signal_new("unselect_all", tree_type, -1, etk_marshaller_VOID__VOID, NULL, 
NULL);
+
       etk_type_property_add(tree_type, "mode", ETK_TREE_MODE_PROPERTY, 
ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE,  
etk_property_value_int(ETK_TREE_MODE_LIST));
       etk_type_property_add(tree_type, "multiple_select", 
ETK_TREE_MULTIPLE_SELECT_PROPERTY, ETK_PROPERTY_BOOL, 
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_bool(TRUE));
       etk_type_property_add(tree_type, "headers_visible", 
ETK_TREE_HEADERS_VISIBLE_PROPERTY, ETK_PROPERTY_BOOL, 
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_bool(TRUE));
@@ -122,16 +161,43 @@
 }
 
 /**
+ * @brief Gets the type of an Etk_Tree_Col
+ * @return Returns the type on an Etk_Tree_Col
+ */
+Etk_Type *etk_tree_col_type_get()
+{
+   static Etk_Type *tree_col_type = NULL;
+
+   if (!tree_col_type)
+   {
+      tree_col_type = etk_type_new("Etk_Tree_Col", ETK_OBJECT_TYPE, 
sizeof(Etk_Tree_Col), ETK_CONSTRUCTOR(_etk_tree_col_constructor), 
ETK_DESTRUCTOR(_etk_tree_col_destructor), NULL);
+
+      etk_type_property_add(tree_col_type, "title",         
ETK_TREE_COL_TITLE_PROPERTY,           ETK_PROPERTY_STRING, 
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_string(NULL));
+      etk_type_property_add(tree_col_type, "cell_type",     
ETK_TREE_COL_TYPE_PROPERTY,            ETK_PROPERTY_INT,    
ETK_PROPERTY_READABLE,           NULL);
+      etk_type_property_add(tree_col_type, "width",         
ETK_TREE_COL_WIDTH_PROPERTY,           ETK_PROPERTY_INT,    
ETK_PROPERTY_READABLE_WRITABLE,  
etk_property_value_int(ETK_TREE_MIN_HEADER_WIDTH));
+      etk_type_property_add(tree_col_type, "min_width",     
ETK_TREE_COL_MIN_WIDTH_PROPERTY,       ETK_PROPERTY_INT,    
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_int(-1));
+      etk_type_property_add(tree_col_type, "visible_width", 
ETK_TREE_COL_VISIBLE_WIDTH_PROPERTY,   ETK_PROPERTY_INT,    
ETK_PROPERTY_READABLE,           NULL);
+      etk_type_property_add(tree_col_type, "visible",       
ETK_TREE_COL_VISIBLE_PROPERTY,         ETK_PROPERTY_BOOL,   
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_bool(TRUE));
+      etk_type_property_add(tree_col_type, "resizable",     
ETK_TREE_COL_RESIZABLE_PROPERTY,       ETK_PROPERTY_BOOL,   
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_bool(TRUE));
+      etk_type_property_add(tree_col_type, "place",         
ETK_TREE_COL_PLACE_PROPERTY,           ETK_PROPERTY_INT,    
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_int(0));
+      etk_type_property_add(tree_col_type, "xalign",        
ETK_TREE_COL_XALIGN_PROPERTY,          ETK_PROPERTY_FLOAT,  
ETK_PROPERTY_READABLE_WRITABLE,  etk_property_value_float(0.0));
+
+      tree_col_type->property_set = _etk_tree_col_property_set;
+      tree_col_type->property_get = _etk_tree_col_property_get;
+   }
+
+   return tree_col_type;
+}
+
+/**
  * @brief Creates a new column for a tree
  * @param tree a tree
  * @param title the tile of the column
  * @param type the type of the objects in the cells of the column
- * @param min_width the minimum width of the column
- * @param width the width of the column
- * @param resizable TRUE whether the column should be resizable
+ * @param width the requested width of the column. It won't be necessary the 
visible width of the column since it can be expanded to fit the available space
  * @return Returns the new column
  */
-Etk_Tree_Col *etk_tree_col_new(Etk_Tree *tree, const char *title, 
Etk_Tree_Col_Type type, int min_width, int width, Etk_Bool resizable)
+Etk_Tree_Col *etk_tree_col_new(Etk_Tree *tree, const char *title, 
Etk_Tree_Col_Type type, int width)
 {
    Etk_Tree_Col *new_col;
    Etk_Widget *new_header;
@@ -140,22 +206,25 @@
       return NULL;
 
    tree->columns = realloc(tree->columns, sizeof(Etk_Tree_Col *) * 
(tree->num_cols + 1));
-   new_col = malloc(sizeof(Etk_Tree_Col));
+   new_col = ETK_TREE_COL(etk_object_new(ETK_TREE_COL_TYPE, "title", title, 
"width", width, "visible", TRUE, "resizable", TRUE, NULL));
    tree->columns[tree->num_cols] = new_col;
 
    new_col->id = tree->num_cols;
+   new_col->place = new_col->id;
+   etk_object_notify(ETK_OBJECT(new_col), "place");
    new_col->tree = tree;
-   if (title)
-      new_col->title = strdup(title);
-   else
-      new_col->title = NULL;
    new_col->type = type;
-
-   new_col->min_width = ETK_MAX(0, min_width);
-   new_col->width = ETK_MAX(new_col->min_width, width);
-   new_col->place = new_col->id;
-   new_col->visible = TRUE;
-   new_col->resizable = resizable;
+   etk_object_notify(ETK_OBJECT(new_col), "col_type");
+   switch (type)
+   {
+      case ETK_TREE_COL_INT:
+      case ETK_TREE_COL_DOUBLE:
+         etk_tree_col_xalign_set(new_col, 1.0);
+         break;
+      default:
+         etk_tree_col_xalign_set(new_col, 0.0);
+         break;
+   }
 
    /* Create the header widget */
    new_header = etk_widget_new(ETK_BUTTON_TYPE, "theme_group", "tree_header", 
"label", title, "xalign", 0.0, NULL);
@@ -176,6 +245,18 @@
 }
 
 /**
+ * @brief Gets the number of columns of the tree
+ * @param tree a tree
+ * @return Returns the number of columns of the tree
+ */
+int etk_tree_num_cols_get(Etk_Tree *tree)
+{
+   if (!tree)
+      return 0;
+   return tree->num_cols;
+}
+
+/**
  * @brief Sets whether the column headers should be displayed
  * @param tree a tree
  * @param headers_visible TRUE if the column headers should be displayed
@@ -203,6 +284,214 @@
 }
 
 /**
+ * @brief Sets the title of the column
+ * @param col a tree column
+ * @param title the title to set
+ */
+void etk_tree_col_title_set(Etk_Tree_Col *col, const char *title)
+{
+   if (!col || !col->header)
+      return;
+   etk_button_label_set(ETK_BUTTON(col->header), title);
+   etk_object_notify(ETK_OBJECT(col), "title");
+}
+
+/**
+ * @brief Gets the title of the column
+ * @param col a tree column
+ * @return Returns the title of the column
+ */
+const char *etk_tree_col_title_get(Etk_Tree_Col *col)
+{
+   if (!col || !col->header)
+      return NULL;
+   return etk_button_label_get(ETK_BUTTON(col->header));
+}
+
+/**
+ * @brief Sets the requested width of the column. It won't be necessary the 
visible width of the column since it can be expanded to fit the available space
+ * @param col a tree column
+ * @param width the requested width to set
+ */
+void etk_tree_col_width_set(Etk_Tree_Col *col, int width)
+{
+   if (!col)
+      return;
+   col->requested_width = ETK_MAX(width, ETK_TREE_MIN_HEADER_WIDTH);
+   etk_object_notify(ETK_OBJECT(col), "width");
+   if (col->tree)
+      etk_widget_resize_queue(ETK_WIDGET(col->tree));
+}
+
+/**
+ * @brief Gets the requested width of the column
+ * @param col a tree column
+ * @return Returns the requested width of the column
+ */
+int etk_tree_col_width_get(Etk_Tree_Col *col)
+{
+   if (!col)
+      return 0;
+   return col->requested_width;
+}
+
+/**
+ * @brief Sets the minimum width of the column. The column couldn't be smaller 
than this width
+ * @param col a tree column
+ * @param min_width the minimum width to set. -1 to make etk calculate the 
min_width
+ */
+void etk_tree_col_min_width_set(Etk_Tree_Col *col, int min_width)
+{
+   if (!col || !col->header)
+      return;
+   etk_widget_size_request_set(col->header, min_width, -1);
+   etk_object_notify(ETK_OBJECT(col), "min_width");
+}
+
+/**
+ * @brief Gets the minimum width of the column
+ * @param col a tree column
+ * @return Returns the minimum width of the column
+ */
+int etk_tree_col_min_width_get(Etk_Tree_Col *col)
+{
+   Etk_Size size;
+
+   if (!col || !col->header)
+      return 0;
+   etk_widget_size_request(col->header, &size);
+   return size.w;
+}
+
+/**
+ * @brief Sets whether the column can be resized by the user
+ * @param col a tree column
+ * @param resizable TRUE whether the column should be resizable
+ */
+void etk_tree_col_resizable_set(Etk_Tree_Col *col, Etk_Bool resizable)
+{
+   if (!col)
+      return;
+   col->resizable = resizable;
+   etk_object_notify(ETK_OBJECT(col), "resizable");
+   if (col->tree)
+      etk_widget_resize_queue(ETK_WIDGET(col->tree));
+}
+
+/**
+ * @brief Gets whether the column can be resized by the user
+ * @param col a tree column
+ * @return Returns TRUE if the column is resizable
+ */
+Etk_Bool etk_tree_col_resizable_get(Etk_Tree_Col *col)
+{
+   if (!col)
+      return FALSE;
+   return col->resizable;
+}
+
+/**
+ * @brief Sets whether the column is visible
+ * @param col a tree column
+ * @param visible TRUE whether the column should be visible
+ */
+void etk_tree_col_visible_set(Etk_Tree_Col *col, Etk_Bool visible)
+{
+   if (!col)
+      return;
+   col->visible = visible;
+   etk_object_notify(ETK_OBJECT(col), "visible");
+   if (col->tree)
+      etk_widget_resize_queue(ETK_WIDGET(col->tree));
+}
+
+/**
+ * @brief Gets whether the column is visible
+ * @param col a tree column
+ * @return Returns TRUE if the column is visible
+ */
+Etk_Bool etk_tree_col_visible_get(Etk_Tree_Col *col)
+{
+   if (!col)
+      return FALSE;
+   return col->visible;
+}
+
+/**
+ * @brief Sets the horizontal alignment of the column
+ * @param col a tree column
+ * @param xalign the horizontal alignment to set (0.0 for left, 1.0 for right)
+ */
+void etk_tree_col_xalign_set(Etk_Tree_Col *col, float xalign)
+{
+   if (!col)
+      return;
+
+   col->xalign = ETK_CLAMP(0.0, 1.0, xalign);
+   etk_object_notify(ETK_OBJECT(col), "xalign");
+   if (col->tree)
+      etk_widget_resize_queue(ETK_WIDGET(col->tree));
+}
+
+/**
+ * @brief Gets the horizontal alignment of the column
+ * @param col a tree column
+ * @return Returns the horizontal alignment of the column
+ */
+float etk_tree_col_xalign_get(Etk_Tree_Col *col)
+{
+   if (!col)
+      return 0.0;
+   return col->xalign;
+}
+
+/**
+ * @brief Reorders the the column
+ * @param col a tree column
+ * @param new_place the new place that the column should take (0 is the first 
column on the left of the tree, etk_tree_num_cols_get(tree) - 1 is the last one 
on the right)
+ */
+void etk_tree_col_reorder(Etk_Tree_Col *col, int new_place)
+{
+   int i;
+
+   if (!col || !col->tree || (col->place == new_place))
+      return;
+
+   new_place = ETK_CLAMP(new_place, 0, col->tree->num_cols - 1);
+   if (new_place < col->place)
+   {
+      for (i = 0; i < col->tree->num_cols; i++)
+      {
+         if (col->tree->columns[i]->place >= new_place && 
col->tree->columns[i]->place < col->place)
+            col->tree->columns[i]->place++;
+      }
+   }
+   else if (new_place > col->place)
+   {
+      for (i = 0; i < col->tree->num_cols; i++)
+      {
+         if (col->tree->columns[i]->place > col->place && 
col->tree->columns[i]->place <= new_place)
+            col->tree->columns[i]->place--;
+      }
+   }
+   col->place = new_place;
+   etk_object_notify(ETK_OBJECT(col), "place");
+   etk_widget_redraw_queue(ETK_WIDGET(col->tree));
+}
+
+/**
+ * @brief Gets the place of the column (0 is the first column on the left of 
the tree, etk_tree_num_cols_get(tree) - 1 is the last one on the right)
+ * @param col a tree column
+ * @param Returns the place of the column
+ */
+int etk_tree_col_place_get(Etk_Tree_Col *col)
+{
+   if (!col)
+      return 0;
+   return col->place;
+}
+
+/**
  * @brief Sets the mode used by the tree. The tree has to be not built
  * @param tree a tree
  * @param mode the mode which will be used by the tree: ETK_TREE_MODE_LIST 
(rows can not have children) or ETK_TREE_MODE_TREE (rows can have children)
@@ -241,7 +530,7 @@
 }
 
 /**
- * @brief Freezes the tree: it will not be updated until it is thawed (TODO: 
irregular verb?!) @n
+ * @brief Freezes the tree: it will not be updated until it is thawed @n
  * This function is useful when you want to add a lot of rows quickly.
  * @param tree a tree
  */
@@ -307,6 +596,7 @@
    ecore_list_goto_first(tree->root.child_rows);
    while ((row = ecore_list_next(tree->root.child_rows)))
       row->node.selected = TRUE;
+   etk_signal_emit(_etk_tree_signals[ETK_TREE_SELECT_ALL_SIGNAL], 
ETK_OBJECT(tree), NULL);
    etk_widget_redraw_queue(ETK_WIDGET(tree));
 }
 
@@ -319,55 +609,21 @@
    if (!tree)
       return;
 
-   /* TODO */
-   _etk_tree_node_unselect_all(&tree->root);
-   etk_widget_redraw_queue(ETK_WIDGET(tree));
-}
-
-/**
- * @brief Expands the row. The child rows of the row will be displayed. It 
will only take effect with a tree in the ETK_TREE_MODE_TREE mode
- * @param row a row
- */
-void etk_tree_row_expand(Etk_Tree_Row *row)
-{
-   Etk_Tree_Node *n;
-   float offset;
-
-   if (!row || row->node.expanded || !row->tree || (row->tree->mode != 
ETK_TREE_MODE_TREE))
-      return;
-
-   offset = row->tree->xscroll_percent * row->tree->item_height * 
row->tree->root.num_visible_children;
-   row->node.expanded = TRUE;
-   for (n = row->node.parent; n && n->expanded; n = n->parent)
-      n->num_visible_children += row->node.num_visible_children;
-   row->tree->xscroll_percent = offset / (row->tree->item_height * 
row->tree->root.num_visible_children);
-   row->tree->xscroll_percent = ETK_CLAMP(row->tree->xscroll_percent, 0.0, 
1.0);
-
-   if (!row->tree->frozen)
-      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
-}
-
-/**
- * @brief Collapses the row. The child rows of the row are no longer 
displayed. It will only take effect with a tree in the ETK_TREE_MODE_TREE mode
- * @param row a row
- */
-void etk_tree_row_collapse(Etk_Tree_Row *row)
-{
-   Etk_Tree_Node *n;
-   float offset;
-
-   if (!row || !row->node.expanded || !row->tree || (row->tree->mode != 
ETK_TREE_MODE_TREE))
-      return;
-
-   offset = row->tree->xscroll_percent * row->tree->item_height * 
row->tree->root.num_visible_children;
-   row->node.expanded = FALSE;
-   for (n = row->node.parent; n && n->expanded; n = n->parent)
-      n->num_visible_children -= row->node.num_visible_children;
-   row->tree->xscroll_percent = offset / (row->tree->item_height * 
row->tree->root.num_visible_children);
-   row->tree->xscroll_percent = ETK_CLAMP(row->tree->xscroll_percent, 0.0, 
1.0);
+   if (tree->last_selected)
+   {
+      tree->last_selected->selected = FALSE;
+      etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_UNSELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, tree->last_selected->row);
+   }
+   if (tree->mode == ETK_TREE_MODE_LIST && tree->multiple_select)
+   {
+      Etk_Tree_Row *row;
 
-   if (!row->tree->frozen)
-      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
+      ecore_list_goto_first(tree->root.child_rows);
+      while ((row = ecore_list_next(tree->root.child_rows)))
+         row->node.selected = FALSE;
+      etk_signal_emit(_etk_tree_signals[ETK_TREE_UNSELECT_ALL_SIGNAL], 
ETK_OBJECT(tree), NULL);
+   }
+   etk_widget_redraw_queue(ETK_WIDGET(tree));
 }
 
 /**
@@ -413,6 +669,22 @@
 }
 
 /**
+ * @brief Removes a row from the tree
+ * @param row the the row to remove
+ */
+void etk_tree_row_del(Etk_Tree_Row *row)
+{
+   if (!row)
+      return;
+
+   if (ecore_list_goto(row->node.parent->child_rows, row))
+      ecore_list_remove_destroy(row->node.parent->child_rows);
+   
+   if (!row->tree->frozen)
+      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
+}
+
+/**
  * @brief Removes all the rows of the tree 
  * @param tree a tree 
  */
@@ -425,11 +697,157 @@
    while (!ecore_list_is_empty(tree->root.child_rows))
       ecore_list_remove_destroy(tree->root.child_rows);
    
-   ecore_list_clear(tree->root.child_rows);
    if (!tree->frozen)
       etk_widget_redraw_queue(ETK_WIDGET(tree));
 }
 
+/**
+ * @brief Sets a value to the data member of a row. The date could be 
retrieved with @a etk_tree_row_data_get()
+ * @param row a row
+ * @param data the data to set
+ */
+void etk_tree_row_data_set(Etk_Tree_Row *row, void *data)
+{
+   if (!row)
+      return;
+   row->data = data;
+}
+
+/**
+ * @brief Gets the value of the data member of a row
+ * @param row a row
+ * @return Returns the value of the data member of a row
+ */
+void *etk_tree_row_data_get(Etk_Tree_Row *row)
+{
+   if (!row)
+      return NULL;
+   return row->data;
+}
+
+/**
+ * @brief Selects the row
+ * @param row the row to select
+ */
+void etk_tree_row_select(Etk_Tree_Row *row)
+{
+   if (!row)
+      return;
+   _etk_tree_node_select(row->tree, &row->node, NULL);
+}
+
+/**
+ * @brief Unselects the row
+ * @param row the row to unselect
+ */
+void etk_tree_row_unselect(Etk_Tree_Row *row)
+{
+   if (!row || !row->node.selected)
+      return;
+   
+   row->node.selected = FALSE;
+   etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_UNSELECTED_SIGNAL], 
ETK_OBJECT(row->tree), NULL, row);
+   if (!row->tree->frozen)
+      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
+}
+
+/**
+ * @brief Gets the selected row of the tree
+ * @param tree a tree
+ * @return Returns the selected row of the tree
+ */
+Etk_Tree_Row *etk_tree_selected_row_get(Etk_Tree *tree)
+{
+   if (!tree || !tree->last_selected || !tree->last_selected->selected)
+      return NULL;
+   return tree->last_selected->row;
+}
+
+/**
+ * @brief Gets all the selected rows of the tree
+ * @param tree a tree
+ * @return Returns an Ecore_List * containing the selected rows of the tree
+ * @warning The returned Ecore_List * should be freed with @a 
ecore_list_destroy()
+ */
+Ecore_List *etk_tree_selected_rows_get(Etk_Tree *tree)
+{
+   Ecore_List *selected_rows;
+
+   if (!tree)
+      return NULL;
+
+   if (tree->mode == ETK_TREE_MODE_TREE || !tree->multiple_select)
+   {
+      if (!tree->last_selected || !tree->last_selected->selected)
+         return NULL;
+      
+      selected_rows = ecore_list_new();
+      ecore_list_append(selected_rows, tree->last_selected);
+      return selected_rows;
+   }
+   else
+   {
+      Etk_Tree_Row *row;
+
+      selected_rows = ecore_list_new();
+      ecore_list_goto_first(tree->root.child_rows);
+      while ((row = ecore_list_next(tree->root.child_rows)))
+      {
+         if (row->node.selected)
+            ecore_list_append(selected_rows, row);
+      }
+      return selected_rows;
+   }
+}
+
+/**
+ * @brief Expands the row. The child rows of the row will be displayed. It 
will only take effect with a tree in the ETK_TREE_MODE_TREE mode
+ * @param row a row
+ */
+void etk_tree_row_expand(Etk_Tree_Row *row)
+{
+   Etk_Tree_Node *n;
+   float offset;
+
+   if (!row || row->node.expanded || !row->tree || (row->tree->mode != 
ETK_TREE_MODE_TREE))
+      return;
+
+   offset = row->tree->xscroll_percent * row->tree->item_height * 
row->tree->root.num_visible_children;
+   row->node.expanded = TRUE;
+   for (n = row->node.parent; n && n->expanded; n = n->parent)
+      n->num_visible_children += row->node.num_visible_children;
+   row->tree->xscroll_percent = offset / (row->tree->item_height * 
row->tree->root.num_visible_children);
+   row->tree->xscroll_percent = ETK_CLAMP(row->tree->xscroll_percent, 0.0, 
1.0);
+
+   etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_EXPANDED_SIGNAL], 
ETK_OBJECT(row->tree), NULL, row);
+   if (!row->tree->frozen)
+      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
+}
+
+/**
+ * @brief Collapses the row. The child rows of the row are no longer 
displayed. It will only take effect with a tree in the ETK_TREE_MODE_TREE mode
+ * @param row a row
+ */
+void etk_tree_row_collapse(Etk_Tree_Row *row)
+{
+   Etk_Tree_Node *n;
+   float offset;
+
+   if (!row || !row->node.expanded || !row->tree || (row->tree->mode != 
ETK_TREE_MODE_TREE))
+      return;
+
+   offset = row->tree->xscroll_percent * row->tree->item_height * 
row->tree->root.num_visible_children;
+   row->node.expanded = FALSE;
+   for (n = row->node.parent; n && n->expanded; n = n->parent)
+      n->num_visible_children -= row->node.num_visible_children;
+   row->tree->xscroll_percent = offset / (row->tree->item_height * 
row->tree->root.num_visible_children);
+   row->tree->xscroll_percent = ETK_CLAMP(row->tree->xscroll_percent, 0.0, 
1.0);
+
+   etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_COLLAPSED_SIGNAL], 
ETK_OBJECT(row->tree), NULL, row);
+   if (!row->tree->frozen)
+      etk_widget_redraw_queue(ETK_WIDGET(row->tree));
+}
+
 /**************************
  *
  * Etk specific functions
@@ -569,15 +987,10 @@
    for (i = 0; i < tree->num_cols; i++)
    {
       if (tree->columns[i])
-      {
-         free(tree->columns[i]->title);
-         free(tree->columns[i]);
-         /* TODO: etk_object_destroy("header"); */
-      }
+         etk_object_destroy(ETK_OBJECT(tree->columns[i]));
    }
    free(tree->columns);
-   /* TODO: */
-   /* etk_object_destroy(ETK_OBJECT(tree->grid)); */
+   /* TODO: etk_object_destroy(ETK_OBJECT(tree->grid)); */
 }
 
 /* Sets the property whose id is "property_id" to the value "value" */
@@ -646,6 +1059,21 @@
       return;
 
    /* Calculate the size of the cols */
+   for (i = 0; i < tree->num_cols; i++)
+   {
+      if (tree->headers_visible)
+      {
+         Etk_Size header_requested_size;
+
+         etk_widget_size_request(tree->columns[i]->header, 
&header_requested_size);
+         if (tree->columns[i]->place == 0)
+            header_requested_size.w -= tree->grid->left_inset;
+         tree->columns[i]->width = ETK_MAX(header_requested_size.w, 
tree->columns[i]->requested_width);
+      }
+      else
+         tree->columns[i]->width = tree->columns[i]->requested_width;
+   }
+
    first_visible_col = NULL;
    last_visible_col = NULL;
    for (i = 0; i < tree->num_cols; i++)
@@ -678,11 +1106,11 @@
             if (!tree->columns[j]->visible)
                break;
 
-
             tree->columns[j]->xoffset = xoffset;
             tree->columns[j]->visible_width = tree->columns[j]->width;
             if (tree->columns[j] == last_visible_col)
                tree->columns[j]->visible_width += freespace;
+            etk_object_notify(ETK_OBJECT(tree->columns[j]), "visible_width");
             xoffset += tree->columns[j]->visible_width;
             k++;
             break;
@@ -725,6 +1153,118 @@
 }
 
 /**************************
+ * Tree Col
+ **************************/
+
+/* Initializes the default values of the tree column */
+static void _etk_tree_col_constructor(Etk_Tree_Col *tree_col)
+{
+   if (!tree_col)
+      return;
+
+   tree_col->tree = NULL;
+   tree_col->id = 0;
+   tree_col->place = 0;
+   tree_col->xoffset = 0;
+   tree_col->requested_width = 0;
+   tree_col->width = 0;
+   tree_col->visible_width = 0;
+   tree_col->visible = TRUE;
+   tree_col->resizable = TRUE;
+   tree_col->xalign = 0.0;
+   tree_col->header = NULL;
+   tree_col->clip = NULL;
+   tree_col->separator = NULL;
+}
+
+/* Destroys the tree column */
+static void _etk_tree_col_destructor(Etk_Tree_Col *tree_col)
+{
+   if (!tree_col)
+      return;
+
+   /* TODO: etk_object_destroy("header"); */
+}
+
+/* Sets the property whose id is "property_id" to the value "value" */
+static void _etk_tree_col_property_set(Etk_Object *object, int property_id, 
Etk_Property_Value *value)
+{
+   Etk_Tree_Col *tree_col;
+
+   if (!(tree_col = ETK_TREE_COL(object)) || !value)
+      return;
+
+   switch (property_id)
+   {
+      case ETK_TREE_COL_TITLE_PROPERTY:
+         etk_tree_col_title_set(tree_col, 
etk_property_value_string_get(value));
+         break;
+      case ETK_TREE_COL_WIDTH_PROPERTY:
+         etk_tree_col_width_set(tree_col, etk_property_value_int_get(value));
+         break;
+      case ETK_TREE_COL_MIN_WIDTH_PROPERTY:
+         etk_tree_col_min_width_set(tree_col, 
etk_property_value_int_get(value));
+         break;
+      case ETK_TREE_COL_RESIZABLE_PROPERTY:
+         etk_tree_col_resizable_set(tree_col, 
etk_property_value_bool_get(value));
+         break;
+      case ETK_TREE_COL_VISIBLE_PROPERTY:
+         etk_tree_col_visible_set(tree_col, 
etk_property_value_bool_get(value));
+         break;
+      case ETK_TREE_COL_PLACE_PROPERTY:
+         etk_tree_col_reorder(tree_col, etk_property_value_int_get(value));
+         break;
+      case ETK_TREE_COL_XALIGN_PROPERTY:
+         etk_tree_col_xalign_set(tree_col, 
etk_property_value_float_get(value));
+         break;
+      default:
+         break;
+   }
+}
+
+/* Gets the value of the property whose id is "property_id" */
+static void _etk_tree_col_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value)
+{
+   Etk_Tree_Col *tree_col;
+
+   if (!(tree_col = ETK_TREE_COL(object)) || !value)
+      return;
+
+   switch (property_id)
+   {
+      case ETK_TREE_COL_TITLE_PROPERTY:
+         etk_property_value_string_set(value, 
etk_tree_col_title_get(tree_col));
+         break;
+      case ETK_TREE_COL_TYPE_PROPERTY:
+         etk_property_value_int_set(value, tree_col->type);
+         break;
+      case ETK_TREE_COL_WIDTH_PROPERTY:
+         etk_property_value_int_set(value, tree_col->requested_width);
+         break;
+      case ETK_TREE_COL_MIN_WIDTH_PROPERTY:
+         etk_property_value_int_set(value, 
etk_tree_col_min_width_get(tree_col));
+         break;
+      case ETK_TREE_COL_VISIBLE_WIDTH_PROPERTY:
+         etk_property_value_int_set(value, tree_col->visible_width);
+         break;
+      case ETK_TREE_COL_RESIZABLE_PROPERTY:
+         etk_property_value_bool_set(value, tree_col->resizable);
+         break;
+      case ETK_TREE_COL_VISIBLE_PROPERTY:
+         etk_property_value_bool_set(value, tree_col->visible);
+         break;
+      case ETK_TREE_COL_PLACE_PROPERTY:
+         etk_property_value_int_set(value, tree_col->place);
+         break;
+      case ETK_TREE_COL_XALIGN_PROPERTY:
+         etk_property_value_float_set(value, tree_col->xalign);
+         break;
+      default:
+         break;
+   }
+}
+
+/**************************
  *
  * Callbacks and handlers
  *
@@ -903,11 +1443,10 @@
       new_size = move_event->cur.canvas.x - 
col->tree->column_to_resize->header->geometry.x;
       if (col->tree->column_to_resize->place == 0)
          new_size -= col->tree->grid->left_inset;
-      new_size = ETK_MAX(col->tree->column_to_resize->min_width, new_size);
 
-      if (new_size != col->tree->column_to_resize->width)
+      if (new_size != col->tree->column_to_resize->requested_width)
       {
-         col->tree->column_to_resize->width = new_size;
+         col->tree->column_to_resize->requested_width = ETK_MAX(new_size, 
ETK_TREE_MIN_HEADER_WIDTH);
          etk_widget_resize_queue(ETK_WIDGET(col->tree));
       }
    }
@@ -1008,7 +1547,7 @@
          else
          {
             evas_object_resize(tree->columns[i]->clip, 
tree->columns[i]->visible_width, h);
-            if (i < tree->num_cols - 1)
+            if (tree->columns[i]->place < tree->num_cols - 1)
                evas_object_show(tree->columns[i]->separator);
             else
                evas_object_hide(tree->columns[i]->separator);
@@ -1073,7 +1612,7 @@
          evas_object_data_set(item_objects->rect_bg, "etk_row", row);
          evas_object_show(item_objects->rect_bg);
          if (row->node.selected)
-               evas_object_color_set(item_objects->rect_bg, 
tree->row_selected_color.r, tree->row_selected_color.g, 
tree->row_selected_color.b, tree->row_selected_color.a);
+            evas_object_color_set(item_objects->rect_bg, 
tree->row_selected_color.r, tree->row_selected_color.g, 
tree->row_selected_color.b, tree->row_selected_color.a);
          else
          {
             if ((first_row_color + i) % 2 == 0)
@@ -1207,12 +1746,14 @@
 
    new_row = malloc(sizeof(Etk_Tree_Row));
    new_row->tree = tree;
+   new_row->node.row = new_row;
    new_row->node.parent = node;
    new_row->node.child_rows = NULL;
    new_row->node.num_visible_children = 0;
    new_row->node.num_parent_children = 0;
    new_row->node.expanded = FALSE;
    new_row->node.selected = FALSE;
+   new_row->data = NULL;
 
    new_row->cells = malloc(sizeof(Etk_Tree_Cell) * tree->num_cols);
    while ((col = va_arg(args, Etk_Tree_Col *)))
@@ -1308,7 +1849,6 @@
    return new_row;
 }
 
-
 /* Creates the evas objects needed by a row */ 
 static Etk_Tree_Item_Objects *_etk_tree_item_objects_new(Etk_Tree *tree)
 {
@@ -1493,7 +2033,7 @@
    etk_widget_member_object_add(tree->grid, tree->columns[col_nth]->separator);
 }
 
-/* TODO: doc */
+/* Returns the col to resize according to the x position of the mouse in the 
column "col" */
 static Etk_Tree_Col *etk_tree_col_to_resize_get(Etk_Tree_Col *col, int x)
 {
    int i;
@@ -1520,33 +2060,17 @@
    return NULL;
 }
 
-/* Unselects recursively all the rows of the node */
-static void _etk_tree_node_unselect_all(Etk_Tree_Node *node)
-{
-   Etk_Tree_Row *row;
-
-   if (!node)
-      return;
-
-   node->selected = FALSE;
-   if (node->child_rows)
-   {
-      ecore_list_goto_first(node->child_rows);
-      while ((row = ecore_list_next(node->child_rows)))
-         _etk_tree_node_unselect_all(&row->node);
-   }
-}
-
-/* TODO: doc */
+/* Selects rows in the tree according to the keyboard modifiers and the 
clicked node */
 static void _etk_tree_node_select(Etk_Tree *tree, Etk_Tree_Node *node, 
Evas_Modifier *modifiers)
 {
    if (!tree || !node)
       return;
 
-   if (tree->mode == ETK_TREE_MODE_TREE || !tree->multiple_select)
+   if (tree->mode == ETK_TREE_MODE_TREE || !tree->multiple_select || 
!modifiers)
    {
       etk_tree_unselect_all(tree);
       node->selected = TRUE;
+      etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_SELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, node->row);
    }
    else
    {
@@ -1556,10 +2080,7 @@
             etk_tree_unselect_all(tree);
    
          if (!tree->last_selected)
-         {
             node->selected = TRUE;
-            tree->last_selected = node;
-         }
          else
          {
             Etk_Bool selected = FALSE;
@@ -1580,27 +2101,31 @@
             {
                etk_tree_unselect_all(tree);
                node->selected = TRUE;
-               tree->last_selected = node;
             }
          }
+         etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_SELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, node->row);
       }
       else if (evas_key_modifier_is_set(modifiers, "Control"))
       {
          if (node->selected)
+         {
             node->selected = FALSE;
+            etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_UNSELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, node->row);
+         }
          else
          {
             node->selected = TRUE;
-            tree->last_selected = node;
+            etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_SELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, node->row);
          }
       }
       else
       {
          etk_tree_unselect_all(tree);
          node->selected = TRUE;
-         tree->last_selected = node;
+         etk_signal_emit(_etk_tree_signals[ETK_TREE_ROW_SELECTED_SIGNAL], 
ETK_OBJECT(tree), NULL, node->row);
       }
    }
+   tree->last_selected = node;
 
    etk_widget_redraw_queue(ETK_WIDGET(tree->grid));
 }
===================================================================
RCS file: /cvsroot/enlightenment/e17/proto/etk/src/lib/etk_tree.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -3 -r1.4 -r1.5
--- etk_tree.h  23 Oct 2005 08:05:35 -0000      1.4
+++ etk_tree.h  23 Oct 2005 22:05:38 -0000      1.5
@@ -19,6 +19,13 @@
 /** @brief Check if the object is an Etk_Tree */
 #define ETK_IS_TREE(obj)    (ETK_OBJECT_CHECK_TYPE((obj), ETK_TREE_TYPE))
 
+/** @brief Gets the type of a tree column */
+#define ETK_TREE_COL_TYPE        (etk_tree_col_type_get())
+/** @brief Casts the object to an Etk_Tree_Col */
+#define ETK_TREE_COL(obj)        (ETK_OBJECT_CAST((obj), ETK_TREE_COL_TYPE, 
Etk_Tree_Col))
+/** @brief Check if the object is an Etk_Tree_Col */
+#define ETK_IS_TREE_COL(obj)     (ETK_OBJECT_CHECK_TYPE((obj), 
ETK_TREE_COL_TYPE))
+
 /**
  * @enum Etk_Tree_Col_Type
  * @brief The type of the objects of a column of a tree
@@ -48,6 +55,7 @@
  */
 struct _Etk_Tree_Node
 {
+   Etk_Tree_Row *row;
    Etk_Tree_Node *parent;
    Ecore_List *child_rows;
    int num_visible_children;
@@ -104,18 +112,21 @@
 struct _Etk_Tree_Col
 {
    /* private: */
+   /* Inherit form Etk_Object */
+   Etk_Object object;
+
    int id;
    Etk_Tree *tree;
-   char *title;
    Etk_Tree_Col_Type type;
 
    int xoffset;
-   int min_width;
+   int requested_width;
    int width;
    int visible_width;
    int place;
    Etk_Bool resizable;
    Etk_Bool visible;
+   float xalign;
    
    Evas_Object *clip;
    Evas_Object *separator;
@@ -134,6 +145,7 @@
    Etk_Tree_Node node;
 
    Etk_Tree_Cell *cells;
+   void *data;
 };
 
 /**
@@ -159,10 +171,28 @@
 void etk_tree_mode_set(Etk_Tree *tree, Etk_Tree_Mode mode);
 Etk_Tree_Mode etk_tree_mode_get(Etk_Tree *tree);
 
-Etk_Tree_Col *etk_tree_col_new(Etk_Tree *tree, const char *title, 
Etk_Tree_Col_Type type, int min_width, int width, Etk_Bool resizable);
+Etk_Type *etk_tree_col_type_get();
+Etk_Tree_Col *etk_tree_col_new(Etk_Tree *tree, const char *title, 
Etk_Tree_Col_Type type, int width);
+
+int etk_tree_num_cols_get(Etk_Tree *tree);
 void etk_tree_headers_visible_set(Etk_Tree *tree, Etk_Bool headers_visible);
 Etk_Bool etk_tree_headers_visible_get(Etk_Tree *tree);
 
+void etk_tree_col_title_set(Etk_Tree_Col *col, const char *title);
+const char *etk_tree_col_title_get(Etk_Tree_Col *col);
+void etk_tree_col_width_set(Etk_Tree_Col *col, int width);
+int etk_tree_col_width_get(Etk_Tree_Col *col);
+void etk_tree_col_min_width_set(Etk_Tree_Col *col, int min_width);
+int etk_tree_col_min_width_get(Etk_Tree_Col *col);
+void etk_tree_col_resizable_set(Etk_Tree_Col *col, Etk_Bool resizable);
+Etk_Bool etk_tree_col_resizable_get(Etk_Tree_Col *col);
+void etk_tree_col_visible_set(Etk_Tree_Col *col, Etk_Bool visible);
+Etk_Bool etk_tree_col_visible_get(Etk_Tree_Col *col);
+void etk_tree_col_reorder(Etk_Tree_Col *col, int new_place);
+int etk_tree_col_place_get(Etk_Tree_Col *col);
+void etk_tree_col_xalign_set(Etk_Tree_Col *col, float xalign);
+float etk_tree_col_xalign_get(Etk_Tree_Col *col);
+
 void etk_tree_build(Etk_Tree *tree);
 void etk_tree_freeze(Etk_Tree *tree);
 void etk_tree_thaw(Etk_Tree *tree);
@@ -172,14 +202,21 @@
 void etk_tree_select_all(Etk_Tree *tree);
 void etk_tree_unselect_all(Etk_Tree *tree);
 
-void etk_tree_row_fold(Etk_Tree_Row *row);
-void etk_tree_row_unfold(Etk_Tree_Row *row);
-
 Etk_Tree_Row *etk_tree_append(Etk_Tree *tree, ...);
 Etk_Tree_Row *etk_tree_append_to_row(Etk_Tree_Row *row, ...);
-
+void etk_tree_row_del(Etk_Tree_Row *row);
 void etk_tree_clear(Etk_Tree *tree);
 
+void etk_tree_row_data_set(Etk_Tree_Row *row, void *data);
+void *etk_tree_row_data_get(Etk_Tree_Row *row);
+
+void etk_tree_row_select(Etk_Tree_Row *row);
+void etk_tree_row_unselect(Etk_Tree_Row *row);
+Etk_Tree_Row *etk_tree_selected_row_get(Etk_Tree *tree);
+Ecore_List *etk_tree_selected_rows_get(Etk_Tree *tree);
+void etk_tree_row_expand(Etk_Tree_Row *row);
+void etk_tree_row_collapse(Etk_Tree_Row *row);
+
 /** @} */
 
 #endif




-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.
Get Certified Today * Register for a JBoss Training Course
Free Certification Exam for All Training Attendees Through End of 2005
Visit http://www.jboss.com/services/certification for more information
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to