Enlightenment CVS committal Author : pfritz Project : e17 Module : libs/ewl
Dir : e17/libs/ewl/src/lib Modified Files: ewl_combo.c ewl_combo.h Log Message: the combo can now have submenus, this works the similar to tree2 =================================================================== RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_combo.c,v retrieving revision 1.46 retrieving revision 1.47 diff -u -3 -r1.46 -r1.47 --- ewl_combo.c 6 Feb 2007 13:42:16 -0000 1.46 +++ ewl_combo.c 15 Mar 2007 06:04:17 -0000 1.47 @@ -3,12 +3,17 @@ #include "ewl_combo.h" #include "ewl_button.h" #include "ewl_cell.h" -#include "ewl_popup.h" +#include "ewl_context_menu.h" +#include "ewl_menu.h" #include "ewl_debug.h" #include "ewl_macros.h" #include "ewl_private.h" static void ewl_combo_cb_selected_change(Ewl_MVC *mvc); +Ewl_Widget *ewl_combo_submenu_new(Ewl_Combo *c, Ewl_Model *model, + void *mvc_data); +static void ewl_combo_popup_fill(Ewl_Combo *combo, Ewl_Container *c, + Ewl_Model *model, void *mvc_data); /** * @return Returns a pointer to a new combo on success, NULL on failure. @@ -42,8 +47,6 @@ int ewl_combo_init(Ewl_Combo *combo) { - Ewl_Widget *o; - DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR_RET("combo", combo, FALSE); @@ -68,7 +71,7 @@ /* * setup the popup */ - combo->popup = ewl_popup_new(); + combo->popup = ewl_context_menu_new(); ewl_popup_follow_set(EWL_POPUP(combo->popup), EWL_WIDGET(combo)); ewl_popup_type_set(EWL_POPUP(combo->popup), EWL_POPUP_TYPE_MENU_VERTICAL); @@ -81,20 +84,8 @@ EWL_FLAG_FILL_HFILL); ewl_object_alignment_set(EWL_OBJECT(combo->popup), EWL_FLAG_ALIGN_LEFT | EWL_FLAG_ALIGN_TOP); - ewl_callback_append(combo->popup, EWL_CALLBACK_MOUSE_DOWN, - ewl_combo_cb_popup_mouse_down, combo); - - /* - * setup the popbox - */ - o = ewl_vbox_new(); - ewl_container_child_append(EWL_CONTAINER(combo->popup), o); - ewl_container_redirect_set(EWL_CONTAINER(combo->popup), EWL_CONTAINER(o)); - ewl_widget_show(o); - - ewl_object_fill_policy_set(EWL_OBJECT(combo), - EWL_FLAG_FILL_HFILL | EWL_FLAG_FILL_VSHRINK); - + ewl_callback_append(combo->popup, EWL_CALLBACK_HIDE, + ewl_combo_cb_popup_hide, combo); DRETURN_INT(TRUE, DLEVEL_STABLE); } @@ -158,7 +149,6 @@ Ewl_Model *model; Ewl_View *view; void *mvc_data; - int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("data", data); @@ -186,24 +176,8 @@ DRETURN(DLEVEL_STABLE); ewl_container_reset(EWL_CONTAINER(combo->popup)); - for (i = 0; i < model->count(mvc_data); i++) - { - Ewl_Widget *cell; - Ewl_Widget *item; - - cell = ewl_cell_new(); - ewl_object_fill_policy_set(EWL_OBJECT(cell), - EWL_FLAG_FILL_HFILL); - ewl_container_child_append(EWL_CONTAINER(combo->popup), cell); - ewl_callback_append(cell, EWL_CALLBACK_CLICKED, - ewl_combo_cb_item_clicked, combo); - ewl_widget_show(cell); - - item = view->construct(); - view->assign(item, model->fetch(mvc_data, i, 0)); - ewl_container_child_append(EWL_CONTAINER(cell), item); - ewl_widget_show(item); - } + ewl_combo_popup_fill(combo, EWL_CONTAINER(combo->popup), model, + mvc_data); ewl_mvc_dirty_set(EWL_MVC(combo), FALSE); @@ -219,63 +193,27 @@ * @brief Callback for when the button to close the combo is clicked */ void -ewl_combo_cb_popup_mouse_down(Ewl_Widget *w, +ewl_combo_cb_popup_hide(Ewl_Widget *w, void *ev __UNUSED__, void *data) { - DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR("data", data); - - if (w == ewl_embed_focused_widget_get(EWL_EMBED(w))) { - Ewl_Combo *combo; - - combo = EWL_COMBO(data); - ewl_widget_hide(combo->popup); - ewl_widget_state_set(combo->button, "collapsed", - EWL_STATE_PERSISTENT); - } - - DLEAVE_FUNCTION(DLEVEL_STABLE); -} - -/** - * @internal - * @param w: UNUSED - * @param ev: UNUSED - * @param data: The combo widget - * @return Returns no value - * @brief Callback for when a combo item is clicked - */ -void -ewl_combo_cb_item_clicked(Ewl_Widget *w __UNUSED__, void *ev __UNUSED__, - void *data) -{ - int i; Ewl_Combo *combo; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("data", data); - combo = data; - - i = ewl_container_child_index_get(EWL_CONTAINER(combo->popup), w); - ewl_mvc_selected_set(EWL_MVC(combo), NULL, - ewl_mvc_data_get(EWL_MVC(combo)), i, -1); - - ewl_widget_hide(combo->popup); - ewl_widget_state_set(combo->button, "collapsed", - EWL_STATE_PERSISTENT); + combo = EWL_COMBO(data); + ewl_widget_state_set(combo->button, "collapsed", EWL_STATE_PERSISTENT); DLEAVE_FUNCTION(DLEVEL_STABLE); } + static void ewl_combo_cb_selected_change(Ewl_MVC *mvc) { Ewl_View *view; - Ewl_Model *model; Ewl_Combo *combo; Ewl_Widget *item = NULL; - void *mvc_data; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("mvc", mvc); @@ -283,10 +221,8 @@ combo = EWL_COMBO(mvc); view = ewl_mvc_view_get(mvc); - model = ewl_mvc_model_get(mvc); - mvc_data = ewl_mvc_data_get(mvc); - if (!mvc_data) + if (!ewl_mvc_data_get(mvc)) DRETURN(DLEVEL_STABLE); /* @@ -307,19 +243,289 @@ if (ewl_mvc_selected_count_get(mvc)) { Ewl_Selection_Idx *idx; + Ewl_Model *model; + void *mvc_data; idx = ewl_mvc_selected_get(mvc); + model = idx->sel.model; + mvc_data = idx->sel.data; + item = view->construct(); view->assign(item, model->fetch(mvc_data, idx->row, 0)); } - else if (view->header_fetch) - item = view->header_fetch(mvc_data, -1); + else if (view->header_fetch) + item = view->header_fetch(ewl_mvc_model_get(mvc), -1); if (item) { ewl_container_child_prepend(EWL_CONTAINER(combo->header), item); ewl_widget_show(item); } + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @internal + * @param w: UNUSED + * @param ev: The event data + * @param data: The combo box + * @return Returns no value + * @brief Callback for when the button to expand the combo is pressed + */ +Ewl_Widget * +ewl_combo_submenu_new(Ewl_Combo *combo, Ewl_Model *model, void *mvc_data) +{ + Ewl_Widget *menu; + Ewl_View *view; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("combo", combo, NULL); + + view = ewl_mvc_view_get(EWL_MVC(combo)); + + menu = ewl_menu_new(); + ewl_widget_appearance_set(EWL_MENU(menu)->popup, EWL_COMBO_TYPE + "/"EWL_POPUP_TYPE); + + /* nothing to do if we have no model/view or data */ + if (!model || !view) + DRETURN_PTR(NULL, DLEVEL_STABLE); + + ewl_combo_popup_fill(combo, EWL_CONTAINER(menu), model, mvc_data); + + ewl_button_label_set(EWL_BUTTON(menu), NULL); + ewl_button_image_set(EWL_BUTTON(menu), NULL, NULL); + ewl_object_fill_policy_set(EWL_OBJECT(menu), EWL_FLAG_FILL_HFILL); + ewl_container_redirect_set(EWL_CONTAINER(menu), + EWL_CONTAINER(EWL_BUTTON(menu)->body)); + + DRETURN_PTR(menu, DLEVEL_STABLE); +} + +/** + * @internal + * @param combo: The combo + * @param c: The container to fill + * @param model: The model to fill the container + * @param mvc_data: The data to fill the container + * @return Returns no value + * @brief fill the given container with the items + */ +static void +ewl_combo_popup_fill(Ewl_Combo *combo, Ewl_Container *c, Ewl_Model *model, void *mvc_data) +{ + Ewl_View *view; + int count; + int i; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("combo", combo); + + view = ewl_mvc_view_get(EWL_MVC(combo)); + + /* XXX put checks to make sure all the needed module and view + * function callbacks are setup */ + count = model->count(mvc_data); + for (i = 0; i < count; i++) + { + Ewl_Widget *o, *item; + + if (model->expansion.is && model->expansion.is(mvc_data, i)) + { + Ewl_Model *em; + void *data; + + em = model->expansion.model(mvc_data, i); + data = model->expansion.data(mvc_data, i); + o = ewl_combo_submenu_new(combo, em, data); + } + else + { + o = ewl_combo_cell_new(); + ewl_combo_cell_combo_set(EWL_COMBO_CELL(o), combo); + ewl_combo_cell_model_set(EWL_COMBO_CELL(o), model); + ewl_combo_cell_data_set(EWL_COMBO_CELL(o), mvc_data); + } + ewl_container_child_append(c, o); + ewl_widget_show(o); + + item = view->construct(); + view->assign(item, model->fetch(mvc_data, i, 0)); + ewl_container_child_append(EWL_CONTAINER(o), item); + ewl_widget_show(item); + } + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @return Returns a pointer to a new combo cell on success, NULL on failure. + * @brief Create a new combo cell + */ +Ewl_Widget * +ewl_combo_cell_new(void) +{ + Ewl_Combo_Cell *cell; + + DENTER_FUNCTION(DLEVEL_STABLE); + + cell = NEW(Ewl_Combo_Cell, 1); + if (!cell) + DRETURN_PTR(NULL, DLEVEL_STABLE); + + if (!ewl_combo_cell_init(cell)) + { + ewl_widget_destroy(EWL_WIDGET(cell)); + cell = NULL; + } + + DRETURN_PTR(EWL_WIDGET(cell), DLEVEL_STABLE); +} + +/** + * @param combo: The Ewl_Combo_Cell to initialize + * @return Returns TRUE on success or FALSE on failure + * @brief Initializes a combo cell to default values + */ +int +ewl_combo_cell_init(Ewl_Combo_Cell *cell) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("cell", cell, FALSE); + + if (!ewl_cell_init(EWL_CELL(cell))) + DRETURN_INT(FALSE, DLEVEL_STABLE); + + ewl_widget_inherit(EWL_WIDGET(cell), EWL_COMBO_CELL_TYPE); + ewl_object_fill_policy_set(EWL_OBJECT(cell), EWL_FLAG_FILL_HFILL); + ewl_callback_append(EWL_WIDGET(cell), EWL_CALLBACK_CLICKED, + ewl_combo_cell_cb_clicked, NULL); + + DRETURN_INT(TRUE, DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo_Cell to use + * @param combo: the parent combo widget + * @return Returns no value + */ +void +ewl_combo_cell_combo_set(Ewl_Combo_Cell *cell, Ewl_Combo *combo) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("cell", cell); + DCHECK_TYPE("cell", cell, EWL_COMBO_CELL_TYPE); + DCHECK_PARAM_PTR("combo", combo); + DCHECK_TYPE("combo", combo, EWL_COMBO_TYPE); + + cell->combo = combo; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo to use + * @return Returns the parent combo of the cell + */ +Ewl_Combo * +ewl_combo_cell_combo_get(Ewl_Combo_Cell *cell) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("cell", cell, NULL); + DCHECK_TYPE_RET("cell", cell, EWL_COMBO_TYPE, NULL); + + DRETURN_PTR(cell->combo, DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo_Cell to use + * @param model: the model for the cell + * @return Returns no value + */ +void +ewl_combo_cell_model_set(Ewl_Combo_Cell *cell, Ewl_Model *model) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("cell", cell); + DCHECK_TYPE("cell", cell, EWL_COMBO_CELL_TYPE); + DCHECK_PARAM_PTR("model", model); + + cell->model = model; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo to use + * @return Returns the model of the cell + */ +Ewl_Model * +ewl_combo_cell_model_get(Ewl_Combo_Cell *cell) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("cell", cell, NULL); + DCHECK_TYPE_RET("cell", cell, EWL_COMBO_CELL_TYPE, NULL); + + DRETURN_PTR(cell->model, DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo_Cell to use + * @param mvc_data: the data for the cell + * @return Returns no value + */ +void +ewl_combo_cell_data_set(Ewl_Combo_Cell *cell, void *mvc_data) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("cell", cell); + DCHECK_TYPE("cell", cell, EWL_COMBO_CELL_TYPE); + + cell->mvc_data = mvc_data; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @param cell: The Ewl_Combo to use + * @return Returns the model of the cell + */ +void * +ewl_combo_cell_data_get(Ewl_Combo_Cell *cell) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("cell", cell, NULL); + DCHECK_TYPE_RET("cell", cell, EWL_COMBO_CELL_TYPE, NULL); + + DRETURN_PTR(cell->mvc_data, DLEVEL_STABLE); +} +/** + * @internal + * @param w: UNUSED + * @param ev: UNUSED + * @param data: The combo widget + * @return Returns no value + * @brief Callback for when a combo item is clicked + */ +void +ewl_combo_cell_cb_clicked(Ewl_Widget *w, void *ev __UNUSED__, + void *data __UNUSED__) +{ + Ewl_Combo *combo; + Ewl_Model *model; + void *mvc_data; + int i; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("w", w); + + i = ewl_container_child_index_get(EWL_CONTAINER(w->parent), w); + + combo = ewl_combo_cell_combo_get(EWL_COMBO_CELL(w)); + model = ewl_combo_cell_model_get(EWL_COMBO_CELL(w)); + mvc_data = ewl_combo_cell_data_get(EWL_COMBO_CELL(w)); + + ewl_mvc_selected_set(EWL_MVC(combo), model, mvc_data, i, -1); DLEAVE_FUNCTION(DLEVEL_STABLE); } =================================================================== RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_combo.h,v retrieving revision 1.25 retrieving revision 1.26 diff -u -3 -r1.25 -r1.26 --- ewl_combo.h 4 Mar 2007 00:52:01 -0000 1.25 +++ ewl_combo.h 15 Mar 2007 06:04:17 -0000 1.26 @@ -3,6 +3,7 @@ #define EWL_COMBO_H #include "ewl_mvc.h" +#include "ewl_cell.h" /** * @addtogroup Ewl_Combo Ewl_Combo: A Simple Combo Box @@ -68,11 +69,62 @@ * Internally used callbacks, override at your own risk. */ void ewl_combo_cb_decrement_clicked(Ewl_Widget *w, void *ev, void *data); -void ewl_combo_cb_popup_mouse_down(Ewl_Widget *w, void *ev, void *data); -void ewl_combo_cb_item_clicked(Ewl_Widget *w, void *ev, void *data); +void ewl_combo_cb_popup_hide(Ewl_Widget *w, void *ev, void *data); + +/* + * Ewl_Combo_Cell + */ + +/** + * @def EWL_COMBO_CELL + * The type name for the Ewl_Combo_Cell widget + */ +#define EWL_COMBO_CELL_TYPE "combo_cell" + +/** + * @def EWL_COMBO_CELL_IS(w) + * Returns TRUE if the widget is an Ewl_Combo_Cell, FALSE otherwise + */ +#define EWL_COMBO_CELL_IS(w) (ewl_widget_type_is(EWL_WIDGET(w), EWL_COMBO_CELL_TYPE)) + +/** + * Typedef for the Ewl_Combo_Cell struct + */ +typedef struct Ewl_Combo_Cell Ewl_Combo_Cell; + +/** + * @def EWL_COMBO_CELL(c) + * Typecasts a pointer to an Ewl_Combo_Cell pointer + */ +#define EWL_COMBO_CELL(c) ((Ewl_Combo_Cell *)c) + +/** + * @brief Inherits from Ewl_Cell and is used internally for the combo box + */ +struct Ewl_Combo_Cell +{ + Ewl_Cell cell; /**< Inherit from the cell */ + Ewl_Combo *combo; /**< The parent combo */ + Ewl_Model *model; /**< The model that was used to build the + content of the cell */ + void *mvc_data; /**< The mvc data that was used to build the + content of the cell */ +}; + +Ewl_Widget *ewl_combo_cell_new(void); +int ewl_combo_cell_init(Ewl_Combo_Cell *c); +void ewl_combo_cell_combo_set(Ewl_Combo_Cell *c, Ewl_Combo *combo); +Ewl_Combo *ewl_combo_cell_combo_get(Ewl_Combo_Cell *c); + +void ewl_combo_cell_model_set(Ewl_Combo_Cell *c, Ewl_Model *model); +Ewl_Model *ewl_combo_cell_model_get(Ewl_Combo_Cell *c); + +void ewl_combo_cell_data_set(Ewl_Combo_Cell *c, void *mvc_data); +void *ewl_combo_cell_data_get(Ewl_Combo_Cell *c); /** * @} */ +void ewl_combo_cell_cb_clicked(Ewl_Widget *w, void *ev, void *data); #endif ------------------------------------------------------------------------- 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