From 07404215a91d7e2ef7d7fa9ebbdd5e0c0312384a Mon Sep 17 00:00:00 2001 From: divyesh purohit Date: Thu, 10 Mar 2016 14:24:50 -0800 Subject: [PATCH] combobox: add Multiple selection feature Summary: This patch focuses on Combobox widget customization, Multibuttonentry widget is used instead of entry for taking user input. The idea is to make the widget look like {F28112} {F28115} when the multiple_selection is set. To-DO: 1) Need to add scrollable interface to combobox when MBE is used (need some suggestions on it). 2) focus cycle is still buggy as genlist requires focus otherwise selected item will return NULL (sometimes) Signed-off-by: divyesh purohit @feature Test Plan: Please run combobox multiple selection example from elementart_test. Reviewers: raster, shilpasingh, cedric Subscribers: govi, rajeshps Projects: #elementary Differential Revision: https://phab.enlightenment.org/D3570 --- legacy/elementary/data/objects/Makefile.am | 8 +- .../data/objects/combobox_multiple.edc | 61 +++++++++ legacy/elementary/src/bin/test.c | 2 + legacy/elementary/src/bin/test_combobox.c | 102 +++++++++++++- legacy/elementary/src/lib/elc_combobox.c | 126 +++++++++++++++++- legacy/elementary/src/lib/elm_combobox.eo | 21 ++- .../elementary/src/lib/elm_widget_combobox.h | 2 + 7 files changed, 312 insertions(+), 10 deletions(-) create mode 100644 legacy/elementary/data/objects/combobox_multiple.edc diff --git a/legacy/elementary/data/objects/Makefile.am b/legacy/elementary/data/objects/Makefile.am index f8f37784c5..86593ca8a8 100644 --- a/legacy/elementary/data/objects/Makefile.am +++ b/legacy/elementary/data/objects/Makefile.am @@ -7,7 +7,7 @@ EDJE_CC_FLAGS += -id $(top_srcdir)/data/objects -fd $(top_srcdir)/data/objects filesdir = $(datadir)/elementary/objects -files_DATA = test.edj test_external.edj multip.edj cursors.edj font_preview.edj postit_ent.edj multibuttonentry.edj test_prefs.edj test_prefs.epb test_focus_style.edj +files_DATA = test.edj test_external.edj multip.edj cursors.edj combobox_multiple.edj font_preview.edj postit_ent.edj multibuttonentry.edj test_prefs.edj test_prefs.epb test_focus_style.edj EXTRA_DIST = \ test.edc \ @@ -16,6 +16,7 @@ test_prefs.edc \ test_prefs.epc \ multip.edc \ cursors.edc \ +combobox_multiple.edc \ font_preview.edc \ postit_ent.edc \ multibuttonentry.edc \ @@ -57,6 +58,11 @@ cursors.edj: Makefile $(EXTRA_DIST) $(top_srcdir)/data/objects/cursors.edc \ $(top_builddir)/data/objects/cursors.edj +combobox_multiple.edj: Makefile combobox_multiple.edc + $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) \ + $(top_srcdir)/data/objects/combobox_multiple.edc \ + $(top_builddir)/data/objects/combobox_multiple.edj + font_preview.edj: Makefile $(EXTRA_DIST) $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) \ $(top_srcdir)/data/objects/font_preview.edc \ diff --git a/legacy/elementary/data/objects/combobox_multiple.edc b/legacy/elementary/data/objects/combobox_multiple.edc new file mode 100644 index 0000000000..96543833ed --- /dev/null +++ b/legacy/elementary/data/objects/combobox_multiple.edc @@ -0,0 +1,61 @@ +collections { +group { + name: "combobox_multiple_test"; + parts{ + part { + name: "bg"; + type: RECT; + mouse_events: 1; + scale:1; + description { + state: "default" 0.0; + color: 0 0 0 0; + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + } + } + part{ + name: "top.left"; + type: RECT; + scale: 1; + description { + state: "default" 0.0; + min : 0 0; + fixed: 1 1; + rel1 { relative: 0.0 0.0; to: bg; } + rel2 { relative: 0.0 0.0; to: bg; } + align: 0.0 0.0; + color: 0 0 0 0; + } + } + part{ + name: "bottom.right"; + type: RECT; + scale: 1; + description { + state: "default" 0.0; + min : 0 0; + fixed: 1 1; + rel1 { relative: 1.0 1.0; to: bg; } + rel2 { relative: 1.0 1.0; to: bg; } + align: 1.0 1.0; + color: 0 0 0 0; + } + } + part { + name: "combobox"; + type: SWALLOW; + mouse_events: 1; + scale:1; + description { + state: "default" 0.0; + min : 0 0; + max : -1 300; + rel1 { relative: 0.0 1.0; to: top.left; } + rel2 { relative: 0.0 0.0; to: bottom.right; } + align: 0.0 0.0; + } + } + } +} +} diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index a3ae31d1b5..3bad1c6d2c 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -46,6 +46,7 @@ void test_clock_edit(void *data, Evas_Object *obj, void *event_info); void test_clock_edit2(void *data, Evas_Object *obj, void *event_info); void test_clock_pause(void *data, Evas_Object *obj, void *event_info); void test_combobox(void *data, Evas_Object *obj, void *event_info); +void test_combobox2(void *data, Evas_Object *obj, void *event_info); void test_check(void *data, Evas_Object *obj, void *event_info); void test_check_toggle(void *data, Evas_Object *obj, void *event_info); void test_radio(void *data, Evas_Object *obj, void *event_info); @@ -755,6 +756,7 @@ add_tests: ADD_TEST(NULL, "Selectors", "DaySelector", test_dayselector); ADD_TEST(NULL, "Selectors", "Main menu", test_main_menu); ADD_TEST(NULL, "Selectors", "Combobox", test_combobox); + ADD_TEST(NULL, "Selectors", "Combobox Multiple Selection", test_combobox2); //------------------------------// ADD_TEST(NULL, "Cursors", "Cursor", test_cursor); diff --git a/legacy/elementary/src/bin/test_combobox.c b/legacy/elementary/src/bin/test_combobox.c index 720e3c6b23..baa6962cc3 100644 --- a/legacy/elementary/src/bin/test_combobox.c +++ b/legacy/elementary/src/bin/test_combobox.c @@ -52,6 +52,14 @@ gl_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUS return strdup(buf); } +static char * +gl2_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) +{ + char buf[256]; + snprintf(buf, sizeof(buf), "%s", (char*)data); + return strdup(buf); +} + static Evas_Object *gl_content_get(void *data EINA_UNUSED, Evas_Object *obj, const char *part) { @@ -76,9 +84,9 @@ static Eina_Bool gl_state_get(void *data EINA_UNUSED, static Eina_Bool gl_filter_get(void *data, Evas_Object *obj EINA_UNUSED, void *key) { + char buf[256]; // if the key is empty/NULL, return true for item if (!strlen((char *)key)) return EINA_TRUE; - char buf[256]; snprintf(buf, sizeof(buf), "Item # %i", (int)(uintptr_t)data); if (strcasestr(buf, (char *)key)) return EINA_TRUE; @@ -94,6 +102,27 @@ _gl_filter_restart_cb(void *data EINA_UNUSED, elm_genlist_filter_set(obj, (void *)elm_object_text_get(obj)); } +static void +_gl2_filter_restart_cb(void *data EINA_UNUSED, + Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + elm_genlist_filter_set(obj, (void *)elm_object_text_get(elm_multibuttonentry_entry_get(obj))); +} + +static Eina_Bool +gl2_filter_get(void *data, Evas_Object *obj EINA_UNUSED, void *key) +{ + char buf[256]; + // if the key is empty/NULL, return true for item + if (!strlen((char *)key)) return EINA_TRUE; + snprintf(buf, sizeof(buf), "%s", (char*)data); + if (!strncmp(buf, (char *)key, strlen((char*)key))) + return EINA_TRUE; + // Default case should return false (item fails filter hence will be hidden) + return EINA_FALSE; +} + static void _gl_filter_finished_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, @@ -176,3 +205,74 @@ test_combobox(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, evas_object_resize(win, 320, 500); evas_object_show(win); } + +static void +_combobox2_item_pressed_cb(void *data EINA_UNUSED, Evas_Object *obj, + void *event_info) +{ + const char *txt = elm_object_item_text_get(event_info); + printf("'item,pressed' callback is called. (selected item : %s)\n", txt); + if (elm_combobox_multiple_selection_get(obj)) + elm_multibuttonentry_item_append(obj, txt, NULL, NULL); + else + elm_object_text_set(obj, txt); + elm_combobox_hover_end(obj); +} +// Combobox with multiple selection +void +test_combobox2(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Evas_Object *win, *combobox, *ly; + Elm_Genlist_Item_Class *itc; + char buf[128]; + char* email_address[300] = {"augue.ut.lacus@Suspendisse.com","egestas.Aliquam.nec@Vivamusmolestiedapibus.edu","urna.et@purusNullam.co.uk","elit@Sedid.net","cursus@malesuadafringillaest.net","Lorem@Cras.org","risus@sedhendrerita.co.uk","auctor.nunc.nulla@utsemNulla.com","nunc.nulla@nonenim.org","egestas@egetipsum.co.uk","sed.tortor@tempusmauris.edu","rutrum@gravida.org","nunc@acsemut.com","lobortis.quam@eratvolutpatNulla.net","fames@ullamcorperDuisat.co.uk","pede.et.risus@necurna.edu","semper.cursus.Integer@justo.com","sem.molestie@orciPhasellusdapibus.com","quam.a@tinciduntvehicula.co.uk","ullamcorper.Duis@odioEtiam.com","enim.Sed.nulla@Etiamligulatortor.net","molestie.pharetra.nibh@velfaucibus.com","morbi@neceuismodin.com","egestas.hendrerit.neque@nequetellus.com","Etiam.gravida.molestie@purusDuis.org","metus.vitae@risus.net","tincidunt.tempus.risus@nonummyFusce.co.uk","Curabitur.ut.odio@in.com","rutrum@utnisi.ca","iaculis.nec@ultriciesdignissimlacus.ca","consectetuer.ipsum.nunc@Cumsociisnatoque.ca","non.arcu.Vivamus@ornare.com","arcu.Vestibulum@interdumligula.edu","sem.magna@urnasuscipit.ca","eu.euismod@urnaconvalliserat.net","Maecenas.mi.felis@mattisInteger.ca","magna.Suspendisse@Donecdignissimmagna.ca","cursus.Integer.mollis@fringillaeuismodenim.ca","tellus.eu@molestie.co.uk","metus.In@egestas.co.uk","Cum@nisl.com","Phasellus@atarcu.net","nec.quam.Curabitur@tortorInteger.org","condimentum.Donec@egetodioAliquam.edu","orci.luctus@magnatellus.co.uk","adipiscing@noncursusnon.co.uk","Sed.eget.lacus@Nullam.edu","felis.ullamcorper@ornare.co.uk","Nunc.quis.arcu@Proineget.edu","in@lobortis.co.uk","leo.Vivamus.nibh@seddui.com","eu.tellus.Phasellus@natoque.ca","ultrices.iaculis@Aliquam.net","purus.ac@feugiatLorem.net","tincidunt.neque@ut.net","odio.sagittis.semper@nibhdolornonummy.org","Sed@eunequepellentesque.com","elementum@sempererat.co.uk","Curae.Donec.tincidunt@neque.net","rhoncus@erat.edu","mauris.elit@Donec.ca","metus.vitae.velit@ad.edu","scelerisque.scelerisque@etmalesuadafames.net","velit.in@convallis.co.uk","ridiculus@laoreetlectusquis.org","tincidunt.orci.quis@musDonec.net","tempor@orciconsectetuereuismod.co.uk","Duis.sit@eratSednunc.com","elit.sed.consequat@nuncinterdum.edu","lorem@Pellentesqueultricies.org","ornare.placerat.orci@pretiumnequeMorbi.com","euismod.enim@primisinfaucibus.ca","a.scelerisque.sed@sapienCras.com","Aliquam@Vestibulum.net","nec@at.ca","quis.diam.luctus@atauctor.ca","nec@purusin.org","montes.nascetur.ridiculus@viverraMaecenas.co.uk","elementum@amet.edu","fringilla.cursus.purus@velarcuCurabitur.co.uk","et.rutrum@consectetuerrhoncus.edu","Aenean@maurissapiencursus.com","interdum@vehiculaaliquet.co.uk","orci.quis.lectus@facilisisfacilisis.org","et.netus.et@arcu.net","ipsum.porta.elit@sapienNunc.edu","libero.Morbi@ipsumCurabiturconsequat.ca","libero@sitamet.com","porta@penatibus.org","nec.enim.Nunc@egetmetusIn.edu","Nunc.sollicitudin.commodo@porttitorinterdum.org","Phasellus.at.augue@dolor.org","nec.ante@etlibero.com","diam@gravida.co.uk","laoreet@malesuada.co.uk","in.lobortis@blanditenim.edu","ante@ipsumnon.net","in@odio.org","Quisque.tincidunt@risus.co.uk","lacus.varius@Vestibulum.com","eu.eros.Nam@arcuNunc.org","pellentesque@Vivamuseuismodurna.org","Cum.sociis@eleifendCras.com","neque@vulputate.org","imperdiet.dictum.magna@risus.org","sagittis@enimcondimentum.edu","hendrerit@maurisMorbi.org","suscipit.nonummy@disparturientmontes.org","Vivamus.non.lorem@fermentummetusAenean.net","In.mi@maurisaliquam.com","est@massanonante.org","molestie@a.co.uk","sit@acturpis.org","diam@felisorci.edu","dolor.nonummy.ac@elitsedconsequat.co.uk","justo@Praesentinterdum.co.uk","Quisque.varius@enimMaurisquis.ca","nibh.enim.gravida@ut.ca","arcu.Vivamus@orciquis.co.uk","sociis@Sedeget.net","risus@egetvolutpatornare.com","vel.est.tempor@ipsum.net","ipsum@dolordapibusgravida.edu","sem.egestas@quamelementum.co.uk","ipsum@Duisatlacus.co.uk","facilisis.vitae@acturpisegestas.net","Nam@aliquetlobortis.net","ipsum.dolor.sit@nuncInat.net","gravida.sagittis@et.org","mauris@magnatellus.edu","sed@adipiscingenimmi.org","sed@ipsumportaelit.com","malesuada.vel.convallis@amet.net","Praesent.interdum@dictumeu.co.uk","nunc.In.at@ornare.co.uk","Phasellus.fermentum.convallis@ipsum.net","sed.libero.Proin@Aliquameratvolutpat.org","aliquet.libero@telluslorem.net","lectus.pede.ultrices@Maurisquisturpis.edu","blandit.at.nisi@ut.net","erat@convallisdolor.net","ante.Nunc.mauris@vehiculaetrutrum.ca","vel.quam@egestas.edu","non@justofaucibuslectus.co.uk","sem.ut.dolor@odioNaminterdum.org","et.ipsum@malesuada.net","non@Nulladignissim.com","ullamcorper.nisl@iaculisodio.com","neque.sed@necurna.ca","in.cursus.et@fermentumvelmauris.co.uk","magna.sed@eteuismodet.co.uk","a@Crasvehicula.com","tortor.Nunc.commodo@velmauris.net","dignissim.pharetra@Aeneaneuismodmauris.org","egestas.urna.justo@acorci.org","iaculis.enim.sit@maurisIntegersem.com","malesuada@imperdietnec.com","erat.volutpat.Nulla@ipsum.org","Aliquam@IntegerurnaVivamus.co.uk","Nunc.sollicitudin@ipsumCurabitur.net","nibh.enim@quam.co.uk","pede@quismassa.com","vel.nisl@fringillacursuspurus.co.uk","vel@auctorvelitAliquam.org","auctor.quis.tristique@fringillamilacinia.org","nisl.elementum@amagna.com","facilisis@feugiattelluslorem.co.uk","eleifend.Cras@Vestibulumante.net","Integer.eu.lacus@ipsumCurabiturconsequat.com","Donec.porttitor@Etiamvestibulummassa.ca","montes@auctorquistristique.net","Nunc.ullamcorper.velit@Vivamusnon.co.uk","dictum.cursus@sed.org","Aliquam.erat.volutpat@nonummyut.org","ac.mattis@ligulaNullamenim.net","id.sapien.Cras@Proin.ca","Phasellus.dolor@fermentumfermentum.edu","in@odio.edu","non.luctus@pedeNuncsed.com","per.conubia@euismodacfermentum.com","luctus.aliquet@venenatisvelfaucibus.ca","nulla.Cras@purusaccumsaninterdum.ca","aliquet.vel.vulputate@pedesagittis.edu","rutrum@pedeultrices.co.uk","Nullam.lobortis@hendrerit.ca","nonummy.ac.feugiat@Sedmalesuadaaugue.edu","nibh@ipsum.com","in.faucibus.orci@vehicula.com","odio.vel.est@in.edu","amet.ornare.lectus@Suspendisse.co.uk","Maecenas.malesuada.fringilla@at.co.uk","Aliquam@aceleifendvitae.org","Nullam.feugiat.placerat@massaQuisque.ca","urna@tempor.org","magnis.dis.parturient@arcuCurabitur.edu","erat.vel@In.ca","rutrum@Integervitae.ca","metus.In@odio.co.uk","nec.imperdiet@tellus.ca","dui.semper.et@at.org","sit.amet@quisarcu.org","ante@Donecsollicitudinadipiscing.edu","turpis.egestas.Aliquam@egestasnunc.edu","posuere@quismassaMauris.co.uk","Nulla.dignissim@nibhAliquamornare.com","facilisis.vitae.orci@estmaurisrhoncus.net","vitae.aliquet.nec@nostraper.co.uk","lorem@enimsitamet.co.uk","pellentesque@acipsum.org","pede.et.risus@nonvestibulum.org","sed@Nuncsollicitudin.com","erat@Maurisvestibulum.org","scelerisque@tortorNunc.org","metus@idsapien.org","dignissim@Duis.ca","Duis.at.lacus@egestaslaciniaSed.com","auctor.velit@dapibus.co.uk","Curae.Phasellus.ornare@eudolor.net","arcu@metusfacilisis.ca","laoreet@dictummagna.net","tristique.neque@auctorvitaealiquet.ca","nunc.interdum.feugiat@primisinfaucibus.edu","elit.pede.malesuada@quam.net","semper.et.lacinia@ornareliberoat.ca","magna.Praesent.interdum@elit.net","consequat@loremDonec.ca","Vivamus@nisiMauris.edu","feugiat.tellus@sociisnatoquepenatibus.co.uk","scelerisque.mollis.Phasellus@facilisis.edu","rhoncus.Proin@enimEtiam.com","amet.consectetuer.adipiscing@lacusNullatincidunt.edu","aliquet.lobortis.nisi@leo.com","magna@purus.org","a@etmalesuadafames.com","Nunc.commodo@vulputatenisisem.net","et.rutrum.non@imperdieteratnonummy.com","consectetuer@mauris.net","iaculis.lacus@Proinvelarcu.ca","tincidunt.Donec.vitae@habitant.net","et.ultrices@nequesed.org","Lorem.ipsum@nonante.edu","Vestibulum.ut@sed.co.uk","fermentum.arcu@Duis.com","Morbi.quis.urna@vulputate.org","Sed.eget@liberolacusvarius.net","amet.lorem@tincidunt.co.uk","morbi@Classaptenttaciti.com","nisl.Quisque.fringilla@ut.ca","Aenean.egestas.hendrerit@eleifendnec.co.uk","elit@odio.net","sodales.Mauris.blandit@fermentumfermentumarcu.com","massa.non@Nuncsollicitudin.com","quam@sit.co.uk","consectetuer@quispedePraesent.co.uk","erat.eget@aliquetPhasellusfermentum.ca","libero@convalliserat.net","dui@arcu.ca","Curabitur@ascelerisquesed.org","amet@sed.com","in.aliquet.lobortis@acipsum.net","Donec.non@feugiatnec.com","Suspendisse.dui.Fusce@musProin.com","congue@loremauctor.co.uk","magna@Morbi.com","sit@dolor.edu","Praesent.eu.nulla@parturientmontes.com","eu.dui.Cum@arcuvelquam.org","leo.elementum@aliquet.edu","aliquam@urna.org","congue@nonummy.ca","urna.Nullam@atauctor.ca","natoque.penatibus@id.co.uk","aliquam.arcu@risusQuisque.com","ultrices.iaculis@liberoet.com","mollis.Integer.tincidunt@auctorvelit.org","sit@mus.org","est.mollis@orci.net","gravida@eunullaat.co.uk","varius.ultrices@Intinciduntcongue.org","Duis.cursus@nuncnulla.org","eu.turpis@Cumsociis.com","metus.In@sapiencursusin.org","a.feugiat.tellus@velitjusto.co.uk","nibh.lacinia.orci@mifelis.org","tincidunt.neque.vitae@Sed.ca","convallis.est.vitae@Donec.org","mauris@semelit.co.uk","Nam.interdum@Morbiquis.ca","vel.arcu.Curabitur@ullamcorperDuisat.net","dolor@mauris.com","Suspendisse@ipsum.org","Vivamus@dui.edu","condimentum.eget.volutpat@lobortisultrices.ca","commodo@et.edu","ut.ipsum@MorbimetusVivamus.co.uk","ut@feugiatnecdiam.org","Nam@ultrices.co.uk","orci.Donec@turpis.org","semper.tellus@venenatislacus.com","elit.elit@arcuimperdietullamcorper.edu"}; + win = elm_win_util_standard_add("combobox", "Combobox"); + elm_win_autodel_set(win, EINA_TRUE); + + ly = elm_layout_add(win); + snprintf(buf, sizeof(buf), "%s/objects/combobox_multiple.edj", elm_app_data_dir_get()); + elm_layout_file_set(ly, buf, "combobox_multiple_test"); + evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, ly); + evas_object_show(ly); + + itc = elm_genlist_item_class_new(); + itc->item_style = "default"; + itc->func.text_get = gl2_text_get; + itc->func.content_get = gl_content_get; + itc->func.state_get = gl_state_get; + itc->func.filter_get = gl2_filter_get; + itc->func.del = NULL; + + combobox = elm_combobox_add(win); + evas_object_size_hint_weight_set(combobox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(combobox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(combobox, "To:"); + elm_object_part_text_set(combobox, "guide", "Tap to add recipient"); + elm_combobox_multiple_selection_set(combobox, EINA_TRUE); + for (int i = 0; i < 300; i++) + elm_genlist_item_append(combobox, itc, (void *)email_address[i], + NULL, ELM_GENLIST_ITEM_NONE, NULL, + (void*)(uintptr_t)(i * 10)); + + evas_object_smart_callback_add(combobox, "clicked", + _combobox_clicked_cb, NULL); + evas_object_smart_callback_add(combobox, "item,selected", + _combobox_item_selected_cb, NULL); + evas_object_smart_callback_add(combobox, "dismissed", + _combobox_dismissed_cb, NULL); + evas_object_smart_callback_add(combobox, "expanded", + _combobox_expanded_cb, NULL); + evas_object_smart_callback_add(combobox, "item,pressed", + _combobox2_item_pressed_cb, NULL); + evas_object_smart_callback_add(combobox, "filter,done", + _gl_filter_finished_cb, NULL); + evas_object_smart_callback_add(combobox, "changed", + _gl2_filter_restart_cb, NULL); + elm_object_part_content_set(ly, "combobox", combobox); + evas_object_show(combobox); + + evas_object_resize(win, 640, 600); + evas_object_show(win); +} diff --git a/legacy/elementary/src/lib/elc_combobox.c b/legacy/elementary/src/lib/elc_combobox.c index 8f2b14110f..9719c13db1 100644 --- a/legacy/elementary/src/lib/elc_combobox.c +++ b/legacy/elementary/src/lib/elc_combobox.c @@ -150,7 +150,8 @@ _table_resize(void *data) evas_object_geometry_get(elm_object_item_track(sd->item), NULL, NULL, NULL, &h); if (h) sd->item_height = h; - evas_object_geometry_get(sd->entry, NULL, NULL, &obj_w, NULL); + evas_object_geometry_get(elm_object_part_content_get(data, "elm.swallow.content"), + NULL, NULL, &obj_w, NULL); evas_object_geometry_get(data, NULL, &obj_y, NULL, &obj_h); evas_object_geometry_get(sd->hover_parent, NULL, NULL, &hover_parent_w, &hover_parent_h); @@ -197,7 +198,13 @@ static void _on_item_selected(void *data , Evas_Object *obj EINA_UNUSED, void *event) { ELM_COMBOBOX_DATA_GET(data, sd); - elm_object_focus_set(sd->entry, EINA_TRUE); + + if (!sd->multiple_selection) elm_object_focus_set(sd->entry, EINA_TRUE); + else + { + elm_genlist_item_bring_in(sd->item, ELM_GENLIST_ITEM_SCROLLTO_TOP); + elm_object_focus_set(sd->mbe, EINA_TRUE); + } eo_event_callback_call(data, ELM_COMBOBOX_EVENT_ITEM_SELECTED, event); } @@ -305,6 +312,107 @@ _elm_combobox_elm_button_admits_autorepeat_get(Eo *obj EINA_UNUSED, return EINA_FALSE; } +EOLIAN static Eina_Bool +_elm_combobox_multiple_selection_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd) +{ + return pd->multiple_selection; +} + +static Eina_Bool +_mbe_clicked_cb(void *data EINA_UNUSED, Eo *obj, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + //Unset the multibuttonentry to contracted mode of single line + elm_multibuttonentry_expanded_set(obj, EINA_TRUE); + return EINA_TRUE; +} + +static Eina_Bool +_mbe_focused_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + return EINA_TRUE; +} + +static Eina_Bool +_mbe_unfocused_cb(void *data EINA_UNUSED, Eo *obj, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + //Set the multibuttonentry to contracted mode of single line + elm_multibuttonentry_expanded_set(obj, EINA_FALSE); + return EINA_TRUE; +} + +static Eina_Bool +_mbe_item_added(void *data, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + elm_genlist_filter_set(sd->genlist, NULL); + return EINA_TRUE; +} + +EO_CALLBACKS_ARRAY_DEFINE(mbe_callbacks, + { EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED, _mbe_clicked_cb }, + { ELM_WIDGET_EVENT_FOCUSED, _mbe_focused_cb }, + { ELM_WIDGET_EVENT_UNFOCUSED, _mbe_unfocused_cb }, + { ELM_MULTIBUTTONENTRY_EVENT_ITEM_ADDED , _mbe_item_added }); + +EO_CALLBACKS_ARRAY_DEFINE(entry_callbacks, + { ELM_ENTRY_EVENT_CHANGED_USER, _on_changed }, + { ELM_ENTRY_EVENT_ABORTED, _on_aborted }); + +EOLIAN static void +_elm_combobox_multiple_selection_set(Eo *obj, Elm_Combobox_Data *pd, + Eina_Bool enabled) +{ + Evas_Object* scr; + + pd->multiple_selection = enabled; + + if (enabled) + { + // This is multibuttonentry object that will take over the MBE call + eo_add(&pd->mbe,ELM_MULTIBUTTONENTRY_CLASS, obj); + evas_object_size_hint_weight_set(pd->mbe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(pd->mbe, EVAS_HINT_FILL, EVAS_HINT_FILL); + eo_event_callback_array_add(elm_multibuttonentry_entry_get(pd->mbe), entry_callbacks(), obj); + eo_event_callback_array_add(pd->mbe, mbe_callbacks(), obj); + + pd->entry = elm_object_part_content_unset(obj, "elm.swallow.content"); + elm_object_text_set(pd->mbe, elm_object_part_text_get(pd->entry, NULL)); + elm_object_part_text_set(pd->mbe, "guide", elm_object_part_text_get(pd->entry, + "guide")); + evas_object_hide(pd->entry); + eo_composite_attach(obj, pd->mbe); + + scr = elm_scroller_add(obj); + elm_scroller_bounce_set(scr, EINA_FALSE, EINA_TRUE); + elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); + evas_object_size_hint_weight_set(scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(scr, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(scr); + elm_object_content_set(scr, pd->mbe); + elm_object_part_content_set(obj, "elm.swallow.content", scr); + elm_widget_can_focus_set(pd->genlist, EINA_FALSE); + } + else + { + scr = elm_object_part_content_unset(obj, "elm.swallow.content"); + elm_object_part_content_set(obj, "elm.swallow.content", pd->entry); + elm_object_text_set(pd->entry, elm_object_part_text_get(pd->mbe, NULL)); + elm_object_part_text_set(pd->entry, "guide", + elm_object_part_text_get(pd->mbe, "guide")); + elm_widget_can_focus_set(pd->genlist, EINA_TRUE); + elm_genlist_item_bring_in(pd->item, ELM_GENLIST_ITEM_SCROLLTO_NONE); + evas_object_hide(scr); + } +} + EAPI Evas_Object * elm_combobox_add(Evas_Object *parent) { @@ -336,7 +444,6 @@ _elm_combobox_eo_base_constructor(Eo *obj, Elm_Combobox_Data *sd) eo_add(&sd->hover, ELM_HOVER_CLASS, sd->hover_parent); elm_widget_mirrored_automatic_set(sd->hover, EINA_FALSE); elm_hover_target_set(sd->hover, obj); - elm_widget_sub_object_add(obj, sd->hover); snprintf(buf, sizeof(buf), "combobox_vertical/%s", elm_widget_style_get(obj)); elm_object_style_set(sd->hover, buf); @@ -382,8 +489,7 @@ _elm_combobox_eo_base_constructor(Eo *obj, Elm_Combobox_Data *sd) ELM_SCROLLER_POLICY_OFF); elm_entry_scrollable_set(entry, EINA_TRUE); elm_entry_single_line_set(entry, EINA_TRUE); - eo_event_callback_add(entry, ELM_ENTRY_EVENT_CHANGED_USER, _on_changed, obj); - eo_event_callback_add(entry, ELM_ENTRY_EVENT_ABORTED, _on_aborted, obj); + eo_event_callback_array_add(entry, entry_callbacks(), obj); evas_object_show(entry); eo_composite_attach(obj, gl); @@ -397,7 +503,11 @@ EOLIAN static void _elm_combobox_hover_begin(Eo *obj, Elm_Combobox_Data *sd) { if (!sd->hover) return; - elm_object_focus_set(sd->entry, EINA_TRUE); + + if (sd->multiple_selection) + elm_object_focus_set(sd->mbe, EINA_TRUE); + else elm_object_focus_set(sd->entry, EINA_TRUE); + _activate(obj); } @@ -514,13 +624,15 @@ EOLIAN void _elm_combobox_elm_widget_part_text_set(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, const char * part, const char *label) { - elm_object_part_text_set(pd->entry, part, label); + if (pd->multiple_selection) elm_object_part_text_set(pd->mbe, part, label); + else elm_object_part_text_set(pd->entry, part, label); } EOLIAN const char * _elm_combobox_elm_widget_part_text_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, const char * part) { + if (pd->multiple_selection) return elm_object_part_text_get(pd->mbe, part); return elm_object_part_text_get(pd->entry, part); } diff --git a/legacy/elementary/src/lib/elm_combobox.eo b/legacy/elementary/src/lib/elm_combobox.eo index 598a462b2c..4e711d41d9 100644 --- a/legacy/elementary/src/lib/elm_combobox.eo +++ b/legacy/elementary/src/lib/elm_combobox.eo @@ -1,6 +1,6 @@ class Elm.Combobox (Elm.Button, Evas.Selectable_Interface, Elm.Interface_Atspi_Widget_Action, - Elm.Entry, Elm.Genlist, Elm.Hover) + Elm.Entry, Elm.Genlist, Elm.Hover, Elm.Multibuttonentry) { eo_prefix: elm_obj_combobox; methods { @@ -16,6 +16,25 @@ class Elm.Combobox (Elm.Button, Evas.Selectable_Interface, return: bool; } } + @property multiple_selection { + get { + [[Returns whether the combobox allows multiple selection. + @since 1.18 + ]] + } + set { + [[Enables or disables multiple selection in combobox. + + Warning: This API should be set before any other API on + combobox, if you wish to avoid complications. + @since 1.18 + ]] + } + values { + enabled: bool; [[$true if multiple selection is enabled, + $false otherwise.]] + } + } hover_begin { [[This triggers the combobox popup from code, the same as if the user had clicked the button. diff --git a/legacy/elementary/src/lib/elm_widget_combobox.h b/legacy/elementary/src/lib/elm_widget_combobox.h index 205096a4c8..9d578c5997 100644 --- a/legacy/elementary/src/lib/elm_widget_combobox.h +++ b/legacy/elementary/src/lib/elm_widget_combobox.h @@ -33,6 +33,7 @@ struct _Elm_Combobox_Data Evas_Object *entry; Evas_Object *tbl; Evas_Object *spacer; + Evas_Object *mbe; Elm_Object_Item *item; const char *style; const char *best_location; @@ -40,6 +41,7 @@ struct _Elm_Combobox_Data int item_height; Eina_Bool expanded:1; Eina_Bool first_filter:1; + Eina_Bool multiple_selection:1; }; /**