splits are back again
This commit is contained in:
parent
bbbb9f42e4
commit
8d8075ab36
|
@ -76,13 +76,13 @@ _cb_ct_new(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EIN
|
||||||
static void
|
static void
|
||||||
_cb_ct_split_v(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_cb_ct_split_v(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
main_split_v(ct_win, ct_term, NULL);
|
split_vertically(ct_win, ct_term, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cb_ct_split_h(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_cb_ct_split_h(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
main_split_h(ct_win, ct_term, NULL);
|
split_horizontally(ct_win, ct_term, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -291,7 +291,7 @@ main_ipc_new(Ipc_Instance *inst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win_solo_term_set(wn, term) < 0)
|
if (win_term_set(wn, term) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
main_trans_update(config);
|
main_trans_update(config);
|
||||||
|
@ -862,7 +862,7 @@ remote:
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win_solo_term_set(wn, term) < 0)
|
if (win_term_set(wn, term) < 0)
|
||||||
{
|
{
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
goto end;
|
goto end;
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
Config * main_config_get(void);
|
Config * main_config_get(void);
|
||||||
void main_new(Evas_Object *win, Evas_Object *term);
|
void main_new(Evas_Object *win, Evas_Object *term);
|
||||||
void main_new_with_dir(Evas_Object *win, Evas_Object *term, const char *wdir);
|
void main_new_with_dir(Evas_Object *win, Evas_Object *term, const char *wdir);
|
||||||
void main_split_h(Evas_Object *win, Evas_Object *term, char *cmd);
|
|
||||||
void main_split_v(Evas_Object *win, Evas_Object *term, char *cmd);
|
|
||||||
void main_close(Evas_Object *win, Evas_Object *term);
|
void main_close(Evas_Object *win, Evas_Object *term);
|
||||||
|
|
||||||
void main_trans_update(const Config *config);
|
void main_trans_update(const Config *config);
|
||||||
|
|
529
src/bin/win.c
529
src/bin/win.c
|
@ -1,3 +1,4 @@
|
||||||
|
#include <assert.h>
|
||||||
#include <Elementary.h>
|
#include <Elementary.h>
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "termcmd.h"
|
#include "termcmd.h"
|
||||||
|
@ -24,15 +25,18 @@
|
||||||
|
|
||||||
/* {{{ Structs */
|
/* {{{ Structs */
|
||||||
|
|
||||||
|
typedef struct _Term_Container Term_Container;
|
||||||
typedef struct _Split Split;
|
typedef struct _Split Split;
|
||||||
|
|
||||||
struct _Term
|
struct _Term
|
||||||
{
|
{
|
||||||
Win *wn;
|
Win *wn;
|
||||||
Config *config;
|
Config *config;
|
||||||
|
|
||||||
|
Term_Container *container;
|
||||||
Evas_Object *bg;
|
Evas_Object *bg;
|
||||||
Evas_Object *base;
|
Evas_Object *base;
|
||||||
Evas_Object *term;
|
Evas_Object *term; // TODO: boris: rename into termio
|
||||||
Evas_Object *media;
|
Evas_Object *media;
|
||||||
Evas_Object *popmedia;
|
Evas_Object *popmedia;
|
||||||
Evas_Object *miniview;
|
Evas_Object *miniview;
|
||||||
|
@ -75,55 +79,47 @@ typedef enum _Term_Container_Type
|
||||||
} Term_Container_Type;
|
} Term_Container_Type;
|
||||||
|
|
||||||
typedef struct _Term_Container Term_Container;
|
typedef struct _Term_Container Term_Container;
|
||||||
typedef struct _Term_Container_Api Term_Container_Api;
|
|
||||||
typedef struct _Solo Solo;
|
typedef struct _Solo Solo;
|
||||||
typedef struct _Tab Tab;
|
typedef struct _Tab Tab;
|
||||||
|
|
||||||
struct _Term_Container_Api {
|
struct _Term_Container {
|
||||||
Term *(*find_term_at_coords)(Term_Container *container, Evas_Coord mx, Evas_Coord my);
|
Term_Container_Type type;
|
||||||
|
Term_Container *parent;
|
||||||
|
Win *wn;
|
||||||
|
|
||||||
|
Evas_Object* (*get_evas_object)(Term_Container *container);
|
||||||
|
Term *(*find_term_at_coords)(Term_Container *container,
|
||||||
|
Evas_Coord mx, Evas_Coord my);
|
||||||
void (*size_eval)(Term_Container *container, Sizeinfo *info);
|
void (*size_eval)(Term_Container *container, Sizeinfo *info);
|
||||||
void (*free)(Term_Container *container);
|
void (*split)(Term_Container *container, const char *cmd,
|
||||||
|
Eina_Bool is_horizontal);
|
||||||
|
void (*swallow)(Term_Container *container, Term_Container *orig,
|
||||||
|
Term_Container *new_child);
|
||||||
|
void (*close)(Term_Container *container, Term_Container *child,
|
||||||
|
Eina_Bool refocus);
|
||||||
|
/* TODO: prev/next/focus */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Solo {
|
struct _Solo {
|
||||||
Term_Container_Api api;
|
Term_Container tc;
|
||||||
/* TODO */
|
/* TODO */
|
||||||
Term *term;
|
Term *term;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Tab {
|
struct _Tab {
|
||||||
Term_Container_Api api;
|
Term_Container tc;
|
||||||
/* TODO */
|
/* TODO */
|
||||||
Term *term;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Split
|
struct _Split
|
||||||
{
|
{
|
||||||
Term_Container_Api api;
|
Term_Container tc;
|
||||||
Win *wn; // win this split belongs to
|
Term_Container *tc1, *tc2; // left/right or top/bottom child splits, null if leaf
|
||||||
Split *parent; // the parent split or null if toplevel
|
|
||||||
Split *s1, *s2; // left/right or top/bottom child splits, null if leaf
|
|
||||||
Term *term; // if leaf node this is not null - the CURRENT term from terms list
|
|
||||||
Eina_List *terms; // list of terms in the "tabs"
|
|
||||||
Evas_Object *panes; // null if a leaf node
|
Evas_Object *panes; // null if a leaf node
|
||||||
Evas_Object *sel; // multi "tab" selector is active
|
unsigned char is_horizontal : 1;
|
||||||
Evas_Object *sel_bg; // multi "tab" selector wrapper edje obj for styling
|
|
||||||
unsigned char horizontal : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct _Term_Container
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
Term_Container_Api *api;
|
|
||||||
Split *split;
|
|
||||||
Solo *solo;
|
|
||||||
Tab *tab;
|
|
||||||
} u;
|
|
||||||
Term_Container_Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Win
|
struct _Win
|
||||||
{
|
{
|
||||||
Evas_Object *win;
|
Evas_Object *win;
|
||||||
|
@ -145,7 +141,9 @@ struct _Win
|
||||||
static Eina_List *wins = NULL;
|
static Eina_List *wins = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void _term_resize_track_start(Term *term);
|
static Term_Container *_solo_new(Term *term);
|
||||||
|
static Term_Container *_split_new(Term_Container *tc1, Term_Container *tc2, Eina_Bool is_horizontal);
|
||||||
|
//static void _term_resize_track_start(Term *term);
|
||||||
static void _split_tabcount_update(Split *sp, Term *tm);
|
static void _split_tabcount_update(Split *sp, Term *tm);
|
||||||
static Term * win_focused_term_get(Win *wn);
|
static Term * win_focused_term_get(Win *wn);
|
||||||
static Split * _split_find(Evas_Object *win, Evas_Object *term, Term **ptm);
|
static Split * _split_find(Evas_Object *win, Evas_Object *term, Term **ptm);
|
||||||
|
@ -154,10 +152,10 @@ static void term_free(Term *term);
|
||||||
//static void _split_free(Split *sp);
|
//static void _split_free(Split *sp);
|
||||||
//static void _sel_restore(Split *sp);
|
//static void _sel_restore(Split *sp);
|
||||||
static void _sel_go(Split *sp, Term *term);
|
static void _sel_go(Split *sp, Term *term);
|
||||||
static void _term_resize_track_stop(Term *term);
|
//static void _term_resize_track_stop(Term *term);
|
||||||
//static void _split_merge(Split *spp, Split *sp, const char *slot);
|
//static void _split_merge(Split *spp, Split *sp, const char *slot);
|
||||||
//static void _term_focus_show(Split *sp, Term *term);
|
//static void _term_focus_show(Split *sp, Term *term);
|
||||||
static void _main_term_bg_redo(Term *term);
|
//static void _main_term_bg_redo(Term *term);
|
||||||
static void _term_media_update(Term *term, const Config *config);
|
static void _term_media_update(Term *term, const Config *config);
|
||||||
static void _term_miniview_check(Term *term);
|
static void _term_miniview_check(Term *term);
|
||||||
static void _popmedia_queue_process(Term *term);
|
static void _popmedia_queue_process(Term *term);
|
||||||
|
@ -219,7 +217,7 @@ _cb_win_focus_in(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUS
|
||||||
Evas_Coord mx, my;
|
Evas_Coord mx, my;
|
||||||
|
|
||||||
evas_pointer_canvas_xy_get(evas_object_evas_get(wn->win), &mx, &my);
|
evas_pointer_canvas_xy_get(evas_object_evas_get(wn->win), &mx, &my);
|
||||||
term_mouse = wn->container->u.api->find_term_at_coords(wn->container, mx, my);
|
term_mouse = wn->container->find_term_at_coords(wn->container, mx, my);
|
||||||
if ((term_mouse) && (term_mouse != term))
|
if ((term_mouse) && (term_mouse != term))
|
||||||
{
|
{
|
||||||
if (term)
|
if (term)
|
||||||
|
@ -303,21 +301,38 @@ _cb_term_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSE
|
||||||
|
|
||||||
/* {{{ Solo */
|
/* {{{ Solo */
|
||||||
|
|
||||||
|
static Evas_Object *
|
||||||
|
_solo_get_evas_object(Term_Container *container)
|
||||||
|
{
|
||||||
|
Solo *solo;
|
||||||
|
assert (container->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
solo = (Solo*)container;
|
||||||
|
|
||||||
|
return solo->term->bg;
|
||||||
|
}
|
||||||
|
|
||||||
static Term *
|
static Term *
|
||||||
_solo_find_term_at_coords(Term_Container *container,
|
_solo_find_term_at_coords(Term_Container *container,
|
||||||
Evas_Coord mx EINA_UNUSED,
|
Evas_Coord mx EINA_UNUSED,
|
||||||
Evas_Coord my EINA_UNUSED)
|
Evas_Coord my EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Solo *solo = container->u.solo;
|
Solo *solo;
|
||||||
|
assert (container->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
solo = (Solo*)container;
|
||||||
|
|
||||||
return solo->term;
|
return solo->term;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_solo_size_eval(Term_Container *container, Sizeinfo *info)
|
_solo_size_eval(Term_Container *container, Sizeinfo *info)
|
||||||
{
|
{
|
||||||
Solo *solo = container->u.solo;
|
Term *term;
|
||||||
Term *term = solo->term;
|
|
||||||
int mw = 0, mh = 0;
|
int mw = 0, mh = 0;
|
||||||
|
Solo *solo;
|
||||||
|
assert (container->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
solo = (Solo*)container;
|
||||||
|
|
||||||
|
term = solo->term;
|
||||||
|
|
||||||
info->min_w = term->min_w;
|
info->min_w = term->min_w;
|
||||||
info->min_h = term->min_h;
|
info->min_h = term->min_h;
|
||||||
|
@ -336,49 +351,121 @@ _solo_size_eval(Term_Container *container, Sizeinfo *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_solo_free(Term_Container *container EINA_UNUSED)
|
_solo_close(Term_Container *tc, Term_Container *child EINA_UNUSED,
|
||||||
|
Eina_Bool refocus)
|
||||||
{
|
{
|
||||||
/* TODO */
|
Term_Container *parent;
|
||||||
|
|
||||||
|
parent = tc->parent;
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
parent->close(parent, tc, refocus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(tc == tc->wn->container);
|
||||||
|
tc->wn->container = NULL;
|
||||||
|
win_free(tc->wn);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_solo_split(Term_Container *tc, const char *cmd, Eina_Bool is_horizontal)
|
||||||
|
{
|
||||||
|
Solo *solo;
|
||||||
|
Term *tm_new, *tm;
|
||||||
|
Term_Container *tc_split, *tc_new, *tc_parent;
|
||||||
|
Win *wn;
|
||||||
|
Evas_Object *obj_split;
|
||||||
|
char buf[PATH_MAX], *wdir = NULL;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
solo = (Solo*) tc;
|
||||||
|
tm = solo->term;
|
||||||
|
wn = tc->wn;
|
||||||
|
|
||||||
|
tc_parent = tc->parent;
|
||||||
|
|
||||||
|
DBG("solo split tc:%p cmd:%s is_horizontal:%d", tc, cmd, is_horizontal);
|
||||||
|
/* TODO: boris _split_split */
|
||||||
|
|
||||||
|
if (termio_cwd_get(tm->term, buf, sizeof(buf)))
|
||||||
|
wdir = buf;
|
||||||
|
tm_new = term_new(wn, wn->config,
|
||||||
|
cmd, wn->config->login_shell, wdir,
|
||||||
|
80, 24, EINA_FALSE);
|
||||||
|
tc_new = _solo_new(tm_new);
|
||||||
|
tc_new->wn = wn;
|
||||||
|
|
||||||
|
tc_split = _split_new(tc, tc_new, is_horizontal);
|
||||||
|
|
||||||
|
obj_split = tc_split->get_evas_object(tc_split);
|
||||||
|
tc_split->parent = tc_parent;
|
||||||
|
|
||||||
|
/* TODO: have a window container for that case? */
|
||||||
|
if (!tc_parent)
|
||||||
|
{
|
||||||
|
Evas_Object *base = win_base_get(wn);
|
||||||
|
|
||||||
|
edje_object_part_unswallow(base, tm->bg);
|
||||||
|
|
||||||
|
edje_object_part_swallow(base, "terminology.content", obj_split);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tc_parent->swallow(tc_parent, tc, tc_split);
|
||||||
|
}
|
||||||
|
|
||||||
|
evas_object_show(obj_split);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Term_Container *
|
static Term_Container *
|
||||||
solo_new(Term *term)
|
_solo_new(Term *term)
|
||||||
{
|
{
|
||||||
Term_Container *container = NULL;
|
Term_Container *tc = NULL;
|
||||||
Solo *solo = NULL;
|
Solo *solo = NULL;
|
||||||
Term_Container_Api *api;
|
|
||||||
container = calloc(1, sizeof(Term_Container));
|
|
||||||
solo = calloc(1, sizeof(Solo));
|
solo = calloc(1, sizeof(Solo));
|
||||||
if (!solo || !container)
|
if (!solo)
|
||||||
{
|
{
|
||||||
free(container);
|
|
||||||
free(solo);
|
free(solo);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
api = (Term_Container_Api*)solo;
|
tc = (Term_Container*)solo;
|
||||||
api->find_term_at_coords = _solo_find_term_at_coords;
|
tc->get_evas_object = _solo_get_evas_object;
|
||||||
api->size_eval = _solo_size_eval;
|
tc->find_term_at_coords = _solo_find_term_at_coords;
|
||||||
api->free = _solo_free;
|
tc->size_eval = _solo_size_eval;
|
||||||
solo->term = term;
|
tc->split = _solo_split;
|
||||||
container->u.solo = solo;
|
tc->swallow = NULL;
|
||||||
container->type = TERM_CONTAINER_TYPE_SOLO;
|
tc->close= _solo_close;
|
||||||
|
|
||||||
return container;
|
tc->parent = NULL;
|
||||||
|
tc->wn = NULL;
|
||||||
|
|
||||||
|
solo->term = term;
|
||||||
|
tc->type = TERM_CONTAINER_TYPE_SOLO;
|
||||||
|
|
||||||
|
term->container = tc;
|
||||||
|
|
||||||
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Win */
|
/* {{{ Win */
|
||||||
|
|
||||||
|
|
||||||
int win_solo_term_set(Win *wn, Term *term)
|
int win_term_set(Win *wn, Term *term)
|
||||||
{
|
{
|
||||||
Evas_Object *base = win_base_get(wn);
|
Evas_Object *base = win_base_get(wn);
|
||||||
Evas *evas = evas_object_evas_get(base);
|
Evas *evas = evas_object_evas_get(base);
|
||||||
|
|
||||||
|
/* TODO: boris tab */
|
||||||
|
|
||||||
wn->container = solo_new(term);
|
wn->container = _solo_new(term);
|
||||||
if (!wn->container) return -1;
|
if (!wn->container) return -1;
|
||||||
|
wn->container->wn = wn;
|
||||||
|
|
||||||
/* TODO: resize track */
|
/* TODO: resize track */
|
||||||
//_term_resize_track_start(sp);
|
//_term_resize_track_start(sp);
|
||||||
|
@ -508,11 +595,6 @@ win_free(Win *wn)
|
||||||
evas_object_del(wn->cmdbox);
|
evas_object_del(wn->cmdbox);
|
||||||
wn->cmdbox = NULL;
|
wn->cmdbox = NULL;
|
||||||
}
|
}
|
||||||
if (wn->container)
|
|
||||||
{
|
|
||||||
wn->container->u.api->free(wn->container);
|
|
||||||
wn->container = NULL;
|
|
||||||
}
|
|
||||||
if (wn->win)
|
if (wn->win)
|
||||||
{
|
{
|
||||||
evas_object_event_callback_del_full(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn);
|
evas_object_event_callback_del_full(wn->win, EVAS_CALLBACK_DEL, _cb_del, wn);
|
||||||
|
@ -638,14 +720,13 @@ win_new(const char *name, const char *role, const char *title,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
main_close(Evas_Object *win EINA_UNUSED, Evas_Object *term EINA_UNUSED)
|
main_close(Evas_Object *win, Evas_Object *term)
|
||||||
{
|
{
|
||||||
/* TODO boris */
|
|
||||||
Term *tm;
|
Term *tm;
|
||||||
|
Term_Container *tc;
|
||||||
Win *wn = _win_find(win);
|
Win *wn = _win_find(win);
|
||||||
Eina_Bool term_was_focused;
|
|
||||||
|
|
||||||
if (!wm) return;
|
if (!wn) return;
|
||||||
|
|
||||||
app_server_term_del(term);
|
app_server_term_del(term);
|
||||||
|
|
||||||
|
@ -653,7 +734,10 @@ main_close(Evas_Object *win EINA_UNUSED, Evas_Object *term EINA_UNUSED)
|
||||||
if (!tm) return;
|
if (!tm) return;
|
||||||
|
|
||||||
wn->terms = eina_list_remove(wn->terms, tm);
|
wn->terms = eina_list_remove(wn->terms, tm);
|
||||||
term_was_focused = tm->focused;
|
tc = tm->container;
|
||||||
|
tc->close(tc, tc, tm->focused);
|
||||||
|
|
||||||
|
term_free(tm);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Split *sp = _split_find(win, term, &tm);
|
Split *sp = _split_find(win, term, &tm);
|
||||||
|
@ -788,6 +872,244 @@ win_focused_term_get(Win *wn)
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Splits */
|
/* {{{ Splits */
|
||||||
|
|
||||||
|
static Evas_Object *
|
||||||
|
_split_get_evas_object(Term_Container *tc)
|
||||||
|
{
|
||||||
|
Split *split;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
|
||||||
|
split = (Split*) tc;
|
||||||
|
|
||||||
|
return split->panes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_split_size_eval(Term_Container *tc, Sizeinfo *info)
|
||||||
|
{
|
||||||
|
Evas_Coord mw = 0, mh = 0;
|
||||||
|
Term_Container *tc1, *tc2;
|
||||||
|
Sizeinfo inforet;
|
||||||
|
Split *split;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
|
||||||
|
split = (Split*) tc;
|
||||||
|
|
||||||
|
tc1 = split->tc1;
|
||||||
|
tc2 = split->tc2;
|
||||||
|
|
||||||
|
info->min_w = 0;
|
||||||
|
info->min_h = 0;
|
||||||
|
info->req_w = 0;
|
||||||
|
info->req_h = 0;
|
||||||
|
|
||||||
|
evas_object_size_hint_min_get(split->panes, &mw, &mh);
|
||||||
|
info->bg_min_w = mw;
|
||||||
|
info->bg_min_h = mh;
|
||||||
|
|
||||||
|
if (split->is_horizontal)
|
||||||
|
{
|
||||||
|
tc1->size_eval(tc1, &inforet);
|
||||||
|
info->req |= inforet.req;
|
||||||
|
mh -= inforet.min_h;
|
||||||
|
if (info->req)
|
||||||
|
{
|
||||||
|
info->req_h += inforet.req_h;
|
||||||
|
info->req_w = inforet.req_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
tc2->size_eval(tc2, &inforet);
|
||||||
|
info->req |= inforet.req;
|
||||||
|
mh -= inforet.min_h;
|
||||||
|
if (info->req)
|
||||||
|
{
|
||||||
|
info->req_h += inforet.req_h;
|
||||||
|
info->req_w = inforet.req_w;
|
||||||
|
}
|
||||||
|
info->req_h += mh;
|
||||||
|
if (info->req)
|
||||||
|
info->req_w += mw - inforet.min_w - inforet.step_x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tc1->size_eval(tc1, &inforet);
|
||||||
|
info->req |= inforet.req;
|
||||||
|
mw -= inforet.min_w;
|
||||||
|
if (info->req)
|
||||||
|
{
|
||||||
|
info->req_w += inforet.req_w;
|
||||||
|
info->req_h = inforet.req_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
tc2->size_eval(tc2, &inforet);
|
||||||
|
info->req |= inforet.req;
|
||||||
|
mw -= inforet.min_w;
|
||||||
|
if (info->req)
|
||||||
|
{
|
||||||
|
info->req_w += inforet.req_w;
|
||||||
|
info->req_h = inforet.req_h;
|
||||||
|
}
|
||||||
|
info->req_w += mw;
|
||||||
|
if (info->req)
|
||||||
|
info->req_h += mh - inforet.min_h - inforet.step_y;
|
||||||
|
}
|
||||||
|
info->step_x = inforet.step_x;
|
||||||
|
info->step_y = inforet.step_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_split_swallow(Term_Container *tc, Term_Container *orig,
|
||||||
|
Term_Container *new_child)
|
||||||
|
{
|
||||||
|
Split *split;
|
||||||
|
Evas_Object *o;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
|
||||||
|
split = (Split*) tc;
|
||||||
|
|
||||||
|
o = new_child->get_evas_object(new_child);
|
||||||
|
if (split->tc1 == orig)
|
||||||
|
{
|
||||||
|
elm_object_part_content_unset(split->panes, PANES_TOP);
|
||||||
|
elm_object_part_content_set(split->panes, PANES_TOP, o);
|
||||||
|
split->tc1 = new_child;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
elm_object_part_content_unset(split->panes, PANES_BOTTOM);
|
||||||
|
elm_object_part_content_set(split->panes, PANES_BOTTOM, o);
|
||||||
|
split->tc2 = new_child;
|
||||||
|
}
|
||||||
|
new_child->parent = tc;
|
||||||
|
evas_object_show(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Term *
|
||||||
|
_split_find_term_at_coords(Term_Container *tc,
|
||||||
|
Evas_Coord mx, Evas_Coord my)
|
||||||
|
{
|
||||||
|
Split *split;
|
||||||
|
Evas_Coord ox, oy, ow, oh;
|
||||||
|
Evas_Object *o;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
|
||||||
|
split = (Split*) tc;
|
||||||
|
|
||||||
|
o = split->tc1->get_evas_object(split->tc1);
|
||||||
|
|
||||||
|
evas_object_geometry_get(o, &ox, &oy, &ow, &oh);
|
||||||
|
if (ELM_RECTS_INTERSECT(ox, oy, ow, oh, mx, my, 1, 1))
|
||||||
|
{
|
||||||
|
tc = split->tc1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tc = split->tc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tc->find_term_at_coords(tc, mx, my);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_split_close(Term_Container *tc, Term_Container *child,
|
||||||
|
Eina_Bool refocus EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Split *split;
|
||||||
|
Term_Container *parent;
|
||||||
|
|
||||||
|
assert (tc->type == TERM_CONTAINER_TYPE_SPLIT);
|
||||||
|
split = (Split*) tc;
|
||||||
|
|
||||||
|
/* TODO: refocus */
|
||||||
|
elm_object_part_content_unset(split->panes, PANES_TOP);
|
||||||
|
elm_object_part_content_unset(split->panes, PANES_BOTTOM);
|
||||||
|
|
||||||
|
parent = tc->parent;
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
if (child == split->tc1)
|
||||||
|
{
|
||||||
|
parent->swallow(parent, tc, split->tc2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent->swallow(parent, tc, split->tc1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Evas_Object *base = win_base_get(tc->wn);
|
||||||
|
|
||||||
|
if (child == split->tc1)
|
||||||
|
{
|
||||||
|
edje_object_part_unswallow(base,
|
||||||
|
split->panes);
|
||||||
|
edje_object_part_swallow(base, "terminology.content",
|
||||||
|
split->tc2->get_evas_object(split->tc2));
|
||||||
|
split->tc2->parent = NULL;
|
||||||
|
tc->wn->container = split->tc2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edje_object_part_unswallow(base,
|
||||||
|
split->panes);
|
||||||
|
edje_object_part_swallow(base, "terminology.content",
|
||||||
|
split->tc1->get_evas_object(split->tc1));
|
||||||
|
split->tc1->parent = NULL;
|
||||||
|
tc->wn->container = split->tc1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evas_object_del(split->panes);
|
||||||
|
free(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Term_Container *
|
||||||
|
_split_new(Term_Container *tc1, Term_Container *tc2, Eina_Bool is_horizontal)
|
||||||
|
{
|
||||||
|
Evas_Object *o;
|
||||||
|
Term_Container *tc = NULL;
|
||||||
|
Split *split = NULL;
|
||||||
|
split = calloc(1, sizeof(Split));
|
||||||
|
if (!split)
|
||||||
|
{
|
||||||
|
free(split);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tc = (Term_Container*)split;
|
||||||
|
tc->get_evas_object = _split_get_evas_object;
|
||||||
|
tc->find_term_at_coords = _split_find_term_at_coords;
|
||||||
|
tc->size_eval = _split_size_eval;
|
||||||
|
tc->split = NULL;
|
||||||
|
tc->swallow = _split_swallow;
|
||||||
|
tc->close = _split_close;
|
||||||
|
|
||||||
|
tc->parent = NULL;
|
||||||
|
tc->wn = tc1->wn;
|
||||||
|
|
||||||
|
tc->type = TERM_CONTAINER_TYPE_SPLIT;
|
||||||
|
|
||||||
|
tc1->parent = tc2->parent = tc;
|
||||||
|
|
||||||
|
split->tc1 = tc1;
|
||||||
|
split->tc2 = tc2;
|
||||||
|
|
||||||
|
o = split->panes = elm_panes_add(tc1->wn->win);
|
||||||
|
elm_object_style_set(o, "flush");
|
||||||
|
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||||
|
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
|
|
||||||
|
split->is_horizontal = is_horizontal;
|
||||||
|
elm_panes_horizontal_set(o, split->is_horizontal);
|
||||||
|
|
||||||
|
elm_object_part_content_set(o, PANES_TOP,
|
||||||
|
tc1->get_evas_object(tc1));
|
||||||
|
elm_object_part_content_set(o, PANES_BOTTOM,
|
||||||
|
tc2->get_evas_object(tc2));
|
||||||
|
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
_split_size_walk(Split *sp, Sizeinfo *info)
|
_split_size_walk(Split *sp, Sizeinfo *info)
|
||||||
|
@ -877,14 +1199,7 @@ _size_job(void *data)
|
||||||
|
|
||||||
wn->size_job = NULL;
|
wn->size_job = NULL;
|
||||||
DBG("size job");
|
DBG("size job");
|
||||||
tc->u.api->size_eval(tc, &info);
|
tc->size_eval(tc, &info);
|
||||||
#if 0
|
|
||||||
_split_size_walk(wn->split, &info);
|
|
||||||
if (wn->split->panes)
|
|
||||||
evas_object_size_hint_min_get(wn->split->panes, &mw, &mh);
|
|
||||||
else
|
|
||||||
evas_object_size_hint_min_get(wn->split->term->bg, &mw, &mh);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
elm_win_size_base_set(wn->win,
|
elm_win_size_base_set(wn->win,
|
||||||
info.bg_min_w - info.step_x,
|
info.bg_min_w - info.step_x,
|
||||||
|
@ -992,8 +1307,10 @@ _split_free(Split *sp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_split_tabcount_update(Split *sp, Term *tm)
|
_split_tabcount_update(Split *sp EINA_UNUSED, Term *tm EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
/* TODO */
|
||||||
|
#if 0
|
||||||
char buf[32], bufm[32];
|
char buf[32], bufm[32];
|
||||||
int n = eina_list_count(sp->terms);
|
int n = eina_list_count(sp->terms);
|
||||||
int missed = 0;
|
int missed = 0;
|
||||||
|
@ -1036,11 +1353,14 @@ _split_tabcount_update(Split *sp, Term *tm)
|
||||||
else
|
else
|
||||||
edje_object_signal_emit(term->bg, "tabmissed,off", "terminology");
|
edje_object_signal_emit(term->bg, "tabmissed,off", "terminology");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
_split_split(Split *sp, Eina_Bool horizontal, char *cmd)
|
_split_split(Split *sp, Eina_Bool horizontal, char *cmd)
|
||||||
{
|
{
|
||||||
|
/* TODO: boris */
|
||||||
Split *sp2, *sp1;
|
Split *sp2, *sp1;
|
||||||
Evas_Object *o;
|
Evas_Object *o;
|
||||||
Config *config;
|
Config *config;
|
||||||
|
@ -1104,6 +1424,7 @@ _split_split(Split *sp, Eina_Bool horizontal, char *cmd)
|
||||||
evas_object_show(sp->panes);
|
evas_object_show(sp->panes);
|
||||||
sp->term = NULL;
|
sp->term = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
|
@ -1139,9 +1460,12 @@ _term_focus_show(Split *sp, Term *term)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
main_new_with_dir(Evas_Object *win, Evas_Object *term, const char *wdir)
|
main_new_with_dir(Evas_Object *win EINA_UNUSED,
|
||||||
|
Evas_Object *term EINA_UNUSED,
|
||||||
|
const char *wdir EINA_UNUSED)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
#if 0
|
||||||
Split *sp = _split_find(win, term, NULL);
|
Split *sp = _split_find(win, term, NULL);
|
||||||
Config *config;
|
Config *config;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
@ -1161,6 +1485,7 @@ main_new_with_dir(Evas_Object *win, Evas_Object *term, const char *wdir)
|
||||||
evas_object_data_set(sp->term->term, "sizedone", sp->term->term);
|
evas_object_data_set(sp->term->term, "sizedone", sp->term->term);
|
||||||
//_term_focus_show(sp, sp->term);
|
//_term_focus_show(sp, sp->term);
|
||||||
_split_tabcount_update(sp, sp->term);
|
_split_tabcount_update(sp, sp->term);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1178,21 +1503,31 @@ main_new(Evas_Object *win EINA_UNUSED, Evas_Object *term EINA_UNUSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
main_split_h(Evas_Object *win, Evas_Object *term, char *cmd)
|
split_horizontally(Evas_Object *win EINA_UNUSED, Evas_Object *term,
|
||||||
|
const char *cmd)
|
||||||
{
|
{
|
||||||
Split *sp = _split_find(win, term, NULL);
|
Term *tm;
|
||||||
|
Term_Container *tc;
|
||||||
|
|
||||||
if (!sp) return;
|
tm = evas_object_data_get(term, "term");
|
||||||
_split_split(sp, EINA_TRUE, cmd);
|
if (!tm) return;
|
||||||
|
|
||||||
|
tc = tm->container;
|
||||||
|
tc->split(tc, cmd, EINA_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
main_split_v(Evas_Object *win, Evas_Object *term, char *cmd)
|
split_vertically(Evas_Object *win EINA_UNUSED, Evas_Object *term,
|
||||||
|
const char *cmd)
|
||||||
{
|
{
|
||||||
Split *sp = _split_find(win, term, NULL);
|
Term *tm;
|
||||||
|
Term_Container *tc;
|
||||||
|
|
||||||
if (!sp) return;
|
tm = evas_object_data_get(term, "term");
|
||||||
_split_split(sp, EINA_FALSE, cmd);
|
if (!tm) return;
|
||||||
|
|
||||||
|
tc = tm->container;
|
||||||
|
tc->split(tc, cmd, EINA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1358,6 +1693,7 @@ _split_merge(Split *spp, Split *sp, const char *slot)
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Term */
|
/* {{{ Term */
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
_cb_size_track(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
|
_cb_size_track(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
@ -1386,6 +1722,7 @@ _term_resize_track_stop(Term *term)
|
||||||
evas_object_event_callback_del_full(term->bg, EVAS_CALLBACK_RESIZE,
|
evas_object_event_callback_del_full(term->bg, EVAS_CALLBACK_RESIZE,
|
||||||
_cb_size_track, term);
|
_cb_size_track, term);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void change_theme(Evas_Object *win, Config *config)
|
void change_theme(Evas_Object *win, Config *config)
|
||||||
|
@ -1604,15 +1941,17 @@ _term_miniview_check(Term *term)
|
||||||
|
|
||||||
EINA_LIST_FOREACH(wn_list, l, term)
|
EINA_LIST_FOREACH(wn_list, l, term)
|
||||||
{
|
{
|
||||||
Split *sp = _split_find(term->wn->win, term->term, NULL);
|
//Split *sp = _split_find(term->wn->win, term->term, NULL);
|
||||||
if (term->miniview_shown)
|
if (term->miniview_shown)
|
||||||
{
|
{
|
||||||
if (term->focused)
|
if (term->focused)
|
||||||
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
||||||
|
#if 0
|
||||||
else if (sp->term != term)
|
else if (sp->term != term)
|
||||||
edje_object_signal_emit(term->bg, "miniview,off", "terminology");
|
edje_object_signal_emit(term->bg, "miniview,off", "terminology");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
sp = NULL;
|
//sp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1819,11 +2158,13 @@ _cb_new(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
void
|
void
|
||||||
main_term_focus(Term *term EINA_UNUSED)
|
main_term_focus(Term *term EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
Split *sp;
|
Split *sp;
|
||||||
|
|
||||||
sp = _split_find(term->wn->win, term->term, NULL);
|
sp = _split_find(term->wn->win, term->term, NULL);
|
||||||
if (sp->terms->next != NULL)
|
if (sp->terms->next != NULL)
|
||||||
_sel_go(sp, term);
|
_sel_go(sp, term);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1837,16 +2178,20 @@ static void
|
||||||
_cb_split_h(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_cb_split_h(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Term *term = data;
|
Term *term = data;
|
||||||
|
Term_Container *tc = term->container;
|
||||||
|
|
||||||
main_split_h(term->wn->win, term->term, NULL);
|
assert(tc->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
tc->split(tc, NULL, EINA_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cb_split_v(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_cb_split_v(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Term *term = data;
|
Term *term = data;
|
||||||
|
Term_Container *tc = term->container;
|
||||||
main_split_v(term->wn->win, term->term, NULL);
|
|
||||||
|
assert(tc->type == TERM_CONTAINER_TYPE_SOLO);
|
||||||
|
tc->split(tc, NULL, EINA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1866,15 +2211,17 @@ _cb_icon(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_tab_go(Term *term, int tnum)
|
_tab_go(Term *term EINA_UNUSED, int tnum EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
Term *term2;
|
Term *term2;
|
||||||
Split *sp = _split_find(term->wn->win, term->term, NULL);
|
Split *sp = _split_find(term->wn->win, term->term, NULL);
|
||||||
if (!sp) return;
|
if (!sp) return;
|
||||||
|
|
||||||
term2 = eina_list_nth(sp->terms, tnum);
|
term2 = eina_list_nth(sp->terms, tnum);
|
||||||
if ((!term2) || (term2 == term)) return;
|
if ((!term2) || (term2 == term)) return;
|
||||||
_sel_go(sp, term2);
|
_sel_go(sp, term2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CB_TAB(TAB) \
|
#define CB_TAB(TAB) \
|
||||||
|
@ -2360,6 +2707,7 @@ main_term_bg_config(Term *term)
|
||||||
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
_main_term_bg_redo(Term *term)
|
_main_term_bg_redo(Term *term)
|
||||||
{
|
{
|
||||||
|
@ -2406,6 +2754,7 @@ _main_term_bg_redo(Term *term)
|
||||||
if (term->miniview_shown)
|
if (term->miniview_shown)
|
||||||
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
edje_object_signal_emit(term->bg, "miniview,on", "terminology");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Eina_Bool
|
Eina_Bool
|
||||||
main_term_popup_exists(const Term *term)
|
main_term_popup_exists(const Term *term)
|
||||||
|
@ -2444,6 +2793,7 @@ _cb_bell(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
if (!config) return;
|
if (!config) return;
|
||||||
if (!config->disable_visual_bell)
|
if (!config->disable_visual_bell)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
Split *sp;
|
Split *sp;
|
||||||
|
|
||||||
edje_object_signal_emit(term->bg, "bell", "terminology");
|
edje_object_signal_emit(term->bg, "bell", "terminology");
|
||||||
|
@ -2462,6 +2812,7 @@ _cb_bell(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
_split_tabcount_update(sp, sp->term);
|
_split_tabcount_update(sp, sp->term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (config->urg_bell)
|
if (config->urg_bell)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,8 @@ Evas_Object *term_miniview_get(Term *term);
|
||||||
void term_miniview_toggle(Term *term);
|
void term_miniview_toggle(Term *term);
|
||||||
void term_miniview_hide(Term *term);
|
void term_miniview_hide(Term *term);
|
||||||
|
|
||||||
|
void split_horizontally(Evas_Object *win, Evas_Object *term, const char *cmd);
|
||||||
|
void split_vertically(Evas_Object *win, Evas_Object *term, const char *cmd);
|
||||||
|
|
||||||
Win *
|
Win *
|
||||||
win_new(const char *name, const char *role, const char *title,
|
win_new(const char *name, const char *role, const char *title,
|
||||||
|
@ -35,7 +37,7 @@ Evas_Object *win_base_get(Win *wn);
|
||||||
Evas_Object *win_evas_object_get(Win *win);
|
Evas_Object *win_evas_object_get(Win *win);
|
||||||
Eina_List * win_terms_get(Win *wn);
|
Eina_List * win_terms_get(Win *wn);
|
||||||
Config *win_config_get(Win *wn);
|
Config *win_config_get(Win *wn);
|
||||||
int win_solo_term_set(Win *wn, Term *term);
|
int win_term_set(Win *wn, Term *term);
|
||||||
void win_sizing_handle(Win *wn);
|
void win_sizing_handle(Win *wn);
|
||||||
|
|
||||||
void term_next(Term *term);
|
void term_next(Term *term);
|
||||||
|
|
Loading…
Reference in New Issue