2403 lines
74 KiB
C
2403 lines
74 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <Elementary_Cursor.h>
|
|
#include "common.h"
|
|
|
|
#define CTRL_PT_LAYER 3
|
|
#define INFO_TEXT_LAYER (CTRL_PT_LAYER+1)
|
|
#define PART_NAME_MAX 1024
|
|
#define ALIGN_LINE_LEFT 0x0001
|
|
#define ALIGN_LINE_RIGHT 0x0010
|
|
#define ALIGN_LINE_TOP 0x0100
|
|
#define ALIGN_LINE_BOTTOM 0x1000
|
|
|
|
typedef struct livedit_item_s
|
|
{
|
|
const char *name;
|
|
Edje_Part_Type type;
|
|
} liveedit_item;
|
|
|
|
typedef enum
|
|
{
|
|
Ctrl_Pt_Rel1 = 0,
|
|
Ctrl_Pt_Rel2,
|
|
Ctrl_Pt_Rel3,
|
|
Ctrl_Pt_Rel4,
|
|
Ctrl_Pt_Top,
|
|
Ctrl_Pt_Bottom,
|
|
Ctrl_Pt_Left,
|
|
Ctrl_Pt_Right,
|
|
Ctrl_Pt_Cnt
|
|
} Ctrl_Pt;
|
|
|
|
typedef enum
|
|
{
|
|
Info_Text_Rel1 = 0,
|
|
Info_Text_Rel2,
|
|
Info_Text_Size,
|
|
Info_Text_Cnt
|
|
} Info_Text;
|
|
|
|
typedef enum
|
|
{
|
|
Align_Line_Top,
|
|
Align_Line_Bottom,
|
|
Align_Line_Left,
|
|
Align_Line_Right,
|
|
Align_Line_Cnt
|
|
} Align_Line;
|
|
|
|
typedef struct live_editor_s
|
|
{
|
|
Evas_Object *layout;
|
|
Evas_Object *live_view;
|
|
Evas_Object *ctrl_pt[Ctrl_Pt_Cnt];
|
|
Evas_Object *align_line[Align_Line_Cnt];
|
|
Evas_Object *info_text[Info_Text_Cnt];
|
|
Evas_Object *info_text_bg[Info_Text_Cnt];
|
|
Evas_Coord_Point move_delta;
|
|
double half_ctrl_size;
|
|
unsigned int type;
|
|
|
|
//Relative setting properties
|
|
struct {
|
|
float rel1_x, rel1_y;
|
|
float rel2_x, rel2_y;
|
|
} rel_info;
|
|
|
|
//Relative to information for live edit item
|
|
struct {
|
|
char *rel1_x_part, *rel1_y_part;
|
|
char *rel2_x_part, *rel2_y_part;
|
|
float rel1_x, rel1_y;
|
|
float rel2_x, rel2_y;
|
|
float align_x, align_y;
|
|
int min_w, min_h;
|
|
Evas_Object *ctxpopup;
|
|
} rel_to_info;
|
|
|
|
Evas_Object *keygrabber;
|
|
Eina_Array *auto_align_array;
|
|
Ctrl_Pt last_cp;
|
|
|
|
Evas_Object *fixed_w_check;
|
|
Evas_Object *fixed_h_check;
|
|
|
|
Eina_Bool on : 1;
|
|
Eina_Bool align_left : 1;
|
|
Eina_Bool align_right : 1;
|
|
Eina_Bool align_top : 1;
|
|
Eina_Bool align_bottom : 1;
|
|
Eina_Bool ctrl_pressed : 1;
|
|
} live_data;
|
|
|
|
typedef struct auto_align_data_s
|
|
{
|
|
char part_name[PART_NAME_MAX];
|
|
Evas_Coord_Point pt1;
|
|
Evas_Coord_Point pt2;
|
|
} auto_align_data;
|
|
|
|
typedef struct rel_to_data_s
|
|
{
|
|
char part_name[PART_NAME_MAX];
|
|
float rel_x, rel_y;
|
|
Evas_Coord_Point pt1, pt2;
|
|
live_data *ld;
|
|
} rel_to_data;
|
|
|
|
#define LIVEEDIT_ITEMS_NUM 6
|
|
|
|
static live_data *g_ld = NULL;
|
|
|
|
static const liveedit_item LIVEEDIT_ITEMS[] =
|
|
{
|
|
{"Rect", EDJE_PART_TYPE_RECTANGLE},
|
|
{"Text", EDJE_PART_TYPE_TEXT},
|
|
{"Image", EDJE_PART_TYPE_IMAGE},
|
|
{"Swallow", EDJE_PART_TYPE_SWALLOW},
|
|
{"Textblock", EDJE_PART_TYPE_TEXTBLOCK},
|
|
{"Spacer", EDJE_PART_TYPE_SPACER} //Please leave spacer at last
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* Internal method implementation */
|
|
/*****************************************************************************/
|
|
|
|
static void live_edit_update_internal(live_data *ld);
|
|
|
|
static void
|
|
update_line_attach_effect(live_data *ld, int align_line)
|
|
{
|
|
//Left
|
|
if ((align_line & ALIGN_LINE_LEFT))
|
|
{
|
|
if (!ld->align_left)
|
|
{
|
|
ld->align_left = EINA_TRUE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left],
|
|
"elm,state,show,highlight", "");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ld->align_left)
|
|
{
|
|
ld->align_left = EINA_FALSE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left],
|
|
"elm,state,hide,highlight", "");
|
|
}
|
|
}
|
|
//Right
|
|
if ((align_line & ALIGN_LINE_RIGHT))
|
|
{
|
|
if (!ld->align_right)
|
|
{
|
|
ld->align_right = EINA_TRUE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right],
|
|
"elm,state,show,highlight", "");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ld->align_right)
|
|
{
|
|
ld->align_right = EINA_FALSE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right],
|
|
"elm,state,hide,highlight", "");
|
|
}
|
|
}
|
|
//Top
|
|
if ((align_line & ALIGN_LINE_TOP))
|
|
{
|
|
if (!ld->align_top)
|
|
{
|
|
ld->align_top = EINA_TRUE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top],
|
|
"elm,state,show,highlight", "");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ld->align_top)
|
|
{
|
|
ld->align_top = EINA_FALSE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top],
|
|
"elm,state,hide,highlight", "");
|
|
}
|
|
}
|
|
//Bottom
|
|
if ((align_line & ALIGN_LINE_BOTTOM))
|
|
{
|
|
if (!ld->align_bottom)
|
|
{
|
|
ld->align_bottom = EINA_TRUE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom],
|
|
"elm,state,show,highlight", "");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ld->align_bottom)
|
|
{
|
|
ld->align_bottom = EINA_FALSE;
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom],
|
|
"elm,state,hide,highlight", "");
|
|
}
|
|
}
|
|
}
|
|
|
|
static Evas_Object *
|
|
view_scroller_get(live_data *ld)
|
|
{
|
|
//This is a trick! we got the actual view object from the live edit.
|
|
if (!ld->live_view) return NULL;
|
|
return elm_object_part_content_get(ld->live_view,
|
|
"elm.swallow.content");
|
|
}
|
|
|
|
static Evas_Object *
|
|
view_obj_get(live_data *ld)
|
|
{
|
|
//This is a trick! we got the actual view object from the live edit.
|
|
Evas_Object *o = view_scroller_get(ld);
|
|
if (!o) return NULL;
|
|
Evas_Object *o2 = elm_object_content_get(o);
|
|
if (!o2) return NULL;
|
|
return elm_object_part_content_get(o2, "elm.swallow.content");
|
|
}
|
|
|
|
static void
|
|
view_obj_member_add(live_data *ld, Evas_Object *obj)
|
|
{
|
|
//This is a trick! we got the actual view object from the live edit.
|
|
Evas_Object *scroller = view_scroller_get(ld);
|
|
if (!scroller) return;
|
|
|
|
evas_object_smart_member_add(obj, scroller);
|
|
|
|
Evas_Object *scroller_edje = elm_layout_edje_get(scroller);
|
|
Evas_Object *clipper =
|
|
(Evas_Object *)edje_object_part_object_get(scroller_edje, "clipper");
|
|
evas_object_clip_set(obj, clipper);
|
|
}
|
|
|
|
static void
|
|
view_scroll_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
live_data *ld = data;
|
|
live_edit_update_internal(ld);
|
|
}
|
|
|
|
static void
|
|
info_text_update(live_data *ld)
|
|
{
|
|
//Update Text
|
|
char buf[256];
|
|
|
|
Evas_Coord lx, ly, lw, lh;
|
|
evas_object_geometry_get(ld->live_view, &lx, &ly, &lw, &lh);
|
|
|
|
Enventor_Object *enventor = base_enventor_get();
|
|
|
|
Evas_Coord vw, vh;
|
|
enventor_object_live_view_size_get(enventor, &vw, &vh);
|
|
|
|
//reverse coordinates if mirror mode is enabled.
|
|
double ox = ld->rel_info.rel1_x;
|
|
double ox2 = ld->rel_info.rel2_x;
|
|
double ow = (ld->rel_info.rel1_x * (double) vw);
|
|
double ow2 = (ld->rel_info.rel2_x * (double) vw);
|
|
|
|
if (enventor_object_mirror_mode_get(enventor))
|
|
{
|
|
ox = 1 - ox;
|
|
ox2 = 1 - ox2;
|
|
ow = vw - ow;
|
|
ow2 = vw - ow2;
|
|
}
|
|
|
|
//Rel1
|
|
snprintf(buf, sizeof(buf), "%.2f %.2f (%d, %d)",
|
|
ox, ld->rel_info.rel1_y,
|
|
(int) round(ow),
|
|
(int) round(ld->rel_info.rel1_y * (double) vh));
|
|
evas_object_text_text_set(ld->info_text[Info_Text_Rel1], buf);
|
|
|
|
//Rel2
|
|
snprintf(buf, sizeof(buf), "%.2f %.2f (%d, %d)",
|
|
ox2, ld->rel_info.rel2_y,
|
|
(int) round(ow2),
|
|
(int) round(ld->rel_info.rel2_y * (double) vh));
|
|
evas_object_text_text_set(ld->info_text[Info_Text_Rel2], buf);
|
|
|
|
//Size
|
|
vw = (Evas_Coord) round(((double) vw) *
|
|
(ld->rel_info.rel2_x - ld->rel_info.rel1_x));
|
|
vh = (Evas_Coord) round(((double) vh) *
|
|
(ld->rel_info.rel2_y - ld->rel_info.rel1_y));
|
|
snprintf(buf, sizeof(buf), "%d X %d", vw, vh);
|
|
evas_object_text_text_set(ld->info_text[Info_Text_Size], buf);
|
|
|
|
//Update Position
|
|
Evas_Coord x, y, w, h;
|
|
Evas_Coord rx, ry, rw, rh;
|
|
|
|
//Rel1
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], &rx, &ry, &rw, &rh);
|
|
evas_object_geometry_get(ld->info_text[Info_Text_Rel1], NULL, NULL, &w, &h);
|
|
x = (rx + rw);
|
|
y = ry - h;
|
|
if ((x + w) > (lx + lw)) x = (rx - w);
|
|
if (y < ly) y = (ry + rh);
|
|
evas_object_move(ld->info_text[Info_Text_Rel1], x, y);
|
|
|
|
//Rel1 BG
|
|
evas_object_move(ld->info_text_bg[Info_Text_Rel1], x - 2, y);
|
|
evas_object_resize(ld->info_text_bg[Info_Text_Rel1], w + 4, h);
|
|
|
|
//Rel2
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], &rx, &ry, &rw, &rh);
|
|
evas_object_geometry_get(ld->info_text[Info_Text_Rel2], NULL, NULL, &w, &h);
|
|
x = (rx - w);
|
|
y = (ry + rh);
|
|
if (x < lx) x = (rx + rw);
|
|
if ((y + h) > (ly + lh)) y = (ry - h);
|
|
evas_object_move(ld->info_text[Info_Text_Rel2], x, y);
|
|
|
|
//rel2 BG
|
|
evas_object_move(ld->info_text_bg[Info_Text_Rel2], x - 2, y);
|
|
evas_object_resize(ld->info_text_bg[Info_Text_Rel2], w + 4, h);
|
|
|
|
//Size
|
|
Evas_Coord layout_x, layout_y, layout_w, layout_h;
|
|
evas_object_geometry_get(ld->layout, &layout_x, &layout_y, &layout_w,
|
|
&layout_h);
|
|
evas_object_geometry_get(ld->info_text[Info_Text_Size], NULL, NULL, &w, &h);
|
|
x = (layout_x + (layout_w/2)) - (w/2);
|
|
y = (layout_y + (layout_h/2)) - (h/2);
|
|
if (x < lx) x = lx;
|
|
if (y < ly) y = ly;
|
|
if ((x + w) > (lx + lw)) x = ((lx + lw) - w);
|
|
if ((y + h) > (ly + lh)) y = ((ly + lh) - h);
|
|
evas_object_move(ld->info_text[Info_Text_Size], x, y);
|
|
|
|
//Size BG
|
|
evas_object_move(ld->info_text_bg[Info_Text_Size], x - 2, y);
|
|
evas_object_resize(ld->info_text_bg[Info_Text_Size], w + 4, h);
|
|
}
|
|
|
|
static void
|
|
live_edit_symbol_set(live_data *ld)
|
|
{
|
|
char buf[PATH_MAX];
|
|
snprintf(buf, sizeof(buf), "%s_bg", LIVEEDIT_ITEMS[ld->type].name);
|
|
Evas_Object *layout_symbol = elm_layout_add(ld->layout);
|
|
elm_layout_file_set(layout_symbol, EDJE_PATH, buf);
|
|
elm_object_scale_set(layout_symbol,
|
|
(1/enventor_object_base_scale_get(base_enventor_get())) *
|
|
enventor_object_live_view_scale_get(base_enventor_get()));
|
|
elm_object_part_content_set(ld->layout, "elm.swallow.symbol", layout_symbol);
|
|
}
|
|
|
|
static void
|
|
calc_relative_info(live_data *ld)
|
|
{
|
|
//For Current Input Live Edit Item size
|
|
Evas_Coord lx, ly, lw, lh;
|
|
evas_object_geometry_get(ld->layout, &lx, &ly, &lw, &lh);
|
|
|
|
//Check fixed properties
|
|
Eina_Bool fixed_w = elm_check_state_get(ld->fixed_w_check);
|
|
Eina_Bool fixed_h = elm_check_state_get(ld->fixed_h_check);
|
|
|
|
//For real min size of Live Edit Item
|
|
Evas_Coord vw, vh;
|
|
enventor_object_live_view_size_get(base_enventor_get(), &vw, &vh);
|
|
|
|
//Calculate real min size of Live Edit Item base on current relative
|
|
double base_scale = enventor_object_base_scale_get(base_enventor_get());
|
|
Evas_Coord min_w =
|
|
(Evas_Coord) round(((double) vw) *
|
|
(ld->rel_info.rel2_x - ld->rel_info.rel1_x) *
|
|
base_scale);
|
|
Evas_Coord min_h =
|
|
(Evas_Coord) round(((double) vh) *
|
|
(ld->rel_info.rel2_y - ld->rel_info.rel1_y) *
|
|
base_scale);
|
|
|
|
//Set fixed properties of width for current Live Edit Item
|
|
if (fixed_w)
|
|
{
|
|
if (ld->rel_to_info.rel1_x_part)
|
|
{
|
|
ld->rel_to_info.align_x = 0.0;
|
|
ld->rel_to_info.rel2_x = ld->rel_to_info.rel1_x;
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
ld->rel_to_info.rel2_x_part = strndup(ld->rel_to_info.rel1_x_part,
|
|
strlen(ld->rel_to_info.rel1_x_part));
|
|
}
|
|
else if (ld->rel_to_info.rel2_x_part)
|
|
{
|
|
ld->rel_to_info.align_x = 1.0;
|
|
ld->rel_to_info.rel1_x = ld->rel_to_info.rel2_x;
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
ld->rel_to_info.rel1_x_part = strndup(ld->rel_to_info.rel2_x_part,
|
|
strlen(ld->rel_to_info.rel2_x_part));
|
|
}
|
|
else
|
|
{
|
|
float center = (ld->rel_info.rel1_x + ld->rel_info.rel2_x) / 2;
|
|
ld->rel_to_info.rel1_x = center;
|
|
ld->rel_to_info.rel2_x = center;
|
|
}
|
|
ld->rel_to_info.min_w = min_w;
|
|
}
|
|
else
|
|
{
|
|
//If there is no relative setting, set base relative
|
|
if (!ld->rel_to_info.rel1_x_part)
|
|
ld->rel_to_info.rel1_x = ld->rel_info.rel1_x;
|
|
if (!ld->rel_to_info.rel2_x_part)
|
|
ld->rel_to_info.rel2_x = ld->rel_info.rel2_x;
|
|
}
|
|
|
|
//Set fixed properties of height for current Live Edit Item
|
|
if (fixed_h)
|
|
{
|
|
if (ld->rel_to_info.rel1_y_part)
|
|
{
|
|
ld->rel_to_info.align_y = 0.0;
|
|
ld->rel_to_info.rel2_y = ld->rel_to_info.rel1_y;
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
ld->rel_to_info.rel2_y_part = strndup(ld->rel_to_info.rel1_y_part,
|
|
strlen(ld->rel_to_info.rel1_y_part));
|
|
}
|
|
else if (ld->rel_to_info.rel2_y_part)
|
|
{
|
|
ld->rel_to_info.align_y = 1.0;
|
|
ld->rel_to_info.rel1_y = ld->rel_to_info.rel2_y;
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
ld->rel_to_info.rel1_y_part = strndup(ld->rel_to_info.rel2_y_part,
|
|
strlen(ld->rel_to_info.rel2_y_part));
|
|
}
|
|
else
|
|
{
|
|
float center = (ld->rel_info.rel1_y + ld->rel_info.rel2_y) / 2;
|
|
ld->rel_to_info.rel1_y = center;
|
|
ld->rel_to_info.rel2_y = center;
|
|
}
|
|
ld->rel_to_info.min_h = min_h;
|
|
}
|
|
else
|
|
{
|
|
//If there is no relative setting, set base relative
|
|
if (!ld->rel_to_info.rel1_y_part)
|
|
ld->rel_to_info.rel1_y = ld->rel_info.rel1_y;
|
|
if (!ld->rel_to_info.rel2_y_part)
|
|
ld->rel_to_info.rel2_y = ld->rel_info.rel2_y;
|
|
}
|
|
}
|
|
|
|
static void
|
|
live_edit_insert(live_data *ld)
|
|
{
|
|
int type = LIVEEDIT_ITEMS[ld->type].type;
|
|
|
|
calc_relative_info(ld);
|
|
|
|
Enventor_Item *it = file_mgr_focused_item_get();
|
|
|
|
enventor_item_template_part_insert(file_mgr_focused_item_get(),
|
|
type,
|
|
ENVENTOR_TEMPLATE_INSERT_LIVE_EDIT,
|
|
elm_check_state_get(ld->fixed_w_check),
|
|
elm_check_state_get(ld->fixed_h_check),
|
|
ld->rel_to_info.rel1_x_part,
|
|
ld->rel_to_info.rel1_y_part,
|
|
ld->rel_to_info.rel2_x_part,
|
|
ld->rel_to_info.rel2_y_part,
|
|
ld->rel_to_info.align_x,
|
|
ld->rel_to_info.align_y,
|
|
ld->rel_to_info.min_w,
|
|
ld->rel_to_info.min_h,
|
|
ld->rel_to_info.rel1_x,
|
|
ld->rel_to_info.rel1_y,
|
|
ld->rel_to_info.rel2_x,
|
|
ld->rel_to_info.rel2_y,
|
|
NULL, 0);
|
|
enventor_item_file_save(it, NULL);
|
|
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
}
|
|
|
|
static void
|
|
keygrabber_key_down_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Key_Down *ev = event_info;
|
|
|
|
if (!strcmp(ev->key, "Control_L"))
|
|
ld->ctrl_pressed = EINA_TRUE;
|
|
|
|
if (!strcmp(ev->key, "Return")) live_edit_insert(ld);
|
|
else if (strcmp(ev->key, "Delete") &&
|
|
strcmp(ev->key, "BackSpace")) return;
|
|
|
|
live_edit_cancel(EINA_TRUE);
|
|
}
|
|
|
|
static void
|
|
keygrabber_key_up_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Key_Up *ev = event_info;
|
|
|
|
if (!strcmp(ev->key, "Control_L"))
|
|
ld->ctrl_pressed = EINA_FALSE;
|
|
}
|
|
|
|
Evas_Coord_Point
|
|
calc_ctrl_pt_auto_align_pos(live_data *ld, int cursor_x, int cursor_y,
|
|
int align_in, int *align_out)
|
|
{
|
|
int res_x, res_y;
|
|
unsigned int nx, ny;
|
|
Evas_Coord_Point pt;
|
|
|
|
// if control key is pressed, auto align is not applied
|
|
if (ld->ctrl_pressed)
|
|
{
|
|
pt.x = cursor_x;
|
|
pt.y = cursor_y;
|
|
return pt;
|
|
}
|
|
res_x = res_y = -1;
|
|
nx = ny = LIVE_EDIT_MAX_DIST;
|
|
unsigned int dist = LIVE_EDIT_AUTO_ALIGN_DIST;
|
|
|
|
// This loop finds the closest position of part to control point
|
|
// And then return the position
|
|
unsigned int i;
|
|
auto_align_data *al_pos;
|
|
Eina_Array_Iterator iter;
|
|
EINA_ARRAY_ITER_NEXT(ld->auto_align_array, i, al_pos, iter)
|
|
{
|
|
unsigned int dx, dy;
|
|
|
|
dx = abs(al_pos->pt1.x - cursor_x);
|
|
dy = abs(al_pos->pt1.y - cursor_y);
|
|
|
|
if ((dx < dist) && (dx < nx) && (cursor_y >= al_pos->pt1.y) &&
|
|
(cursor_y <= al_pos->pt2.y))
|
|
{
|
|
nx = dx;
|
|
res_x = al_pos->pt1.x;
|
|
}
|
|
if ((dy < dist) && (dy < ny) && (cursor_x >= al_pos->pt1.x) &&
|
|
(cursor_x <= al_pos->pt2.x))
|
|
{
|
|
ny = dy;
|
|
res_y = al_pos->pt1.y;
|
|
}
|
|
|
|
dx = abs(al_pos->pt2.x - cursor_x);
|
|
dy = abs(al_pos->pt2.y - cursor_y);
|
|
|
|
if ((dx < dist) && (dx < nx) && (cursor_y >= al_pos->pt1.y) &&
|
|
(cursor_y <= al_pos->pt2.y))
|
|
{
|
|
nx = dx;
|
|
res_x = al_pos->pt2.x;
|
|
}
|
|
if ((dy < dist) && (dy < ny) && (cursor_x >= al_pos->pt1.x) &&
|
|
(cursor_x <= al_pos->pt2.x))
|
|
{
|
|
ny = dy;
|
|
res_y = al_pos->pt2.y;
|
|
}
|
|
}
|
|
|
|
|
|
if (res_x != -1)
|
|
{
|
|
pt.x = res_x;
|
|
if (align_out)
|
|
{
|
|
if (align_in & ALIGN_LINE_LEFT)
|
|
*align_out |= ALIGN_LINE_LEFT;
|
|
else if (align_in & ALIGN_LINE_RIGHT)
|
|
*align_out |= ALIGN_LINE_RIGHT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pt.x = cursor_x;
|
|
}
|
|
|
|
if (res_y != -1)
|
|
{
|
|
pt.y = res_y;
|
|
if (align_out)
|
|
{
|
|
if (align_in & ALIGN_LINE_TOP)
|
|
*align_out |= ALIGN_LINE_TOP;
|
|
else if (align_in & ALIGN_LINE_BOTTOM)
|
|
*align_out |= ALIGN_LINE_BOTTOM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pt.y = cursor_y;
|
|
}
|
|
|
|
return pt;
|
|
}
|
|
|
|
|
|
static void
|
|
ctrl_pt_update(live_data *ld)
|
|
{
|
|
//Init Control Point Positions
|
|
Evas_Coord dx, dy, dw, dh;
|
|
evas_object_geometry_get(ld->layout, &dx, &dy, &dw, &dh);
|
|
|
|
double x = dx;
|
|
double y = dy;
|
|
double w = dw;
|
|
double h = dh;
|
|
|
|
int half_ctrl_size = ld->half_ctrl_size;
|
|
|
|
//Rel1
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Rel1],
|
|
round((x - half_ctrl_size)), round((y - half_ctrl_size)));
|
|
|
|
//Rel2
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Rel2],
|
|
round((x + w) - half_ctrl_size),
|
|
round((y + h) - half_ctrl_size));
|
|
|
|
//Rel3
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Rel3],
|
|
round((x + w) - half_ctrl_size),
|
|
round(y - half_ctrl_size));
|
|
|
|
//Rel4
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Rel4],
|
|
round(x - half_ctrl_size),
|
|
round((y + h) - half_ctrl_size));
|
|
|
|
//Top
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Top],
|
|
round((x + (w/2)) - half_ctrl_size),
|
|
round(y - half_ctrl_size));
|
|
|
|
//Bottom
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Bottom],
|
|
round((x + (w/2)) - half_ctrl_size),
|
|
round((y + h) - half_ctrl_size));
|
|
|
|
//Left
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Left],
|
|
round(x - half_ctrl_size),
|
|
round((y + (h/2)) - half_ctrl_size));
|
|
|
|
//Right
|
|
evas_object_move(ld->ctrl_pt[Ctrl_Pt_Right],
|
|
round((x + w) - half_ctrl_size),
|
|
round((y + (h/2)) - half_ctrl_size));
|
|
}
|
|
|
|
static void
|
|
cp_top_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel2_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], NULL, &rel2_y,
|
|
NULL, NULL);
|
|
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt = calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
ALIGN_LINE_TOP,
|
|
&align_line);
|
|
y = pt.y;
|
|
|
|
if (vy > y) y = vy;
|
|
if ((y - ld->half_ctrl_size) > rel2_y) y = (rel2_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel1_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top], "elm,state,show", "");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel1_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
ld->rel_to_info.rel1_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_bottom_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel1_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], NULL, &rel1_y,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt = calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
ALIGN_LINE_BOTTOM,
|
|
&align_line);
|
|
y = pt.y;
|
|
|
|
|
|
if (y > (vy + vh)) y = (vy + vh);
|
|
if (rel1_y > (y + ld->half_ctrl_size)) y = (rel1_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel2_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom], "elm,state,show",
|
|
"");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel2_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
ld->rel_to_info.rel2_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
align_line_update(live_data *ld)
|
|
{
|
|
Evas_Coord lx, ly, lw, lh;
|
|
Evas_Object *view_obj = view_obj_get(ld);
|
|
evas_object_geometry_get(view_obj, &lx, &ly, &lw, &lh);
|
|
int x, y;
|
|
|
|
//Top
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Top], NULL, &y, NULL, NULL);
|
|
y = round(((double) y) + ld->half_ctrl_size);
|
|
evas_object_move(ld->align_line[Align_Line_Top], lx, y);
|
|
evas_object_resize(ld->align_line[Align_Line_Top], lw, ELM_SCALE_SIZE(1));
|
|
|
|
//Bottom
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Bottom], NULL, &y, NULL, NULL);
|
|
y = round(((double) y) + ld->half_ctrl_size);
|
|
evas_object_move(ld->align_line[Align_Line_Bottom], lx, y);
|
|
evas_object_resize(ld->align_line[Align_Line_Bottom], lw, ELM_SCALE_SIZE(1));
|
|
|
|
//Left
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Left], &x, NULL, NULL, NULL);
|
|
x = round(((double) x) + ld->half_ctrl_size);
|
|
evas_object_move(ld->align_line[Align_Line_Left], x, ly);
|
|
evas_object_resize(ld->align_line[Align_Line_Left], ELM_SCALE_SIZE(1), lh);
|
|
|
|
//Righit
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Right], &x, NULL, NULL, NULL);
|
|
x = round(((double) x) + ld->half_ctrl_size);
|
|
evas_object_move(ld->align_line[Align_Line_Right], x, ly);
|
|
evas_object_resize(ld->align_line[Align_Line_Right], ELM_SCALE_SIZE(1), lh);
|
|
}
|
|
|
|
static void
|
|
keygrabber_direction_key_down_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Key_Down *ev = event_info;
|
|
|
|
Evas_Coord x, y, w, h;
|
|
evas_object_geometry_get(ld->layout, &x, &y, &w, &h);
|
|
|
|
Evas_Coord vx, vy, vw, vh;
|
|
Evas_Object *view = view_obj_get(ld);
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
//Move the live item by 1 pixel to set detailed
|
|
//Move up
|
|
if (!strcmp(ev->key, "Up"))
|
|
y -= 1;
|
|
//Move down
|
|
else if (!strcmp(ev->key, "Down"))
|
|
y += 1;
|
|
//Move left
|
|
else if (!strcmp(ev->key, "Left"))
|
|
x -= 1;
|
|
//Move Right
|
|
else if (!strcmp(ev->key, "Right"))
|
|
x += 1;
|
|
|
|
//Check live view boundary
|
|
if (vx > x) x = vx;
|
|
if ((x + w) > (vx + vw)) x = (vx + vw) - w;
|
|
if (vy > y) y = vy;
|
|
if ((y + h) > (vy + vh)) y -= ((y + h) - (vy + vh));
|
|
|
|
evas_object_move(ld->layout, x, y);
|
|
|
|
//Calculate the relative value of live view item to 4 places of decimals
|
|
double orig_rel1_x = ld->rel_info.rel1_x;
|
|
double orig_rel1_y = ld->rel_info.rel1_y;
|
|
ld->rel_info.rel1_x = (double) (x - vx) / vw;
|
|
ld->rel_info.rel1_y = (double) (y - vy) / vh;
|
|
ld->rel_info.rel2_x += ld->rel_info.rel1_x - orig_rel1_x;
|
|
ld->rel_info.rel2_y += ld->rel_info.rel1_y - orig_rel1_y;
|
|
|
|
//Round off in the end to reduce round-off error.
|
|
ld->rel_info.rel1_x = ROUNDING(ld->rel_info.rel1_x, 4);
|
|
ld->rel_info.rel1_y = ROUNDING(ld->rel_info.rel1_y, 4);
|
|
ld->rel_info.rel2_x = ROUNDING(ld->rel_info.rel2_x, 4);
|
|
ld->rel_info.rel2_y = ROUNDING(ld->rel_info.rel2_y, 4);
|
|
|
|
ctrl_pt_update(ld);
|
|
info_text_update(ld);
|
|
}
|
|
|
|
static void
|
|
cp_rel1_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel2_x, rel2_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], &rel2_x, &rel2_y,
|
|
NULL, NULL);
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt =
|
|
calc_ctrl_pt_auto_align_pos(ld, x, y, (ALIGN_LINE_TOP | ALIGN_LINE_LEFT),
|
|
&align_line);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
|
|
if (vx > x) x = vx;
|
|
if (vy > y) y = vy;
|
|
if ((x - ld->half_ctrl_size) > rel2_x) x = (rel2_x + ld->half_ctrl_size);
|
|
if ((y - ld->half_ctrl_size) > rel2_y) y = (rel2_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel1_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
ld->rel_info.rel1_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top], "elm,state,show", "");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel1_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
ld->rel_to_info.rel1_x_part = NULL;
|
|
}
|
|
|
|
if (ld->rel_to_info.rel1_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
ld->rel_to_info.rel1_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_rel2_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel1_x, rel1_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], &rel1_x, &rel1_y,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt =
|
|
calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
(ALIGN_LINE_RIGHT | ALIGN_LINE_BOTTOM),
|
|
&align_line);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
|
|
if (x > (vx + vw)) x = (vx + vw);
|
|
if (y > (vy + vh)) y = (vy + vh);
|
|
if (rel1_x > (x + ld->half_ctrl_size)) x = (rel1_x + ld->half_ctrl_size);
|
|
if (rel1_y > (y + ld->half_ctrl_size)) y = (rel1_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel2_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
ld->rel_info.rel2_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom], "elm,state,show",
|
|
"");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel2_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
ld->rel_to_info.rel2_x_part = NULL;
|
|
}
|
|
|
|
if (ld->rel_to_info.rel2_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
ld->rel_to_info.rel2_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_rel3_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel1_x;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], &rel1_x, NULL,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt =
|
|
calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
(ALIGN_LINE_TOP | ALIGN_LINE_RIGHT),
|
|
&align_line);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
|
|
if (x > (vx + vw)) x = (vx + vw);
|
|
if (rel1_x > (x + ld->half_ctrl_size)) x = (rel1_x - ld->half_ctrl_size);
|
|
|
|
Evas_Coord rel2_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], NULL, &rel2_y,
|
|
NULL, NULL);
|
|
if (vy > y) y = vy;
|
|
if ((y - ld->half_ctrl_size) > rel2_y) y = (rel2_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel2_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
ld->rel_info.rel1_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top], "elm,state,show", "");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel2_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
ld->rel_to_info.rel2_x_part = NULL;
|
|
}
|
|
|
|
if (ld->rel_to_info.rel1_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
ld->rel_to_info.rel1_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_rel4_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel2_x;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], &rel2_x, NULL,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt =
|
|
calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
(ALIGN_LINE_LEFT | ALIGN_LINE_BOTTOM),
|
|
&align_line);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
|
|
if (vx > x) x = vx;
|
|
if ((x - ld->half_ctrl_size) > rel2_x) x = (rel2_x + ld->half_ctrl_size);
|
|
|
|
Evas_Coord rel1_y;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], NULL, &rel1_y,
|
|
NULL, NULL);
|
|
if (y > (vy + vh)) y = (vy + vh);
|
|
if (rel1_y > (y + ld->half_ctrl_size)) y = (rel1_y + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel1_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
ld->rel_info.rel2_y = ROUNDING(((double) (y - vy) / (double) vh), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom], "elm,state,show",
|
|
"");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel1_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
ld->rel_to_info.rel1_x_part = NULL;
|
|
}
|
|
|
|
if (ld->rel_to_info.rel2_y_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
ld->rel_to_info.rel2_y_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_left_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel2_x;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel2], &rel2_x, NULL,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt = calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
ALIGN_LINE_LEFT,
|
|
&align_line);
|
|
x = pt.x;
|
|
|
|
if (vx > x) x = vx;
|
|
if ((x - ld->half_ctrl_size) > rel2_x) x = (rel2_x + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel1_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left], "elm,state,show",
|
|
"");
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel1_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
ld->rel_to_info.rel1_x_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_right_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED,
|
|
void *event_info)
|
|
{
|
|
live_data *ld = data;
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
|
|
Evas_Coord x = ev->cur.canvas.x;
|
|
Evas_Coord y = ev->cur.canvas.y;
|
|
|
|
Evas_Object *view = view_obj_get(ld);
|
|
Evas_Coord vx, vy, vw, vh;
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
Evas_Coord rel1_x;
|
|
evas_object_geometry_get(ld->ctrl_pt[Ctrl_Pt_Rel1], &rel1_x, NULL,
|
|
NULL, NULL);
|
|
|
|
int align_line = 0;
|
|
Evas_Coord_Point pt = calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
ALIGN_LINE_RIGHT,
|
|
&align_line);
|
|
x = pt.x;
|
|
|
|
|
|
if (x > (vx + vw)) x = (vx + vw);
|
|
if (rel1_x > (x + ld->half_ctrl_size)) x = (rel1_x + ld->half_ctrl_size);
|
|
|
|
ld->rel_info.rel2_x = ROUNDING(((double) (x - vx) / (double) vw), 2);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right], "elm,state,show",
|
|
"");
|
|
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
//cancel relative to
|
|
if (ld->rel_to_info.rel2_x_part)
|
|
{
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
ld->rel_to_info.rel2_x_part = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
//Dispatch to actual mouse move call
|
|
Ctrl_Pt cp = (Ctrl_Pt) evas_object_data_get(obj, "index");
|
|
if (cp == Ctrl_Pt_Cnt) return; //not to use Ctrl_Pt_Cnt as index.
|
|
|
|
//Show Control Point
|
|
live_data *ld = data;
|
|
elm_object_signal_emit(ld->ctrl_pt[cp], "elm,state,show", "");
|
|
|
|
switch (cp)
|
|
{
|
|
case Ctrl_Pt_Rel1:
|
|
cp_rel1_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Rel2:
|
|
cp_rel2_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Rel3:
|
|
cp_rel3_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Rel4:
|
|
cp_rel4_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Top:
|
|
cp_top_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Bottom:
|
|
cp_bottom_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Left:
|
|
cp_left_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
case Ctrl_Pt_Right:
|
|
cp_right_mouse_move_cb(data, e, obj, event_info);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//Memorize last selected control point for setting relative_to
|
|
ld->last_cp = cp;
|
|
live_edit_update_internal(ld);
|
|
}
|
|
|
|
static void
|
|
align_lines_hide(live_data *ld)
|
|
{
|
|
int i;
|
|
for (i = 0; i < Align_Line_Cnt; i++)
|
|
elm_object_signal_emit(ld->align_line[i], "elm,state,hide", "");
|
|
}
|
|
|
|
static void
|
|
rel_to_btn_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
Evas_Object *ctxpopup = data;
|
|
Evas_Object *layout = elm_object_content_get(ctxpopup);
|
|
if (!layout) return;
|
|
|
|
//Rel X
|
|
Evas_Object *list_x = elm_object_part_content_get(layout, "elm.swallow.x");
|
|
if (list_x)
|
|
{
|
|
Elm_Object_Item *it = elm_list_selected_item_get(list_x);
|
|
if (it)
|
|
{
|
|
rel_to_data *rel_data = elm_object_item_data_get(it);
|
|
if (rel_data)
|
|
{
|
|
live_data *ld = rel_data->ld;
|
|
//Case 1: Set relative properties of left side
|
|
if ((ld->last_cp == Ctrl_Pt_Rel1) ||
|
|
(ld->last_cp == Ctrl_Pt_Rel4) ||
|
|
(ld->last_cp == Ctrl_Pt_Left))
|
|
{
|
|
free(ld->rel_to_info.rel1_x_part);
|
|
ld->rel_to_info.rel1_x_part = strndup(rel_data->part_name,
|
|
strlen(rel_data->part_name));
|
|
ld->rel_to_info.rel1_x = rel_data->rel_x;
|
|
}
|
|
//Case 2: Set relative properties of right side
|
|
else if ((ld->last_cp == Ctrl_Pt_Rel2) ||
|
|
(ld->last_cp == Ctrl_Pt_Rel3) ||
|
|
(ld->last_cp == Ctrl_Pt_Right))
|
|
{
|
|
free(ld->rel_to_info.rel2_x_part);
|
|
ld->rel_to_info.rel2_x_part = strndup(rel_data->part_name,
|
|
strlen(rel_data->part_name));
|
|
ld->rel_to_info.rel2_x = rel_data->rel_x;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Rel Y
|
|
Evas_Object *list_y = elm_object_part_content_get(layout, "elm.swallow.y");
|
|
if (list_y)
|
|
{
|
|
Elm_Object_Item *it = elm_list_selected_item_get(list_y);
|
|
if (it)
|
|
{
|
|
rel_to_data *rel_data = elm_object_item_data_get(it);
|
|
if (rel_data)
|
|
{
|
|
live_data *ld = rel_data->ld;
|
|
//Case 1: Set relative properties of top side
|
|
if ((ld->last_cp == Ctrl_Pt_Rel1) ||
|
|
(ld->last_cp == Ctrl_Pt_Rel3) ||
|
|
(ld->last_cp == Ctrl_Pt_Top))
|
|
{
|
|
free(ld->rel_to_info.rel1_y_part);
|
|
ld->rel_to_info.rel1_y_part = strndup(rel_data->part_name,
|
|
strlen(rel_data->part_name));
|
|
ld->rel_to_info.rel1_y = rel_data->rel_y;
|
|
}
|
|
//Case 2: Set relative properties of bottom side
|
|
else if ((ld->last_cp == Ctrl_Pt_Rel2) ||
|
|
(ld->last_cp == Ctrl_Pt_Rel4) ||
|
|
(ld->last_cp == Ctrl_Pt_Bottom))
|
|
{
|
|
free(ld->rel_to_info.rel2_y_part);
|
|
ld->rel_to_info.rel2_y_part = strndup(rel_data->part_name,
|
|
strlen(rel_data->part_name));
|
|
ld->rel_to_info.rel2_y = rel_data->rel_y;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
elm_ctxpopup_dismiss(ctxpopup);
|
|
}
|
|
|
|
static void
|
|
list_it_del_cb(void *data, Elm_Object_Item *it EINA_UNUSED,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
rel_to_data *rel_data = data;
|
|
free(rel_data);
|
|
}
|
|
|
|
static void
|
|
ctxpopup_dismissed_cb(void *data, Evas_Object *obj,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
live_data *ld = data;
|
|
evas_object_del(obj);
|
|
ld->rel_to_info.ctxpopup = NULL;
|
|
}
|
|
|
|
static void
|
|
make_rel_data(Evas_Object *list, live_data *ld,
|
|
float rel_x, float rel_y,
|
|
auto_align_data *al_pos)
|
|
{
|
|
rel_to_data *rel_data = calloc(1, sizeof(rel_to_data));
|
|
strncpy(rel_data->part_name, al_pos->part_name, strlen(al_pos->part_name));
|
|
rel_data->rel_x = rel_x;
|
|
rel_data->rel_y = rel_y;
|
|
rel_data->pt1.x = al_pos->pt1.x;
|
|
rel_data->pt1.y = al_pos->pt1.y;
|
|
rel_data->pt2.x = al_pos->pt2.x;
|
|
rel_data->pt2.y = al_pos->pt2.y;
|
|
rel_data->ld = ld;
|
|
|
|
Elm_Object_Item *it = elm_list_item_append(list, al_pos->part_name, NULL,
|
|
NULL, NULL, rel_data);
|
|
elm_object_item_del_cb_set(it, list_it_del_cb);
|
|
}
|
|
|
|
static void
|
|
show_relative_to_list(live_data *ld, int x, int y, Ctrl_Pt cp)
|
|
{
|
|
if (ld->rel_to_info.ctxpopup) return;
|
|
|
|
unsigned int i;
|
|
Eina_Array_Iterator iter;
|
|
auto_align_data *al_pos;
|
|
Evas_Coord_Point cur_ctrl_pt = calc_ctrl_pt_auto_align_pos(ld, x, y,
|
|
0, NULL);
|
|
//Ctxpopup
|
|
Evas_Object *ctxpopup = elm_ctxpopup_add(base_layout_get());
|
|
elm_object_style_set(ctxpopup, "enventor");
|
|
//FIXME: because the focus highlighting is floated after ctxpopup is
|
|
//dismissed, i disable the focus here
|
|
elm_object_tree_focus_allow_set(ctxpopup, EINA_FALSE);
|
|
|
|
//Layout
|
|
Evas_Object *layout = elm_layout_add(ctxpopup);
|
|
elm_layout_file_set(layout, EDJE_PATH, "rel_to_layout");
|
|
elm_object_content_set(ctxpopup, layout);
|
|
|
|
//Ok Button
|
|
Evas_Object *ok_btn= elm_button_add(layout);
|
|
evas_object_smart_callback_add(ok_btn, "clicked", rel_to_btn_clicked_cb,
|
|
ctxpopup);
|
|
elm_object_text_set(ok_btn, "Ok");
|
|
elm_object_part_content_set(layout, "elm.swallow.ok_btn", ok_btn);
|
|
|
|
Elm_Object_Item *it;
|
|
|
|
//List for relative X
|
|
Evas_Object *list_x = elm_list_add(layout);
|
|
elm_list_mode_set(list_x, ELM_LIST_EXPAND);
|
|
evas_object_size_hint_max_set(list_x, ELM_SCALE_SIZE(115), ELM_SCALE_SIZE(200));
|
|
it = elm_list_item_append(list_x, "(none)", NULL, NULL, NULL, NULL);
|
|
elm_list_item_selected_set(it, EINA_TRUE);
|
|
elm_object_part_content_set(layout, "elm.swallow.x", list_x);
|
|
|
|
//List for relative Y
|
|
Evas_Object *list_y = elm_list_add(layout);
|
|
elm_list_mode_set(list_y, ELM_LIST_EXPAND);
|
|
evas_object_size_hint_max_set(list_y, ELM_SCALE_SIZE(115), ELM_SCALE_SIZE(200));
|
|
it = elm_list_item_append(list_y, "(none)", NULL, NULL, NULL, NULL);
|
|
elm_list_item_selected_set(it, EINA_TRUE);
|
|
elm_object_part_content_set(layout, "elm.swallow.y", list_y);
|
|
|
|
Eina_Bool is_rel_to_x = EINA_FALSE;
|
|
Eina_Bool is_rel_to_y = EINA_FALSE;
|
|
|
|
//Find relative_to part corresponding to the current control point
|
|
EINA_ARRAY_ITER_NEXT(ld->auto_align_array, i, al_pos, iter)
|
|
{
|
|
//Case 1: Find relative_to x
|
|
if (((cp != Ctrl_Pt_Top) && (cp != Ctrl_Pt_Bottom)) &&
|
|
(cur_ctrl_pt.y >= al_pos->pt1.y) && (cur_ctrl_pt.y <= al_pos->pt2.y))
|
|
{
|
|
//Control point is located left side of existing part
|
|
if (al_pos->pt1.x == cur_ctrl_pt.x)
|
|
{
|
|
is_rel_to_x = EINA_TRUE;
|
|
make_rel_data(list_x, ld, 0.0, 0.0, al_pos);
|
|
}
|
|
//Control point is located right side of existing part
|
|
else if (al_pos->pt2.x == cur_ctrl_pt.x)
|
|
{
|
|
is_rel_to_x = EINA_TRUE;
|
|
make_rel_data(list_x, ld, 1.0, 0.0, al_pos);
|
|
}
|
|
}
|
|
//Case 2: Find relative_to y
|
|
if (((cp != Ctrl_Pt_Left) && (cp != Ctrl_Pt_Right)) &&
|
|
(cur_ctrl_pt.x >= al_pos->pt1.x) && (cur_ctrl_pt.x <= al_pos->pt2.x))
|
|
{
|
|
//Control point is located top side of existing part
|
|
if (al_pos->pt1.y == cur_ctrl_pt.y)
|
|
{
|
|
is_rel_to_y = EINA_TRUE;
|
|
make_rel_data(list_y, ld, 0.0, 0.0, al_pos);
|
|
}
|
|
//Control point is located bottom side of existing part
|
|
else if (al_pos->pt2.y == cur_ctrl_pt.y)
|
|
{
|
|
is_rel_to_y = EINA_TRUE;
|
|
make_rel_data(list_y, ld, 0.0, 1.0, al_pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_rel_to_x || is_rel_to_y)
|
|
{
|
|
elm_list_go(list_x);
|
|
elm_list_go(list_y);
|
|
|
|
//Control Layout
|
|
if (is_rel_to_x && !is_rel_to_y)
|
|
elm_object_signal_emit(layout, "elm,state,show,x", "");
|
|
if (!is_rel_to_x && is_rel_to_y)
|
|
elm_object_signal_emit(layout, "elm,state,show,y", "");
|
|
|
|
ld->rel_to_info.ctxpopup = ctxpopup;
|
|
evas_object_smart_callback_add(ctxpopup, "dismissed",
|
|
ctxpopup_dismissed_cb, ld);
|
|
evas_object_move(ctxpopup, x, y);
|
|
evas_object_show(ctxpopup);
|
|
}
|
|
else
|
|
{
|
|
evas_object_del(ctxpopup);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cp_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
Evas_Event_Mouse_Up *ev = event_info;
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
|
|
cp_mouse_move_cb);
|
|
live_data *ld = data;
|
|
align_lines_hide(ld);
|
|
|
|
Evas_Coord x = ev->canvas.x;
|
|
Evas_Coord y = ev->canvas.y;
|
|
|
|
Ctrl_Pt cp = (Ctrl_Pt) evas_object_data_get(obj, "index");
|
|
show_relative_to_list(ld, x, y, cp);
|
|
|
|
//Show All Control Points
|
|
int i;
|
|
for (i = 0; i < Ctrl_Pt_Cnt; i++)
|
|
elm_object_signal_emit(ld->ctrl_pt[i], "elm,state,show", "");
|
|
}
|
|
|
|
static void
|
|
cp_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
Evas_Event_Mouse_Down *ev = event_info;
|
|
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
|
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
|
|
cp_mouse_move_cb, data);
|
|
|
|
//Hide All Control Points
|
|
live_data *ld = data;
|
|
int i;
|
|
for (i = 0; i < Ctrl_Pt_Cnt; i++)
|
|
elm_object_signal_emit(ld->ctrl_pt[i], "elm,state,hide", "");
|
|
}
|
|
|
|
static void
|
|
ctrl_pt_init(live_data *ld)
|
|
{
|
|
//Ctrl Point Size
|
|
Evas_Object *edje = elm_layout_edje_get(ld->layout);
|
|
double ctrl_size = atof(edje_object_data_get(edje, "ctrl_size"));
|
|
ctrl_size = ELM_SCALE_SIZE(ctrl_size);
|
|
ld->half_ctrl_size = ctrl_size * 0.5;
|
|
|
|
//Create Control Points
|
|
int i;
|
|
for (i = 0; i < Ctrl_Pt_Cnt; i++)
|
|
{
|
|
Evas_Object *layout = elm_layout_add(ld->layout);
|
|
view_obj_member_add(ld, layout);
|
|
elm_layout_file_set(layout, EDJE_PATH, "ctrl_pt");
|
|
evas_object_resize(layout, ctrl_size, ctrl_size);
|
|
evas_object_show(layout);
|
|
evas_object_event_callback_add(layout,
|
|
EVAS_CALLBACK_MOUSE_DOWN,
|
|
cp_mouse_down_cb, ld);
|
|
evas_object_event_callback_add(layout,
|
|
EVAS_CALLBACK_MOUSE_UP,
|
|
cp_mouse_up_cb, ld);
|
|
evas_object_data_set(layout, "index", (void *)(uintptr_t)i);
|
|
|
|
ld->ctrl_pt[i] = layout;
|
|
}
|
|
|
|
//Set Mouse Cursors
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Rel1],
|
|
ELM_CURSOR_TOP_LEFT_CORNER);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Rel2],
|
|
ELM_CURSOR_BOTTOM_RIGHT_CORNER);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Rel3],
|
|
ELM_CURSOR_TOP_RIGHT_CORNER);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Rel4],
|
|
ELM_CURSOR_BOTTOM_LEFT_CORNER);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Top], ELM_CURSOR_TOP_SIDE);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Bottom], ELM_CURSOR_BOTTOM_SIDE);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Left], ELM_CURSOR_LEFT_SIDE);
|
|
elm_object_cursor_set(ld->ctrl_pt[Ctrl_Pt_Right], ELM_CURSOR_RIGHT_SIDE);
|
|
|
|
ctrl_pt_update(ld);
|
|
}
|
|
|
|
static void
|
|
free_auto_align_data(Eina_Array *arr)
|
|
{
|
|
unsigned int i;
|
|
Eina_Array_Iterator iter;
|
|
auto_align_data *al_pos;
|
|
|
|
if (arr)
|
|
{
|
|
EINA_ARRAY_ITER_NEXT(arr, i, al_pos, iter)
|
|
{
|
|
free(al_pos);
|
|
}
|
|
eina_array_free(arr);
|
|
arr = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
live_edit_auto_align_target_parts_init(live_data *ld, Eina_Bool is_update)
|
|
{
|
|
Eina_List *l;
|
|
|
|
Evas_Object *view_obj = view_obj_get(ld);
|
|
Evas_Coord vx, vy;
|
|
evas_object_geometry_get(view_obj, &vx, &vy, NULL, NULL);
|
|
|
|
// set target parts for finding the boundary of exists parts
|
|
char *part_name;
|
|
Eina_List *parts = enventor_object_parts_list_get(base_enventor_get());
|
|
|
|
Evas_Coord x,y,w,h;
|
|
//Case 1: create new auto_align_data for new live edit item
|
|
if (!is_update)
|
|
{
|
|
free_auto_align_data(ld->auto_align_array);
|
|
ld->auto_align_array = eina_array_new(eina_list_count(parts));
|
|
EINA_LIST_FOREACH(parts, l, part_name)
|
|
{
|
|
edje_object_part_geometry_get(view_obj, part_name, &x, &y, &w, &h);
|
|
auto_align_data *al_pos = calloc(1, sizeof(auto_align_data));
|
|
snprintf(al_pos->part_name, PART_NAME_MAX, "%s", part_name);
|
|
al_pos->pt1.x = x + vx;
|
|
al_pos->pt1.y = y + vy;
|
|
al_pos->pt2.x = x + w + vx;
|
|
al_pos->pt2.y = y + h + vy;
|
|
eina_array_push(ld->auto_align_array, al_pos);
|
|
}
|
|
}
|
|
//Case 2: update the exsit auto_align_data when view is resized
|
|
else
|
|
{
|
|
int i = 0, item_cnt;
|
|
if (ld->auto_align_array)
|
|
{
|
|
item_cnt = eina_array_count_get(ld->auto_align_array);
|
|
EINA_LIST_FOREACH(parts, l, part_name)
|
|
{
|
|
edje_object_part_geometry_get(view_obj, part_name,
|
|
&x, &y, &w, &h);
|
|
|
|
if (i < item_cnt)
|
|
{
|
|
auto_align_data *al_pos =
|
|
eina_array_data_get(ld->auto_align_array, i++);
|
|
al_pos->pt1.x = x + vx;
|
|
al_pos->pt1.y = y + vy;
|
|
al_pos->pt2.x = x + w + vx;
|
|
al_pos->pt2.y = y + h + vy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
layout_update(live_data *ld)
|
|
{
|
|
Evas_Coord x, y, w, h;
|
|
Evas_Object *view = view_obj_get(ld);
|
|
evas_object_geometry_get(view, &x, &y, &w, &h);
|
|
|
|
double x2 = round(w * ld->rel_info.rel1_x);
|
|
double y2 = round(h * ld->rel_info.rel1_y);
|
|
evas_object_move(ld->layout, (x + x2), (y + y2));
|
|
double w2 =
|
|
round(((double) w * (ld->rel_info.rel2_x - ld->rel_info.rel1_x)));
|
|
double h2 =
|
|
round(((double) h * (ld->rel_info.rel2_y - ld->rel_info.rel1_y)));
|
|
evas_object_resize(ld->layout, w2, h2);
|
|
|
|
live_edit_auto_align_target_parts_init(ld, EINA_TRUE);
|
|
}
|
|
|
|
static void
|
|
live_edit_update_internal(live_data *ld)
|
|
{
|
|
evas_smart_objects_calculate(evas_object_evas_get(ld->layout));
|
|
layout_update(ld);
|
|
ctrl_pt_update(ld);
|
|
align_line_update(ld);
|
|
info_text_update(ld);
|
|
|
|
//ctxpopup position won't be valid anymore.
|
|
if (ld->rel_to_info.ctxpopup)
|
|
elm_ctxpopup_dismiss(ld->rel_to_info.ctxpopup);
|
|
}
|
|
|
|
static void
|
|
live_view_geom_cb(void *data, Evas *e EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
live_data *ld = data;
|
|
live_edit_update_internal(ld);
|
|
}
|
|
|
|
// This function cacluates the position of layout to the closest part edge
|
|
static int
|
|
calc_layout_auto_align_pos(Evas_Object *layout, live_data *ld, int x, int y,
|
|
int layout_dir_x, int layout_dir_y, int *ret_x,
|
|
int *ret_y)
|
|
{
|
|
static int pre_layout_dir_x = 0;
|
|
static int pre_layout_dir_y = 0;
|
|
|
|
// if control key is pressed, auto align is not applied
|
|
if (ld->ctrl_pressed)
|
|
{
|
|
*ret_x = x;
|
|
*ret_y = y;
|
|
return 0;
|
|
}
|
|
|
|
Eina_Bool is_up, is_down, is_left, is_right;
|
|
is_up = is_down = is_left = is_right = EINA_FALSE;
|
|
|
|
Evas_Coord w, h;
|
|
evas_object_geometry_get(layout, NULL, NULL, &w, &h);
|
|
|
|
// layout_dir_x and layout_dir_y are the current direction of layout,
|
|
// pre_layout_dir_x and pre_layout_dir_y are previous direction of layout.
|
|
// These conditions are used to align the layout in moving direction
|
|
if (layout_dir_x == 0)
|
|
{
|
|
if (pre_layout_dir_x < 0)
|
|
{
|
|
is_left = EINA_TRUE;
|
|
pre_layout_dir_x = -1;
|
|
}
|
|
else
|
|
{
|
|
is_right = EINA_TRUE;
|
|
pre_layout_dir_x = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pre_layout_dir_x = layout_dir_x;
|
|
if (layout_dir_x < 0) is_left = EINA_TRUE;
|
|
else if (layout_dir_x > 0) is_right = EINA_TRUE;
|
|
}
|
|
|
|
if (layout_dir_y == 0)
|
|
{
|
|
if (pre_layout_dir_y < 0)
|
|
{
|
|
is_up = EINA_TRUE;
|
|
pre_layout_dir_y = -1;
|
|
}
|
|
else
|
|
{
|
|
is_down = EINA_TRUE;
|
|
pre_layout_dir_y = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pre_layout_dir_y = layout_dir_y;
|
|
if (layout_dir_y < 0) is_up = EINA_TRUE;
|
|
else if (layout_dir_y > 0) is_down = EINA_TRUE;
|
|
}
|
|
|
|
int res_x1, res_y1, res_x2, res_y2;
|
|
unsigned int nx, ny, nx2, ny2;
|
|
res_x1 = res_y1 = res_x2 = res_y2 = -1;
|
|
nx = ny = nx2 = ny2 = LIVE_EDIT_MAX_DIST;
|
|
unsigned int dist = LIVE_EDIT_AUTO_ALIGN_DIST;
|
|
|
|
// This loop finds the closest part to the layout
|
|
unsigned int i;
|
|
auto_align_data *al_pos;
|
|
Eina_Array_Iterator iter;
|
|
EINA_ARRAY_ITER_NEXT(ld->auto_align_array, i, al_pos, iter)
|
|
{
|
|
unsigned int dx1, dy1, dx2, dy2;
|
|
dx1 = dy1 = dx2 = dy2 = LIVE_EDIT_MAX_DIST;
|
|
if (((al_pos->pt1.y <= y) && (al_pos->pt2.y >= y)) ||
|
|
((al_pos->pt1.y <= (y + h)) && (al_pos->pt2.y >= (y + h))) ||
|
|
((al_pos->pt1.y >= y) && (al_pos->pt2.y <= (y + h))))
|
|
{
|
|
dx1 = abs(al_pos->pt1.x - x);
|
|
dx2 = abs(al_pos->pt1.x - (x + w));
|
|
}
|
|
|
|
if (((al_pos->pt1.x <= x) && (al_pos->pt2.x >= x)) ||
|
|
((al_pos->pt1.x <= (x + w)) && (al_pos->pt2.x >= (x + w))) ||
|
|
((al_pos->pt1.x >= x) && (al_pos->pt2.x <= (x + w))))
|
|
{
|
|
dy1 = abs(al_pos->pt1.y - y);
|
|
dy2 = abs(al_pos->pt1.y - (y + h));
|
|
}
|
|
|
|
if (is_left && (dx1 < dist) && (dx1 < nx))
|
|
{
|
|
nx = dx1;
|
|
res_x1 = al_pos->pt1.x;
|
|
}
|
|
if (is_right && (dx2 < dist) && (dx2 < nx2))
|
|
{
|
|
nx2 = dx2;
|
|
res_x2 = al_pos->pt1.x;
|
|
}
|
|
if (is_up && (dy1 < dist) && (dy1 < ny))
|
|
{
|
|
ny = dy1;
|
|
res_y1 = al_pos->pt1.y;
|
|
}
|
|
if (is_down && (dy2 < dist) && (dy2 < ny2))
|
|
{
|
|
ny2 = dy2;
|
|
res_y2 = al_pos->pt1.y;
|
|
}
|
|
|
|
if (((al_pos->pt1.y <= y) && (al_pos->pt2.y >= y)) ||
|
|
((al_pos->pt1.y <= (y + h)) && (al_pos->pt2.y >= (y + h))) ||
|
|
((al_pos->pt1.y >= y) && (al_pos->pt2.y <= (y + h))))
|
|
{
|
|
dx1 = abs(al_pos->pt2.x - x);
|
|
dx2 = abs(al_pos->pt2.x - (x + w));
|
|
}
|
|
|
|
if (((al_pos->pt1.x <= x) && (al_pos->pt2.x >= x)) ||
|
|
((al_pos->pt1.x <= (x + w)) && (al_pos->pt2.x >= (x + w))) ||
|
|
((al_pos->pt1.x >= x) && (al_pos->pt2.x <= (x + w))))
|
|
{
|
|
dy1 = abs(al_pos->pt2.y - y);
|
|
dy2 = abs(al_pos->pt2.y - (y + h));
|
|
}
|
|
|
|
if (is_left && (dx1 < dist) && (dx1 < nx))
|
|
{
|
|
nx = dx1;
|
|
res_x1 = al_pos->pt2.x;
|
|
}
|
|
if (is_right && (dx2 < dist) && (dx2 < nx2))
|
|
{
|
|
nx2 = dx2;
|
|
res_x2 = al_pos->pt2.x;
|
|
}
|
|
if (is_up && (dy1 < dist) && (dy1 < ny))
|
|
{
|
|
ny = dy1;
|
|
res_y1 = al_pos->pt2.y;
|
|
}
|
|
if (is_down && (dy2 < dist) && (dy2 < ny2))
|
|
{
|
|
ny2 = dy2;
|
|
res_y2 = al_pos->pt2.y;
|
|
}
|
|
}
|
|
|
|
int align_line = 0;
|
|
|
|
// If we find the closest position and return it
|
|
if (is_left && (res_x1 != -1))
|
|
{
|
|
*ret_x = res_x1;
|
|
align_line |= ALIGN_LINE_LEFT;
|
|
}
|
|
else if (is_right && (res_x2 != -1))
|
|
{
|
|
*ret_x = res_x2 - w;
|
|
align_line |= ALIGN_LINE_RIGHT;
|
|
}
|
|
|
|
if (is_up && (res_y1 != -1))
|
|
{
|
|
*ret_y = res_y1;
|
|
align_line |= ALIGN_LINE_TOP;
|
|
}
|
|
else if (is_down && (res_y2 != -1))
|
|
{
|
|
*ret_y = res_y2 - h;
|
|
align_line |= ALIGN_LINE_BOTTOM;
|
|
}
|
|
|
|
return align_line;
|
|
}
|
|
|
|
static void
|
|
layout_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
|
|
void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Move *ev = event_info;
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
|
|
live_data *ld = data;
|
|
|
|
Evas_Coord vx, vy, vw, vh; //layout geometry
|
|
Evas_Object *view = view_obj_get(ld);
|
|
evas_object_geometry_get(view, &vx, &vy, &vw, &vh);
|
|
|
|
//only affect when cursor is inside of the part
|
|
Evas_Coord x, y, w, h;
|
|
evas_object_geometry_get(obj, &x, &y, &w, &h);
|
|
|
|
if (ev->cur.canvas.x > (x + w)) return;
|
|
if (x > ev->cur.canvas.x) return;
|
|
if (ev->cur.canvas.y > (y + h)) return;
|
|
if (y > ev->cur.canvas.y) return;
|
|
|
|
x = ev->cur.canvas.x - ld->move_delta.x;
|
|
y = ev->cur.canvas.y - ld->move_delta.y;
|
|
|
|
Evas_Coord dir_x, dir_y;
|
|
dir_x = ev->cur.canvas.x - ev->prev.canvas.x;
|
|
dir_y = ev->cur.canvas.y - ev->prev.canvas.y;
|
|
|
|
int ret_x, ret_y;
|
|
ret_x = x;
|
|
ret_y = y;
|
|
|
|
// This function set the position of layout to the closest part edge
|
|
int align_line =
|
|
calc_layout_auto_align_pos(obj, ld, x, y, dir_x, dir_y, &ret_x, &ret_y);
|
|
|
|
x = ret_x;
|
|
y = ret_y;
|
|
|
|
//limit to live view boundary
|
|
if (vx > x) x = vx;
|
|
if ((x + w) > (vx + vw)) x = (vx + vw) - w;
|
|
if (vy > y) y = vy;
|
|
if ((y + h) > (vy + vh)) y -= ((y + h) - (vy + vh));
|
|
|
|
double orig_rel1_x = ld->rel_info.rel1_x;
|
|
double orig_rel1_y = ld->rel_info.rel1_y;
|
|
ld->rel_info.rel1_x = (double) (x - vx) / vw;
|
|
ld->rel_info.rel1_y = (double) (y - vy) / vh;
|
|
ld->rel_info.rel2_x += ld->rel_info.rel1_x - orig_rel1_x;
|
|
ld->rel_info.rel2_y += ld->rel_info.rel1_y - orig_rel1_y;
|
|
|
|
//Round off in the end to reduce round-off error.
|
|
ld->rel_info.rel1_x = ROUNDING(ld->rel_info.rel1_x, 2);
|
|
ld->rel_info.rel1_y = ROUNDING(ld->rel_info.rel1_y, 2);
|
|
ld->rel_info.rel2_x = ROUNDING(ld->rel_info.rel2_x, 2);
|
|
ld->rel_info.rel2_y = ROUNDING(ld->rel_info.rel2_y, 2);
|
|
|
|
evas_object_move(obj, x, y);
|
|
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Top], "elm,state,show", "");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Bottom], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Left], "elm,state,show",
|
|
"");
|
|
elm_object_signal_emit(ld->align_line[Align_Line_Right], "elm,state,show",
|
|
"");
|
|
|
|
ctrl_pt_update(ld);
|
|
info_text_update(ld);
|
|
align_line_update(ld);
|
|
update_line_attach_effect(ld, align_line);
|
|
|
|
|
|
static void
|
|
layout_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
Evas_Event_Mouse_Up *ev = event_info;
|
|
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
|
|
layout_mouse_move_cb);
|
|
live_data *ld = data;
|
|
align_lines_hide(ld);
|
|
|
|
//Show hidden control points
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Top], "elm,state,show", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Bottom], "elm,state,show", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Left], "elm,state,show", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Right], "elm,state,show", "");
|
|
}
|
|
|
|
static void
|
|
layout_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
|
|
void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Down *ev = event_info;
|
|
live_data *ld = data;
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
|
|
//insert part on double click
|
|
if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
|
|
{
|
|
live_edit_insert(ld);
|
|
live_edit_cancel(EINA_FALSE);
|
|
return;
|
|
}
|
|
|
|
/* Store (cursor - obj position) distance.
|
|
And keep this distance while obj is moving. */
|
|
Evas_Coord x, y;
|
|
evas_object_geometry_get(obj, &x, &y, NULL, NULL);
|
|
ld->move_delta.x = ev->canvas.x - x;
|
|
ld->move_delta.y = ev->canvas.y - y;
|
|
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
|
|
layout_mouse_move_cb, data);
|
|
|
|
//Hide unnecessary control points
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Top], "elm,state,hide", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Bottom], "elm,state,hide", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Left], "elm,state,hide", "");
|
|
elm_object_signal_emit(ld->ctrl_pt[Ctrl_Pt_Right], "elm,state,hide", "");
|
|
}
|
|
|
|
static void
|
|
align_line_init(live_data *ld)
|
|
{
|
|
//Create Align Lines
|
|
int i;
|
|
for (i = 0; i < Align_Line_Cnt; i++)
|
|
{
|
|
//Align line should be located between live edit item and live view
|
|
Evas_Object *layout = elm_layout_add(ld->live_view);
|
|
view_obj_member_add(ld, layout);
|
|
elm_layout_file_set(layout, EDJE_PATH, "ctrl_pt");
|
|
evas_object_show(layout);
|
|
elm_object_signal_emit(layout, "elm,state,hide,instance", "");
|
|
ld->align_line[i] = layout;
|
|
}
|
|
}
|
|
|
|
static void
|
|
info_text_init(live_data *ld)
|
|
{
|
|
//Create Info Texts
|
|
int i;
|
|
Evas *e = evas_object_evas_get(ld->layout);
|
|
double scale = elm_config_scale_get();
|
|
for (i = 0; i < Info_Text_Cnt; i++)
|
|
{
|
|
Evas_Object *rect = evas_object_rectangle_add(e);
|
|
view_obj_member_add(ld, rect);
|
|
evas_object_pass_events_set(rect, EINA_TRUE);
|
|
evas_object_color_set(rect, 0, 0, 0, 125);
|
|
evas_object_show(rect);
|
|
ld->info_text_bg[i] = rect;
|
|
|
|
Evas_Object *text = evas_object_text_add(e);
|
|
view_obj_member_add(ld, text);
|
|
evas_object_pass_events_set(text, EINA_TRUE);
|
|
evas_object_text_font_set(text, LIVE_EDIT_FONT,
|
|
( LIVE_EDIT_FONT_SIZE * scale));
|
|
evas_object_show(text);
|
|
ld->info_text[i] = text;
|
|
}
|
|
|
|
info_text_update(ld);
|
|
}
|
|
|
|
static void
|
|
key_grab_add(Evas_Object *keygrabber, const char *key)
|
|
{
|
|
if (!evas_object_key_grab(keygrabber, key, 0, 0, EINA_TRUE))
|
|
EINA_LOG_ERR(_("Failed to grab key - %s"), key);
|
|
}
|
|
|
|
static void
|
|
rel_to_values_reset(live_data *ld)
|
|
{
|
|
ld->rel_to_info.align_x = 0.5;
|
|
ld->rel_to_info.align_y = 0.5;
|
|
ld->rel_to_info.rel1_x_part = NULL;
|
|
ld->rel_to_info.rel1_y_part = NULL;
|
|
ld->rel_to_info.rel2_x_part = NULL;
|
|
ld->rel_to_info.rel2_y_part = NULL;
|
|
ld->rel_to_info.min_w = 0;
|
|
ld->rel_to_info.min_h = 0;
|
|
}
|
|
|
|
static Eina_Bool
|
|
live_edit_layer_set(live_data *ld)
|
|
{
|
|
//Keygrabber
|
|
ld->keygrabber =
|
|
evas_object_rectangle_add(evas_object_evas_get(ld->live_view));
|
|
evas_object_event_callback_add(ld->keygrabber, EVAS_CALLBACK_KEY_DOWN,
|
|
keygrabber_key_down_cb, ld);
|
|
evas_object_event_callback_add(ld->keygrabber, EVAS_CALLBACK_KEY_UP,
|
|
keygrabber_key_up_cb, ld);
|
|
evas_object_event_callback_add(ld->keygrabber, EVAS_CALLBACK_KEY_DOWN,
|
|
keygrabber_direction_key_down_cb, ld);
|
|
evas_object_event_callback_add(ld->live_view, EVAS_CALLBACK_RESIZE,
|
|
live_view_geom_cb, ld);
|
|
evas_object_event_callback_add(ld->live_view, EVAS_CALLBACK_MOVE,
|
|
live_view_geom_cb, ld);
|
|
|
|
// Add keygrab for Control_L, To receive key_up_callback we need to use mask
|
|
Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
|
|
evas_object_evas_get(ld->keygrabber), "Control");
|
|
if (!evas_object_key_grab(ld->keygrabber, "Control_L", mask, 0, EINA_FALSE))
|
|
EINA_LOG_ERR(_("Failed to grab key - %s"), "Control_L");
|
|
if (!evas_object_key_grab(ld->keygrabber, "Control_L", 0, 0, EINA_FALSE))
|
|
EINA_LOG_ERR(_("Failed to grab key - %s"), "Control_L");
|
|
|
|
key_grab_add(ld->keygrabber, "Return");
|
|
key_grab_add(ld->keygrabber, "Delete");
|
|
key_grab_add(ld->keygrabber, "BackSpace");
|
|
key_grab_add(ld->keygrabber, "Up");
|
|
key_grab_add(ld->keygrabber, "Down");
|
|
key_grab_add(ld->keygrabber, "Left");
|
|
key_grab_add(ld->keygrabber, "Right");
|
|
|
|
//Create Live View Layout
|
|
Evas_Object *layout = elm_layout_add(ld->live_view);
|
|
Evas_Object *view_obj = view_obj_get(ld);
|
|
if (!view_obj)
|
|
{
|
|
stats_info_msg_update("Live Edit is not available here. A base group is required!");
|
|
live_edit_cancel(EINA_FALSE);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
//Check canvas has been set or not.
|
|
Evas_Coord w, h;
|
|
evas_object_geometry_get(view_obj, NULL, NULL, &w, &h);
|
|
if ((w < 2) || (h < 2))
|
|
{
|
|
stats_info_msg_update("Live Edit is not available here. Please set up live view size first!");
|
|
live_edit_cancel(EINA_FALSE);
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
view_obj_member_add(ld, layout);
|
|
elm_layout_file_set(layout, EDJE_PATH, "live_edit_layout");
|
|
evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_DOWN,
|
|
layout_mouse_down_cb, ld);
|
|
evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_UP,
|
|
layout_mouse_up_cb, ld);
|
|
elm_layout_part_cursor_set(layout, "cursor_body", ELM_CURSOR_FLEUR);
|
|
evas_object_show(layout);
|
|
|
|
ld->layout = layout;
|
|
|
|
evas_object_smart_callback_add(view_scroller_get(ld), "scroll",
|
|
view_scroll_cb, ld);
|
|
|
|
//Initial Layout Geometry
|
|
ld->rel_info.rel1_x = LIVE_EDIT_REL1;
|
|
ld->rel_info.rel1_y = LIVE_EDIT_REL1;
|
|
ld->rel_info.rel2_x = LIVE_EDIT_REL2;
|
|
ld->rel_info.rel2_y = LIVE_EDIT_REL2;
|
|
rel_to_values_reset(ld);
|
|
live_edit_symbol_set(ld);
|
|
ctrl_pt_init(ld);
|
|
align_line_init(ld);
|
|
live_edit_update_internal(ld);
|
|
info_text_init(ld);
|
|
live_edit_auto_align_target_parts_init(ld, EINA_FALSE);
|
|
ld->last_cp = Ctrl_Pt_Cnt;
|
|
|
|
panes_live_edit_fixed_bar_visible_set(EINA_TRUE);
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
live_btn_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED,
|
|
void *event_info EINA_UNUSED)
|
|
{
|
|
live_edit_cancel(EINA_FALSE);
|
|
goto_close();
|
|
search_close();
|
|
|
|
live_data *ld = g_ld;
|
|
|
|
ld->type = (unsigned int)(uintptr_t)data;
|
|
enventor_object_disabled_set(base_enventor_get(), EINA_TRUE);
|
|
ld->live_view = enventor_object_live_view_get(base_enventor_get());
|
|
ld->on = EINA_TRUE;
|
|
|
|
if (!live_edit_layer_set(ld)) return;
|
|
|
|
stats_info_msg_update(_("Double click part to confirm."
|
|
"(Esc = cancel, Direction Key ="
|
|
" move item per pixel,"
|
|
"Ctrl = disable auto-aligning)"));
|
|
}
|
|
|
|
static Evas_Object *
|
|
live_btn_create(Evas_Object *parent, const char *name, void * data,
|
|
Edje_Part_Type type)
|
|
{
|
|
Evas_Object *btn = elm_button_add(parent);
|
|
elm_object_style_set(btn, ENVENTOR_NAME);
|
|
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
elm_object_focus_allow_set(btn, EINA_FALSE);
|
|
|
|
switch (type)
|
|
{
|
|
case EDJE_PART_TYPE_RECTANGLE:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add a Rect part to the live view.<br>"
|
|
"A Rect part is used as a solid color<br>"
|
|
"component or clipping other components."));
|
|
break;
|
|
case EDJE_PART_TYPE_TEXT:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add a Text part to the live view.<br>"
|
|
"A Text part is used for plain text."));
|
|
break;
|
|
case EDJE_PART_TYPE_IMAGE:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add an Image part to the live view.<br>"
|
|
"An Image part contains a single image<br>"
|
|
"resource, usually an image file."));
|
|
break;
|
|
case EDJE_PART_TYPE_SWALLOW:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add a Swallow part to the live view.<br>"
|
|
"A Swallow part is a placeholder for<br>"
|
|
"objects that you may want to<br>"
|
|
"include in the layout later."));
|
|
break;
|
|
case EDJE_PART_TYPE_TEXTBLOCK:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add a Textblock part to the live view.<br>"
|
|
"A Textblock part is a rich-text part<br>"
|
|
"that can show big chunks of text."));
|
|
break;
|
|
case EDJE_PART_TYPE_SPACER:
|
|
elm_object_tooltip_text_set(btn,
|
|
_("Add a Spacer part to the live view.<br>"
|
|
"A Spacer part is an anchor to locate <br>"
|
|
"other parts. It is invisible and<br>"
|
|
"normally used for padding."));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
elm_object_tooltip_orient_set(btn, ELM_TOOLTIP_ORIENT_BOTTOM);
|
|
|
|
Evas_Object *img = elm_image_add(btn);
|
|
elm_image_file_set(img, EDJE_PATH, name);
|
|
elm_object_content_set(btn, img);
|
|
|
|
evas_object_smart_callback_add(btn, "clicked", live_btn_clicked_cb, data);
|
|
evas_object_show(btn);
|
|
|
|
return btn;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Externally accessible calls */
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
live_edit_update(void)
|
|
{
|
|
if (!live_edit_get()) return;
|
|
|
|
live_data *ld = g_ld;
|
|
EINA_SAFETY_ON_NULL_RETURN(ld);
|
|
|
|
//Scale up/down of the symbol object.
|
|
Evas_Object *layout_symbol =
|
|
elm_object_part_content_get(ld->layout, "elm.swallow.symbol");
|
|
if (layout_symbol)
|
|
elm_object_scale_set(layout_symbol,
|
|
enventor_object_live_view_scale_get(base_enventor_get()));
|
|
|
|
live_edit_update_internal(ld);
|
|
}
|
|
|
|
Eina_Bool
|
|
live_edit_get(void)
|
|
{
|
|
live_data *ld = g_ld;
|
|
if (!ld) return EINA_FALSE;
|
|
return ld->on;
|
|
}
|
|
|
|
Eina_Bool
|
|
live_edit_cancel(Eina_Bool phase_in)
|
|
{
|
|
live_data *ld = g_ld;
|
|
if (!ld || !ld->on) return EINA_FALSE;
|
|
|
|
//Dismiss Relative To Ctxpopup firstly.
|
|
if (phase_in && ld->rel_to_info.ctxpopup)
|
|
{
|
|
evas_object_del(ld->rel_to_info.ctxpopup);
|
|
ld->rel_to_info.ctxpopup = NULL;
|
|
return EINA_TRUE;
|
|
}
|
|
else
|
|
{
|
|
evas_object_del(ld->rel_to_info.ctxpopup);
|
|
ld->rel_to_info.ctxpopup = NULL;
|
|
}
|
|
|
|
enventor_object_disabled_set(base_enventor_get(), EINA_FALSE);
|
|
|
|
evas_object_del(ld->keygrabber);
|
|
ld->keygrabber = NULL;
|
|
|
|
evas_object_event_callback_del(ld->live_view, EVAS_CALLBACK_RESIZE,
|
|
live_view_geom_cb);
|
|
evas_object_event_callback_del(ld->live_view, EVAS_CALLBACK_MOVE,
|
|
live_view_geom_cb);
|
|
|
|
evas_object_smart_callback_del(view_scroller_get(ld),
|
|
"scroll",
|
|
view_scroll_cb);
|
|
ld->live_view = NULL;
|
|
|
|
evas_object_del(ld->layout);
|
|
ld->layout = NULL;
|
|
|
|
//Delete Control Points
|
|
int i;
|
|
for (i = 0; i < Ctrl_Pt_Cnt; i++)
|
|
{
|
|
evas_object_del(ld->ctrl_pt[i]);
|
|
ld->ctrl_pt[i] = NULL;
|
|
}
|
|
|
|
//Delete Align Lines
|
|
for (i = 0; i < Align_Line_Cnt; i++)
|
|
{
|
|
evas_object_del(ld->align_line[i]);
|
|
ld->align_line[i] = NULL;
|
|
}
|
|
|
|
//Delete Info Texts
|
|
for (i = 0; i < Info_Text_Cnt; i++)
|
|
{
|
|
evas_object_del(ld->info_text[i]);
|
|
ld->info_text[i] = NULL;
|
|
}
|
|
//Delete Info Text BGs
|
|
for (i = 0 ; i < Info_Text_Cnt; i++)
|
|
{
|
|
evas_object_del(ld->info_text_bg[i]);
|
|
ld->info_text_bg[i] = NULL;
|
|
}
|
|
|
|
ld->on = EINA_FALSE;
|
|
ld->align_left = EINA_FALSE;
|
|
ld->align_right = EINA_FALSE;
|
|
ld->align_top = EINA_FALSE;
|
|
ld->align_bottom = EINA_FALSE;
|
|
|
|
elm_check_state_set(ld->fixed_w_check, EINA_FALSE);
|
|
elm_check_state_set(ld->fixed_h_check, EINA_FALSE);
|
|
panes_live_edit_fixed_bar_visible_set(EINA_FALSE);
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
//Create and return a list of buttons.
|
|
Eina_List *
|
|
live_edit_tools_create(Evas_Object *parent)
|
|
{
|
|
Eina_List *btn_list = NULL;
|
|
Evas_Object *btn;
|
|
int i;
|
|
|
|
for (i = 0; i < (LIVEEDIT_ITEMS_NUM - 1); i++)
|
|
{
|
|
btn = live_btn_create(parent, LIVEEDIT_ITEMS[i].name,
|
|
(void *)(uintptr_t) i,
|
|
LIVEEDIT_ITEMS[i].type);
|
|
btn_list = eina_list_append(btn_list, btn);
|
|
}
|
|
|
|
//Just for spacer. Because we'd like to avoid margin in the icon image,
|
|
//We use 2 images - button icon's and live edit object's.
|
|
btn = live_btn_create(parent, "Spacer_Icon",
|
|
(void *)(uintptr_t) i, EDJE_PART_TYPE_SPACER);
|
|
btn_list = eina_list_append(btn_list, btn);
|
|
|
|
return btn_list;
|
|
}
|
|
|
|
Evas_Object *
|
|
live_edit_init(Evas_Object *parent)
|
|
{
|
|
live_data *ld = calloc(1, sizeof(live_data));
|
|
if (!ld)
|
|
{
|
|
EINA_LOG_ERR(_("Faild to allocate Memory!"));
|
|
return NULL;
|
|
}
|
|
g_ld = ld;
|
|
|
|
//Create fixed bar for setting fixed option
|
|
Evas_Object *fixed_box = elm_box_add(parent);
|
|
elm_box_padding_set(fixed_box, ELM_SCALE_SIZE(50), 0);
|
|
elm_box_horizontal_set(fixed_box, EINA_TRUE);
|
|
evas_object_show(fixed_box);
|
|
|
|
//Fixed Width Check
|
|
Evas_Object *fixed_w_check = elm_check_add(fixed_box);
|
|
elm_object_focus_allow_set(fixed_w_check, EINA_FALSE);
|
|
elm_object_text_set(fixed_w_check, "Fixed width");
|
|
elm_object_tooltip_text_set(fixed_w_check,
|
|
"When you check Fixed width, width of a new<br>"
|
|
"part won't be resizable but it will stick a<br>"
|
|
"fixed size.");
|
|
evas_object_show(fixed_w_check);
|
|
elm_box_pack_end(fixed_box, fixed_w_check);
|
|
|
|
//Fixed Height Check
|
|
Evas_Object *fixed_h_check = elm_check_add(fixed_box);
|
|
elm_object_focus_allow_set(fixed_h_check, EINA_FALSE);
|
|
elm_object_text_set(fixed_h_check, "Fixed height");
|
|
elm_object_tooltip_text_set(fixed_h_check,
|
|
"When you check Fixed height, height of a<br>"
|
|
"new part won't be resizable but it will<br>"
|
|
"stick a fixed size.");
|
|
evas_object_show(fixed_h_check);
|
|
elm_box_pack_end(fixed_box, fixed_h_check);
|
|
|
|
ld->fixed_w_check = fixed_w_check;
|
|
ld->fixed_h_check = fixed_h_check;
|
|
|
|
return fixed_box;
|
|
}
|
|
|
|
void
|
|
live_edit_term(void)
|
|
{
|
|
live_data *ld = g_ld;
|
|
if (!ld) return;
|
|
|
|
live_edit_cancel(EINA_FALSE);
|
|
|
|
free_auto_align_data(ld->auto_align_array);
|
|
free(ld);
|
|
g_ld = NULL;
|
|
}
|
|
|
|
|