summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeeyong Um <conr2d@gmail.com>2017-04-25 16:25:11 -0700
committerCedric BAIL <cedric@osg.samsung.com>2017-04-25 16:25:15 -0700
commite105646041545ee3c8a0acc3cbac73dc36ed9e95 (patch)
treeda9fcf1026a2cfb70eb1c4cc853ab940fee41bb2
parent7f5ec0c8ea00020be823808edbee12ad74c19fe6 (diff)
downloadefl-e105646041545ee3c8a0acc3cbac73dc36ed9e95.tar.gz
edje_cc: introduce "Anchors" - easy way to set parts relationship
Test Plan: compile src/examples/edc-anchors.c and run Reviewers: zmike, raster, cedric, jpeg Reviewed By: raster, jpeg Subscribers: raster, barbieri, zmike, SanghyeonLee, taxi2se, Jaehyun_Cho Differential Revision: https://phab.enlightenment.org/D4775 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/bin/edje/edje_cc.h38
-rw-r--r--src/bin/edje/edje_cc_handlers.c601
-rw-r--r--src/examples/edje/edje-anchors.c58
-rw-r--r--src/examples/edje/edje-anchors.edc58
-rw-r--r--src/lib/edje/edje_calc.c48
-rw-r--r--src/lib/edje/edje_data.c4
-rw-r--r--src/lib/edje/edje_private.h2
7 files changed, 799 insertions, 10 deletions
diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h
index 9e47283dde..704a7fbdd5 100644
--- a/src/bin/edje/edje_cc.h
+++ b/src/bin/edje/edje_cc.h
@@ -164,6 +164,44 @@ struct _Edje_Part_Collection_Parser
Eina_Bool inherit_only;
};
+typedef enum
+{
+ EDJE_PART_ANCHOR_LINE_NONE,
+ EDJE_PART_ANCHOR_LINE_TOP,
+ EDJE_PART_ANCHOR_LINE_BOTTOM,
+ EDJE_PART_ANCHOR_LINE_LEFT,
+ EDJE_PART_ANCHOR_LINE_RIGHT,
+ EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER,
+ EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER
+} Edje_Part_Anchor_Line;
+
+typedef enum
+{
+ EDJE_PART_ANCHOR_FILL_BOTH,
+ EDJE_PART_ANCHOR_FILL_HORIZONTAL,
+ EDJE_PART_ANCHOR_FILL_VERTICAL
+} Edje_Part_Anchor_Fill;
+
+typedef struct
+{
+ union {
+ Edje_Part_Anchor_Line line;
+ Edje_Part_Anchor_Fill fill;
+ } base;
+ Eina_Bool set : 1;
+} Edje_Part_Anchor;
+
+typedef struct
+{
+ Edje_Part_Anchor top;
+ Edje_Part_Anchor bottom;
+ Edje_Part_Anchor left;
+ Edje_Part_Anchor right;
+ Edje_Part_Anchor vertical_center;
+ Edje_Part_Anchor horizontal_center;
+ Edje_Part_Anchor fill;
+} Edje_Part_Description_Anchors;
+
/* global fn calls */
void data_setup(void);
void data_write(void);
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 8c80b19c60..b38ddec37a 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -167,6 +167,8 @@ Eina_Bool script_override = EINA_FALSE;
static Edje_Program *sequencing = NULL;
static Eina_List *sequencing_lookups = NULL;
static int *anonymous_delete = NULL;
+static Edje_Part_Description_Anchors *current_anchors = NULL;
+static Eina_Bool has_relatives = EINA_FALSE;
Eina_List *po_files;
@@ -195,6 +197,8 @@ static void _program_target_add(char *name);
static void _program_after(const char *name);
static void _program_free(Edje_Program *pr);
+static void check_has_anchors(void);
+
static void st_externals_external(void);
static void st_images_image(void);
@@ -367,6 +371,14 @@ static void st_collections_group_parts_part_description_rel2_to_set(const char *
static void st_collections_group_parts_part_description_rel2_to(void);
static void st_collections_group_parts_part_description_rel2_to_x(void);
static void st_collections_group_parts_part_description_rel2_to_y(void);
+static void st_collections_group_parts_part_description_anchors_top(void);
+static void st_collections_group_parts_part_description_anchors_bottom(void);
+static void st_collections_group_parts_part_description_anchors_left(void);
+static void st_collections_group_parts_part_description_anchors_right(void);
+static void st_collections_group_parts_part_description_anchors_vertical_center(void);
+static void st_collections_group_parts_part_description_anchors_horizontal_center(void);
+static void st_collections_group_parts_part_description_anchors_fill(void);
+static void st_collections_group_parts_part_description_anchors_margin(void);
static void st_collections_group_parts_part_description_clip_to_id(void);
static void st_collections_group_parts_part_description_size_class(void);
static void st_collections_group_parts_part_description_image_normal(void);
@@ -858,6 +870,14 @@ New_Statement_Handler statement_handlers[] =
{"collections.group.parts.part.description.rel2.to", st_collections_group_parts_part_description_rel2_to},
{"collections.group.parts.part.description.rel2.to_x", st_collections_group_parts_part_description_rel2_to_x},
{"collections.group.parts.part.description.rel2.to_y", st_collections_group_parts_part_description_rel2_to_y},
+ {"collections.group.parts.part.description.anchors.top", st_collections_group_parts_part_description_anchors_top},
+ {"collections.group.parts.part.description.anchors.bottom", st_collections_group_parts_part_description_anchors_bottom},
+ {"collections.group.parts.part.description.anchors.left", st_collections_group_parts_part_description_anchors_left},
+ {"collections.group.parts.part.description.anchors.right", st_collections_group_parts_part_description_anchors_right},
+ {"collections.group.parts.part.description.anchors.vertical_center", st_collections_group_parts_part_description_anchors_vertical_center},
+ {"collections.group.parts.part.description.anchors.horizontal_center", st_collections_group_parts_part_description_anchors_horizontal_center},
+ {"collections.group.parts.part.description.anchors.fill", st_collections_group_parts_part_description_anchors_fill},
+ {"collections.group.parts.part.description.anchors.margin", st_collections_group_parts_part_description_anchors_margin},
{"collections.group.parts.part.description.clip_to", st_collections_group_parts_part_description_clip_to_id},
{"collections.group.parts.part.description.size_class", st_collections_group_parts_part_description_size_class},
{"collections.group.parts.part.description.image.normal", st_collections_group_parts_part_description_image_normal},
@@ -1470,6 +1490,7 @@ New_Object_Handler object_handlers[] =
{"collections.group.parts.part.description.link", ob_collections_group_parts_part_description_link},
{"collections.group.parts.part.description.rel1", NULL},
{"collections.group.parts.part.description.rel2", NULL},
+ {"collections.group.parts.part.description.anchors", NULL},
{"collections.group.parts.part.description.image", NULL}, /* dup */
{"collections.group.parts.part.description.image.set", ob_images_set}, /* dup */
{"collections.group.parts.part.description.image.set.image", ob_images_set_image}, /* dup */
@@ -8754,6 +8775,8 @@ st_collections_group_parts_part_description_limit(void)
static void
st_collections_group_parts_part_description_align(void)
{
+ check_has_anchors();
+
if (get_arg_count() == 2)
{
current_desc->align.x = FROM_DOUBLE(parse_float_range(0, 0.0, 1.0));
@@ -8784,6 +8807,7 @@ st_collections_group_parts_part_description_align(void)
static void
st_collections_group_parts_part_description_fixed(void)
{
+ check_has_anchors();
check_arg_count(2);
current_desc->fixed.w = parse_float_range(0, 0, 1);
@@ -9162,6 +9186,7 @@ st_collections_group_parts_part_description_clip_to_id(void)
static void
st_collections_group_parts_part_description_rel1_relative(void)
{
+ check_has_anchors();
check_arg_count(2);
current_desc->rel1.relative_x = FROM_DOUBLE(parse_float(0));
@@ -9181,6 +9206,7 @@ st_collections_group_parts_part_description_rel1_relative(void)
static void
st_collections_group_parts_part_description_rel1_offset(void)
{
+ check_has_anchors();
check_arg_count(2);
current_desc->rel1.offset_x = parse_int(0);
@@ -9211,6 +9237,7 @@ st_collections_group_parts_part_description_rel1_to_set(const char *name)
static void
st_collections_group_parts_part_description_rel_to(void)
{
+ check_has_anchors();
check_arg_count(1);
{
@@ -9225,6 +9252,7 @@ st_collections_group_parts_part_description_rel_to(void)
static void
st_collections_group_parts_part_description_rel1_to(void)
{
+ check_has_anchors();
check_arg_count(1);
{
@@ -9252,6 +9280,7 @@ st_collections_group_parts_part_description_rel_to_x(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9271,6 +9300,7 @@ st_collections_group_parts_part_description_rel1_to_x(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9301,6 +9331,7 @@ st_collections_group_parts_part_description_rel_to_y(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9320,6 +9351,7 @@ st_collections_group_parts_part_description_rel1_to_y(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9336,6 +9368,7 @@ st_collections_group_parts_part_description_rel1_to_y(void)
static void
st_collections_group_parts_part_description_rel2_relative(void)
{
+ check_has_anchors();
check_arg_count(2);
current_desc->rel2.relative_x = FROM_DOUBLE(parse_float(0));
@@ -9345,6 +9378,7 @@ st_collections_group_parts_part_description_rel2_relative(void)
static void
st_collections_group_parts_part_description_rel2_offset(void)
{
+ check_has_anchors();
check_arg_count(2);
current_desc->rel2.offset_x = parse_int(0);
@@ -9363,6 +9397,7 @@ st_collections_group_parts_part_description_rel2_to_set(const char *name)
static void
st_collections_group_parts_part_description_rel2_to(void)
{
+ check_has_anchors();
check_arg_count(1);
{
@@ -9378,6 +9413,7 @@ st_collections_group_parts_part_description_rel2_to_x(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9396,6 +9432,7 @@ st_collections_group_parts_part_description_rel2_to_y(void)
{
Edje_Part_Collection *pc;
+ check_has_anchors();
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
@@ -9409,6 +9446,568 @@ st_collections_group_parts_part_description_rel2_to_y(void)
}
}
+/** @edcsubsection{collections_group_parts_description_anchors,
+ * Group.Parts.Part.Description.Anchors} */
+
+/**
+ @page edcref
+ @block
+ anchors
+ @context
+ // This part will be expanded from the top-left corner of edje group
+ part { name : "part1";
+ description { state: "default" 0.0;
+ anchors {
+ top: GROUP TOP;
+ left: GROUP; // This means 'left: GROUP LEFT;'
+ }
+ min: 50 50;
+ }
+ }
+ // This part will be expanded from the bottom-right corner of "part1"
+ // to the bottom-right
+ part { name: "part2";
+ description { state: "default" 0.0;
+ anchors {
+ top: "part1" BOTTOM;
+ left: "part1"; // This means 'left: "part1" RIGHT;'
+ }
+ min: 50 50;
+ }
+ }
+ // This part will be expanded from the right edje of "part2" to the right
+ part { name: "part3";
+ description { state: "default" 0.0;
+ anchors {
+ left: "part2";
+ fill: "part2" VERTICAL;
+ }
+ min: 100 0; // The height will be determined by the height of "part2"
+ }
+ }
+ // This part will be expanded from the center of right edge of "part3"
+ // to the bottom-right corner of edje group
+ part { name: "part4";
+ description { state: "default" 0.0;
+ anchors {
+ top: "part3" VERTICAL_CENTER;
+ left: "part3";
+ right: GROUP;
+ bottom: GROUP;
+ }
+ }
+ }
+ @description
+ The anchors blocks are used to define the position of each edge of
+ the part's container. Anchors will change relative, align and fixed
+ attributes internally, so setting both of them is not allowed.
+ When the second parameter of position enumeration is omitted, anchoring
+ a part to the other part will put the part adjacent to the given part.
+ However, if the part is anchored to edje group, the part will be contained
+ inside the group.
+ @endblock
+
+ @property
+ anchors
+ @parameters
+ [partname] [the edge of other part]
+ @effect
+ Moves an edge of the part to the position of the edge of given part or
+ whole edje group. (GROUP means edje group that the part belong to)
+ @endproperty
+*/
+
+static void
+check_has_anchors(void)
+{
+ if (current_anchors)
+ {
+ ERR("parse error %s:%i. Anchors and Relatives(rel/align/fixed) cannot be used at the same time.",
+ file_in, line - 1);
+ exit(-1);
+ }
+
+ has_relatives = EINA_TRUE;
+}
+
+static void
+check_has_relatives(void)
+{
+ if (has_relatives)
+ {
+ ERR("parse error %s:%i. Anchors and Relatives(rel/align/fixed) cannot be used at the same time.",
+ file_in, line - 1);
+ exit(-1);
+ }
+
+ current_desc->offset_is_scaled = EINA_TRUE;
+}
+
+static void
+parse_anchor_line(Edje_Part_Anchor *anchor, Edje_Part_Anchor_Line undefined)
+{
+ int nargs;
+ char *name;
+
+ nargs = get_arg_count();
+ if (!nargs || (nargs > 2))
+ {
+ ERR("parse error %s:%i. Anchors should have a name of part and base line.",
+ file_in, line - 1);
+ exit(-1);
+ }
+
+ name = parse_str(0);
+ anchor->set = EINA_TRUE;
+
+ if (nargs == 2)
+ anchor->base.line = parse_enum(1,
+ "TOP", EDJE_PART_ANCHOR_LINE_TOP,
+ "BOTTOM", EDJE_PART_ANCHOR_LINE_BOTTOM,
+ "LEFT", EDJE_PART_ANCHOR_LINE_LEFT,
+ "RIGHT", EDJE_PART_ANCHOR_LINE_RIGHT,
+ "VERTICAL_CENTER", EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER,
+ "HORIZONTAL_CENTER", EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER,
+ NULL);
+ else if (strcmp(name, "GROUP"))
+ anchor->base.line = undefined;
+}
+
+static void
+parse_anchor_fill(Edje_Part_Anchor *anchor)
+{
+ int nargs;
+
+ nargs = get_arg_count();
+ if (!nargs || (nargs > 2))
+ {
+ ERR("parse error %s:%i. Anchors should have a name of part and base line.",
+ file_in, line - 1);
+ exit(-1);
+ }
+
+ anchor->set = EINA_TRUE;
+
+ if (nargs == 2)
+ anchor->base.fill = parse_enum(1,
+ "BOTH", EDJE_PART_ANCHOR_FILL_BOTH,
+ "HORIZONTAL", EDJE_PART_ANCHOR_FILL_HORIZONTAL,
+ "VERTICAL", EDJE_PART_ANCHOR_FILL_VERTICAL,
+ NULL);
+ else
+ anchor->base.fill = EDJE_PART_ANCHOR_FILL_BOTH;
+}
+
+static void
+anchor_queue_part_lookup(int *part, int *counterpart, Eina_Bool counterpart_is_set)
+{
+ Edje_Part_Collection *pc;
+ char *name;
+
+ pc = eina_list_data_get(eina_list_last(edje_collections));
+
+ name = parse_str(0);
+ if (!strcmp(name, "GROUP")) return;
+
+ data_queue_part_lookup(pc, name, part);
+
+ if (!counterpart_is_set)
+ data_queue_part_lookup(pc, name, counterpart);
+
+ free(name);
+}
+
+static void
+anchor_dequeue_part_lookup(int *part, Eina_Bool counterpart_is_set)
+{
+ Edje_Part_Collection *pc;
+
+ pc = eina_list_data_get(eina_list_last(edje_collections));
+
+ if (counterpart_is_set && part)
+ part_lookup_del(pc, part);
+}
+
+static void
+anchor_adjust_align(FLOAT_T *align, FLOAT_T val, unsigned char *fixed, Eina_Bool counterpart_is_set)
+{
+ if (counterpart_is_set)
+ {
+ *align = 0.5;
+ *fixed = 0;
+ }
+ else
+ {
+ *align = val;
+ *fixed = 1;
+ }
+}
+
+static void
+anchor_adjust_relative(Edje_Part_Anchor_Line *lines, FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
+{
+ if (line == EDJE_PART_ANCHOR_LINE_NONE)
+ line = base;
+
+ if (line == lines[0])
+ {
+ *rel = FROM_DOUBLE(0.0);
+ if (!counterpart_is_set)
+ *relc = FROM_DOUBLE(0.0);
+ }
+ else if (line == lines[1])
+ {
+ *rel = FROM_DOUBLE(1.0);
+ if (!counterpart_is_set)
+ *relc = FROM_DOUBLE(1.0);
+ }
+ else if (line == lines[2])
+ {
+ *rel = FROM_DOUBLE(0.5);
+ if (!counterpart_is_set)
+ *relc = FROM_DOUBLE(0.5);
+ }
+ else
+ {
+ ERR("parse error %s:%i. Edje part is anchored to wrong position.",
+ file_in, line - 1);
+ exit(-1);
+ }
+}
+
+static void
+anchor_adjust_relative_vertical(FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
+{
+ static const Edje_Part_Anchor_Line lines[] = {
+ EDJE_PART_ANCHOR_LINE_TOP,
+ EDJE_PART_ANCHOR_LINE_BOTTOM,
+ EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER
+ };
+
+ anchor_adjust_relative(lines, rel, relc, line, base, counterpart_is_set);
+}
+
+static void
+anchor_adjust_relative_horizontal(FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
+{
+ static const Edje_Part_Anchor_Line lines[] = {
+ EDJE_PART_ANCHOR_LINE_LEFT,
+ EDJE_PART_ANCHOR_LINE_RIGHT,
+ EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER
+ };
+
+ anchor_adjust_relative(lines, rel, relc, line, base, counterpart_is_set);
+}
+
+/**
+ @page edcref
+ @property
+ top
+ @parameters
+ [partname] [TOP/BOTTOM/VERTICAL_CENTER]
+ @effect
+ Causes top edge to be positioned to the edge of another part's container.
+ Setting to GROUP will indicate edje group instead of another part.
+ If bottom anchor is not set, edje part will be expanded to the bottom.
+ The second parameter of position enumeration can be omitted. (Default
+ value is BOTTOM, but TOP when the part is anchored to edje group)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_top(void)
+{
+ Eina_Bool counterpart_is_set;
+
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ counterpart_is_set = current_anchors->bottom.set;
+
+ parse_anchor_line(&(current_anchors->top), EDJE_PART_ANCHOR_LINE_BOTTOM);
+
+ anchor_dequeue_part_lookup(&(current_desc->rel1.id_y), counterpart_is_set);
+ anchor_queue_part_lookup(&(current_desc->rel1.id_y), &(current_desc->rel2.id_y), counterpart_is_set);
+
+ anchor_adjust_align(&(current_desc->align.y), 0.0, &(current_desc->fixed.h), counterpart_is_set);
+ anchor_adjust_relative_vertical(&(current_desc->rel1.relative_y), &(current_desc->rel2.relative_y), current_anchors->top.base.line, EDJE_PART_ANCHOR_LINE_TOP, counterpart_is_set);
+}
+
+/**
+ @page edcref
+ @property
+ bottom
+ @parameters
+ [partname] [TOP/BOTTOM/VERTICAL_CENTER]
+ @effect
+ Causes bottom edge to be positioned to the edge of another part's container.
+ Setting to GROUP will indicate edje group instead of another part.
+ If top anchor is not set, edje part will be expanded to the top.
+ The second parameter of position enumeration can be omitted. (Default
+ value is TOP, but BOTTOM when the part is anchored to edje group)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_bottom(void)
+{
+ Eina_Bool counterpart_is_set;
+
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ counterpart_is_set = current_anchors->top.set;
+
+ parse_anchor_line(&(current_anchors->bottom), EDJE_PART_ANCHOR_LINE_TOP);
+
+ anchor_dequeue_part_lookup(&(current_desc->rel2.id_y), counterpart_is_set);
+ anchor_queue_part_lookup(&(current_desc->rel2.id_y), &(current_desc->rel1.id_y), counterpart_is_set);
+
+ anchor_adjust_align(&(current_desc->align.y), 1.0, &(current_desc->fixed.h), counterpart_is_set);
+ anchor_adjust_relative_vertical(&(current_desc->rel2.relative_y), &(current_desc->rel1.relative_y), current_anchors->bottom.base.line, EDJE_PART_ANCHOR_LINE_BOTTOM, counterpart_is_set);
+}
+
+/**
+ @page edcref
+ @property
+ left
+ @parameters
+ [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
+ @effect
+ Causes left edge to be positioned to the edge of another part's container.
+ Setting to GROUP will indicate edje group instead of another part.
+ If right anchor is not set, edje part will be expanded to the right.
+ The second parameter of position enumeration can be omitted. (Default
+ value is RIGHT, but LEFT when the part is anchored to edje group)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_left(void)
+{
+ Eina_Bool counterpart_is_set;
+
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ counterpart_is_set = current_anchors->right.set;
+
+ parse_anchor_line(&(current_anchors->left), EDJE_PART_ANCHOR_LINE_RIGHT);
+
+ anchor_dequeue_part_lookup(&(current_desc->rel1.id_x), counterpart_is_set);
+ anchor_queue_part_lookup(&(current_desc->rel1.id_x), &(current_desc->rel2.id_x), counterpart_is_set);
+
+ anchor_adjust_align(&(current_desc->align.x), 0.0, &(current_desc->fixed.w), counterpart_is_set);
+ anchor_adjust_relative_horizontal(&(current_desc->rel1.relative_x), &(current_desc->rel2.relative_x), current_anchors->left.base.line, EDJE_PART_ANCHOR_LINE_LEFT, counterpart_is_set);
+}
+
+/**
+ @page edcref
+ @property
+ right
+ @parameters
+ [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
+ @effect
+ Causes right edge to be positioned to the edge of another part's container.
+ Setting to GROUP will indicate edje group instead of another part.
+ If left anchor is not set, edje part will be expanded to the left.
+ The second parameter of position enumeration can be omitted. (Default
+ value is LEFT, but RIGHT when the part is anchored to edje group)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_right(void)
+{
+ Eina_Bool counterpart_is_set;
+
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ counterpart_is_set = current_anchors->left.set;
+
+ parse_anchor_line(&(current_anchors->right), EDJE_PART_ANCHOR_LINE_LEFT);
+
+ anchor_dequeue_part_lookup(&(current_desc->rel2.id_x), counterpart_is_set);
+ anchor_queue_part_lookup(&(current_desc->rel2.id_x), &(current_desc->rel1.id_x), counterpart_is_set);
+
+ anchor_adjust_align(&(current_desc->align.x), 1.0, &(current_desc->fixed.w), counterpart_is_set);
+ anchor_adjust_relative_horizontal(&(current_desc->rel2.relative_x), &(current_desc->rel1.relative_x), current_anchors->right.base.line, EDJE_PART_ANCHOR_LINE_RIGHT, counterpart_is_set);
+}
+
+/**
+ @page edcref
+ @property
+ vertical_center
+ @parameters
+ [partname] [TOP/BOTTOM/VERTICAL_CENTER]
+ @effect
+ Causes (virtual) vertical center line to be positioned to the edge of
+ another part's container. Setting to GROUP will indicate edje group instead
+ of another part.
+ This part will be expanded vertically in both directions, so do not
+ set top or bottom anchor with vertical_center anchor.
+ The second parameter of position enumeration can be omitted. (Default
+ value is VERTICAL_CENTER)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_vertical_center(void)
+{
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ parse_anchor_line(&(current_anchors->vertical_center), EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER);
+
+ anchor_queue_part_lookup(&(current_desc->rel1.id_y), &(current_desc->rel2.id_y), EINA_FALSE);
+
+ anchor_adjust_align(&(current_desc->align.y), 0.5, &(current_desc->fixed.h), EINA_FALSE);
+ anchor_adjust_relative_vertical(&(current_desc->rel1.relative_y), &(current_desc->rel2.relative_y), current_anchors->vertical_center.base.line, EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER, EINA_FALSE);
+}
+
+/**
+ @page edcref
+ @property
+ horizontal_center
+ @parameters
+ [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
+ @effect
+ Causes (virtual) horizontal center line to be positioned to the edge of
+ another part's container. Setting to GROUP will indicate edje group instead
+ of another part.
+ This part will be expanded horizontally in both directions, so do not
+ set left or right anchor with vertical_center anchor.
+ The second parameter of position enumeration can be omitted. (Default
+ value is HORIZONTAL_CENTER)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_horizontal_center(void)
+{
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ parse_anchor_line(&(current_anchors->horizontal_center), EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER);
+
+ anchor_queue_part_lookup(&(current_desc->rel1.id_x), &(current_desc->rel2.id_x), EINA_FALSE);
+
+ anchor_adjust_align(&(current_desc->align.x), 0.5, &(current_desc->fixed.w), EINA_FALSE);
+ anchor_adjust_relative_horizontal(&(current_desc->rel1.relative_x), &(current_desc->rel2.relative_x), current_anchors->horizontal_center.base.line, EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER, EINA_FALSE);
+}
+
+/**
+ @page edcref
+ @property
+ fill
+ @parameters
+ [partname] [BOTH/HORIZONTAL/VERTICAL]
+ @effect
+ Causes the part's container to expand to the width or height of another
+ part's container. Setting to GROUP will indicate edje group instead of another part.
+ Setting horizontal fill has same effect to setting top and bottom anchors
+ to the same part.
+ (setting vertical fill means left and right anchors to the same part)
+ The second parameter of direction enumeration can be omitted. (Default
+ value is BOTH)
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_fill(void)
+{
+ Edje_Part_Collection *pc;
+ char *name;
+
+ pc = eina_list_last_data_get(edje_collections);
+
+ check_has_relatives();
+
+ if (!current_anchors)
+ current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
+
+ parse_anchor_fill(&(current_anchors->fill));
+
+ name = parse_str(0);
+
+ switch (current_anchors->fill.base.fill)
+ {
+ case EDJE_PART_ANCHOR_FILL_BOTH:
+ if (strcmp("GROUP", name))
+ {
+ data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
+ data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
+ data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
+ data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
+ }
+ current_desc->align.x = 0.5;
+ current_desc->align.y = 0.5;
+ current_desc->fixed.w = 0;
+ current_desc->fixed.h = 0;
+ break;
+ case EDJE_PART_ANCHOR_FILL_HORIZONTAL:
+ if (strcmp("GROUP", name))
+ {
+ data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
+ data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
+ }
+ current_desc->align.x = 0.5;
+ current_desc->fixed.w = 0;
+ break;
+ case EDJE_PART_ANCHOR_FILL_VERTICAL:
+ if (strcmp("GROUP", name))
+ {
+ data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
+ data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
+ }
+ current_desc->align.y = 0.5;
+ current_desc->fixed.h = 0;
+ break;
+ }
+
+ free(name);
+}
+
+/**
+ @page edcref
+ @property
+ margin
+ @parameters
+ [left] [right] [top] [bottom]
+ @effect
+ Affects the edge position a fixed number of pixels along each direction.
+ Margins will scale its size with an edje scaling factor.
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_anchors_margin(void)
+{
+ check_has_relatives();
+ check_arg_count(4);
+
+ current_desc->rel1.offset_x = parse_int(0);
+ current_desc->rel2.offset_x = -parse_int(1) - 1;
+ current_desc->rel1.offset_y = parse_int(2);
+ current_desc->rel2.offset_y = -parse_int(3) - 1;
+}
+
+static void
+free_anchors(void)
+{
+ has_relatives = EINA_FALSE;
+
+ if (!current_anchors) return;
+
+ free(current_anchors);
+ current_anchors = NULL;
+}
+
/** @edcsubsection{collections_group_parts_description_image,
* Group.Parts.Part.Description.Image} */
@@ -15154,6 +15753,8 @@ edje_cc_handlers_pop_notify(const char *token)
current_program = NULL;
else if (current_de && (!strcmp(token, "group")))
_link_combine();
+ else if (current_desc && (!strcmp(token, "description")))
+ free_anchors();
}
static void
diff --git a/src/examples/edje/edje-anchors.c b/src/examples/edje/edje-anchors.c
new file mode 100644
index 0000000000..135f0abc31
--- /dev/null
+++ b/src/examples/edje/edje-anchors.c
@@ -0,0 +1,58 @@
+/**
+ * Simple Edje example for layouting parts with anchors.
+ *
+ * You'll need at least one Evas engine built for it (excluding the
+ * buffer one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * edje_cc edje-anchors.edc && gcc -o edje-anchors edje-anchors.c `pkg-config --libs --cflags evas ecore ecore-evas edje`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# define EINA_UNUSED
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+#include <libgen.h>
+
+#define WIDTH 400
+#define HEIGHT 400
+
+int
+main(int argc, char **argv)
+{
+ char path[PATH_MAX] = { 0, };
+
+ ecore_init();
+ ecore_evas_init();
+ edje_init();
+
+ Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ Evas *e = ecore_evas_get(ee);
+ ecore_evas_show(ee);
+
+ Evas_Object *bg = evas_object_rectangle_add(e);
+ evas_object_color_set(bg, 64, 64, 64, 255);
+ evas_object_resize(bg, WIDTH, HEIGHT);
+ evas_object_show(bg);
+
+ snprintf(path, sizeof(path), "%s/edje-anchors.edj", dirname(*argv));
+
+ Evas_Object *edje = edje_object_add(e);
+ edje_object_file_set(edje, path, "main");
+ evas_object_resize(edje, WIDTH, HEIGHT);
+ evas_object_show(edje);
+
+ ecore_main_loop_begin();
+
+ edje_shutdown();
+ ecore_evas_shutdown();
+ ecore_shutdown();
+
+ return 0;
+}
diff --git a/src/examples/edje/edje-anchors.edc b/src/examples/edje/edje-anchors.edc
new file mode 100644
index 0000000000..2d3d485e9f
--- /dev/null
+++ b/src/examples/edje/edje-anchors.edc
@@ -0,0 +1,58 @@
+collections {
+ group { "main";
+ parts {
+ rect { "rect1";
+ desc {
+ anchors.top: GROUP TOP;
+ anchors.left: GROUP; // anchors.left: GROUP LEFT;
+ color: "#f00";
+ min: 50 50;
+ }
+ }
+ rect { "rect2";
+ desc {
+ anchors.top: "rect1" BOTTOM;
+ anchors.left: "rect1" RIGHT;
+ color: "#00f";
+ min: 50 50;
+ }
+ }
+ rect { "rect3";
+ desc {
+ anchors.left: "rect2"; // anchors.left: "rect1" RIGHT;
+ anchors.fill: "rect2" VERTICAL;
+ anchors.margin: 20 0 0 0;
+ color: "#0f0";
+ min: 100 0;
+ }
+ }
+ rect { "rect4";
+ desc {
+ anchors {
+ top: "rect3";
+ left: "rect3";
+ right: GROUP;
+ bottom: GROUP;
+ margin: 0 10 0 50;
+ }
+ }
+ }
+ rect { "rect5";
+ desc {
+ anchors.vertical_center: "rect4";
+ anchors.fill: "rect4" HORIZONTAL;
+ min: 0 50;
+ color: "#000";
+ }
+ }
+ rect { "rect6";
+ desc {
+ anchors.right: "rect5" HORIZONTAL_CENTER;
+ anchors.fill: "rect5" VERTICAL;
+ min: 30 0;
+ color: "#ff0";
+ }
+ }
+ }
+ }
+}
diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c
index bf0d809c5a..37163c3a14 100644
--- a/src/lib/edje/edje_calc.c
+++ b/src/lib/edje/edje_calc.c
@@ -1114,42 +1114,71 @@ _edje_part_recalc_single_rel(Edje *ed,
{
FLOAT_T x, w;
FLOAT_T y, h;
+ FLOAT_T offset, sc;
+ Eina_Bool offset_is_scaled = (desc->offset_is_scaled) && (ep->part->scale);
+
+ if (offset_is_scaled)
+ {
+ sc = DIV(ed->scale, ed->file->base_scale);
+ if (EQ(sc, ZERO)) sc = DIV(_edje_scale, ed->file->base_scale);
+ }
+
+ if (offset_is_scaled)
+ offset = SCALE(sc, desc->rel1.offset_x);
+ else
+ offset = FROM_INT(desc->rel1.offset_x);
if (rel1_to_x)
- x = ADD(FROM_INT(desc->rel1.offset_x + rel1_to_x->x),
+ x = ADD(ADD(offset, FROM_INT(rel1_to_x->x)),
SCALE(desc->rel1.relative_x, rel1_to_x->w));
else
- x = ADD(FROM_INT(desc->rel1.offset_x),
+ x = ADD(offset,
SCALE(desc->rel1.relative_x, ed->w));
params->eval.x = x;
+ if (offset_is_scaled)
+ offset = SUB(SCALE(sc, desc->rel2.offset_x + 1), FROM_INT(1));
+ else
+ offset = FROM_INT(desc->rel2.offset_x);
+
if (rel2_to_x)
- w = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_x + rel2_to_x->x),
+ w = ADD(SUB(ADD(ADD(offset, FROM_INT(rel2_to_x->x)),
SCALE(desc->rel2.relative_x, rel2_to_x->w)),
x),
FROM_INT(1));
else
- w = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_x),
+ w = ADD(SUB(ADD(offset,
SCALE(desc->rel2.relative_x, ed->w)),
x),
FROM_INT(1));
params->eval.w = w;
+
+ if (offset_is_scaled)
+ offset = SCALE(sc, desc->rel1.offset_y);
+ else
+ offset = FROM_INT(desc->rel1.offset_y);
+
if (rel1_to_y)
- y = ADD(FROM_INT(desc->rel1.offset_y + rel1_to_y->y),
+ y = ADD(ADD(offset, FROM_INT(rel1_to_y->y)),
SCALE(desc->rel1.relative_y, rel1_to_y->h));
else
- y = ADD(FROM_INT(desc->rel1.offset_y),
+ y = ADD(offset,
SCALE(desc->rel1.relative_y, ed->h));
params->eval.y = y;
+ if (offset_is_scaled)
+ offset = SUB(SCALE(sc, desc->rel2.offset_y + 1), FROM_INT(1));
+ else
+ offset = FROM_INT(desc->rel2.offset_y);
+
if (rel2_to_y)
- h = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_y + rel2_to_y->y),
+ h = ADD(SUB(ADD(ADD(offset, FROM_INT(rel2_to_y->y)),
SCALE(desc->rel2.relative_y, rel2_to_y->h)),
y),
FROM_INT(1));
else
- h = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_y),
+ h = ADD(SUB(ADD(offset,
SCALE(desc->rel2.relative_y, ed->h)),
y),
FROM_INT(1));
@@ -4577,6 +4606,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
rp1[Rel2X], rp1[Rel2Y], clip1, confine_to,
threshold, p1, mmw, mmh,
pos);
+
#ifdef EDJE_CALC_CACHE
if (flags == FLAG_XY) ep->param1.state = ed->state;
#endif
@@ -4622,6 +4652,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
rp2[Rel2X], rp2[Rel2Y], clip2, confine_to,
threshold, p2, mmw, mmh,
pos);
+
#ifdef EDJE_CALC_CACHE
if (flags == FLAG_XY) ep->param2->state = ed->state;
#endif
@@ -4705,7 +4736,6 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta
p3->smooth = (beginning_pos) ? p1->smooth : p2->smooth;
/* FIXME: do x and y separately base on flag */
-
p3->final.x = INTP(p1->final.x, p2->final.x, pos);
p3->final.y = INTP(p1->final.y, p2->final.y, pos);
p3->final.w = INTP(p1->final.w, p2->final.w, pos);
diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c
index e6d2fbb081..5e3ffe5bb4 100644
--- a/src/lib/edje/edje_data.c
+++ b/src/lib/edje/edje_data.c
@@ -1217,7 +1217,8 @@ _edje_edd_init(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.zoom.x", map.zoom.x, EDJE_T_FLOAT); \
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.zoom.y", map.zoom.y, EDJE_T_FLOAT); \
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "persp.zplane", persp.zplane, EET_T_INT); \
- EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "persp.focal", persp.focal, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "persp.focal", persp.focal, EET_T_INT); \
+ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "offset_is_scaled", offset_is_scaled, EET_T_UCHAR);
#ifdef HAVE_EPHYSICS
#define EDJE_DATA_DESCRIPTOR_DESCRIPTION_COMMON(Edd, Type) \
@@ -1311,6 +1312,7 @@ _edje_edd_init(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.zoom.y", Dec.map.zoom.y, EDJE_T_FLOAT); \
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "persp.zplane", Dec.persp.zplane, EET_T_INT); \
EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "persp.focal", Dec.persp.focal, EET_T_INT); \
+ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "offset_is_scaled", Dec.offset_is_scaled, EET_T_UCHAR);
#ifdef HAVE_EPHYSICS
#define EDJE_DATA_DESCRIPTOR_DESCRIPTION_COMMON_SUB(Edd, Type, Dec) \
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index b5cd5543d3..94c994a9a7 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -1330,9 +1330,11 @@ struct _Edje_Part_Description_Common
#endif
Edje_3D_Vec align_3d;
+
unsigned char visible; /* is it shown */
unsigned char limit; /* 0 == no, 1 = width, 2 = height, 3 = both */
unsigned char no_render; /* no_render override @since 1.19 */
+ unsigned char offset_is_scaled;
};
struct _Edje_Part_Description_Spec_Fill