tab dnd: add anim on where to drag the tab to split

This commit is contained in:
Boris Faure 2020-02-25 23:43:16 +01:00
parent d4d7de118d
commit 7b97a64644
Signed by: borisfaure
GPG Key ID: 35C0410516166BE8
4 changed files with 303 additions and 8 deletions

View File

@ -18,6 +18,12 @@ Changes since 1.6.0:
the current tab is dragged outside of the tabbar.
* In group "terminology/background", parts "tabdrag", "tabmiddle" are used
to adjust drag.
* In group "terminology/background", parts "drag_left_outline",
"drag_right_outline", "drag_top_outline", "drag_bottom_outline" are used to
know when the cursor enters them when dragging a tab into them.
* In group "terminology/background", signals "drag_left,on", "drag_left,off"
are received when the mouse enters or leaves "drag_left_outline". Same for
right, top, bottom.
Changes since 1.5.0:
--------------------

View File

@ -61,11 +61,20 @@ Here is swallowed an object of group `terminology.background`.
### `tabdrag` and `tabmiddle`
Their geometry are used to adjust drag values.
### `drag_left_outline`, `drag_right_outline`, `drag_top_outline`, `drag_bottom_outline`
Their geometry are used to know when the cursor enters them when dragging a
tab.
## 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.
### `drag_left,on`, `drag_right,on`, `drag_top,on`, `drag_bottom,on`
When to start an animation when the cursor enters `drag_XXXX_outline` while
dragging a tab.
### `drag_left,off`, `drag_right,off`, `drag_top,off`, `drag_bottom,off`
When to stop an animation started by the related `*,on` signals.
### TODO

View File

