summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-03-19 19:49:47 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-03-19 19:49:47 +0900
commite60db60b1255855bfffe5a65503bd7d7dbabfd13 (patch)
tree27aa4d736d2116fc885d5b4abc692b68e24ec8b9
parent53fcba486a5a694cfedd38ec3e5644853fea4e6e (diff)
guess what the cat dragged in... "tabs" in terminology. just a
selector right now that u call up from keybindings. if u switch terms it kicks in with some visuals too. theme stuff is currently not done/ready at all. just recycling terminolgy bg edje atm. havent done anything to: 1. track "window titles" per term and put into tab term previews 2. make preview look decent (some shadowing and spacing between terms etc.) 3. track/display things like bell alerts still need to have a way to suspend/unsuspend invisible terms so media stuff pauses in playback etc. etc.
-rw-r--r--README1
-rw-r--r--src/bin/Makefile.am1
-rw-r--r--src/bin/main.c162
-rw-r--r--src/bin/sel.c519
-rw-r--r--src/bin/sel.h14
-rw-r--r--src/bin/termio.c10
6 files changed, 697 insertions, 10 deletions
diff --git a/README b/README
index c21b125..4d27718 100644
--- a/README
+++ b/README
@@ -55,6 +55,7 @@ Shift+Keypad-Divide = Copy highlight to Clipboard (same as ctrl+c in gui apps)
55Ctrl+PgUp = switch focus to previous terminal inside a window 55Ctrl+PgUp = switch focus to previous terminal inside a window
56Ctrl+PgDn = switch focus to next terminal inside a window 56Ctrl+PgDn = switch focus to next terminal inside a window
57Ctrl+Shift+t = create new terminal on top of current inside window (tabs) (not implemented) 57Ctrl+Shift+t = create new terminal on top of current inside window (tabs) (not implemented)
58Ctrl+Shift+Home = bring up "tab" switcher
58Ctrl+Shift+PgUp = split terminal horizontally (1 term above the other) 59Ctrl+Shift+PgUp = split terminal horizontally (1 term above the other)
59Ctrl+Shift+PgDn = split terminal vertically (1 term to the left of the other) 60Ctrl+Shift+PgDn = split terminal vertically (1 term to the left of the other)
60Alt+Home = Enter command mode (enter commands to control terminology itself) 61Alt+Home = Enter command mode (enter commands to control terminology itself)
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 8fc515b..e8734a0 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -26,6 +26,7 @@ options_helpers.c options_helpers.h \
26options_video.c options_video.h \ 26options_video.c options_video.h \
27options_theme.c options_theme.h \ 27options_theme.c options_theme.h \
28options_wallpaper.c options_wallpaper.h \ 28options_wallpaper.c options_wallpaper.h \
29sel.c sel.h \
29termio.c termio.h \ 30termio.c termio.h \
30termcmd.c termcmd.h \ 31termcmd.c termcmd.h \
31termiolink.c termiolink.h \ 32termiolink.c termiolink.h \
diff --git a/src/bin/main.c b/src/bin/main.c
index 5eb950a..8ad7948 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -12,6 +12,7 @@
12#include "media.h" 12#include "media.h"
13#include "utils.h" 13#include "utils.h"
14#include "ipc.h" 14#include "ipc.h"
15#include "sel.h"
15 16
16#if (ELM_VERSION_MAJOR == 1) && (ELM_VERSION_MINOR < 8) 17#if (ELM_VERSION_MAJOR == 1) && (ELM_VERSION_MINOR < 8)
17 #define PANES_TOP "left" 18 #define PANES_TOP "left"
@@ -50,6 +51,7 @@ struct _Term
50 Evas_Object *term; 51 Evas_Object *term;
51 Evas_Object *media; 52 Evas_Object *media;
52 Evas_Object *popmedia; 53 Evas_Object *popmedia;
54 Evas_Object *sel;
53 Eina_List *popmedia_queue; 55 Eina_List *popmedia_queue;
54 int poptype, mediatype; 56 int poptype, mediatype;
55 int step_x, step_y, min_w, min_h, req_w, req_h; 57 int step_x, step_y, min_w, min_h, req_w, req_h;
@@ -58,6 +60,7 @@ struct _Term
58 } down; 60 } down;
59 Eina_Bool focused : 1; 61 Eina_Bool focused : 1;
60 Eina_Bool hold : 1; 62 Eina_Bool hold : 1;
63 Eina_Bool unswallowed : 1;
61}; 64};
62 65
63struct _Split 66struct _Split
@@ -68,6 +71,7 @@ struct _Split
68 Term *term; // if leaf node this is not null - the CURRENT term from terms list 71 Term *term; // if leaf node this is not null - the CURRENT term from terms list
69 Eina_List *terms; // list of terms in the "tabs" 72 Eina_List *terms; // list of terms in the "tabs"
70 Evas_Object *panes; // null if a leaf node 73 Evas_Object *panes; // null if a leaf node
74 Evas_Object *sel; // multi "tab" selector is active
71 Eina_Bool horizontal : 1; 75 Eina_Bool horizontal : 1;
72}; 76};
73 77
@@ -449,7 +453,7 @@ _term_focus(Term *term)
449{ 453{
450 Eina_List *l; 454 Eina_List *l;
451 Term *term2; 455 Term *term2;
452 456
453 EINA_LIST_FOREACH(term->wn->terms, l, term2) 457 EINA_LIST_FOREACH(term->wn->terms, l, term2)
454 { 458 {
455 if (term2 != term) 459 if (term2 != term)
@@ -588,6 +592,7 @@ _cb_focus_in(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
588{ 592{
589 Win *wn = data; 593 Win *wn = data;
590 Term *term; 594 Term *term;
595 Split *sp;
591 596
592 if (!wn->focused) elm_win_urgent_set(wn->win, EINA_FALSE); 597 if (!wn->focused) elm_win_urgent_set(wn->win, EINA_FALSE);
593 wn->focused = EINA_TRUE; 598 wn->focused = EINA_TRUE;
@@ -595,8 +600,16 @@ _cb_focus_in(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
595 elm_object_focus_set(wn->cmdbox, EINA_TRUE); 600 elm_object_focus_set(wn->cmdbox, EINA_TRUE);
596 term = main_win_focused_term_get(wn); 601 term = main_win_focused_term_get(wn);
597 if (!term) return; 602 if (!term) return;
598 edje_object_signal_emit(term->bg, "focus,in", "terminology"); 603 sp = _split_find(wn->win, term->term);
599 if (!wn->cmdbox_up) elm_object_focus_set(term->term, EINA_TRUE); 604 if (sp->sel)
605 {
606 if (!wn->cmdbox_up) elm_object_focus_set(sp->sel, EINA_TRUE);
607 }
608 else
609 {
610 edje_object_signal_emit(term->bg, "focus,in", "terminology");
611 if (!wn->cmdbox_up) elm_object_focus_set(term->term, EINA_TRUE);
612 }
600} 613}
601 614
602static void 615static void
@@ -1037,6 +1050,113 @@ _cb_command(void *data, Evas_Object *obj __UNUSED__, void *event)
1037} 1050}
1038 1051
1039static void 1052static void
1053_sel_restore(Split *sp)
1054{
1055 Eina_List *l;
1056 Term *tm;
1057
1058 EINA_LIST_FOREACH(sp->terms, l, tm)
1059 {
1060 if (tm->unswallowed)
1061 {
1062 evas_object_image_source_visible_set(tm->sel, EINA_TRUE);
1063 edje_object_part_swallow(tm->bg, "terminology.content", tm->term);
1064 tm->unswallowed = EINA_FALSE;
1065 evas_object_show(tm->term);
1066 tm->sel = NULL;
1067 }
1068 }
1069 evas_object_del(sp->sel);
1070 sp->sel = NULL;
1071}
1072
1073static void
1074_sel_cb_selected(void *data, Evas_Object *obj __UNUSED__, void *info)
1075{
1076 Split *sp = data;
1077 Eina_List *l;
1078 Term *tm;
1079
1080 EINA_LIST_FOREACH(sp->terms, l, tm)
1081 {
1082 if (tm->sel == info)
1083 {
1084 _term_focus(tm);
1085 _term_focus_show(sp, tm);
1086 _sel_restore(sp);
1087 return;
1088 }
1089 }
1090 _sel_restore(sp);
1091 _term_focus(sp->term);
1092 _term_focus_show(sp, sp->term);
1093}
1094
1095static void
1096_sel_cb_exit(void *data, Evas_Object *obj __UNUSED__, void *info __UNUSED__)
1097{
1098 Split *sp = data;
1099 _sel_restore(sp);
1100 _term_focus(sp->term);
1101 _term_focus_show(sp, sp->term);
1102}
1103
1104static void
1105_sel_go(Split *sp, Term *term)
1106{
1107 Eina_List *l;
1108 Term *tm;
1109 double z;
1110
1111 evas_object_hide(sp->term->bg);
1112 sp->sel = sel_add(sp->wn->win);
1113 EINA_LIST_FOREACH(sp->terms, l, tm)
1114 {
1115 edje_object_part_unswallow(tm->bg, tm->term);
1116 evas_object_lower(tm->term);
1117 evas_object_move(tm->term, 0, 0);
1118 evas_object_show(tm->term);
1119 evas_object_clip_unset(tm->term);
1120 evas_object_image_source_visible_set(tm->sel, EINA_FALSE);
1121 tm->unswallowed = EINA_TRUE;
1122
1123 tm->sel = termio_mirror_add(tm->term);
1124 sel_entry_add(sp->sel, tm->sel, (tm == sp->term), tm->config);
1125 }
1126 if (!sp->parent)
1127 edje_object_part_swallow(sp->wn->base, "terminology.content", sp->sel);
1128 else
1129 {
1130 if (sp == sp->parent->s1)
1131 {
1132 elm_object_part_content_unset(sp->parent->panes, PANES_TOP);
1133 elm_object_part_content_set(sp->parent->panes, PANES_TOP, sp->sel);
1134 }
1135 else
1136 {
1137 elm_object_part_content_unset(sp->parent->panes, PANES_BOTTOM);
1138 elm_object_part_content_set(sp->parent->panes, PANES_BOTTOM, sp->sel);
1139 }
1140 }
1141 evas_object_show(sp->sel);
1142 z = 1.0;
1143 sel_go(sp->sel);
1144 if (eina_list_count(sp->terms) >= 1)
1145 z = 1.0 / (sqrt(eina_list_count(sp->terms)) * 0.8);
1146 if (z > 1.0) z = 1.0;
1147 sel_orig_zoom_set(sp->sel, z);
1148 sel_zoom(sp->sel, z);
1149 if (term != sp->term)
1150 {
1151 sel_entry_selected_set(sp->sel, term->sel);
1152 sel_exit(sp->sel);
1153 }
1154 elm_object_focus_set(sp->sel, EINA_TRUE);
1155 evas_object_smart_callback_add(sp->sel, "selected", _sel_cb_selected, sp);
1156 evas_object_smart_callback_add(sp->sel, "exit", _sel_cb_exit, sp);
1157}
1158
1159static void
1040_cb_prev(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__) 1160_cb_prev(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
1041{ 1161{
1042 Term *term = data; 1162 Term *term = data;
@@ -1045,11 +1165,17 @@ _cb_prev(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
1045 if (term->focused) term2 = _term_prev_get(term); 1165 if (term->focused) term2 = _term_prev_get(term);
1046 if (term2) 1166 if (term2)
1047 { 1167 {
1048 Split *sp; 1168 Split *sp, *sp0;
1049 1169
1050 _term_focus(term2); 1170 sp0 = _split_find(term->wn->win, term->term);
1051 sp = _split_find(term2->wn->win, term2->term); 1171 sp = _split_find(term2->wn->win, term2->term);
1052 if (sp) _term_focus_show(sp, term2); 1172 if (sp == sp0)
1173 _sel_go(sp, term2);
1174 else
1175 {
1176 _term_focus(term2);
1177 if (sp) _term_focus_show(sp, term2);
1178 }
1053 } 1179 }
1054} 1180}
1055 1181
@@ -1062,11 +1188,17 @@ _cb_next(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
1062 if (term->focused) term2 = _term_next_get(term); 1188 if (term->focused) term2 = _term_next_get(term);
1063 if (term2) 1189 if (term2)
1064 { 1190 {
1065 Split *sp; 1191 Split *sp, *sp0;
1066 1192
1067 _term_focus(term2); 1193 sp0 = _split_find(term->wn->win, term->term);
1068 sp = _split_find(term2->wn->win, term2->term); 1194 sp = _split_find(term2->wn->win, term2->term);
1069 if (sp) _term_focus_show(sp, term2); 1195 if (sp == sp0)
1196 _sel_go(sp, term2);
1197 else
1198 {
1199 _term_focus(term2);
1200 if (sp) _term_focus_show(sp, term2);
1201 }
1070 } 1202 }
1071} 1203}
1072 1204
@@ -1079,6 +1211,17 @@ _cb_new(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED
1079} 1211}
1080 1212
1081static void 1213static void
1214_cb_select(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
1215{
1216 Term *term = data;
1217 Split *sp;
1218
1219 sp = _split_find(term->wn->win, term->term);
1220 _sel_go(sp, term);
1221}
1222
1223
1224static void
1082_cb_split_h(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__) 1225_cb_split_h(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
1083{ 1226{
1084 Term *term = data; 1227 Term *term = data;
@@ -1669,6 +1812,7 @@ main_term_new(Win *wn, Config *config, const char *cmd,
1669 evas_object_smart_callback_add(o, "prev", _cb_prev, term); 1812 evas_object_smart_callback_add(o, "prev", _cb_prev, term);
1670 evas_object_smart_callback_add(o, "next", _cb_next, term); 1813 evas_object_smart_callback_add(o, "next", _cb_next, term);
1671 evas_object_smart_callback_add(o, "new", _cb_new, term); 1814 evas_object_smart_callback_add(o, "new", _cb_new, term);
1815 evas_object_smart_callback_add(o, "select", _cb_select, term);
1672 evas_object_smart_callback_add(o, "split,h", _cb_split_h, term); 1816 evas_object_smart_callback_add(o, "split,h", _cb_split_h, term);
1673 evas_object_smart_callback_add(o, "split,v", _cb_split_v, term); 1817 evas_object_smart_callback_add(o, "split,v", _cb_split_v, term);
1674 evas_object_show(o); 1818 evas_object_show(o);
diff --git a/src/bin/sel.c b/src/bin/sel.c
new file mode 100644
index 0000000..b290c01
--- /dev/null
+++ b/src/bin/sel.c
@@ -0,0 +1,519 @@
1#include "private.h"
2
3#include <Elementary.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include "sel.h"
7#include "config.h"
8#include "utils.h"
9
10typedef struct _Sel Sel;
11typedef struct _Entry Entry;
12
13struct _Sel
14{
15 Evas_Object_Smart_Clipped_Data __clipped_data;
16 Evas_Object *clip, *o_event;
17 Ecore_Animator *anim;
18 Ecore_Timer *autozoom_timeout;
19 Eina_List *items;
20 double t_start, t_total;
21 double zoom, zoom0, zoom1;
22 double last_cmd;
23 double interp;
24 double orig_zoom;
25 Evas_Coord px, px0, px1;
26 Evas_Coord py, py0, py1;
27 int w, h;
28 struct {
29 Evas_Coord x, y;
30 Eina_Bool down : 1;
31 } down;
32 Eina_Bool select_me : 1;
33 Eina_Bool exit_me : 1;
34 Eina_Bool exit_on_sel : 1;
35 Eina_Bool exit_now : 1;
36};
37
38struct _Entry
39{
40 Evas_Object *obj, *bg;
41 Eina_Bool selected : 1;
42 Eina_Bool selected_before : 1;
43 Eina_Bool selected_orig : 1;
44};
45
46static Evas_Smart *_smart = NULL;
47static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
48
49static void _smart_calculate(Evas_Object *obj);
50
51
52static void
53_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
54{
55 Evas_Event_Mouse_Down *ev = event;
56 Sel *sd = evas_object_smart_data_get(data);
57 if (!sd) return;
58
59 if (sd->down.down) return;
60 if (ev->button != 1) return;
61 sd->down.x = ev->canvas.x;
62 sd->down.y = ev->canvas.y;
63 sd->down.down = EINA_TRUE;
64}
65
66static void
67_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
68{
69 Evas_Event_Mouse_Down *ev = event;
70 Sel *sd = evas_object_smart_data_get(data);
71 Evas_Coord dx, dy;
72 if (!sd) return;
73
74 if (!sd->down.down) return;
75 sd->down.down = EINA_FALSE;
76 dx = abs(ev->canvas.x - sd->down.x);
77 dy = abs(ev->canvas.y - sd->down.y);
78 if ((dx <= elm_config_finger_size_get()) &&
79 (dy <= elm_config_finger_size_get()))
80 evas_object_smart_callback_call(data, "clicked", NULL);
81}
82
83static Eina_Bool
84_autozoom_reset(void *data)
85{
86 Sel *sd = evas_object_smart_data_get(data);
87 if (!sd) return EINA_FALSE;
88 sd->autozoom_timeout = NULL;
89 sel_zoom(data, sd->orig_zoom);
90 return EINA_FALSE;
91}
92
93static void
94_autozoom(Evas_Object *obj)
95{
96 Sel *sd = evas_object_smart_data_get(obj);
97 double t = ecore_loop_time_get();
98 if (!sd) return;
99 if ((t - sd->last_cmd) < 0.5)
100 {
101 sel_zoom(obj, sd->zoom * 0.9);
102 }
103 sd->last_cmd = t;
104 if (sd->autozoom_timeout) ecore_timer_del(sd->autozoom_timeout);
105 sd->autozoom_timeout = ecore_timer_add(0.5, _autozoom_reset, obj);
106}
107
108void
109_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
110{
111 Evas_Event_Key_Down *ev = event;
112 Sel *sd = evas_object_smart_data_get(data);
113 Eina_List *l;
114 Entry *en;
115 if (!sd) return;
116 if ((!strcmp(ev->keyname, "Next")) ||
117 (!strcmp(ev->keyname, "Right")))
118 {
119 EINA_LIST_FOREACH(sd->items, l, en)
120 {
121 if (en->selected)
122 {
123 if (l->next)
124 {
125 en = l->next->data;
126 sel_entry_selected_set(obj, en->obj);
127 break;
128 }
129 }
130 }
131 sd->exit_now = EINA_FALSE;
132 _autozoom(data);
133 }
134 else if ((!strcmp(ev->keyname, "Prior")) ||
135 (!strcmp(ev->keyname, "Left")))
136 {
137 EINA_LIST_FOREACH(sd->items, l, en)
138 {
139 if (en->selected)
140 {
141 if (l->prev)
142 {
143 en = l->prev->data;
144 sel_entry_selected_set(obj, en->obj);
145 break;
146 }
147 }
148 }
149 sd->exit_now = EINA_FALSE;
150 _autozoom(data);
151 }
152 else if ((!strcmp(ev->keyname, "Return")) ||
153 (!strcmp(ev->keyname, "KP_Enter")) ||
154 (!strcmp(ev->keyname, "space")))
155 {
156 sd->select_me = EINA_TRUE;
157 sd->exit_me = EINA_FALSE;
158 if (sd->autozoom_timeout)
159 {
160 ecore_timer_del(sd->autozoom_timeout);
161 sd->autozoom_timeout = NULL;
162 }
163 sel_zoom(data, 1.0);
164 }
165 else if (!strcmp(ev->keyname, "Escape"))
166 {
167 Evas_Object *entry = NULL;
168
169 EINA_LIST_FOREACH(sd->items, l, en)
170 {
171 if (en->selected_orig) entry = en->obj;
172 }
173 if (entry) sel_entry_selected_set(obj, entry);
174 sd->select_me = EINA_FALSE;
175 sd->exit_me = EINA_TRUE;
176 if (sd->autozoom_timeout)
177 {
178 ecore_timer_del(sd->autozoom_timeout);
179 sd->autozoom_timeout = NULL;
180 }
181 sel_zoom(data, 1.0);
182 }
183}
184
185static void
186_layout(Evas_Object *obj)
187{
188 Sel *sd = evas_object_smart_data_get(obj);
189 int iw, ih, x, y;
190 Evas_Coord ox, oy, ow, oh, w, h, px, py, ww, hh;
191 Eina_List *l;
192 Entry *en;
193 if (!sd) return;
194 iw = sqrt(eina_list_count(sd->items));
195 if (iw < 1) iw = 1;
196 ih = (eina_list_count(sd->items) + (iw - 1)) / iw;
197 if (ih < 1) ih = 1;
198 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
199 w = ow * sd->zoom;
200 h = oh * sd->zoom;
201 x = y = 0;
202 EINA_LIST_FOREACH(sd->items, l, en)
203 {
204 if (en->selected_before)
205 {
206 sd->px0 = (x * w);
207 sd->py0 = (y * h);
208 }
209 if (en->selected)
210 {
211 sd->px1 = (x * w);
212 sd->py1 = (y * h);
213 }
214 x++;
215 if (x >= iw)
216 {
217 x = 0;
218 y++;
219 }
220 }
221
222 sd->px = sd->px0 + ((sd->px1 - sd->px0) * sd->interp);
223 sd->py = sd->py0 + ((sd->py1 - sd->py0) * sd->interp);
224
225 px = sd->px;
226 py = sd->py;
227
228 if ((iw > 0) && (w > 0) && (ih > 0) && (h > 0))
229 {
230 ww = iw * w;
231 hh = ih * h;
232 if (ww <= w) px = (ww - ow) / 2;
233 else px = px - ((px * (ow - w)) / (ww - w));
234 if (hh <= h) py = (hh - oh) / 2;
235 else py = py - ((py * (oh - h)) / (hh - h));
236 }
237 x = y = 0;
238 EINA_LIST_FOREACH(sd->items, l, en)
239 {
240 evas_object_move(en->bg, ox + (x * w) - px, oy + (y * h) - py);
241 evas_object_resize(en->bg, w, h);
242 evas_object_show(en->obj);
243 evas_object_show(en->bg);
244 x++;
245 if (x >= iw)
246 {
247 x = 0;
248 y++;
249 }
250 }
251}
252
253static Eina_Bool
254_anim_cb(void *data)
255{
256 Evas_Object *obj = data;
257 Sel *sd = evas_object_smart_data_get(obj);
258 double t = 1.0;
259 if (!sd) return EINA_FALSE;
260 if (sd->t_total > 0.0)
261 {
262 t = (ecore_loop_time_get() - sd->t_start) / sd->t_total;
263 if (t < 0.0) t = 0.0;
264 else if (t > 1.0) t = 1.0;
265 }
266 sd->interp = ecore_animator_pos_map(t, ECORE_POS_MAP_DECELERATE, 0, 0);
267 sd->zoom = sd->zoom0 + ((sd->zoom1 - sd->zoom0) * sd->interp);
268 _layout(obj);
269 if (t >= 1.0)
270 {
271 sd->anim = NULL;
272 if ((sd->exit_on_sel) && (!sd->exit_now))
273 {
274 if (sd->autozoom_timeout)
275 {
276 ecore_timer_del(sd->autozoom_timeout);
277 sd->autozoom_timeout = NULL;
278 }
279 sd->exit_now = EINA_TRUE;
280 sel_zoom(obj, 1.0);
281 return EINA_FALSE;
282 }
283 if ((sd->select_me) || (sd->exit_now))
284 {
285 Eina_List *l;
286 Entry *en;
287 Evas_Object *entry = NULL;
288
289 EINA_LIST_FOREACH(sd->items, l, en)
290 {
291 if (en->selected) entry = en->obj;
292 }
293 if (entry) evas_object_smart_callback_call(obj, "selected", entry);
294 }
295 else if (sd->exit_me)
296 evas_object_smart_callback_call(obj, "exit", NULL);
297 return EINA_FALSE;
298 }
299 return EINA_TRUE;
300}
301
302static void
303_transit(Evas_Object *obj, double tim)
304{
305 Sel *sd = evas_object_smart_data_get(obj);
306 if (!sd) return;
307 sd->px0 = sd->px;
308 sd->py0 = sd->py;
309 sd->zoom0 = sd->zoom;
310 sd->t_start = ecore_loop_time_get();
311 sd->t_total = tim;
312 sd->interp = 0.0;
313 if (!sd->anim) sd->anim = ecore_animator_add(_anim_cb, obj);
314}
315
316static void
317_smart_add(Evas_Object *obj)
318{
319 Sel *sd;
320 Evas_Object *o;
321
322 sd = calloc(1, sizeof(Sel));
323 EINA_SAFETY_ON_NULL_RETURN(sd);
324 evas_object_smart_data_set(obj, sd);
325
326 _parent_sc.add(obj);
327
328 o = evas_object_rectangle_add(evas_object_evas_get(obj));
329 evas_object_smart_member_add(o, obj);
330 sd->clip = o;
331 evas_object_color_set(o, 255, 255, 255, 255);
332}
333
334static void
335_smart_del(Evas_Object *obj)
336{
337 Sel *sd = evas_object_smart_data_get(obj);
338 Entry *en;
339 if (!sd) return;
340 if (sd->clip) evas_object_del(sd->clip);
341 if (sd->o_event) evas_object_del(sd->o_event);
342 if (sd->anim) ecore_animator_del(sd->anim);
343 if (sd->autozoom_timeout) ecore_timer_del(sd->autozoom_timeout);
344 EINA_LIST_FREE(sd->items, en)
345 {
346 evas_object_del(en->obj);
347 evas_object_del(en->bg);
348 free(en);
349 }
350 _parent_sc.del(obj);
351}
352
353static void
354_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
355{
356 Sel *sd = evas_object_smart_data_get(obj);
357 Evas_Coord ox, oy, ow, oh;
358 if (!sd) return;
359 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
360 if ((ow == w) && (oh == h)) return;
361 evas_object_smart_changed(obj);
362 evas_object_resize(sd->clip, ow, oh);
363}
364
365static void
366_smart_calculate(Evas_Object *obj)
367{
368 Sel *sd = evas_object_smart_data_get(obj);
369 Evas_Coord ox, oy, ow, oh;
370
371 if (!sd) return;
372 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
373 sd->w = ow;
374 sd->h = oh;
375 evas_object_move(sd->clip, ox, oy);
376 evas_object_resize(sd->clip, ow, oh);
377 _layout(obj);
378}
379
380static void
381_smart_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
382{
383 Sel *sd = evas_object_smart_data_get(obj);
384 if (!sd) return;
385 evas_object_smart_changed(obj);
386}
387static void
388_smart_init(void)
389{
390 static Evas_Smart_Class sc;
391
392 evas_object_smart_clipped_smart_set(&_parent_sc);
393 sc = _parent_sc;
394 sc.name = "media";
395 sc.version = EVAS_SMART_CLASS_VERSION;
396 sc.add = _smart_add;
397 sc.del = _smart_del;
398 sc.resize = _smart_resize;
399 sc.move = _smart_move;
400 sc.calculate = _smart_calculate;
401 _smart = evas_smart_class_new(&sc);
402}
403
404Evas_Object *
405sel_add(Evas_Object *parent)
406{
407 Evas *e;
408 Evas_Object *obj;
409 Sel *sd;
410
411 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
412 e = evas_object_evas_get(parent);
413 if (!e) return NULL;
414
415 if (!_smart) _smart_init();
416 obj = evas_object_smart_add(e, _smart);
417 sd = evas_object_smart_data_get(obj);
418 if (!sd) return obj;
419
420 sd->o_event = evas_object_rectangle_add(e);
421 evas_object_color_set(sd->o_event, 0, 0, 0, 0);
422 evas_object_repeat_events_set(sd->o_event, EINA_TRUE);
423 evas_object_smart_member_add(sd->o_event, obj);
424 evas_object_clip_set(sd->o_event, sd->clip);
425 evas_object_show(sd->o_event);
426 evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_MOUSE_DOWN,
427 _mouse_down_cb, obj);
428 evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_MOUSE_UP,
429 _mouse_up_cb, obj);
430 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
431 _key_down_cb, obj);
432 sd->zoom = 1.0;
433
434 return obj;
435}
436
437void
438sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, Config *config)
439{
440 Sel *sd = evas_object_smart_data_get(obj);
441 Entry *en = calloc(1, sizeof(Entry));
442 if (!en) return;
443 sd->items = eina_list_append(sd->items, en);
444 en->obj = entry;
445 en->selected = selected;
446 en->selected_before = selected;
447 en->selected_orig = selected;
448 en->bg = edje_object_add(evas_object_evas_get(obj));
449 theme_apply(en->bg, config, "terminology/background");
450 evas_object_smart_member_add(en->bg, obj);
451 evas_object_clip_set(en->bg, sd->clip);
452 edje_object_part_swallow(en->bg, "terminology.content", en->obj);
453 evas_object_show(en->obj);
454 evas_object_stack_below(en->bg, sd->o_event);
455 if (en->selected)
456 edje_object_signal_emit(en->bg, "focus,in", "terminology");
457 sd->interp = 1.0;
458}
459
460void
461sel_go(Evas_Object *obj)
462{
463 Sel *sd = evas_object_smart_data_get(obj);
464 if (!sd) return;
465 _layout(obj);
466 evas_object_show(sd->clip);
467}
468
469void
470sel_entry_selected_set(Evas_Object *obj, Evas_Object *entry)
471{
472 Sel *sd = evas_object_smart_data_get(obj);
473 Eina_List *l;
474 Entry *en;
475 if (!sd) return;
476 EINA_LIST_FOREACH(sd->items, l, en)
477 {
478 if (en->obj == entry)
479 {
480 edje_object_signal_emit(en->bg, "focus,in", "terminology");
481 en->selected = EINA_TRUE;
482 }
483 else if (en->obj != entry)
484 {
485 if (en->selected)
486 {
487 edje_object_signal_emit(en->bg, "focus,out", "terminology");
488 en->selected = EINA_FALSE;
489 }
490 }
491 en->selected_before = EINA_FALSE;
492 }
493 _transit(obj, 0.3);
494}
495
496void
497sel_zoom(Evas_Object *obj, double zoom)
498{
499 Sel *sd = evas_object_smart_data_get(obj);
500 if (!sd) return;
501 sd->zoom1 = zoom;
502 _transit(obj, 0.3);
503}
504
505void
506sel_orig_zoom_set(Evas_Object *obj, double zoom)
507{
508 Sel *sd = evas_object_smart_data_get(obj);
509 if (!sd) return;
510 sd->orig_zoom = zoom;
511}
512
513void
514sel_exit(Evas_Object *obj)
515{
516 Sel *sd = evas_object_smart_data_get(obj);
517 if (!sd) return;
518 sd->exit_on_sel = EINA_TRUE;
519}
diff --git a/src/bin/sel.h b/src/bin/sel.h
new file mode 100644
index 0000000..fff9248
--- /dev/null
+++ b/src/bin/sel.h
@@ -0,0 +1,14 @@
1#ifndef _SEL_H__
2#define _SEL_H__ 1
3
4#include "config.h"
5
6Evas_Object *sel_add(Evas_Object *parent);
7void sel_entry_add(Evas_Object *obj, Evas_Object *entry, Eina_Bool selected, Config *config);
8void sel_go(Evas_Object *obj);
9void sel_entry_selected_set(Evas_Object *obj, Evas_Object *entry);
10void sel_zoom(Evas_Object *obj, double zoom);
11void sel_orig_zoom_set(Evas_Object *obj, double zoom);
12void sel_exit(Evas_Object *obj);
13
14#endif
diff --git a/src/bin/termio.c b/src/bin/termio.c
index 1cd9e2d..2193913 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -1372,6 +1372,11 @@ _smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
1372 evas_object_smart_callback_call(data, "new", NULL); 1372 evas_object_smart_callback_call(data, "new", NULL);
1373 goto end; 1373 goto end;
1374 } 1374 }
1375 else if (!strcmp(ev->keyname, "Home"))
1376 {
1377 evas_object_smart_callback_call(data, "select", NULL);
1378 goto end;
1379 }
1375 } 1380 }
1376 if ((evas_key_modifier_is_set(ev->modifiers, "Alt")) && 1381 if ((evas_key_modifier_is_set(ev->modifiers, "Alt")) &&
1377 (!evas_key_modifier_is_set(ev->modifiers, "Shift")) && 1382 (!evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
@@ -3503,12 +3508,15 @@ termio_mirror_add(Evas_Object *obj)
3503{ 3508{
3504 Evas_Object *img; 3509 Evas_Object *img;
3505 Termio *sd = evas_object_smart_data_get(obj); 3510 Termio *sd = evas_object_smart_data_get(obj);
3511 Evas_Coord w = 0, h = 0;
3506 if (!sd) return NULL; 3512 if (!sd) return NULL;
3507 img = evas_object_image_filled_add(evas_object_evas_get(obj)); 3513 img = evas_object_image_filled_add(evas_object_evas_get(obj));
3508 evas_object_image_source_set(img, obj); 3514 evas_object_image_source_set(img, obj);
3515 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3516 evas_object_resize(img, w, h);
3509 sd->mirrors = eina_list_append(sd->mirrors, img); 3517 sd->mirrors = eina_list_append(sd->mirrors, img);
3510 evas_object_data_set(img, "termio", obj); 3518 evas_object_data_set(img, "termio", obj);
3511 evas_object_event_callback_add(img, EVAS_CALLBACK_DEL, 3519 evas_object_event_callback_add(img, EVAS_CALLBACK_DEL,
3512 _smart_mirror_del, obj); 3520 _smart_mirror_del, obj);
3513 return obj; 3521 return img;
3514} 3522}