summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiscomfitor <michael.blumenkrantz@gmail.com>2013-09-01 14:07:13 +0100
committerdiscomfitor <michael.blumenkrantz@gmail.com>2013-09-01 14:07:13 +0100
commited74c7338657e5ac36f26aaefb9767e8ca2d48b0 (patch)
tree871c1b37fa19904669757dc1078ede9e00aa3996
parentec250b84878179a0bf6970cd4e5a805b77bd4d63 (diff)
add basic chat module
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac10
-rw-r--r--data/themes/chat_basic.edc35
-rw-r--r--data/themes/chat_basic.mk16
-rw-r--r--src/bin/S2.h41
-rw-r--r--src/bin/main.c51
-rw-r--r--src/modules/Makefile.mk26
-rw-r--r--src/modules/chat_basic.c429
-rw-r--r--src/modules/dbus_conn.c22
-rw-r--r--src/modules/list_basic.c17
10 files changed, 608 insertions, 43 deletions
diff --git a/Makefile.am b/Makefile.am
index f707f8b..6916917 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,5 +32,9 @@ if MOD_LIST_BASIC
32include data/themes/list_basic.mk 32include data/themes/list_basic.mk
33endif 33endif
34 34
35if MOD_CHAT_BASIC
36include data/themes/chat_basic.mk
37endif
38
35maintainer-clean-local: 39maintainer-clean-local:
36 rm -rf autom4te.cache 40 rm -rf autom4te.cache
diff --git a/configure.ac b/configure.ac
index 78a8610..fde796d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -129,6 +129,15 @@ if test "x$want_list_basic" != "xno" ; then
129fi 129fi
130AM_CONDITIONAL([MOD_LIST_BASIC], [test "x$have_list_basic" = "xyes"]) 130AM_CONDITIONAL([MOD_LIST_BASIC], [test "x$have_list_basic" = "xyes"])
131 131
132want_chat_basic=yes
133AC_ARG_ENABLE([module-chat-basic],
134 [AC_HELP_STRING([--disable-module-chat-basic], [disable basic chat module. @<:@default=detect@:>@])],
135 [want_chat_basic=$enableval], [])
136if test "x$want_chat_basic" != "xno" ; then
137 PKG_CHECK_MODULES([CHAT_BASIC], [evas edje elementary], [have_chat_basic=yes])
138fi
139AM_CONDITIONAL([MOD_CHAT_BASIC], [test "x$have_chat_basic" = "xyes"])
140
132######################################## 141########################################
133 142
134case "$host_os" in 143case "$host_os" in
@@ -190,6 +199,7 @@ Modules:
190 * dummy_login.........: $want_dummy_login 199 * dummy_login.........: $want_dummy_login
191 * dbus_conn...........: $want_dbus_conn_mod 200 * dbus_conn...........: $want_dbus_conn_mod
192 * list_basic..........: $have_list_basic 201 * list_basic..........: $have_list_basic
202 * chat_basic..........: $have_chat_basic
193MODULES_EOF 203MODULES_EOF
194echo 204echo
195 205
diff --git a/data/themes/chat_basic.edc b/data/themes/chat_basic.edc
new file mode 100644
index 0000000..6f963cc
--- /dev/null
+++ b/data/themes/chat_basic.edc
@@ -0,0 +1,35 @@
1collections {
2 group { name: "chat";
3 data.item: "markup/header/timestamp" "[%H:%M:%S] ";
4 data.item: "markup/header/send" "<color=#00FF01>%s</color>";
5 data.item: "markup/header/receive" "<color=#0001FF>%s</color>";
6 data.item: "markup/header/name" "<b>%s: </b>";
7 parts {
8 part { name: "base"; type: RECT;
9 description { state: "default";
10 color: 0 0 0 255;
11 }
12 }
13 part { name: "swallow.bar"; type: SWALLOW;
14 description { state: "default";
15 fixed: 0 1;
16 }
17 }
18 part { name: "swallow.chat"; type: SWALLOW;
19 description { state: "default";
20 rel1 {
21 relative: 0 1;
22 offset: 0 2;
23 to_y: "swallow.bar";
24 }
25 }
26 }
27 }
28 }
29#define ICON(Name, Min, Max, Rel1, Rel2) \
30 group { name: "chat_basic/"##Name##""; min: Min Min; max: Max Max; \
31 images.image: Name##".png" COMP; parts { part { name: "base"; \
32 description { aspect: 1.0 1.0; aspect_preference: BOTH; rel1.offset: Rel1 Rel1; rel2.offset: Rel2 Rel2; \
33 image.normal: Name##".png"; } } } }
34 ICON("userunknown", 16, 0, 5, -6);
35}
diff --git a/data/themes/chat_basic.mk b/data/themes/chat_basic.mk
new file mode 100644
index 0000000..c5b4e31
--- /dev/null
+++ b/data/themes/chat_basic.mk
@@ -0,0 +1,16 @@
1EDJE_FLAGS = -id $(top_srcdir)/data/themes
2
3chat_basic_filesdir = $(datadir)/s2
4chat_basic_files_DATA = data/themes/chat_basic.edj
5
6images = \
7data/themes/userunknown.png
8
9EXTRA_DIST += \
10data/themes/chat_basic.edc \
11$(images)
12
13data/themes/chat_basic.edj: $(images) data/themes/chat_basic.edc
14 @edje_cc@ $(EDJE_FLAGS) \
15 $(top_srcdir)/data/themes/chat_basic.edc \
16 $(top_builddir)/data/themes/chat_basic.edj
diff --git a/src/bin/S2.h b/src/bin/S2.h
index 6d31896..c4e4216 100644
--- a/src/bin/S2.h
+++ b/src/bin/S2.h
@@ -37,6 +37,7 @@ typedef struct S2_Auth
37 unsigned int id; 37 unsigned int id;
38 Shotgun_Auth *auth; 38 Shotgun_Auth *auth;
39 Eina_Hash *contacts; 39 Eina_Hash *contacts;
40 Eina_List *message_send_listeners;
40 Eina_Bool global_otr : 1; 41 Eina_Bool global_otr : 1;
41 Eina_Bool mail_notifications : 1; 42 Eina_Bool mail_notifications : 1;
42} S2_Auth; 43} S2_Auth;
@@ -45,6 +46,7 @@ typedef struct S2_Contact
45{ 46{
46 S2_Auth *auth; 47 S2_Auth *auth;
47 Eina_Stringshare *jid; 48 Eina_Stringshare *jid;
49 Eina_Stringshare *send_jid; //user-selected
48 Eina_Stringshare *name; 50 Eina_Stringshare *name;
49 Eina_List *groups; 51 Eina_List *groups;
50 Shotgun_Presence_Type ptype; 52 Shotgun_Presence_Type ptype;
@@ -66,22 +68,24 @@ typedef struct S2_Contact
66 Eina_Bool xhtml_im : 1; 68 Eina_Bool xhtml_im : 1;
67} S2_Contact; 69} S2_Contact;
68 70
69typedef void (*S2_Message_Send_Listener_Cb)(S2_Auth *sa, const char *to, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im); 71typedef void (*S2_Message_Send_Listener_Cb)(S2_Auth *sa, S2_Contact *sc, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im);
70 72
71EAPI extern int S2_EVENT_CONTACT_ADD; 73EAPI extern int S2_EVENT_CONTACT_ADD;
72EAPI extern int S2_EVENT_CONTACT_UPDATE; 74EAPI extern int S2_EVENT_CONTACT_UPDATE;
75EAPI extern int S2_EVENT_CONTACT_CHAT;
73EAPI extern int S2_EVENT_CONTACT_PRESENCE_ADD; 76EAPI extern int S2_EVENT_CONTACT_PRESENCE_ADD;
74EAPI extern int S2_EVENT_CONTACT_PRESENCE_UPDATE; 77EAPI extern int S2_EVENT_CONTACT_PRESENCE_UPDATE;
75EAPI extern int S2_EVENT_CONTACT_PRESENCE_DEL; 78EAPI extern int S2_EVENT_CONTACT_PRESENCE_DEL;
76EAPI extern int S2_EVENT_CONTACT_DEL; 79EAPI extern int S2_EVENT_CONTACT_DEL;
77 80
78EAPI S2_Contact *ui_contact_find(S2_Auth *sa, const char *jid); 81EAPI S2_Contact *ui_contact_find(S2_Auth *sa, const char *jid);
82EAPI void ui_contact_chat_open(S2_Contact *sc);
79EAPI S2_Auth *ui_shotgun_find(const char *jid); 83EAPI S2_Auth *ui_shotgun_find(const char *jid);
80EAPI S2_Auth *ui_shotgun_find_by_id(unsigned int id); 84EAPI S2_Auth *ui_shotgun_find_by_id(unsigned int id);
81EAPI Eina_Bool ui_shotgun_userinfo_eq(S2_Contact *sc, Shotgun_User_Info *info); 85EAPI Eina_Bool ui_shotgun_userinfo_eq(S2_Contact *sc, Shotgun_User_Info *info);
82EAPI void ui_shotgun_message_send(S2_Auth *sa, const char *to, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im);; 86EAPI void ui_shotgun_message_send(S2_Auth *sa, S2_Contact *sc, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im);;
83EAPI void ui_shotgun_message_send_listener_add(S2_Message_Send_Listener_Cb cb); 87EAPI void ui_shotgun_message_send_listener_add(S2_Auth *sa, S2_Message_Send_Listener_Cb cb);
84EAPI void ui_shotgun_message_send_listener_del(S2_Message_Send_Listener_Cb cb); 88EAPI void ui_shotgun_message_send_listener_del(S2_Auth *sa, S2_Message_Send_Listener_Cb cb);
85 89
86static inline Eina_Stringshare * 90static inline Eina_Stringshare *
87ui_contact_name_get(const S2_Contact *sc) 91ui_contact_name_get(const S2_Contact *sc)
@@ -94,4 +98,33 @@ ui_contact_name_get(const S2_Contact *sc)
94 return sc->jid; 98 return sc->jid;
95} 99}
96 100
101static inline Eina_Stringshare *
102ui_contact_send_jid_get(const S2_Contact *sc)
103{
104 EINA_SAFETY_ON_NULL_RETURN_VAL(sc, NULL);
105 if (sc->send_jid) return sc->send_jid;
106 if (sc->presences)
107 {
108 Shotgun_Event_Presence *p;
109
110 p = eina_list_data_get(sc->presences);
111 return p->jid;
112 }
113 return sc->jid;
114}
115
116static inline const char *
117ui_jid_base_get(const char *jid)
118{
119 static char buf[4096];
120 const char *p;
121
122 p = strchr(jid, '/');
123 if (!p) return jid;
124
125 memcpy(buf, jid, p - jid);
126 buf[p - jid] = 0;
127 return buf;
128}
129
97#endif 130#endif
diff --git a/src/bin/main.c b/src/bin/main.c
index 7795dfb..67f44fb 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -35,6 +35,7 @@ struct _S2_Module
35int ui_log_dom = -1; 35int ui_log_dom = -1;
36EAPI int S2_EVENT_CONTACT_ADD = -1; 36EAPI int S2_EVENT_CONTACT_ADD = -1;
37EAPI int S2_EVENT_CONTACT_UPDATE = -1; 37EAPI int S2_EVENT_CONTACT_UPDATE = -1;
38EAPI int S2_EVENT_CONTACT_CHAT = -1;
38EAPI int S2_EVENT_CONTACT_PRESENCE_ADD = -1; 39EAPI int S2_EVENT_CONTACT_PRESENCE_ADD = -1;
39EAPI int S2_EVENT_CONTACT_PRESENCE_UPDATE = -1; 40EAPI int S2_EVENT_CONTACT_PRESENCE_UPDATE = -1;
40EAPI int S2_EVENT_CONTACT_PRESENCE_DEL = -1; 41EAPI int S2_EVENT_CONTACT_PRESENCE_DEL = -1;
@@ -50,7 +51,6 @@ static Eina_Hash *connections_by_id = NULL;
50static Eina_Hash *contacts = NULL; 51static Eina_Hash *contacts = NULL;
51static Eina_Inlist *modules[S2_MODULE_TYPE_LAST]; 52static Eina_Inlist *modules[S2_MODULE_TYPE_LAST];
52 53
53static Eina_List *message_send_listeners = NULL;
54static unsigned int connected_count = 0; 54static unsigned int connected_count = 0;
55 55
56static void 56static void
@@ -114,6 +114,7 @@ s2_auth_free(S2_Auth *sa)
114 eina_hash_del_by_key(connections_by_id, &sa->id); 114 eina_hash_del_by_key(connections_by_id, &sa->id);
115 eina_hash_free(sa->contacts); 115 eina_hash_free(sa->contacts);
116 shotgun_free(sa->auth); 116 shotgun_free(sa->auth);
117 eina_list_free(sa->message_send_listeners);
117 free(sa); 118 free(sa);
118} 119}
119 120
@@ -259,12 +260,10 @@ presence_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Event_Presence *ev)
259{ 260{
260 S2_Auth *sa; 261 S2_Auth *sa;
261 S2_Contact *sc; 262 S2_Contact *sc;
262 const char *base_jid = ev->jid, *p; 263 const char *base_jid, *p;
263 264
264 sa = shotgun_data_get(ev->account); 265 sa = shotgun_data_get(ev->account);
265 p = strchr(ev->jid, '/'); 266 base_jid = ui_jid_base_get(ev->jid);
266 if (p)
267 base_jid = strndupa(ev->jid, p - ev->jid);
268 sc = ui_contact_find(sa, base_jid); 267 sc = ui_contact_find(sa, base_jid);
269 if (!sc) 268 if (!sc)
270 { 269 {
@@ -413,13 +412,13 @@ iq_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Event_Iq *ev)
413 return ECORE_CALLBACK_RENEW; 412 return ECORE_CALLBACK_RENEW;
414} 413}
415 414
416static Eina_Bool 415//static Eina_Bool
417message_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Event_Message *ev) 416//message_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Event_Message *ev)
418{ 417//{
419#warning send message to chat module... 418//#warning send message to chat module...
420 return ECORE_CALLBACK_RENEW; 419 //return ECORE_CALLBACK_RENEW;
421} 420//}
422 421//
423/********************************* API ******************************/ 422/********************************* API ******************************/
424 423
425EAPI S2_Contact * 424EAPI S2_Contact *
@@ -431,7 +430,7 @@ ui_contact_find(S2_Auth *sa, const char *jid)
431EAPI void 430EAPI void
432ui_contact_chat_open(S2_Contact *sc) 431ui_contact_chat_open(S2_Contact *sc)
433{ 432{
434 433 ecore_event_add(S2_EVENT_CONTACT_CHAT, sc, fake_free, NULL);
435} 434}
436 435
437EAPI S2_Auth * 436EAPI S2_Auth *
@@ -448,28 +447,30 @@ ui_shotgun_find_by_id(unsigned int id)
448} 447}
449 448
450EAPI void 449EAPI void
451ui_shotgun_message_send(S2_Auth *sa, const char *to, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im) 450ui_shotgun_message_send(S2_Auth *sa, S2_Contact *sc, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im)
452{ 451{
453 Eina_List *l; 452 Eina_List *l;
454 S2_Message_Send_Listener_Cb cb; 453 S2_Message_Send_Listener_Cb cb;
455 454
456 shotgun_message_send(sa->auth, to, msg, status, xhtml_im); 455 shotgun_message_send(sa->auth, ui_contact_send_jid_get(sc), msg, status, xhtml_im);
457 EINA_LIST_FOREACH(message_send_listeners, l, cb) 456 EINA_LIST_FOREACH(sa->message_send_listeners, l, cb)
458 cb(sa, to, msg, status, xhtml_im); 457 cb(sa, sc, msg, status, xhtml_im);
459} 458}
460 459
461EAPI void 460EAPI void
462ui_shotgun_message_send_listener_add(S2_Message_Send_Listener_Cb cb) 461ui_shotgun_message_send_listener_add(S2_Auth *sa, S2_Message_Send_Listener_Cb cb)
463{ 462{
464 EINA_SAFETY_ON_NULL_RETURN(cb); 463 EINA_SAFETY_ON_NULL_RETURN(cb);
465 message_send_listeners = eina_list_append(message_send_listeners, cb); 464 sa->message_send_listeners = eina_list_append(sa->message_send_listeners, cb);
466} 465}
467 466
468EAPI void 467EAPI void
469ui_shotgun_message_send_listener_del(S2_Message_Send_Listener_Cb cb) 468ui_shotgun_message_send_listener_del(S2_Auth *sa, S2_Message_Send_Listener_Cb cb)
470{ 469{
471 EINA_SAFETY_ON_NULL_RETURN(cb); 470 EINA_SAFETY_ON_NULL_RETURN(cb);
472 message_send_listeners = eina_list_remove(message_send_listeners, cb); 471 EINA_SAFETY_ON_NULL_RETURN(sa);
472 if (sa->message_send_listeners)
473 sa->message_send_listeners = eina_list_remove(sa->message_send_listeners, cb);
473} 474}
474 475
475 476
@@ -506,10 +507,11 @@ main(int argc, char *argv[])
506 ecore_event_handler_add(SHOTGUN_EVENT_CONNECTION_STATE, (Ecore_Event_Handler_Cb)con_state, NULL); 507 ecore_event_handler_add(SHOTGUN_EVENT_CONNECTION_STATE, (Ecore_Event_Handler_Cb)con_state, NULL);
507 ecore_event_handler_add(SHOTGUN_EVENT_PRESENCE, (Ecore_Event_Handler_Cb)presence_cb, NULL); 508 ecore_event_handler_add(SHOTGUN_EVENT_PRESENCE, (Ecore_Event_Handler_Cb)presence_cb, NULL);
508 ecore_event_handler_add(SHOTGUN_EVENT_IQ, (Ecore_Event_Handler_Cb)iq_cb, NULL); 509 ecore_event_handler_add(SHOTGUN_EVENT_IQ, (Ecore_Event_Handler_Cb)iq_cb, NULL);
509 ecore_event_handler_add(SHOTGUN_EVENT_MESSAGE, (Ecore_Event_Handler_Cb)message_cb, NULL); 510 //ecore_event_handler_add(SHOTGUN_EVENT_MESSAGE, (Ecore_Event_Handler_Cb)message_cb, NULL);
510 511
511 S2_EVENT_CONTACT_ADD = ecore_event_type_new(); 512 S2_EVENT_CONTACT_ADD = ecore_event_type_new();
512 S2_EVENT_CONTACT_UPDATE = ecore_event_type_new(); 513 S2_EVENT_CONTACT_UPDATE = ecore_event_type_new();
514 S2_EVENT_CONTACT_CHAT = ecore_event_type_new();
513 S2_EVENT_CONTACT_PRESENCE_ADD = ecore_event_type_new(); 515 S2_EVENT_CONTACT_PRESENCE_ADD = ecore_event_type_new();
514 S2_EVENT_CONTACT_PRESENCE_UPDATE = ecore_event_type_new(); 516 S2_EVENT_CONTACT_PRESENCE_UPDATE = ecore_event_type_new();
515 S2_EVENT_CONTACT_PRESENCE_DEL = ecore_event_type_new(); 517 S2_EVENT_CONTACT_PRESENCE_DEL = ecore_event_type_new();
@@ -571,6 +573,11 @@ main(int argc, char *argv[])
571 if (!mod->init()) 573 if (!mod->init())
572 ERR("Module '%s' failed to load!", eina_module_file_get(mod->mod)); 574 ERR("Module '%s' failed to load!", eina_module_file_get(mod->mod));
573 } 575 }
576 EINA_INLIST_FOREACH(modules[S2_MODULE_TYPE_CHAT], mod)
577 {
578 if (!mod->init())
579 ERR("Module '%s' failed to load!", eina_module_file_get(mod->mod));
580 }
574 581
575 ecore_main_loop_begin(); 582 ecore_main_loop_begin();
576 583
diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk
index 3a38a30..863f7c4 100644
--- a/src/modules/Makefile.mk
+++ b/src/modules/Makefile.mk
@@ -78,3 +78,29 @@ src_modules_list_basic_la_LIBTOOLFLAGS = --tag=disable-static
78 78
79endif 79endif
80 80
81
82if MOD_CHAT_BASIC
83
84mod_LTLIBRARIES += src/modules/chat_basic.la
85
86src_modules_chat_basic_la_SOURCES = \
87src/modules/chat_basic.c
88
89src_modules_chat_basic_la_CPPFLAGS = \
90$(AM_CFLAGS) \
91$(mod_cppflags) \
92@EFL_CFLAGS@ \
93@CHAT_BASIC_CFLAGS@ \
94-I$(top_srcdir)/src/bin \
95-I$(top_builddir)
96
97src_modules_chat_basic_la_LIBADD = \
98@EFL_LIBS@ \
99@CHAT_BASIC_LIBS@
100
101src_modules_chat_basic_la_LDFLAGS = -module -avoid-version
102
103src_modules_chat_basic_la_LIBTOOLFLAGS = --tag=disable-static
104
105endif
106
diff --git a/src/modules/chat_basic.c b/src/modules/chat_basic.c
new file mode 100644
index 0000000..62bb749
--- /dev/null
+++ b/src/modules/chat_basic.c
@@ -0,0 +1,429 @@
1#include "S2.h"
2#include <Elementary.h>
3#include <assert.h>
4
5#define WEIGHT evas_object_size_hint_weight_set
6#define ALIGN evas_object_size_hint_align_set
7#define EXPAND(X) WEIGHT((X), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND)
8#define FILL(X) ALIGN((X), EVAS_HINT_FILL, EVAS_HINT_FILL)
9
10# define E_LIST_HANDLER_APPEND(list, type, callback, data) \
11 do \
12 { \
13 Ecore_Event_Handler *_eh; \
14 _eh = ecore_event_handler_add(type, (Ecore_Event_Handler_Cb)callback, data); \
15 assert(_eh); \
16 list = eina_list_append(list, _eh); \
17 } \
18 while (0)
19
20
21static Eina_List *handlers = NULL;
22static Eina_Hash *chats = NULL;
23
24static void
25chat_win_key(S2_Auth *sa, Evas *e EINA_UNUSED, Evas_Object *obj, Evas_Event_Key_Down *ev)
26{
27 if ((!strcmp(ev->keyname, "Return")) || (!strcmp(ev->keyname, "KP_Enter")))
28 {
29 char *s;
30 const char *txt;
31 S2_Contact *sc;
32 Evas_Object *pane, *entry;
33
34 /* FIXME: add popup error or something? */
35 if (shotgun_connection_state_get(sa->auth) != SHOTGUN_CONNECTION_STATE_CONNECTED) return;
36 sc = ui_contact_find(sa, evas_object_data_get(obj, "focused"));
37
38 pane = evas_object_data_get(obj, sc->jid);
39 entry = elm_object_part_content_get(pane, "elm.swallow.right");
40
41 txt = elm_entry_entry_get(entry);
42 if ((!txt) || (!txt[0])) return;
43
44 s = elm_entry_markup_to_utf8(txt);
45
46 ui_shotgun_message_send(sa, sc, s, SHOTGUN_MESSAGE_STATUS_ACTIVE, sc->xhtml_im);
47 elm_entry_entry_set(entry, "");
48 elm_entry_cursor_end_set(entry);
49
50 free(s);
51 }
52}
53
54static void
55chat_insert(Evas_Object *win, Evas_Object *entry, const char *from, const char *msg)
56{
57 const char *grp[] =
58 {
59 "markup/header/receive",
60 "markup/header/send"
61 };
62 size_t tlen = 0, len = 0, mlen, nlen;
63 char timebuf[256];
64 char *buf, *namebuf, *s;
65 const char *markup, *name, *ts;
66 Eina_Bool me = !from;
67 Evas_Object *ly;
68
69 ly = evas_object_data_get(win, "layout");
70 s = elm_entry_utf8_to_markup(msg);
71 /* ideally this would be an entry theme with tags for sending/receiving/formatting,
72 * but fuck writing a whole new entry theme just for that :/
73 */
74 markup = elm_layout_data_get(ly, grp[me]);
75 if ((!markup) || (!markup[0]))
76 markup = NULL;
77 mlen = markup ? strlen(markup) : 0;
78 name = elm_layout_data_get(ly, "markup/header/name");
79 if ((!name) || (!name[0]))
80 name = NULL;
81 nlen = name ? strlen(name) : 0;
82
83 /* construct timestamp if requested by current theme */
84 ts = elm_layout_data_get(ly, "timestamp");
85 if (ts)
86 len = strftime(timebuf, sizeof(timebuf), ts,
87 localtime((time_t[]){ ecore_time_unix_get() }));
88
89
90 /* construct the name header string */
91 if (nlen)
92 {
93 /* nlen implies that the theme has a %s for the name */
94 len += nlen + 1;
95 namebuf = alloca(len);
96 snprintf(namebuf, len, name, from ?: "Me");
97 }
98 else
99 namebuf = NULL;
100
101 if (mlen)
102 {
103 /* theme has markup for header */
104 len += mlen + 1;
105 buf = alloca(len);
106 if (tlen && nlen)
107 snprintf(buf, len, markup, timebuf, namebuf);
108 else if (tlen)
109 snprintf(buf, len, markup, timebuf);
110 else if (nlen)
111 snprintf(buf, len, markup, namebuf);
112 else
113 snprintf(buf, len, markup, from ?: "Me");
114 }
115 else if (tlen || nlen)
116 {
117 /* no overall markup, but timestamp or name requested */
118 if (tlen && nlen)
119 {
120 buf = alloca(len);
121 snprintf(buf, len, "%s%s", timebuf, namebuf);
122 }
123 else if (tlen)
124 buf = timebuf;
125 else
126 buf = namebuf;
127 }
128 else
129 /* no header at all, somebody's not gonna know wtf is going on */
130 buf = NULL;
131
132 if (buf)
133 elm_entry_entry_append(entry, buf);
134 elm_entry_entry_append(entry, s);
135 elm_entry_entry_append(entry, "<ps>");
136 elm_entry_cursor_end_set(entry);
137}
138
139static void
140chat_listener(S2_Auth *sa, S2_Contact *sc, const char *msg, Shotgun_Message_Status status EINA_UNUSED, Eina_Bool xhtml_im EINA_UNUSED)
141{
142 Evas_Object *win, *pane, *entry;
143
144 win = eina_hash_find(chats, &sa->auth);
145 pane = evas_object_data_get(win, sc->jid);
146 entry = elm_object_part_content_get(pane, "elm.swallow.left");
147 chat_insert(win, entry, NULL, msg);
148}
149
150static void
151chat_win_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
152{
153 S2_Auth *sa = data;
154
155 eina_stringshare_del(evas_object_data_del(obj, "file"));
156 ui_shotgun_message_send_listener_del(sa, chat_listener);
157 eina_hash_del_by_key(chats, &sa->auth);
158}
159
160static Evas_Object *
161chat_win_new(S2_Auth *sa)
162{
163 Evas_Object *win, *box, *ly, *tb;
164 const char *override;
165 char buf[PATH_MAX];
166 Evas *e;
167 Evas_Modifier_Mask ctrl, shift, alt;
168
169 win = elm_win_util_standard_add("chat", NULL);
170 evas_object_resize(win, 520, 320);
171 evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, chat_win_del, sa);
172 evas_object_data_set(win, "auth", sa);
173 elm_win_autodel_set(win, EINA_TRUE);
174 //evas_object_smart_callback_add(win, "focus,in", (Evas_Smart_Cb)chat_win_focus, sa);
175 evas_object_event_callback_add(win, EVAS_CALLBACK_KEY_DOWN, (Evas_Object_Event_Cb)chat_win_key, sa);
176
177 e = evas_object_evas_get(win);
178 ctrl = evas_key_modifier_mask_get(e, "Control");
179 shift = evas_key_modifier_mask_get(e, "Shift");
180 alt = evas_key_modifier_mask_get(e, "Alt");
181 1 | evas_object_key_grab(win, "w", ctrl, shift | alt, 1); /* worst warn_unused ever. */
182 1 | evas_object_key_grab(win, "Tab", ctrl, alt, 1); /* worst warn_unused ever. */
183 1 | evas_object_key_grab(win, "Prior", ctrl, alt, 1); /* worst warn_unused ever. */
184 1 | evas_object_key_grab(win, "KP_Prior", ctrl, alt, 1); /* worst warn_unused ever. */
185 1 | evas_object_key_grab(win, "Tab", ctrl | shift, alt, 1); /* worst warn_unused ever. */
186 1 | evas_object_key_grab(win, "Return", 0, ctrl | shift | alt, 1); /* worst warn_unused ever. */
187 1 | evas_object_key_grab(win, "KP_Enter", 0, ctrl | shift | alt, 1); /* worst warn_unused ever. */
188
189 box = elm_box_add(win);
190 EXPAND(box);
191 FILL(box);
192 elm_win_resize_object_add(win, box);
193 evas_object_show(box);
194
195 ly = elm_layout_add(win);
196 EXPAND(ly);
197 FILL(ly);
198 override = getenv("S2_THEME_OVERRIDE_DIR");
199 snprintf(buf, sizeof(buf), "%s/chat_basic.edj", override ?: PACKAGE_DATA_DIR);
200 elm_layout_file_set(ly, buf, "chat");
201 evas_object_data_set(win, "file", eina_stringshare_add(buf));
202 elm_box_pack_end(box, ly);
203 evas_object_data_set(win, "layout", ly);
204 evas_object_show(ly);
205
206 tb = elm_toolbar_add(win);
207 elm_toolbar_horizontal_set(tb, 1);
208 elm_toolbar_shrink_mode_set(tb, ELM_TOOLBAR_SHRINK_SCROLL);
209 elm_toolbar_select_mode_set(tb, ELM_OBJECT_SELECT_MODE_ALWAYS);
210 elm_object_focus_allow_set(tb, 0);
211 elm_object_style_set(tb, "item_horizontal");
212 elm_layout_content_set(ly, "swallow.bar", tb);
213 evas_object_data_set(win, "toolbar", tb);
214
215 evas_object_show(win);
216
217 /* FIXME: this should be in module init */
218 ui_shotgun_message_send_listener_add(sa, chat_listener);
219
220 return win;
221}
222
223static void
224chat_focus(Evas_Object *pane)
225{
226 Evas_Object *cur, *ly, *win = elm_object_top_widget_get(pane);
227 Elm_Object_Item *it;
228 Eina_Stringshare *focused;
229 S2_Contact *sc;
230
231 sc = evas_object_data_get(pane, "sc");
232 focused = evas_object_data_get(win, "focused");
233 /* trying to refocus current focused */
234 if (focused == sc->jid) return;
235 ly = evas_object_data_get(win, "layout");
236
237 cur = elm_layout_content_unset(ly, "swallow.chat");
238 if (cur) evas_object_hide(cur);
239 elm_layout_content_set(ly, "swallow.chat", pane);
240 evas_object_data_set(win, "focused", sc->jid);
241
242 it = evas_object_data_get(pane, "toolbar_item");
243 if (it) //can be NULL if selected during creation */
244 elm_toolbar_item_selected_set(it, 1);
245}
246
247static void
248chat_toolbar_select(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
249{
250 chat_focus(data);
251}
252
253static void
254chat_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *pane, void *event_info EINA_UNUSED)
255{
256 Evas_Object *win;
257 Elm_Object_Item *it, *next;
258 S2_Contact *sc = data;
259 Eina_Stringshare *focused;
260
261 win = elm_object_top_widget_get(pane);
262 focused = evas_object_data_get(win, "focused");
263 it = evas_object_data_get(pane, "toolbar_item");
264 if (!it) return; //canvas deleted
265 if (focused != sc->jid)
266 {
267 elm_object_item_del(it);
268 return;
269 }
270 next = elm_toolbar_item_prev_get(it);
271 if (!next) elm_toolbar_item_next_get(it);
272 if (next)
273 {
274 elm_toolbar_item_selected_set(next, 1);
275 elm_object_item_del(it);
276 }
277 else
278 evas_object_del(win);
279}
280
281static void
282chat_tb_item_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED)
283{
284 evas_object_data_del(data, "toolbar_item");
285}
286
287static Evas_Object *
288chat_new(Evas_Object *win, S2_Contact *sc)
289{
290 Evas_Object *tb, *pane, *o;
291 Elm_Object_Item *it;
292 const char *icon = sc->info.photo.data ? NULL : "chat_basic/userunknown";
293
294 tb = evas_object_data_get(win, "toolbar");
295
296 pane = elm_panes_add(win);
297 evas_object_event_callback_add(pane, EVAS_CALLBACK_DEL, chat_del_cb, sc);
298 evas_object_data_set(pane, "sc", sc);
299 evas_object_data_set(win, sc->jid, pane);
300 elm_panes_horizontal_set(pane, 1);
301
302 o = elm_entry_add(win);
303 elm_entry_cnp_mode_set(o, ELM_CNP_MODE_NO_IMAGE);
304 elm_scroller_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
305 elm_entry_editable_set(o, 0);
306 elm_entry_single_line_set(o, 0);
307 elm_entry_scrollable_set(o, 1);
308 elm_object_focus_allow_set(o, 0);
309 elm_entry_line_wrap_set(o, ELM_WRAP_MIXED);
310 //elm_entry_markup_filter_append(o, (Elm_Entry_Filter_Cb)chat_filter, sc);
311 //evas_object_smart_callback_add(o, "anchor,in", (Evas_Smart_Cb)chat_anchor_in, sc);
312 //evas_object_smart_callback_add(o, "anchor,out", (Evas_Smart_Cb)chat_anchor_out, sc);
313 //evas_object_smart_callback_add(o, "anchor,clicked", (Evas_Smart_Cb)chat_anchor_click, sc);
314 EXPAND(o);
315 FILL(o);
316 elm_object_part_content_set(pane, "elm.swallow.left", o);
317 elm_entry_cursor_end_set(o);
318 evas_object_show(o);
319
320 o = elm_entry_add(win);
321 elm_entry_scrollable_set(o, 1);
322 elm_entry_line_wrap_set(o, ELM_WRAP_MIXED);
323 elm_scroller_policy_set(o, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_AUTO);
324 EXPAND(o);
325 FILL(o);
326 elm_object_part_content_set(pane, "elm.swallow.right", o);
327 //evas_object_smart_callback_add(o, "changed,user", (Evas_Smart_Cb)chat_typing, sc);
328 evas_object_show(o);
329
330 it = elm_toolbar_item_append(tb, icon, ui_contact_name_get(sc), chat_toolbar_select, pane);
331 if (!icon)
332 elm_toolbar_item_icon_memfile_set(it, sc->info.photo.data, sc->info.photo.size, NULL, NULL);
333 elm_object_item_del_cb_set(it, chat_tb_item_del_cb);
334 evas_object_data_set(pane, "toolbar_item", it);
335
336 elm_panes_content_left_size_set(pane, 0.8);
337 return pane;
338}
339
340static Eina_Bool
341chat_request(void *d EINA_UNUSED, int t EINA_UNUSED, S2_Contact *sc)
342{
343 Evas_Object *win, *o;
344
345 win = eina_hash_find(chats, &sc->auth->auth);
346 if (!win)
347 {
348 win = chat_win_new(sc->auth);
349 eina_hash_direct_add(chats, &sc->auth->auth, win);
350 }
351 elm_win_activate(win);
352 o = evas_object_data_get(win, sc->jid);
353 if (!o)
354 o = chat_new(win, sc);
355 chat_focus(o);
356 return ECORE_CALLBACK_RENEW;
357}
358
359static Eina_Bool
360chat_message(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Event_Message *ev)
361{
362 Evas_Object *win, *pane, *entry;
363 const char *jid;
364
365 win = eina_hash_find(chats, &ev->account);
366 jid = ui_jid_base_get(ev->jid);
367 pane = evas_object_data_get(win, jid);
368 if (!pane)
369 {
370 S2_Contact *sc;
371
372 sc = ui_contact_find(shotgun_data_get(ev->account), jid);
373 if (!sc)
374 {
375 fprintf(stderr, "wtf\n");
376 return ECORE_CALLBACK_RENEW;
377 }
378 pane = chat_new(win, sc);
379 }
380 entry = elm_object_part_content_get(pane, "elm.swallow.left");
381 chat_insert(win, entry, NULL, ev->msg);
382 return ECORE_CALLBACK_RENEW;
383}
384
385static Eina_Bool
386chat_contact_del(void *d EINA_UNUSED, int t EINA_UNUSED, S2_Contact *sc)
387{
388 Evas_Object *win, *o;
389
390 win = eina_hash_find(chats, &sc->auth->auth);
391 if (!win) return ECORE_CALLBACK_RENEW;
392 o = evas_object_data_get(win, sc->jid);
393 if (o) evas_object_del(o);
394 return ECORE_CALLBACK_RENEW;
395}
396
397EAPI S2_Module_Type
398ui_module_type(void)
399{
400 return S2_MODULE_TYPE_CHAT;
401}
402
403EAPI Eina_Bool
404ui_module_init(void)
405{
406 int argc;
407 char **argv;
408
409 ecore_app_args_get(&argc, &argv);
410
411 if (!elm_init(argc, argv))
412 return EINA_FALSE;
413
414 chats = eina_hash_pointer_new((Eina_Free_Cb)evas_object_del);
415
416 E_LIST_HANDLER_APPEND(handlers, S2_EVENT_CONTACT_CHAT, chat_request, NULL);
417 E_LIST_HANDLER_APPEND(handlers, SHOTGUN_EVENT_MESSAGE, chat_message, NULL);
418 E_LIST_HANDLER_APPEND(handlers, S2_EVENT_CONTACT_DEL, chat_contact_del, NULL);
419 return EINA_TRUE;
420}
421
422EAPI void
423ui_module_shutdown(void)
424{
425 void *h;
426 EINA_LIST_FREE(handlers, h)
427 ecore_event_handler_del(h);
428 eina_hash_free(chats);
429}
diff --git a/src/modules/dbus_conn.c b/src/modules/dbus_conn.c
index 625078a..b54e912 100644
--- a/src/modules/dbus_conn.c
+++ b/src/modules/dbus_conn.c
@@ -55,13 +55,13 @@ static const Eldbus_Signal connection_signals[] =
55}; 55};
56 56
57static void 57static void
58_dbus_connection_signal_message_sent(S2_Auth *sa, const char *to, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im EINA_UNUSED) 58_dbus_connection_signal_message_sent(S2_Auth *sa, S2_Contact *sc, const char *msg, Shotgun_Message_Status status, Eina_Bool xhtml_im EINA_UNUSED)
59{ 59{
60 Eldbus_Service_Interface *iface; 60 Eldbus_Service_Interface *iface;
61 61
62 iface = eina_hash_find(connection_ifaces, shotgun_jid_full_get(sa->auth)); 62 iface = eina_hash_find(connection_ifaces, shotgun_jid_full_get(sa->auth));
63 if (iface) 63 if (iface)
64 eldbus_service_signal_emit(iface, CONNECTION_SIGNAL_MESSAGE_SENT, to, msg, status); 64 eldbus_service_signal_emit(iface, CONNECTION_SIGNAL_MESSAGE_SENT, ui_contact_send_jid_get(sc), msg, status);
65} 65}
66 66
67static Eina_Bool 67static Eina_Bool
@@ -147,11 +147,11 @@ error:
147static Eldbus_Message * 147static Eldbus_Message *
148_dbus_connection_sendmessage_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) 148_dbus_connection_sendmessage_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
149{ 149{
150 const char *path, *jid, *txt, *p; 150 const char *path, *jid, *txt;
151 Shotgun_Message_Status st; 151 Shotgun_Message_Status st;
152 unsigned int id; 152 unsigned int id;
153 S2_Auth *sa; 153 S2_Auth *sa;
154 char buf[4096] = {0}; 154 S2_Contact *sc;
155 Eldbus_Message *reply; 155 Eldbus_Message *reply;
156 156
157 path = eldbus_message_path_get(msg); 157 path = eldbus_message_path_get(msg);
@@ -166,12 +166,9 @@ _dbus_connection_sendmessage_cb(const Eldbus_Service_Interface *iface EINA_UNUSE
166 if (!eldbus_message_arguments_get(msg, "ssu", &jid, &txt, &st)) goto contact_error; 166 if (!eldbus_message_arguments_get(msg, "ssu", &jid, &txt, &st)) goto contact_error;
167 167
168 /* FIXME: need to check existence of resource... */ 168 /* FIXME: need to check existence of resource... */
169 p = strchr(jid, '/'); 169 sc = ui_contact_find(sa, ui_jid_base_get(jid));
170 if (p) 170 if (!sc) goto contact_error;
171 memcpy(buf, jid, p - jid); 171 ui_shotgun_message_send(sa, sc, txt, st, sc->xhtml_im);
172 if (!ui_contact_find(sa, p ? buf : jid)) goto contact_error;
173 /* FIXME: need to check xhtml_im */
174 ui_shotgun_message_send(sa, jid, txt, st, 0);
175 reply = eldbus_message_method_return_new(msg); 172 reply = eldbus_message_method_return_new(msg);
176 return reply; 173 return reply;
177acct_error: 174acct_error:
@@ -228,6 +225,7 @@ _dbus_connect_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Auth *auth)
228 if (!sa) return ECORE_CALLBACK_RENEW; 225 if (!sa) return ECORE_CALLBACK_RENEW;
229 snprintf(buf, sizeof(buf), "/%u", sa->id); 226 snprintf(buf, sizeof(buf), "/%u", sa->id);
230 iface = eldbus_service_interface_register(dbus_conn, buf, &connection_desc); 227 iface = eldbus_service_interface_register(dbus_conn, buf, &connection_desc);
228 ui_shotgun_message_send_listener_add(sa, _dbus_connection_signal_message_sent);
231 eina_hash_add(connection_ifaces, shotgun_jid_full_get(auth), iface); 229 eina_hash_add(connection_ifaces, shotgun_jid_full_get(auth), iface);
232 } 230 }
233 return ECORE_CALLBACK_RENEW; 231 return ECORE_CALLBACK_RENEW;
@@ -236,7 +234,10 @@ _dbus_connect_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Auth *auth)
236static Eina_Bool 234static Eina_Bool
237_dbus_disconnect_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Auth *auth) 235_dbus_disconnect_cb(void *d EINA_UNUSED, int t EINA_UNUSED, Shotgun_Auth *auth)
238{ 236{
237 S2_Auth *sa = shotgun_data_get(auth);
238
239 eina_hash_del_by_key(connection_ifaces, shotgun_jid_full_get(auth)); 239 eina_hash_del_by_key(connection_ifaces, shotgun_jid_full_get(auth));
240 ui_shotgun_message_send_listener_del(sa, _dbus_connection_signal_message_sent);
240 return ECORE_CALLBACK_RENEW; 241 return ECORE_CALLBACK_RENEW;
241} 242}
242 243
@@ -254,7 +255,6 @@ ui_module_init(void)
254 eldbus_name_request(dbus_conn, "org.s2", 0, _dbus_request_name_cb, NULL); 255 eldbus_name_request(dbus_conn, "org.s2", 0, _dbus_request_name_cb, NULL);
255 eldbus_service_interface_register(dbus_conn, "/", &base_desc); 256 eldbus_service_interface_register(dbus_conn, "/", &base_desc);
256 core_iface = eldbus_service_interface_register(dbus_conn, "/", &core_desc); 257 core_iface = eldbus_service_interface_register(dbus_conn, "/", &core_desc);
257 ui_shotgun_message_send_listener_add(_dbus_connection_signal_message_sent);
258 connection_ifaces = eina_hash_string_superfast_new((Eina_Free_Cb)eldbus_service_object_unregister); 258 connection_ifaces = eina_hash_string_superfast_new((Eina_Free_Cb)eldbus_service_object_unregister);
259 E_LIST_HANDLER_APPEND(handlers, SHOTGUN_EVENT_MESSAGE, _dbus_connection_signal_message_received_cb, NULL); 259 E_LIST_HANDLER_APPEND(handlers, SHOTGUN_EVENT_MESSAGE, _dbus_connection_signal_message_received_cb, NULL);
260 E_LIST_HANDLER_APPEND(handlers, SHOTGUN_EVENT_PRESENCE, _dbus_connection_signal_status_cb, NULL); 260 E_LIST_HANDLER_APPEND(handlers, SHOTGUN_EVENT_PRESENCE, _dbus_connection_signal_status_cb, NULL);
diff --git a/src/modules/list_basic.c b/src/modules/list_basic.c
index 8489947..ab731ba 100644
--- a/src/modules/list_basic.c
+++ b/src/modules/list_basic.c
@@ -217,7 +217,6 @@ overlay_item_content_get(Shotgun_Event_Presence *p, Evas_Object *obj, const char
217{ 217{
218 Evas_Object *ic; 218 Evas_Object *ic;
219 const char *file; 219 const char *file;
220 char *jid, *s;
221 220
222 file = evas_object_data_get(elm_object_top_widget_get(obj), "file"); 221 file = evas_object_data_get(elm_object_top_widget_get(obj), "file");
223 if (!strcmp(part, "elm.swallow.end")) 222 if (!strcmp(part, "elm.swallow.end"))
@@ -225,9 +224,7 @@ overlay_item_content_get(Shotgun_Event_Presence *p, Evas_Object *obj, const char
225 return NULL; 224 return NULL;
226 } 225 }
227 226
228 s = strchr(p->jid, '/'); 227 return list_item_status_icon_new(ui_contact_find(shotgun_data_get(p->account), ui_jid_base_get(p->jid)), p, file, evas_object_evas_get(obj));
229 jid = strndupa(p->jid, s - p->jid);
230 return list_item_status_icon_new(ui_contact_find(shotgun_data_get(p->account), jid), p, file, evas_object_evas_get(obj));
231} 228}
232 229
233static void 230static void
@@ -407,6 +404,14 @@ list_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Down
407 evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_DOWN, overlay_dismiss, overlay); 404 evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_DOWN, overlay_dismiss, overlay);
408} 405}
409 406
407static void
408list_click_cb(void *data, Evas_Object *obj, Elm_Object_Item *it)
409{
410 S2_Contact *sc = elm_object_item_data_get(it);
411
412 ui_contact_chat_open(sc);
413}
414
410static Evas_Object * 415static Evas_Object *
411list_create(S2_Auth *sa) 416list_create(S2_Auth *sa)
412{ 417{
@@ -444,8 +449,8 @@ list_create(S2_Auth *sa)
444 elm_genlist_mode_set(o, ELM_LIST_COMPRESS); 449 elm_genlist_mode_set(o, ELM_LIST_COMPRESS);
445 elm_layout_content_set(ly, "swallow.list", o); 450 elm_layout_content_set(ly, "swallow.list", o);
446 evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)list_mouse_down_cb, o); 451 evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)list_mouse_down_cb, o);
447 //evas_object_smart_callback_add(o, "activated", 452 evas_object_smart_callback_add(o, "activated",
448 //(Evas_Smart_Cb)list_click_cb, NULL); 453 (Evas_Smart_Cb)list_click_cb, NULL);
449 //evas_object_smart_callback_add(o, "moved", 454 //evas_object_smart_callback_add(o, "moved",
450 //(Evas_Smart_Cb)list_reorder_cb, NULL); 455 //(Evas_Smart_Cb)list_reorder_cb, NULL);
451 456