@ -1373,11 +1373,35 @@ group { name: "terminology/background";
signal: "hdrag,on"; source: "terminology";
action: STATE_SET "default" 0.0;
target: "tabdrag";
target: "drag_left_pulse";
target: "drag_left_outline";
target: "drag_left_glow";
target: "drag_right_pulse";
target: "drag_right_outline";
target: "drag_right_glow";
target: "drag_top_pulse";
target: "drag_top_outline";
target: "drag_top_glow";
target: "drag_bottom_pulse";
target: "drag_bottom_outline";
target: "drag_bottom_glow";
}
program {
signal: "hdrag,off"; source: "terminology";
action: STATE_SET "hdrag,off" 0.0;
target: "tabdrag";
target: "drag_left_pulse";
target: "drag_left_outline";
target: "drag_left_glow";
target: "drag_right_pulse";
target: "drag_right_outline";
target: "drag_right_glow";
target: "drag_top_pulse";
target: "drag_top_outline";
target: "drag_top_glow";
target: "drag_bottom_pulse";
target: "drag_bottom_outline";
target: "drag_bottom_glow";
}
// left boundary of the active tab (dragable 0.0 -> 1.0)
part { name: "terminology.tabl"; type: SPACER;
@ -1439,8 +1463,8 @@ group { name: "terminology/background";
align: 0.5 0.5;
rel1.to_x: "tab_bevel_top2";
rel1.to_y: "tabmiddle";
rel2.to_y: "tabmiddle";
rel2.to_x: "tabclose";
rel2.to_y: "tabmiddle";
rel2.relative: 0.5 1.0;
visible: 0;
fixed: 1 1;
@ -1607,7 +1631,6 @@ group { name: "terminology/background";
}
}
}
program {
signal: "mouse,down,1,double"; source: "tabmiddle";
action: SIGNAL_EMIT "tab,title" "terminology";
@ -1763,6 +1786,141 @@ group { name: "terminology/background";
target: "bell_strobe";
}
#define DRAG_TARGET(DIR, REL_ONE, REL_TWO) \
part { name: "drag_"##DIR##"_pulse"; \
mouse_events: 0; \
description { state: "default" 0.0; \
rel1.offset: -4 -4; \
rel1.to: "drag_"##DIR##"_outline"; \
rel2.offset: 3 3; \
rel2.to: "drag_"##DIR##"_outline"; \
image { \
normal: "cr_pulse.png"; \
border: 4 4 4 4; \
} \
color: 51 153 255 0; \
visible: 0; \
} \
description { state: "hdrag,off" 0.0; \
inherit: "default" 0.0; \
} \
description { state: "on" 0.0; \
inherit: "default" 0.0; \
color: 51 153 255 255; \
visible: 1; \
} \
description { state: "out" 0.0; \
inherit: "default" 0.0; \
color: 51 153 255 0; \
rel1.offset: -8 -8; \
rel2.offset: 7 7; \
visible: 1; \
} \
} \
part { name: "drag_"##DIR##"_glow"; \
mouse_events: 0; \
description { state: "default" 0.0; \
rel1.offset: -4 -4; \
rel1.to: "drag_"##DIR##"_outline"; \
rel2.offset: 3 3; \
rel2.to: "drag_"##DIR##"_outline"; \
image { \
normal: "cr_glow.png"; \
border: 9 9 9 9; \
} \
color: 51 153 255 40; \
visible: 0; \
} \
description { state: "hdrag,off" 0.0; \
inherit: "default" 0.0; \
visible: 1; \
} \
description { state: "active" 0.0; \
inherit: "default" 0.0; \
color: 51 153 255 255; \
visible: 1; \
} \
} \
part { name: "drag_"##DIR##"_outline"; \
mouse_events: 0; \
description { state: "default" 0.0; \
rel1.to: "viewregion"; \
rel1.relative: REL_ONE; \
rel2.to: "viewregion"; \
rel2.relative: REL_TWO; \
image { \
normal: "cr_out.png"; \
border: 3 3 3 3; \
} \
color: 51 153 255 80; \
visible: 0; \
} \
description { state: "hdrag,off" 0.0; \
inherit: "default" 0.0; \
visible: 1; \
} \
description { state: "active" 0.0; \
inherit: "default" 0.0; \
color: 255 255 255 255; \
visible: 1; \
} \
} \
program { \
name: "drag_"##DIR##",on"; \
signal: "drag_"##DIR##",on"; source: "terminology"; \
action: STATE_SET "active" 0.0; \
target: "drag_"##DIR##"_glow"; \
target: "drag_"##DIR##"_outline"; \
after: "drag_"##DIR##",on2"; \
after: "drag_"##DIR##"_pulse"; \
} \
program { name: "drag_"##DIR##",on2"; \
in: 0.5 0.0; \
action: STATE_SET "default" 0.0; \
transition: DECELERATE 0.2; \
target: "drag_"##DIR##"_glow"; \
target: "drag_"##DIR##"_outline"; \
after: "drag_"##DIR##",on3"; \
} \
program { name: "drag_"##DIR##",on3"; \
in: 0.5 0.0; \
action: STATE_SET "active" 0.0; \
target: "drag_"##DIR##"_glow"; \
target: "drag_"##DIR##"_outline"; \
after: "drag_"##DIR##",on2"; \
after: "drag_"##DIR##"_pulse"; \
} \
program { name: "drag_"##DIR##"_pulse"; \
action: STATE_SET "on" 0.0; \
target: "drag_"##DIR##"_pulse"; \
after: "drag_"##DIR##"_pulse2"; \
} \
program { name: "drag_"##DIR##"_pulse2"; \
action: STATE_SET "out" 0.0; \
transition: DECELERATE 0.4; \
target: "drag_"##DIR##"_pulse"; \
} \
program { \
signal: "drag_"##DIR##",off"; source: "terminology"; \
action: ACTION_STOP; \
target: "drag_"##DIR##",on"; \
target: "drag_"##DIR##",on2"; \
target: "drag_"##DIR##",on3"; \
target: "drag_"##DIR##"_pulse"; \
target: "drag_"##DIR##"_pulse2"; \
after: "drag_"##DIR##",off2"; \
} \
program { name: "drag_"##DIR##",off2"; \
action: STATE_SET "default" 0.0; \
target: "drag_"##DIR##"_glow"; \
target: "drag_"##DIR##"_outline"; \
}
DRAG_TARGET(left, 0.0 0.2, 0.15 0.8)
DRAG_TARGET(right, 0.85 0.2, 1.0 0.8)
DRAG_TARGET(top, 0.2 0.0, 0.8 0.2)
DRAG_TARGET(bottom, 0.2 0.8, 0.8 1.0)
////////////////////////////////////////////////////////////////////
// popup media over the terminal (until dismissed)
part { name: "popmedia_clip"; type: RECT;

View File

@ -73,10 +73,20 @@ typedef struct _Tabs Tabs;
typedef struct _Tab_Item Tab_Item;
typedef struct _Tab_Drag Tab_Drag;
enum drag_over_position {
DRAG_OVER_NONE,
DRAG_OVER_LEFT,
DRAG_OVER_RIGHT,
DRAG_OVER_TOP,
DRAG_OVER_BOTTOM,
};
struct _Tab_Drag
{
Evas_Coord mdx; /* Mouse-down x */
Evas_Coord mdy; /* Mouse-down y */
enum drag_over_position drag_over;
Term *term_over;
Evas_Object *icon;
Evas *e;
Ecore_Timer *timer;
@ -2963,12 +2973,46 @@ _term_hdrag_off(Term *term, void *data EINA_UNUSED)
return ECORE_CALLBACK_PASS_ON;
}
static void
_tab_drag_disable_anim_over(void)
{
if ((!_tab_drag) || (!_tab_drag->term_over) ||
(_tab_drag->drag_over == DRAG_OVER_NONE))
return;
switch (_tab_drag->drag_over)
{
case DRAG_OVER_LEFT:
elm_layout_signal_emit(_tab_drag->term_over->bg,
"drag_left,off", "terminology");
break;
case DRAG_OVER_RIGHT:
elm_layout_signal_emit(_tab_drag->term_over->bg,
"drag_right,off", "terminology");
break;
case DRAG_OVER_TOP:
elm_layout_signal_emit(_tab_drag->term_over->bg,
"drag_top,off", "terminology");
break;
case DRAG_OVER_BOTTOM:
elm_layout_signal_emit(_tab_drag->term_over->bg,
"drag_bottom,off", "terminology");
break;
default:
break;
}
elm_layout_signal_emit(_tab_drag->term_over->bg,
"hdrag,off", "terminology");
}
static void
_tab_drag_free(void)
{
if (!_tab_drag)
return;
_tab_drag_disable_anim_over();
for_each_term_do(_tab_drag->term->wn, &_term_hdrag_on, NULL);
ecore_timer_del(_tab_drag->timer);
@ -3248,18 +3292,91 @@ _tabs_drag_mouse_move(
const char *emission EINA_UNUSED,
const char *source EINA_UNUSED)
{
int x, y, w, h;
Evas_Coord xm, ym;
Evas_Coord x, y, w, h, off_x, off_y, mx, my;
Win *wn;
Term_Container *tc_wn;
Term *term_at_coords;
enum drag_over_position drag_over_position = DRAG_OVER_NONE;
if (!_tab_drag || !_tab_drag->icon)
return;
wn = _tab_drag->term->wn;
tc_wn = (Term_Container*) wn;
evas_object_geometry_get(_tab_drag->icon, NULL, NULL, &w, &h);
evas_pointer_canvas_xy_get(_tab_drag->e, &xm, &ym);
x = (xm - (w/2));
y = (ym - (h/2));
evas_pointer_canvas_xy_get(_tab_drag->e, &mx, &my);
x = (mx - (w/2));
y = (my - (h/2));
evas_object_move(_tab_drag->icon, x, y);
/* TODO: boris */
term_at_coords = tc_wn->find_term_at_coords(tc_wn, mx, my);
if (!term_at_coords)
return;
evas_object_geometry_get(term_at_coords->bg_edj, &off_x, &off_y, NULL, NULL);
edje_object_part_geometry_get(term_at_coords->bg_edj, "drag_left_outline",
&x, &y, &w, &h);
if (ELM_RECTS_INTERSECT(x+off_x, y+off_y, w, h, mx, my, 1, 1))
{
drag_over_position = DRAG_OVER_LEFT;
goto found;
}
edje_object_part_geometry_get(term_at_coords->bg_edj, "drag_right_outline",
&x, &y, &w, &h);
if (ELM_RECTS_INTERSECT(x+off_x, y+off_y, w, h, mx, my, 1, 1))
{
drag_over_position = DRAG_OVER_RIGHT;
goto found;
}
edje_object_part_geometry_get(term_at_coords->bg_edj, "drag_top_outline",
&x, &y, &w, &h);
if (ELM_RECTS_INTERSECT(x+off_x, y+off_y, w, h, mx, my, 1, 1))
{
drag_over_position = DRAG_OVER_TOP;
goto found;
}
edje_object_part_geometry_get(term_at_coords->bg_edj, "drag_bottom_outline",
&x, &y, &w, &h);
if (ELM_RECTS_INTERSECT(x+off_x, y+off_y, w, h, mx, my, 1, 1))
{
drag_over_position = DRAG_OVER_BOTTOM;
goto found;
}
found:
if ((_tab_drag->term_over != NULL) &&
((_tab_drag->term_over != term_at_coords) ||
(_tab_drag->drag_over != drag_over_position)))
{
_tab_drag_disable_anim_over();
}
if ((drag_over_position != DRAG_OVER_NONE) &&
((_tab_drag->term_over != term_at_coords) ||
(_tab_drag->drag_over != drag_over_position)))
{
switch (drag_over_position)
{
case DRAG_OVER_LEFT:
elm_layout_signal_emit(term_at_coords->bg,
"drag_left,on", "terminology");
break;
case DRAG_OVER_RIGHT:
elm_layout_signal_emit(term_at_coords->bg,
"drag_right,on", "terminology");
break;
case DRAG_OVER_TOP:
elm_layout_signal_emit(term_at_coords->bg,
"drag_top,on", "terminology");
break;
case DRAG_OVER_BOTTOM:
elm_layout_signal_emit(term_at_coords->bg,
"drag_bottom,on", "terminology");
break;
default:
break;
}
}
_tab_drag->term_over = term_at_coords;
_tab_drag->drag_over = drag_over_position;
}
static Eina_Bool
@ -6201,6 +6318,11 @@ _term_free(Term *term)
{
_tab_drag_free();
}
if (_tab_drag && _tab_drag->term_over == term)
{
_tab_drag->term_over = NULL;
_tab_drag->drag_over = DRAG_OVER_NONE;
}
if (term->sendfile_request)
{
evas_object_del(term->sendfile_request);