tasn pushed a commit to branch master. http://git.enlightenment.org/bindings/cxx/eflxx.git/commit/?id=02acfd034944af4002f6276ecbe415412d9c36e2
commit 02acfd034944af4002f6276ecbe415412d9c36e2 Author: Andreas Volz <[email protected]> Date: Wed May 26 21:01:36 2010 +0000 added more GenList API wrapper SVN revision: 49215 --- elementaryxx/include/elementaryxx/GenList.h | 252 ++++++++++++++++++++- .../elementaryxx/GenListColumnConstructor.h | 25 ++ .../include/elementaryxx/GenListColumnSelector.h | 23 ++ .../include/elementaryxx/GenListDataModel.h | 16 +- elementaryxx/include/elementaryxx/GenListItem.h | 4 + elementaryxx/include/elementaryxx/Makefile.am | 4 +- elementaryxx/src/GenList.cpp | 52 ++++- elementaryxx/src/GenListColumnConstructor.cpp | 4 + elementaryxx/src/GenListColumnSelector.cpp | 4 + elementaryxx/src/GenListDataModel.cpp | 66 ++++-- elementaryxx/src/Makefile.am | 4 +- 11 files changed, 422 insertions(+), 32 deletions(-) diff --git a/elementaryxx/include/elementaryxx/GenList.h b/elementaryxx/include/elementaryxx/GenList.h index 0e1a27a..021931c 100644 --- a/elementaryxx/include/elementaryxx/GenList.h +++ b/elementaryxx/include/elementaryxx/GenList.h @@ -13,11 +13,247 @@ namespace Elmxx { +/* forward declarations */ +class GenListItem; +class GenListColumnConstructor; +class GenListColumnSelector; + /*! - * smart callbacks called: - + * @defgroup Genlist Genlist + * + * The aim was to have more expansive list that the simple list in + * Elementary that could have more flexible items and allow many more entries + * while still being fast and low on memory usage. At the same time it was + * also made to be able to do tree structures. But the price to pay is more + * complexity when it comes to usage. If all you want is a simple list with + * icons and a single label, use the normal List object. + * + * Signals that you can add callbacks for are: + * + * clicked - This is called when a user has double-clicked an item. The + * event_info parameter is the genlist item that was double-clicked. + * + * selected - This is called when a user has made an item selected. The + * event_info parameter is the genlist item that was selected. + * + * unselected - This is called when a user has made an item unselected. The + * event_info parameter is the genlist item that was unselected. + * + * expanded - This is called when elm_genlist_item_expanded_set() is called + * and the item is now meant to be expanded. The event_info parameter is the + * genlist item that was indicated to expand. It is the job of this callback + * to then fill in the child items. + * + * contracted - This is called when elm_genlist_item_expanded_set() is called + * and the item is now meant to be contracted. The event_info parameter is + * the genlist item that was indicated to contract. It is the job of this + * callback to then delete the child items + * + * expand,request - This is called when a user has indicated they want to + * expand a tree branch item. The callback should decide if the item can + * expand (has any children) and then call elm_genlist_item_expanded_set() + * appropriately to set the state. The event_info parameter is the genlist + * item that was indicated to expand. + * + * contract,request - This is called when a user has indicated they want to + * contract a tree branch item. The callback should decide if the item can + * contract (has any children) and then call elm_genlist_item_expanded_set() + * appropriately to set the state. The event_info parameter is the genlist + * item that was indicated to contract. + * + * realized - This is called when the item in the list is created as a real + * evas object. event_info parameter is the genlist item that was created. + * The object may be deleted at any time, so it is up to the caller to + * not use the object pointer from elm_genlist_item_object_get() in a way + * where it may point to freed objects. + * + * drag,start,up - This is called when the item in the list has been dragged + * (not scrolled) up. + * + * drag,start,down - This is called when the item in the list has been dragged + * (not scrolled) down. + * + * drag,start,left - This is called when the item in the list has been dragged + * (not scrolled) left. + * + * drag,start,right - This is called when the item in the list has been dragged + * (not scrolled) right. + * + * drag,stop - This is called when the item in the list has stopped being + * dragged. + * + * drag - This is called when the item in the list is being dragged. + * + * Genlist has a fairly large API, mostly because it's relatively complex, + * trying to be both expansive, powerful and efficient. First we will begin + * an overview o the theory behind genlist. + * + * Evas tracks every object you create. Every time it processes an event + * (mouse move, down, up etc.) it needs to walk through objects and find out + * what event that affects. Even worse every time it renders display updates, + * in order to just calculate what to re-draw, it needs to walk through many + * many many objects. Thus, the more objects you keep active, the more + * overhead Evas has in just doing its work. It is advisable to keep your + * active objects to the minimum working set you need. Also remember that + * object creation and deletion carries an overhead, so there is a + * middle-ground, which is not easily determined. But don't keep massive lists + * of objects you can't see or use. Genlist does this with list objects. It + * creates and destroys them dynamically as you scroll around. It groups them + * into blocks so it can determine the visibility etc. of a whole block at + * once as opposed to having to walk the whole list. This 2-level list allows + * for very large numbers of items to be in the list (tests have used up to + * 2,000,000 items). Also genlist employs a queue for adding items. As items + * may be different sizes, every item added needs to be calculated as to its + * size and thus this presents a lot of overhead on populating the list, this + * genlist employs a queue. Any item added is queued and spooled off over + * time, actually appearing some time later, so if your list has many members + * you may find it takes a while for them to all appear, with your process + * consuming a lot of CPU while it is busy spooling. + * + * Genlist also implements a tree structure, but it does so with callbacks to + * the application, with the application filling in tree structures when + * requested (allowing for efficient building of a very deep tree that could + * even be used for file-management). See the above smart signal callbacks for + * details. + * + * An item in the genlist world can have 0 or more text labels (they can be + * regular text or textblock – that's up to the style to determine), 0 or + * more icons (which are simply objects swallowed into the genlist item) and + * 0 or more boolean states that can be used for check, radio or other + * indicators by the edje theme style. An item may be one of several styles + * (Elementary provides 2 by default - “default” and “double_label”, but this + * can be extended by system or application custom themes/overlays/extensions). + * + * In order to implement the ability to add and delete items on the fly, + * Genlist implements a class/callback system where the application provides + * a structure with information about that type of item (genlist may contain + * multiple different items with different classes, states and styles). + * Genlist will call the functions in this struct (methods) when an item is + * “realized” (that is created dynamically while scrolling). All objects will + * simply be deleted when no longer needed with evas_object_del(). The + * Elm_Genlist_Item_Class structure contains the following members: + * + * item_style - This is a constant string and simply defines the name of the + * item style. It must be specified and the default should be “default”. + * + * func.label_get - This function is called when an actual item object is + * created. The data parameter is the data parameter passed to + * elm_genlist_item_append() and related item creation functions. The obj + * parameter is the genlist object and the part parameter is the string name + * of the text part in the edje design that is listed as one of the possible + * labels that can be set. This function must return a strudup()'ed string as + * the caller will free() it when done. + * + * func.icon_get - This function is called when an actual item object is + * created. The data parameter is the data parameter passed to + * elm_genlist_item_append() and related item creation functions. The obj + * parameter is the genlist object and the part parameter is the string name + * of the icon part in the edje design that is listed as one of the possible + * icons that can be set. This must return NULL for no object or a valid + * object. The object will be deleted by genlist on shutdown or when the item + * its unrealized. + * + * func.state_get - This function is called when an actual item object is + * created. The data parameter is the data parameter passed to + * elm_genlist_item_append() and related item creation functions. The obj + * parameter is the genlist object and the part parameter is the string name + * of the state part in the edje design that is listed as one of the possible + * states that can be set. Return 0 for false or 1 for true. Genlist will + * emit a signal to the edje object with “elm,state,XXX,active” “elm” when + * true (the default is false), where XXX is the name of the part. + * + * func.del - This is called when elm_genlist_item_del() is called on an + * item, elm_genlist_clear() is called on the genlist, or + * elm_genlist_item_subitems_clear() is called to clear sub-items. This is + * intended for use when actual genlist items are deleted, so any backing + * data attached to the item (e.g. its data parameter on creation) can be + * deleted. + * + * Items can be added by several calls. All of them return a Elm_Genlist_Item + * handle that is an internal member inside the genlist. They all take a data + * parameter that is meant to be used for a handle to the applications + * internal data (eg the struct with the original item data). The parent + * parameter is the parent genlist item this belongs to if it is a tree, and + * NULL if there is no parent. The flags can be a bitmask of + * ELM_GENLIST_ITEM_NONE and ELM_GENLIST_ITEM_SUBITEMS. If + * ELM_GENLIST_ITEM_SUBITEMS is set then this item is displayed as a item + * that is able to expand and have child items. The func parameter is a + * convenience callback that is called when the item is selected and the data + * parameter will be the func_data parameter, obj be the genlist object and + * vent_info will be the genlist item. + * + * elm_genlist_item_append() appends an item to the end of the list, or if + * there is a parent, to the end of all the child items of the parent. + * elm_genlist_item_prepend() is the same but prepends to the beginning of + * the list or children list. elm_genlist_item_insert_before() inserts at + * item before another item and elm_genlist_item_insert_after() inserts after + * the indicated item. + * + * The application can clear the list with elm_genlist_clear() which deletes + * all the items in the list and elm_genlist_item_del() will delete a specific + * item. elm_genlist_item_subitems_clear() will clear all items that are + * children of the indicated parent item. + * + * If the application wants multiple items to be able to be selected, + * elm_genlist_multi_select_set() can enable this. If the list is + * single-selection only (the default), then elm_genlist_selected_item_get() + * will return the selected item, if any, or NULL I none is selected. If the + * list is multi-select then elm_genlist_selected_items_get() will return a + * list (that is only valid as long as no items are modified (added, deleted, + * selected or unselected). + * + * To help inspect list items you can jump to the item at the top of the list + * with elm_genlist_first_item_get() which will return the item pointer, and + * similarly elm_genlist_last_item_get() gets the item at the end of the list. + * elm_genlist_item_next_get() and elm_genlist_item_prev_get() get the next + * and previous items respectively relative to the indicated item. Using + * these calls you can walk the entire item list/tree. Note that as a tree + * the items are flattened in the list, so elm_genlist_item_parent_get() will + * let you know which item is the parent (and thus know how to skip them if + * wanted). + * + * There are also convenience functions. elm_genlist_item_genlist_get() will + * return the genlist object the item belongs to. elm_genlist_item_show() + * will make the scroller scroll to show that specific item so its visible. + * elm_genlist_item_data_get() returns the data pointer set by the item + * creation functions. + * + * If an item changes (state of boolean changes, label or icons change), + * then use elm_genlist_item_update() to have genlist update the item with + * the new state. Genlist will re-realize the item thus call the functions + * in the _Elm_Genlist_Item_Class for that item. + * + * To programmatically (un)select an item use elm_genlist_item_selected_set(). + * To get its selected state use elm_genlist_item_selected_get(). Similarly + * to expand/contract and item and get its expanded state, use + * elm_genlist_item_expanded_set() and elm_genlist_item_expanded_get(). And + * again to make an item disabled (unable to be selected and appear + * differently) use elm_genlist_item_disabled_set() to set this and + * elm_genlist_item_disabled_get() to get the disabled state. + * + * In general to indicate how the genlist should expand items horizontally to + * fill the list area, use elm_genlist_horizontal_mode_set(). Valid modes are + * ELM_LIST_LIMIT and ELM_LIST_SCROLL . The default is ELM_LIST_SCROLL. This + * mode means that if items are too wide to fit, the scroller will scroll + * horizontally. Otherwise items are expanded to fill the width of the + * viewport of the scroller. If it is ELM_LIST_LIMIT, Items will be expanded + * to the viewport width and limited to that size. This can be combined with + * a different style that uses edjes' ellipsis feature (cutting text off like + * this: “tex...”). + * + * Items will only call their selection func and callback when first becoming + * selected. Any further clicks will do nothing, unless you enable always + * select with elm_genlist_always_select_mode_set(). This means even if + * selected, every click will make the selected callbacks be called. + * elm_genlist_no_select_mode_set() will turn off the ability to select + * items entirely and they will neither appear selected nor call selected + * callback functions. + * + * Remember that you can create new styles and add you own theme augmentation + * per application with elm_theme_extension_add(). If you absolutely must + * have a specific style that overrides any theme the user or system sets up + * you can use elm_theme_overlay_add() to add such a file. */ - class GenList : public Object { public: @@ -78,8 +314,16 @@ public: * * @ingroup Genlist */ + + //EAPI Elm_Genlist_Item *elm_genlist_item_append(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, + // const void *data, Elm_Genlist_Item *parent, Elm_Genlist_Item_Flags flags, + // Evas_Smart_Cb func, const void *func_data); + - void append (); + void append (GenListColumnConstructor *construction, GenListItem *parent, Elm_Genlist_Item_Flags flags, GenListColumnSelector *selection); + + // TODO: which type is event_info here instead of void*? + sigc::signal <void, const Evasxx::Object&, void*> signalSelect; private: GenList (); // forbid standard constructor diff --git a/elementaryxx/include/elementaryxx/GenListColumnConstructor.h b/elementaryxx/include/elementaryxx/GenListColumnConstructor.h new file mode 100644 index 0000000..71fbb45 --- /dev/null +++ b/elementaryxx/include/elementaryxx/GenListColumnConstructor.h @@ -0,0 +1,25 @@ +#ifndef ELMXX_GEN_LIST_COLUMN_CONSTRUCTOR +#define ELMXX_GEN_LIST_COLUMN_CONSTRUCTOR + +/* STD */ +#include <string> + +namespace Elmxx { + +/* forward declarations */ +class GenList; +class GenListDataModel; + +class GenListColumnConstructor +{ +public: + friend class GenList; + friend class GenListDataModel; + +private: + GenListDataModel *mDataModel; +}; + +} // end namespace Elmxx + +#endif // ELMXX_GEN_LIST_COLUMN_CONSTRUCTOR diff --git a/elementaryxx/include/elementaryxx/GenListColumnSelector.h b/elementaryxx/include/elementaryxx/GenListColumnSelector.h new file mode 100644 index 0000000..0bb18e8 --- /dev/null +++ b/elementaryxx/include/elementaryxx/GenListColumnSelector.h @@ -0,0 +1,23 @@ +#ifndef ELMXX_GEN_LIST_COLUMN_SELECTOR +#define ELMXX_GEN_LIST_COLUMN_SELECTOR + +/* STD */ +#include <string> + +namespace Elmxx { + +/* forward declarations */ +class GenList; + +class GenListColumnSelector +{ +public: + friend class GenList; + +private: + GenList *mGenList; +}; + +} // end namespace Elmxx + +#endif // ELMXX_GEN_LIST_COLUMN_SELECTOR diff --git a/elementaryxx/include/elementaryxx/GenListDataModel.h b/elementaryxx/include/elementaryxx/GenListDataModel.h index 79129eb..8cc3221 100644 --- a/elementaryxx/include/elementaryxx/GenListDataModel.h +++ b/elementaryxx/include/elementaryxx/GenListDataModel.h @@ -12,7 +12,11 @@ namespace Elmxx { /* forward declarations */ class GenList; - +class Icon; +class Window; +class Object; +class GenListColumnConstructor; + class GenListDataModel { public: @@ -20,7 +24,15 @@ public: GenListDataModel (); - std::string getLabel (Evasxx::Object &obj, const std::string &part) const; + // TODO: implement these 4 functions pure virtual? + + std::string getLabel (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part) const; + + Elmxx::Object *getIcon (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part); + + bool getState (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part); + + void del (GenListColumnConstructor *construction, Evasxx::Object &obj); private: static char *gl_label_get (const void *data, Evas_Object *obj, const char *part); diff --git a/elementaryxx/include/elementaryxx/GenListItem.h b/elementaryxx/include/elementaryxx/GenListItem.h index dc118e4..6a967d1 100644 --- a/elementaryxx/include/elementaryxx/GenListItem.h +++ b/elementaryxx/include/elementaryxx/GenListItem.h @@ -6,9 +6,13 @@ namespace Elmxx { +/* forward declarations */ +class GenList; + class GenListItem { public: + friend class GenList; private: Elm_Genlist_Item *mItem; diff --git a/elementaryxx/include/elementaryxx/Makefile.am b/elementaryxx/include/elementaryxx/Makefile.am index 9f756db..f121b8e 100644 --- a/elementaryxx/include/elementaryxx/Makefile.am +++ b/elementaryxx/include/elementaryxx/Makefile.am @@ -33,7 +33,9 @@ libelementaryxx_HEADERS = \ Separator.h \ GenList.h \ GenListItem.h \ - GenListDataModel.h + GenListDataModel.h \ + GenListColumnConstructor.h \ + GenListColumnSelector.h libelementaryxxdir = \ $(pkgincludedir) diff --git a/elementaryxx/src/GenList.cpp b/elementaryxx/src/GenList.cpp index 19550c3..fa18b23 100644 --- a/elementaryxx/src/GenList.cpp +++ b/elementaryxx/src/GenList.cpp @@ -4,6 +4,9 @@ /* Project */ #include "../include/elementaryxx/GenList.h" +#include "../include/elementaryxx/GenListItem.h" +#include "../include/elementaryxx/GenListColumnConstructor.h" +#include "../include/elementaryxx/GenListColumnSelector.h" /* STD */ #include <cassert> @@ -121,27 +124,56 @@ void GenList::setDataModel (GenListDataModel &model) void GenList::gl_sel (void *data, Evas_Object *obj, void *event_info) { - // TODO: sigc - printf("sel item data [%p] on genlist obj [%p], item pointer [%p]\n", data, obj, event_info); + GenListColumnSelector *selection = (GenListColumnSelector*) data; + GenList *gl = selection->mGenList; + Evasxx::Object *eo = Evasxx::Object::objectLink (obj); + gl->signalSelect.emit (*eo, event_info); } /* operations to add items */ -void GenList::append () +void GenList::append (GenListColumnConstructor *construction, GenListItem *parent, Elm_Genlist_Item_Flags flags, GenListColumnSelector *selection) { assert (mModel); Elm_Genlist_Item *gli; - - int i = 99; + bool internalConstruction = false; + bool internalSelection = false; + + if (!construction) + { + // create internal construction object if construction==NULL was given and delete if after adding + // this is needed to provide the user an easy API to add type save data to item append callbacks + internalConstruction = true; + construction = new GenListColumnConstructor (); + } + + if (!selection) + { + // create internal construction object if construction==NULL was given and delete if after adding + // this is needed to provide the user an easy API to add type save data to item append callbacks + internalSelection = true; + selection = new GenListColumnSelector (); + } + + construction->mDataModel = mModel; + selection->mGenList = this; gli = elm_genlist_item_append (o, &mModel->mGLIC, - mModel /* item data */, - NULL/* parent */, - ELM_GENLIST_ITEM_NONE, + construction /* item data */, + parent ? parent->mItem : NULL /* parent */, + flags, GenList::gl_sel/* func */, - (void *)(i * 10)/* func data */); - + selection /* func data */); + + if (internalConstruction) + { + delete construction; + } + if (internalSelection) + { + delete selection; + } } } // end namespace Elmxx diff --git a/elementaryxx/src/GenListColumnConstructor.cpp b/elementaryxx/src/GenListColumnConstructor.cpp new file mode 100644 index 0000000..e3d24a3 --- /dev/null +++ b/elementaryxx/src/GenListColumnConstructor.cpp @@ -0,0 +1,4 @@ +/* Project */ +#include "../include/elementaryxx/GenListColumnConstructor.h" + +using namespace std; \ No newline at end of file diff --git a/elementaryxx/src/GenListColumnSelector.cpp b/elementaryxx/src/GenListColumnSelector.cpp new file mode 100644 index 0000000..0b6f713 --- /dev/null +++ b/elementaryxx/src/GenListColumnSelector.cpp @@ -0,0 +1,4 @@ +/* Project */ +#include "../include/elementaryxx/GenListColumnSelector.h" + +using namespace std; \ No newline at end of file diff --git a/elementaryxx/src/GenListDataModel.cpp b/elementaryxx/src/GenListDataModel.cpp index 68bdd88..eee00a5 100644 --- a/elementaryxx/src/GenListDataModel.cpp +++ b/elementaryxx/src/GenListDataModel.cpp @@ -1,5 +1,8 @@ /* Project */ #include "../include/elementaryxx/GenListDataModel.h" +#include "../include/elementaryxx/Icon.h" +#include "../include/elementaryxx/Window.h" +#include "../include/elementaryxx/GenListColumnConstructor.h" /* STD */ #include <iostream> @@ -17,43 +20,78 @@ GenListDataModel::GenListDataModel () mGLIC.func.del = GenListDataModel::gl_del; } -std::string GenListDataModel::getLabel (Evasxx::Object &obj, const std::string &part) const +std::string GenListDataModel::getLabel (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part) const { cout << "GenListDataModel::getLabel" << endl; return "Item"; } +Elmxx::Object *GenListDataModel::getIcon (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part) +{ + Window *win = static_cast <Window*> (&obj); + Icon *ic = Icon::factory (*win); + ic->setFile ("/home/andreas/Bilder/e_penguin/penguin.png"); + ic->setAspectHintSize (EVAS_ASPECT_CONTROL_VERTICAL, Eflxx::Size (1, 1)); + + //part: elm.swallow.icon + //part: elm.swallow.end + + return ic; +} + +bool GenListDataModel::getState (GenListColumnConstructor *construction, Evasxx::Object &obj, const std::string &part) +{ + return true; +} + +void GenListDataModel::del (GenListColumnConstructor *construction, Evasxx::Object &obj) +{ + +} + /* wrappers */ char *GenListDataModel::gl_label_get (const void *data, Evas_Object *obj, const char *part) { cout << "gl_label_get" << endl; - - GenListDataModel *model = (GenListDataModel*) data; - Evasxx::Object *objWrap = Evasxx::Object::wrap (obj); - - std::string label = model->getLabel (*objWrap, part); - - // FIXME: from logic this should be deleted, but results in a segfault. no idea why... - //delete objWrap; - - return strdup (label.c_str ()); + + GenListColumnConstructor *construction = (GenListColumnConstructor*) data; + GenListDataModel *model = construction->mDataModel; + Evasxx::Object *objWrap = Evasxx::Object::objectLink (obj); + + const std::string &label = model->getLabel (construction, *objWrap, part); + + return (!label.empty ()) ? strdup (label.c_str ()) : NULL; } Evas_Object *GenListDataModel::gl_icon_get (const void *data, Evas_Object *obj, const char *part) { - return NULL; + GenListColumnConstructor *construction = (GenListColumnConstructor*) data; + GenListDataModel *model = construction->mDataModel; + Evasxx::Object *objWrap = Evasxx::Object::objectLink (obj); + + Object *objxx = model->getIcon (construction, *objWrap, part); + + return objxx ? objxx->obj () : NULL; } Eina_Bool GenListDataModel::gl_state_get (const void *data, Evas_Object *obj, const char *part) { - return true; + GenListColumnConstructor *construction = (GenListColumnConstructor*) data; + GenListDataModel *model = construction->mDataModel; + Evasxx::Object *objWrap = Evasxx::Object::objectLink (obj); + + return model->getState (construction, *objWrap, part); } void GenListDataModel::gl_del(const void *data, Evas_Object *obj) { - printf ("del\n"); + GenListColumnConstructor *construction = (GenListColumnConstructor*) data; + GenListDataModel *model = construction->mDataModel; + Evasxx::Object *objWrap = Evasxx::Object::objectLink (obj); + + return model->del (construction, *objWrap); } } // end namespace Elmxx diff --git a/elementaryxx/src/Makefile.am b/elementaryxx/src/Makefile.am index 9d061cb..ad963c3 100644 --- a/elementaryxx/src/Makefile.am +++ b/elementaryxx/src/Makefile.am @@ -49,5 +49,7 @@ libelementaryxx_la_SOURCES = \ Separator.cpp \ GenList.cpp \ GenListItem.cpp \ - GenListDataModel.cpp + GenListDataModel.cpp \ + GenListColumnConstructor.cpp \ + GenListColumnSelector.cpp --
