Enlightenment CVS committal Author : moom Project : e17 Module : proto
Dir : e17/proto/etk/src/lib Modified Files: Etk.h Makefile.am etk_combobox.c etk_scrolled_view.c etk_table.c etk_toplevel.c etk_toplevel.h etk_tree.c etk_tree2.c etk_tree2.h etk_types.h Added Files: etk_fixed.c etk_fixed.h Log Message: Lib: ---- * [Etk_Fixed] A new container that allows you to position widgets at fixed coords (see the test app of the scrolled view in etk_test for an example) * [Etk_Tree2] More work on Etk_Tree2: deletion and selection has been implemented Misc: ----- * [Theme] The sliders now look like those of e17 * [Theme] The theme of the rows have been improved (better colors imho) * [Autofoo] make dist is fixed =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/Etk.h,v retrieving revision 1.45 retrieving revision 1.46 diff -u -3 -r1.45 -r1.46 --- Etk.h 28 Nov 2006 21:40:07 -0000 1.45 +++ Etk.h 9 Dec 2006 09:56:32 -0000 1.46 @@ -40,6 +40,7 @@ #include "etk_entry.h" #include "etk_event.h" #include "etk_filechooser_widget.h" +#include "etk_fixed.h" #include "etk_frame.h" #include "etk_iconbox.h" #include "etk_image.h" =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/Makefile.am,v retrieving revision 1.49 retrieving revision 1.50 diff -u -3 -r1.49 -r1.50 --- Makefile.am 28 Nov 2006 21:40:07 -0000 1.49 +++ Makefile.am 9 Dec 2006 09:56:32 -0000 1.50 @@ -38,6 +38,7 @@ etk_entry.h \ etk_event.h \ etk_filechooser_widget.h \ +etk_fixed.h \ etk_frame.h \ etk_iconbox.h \ etk_image.h \ @@ -111,6 +112,7 @@ etk_entry.c \ etk_event.c \ etk_filechooser_widget.c \ +etk_fixed.c \ etk_frame.c \ etk_iconbox.c \ etk_image.c \ =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_combobox.c,v retrieving revision 1.31 retrieving revision 1.32 diff -u -3 -r1.31 -r1.32 --- etk_combobox.c 6 Oct 2006 17:04:14 -0000 1.31 +++ etk_combobox.c 9 Dec 2006 09:56:32 -0000 1.32 @@ -1301,7 +1301,7 @@ * @code * Etk_Combobox *combobox; * - * combobox = etk_combobox_new(); + * 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_build(combobox); =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_scrolled_view.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -3 -r1.24 -r1.25 --- etk_scrolled_view.c 20 Oct 2006 17:51:44 -0000 1.24 +++ etk_scrolled_view.c 9 Dec 2006 09:56:33 -0000 1.25 @@ -182,13 +182,13 @@ scrolled_view->hpolicy = ETK_POLICY_AUTO; scrolled_view->vpolicy = ETK_POLICY_AUTO; - scrolled_view->hscrollbar = etk_hscrollbar_new(0.0, 0.0, 0.0, 6.0, 40.0, 0.0); + scrolled_view->hscrollbar = etk_hscrollbar_new(0.0, 0.0, 0.0, 12.0, 50.0, 0.0); etk_widget_theme_parent_set(scrolled_view->hscrollbar, ETK_WIDGET(scrolled_view)); etk_widget_parent_set(scrolled_view->hscrollbar, ETK_WIDGET(scrolled_view)); etk_widget_internal_set(scrolled_view->hscrollbar, ETK_TRUE); etk_widget_show(scrolled_view->hscrollbar); - scrolled_view->vscrollbar = etk_vscrollbar_new(0.0, 0.0, 0.0, 6.0, 40.0, 0.0); + scrolled_view->vscrollbar = etk_vscrollbar_new(0.0, 0.0, 0.0, 12.0, 50.0, 0.0); etk_widget_theme_parent_set(scrolled_view->vscrollbar, ETK_WIDGET(scrolled_view)); etk_widget_parent_set(scrolled_view->vscrollbar, ETK_WIDGET(scrolled_view)); etk_widget_internal_set(scrolled_view->vscrollbar, ETK_TRUE); =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_table.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -3 -r1.19 -r1.20 --- etk_table.c 6 Oct 2006 17:04:15 -0000 1.19 +++ etk_table.c 9 Dec 2006 09:56:33 -0000 1.20 @@ -39,7 +39,7 @@ /** * @internal * @brief Gets the type of an Etk_Table - * @return Returns the type on an Etk_Table + * @return Returns the type of an Etk_Table */ Etk_Type *etk_table_type_get() { @@ -47,11 +47,15 @@ if (!table_type) { - table_type = etk_type_new("Etk_Table", ETK_CONTAINER_TYPE, sizeof(Etk_Table), ETK_CONSTRUCTOR(_etk_table_constructor), ETK_DESTRUCTOR(_etk_table_destructor)); + table_type = etk_type_new("Etk_Table", ETK_CONTAINER_TYPE, sizeof(Etk_Table), + ETK_CONSTRUCTOR(_etk_table_constructor), ETK_DESTRUCTOR(_etk_table_destructor)); - etk_type_property_add(table_type, "num_cols", ETK_TABLE_NUM_COLS_PROPERTY, ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(0)); - etk_type_property_add(table_type, "num_rows", ETK_TABLE_NUM_ROWS_PROPERTY, ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(0)); - etk_type_property_add(table_type, "homogeneous", ETK_TABLE_HOMOGENEOUS_PROPERTY, ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_FALSE)); + etk_type_property_add(table_type, "num_cols", ETK_TABLE_NUM_COLS_PROPERTY, + ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(0)); + etk_type_property_add(table_type, "num_rows", ETK_TABLE_NUM_ROWS_PROPERTY, + ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(0)); + etk_type_property_add(table_type, "homogeneous", ETK_TABLE_HOMOGENEOUS_PROPERTY, + ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_FALSE)); table_type->property_set = _etk_table_property_set; table_type->property_get = _etk_table_property_get; @@ -65,18 +69,12 @@ * @param num_cols the number of columns of the new table * @param num_rows the number of rows of the new table * @param homogeneous if homogeneous != 0, all the cells will have the same size + * @return Returns the new table */ Etk_Widget *etk_table_new(int num_cols, int num_rows, Etk_Bool homogeneous) { - Etk_Widget *new_widget; - Etk_Table *new_table; - - new_widget = etk_widget_new(ETK_TABLE_TYPE, NULL); - new_table = ETK_TABLE(new_widget); - etk_table_resize(new_table, num_cols, num_rows); - etk_table_homogeneous_set(new_table, homogeneous); - - return new_widget; + return etk_widget_new(ETK_TABLE_TYPE, "homogeneous", homogeneous, + "num_cols", num_cols, "num_rows", num_rows, NULL); } /** @@ -696,12 +694,6 @@ } } -/************************** - * - * Callbacks and handlers - * - **************************/ - /* Adds a child to the table */ static void _etk_table_child_add(Etk_Container *container, Etk_Widget *widget) { @@ -726,10 +718,15 @@ static Evas_List *_etk_table_children_get(Etk_Container *container) { Etk_Table *table; + Evas_List *children, *l; if (!(table = ETK_TABLE(container))) return NULL; - return table->children; + + children = NULL; + for (l = table->children; l; l = l->next) + children = evas_list_append(children, l->data); + return children; } /** @} */ =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_toplevel.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -3 -r1.2 -r1.3 --- etk_toplevel.c 20 Oct 2006 17:51:44 -0000 1.2 +++ etk_toplevel.c 9 Dec 2006 09:56:33 -0000 1.3 @@ -260,7 +260,7 @@ toplevel->pointer_set(toplevel, *current_pointer_ptr); } else - toplevel->pointer_set(toplevel, ETK_POINTER_DEFAULT); + toplevel->pointer_set(toplevel, ETK_POINTER_NONE); } } =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_toplevel.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -3 -r1.2 -r1.3 --- etk_toplevel.h 20 Oct 2006 17:51:44 -0000 1.2 +++ etk_toplevel.h 9 Dec 2006 09:56:33 -0000 1.3 @@ -22,6 +22,7 @@ /** @brief The different types of mouse pointer */ typedef enum Etk_Pointer_Type { + ETK_POINTER_NONE, ETK_POINTER_DEFAULT, ETK_POINTER_MOVE, ETK_POINTER_H_DOUBLE_ARROW, =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_tree.c,v retrieving revision 1.79 retrieving revision 1.80 diff -u -3 -r1.79 -r1.80 --- etk_tree.c 29 Oct 2006 11:39:54 -0000 1.79 +++ etk_tree.c 9 Dec 2006 09:56:33 -0000 1.80 @@ -2247,14 +2247,6 @@ etk_tree_row_expand(tree->last_selected); else if (strcmp(event->keyname, "Left") == 0 && tree->last_selected && tree->last_selected->selected) etk_tree_row_collapse(tree->last_selected); - else if (strcmp(event->keyname, "Home") == 0) - etk_range_value_set(vscrollbar_range, vscrollbar_range->lower); - else if (strcmp(event->keyname, "End") == 0) - etk_range_value_set(vscrollbar_range, vscrollbar_range->upper); - else if (strcmp(event->keyname, "Next") == 0) - etk_range_value_set(vscrollbar_range, vscrollbar_range->value + vscrollbar_range->page_increment); - else if (strcmp(event->keyname, "Prior") == 0) - etk_range_value_set(vscrollbar_range, vscrollbar_range->value - vscrollbar_range->page_increment); else if (strcmp(event->keyname, "space") == 0) { if (tree->last_selected) =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_tree2.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -3 -r1.1 -r1.2 --- etk_tree2.c 28 Nov 2006 21:40:07 -0000 1.1 +++ etk_tree2.c 9 Dec 2006 09:56:33 -0000 1.2 @@ -62,7 +62,7 @@ ETK_TREE2_MODE_PROPERTY, ETK_TREE2_MULTIPLE_SELECT_PROPERTY, ETK_TREE2_HEADERS_VISIBLE_PROPERTY, - ETK_TREE2_ROW_HEIGHT_PROPERTY + ETK_TREE2_ROWS_HEIGHT_PROPERTY }; enum Etk_Tree2_Col_Signal_Id @@ -106,6 +106,7 @@ static void _etk_tree2_realize_cb(Etk_Object *object, void *data); static void _etk_tree2_focus_cb(Etk_Object *object, void *event, void *data); static void _etk_tree2_unfocus_cb(Etk_Object *object, void *event, void *data); +static void _etk_tree2_key_down_cb(Etk_Object *object, Etk_Event_Key_Down *event, void *data); static void _etk_tree2_scroll_content_realize_cb(Etk_Object *object, void *data); static void _etk_tree2_scroll_content_unrealize_cb(Etk_Object *object, void *data); static void _etk_tree2_grid_realize_cb(Etk_Object *object, void *data); @@ -121,11 +122,18 @@ static void _etk_tree2_row_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _etk_tree2_row_expander_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _etk_tree2_purge_job(void *data); +static void _etk_tree2_purge(Etk_Tree2 *tree); +static void _etk_tree2_row_move_to_purge_pool(Etk_Tree2_Row *row); + +/* TODO: static void _etk_tree2_sort(Etk_Tree2 *tree); */ + static void _etk_tree2_col_realize(Etk_Tree2 *tree, int col_nth); static Etk_Tree2_Col *etk_tree2_col_to_resize_get(Etk_Tree2_Col *col, int x); -static void _etk_tree2_row_fields_set_valist_full(Etk_Tree2_Row *row, va_list args, Etk_Bool emit_signal); +static Etk_Tree2_Row *_etk_tree2_row_next_get_full(Etk_Tree2_Row *row, Etk_Bool only_visible); static Etk_Tree2_Row *_etk_tree2_row_next_to_render_get(Etk_Tree2_Row *row, int *depth); +static void _etk_tree2_row_fields_set_valist_full(Etk_Tree2_Row *row, va_list args, Etk_Bool emit_signal); static Etk_Tree2_Row_Object *_etk_tree2_row_object_create(Etk_Tree2 *tree); static void _etk_tree2_row_object_destroy(Etk_Tree2 *tree, Etk_Tree2_Row_Object *row_object); @@ -135,6 +143,8 @@ static Etk_Signal *_etk_tree2_signals[ETK_TREE2_NUM_SIGNALS]; static Etk_Signal *_etk_tree2_col_signals[ETK_TREE2_COL_NUM_SIGNALS]; +/* TODO: better doc of row_next_get()... (with a note about deleted rows...) */ + /************************** * @@ -183,7 +193,7 @@ ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_TRUE)); etk_type_property_add(tree2_type, "headers_visible", ETK_TREE2_HEADERS_VISIBLE_PROPERTY, ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_TRUE)); - etk_type_property_add(tree2_type, "row_height", ETK_TREE2_ROW_HEIGHT_PROPERTY, + etk_type_property_add(tree2_type, "rows_height", ETK_TREE2_ROWS_HEIGHT_PROPERTY, ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(DEFAULT_ROW_HEIGHT)); tree2_type->property_set = _etk_tree2_property_set; @@ -283,9 +293,8 @@ if (!tree || tree->multiple_select == multiple_select) return; - /* TODO: */ - /*if (!multiple_select) - etk_tree2_unselect_all(tree);*/ + if (!multiple_select) + etk_tree2_unselect_all(tree); tree->multiple_select = multiple_select; etk_object_notify(ETK_OBJECT(tree), "multiple_select"); } @@ -320,7 +329,7 @@ /** * @brief Gets whether or not the column-headers are visible * @param tree a tree - * @return Returns ETK_TRUE if the column headers are visible, ETK_FALSE otherwise + * @return Returns ETK_TRUE if the column-headers are visible, ETK_FALSE otherwise */ Etk_Bool etk_tree2_headers_visible_get(Etk_Tree2 *tree) { @@ -332,18 +341,18 @@ /** * @brief Sets the height of the rows of the tree * @param tree a tree - * @param row_height the row height to set. The minimum value is 12 + * @param rows_height the rows height to set. The minimum value is 12 */ -void etk_tree2_rows_height_set(Etk_Tree2 *tree, int row_height) +void etk_tree2_rows_height_set(Etk_Tree2 *tree, int rows_height) { if (!tree) return; - row_height = ETK_MAX(row_height, MIN_ROW_HEIGHT); - if (tree->row_height != row_height) + rows_height = ETK_MAX(rows_height, MIN_ROW_HEIGHT); + if (tree->rows_height != rows_height) { - tree->row_height = row_height; - etk_object_notify(ETK_OBJECT(tree), "row_height"); + tree->rows_height = rows_height; + etk_object_notify(ETK_OBJECT(tree), "rows_height"); etk_signal_emit_by_name("scroll_size_changed", ETK_OBJECT(tree->scroll_content), NULL); etk_widget_redraw_queue(ETK_WIDGET(tree)); } @@ -358,7 +367,7 @@ { if (!tree) return DEFAULT_ROW_HEIGHT; - return tree->row_height; + return tree->rows_height; } /** @@ -854,10 +863,11 @@ parent = after->parent; if (!parent) parent = &tree->root; - + new_row = malloc(sizeof(Etk_Tree2_Row)); new_row->data = NULL; new_row->data_free_cb = NULL; + new_row->delete_me = ETK_FALSE; new_row->selected = ETK_FALSE; new_row->unfolded = ETK_FALSE; @@ -910,21 +920,46 @@ if (!tree->frozen) { etk_signal_emit_by_name("scroll_size_changed", ETK_OBJECT(tree->scroll_content), NULL); - etk_widget_redraw_queue(ETK_WIDGET(tree->grid)); + etk_widget_redraw_queue(ETK_WIDGET(tree)); } return new_row; } -/* TODOC */ -void etk_tree2_row_del(Etk_Tree2_Row *row) +/** + * @brief Deletes an existing row and all its children. Note that the row will just be marked as deleted. + * It will be effectively deleted only during the next iteration of Ecore's main loop. Thus, you can still manipulate + * safely a row marked as deleted. + * @param row the row to delete + */ +void etk_tree2_row_delete(Etk_Tree2_Row *row) { - /* TODO: */ + if (!row || row->delete_me) + return; + + _etk_tree2_row_move_to_purge_pool(row); + + if (!row->tree->frozen) + { + etk_signal_emit_by_name("scroll_size_changed", ETK_OBJECT(row->tree->scroll_content), NULL); + etk_widget_redraw_queue(ETK_WIDGET(row->tree)); + } } -/* TODOC */ +/** + * @brief Deletes all the rows of the tree. Note that the rows will just be marked as deleted. They will be effectively + * deleted during the next iteration of Ecore's main loop. Thus, you can still manipulate safely the rows immediately + * after a clear. + */ void etk_tree2_clear(Etk_Tree2 *tree) { - /* TODO: */ + if (!tree) + return; + + while (tree->root.first_child) + _etk_tree2_row_move_to_purge_pool(tree->root.first_child); + + etk_signal_emit_by_name("scroll_size_changed", ETK_OBJECT(tree->scroll_content), NULL); + etk_widget_redraw_queue(ETK_WIDGET(tree)); } /** @@ -1008,6 +1043,48 @@ } /** + * @brief Sets the user data associated to the row. The data could be retrieved later with etk_tree2_row_data_get() + * @param row a row of the tree + * @param data the data to associate to the row + * @note This is equivalent to etk_tree2_row_data_set_full(row, data, NULL); + */ +void etk_tree2_row_data_set(Etk_Tree2_Row *row, void *data) +{ + etk_tree2_row_data_set_full(row, data, NULL); +} + +/** + * @brief Sets the user data associated to the row. The data could be retrieved later with etk_tree2_row_data_get(). + * You can also set a function to call to free automatically the data when the row is deleted + * @param row a row of the tree + * @param data the data to associate to the row + * @param free_cb a function to call to free the data automatically when the row is deleted + */ +void etk_tree2_row_data_set_full(Etk_Tree2_Row *row, void *data, void (*free_cb)(void *data)) +{ + if (!row) + return; + + if (row->data && row->data_free_cb) + row->data_free_cb(row->data); + + row->data = data; + row->data_free_cb = free_cb; +} + +/** + * @brief Gets the user data associated to the row (previously set with etk_tree2_row_data_set()). + * @param row a row of the tree + * @return Returns the user data associated to the row + */ +void *etk_tree2_row_data_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + return row->data; +} + +/** * @brief Selects all the rows of the tree * @param tree a tree * @note When you call etk_tree2_select_all(), for performance reasons, the signal "row_selected" is not emitted for @@ -1020,27 +1097,11 @@ if (!tree) return; - for (row = tree->root.first_child; row; ) - { + for (row = tree->root.first_child; row; row = _etk_tree2_row_next_get_full(row, ETK_FALSE)) row->selected = ETK_TRUE; - - if (row->first_child) - row = row->first_child; - else - { - for (row = row; row; row = row->parent) - { - if (row->next) - { - row = row->next; - break; - } - } - } - } - etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ALL_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL); - etk_widget_redraw_queue(ETK_WIDGET(row->tree)); + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ALL_SELECTED_SIGNAL], ETK_OBJECT(tree), NULL); + etk_widget_redraw_queue(ETK_WIDGET(tree)); } /** @@ -1056,27 +1117,11 @@ if (!tree) return; - for (row = tree->root.first_child; row; ) - { + for (row = tree->root.first_child; row; row = _etk_tree2_row_next_get_full(row, ETK_FALSE)) row->selected = ETK_FALSE; - - if (row->first_child) - row = row->first_child; - else - { - for (row = row; row; row = row->parent) - { - if (row->next) - { - row = row->next; - break; - } - } - } - } - etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ALL_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL); - etk_widget_redraw_queue(ETK_WIDGET(row->tree)); + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ALL_SELECTED_SIGNAL], ETK_OBJECT(tree), NULL); + etk_widget_redraw_queue(ETK_WIDGET(tree)); } /** @@ -1087,11 +1132,7 @@ { if (!row || row->selected) return; - - row->selected = ETK_TRUE; - etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL, row); - if (!row->tree->frozen) - etk_widget_redraw_queue(ETK_WIDGET(row->tree)); + _etk_tree2_row_select(row->tree, row, ETK_MODIFIER_NONE); } /** @@ -1182,6 +1223,100 @@ return !row->unfolded; } +/** + * @brief Gets the first row of the tree + * @param tree a tree + * @return Returns the first row of the tree, or NULL if the tree is empty + */ +Etk_Tree2_Row *etk_tree2_first_row_get(Etk_Tree2 *tree) +{ + if (!tree) + return NULL; + return tree->root.first_child; +} + +/** + * @brief Gets the last row of the tree + * @param tree a tree + * @return Returns the last row of the tree, or NULL if the tree is empty + */ +Etk_Tree2_Row *etk_tree2_last_row_get(Etk_Tree2 *tree) +{ + if (!tree) + return NULL; + return tree->root.last_child; +} + +/** + * @brief Gets the previous row before the specified row + * @param row a row + * @return Returns the previous row before the specified row, or NULL if the row is the first row of its parent + * @note This function does not return the previous visible row, but only the previous row that is on the same + * level as the specified row. So if some rows of the tree have children, you'll have to use etk_tree2_row_parent_get(), + * etk_tree2_row_first_child_get(), ... if you want to walk through all the rows of the tree. See the examples at + * the top of this page. + */ +Etk_Tree2_Row *etk_tree2_row_prev_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + return row->prev; +} + +/** + * @brief Gets the next row after the specified row + * @param row a row + * @return Returns the next row after the specified row, or NULL if the row is the last row of its parent + * @note This function does not return the next visible row, but only the next row that is on the same + * level as the specified row. So if some rows of the tree have children, you'll have to use etk_tree2_row_parent_get(), + * etk_tree2_row_first_child_get(), ... if you want to walk through all the rows of the tree. See the examples at + * the top of this page. + */ +Etk_Tree2_Row *etk_tree2_row_next_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + return row->next; +} + +/** + * @brief Gets the parent row of the specified row + * @param row a row + * @return Returns the parent row of the specified row, or NULL if the row is at the tree's root + */ +Etk_Tree2_Row *etk_tree2_row_parent_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + if (!row->parent || row->parent == &row->tree->root) + return NULL; + return row->parent; +} + +/** + * @brief Gets the first child of the specified row + * @param row a row + * @return Returns the first child of the row + */ +Etk_Tree2_Row *etk_tree2_row_first_child_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + return row->first_child; +} + +/** + * @brief Gets the last child of the specified row + * @param row a row + * @return Returns the last child of the row + */ +Etk_Tree2_Row *etk_tree2_row_last_child_get(Etk_Tree2_Row *row) +{ + if (!row) + return NULL; + return row->last_child; +} + /************************** * * Etk specific functions @@ -1235,6 +1370,7 @@ tree->grid_clip = NULL; tree->root.tree = tree; + tree->root.delete_me = ETK_FALSE; tree->root.selected = ETK_FALSE; tree->root.unfolded = ETK_TRUE; tree->root.data = NULL; @@ -1250,12 +1386,15 @@ tree->root.num_visible_children = 0; tree->total_rows = 0; + tree->last_selected_row = NULL; + tree->purge_pool = NULL; tree->row_objects = NULL; - tree->row_height = DEFAULT_ROW_HEIGHT; + tree->rows_height = DEFAULT_ROW_HEIGHT; tree->scroll_x = 0; tree->scroll_y = 0; + tree->purge_job = NULL; tree->mode = ETK_TREE2_MODE_LIST; tree->multiple_select = ETK_FALSE; tree->tree_contains_headers = ETK_TRUE; @@ -1263,7 +1402,6 @@ tree->frozen = ETK_FALSE; tree->built = ETK_FALSE; - ETK_WIDGET(tree)->size_request = _etk_tree2_size_request; ETK_WIDGET(tree)->size_allocate = _etk_tree2_size_allocate; @@ -1271,15 +1409,24 @@ etk_signal_connect("unrealize", ETK_OBJECT(tree), ETK_CALLBACK(_etk_tree2_unrealize_cb), NULL); etk_signal_connect("focus", ETK_OBJECT(tree), ETK_CALLBACK(_etk_tree2_focus_cb), NULL); etk_signal_connect("unfocus", ETK_OBJECT(tree), ETK_CALLBACK(_etk_tree2_unfocus_cb), NULL); + etk_signal_connect("key_down", ETK_OBJECT(tree), ETK_CALLBACK(_etk_tree2_key_down_cb), NULL); } +/* TODO: last selected when deleted... */ + /* Destroys the tree */ static void _etk_tree2_destructor(Etk_Tree2 *tree) { if (!tree) return; - + + /* TODO: more efficient cleaning?? */ etk_tree2_clear(tree); + _etk_tree2_purge(tree); + + if (tree->purge_job) + ecore_job_del(tree->purge_job); + free(tree->columns); } @@ -1374,7 +1521,7 @@ { for (i = 0; i < tree->num_cols; i++) { - etk_widget_size_request(tree->columns[i]->header, &header_size); + etk_widget_size_request_full(tree->columns[i]->header, &header_size, ETK_FALSE); if (header_size.h > max_header_height) max_header_height = header_size.h; } @@ -1642,7 +1789,7 @@ scroll_size->w = 0; for (i = 0; i < tree->num_cols; i++) scroll_size->w += tree->columns[i]->width; - scroll_size->h = tree->root.num_visible_children * tree->row_height; + scroll_size->h = tree->root.num_visible_children * tree->rows_height; } /************************** @@ -1789,7 +1936,14 @@ if (!tree->built) return; - /* Save the rows currently rendered so we can emit the "row_shown/hidden" signals */ + /* Remove the rows marked as "deleted" */ + if (tree->purge_job) + { + _etk_tree2_purge(tree); + tree->purge_job = NULL; + } + + /* Save the rows currently rendered so we could emit the "row_shown/hidden" signals later */ prev_visible_rows = NULL; new_visible_rows = NULL; for (l = tree->row_objects; l; l = l->next) @@ -1806,7 +1960,7 @@ int num_visible_rows; int current_num_rows; - num_visible_rows = (geometry.h / tree->row_height) + 2; + num_visible_rows = (geometry.h / tree->rows_height) + 2; current_num_rows = evas_list_count(tree->row_objects); if (current_num_rows < num_visible_rows) @@ -1848,15 +2002,11 @@ int depth; depth = 0; - row_id = tree->scroll_y / tree->row_height; - row_y = -(tree->scroll_y % tree->row_height); + row_id = tree->scroll_y / tree->rows_height; + row_y = -(tree->scroll_y % tree->rows_height); for (row = tree->root.first_child, i = 0; i < row_id && row; i++) row = _etk_tree2_row_next_to_render_get(row, &depth); show_expanders = (tree->total_rows > tree->root.num_children && first_visible_col); - /*if (tree->total_rows > tree->root.num_children && first_visible_col) - first_col_xoffset = 18 + CELL_HMARGINS; - else - first_col_xoffset = 0;*/ for (l = tree->row_objects; l; l = l->next) { @@ -1866,7 +2016,7 @@ { /* If there is still a row to render, we render the content of the row */ evas_object_move(row_object->background, geometry.x, geometry.y + row_y); - evas_object_resize(row_object->background, geometry.w, tree->row_height); + evas_object_resize(row_object->background, geometry.w, tree->rows_height); evas_object_show(row_object->background); edje_object_signal_emit(row_object->background, @@ -1899,7 +2049,7 @@ cell_geometry.x = geometry.x + col->xoffset + CELL_HMARGINS; cell_geometry.y = geometry.y + row_y + CELL_VMARGINS; cell_geometry.w = col->width - (2 * CELL_HMARGINS); - cell_geometry.h = tree->row_height - (2 * CELL_VMARGINS); + cell_geometry.h = tree->rows_height - (2 * CELL_VMARGINS); /* Render the expander of the row */ if (col == first_visible_col && show_expanders) @@ -1942,7 +2092,7 @@ } row = _etk_tree2_row_next_to_render_get(row, &depth); - row_y += tree->row_height; + row_y += tree->rows_height; row_id++; } } @@ -2061,6 +2211,28 @@ etk_widget_theme_signal_emit(tree->grid, "etk,state,unfocused", ETK_FALSE); } +/* Called when a key is pressed while the tree is focused */ +static void _etk_tree2_key_down_cb(Etk_Object *object, Etk_Event_Key_Down *event, void *data) +{ + Etk_Tree2 *tree; + + if (!(tree = ETK_TREE2(object))) + return; + + if (event->modifiers == ETK_MODIFIER_NONE) + { + } + else if (event->modifiers & ETK_MODIFIER_CTRL) + { + /* CTRL + A: Select all the rows */ + if (strcmp(event->keyname, "a") == 0) + { + etk_tree2_select_all(tree); + etk_signal_stop(); + } + } +} + /************************** * Tree Scroll Content **************************/ @@ -2255,20 +2427,30 @@ { Etk_Tree2_Row_Object *row_object; Etk_Event_Mouse_Down event; - //Evas_Coord x, y, w, h; if (!(row_object = data) || !row_object->row) return; etk_event_mouse_down_wrap(ETK_WIDGET(row_object->row->tree), event_info, &event); - /* Selects the corresponding row(s) */ - _etk_tree2_row_select(row_object->row->tree, row_object->row, event.modifiers); + /* We do not select a row on the "key-down" event if the row is already selected + * to allow the user to drag and drop several rows. The selection will be done on "key-up" */ + if (!row_object->row->selected || event.modifiers != ETK_MODIFIER_NONE) + _etk_tree2_row_select(row_object->row->tree, row_object->row, event.modifiers); } /* Called when the background of a row is released by the mouse */ static void _etk_tree2_row_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) { + Etk_Tree2_Row_Object *row_object; + Etk_Event_Mouse_Up event; + + if (!(row_object = data) || !row_object->row) + return; + + etk_event_mouse_up_wrap(ETK_WIDGET(row_object->row->tree), event_info, &event); + if (row_object->row->selected && event.modifiers == ETK_MODIFIER_NONE) + _etk_tree2_row_select(row_object->row->tree, row_object->row, ETK_MODIFIER_NONE); } /* Called when the expander of a row is released by the mouse */ @@ -2297,6 +2479,133 @@ * **************************/ +/* A job called when rows need to be deleted */ +static void _etk_tree2_purge_job(void *data) +{ + Etk_Tree2 *tree; + + if (!(tree = ETK_TREE2(data))) + return; + + _etk_tree2_purge(tree); + tree->purge_job = NULL; +} + +/* Deletes effectively all the rows marked as deleted */ +static void _etk_tree2_purge(Etk_Tree2 *tree) +{ + Evas_List *l; + Etk_Tree2_Row *row, *r, *next; + int i; + + if (!tree) + return; + + /* First we dissociate the row objects from the rows that will be deleted */ + for (l = tree->row_objects; l; l = l->next) + { + Etk_Tree2_Row_Object *row_object; + + row_object = l->data; + if (row_object->row && row_object->row->delete_me) + { + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_HIDDEN_SIGNAL], ETK_OBJECT(tree), NULL, row_object->row); + row_object->row = NULL; + } + } + + /* Then we delete all the rows of the purge pool */ + while (tree->purge_pool) + { + row = tree->purge_pool->data; + row->next = NULL; + for (r = row; r; r = next) + { + /* Get the next row to free after this one */ + if (r->first_child) + { + r->last_child->next = r->next; + r->next = r->first_child; + } + next = r->next; + + /* Free the row */ + if (r->cells_data) + { + for (i = 0; i < tree->num_cols; i++) + { + if (tree->columns[i]->model->cell_data_free) + tree->columns[i]->model->cell_data_free(tree->columns[i]->model, r->cells_data[i]); + free(r->cells_data[i]); + } + free(r->cells_data); + } + + if (r->data && r->data_free_cb) + r->data_free_cb(r->data); + + free(r); + } + tree->purge_pool = evas_list_remove_list(tree->purge_pool, tree->purge_pool); + } +} + +/* Moves a row of the tree to the list of rows to delete during the next iteration */ +static void _etk_tree2_row_move_to_purge_pool(Etk_Tree2_Row *row) +{ + Etk_Tree2 *tree; + Etk_Tree2_Row *r; + + if (!row || row->delete_me) + return; + + tree = row->tree; + + /* Mark the row and all its children as deleted */ + row->delete_me = ETK_TRUE; + tree->total_rows--; + for (r = row->first_child; r; ) + { + r->delete_me = ETK_TRUE; + tree->total_rows--; + + if (r->first_child) + r = r->first_child; + else + { + while (r && !r->next) + { + if (r->parent == row) + r = NULL; + else + r = r->parent; + } + r = r ? r->next : NULL; + } + } + + /* Move the row to the purge_pool */ + if (row->prev) + row->prev->next = row->next; + if (row->next) + row->next->prev = row->prev; + if (row->parent) + { + if (row->parent->first_child == row) + row->parent->first_child = row->next; + if (row->parent->last_child == row) + row->parent->last_child = row->prev; + row->parent->num_children--; + } + for (r = row->parent; r && r->unfolded; r = r->parent) + r->num_visible_children -= row->num_visible_children + 1; + + tree->purge_pool = evas_list_append(tree->purge_pool, row); + + if (!tree->purge_job) + tree->purge_job = ecore_job_add(_etk_tree2_purge_job, tree); +} + /* Creates the Evas objects of the corresponding column */ static void _etk_tree2_col_realize(Etk_Tree2 *tree, int col_nth) { @@ -2347,29 +2656,21 @@ return NULL; } -/* Sets the fields of a row */ -static void _etk_tree2_row_fields_set_valist_full(Etk_Tree2_Row *row, va_list args, Etk_Bool emit_signal) +/* Gets the next row after the specified row */ +/* TODO: make it public?? */ +static Etk_Tree2_Row *_etk_tree2_row_next_get_full(Etk_Tree2_Row *row, Etk_Bool only_visible) { - Etk_Tree2_Col *col; - va_list args2; - if (!row) - return; + return NULL; - va_copy(args2, args); - while ((col = va_arg(args2, Etk_Tree2_Col *))) + if (row->first_child && (row->unfolded || !only_visible)) + return row->first_child; + else { - if (col->model->cell_data_set) - { - col->model->cell_data_set(col->model, row->cells_data[col->id], &args2); - if (emit_signal) - etk_signal_emit(_etk_tree2_col_signals[ETK_TREE2_COL_CELL_VALUE_CHANGED], ETK_OBJECT(col), NULL, row); - } + while (row && !row->next) + row = row->parent; + return row ? row->next : NULL; } - va_end(args2); - - if (!row->tree->frozen) - etk_widget_redraw_queue(ETK_WIDGET(row->tree)); } /* Gets the next row to render */ @@ -2396,6 +2697,31 @@ } } +/* Sets the fields of a row */ +static void _etk_tree2_row_fields_set_valist_full(Etk_Tree2_Row *row, va_list args, Etk_Bool emit_signal) +{ + Etk_Tree2_Col *col; + va_list args2; + + if (!row) + return; + + va_copy(args2, args); + while ((col = va_arg(args2, Etk_Tree2_Col *))) + { + if (col->model->cell_data_set) + { + col->model->cell_data_set(col->model, row->cells_data[col->id], &args2); + if (emit_signal) + etk_signal_emit(_etk_tree2_col_signals[ETK_TREE2_COL_CELL_VALUE_CHANGED], ETK_OBJECT(col), NULL, row); + } + } + va_end(args2); + + if (!row->tree->frozen) + etk_widget_redraw_queue(ETK_WIDGET(row->tree)); +} + /* Creates a new row object and its subobjects */ static Etk_Tree2_Row_Object *_etk_tree2_row_object_create(Etk_Tree2 *tree) { @@ -2484,10 +2810,77 @@ if (!tree || !row) return; - if (!(modifiers & ETK_MODIFIER_CTRL) || !row->selected) - etk_tree2_row_select(row); + if (!tree->multiple_select) + { + if (row->selected) + { + /* Unselect the row */ + if (modifiers & ETK_MODIFIER_CTRL) + etk_tree2_row_unselect(row); + } + else + { + /* Unselect the selected row and select only the given row */ + if (tree->last_selected_row && tree->last_selected_row->selected) + etk_tree2_row_unselect(tree->last_selected_row); + else + etk_tree2_unselect_all(tree); + + row->selected = ETK_TRUE; + row->tree->last_selected_row = row; + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL, row); + } + } else - etk_tree2_row_unselect(row); + { + if ((modifiers & ETK_MODIFIER_SHIFT) && tree->last_selected_row) + { + Etk_Tree2_Row *r; + int cnt = 0; + + etk_tree2_unselect_all(tree); + + /* Walk through all the rows of the tree and select the rows + * between the last selected row and the given row */ + for (r = tree->root.first_child; r; r = _etk_tree2_row_next_get_full(r, ETK_FALSE)) + { + if (r == tree->last_selected_row) + cnt++; + if (r == row) + cnt++; + + if (cnt >= 1) + r->selected = ETK_TRUE; + if (cnt >= 2) + break; + } + + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL, row); + } + /* Invert the selected state of the given row */ + else if (modifiers & ETK_MODIFIER_CTRL) + { + if (row->selected) + etk_tree2_row_unselect(row); + else + { + row->selected = ETK_TRUE; + row->tree->last_selected_row = row; + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL, row); + } + } + else + { + /* Unselect all the rows and select only the given row */ + etk_tree2_unselect_all(tree); + row->selected = ETK_TRUE; + row->tree->last_selected_row = row; + etk_signal_emit(_etk_tree2_signals[ETK_TREE2_ROW_SELECTED_SIGNAL], ETK_OBJECT(row->tree), NULL, row); + } + } + + if (!row->tree->frozen) + etk_widget_redraw_queue(ETK_WIDGET(row->tree)); } /** @} */ =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_tree2.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -3 -r1.1 -r1.2 --- etk_tree2.h 28 Nov 2006 21:40:07 -0000 1.1 +++ etk_tree2.h 9 Dec 2006 09:56:33 -0000 1.2 @@ -5,6 +5,7 @@ #include "etk_widget.h" #include <stdarg.h> #include <Evas.h> +#include <Ecore_Job.h> #include "etk_types.h" /** @@ -88,13 +89,12 @@ int num_visible_children; void **cells_data; - //~ void *row_objects; - void *data; void (*data_free_cb)(void *data); - Etk_Bool unfolded; - Etk_Bool selected; + unsigned int delete_me : 1; + unsigned int unfolded : 1; + unsigned int selected : 1; }; /** @@ -121,14 +121,17 @@ Evas_Object *headers_clip; Evas_Object *grid_clip; - Etk_Tree2_Row root; int total_rows; + Etk_Tree2_Row root; + Etk_Tree2_Row *last_selected_row; + Evas_List *purge_pool; Evas_List *row_objects; - int row_height; + int rows_height; int scroll_x; int scroll_y; + Ecore_Job *purge_job; Etk_Color separator_color; Etk_Bool tree_contains_headers; Etk_Tree2_Mode mode; @@ -182,7 +185,7 @@ Etk_Tree2_Row *etk_tree2_row_insert(Etk_Tree2 *tree, Etk_Tree2_Row *parent, Etk_Tree2_Row *after, ...); Etk_Tree2_Row *etk_tree2_row_insert_valist(Etk_Tree2 *tree, Etk_Tree2_Row *parent, Etk_Tree2_Row *after, va_list args); /* TODO: Etk_Tree2_Row *etk_tree2_row_insert_sorted(Etk_Tree2 *tree, Etk_Tree2_Row *parent, ...); */ -void etk_tree2_row_del(Etk_Tree2_Row *row); +void etk_tree2_row_delete(Etk_Tree2_Row *row); void etk_tree2_clear(Etk_Tree2 *tree); void etk_tree2_row_fields_set(Etk_Tree2_Row *row, ...); @@ -190,6 +193,10 @@ void etk_tree2_row_fields_get(Etk_Tree2_Row *row, ...); void etk_tree2_row_fields_get_valist(Etk_Tree2_Row *row, va_list args); +void etk_tree2_row_data_set(Etk_Tree2_Row *row, void *data); +void etk_tree2_row_data_set_full(Etk_Tree2_Row *row, void *data, void (*free_cb)(void *data)); +void *etk_tree2_row_data_get(Etk_Tree2_Row *row); + void etk_tree2_select_all(Etk_Tree2 *tree); void etk_tree2_unselect_all(Etk_Tree2 *tree); void etk_tree2_row_select(Etk_Tree2_Row *row); @@ -199,6 +206,14 @@ void etk_tree2_row_fold(Etk_Tree2_Row *row); void etk_tree2_row_unfold(Etk_Tree2_Row *row); Etk_Bool etk_tree2_row_is_folded(Etk_Tree2_Row *row); + +Etk_Tree2_Row *etk_tree2_first_row_get(Etk_Tree2 *tree); +Etk_Tree2_Row *etk_tree2_last_row_get(Etk_Tree2 *tree); +Etk_Tree2_Row *etk_tree2_row_prev_get(Etk_Tree2_Row *row); +Etk_Tree2_Row *etk_tree2_row_next_get(Etk_Tree2_Row *row); +Etk_Tree2_Row *etk_tree2_row_parent_get(Etk_Tree2_Row *row); +Etk_Tree2_Row *etk_tree2_row_first_child_get(Etk_Tree2_Row *row); +Etk_Tree2_Row *etk_tree2_row_last_child_get(Etk_Tree2_Row *row); /** @} */ =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_types.h,v retrieving revision 1.58 retrieving revision 1.59 diff -u -3 -r1.58 -r1.59 --- etk_types.h 28 Nov 2006 21:40:07 -0000 1.58 +++ etk_types.h 9 Dec 2006 09:56:33 -0000 1.59 @@ -57,8 +57,9 @@ typedef struct Etk_Event_Mouse_Up Etk_Event_Mouse_Up; typedef struct Etk_Event_Mouse_Wheel Etk_Event_Mouse_Wheel; typedef struct _Etk_Event_Selection_Request Etk_Event_Selection_Request; -typedef struct Etk_Frame Etk_Frame; typedef struct _Etk_Filechooser_Widget Etk_Filechooser_Widget; +typedef struct Etk_Fixed Etk_Fixed; +typedef struct Etk_Frame Etk_Frame; typedef struct Etk_Iconbox Etk_Iconbox; typedef struct Etk_Iconbox_Icon Etk_Iconbox_Icon; typedef struct Etk_Iconbox_Model Etk_Iconbox_Model; ------------------------------------------------------------------------- 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