forked from enlightenment/terminology
drag tabs to reinsert them
This commit is contained in:
parent
4cbf4c7b28
commit
ef29315736
|
@ -6,8 +6,14 @@ Changes since 1.6.0:
|
|||
--------------------
|
||||
* In group "terminology/tabbar_back", add signal "bell,off" from "terminology"
|
||||
to unmark a tab as having missed the bell.
|
||||
* In group "terminology/background", signals "tab,drag" and "tab,drag,stop"
|
||||
are emitted when the current tab is dragged.
|
||||
* In group "terminology/background", add signals "hdrag,on" (default) and
|
||||
"hdrag,off" to restrict (default) tab to be dragged only horizontally
|
||||
* In group "terminology/background", signals "tab,mouse,down" and
|
||||
"tab,mouse,up" whenever the left mouse button is pressed on a tab.
|
||||
* In group "terminology/background", signals "tab,hdrag" and "tab,drag,stop"
|
||||
are emitted when the current tab is dragged between tabs.
|
||||
* In group "terminology/background", signal "tab,drag,move" is emitted when
|
||||
the current tab is dragged outside of the tabbar.
|
||||
|
||||
Changes since 1.5.0:
|
||||
--------------------
|
||||
|
|
26
THEME.md
26
THEME.md
|
@ -54,7 +54,25 @@ It reacts to the following signals:
|
|||
### `terminology.content`
|
||||
Here is swallowed an object of group `terminology.background`.
|
||||
|
||||
__TODO__
|
||||
### TODO
|
||||
|
||||
## Signal received
|
||||
### `tabbar,off` and `tabbar,on`
|
||||
Whether to display a tab bar. Default is off.
|
||||
### `tab_btn,off` and `tab_btn,on`
|
||||
Whether to display a tab button to easily navigate through tabs. Default is off.
|
||||
|
||||
### TODO
|
||||
|
||||
## Signal emitted
|
||||
### `tab,hdrag`
|
||||
To notify that the current tab is being dragged.
|
||||
### `tab,drag,stop`
|
||||
To notify that the current tab is no longer being dragged.
|
||||
### `tab,drag,move`
|
||||
To notify that the current tab is being dragged outside of other tabs.
|
||||
|
||||
### TODO
|
||||
|
||||
|
||||
|
||||
|
@ -83,10 +101,14 @@ Where actual text grid goes.
|
|||
Whether to display a tab bar. Default is off.
|
||||
### `tab_btn,off` and `tab_btn,on`
|
||||
Whether to display a tab button to easily navigate through tabs. Default is off.
|
||||
### `hdrag,on` and `hdrag,off`
|
||||
Whether to restrict (default) horizontal tab drag
|
||||
|
||||
## Signal emitted
|
||||
### `tab,drag` and `tab,drage,stop`
|
||||
### `tab,drag` and `tab,drag,stop`
|
||||
To notify that the current tab is being dragged.
|
||||
### `tab,mouse,down` and `tab,mouse,up`
|
||||
Whenever the left mouse button is pressed on a tab.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1361,6 +1361,19 @@ group { name: "terminology/background";
|
|||
rel2.to_x: "terminology.tab_btn";
|
||||
fixed: 1 1;
|
||||
}
|
||||
description { state: "hdrag,off" 0.0;
|
||||
inherit: "default" 0.0;
|
||||
}
|
||||
}
|
||||
program {
|
||||
signal: "hdrag,on"; source: "terminology";
|
||||
action: STATE_SET "default" 0.0;
|
||||
target: "tabdrag";
|
||||
}
|
||||
program {
|
||||
signal: "hdrag,off"; source: "terminology";
|
||||
action: STATE_SET "hdrag,off" 0.0;
|
||||
target: "tabdrag";
|
||||
}
|
||||
// left boundary of the active tab (dragable 0.0 -> 1.0)
|
||||
part { name: "terminology.tabl"; type: SPACER;
|
||||
|
@ -1540,8 +1553,16 @@ group { name: "terminology/background";
|
|||
signal: "mouse,move"; source: "tabmiddle";
|
||||
script {
|
||||
new y, h, drag_x, drag_w;
|
||||
new state[31]; \
|
||||
new Float:vl;
|
||||
|
||||
if (!get_mouse_buttons())
|
||||
return;
|
||||
get_state(PART:"tabdrag", state, 30, vl);
|
||||
if (!strcmp(state, "hdrag,off")) {
|
||||
emit("tab,drag,move", "terminology");
|
||||
return
|
||||
}
|
||||
get_geometry(PART:"tabdrag", drag_x, y, drag_w, h);
|
||||
if (drag_w > 0) {
|
||||
new m_x, m_y;
|
||||
|
@ -1561,7 +1582,7 @@ group { name: "terminology/background";
|
|||
d = (v2 - v1) / 2;
|
||||
set_drag(PART:"terminology.tabl", mid - d, 0.0);
|
||||
set_drag(PART:"terminology.tabr", mid + d, 0.0);
|
||||
emit("tab,drag", "terminology");
|
||||
emit("tab,hdrag", "terminology");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1570,6 +1591,14 @@ group { name: "terminology/background";
|
|||
signal: "mouse,down,1,double"; source: "tabmiddle";
|
||||
action: SIGNAL_EMIT "tab,title" "terminology";
|
||||
}
|
||||
program {
|
||||
signal: "mouse,down,1"; source: "tabmiddle";
|
||||
action: SIGNAL_EMIT "tab,mouse,down" "terminology";
|
||||
}
|
||||
program {
|
||||
signal: "mouse,up,1"; source: "tabmiddle";
|
||||
action: SIGNAL_EMIT "tab,mouse,up" "terminology";
|
||||
}
|
||||
program {
|
||||
signal: "mouse,clicked,1"; source: "tabclose";
|
||||
action: SIGNAL_EMIT "tab,close" "terminology";
|
||||
|
|
294
src/bin/win.c
294
src/bin/win.c
|
@ -62,6 +62,9 @@ int _win_log_dom = -1;
|
|||
#define PANES_TOP "top"
|
||||
#define PANES_BOTTOM "bottom"
|
||||
|
||||
#define DRAG_TIMEOUT 0.4
|
||||
#define ANIM_TIME 0.8
|
||||
|
||||
/* {{{ Structs */
|
||||
|
||||
typedef struct _Split Split;
|
||||
|
@ -69,6 +72,27 @@ typedef struct _Tabbar Tabbar;
|
|||
typedef struct _Solo Solo;
|
||||
typedef struct _Tabs Tabs;
|
||||
typedef struct _Tab_Item Tab_Item;
|
||||
typedef struct _Anim_Icon Anim_Icon;
|
||||
typedef struct _Drag_Anim Drag_Anim;
|
||||
|
||||
struct _Anim_Icon
|
||||
{
|
||||
int start_x;
|
||||
int start_y;
|
||||
Evas_Object *o;
|
||||
};
|
||||
|
||||
struct _Drag_Anim
|
||||
{
|
||||
Evas_Object *icwin;
|
||||
Evas_Coord mdx; /* Mouse-down x */
|
||||
Evas_Coord mdy; /* Mouse-down y */
|
||||
Anim_Icon *icon;
|
||||
Evas *e;
|
||||
Ecore_Timer *timer;
|
||||
Ecore_Animator *ea;
|
||||
Term *term;
|
||||
};
|
||||
|
||||
struct _Tabbar
|
||||
{
|
||||
|
@ -99,6 +123,7 @@ struct _Term
|
|||
Evas_Object *tab_region_bg;
|
||||
Evas_Object *tab_inactive;
|
||||
Tab_Item *tab_item;
|
||||
Drag_Anim *drag_anim;
|
||||
Eina_List *popmedia_queue;
|
||||
Ecore_Timer *sendfile_request_hide_timer;
|
||||
Ecore_Timer *sendfile_progress_hide_timer;
|
||||
|
@ -525,6 +550,11 @@ _solo_set_title(Term_Container *tc,
|
|||
{
|
||||
elm_layout_text_set(term->bg, "terminology.tab.title", title);
|
||||
}
|
||||
if (term->drag_anim && term->drag_anim->icon)
|
||||
{
|
||||
elm_layout_text_set(term->drag_anim->icon->o,
|
||||
"terminology.title", title);
|
||||
}
|
||||
tc->parent->set_title(tc->parent, tc, title);
|
||||
}
|
||||
|
||||
|
@ -2917,20 +2947,51 @@ _tabs_recompute_drag(Tabs *tabs)
|
|||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabr", v2, 0.0);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_term_hdrag_on(Term *term, void *data EINA_UNUSED)
|
||||
{
|
||||
elm_layout_signal_emit(term->bg, "hdrag,on", "terminology");
|
||||
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_term_hdrag_off(Term *term, void *data EINA_UNUSED)
|
||||
{
|
||||
elm_layout_signal_emit(term->bg, "hdrag,off", "terminology");
|
||||
|
||||
return ECORE_CALLBACK_PASS_ON;
|
||||
}
|
||||
|
||||
static void
|
||||
_tabs_on_drag_stop(void *data,
|
||||
Evas_Object *o EINA_UNUSED,
|
||||
const char *emission EINA_UNUSED,
|
||||
const char *source EINA_UNUSED)
|
||||
_drag_anim_free(Term *term)
|
||||
{
|
||||
Term *term = data;
|
||||
Tabs *tabs = evas_object_data_get(term->bg, "tabs");
|
||||
Anim_Icon *icon;
|
||||
Drag_Anim *drag_anim = term->drag_anim;
|
||||
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabl",
|
||||
tabs->v1_orig, 0.0);
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabr",
|
||||
tabs->v2_orig, 0.0);
|
||||
if (!drag_anim)
|
||||
return;
|
||||
|
||||
for_each_term_do(drag_anim->term->wn, &_term_hdrag_on, NULL);
|
||||
|
||||
ecore_timer_del(drag_anim->timer);
|
||||
drag_anim->timer = NULL;
|
||||
|
||||
ecore_animator_del(drag_anim->ea);
|
||||
drag_anim->ea = NULL;
|
||||
|
||||
icon = drag_anim->icon;
|
||||
|
||||
if (icon)
|
||||
{
|
||||
evas_object_hide(icon->o);
|
||||
evas_object_del(icon->o);
|
||||
free(icon);
|
||||
}
|
||||
|
||||
term->drag_anim = NULL;
|
||||
term_unref(drag_anim->term);
|
||||
free(drag_anim);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2953,6 +3014,13 @@ _tabs_on_drag(void *data,
|
|||
tabs = evas_object_data_get(term->bg, "tabs");
|
||||
n = eina_list_count(tabs->tabs);
|
||||
|
||||
tab_item = tabs->current;
|
||||
assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
|
||||
solo = (Solo*)tab_item->tc;
|
||||
term = solo->term;
|
||||
|
||||
_drag_anim_free(term);
|
||||
|
||||
tab_active_idx = -1;
|
||||
EINA_LIST_FOREACH(tabs->tabs, l, tab_item)
|
||||
{
|
||||
|
@ -2961,9 +3029,6 @@ _tabs_on_drag(void *data,
|
|||
break;
|
||||
}
|
||||
tab_item = tabs->current;
|
||||
assert (tab_item->tc->type == TERM_CONTAINER_TYPE_SOLO);
|
||||
solo = (Solo*)tab_item->tc;
|
||||
term = solo->term;
|
||||
|
||||
edje_object_part_drag_value_get(term->bg_edj, "terminology.tabl",
|
||||
&v1, NULL);
|
||||
|
@ -2986,6 +3051,8 @@ _tabs_on_drag(void *data,
|
|||
eina_list_data_get(l),
|
||||
next);
|
||||
_tabs_recompute_drag(tabs);
|
||||
tab_active_idx++;
|
||||
if (v2 <= tabs->v2_orig)
|
||||
return;
|
||||
}
|
||||
while ((tab_active_idx > 0) &&
|
||||
|
@ -3005,10 +3072,205 @@ _tabs_on_drag(void *data,
|
|||
eina_list_data_get(prev),
|
||||
l);
|
||||
_tabs_recompute_drag(tabs);
|
||||
tab_active_idx--;
|
||||
if (v1 >= tabs->v1_orig)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_tabs_drag_reinsert(Term *term, Evas_Coord mx, Evas_Coord my)
|
||||
{
|
||||
Evas_Coord x = 0, y = 0, w = 0, h = 0;
|
||||
Tabs *tabs = evas_object_data_get(term->bg, "tabs");
|
||||
double mid;
|
||||
|
||||
edje_object_part_geometry_get(term->bg_edj, "tabdrag",
|
||||
&x, NULL, &w, NULL);
|
||||
edje_object_part_geometry_get(term->bg_edj, "tabmiddle",
|
||||
NULL, &y, NULL, &h);
|
||||
|
||||
if (!ELM_RECTS_INTERSECT(x,y,w,h, mx,my,1,1))
|
||||
return;
|
||||
|
||||
mid = (double)(mx - x) / (double)w;
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabl", mid, 0.0);
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabr", mid, 0.0);
|
||||
|
||||
_tabs_on_drag(term, NULL, NULL, NULL);
|
||||
/* In case there is no drag, need to recompute to something valid */
|
||||
_tabs_recompute_drag(tabs);
|
||||
}
|
||||
|
||||
static void
|
||||
_tabs_drag_anim_stop(Term *term)
|
||||
{
|
||||
Evas_Coord mx = 0, my = 0;
|
||||
Drag_Anim *drag_anim = term->drag_anim;
|
||||
Win *wn = term->wn;
|
||||
Term_Container *tc = (Term_Container*) wn;
|
||||
Term *term_at_coords;
|
||||
|
||||
assert(drag_anim);
|
||||
|
||||
evas_pointer_canvas_xy_get(drag_anim->e, &mx, &my);
|
||||
term_at_coords = tc->find_term_at_coords(tc, mx, my);
|
||||
if (!term_at_coords)
|
||||
goto end;
|
||||
|
||||
if (term_at_coords == term)
|
||||
{
|
||||
/* Reinsert in same set of Tabs */
|
||||
_tabs_drag_reinsert(term, mx, my);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move to different set of Tabs */
|
||||
/* TODO: boris */
|
||||
}
|
||||
|
||||
end:
|
||||
_drag_anim_free(term);
|
||||
}
|
||||
|
||||
static void
|
||||
_tabs_on_drag_stop(void *data,
|
||||
Evas_Object *o EINA_UNUSED,
|
||||
const char *emission EINA_UNUSED,
|
||||
const char *source EINA_UNUSED)
|
||||
{
|
||||
Term *term = data;
|
||||
Tabs *tabs = evas_object_data_get(term->bg, "tabs");
|
||||
|
||||
if (term->drag_anim && term->drag_anim->icon)
|
||||
{
|
||||
_tabs_drag_anim_stop(term);
|
||||
return;
|
||||
}
|
||||
_drag_anim_free(term);
|
||||
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabl",
|
||||
tabs->v1_orig, 0.0);
|
||||
edje_object_part_drag_value_set(term->bg_edj, "terminology.tabr",
|
||||
tabs->v2_orig, 0.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_tabs_drag_mouse_move(
|
||||
void *data,
|
||||
Evas_Object *obj EINA_UNUSED,
|
||||
const char *emission EINA_UNUSED,
|
||||
const char *source EINA_UNUSED)
|
||||
{
|
||||
Term *term = data;
|
||||
Drag_Anim *drag_anim = term->drag_anim;
|
||||
Anim_Icon *icon;
|
||||
int x, y, w, h;
|
||||
Evas_Coord xm, ym;
|
||||
|
||||
if (!drag_anim)
|
||||
return;
|
||||
|
||||
icon = drag_anim->icon;
|
||||
if (!icon)
|
||||
return;
|
||||
|
||||
evas_object_geometry_get(icon->o, NULL, NULL, &w, &h);
|
||||
evas_pointer_canvas_xy_get(drag_anim->e, &xm, &ym);
|
||||
x = (xm - (w/2));
|
||||
y = (ym - (h/2));
|
||||
evas_object_move(icon->o, x, y);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_drag_anim_play(void *data, double pos)
|
||||
{
|
||||
Drag_Anim *drag_anim = data;
|
||||
Anim_Icon *icon;
|
||||
int x, y, w, h;
|
||||
Evas_Coord xm, ym;
|
||||
|
||||
if (!drag_anim)
|
||||
return ECORE_CALLBACK_CANCEL;
|
||||
|
||||
icon = drag_anim->icon;
|
||||
if (pos > 0.99)
|
||||
{
|
||||
drag_anim->ea = NULL; /* Avoid deleting on mouse up */
|
||||
return ECORE_CALLBACK_CANCEL;
|
||||
}
|
||||
|
||||
evas_object_geometry_get(icon->o, NULL, NULL, &w, &h);
|
||||
evas_pointer_canvas_xy_get(drag_anim->e, &xm, &ym);
|
||||
x = icon->start_x + (pos * (xm - (icon->start_x + (w/2))));
|
||||
y = icon->start_y + (pos * (ym - (icon->start_y + (h/2))));
|
||||
evas_object_move(icon->o, x, y);
|
||||
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_drag_anim_start(void *data)
|
||||
{
|
||||
/* Start icons animation before actually drag-starts */
|
||||
Drag_Anim *drag_anim = data;
|
||||
Evas_Coord w, h;
|
||||
Term *term = drag_anim->term;
|
||||
Anim_Icon *icon = calloc(1, sizeof(*icon));
|
||||
Evas_Object *o = elm_layout_add(term->bg);
|
||||
|
||||
theme_apply_elm(o, term->config, "terminology/tabbar_back");
|
||||
elm_layout_text_set(o, "terminology.title",
|
||||
term->container->title);
|
||||
|
||||
for_each_term_do(drag_anim->term->wn, &_term_hdrag_off, NULL);
|
||||
|
||||
edje_object_part_geometry_get(term->bg_edj, "tabmiddle",
|
||||
&icon->start_x, &icon->start_y, &w, &h);
|
||||
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
|
||||
evas_object_move(o, icon->start_x, icon->start_y);
|
||||
evas_object_resize(o, w, h);
|
||||
evas_object_show(o);
|
||||
|
||||
icon->o = o;
|
||||
drag_anim->icon = icon;
|
||||
|
||||
drag_anim->ea = ecore_animator_timeline_add(DRAG_TIMEOUT,
|
||||
_drag_anim_play, drag_anim);
|
||||
|
||||
drag_anim->timer = NULL;
|
||||
return ECORE_CALLBACK_CANCEL;
|
||||
}
|
||||
|
||||
static void
|
||||
_tabs_mouse_down(
|
||||
void *data,
|
||||
Evas_Object *obj EINA_UNUSED,
|
||||
const char *emission EINA_UNUSED,
|
||||
const char *source EINA_UNUSED)
|
||||
{
|
||||
/* Launch a timer to start drag animation */
|
||||
Term *term = data;
|
||||
Evas_Coord mx = 0, my = 0;
|
||||
Drag_Anim *drag_anim = calloc(1, sizeof(*drag_anim));
|
||||
|
||||
drag_anim->e = evas_object_evas_get(term->bg);
|
||||
evas_pointer_canvas_xy_get(drag_anim->e, &mx, &my);
|
||||
|
||||
term_ref(term);
|
||||
|
||||
term->drag_anim = drag_anim;
|
||||
drag_anim->mdx = mx;
|
||||
drag_anim->mdy = my;
|
||||
drag_anim->term = term;
|
||||
drag_anim->timer = ecore_timer_add(DRAG_TIMEOUT,
|
||||
_drag_anim_start, drag_anim);
|
||||
}
|
||||
|
||||
|
||||
static Evas_Object*
|
||||
_tab_inactive_get_or_create(Evas *canvas,
|
||||
Term *term,
|
||||
|
@ -6008,10 +6270,14 @@ _term_bg_config(Term *term)
|
|||
_cb_tab_close, term);
|
||||
elm_layout_signal_callback_add(term->bg, "tab,title", "terminology",
|
||||
_cb_tab_title, term);
|
||||
elm_layout_signal_callback_add(term->bg, "tab,drag", "*",
|
||||
elm_layout_signal_callback_add(term->bg, "tab,hdrag", "*",
|
||||
_tabs_on_drag, term);
|
||||
elm_layout_signal_callback_add(term->bg, "tab,drag,move", "*",
|
||||
_tabs_drag_mouse_move, term);
|
||||
elm_layout_signal_callback_add(term->bg, "tab,drag,stop", "*",
|
||||
_tabs_on_drag_stop, term);
|
||||
elm_layout_signal_callback_add(term->bg, "tab,mouse,down", "*",
|
||||
_tabs_mouse_down, term);
|
||||
elm_layout_content_set(term->core, "terminology.content", term->termio);
|
||||
elm_layout_content_set(term->bg, "terminology.content", term->core);
|
||||
elm_layout_content_set(term->bg, "terminology.miniview", term->miniview);
|
||||
|
|
Loading…
Reference in New Issue