2017-08-29 03:04:15 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "elementary_config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define ELM_LAYOUT_PROTECTED
|
|
|
|
|
|
|
|
#include <Elementary.h>
|
|
|
|
#include "elm_priv.h"
|
|
|
|
|
|
|
|
#include "elm_widget_layout.h"
|
edje/elm: Rename _internal_ to _part_ (EO)
In Edje and Elementary, we have part objects, which are what is returned
by the interface efl_part(). Those objects can't be of an opaque type as
this doesn't work nicely with strongly typed languages such as C++ or
C#. In JS, Lua, C the types are weak and mostly runtime-based so it
doesn't matter much.
As a consequence, the documentation and the types need to look nice in
this EO API. Thus, we remove the abusive term "internal" and explicitly
call all those classes "part" something.
Eventually we want the types to be declared in the EO file so bindings
(C#, C++, ...) can generate the proper access methods, returning the
best possible types.
Note that right now a few of those part types are used in the legacy API
but don't actually need to be exposed externally.
This is kind of a mega commit that does all the renaming at once, but
it's really just a big sed operation. The power of good IDEs :)
Ref T5315
Ref T5306
2017-09-12 21:29:25 -07:00
|
|
|
#include "efl_ui_textpath_part.eo.h"
|
2017-08-29 03:04:15 -07:00
|
|
|
#include "elm_part_helper.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define MY_CLASS EFL_UI_TEXTPATH_CLASS
|
|
|
|
#define MY_CLASS_NAME "Efl.Ui.Textpath"
|
|
|
|
|
|
|
|
#define SLICE_DEFAULT_NO 99
|
|
|
|
|
|
|
|
typedef struct _Efl_Ui_Textpath_Point Efl_Ui_Textpath_Point;
|
|
|
|
typedef struct _Efl_Ui_Textpath_Line Efl_Ui_Textpath_Line;
|
|
|
|
typedef struct _Efl_Ui_Textpath_Segment Efl_Ui_Textpath_Segment;
|
|
|
|
typedef struct _Efl_Ui_Textpath_Data Efl_Ui_Textpath_Data;
|
|
|
|
|
|
|
|
struct _Efl_Ui_Textpath_Point
|
|
|
|
{
|
|
|
|
double x;
|
|
|
|
double y;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Efl_Ui_Textpath_Line
|
|
|
|
{
|
|
|
|
Efl_Ui_Textpath_Point start;
|
|
|
|
Efl_Ui_Textpath_Point end;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Efl_Ui_Textpath_Segment
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
int length;
|
|
|
|
Efl_Gfx_Path_Command_Type type;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
Eina_Bezier bezier;
|
|
|
|
Efl_Ui_Textpath_Line line;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Efl_Ui_Textpath_Data
|
|
|
|
{
|
|
|
|
Evas_Object *text_obj;
|
|
|
|
char *text;
|
|
|
|
Efl_Gfx_Path *path;
|
|
|
|
struct {
|
|
|
|
double x, y;
|
|
|
|
double radius;
|
|
|
|
double start_angle;
|
|
|
|
} circle;
|
|
|
|
Efl_Ui_Textpath_Direction direction;
|
|
|
|
int slice_no;
|
|
|
|
Eina_Bool autofit;
|
|
|
|
Eina_Bool ellipsis;
|
|
|
|
|
|
|
|
Eina_Inlist *segments;
|
|
|
|
int total_length;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define EFL_UI_TEXTPATH_DATA_GET(o, sd) \
|
|
|
|
Efl_Ui_Textpath_Data *sd = efl_data_scope_get(o, EFL_UI_TEXTPATH_CLASS)
|
|
|
|
|
|
|
|
static inline double
|
|
|
|
_deg_to_rad(double angle)
|
|
|
|
{
|
|
|
|
return angle / 180 * M_PI;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_segment_draw(Efl_Ui_Textpath_Data *pd, int slice_no, int w1, int w2, int cmp, Evas_Map *map, Eina_Bezier bezier)
|
|
|
|
{
|
|
|
|
int i, len, seg_len;
|
|
|
|
double u0, u1, v0, v1;
|
|
|
|
double dist, t, dt;
|
|
|
|
double px, py, px2, py2;
|
|
|
|
double rad;
|
2017-10-17 18:51:04 -07:00
|
|
|
Eina_Rect r;
|
2017-08-29 03:04:15 -07:00
|
|
|
Eina_Vector2 vec, nvec, vec0, vec1, vec2, vec3;
|
|
|
|
Eina_Matrix2 mat;
|
|
|
|
|
|
|
|
len = w2 - w1;
|
2017-10-17 18:51:04 -07:00
|
|
|
r = efl_gfx_geometry_get(pd->text_obj);
|
|
|
|
|
2017-08-29 03:04:15 -07:00
|
|
|
seg_len = eina_bezier_length_get(&bezier);
|
|
|
|
if (pd->autofit)
|
|
|
|
dt = len / (seg_len * (double) slice_no);
|
|
|
|
else
|
|
|
|
dt = 1.0 / (double) slice_no;
|
|
|
|
dist = len / (double)slice_no;
|
|
|
|
rad = _deg_to_rad(90);
|
|
|
|
eina_matrix2_values_set(&mat, cos(rad), -sin(rad), sin(rad), cos(rad));
|
|
|
|
|
|
|
|
eina_bezier_values_get(&bezier, NULL, NULL, NULL, NULL, NULL, NULL, &px2, &py2);
|
|
|
|
t = 0;
|
|
|
|
eina_bezier_point_at(&bezier, t, &px, &py);
|
|
|
|
eina_bezier_point_at(&bezier, t + dt, &px2, &py2);
|
|
|
|
|
|
|
|
vec.x = (px2 - px);
|
|
|
|
vec.y = (py2 - py);
|
|
|
|
eina_vector2_normalize(&nvec, &vec);
|
|
|
|
|
|
|
|
eina_vector2_transform(&vec, &mat, &nvec);
|
|
|
|
eina_vector2_normalize(&nvec, &vec);
|
2017-10-17 18:51:04 -07:00
|
|
|
eina_vector2_scale(&vec, &nvec, ((double) r.h) * 0.5);
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
vec1.x = (vec.x + px);
|
|
|
|
vec1.y = (vec.y + py);
|
|
|
|
vec2.x = (-vec.x + px);
|
|
|
|
vec2.y = (-vec.y + py);
|
|
|
|
|
|
|
|
//add points to map
|
|
|
|
for (i = 0; i < slice_no; i++)
|
|
|
|
{
|
|
|
|
//v0, v3
|
|
|
|
vec0.x = vec1.x;
|
|
|
|
vec0.y = vec1.y;
|
|
|
|
vec3.x = vec2.x;
|
|
|
|
vec3.y = vec2.y;
|
|
|
|
|
|
|
|
//v1, v2
|
|
|
|
t = ((double) (i + 1) * dt);
|
|
|
|
eina_bezier_point_at(&bezier, t, &px, &py);
|
|
|
|
eina_bezier_point_at(&bezier, t + dt, &px2, &py2);
|
|
|
|
|
|
|
|
vec.x = (px2 - px);
|
|
|
|
vec.y = (py2 - py);
|
|
|
|
eina_vector2_normalize(&nvec, &vec);
|
|
|
|
eina_vector2_transform(&vec, &mat, &nvec);
|
|
|
|
eina_vector2_normalize(&nvec, &vec);
|
2017-10-17 18:51:04 -07:00
|
|
|
eina_vector2_scale(&vec, &nvec, ((double) r.h) * 0.5);
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
vec1.x = (vec.x + px);
|
|
|
|
vec1.y = (vec.y + py);
|
|
|
|
vec2.x = (-vec.x + px);
|
|
|
|
vec2.y = (-vec.y + py);
|
|
|
|
|
2017-10-17 18:51:04 -07:00
|
|
|
evas_map_point_coord_set(map, cmp + i * 4, (int) vec0.x + r.x, (int) vec0.y + r.y, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + i * 4 + 1, (int) vec1.x + r.x, (int) vec1.y + r.y, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + i * 4 + 2, (int) vec2.x + r.x, (int) vec2.y + r.y, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + i * 4 + 3, (int) vec3.x + r.x, (int) vec3.y + r.y, 0);
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
//UV
|
|
|
|
u0 = w1 + i * dist;
|
|
|
|
u1 = u0 + dist;
|
|
|
|
v0 = (double) 0;
|
2017-10-17 18:51:04 -07:00
|
|
|
v1 = (double) r.h;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
evas_map_point_image_uv_set(map, cmp + i * 4, u0, v0);
|
|
|
|
evas_map_point_image_uv_set(map, cmp + i * 4 + 1, u1, v0);
|
|
|
|
evas_map_point_image_uv_set(map, cmp + i * 4 + 2, u1, v1);
|
|
|
|
evas_map_point_image_uv_set(map, cmp + i * 4 + 3, u0, v1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_text_on_line_draw(Efl_Ui_Textpath_Data *pd, int w1, int w2, int cmp, Evas_Map *map, Efl_Ui_Textpath_Line line)
|
|
|
|
{
|
|
|
|
double x1, x2, y1, y2;
|
|
|
|
double line_len, len, sina, cosa;
|
2017-09-13 19:59:44 -07:00
|
|
|
Eina_Rect r;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
x1 = line.start.x;
|
|
|
|
y1 = line.start.y;
|
|
|
|
x2 = line.end.x;
|
|
|
|
y2 = line.end.y;
|
|
|
|
|
|
|
|
line_len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
|
|
|
|
len = w2 - w1;
|
|
|
|
if (line_len > len)
|
|
|
|
{
|
|
|
|
x2 = x1 + len * (x2 - x1) / line_len;
|
|
|
|
y2 = y1 + len * (y2 - y1) / line_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
|
|
|
|
sina = (y2 - y1) / len;
|
|
|
|
cosa = (x2 - x1) / len;
|
|
|
|
|
2017-09-13 00:49:04 -07:00
|
|
|
r = efl_gfx_geometry_get(pd->text_obj);
|
|
|
|
r.h /= 2;
|
|
|
|
evas_map_point_coord_set(map, cmp + 3, x1 - r.h * sina, y1 + r.h * cosa, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + 2, x2 - r.h * sina, y2 + r.h * cosa, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + 1, x2 + r.h * sina, y2 - r.h * cosa, 0);
|
|
|
|
evas_map_point_coord_set(map, cmp + 0, x1 + r.h * sina, y1 - r.h * cosa, 0);
|
2017-08-29 03:04:15 -07:00
|
|
|
|
2017-09-13 00:49:04 -07:00
|
|
|
r.h *= 2;
|
2017-08-29 03:04:15 -07:00
|
|
|
evas_map_point_image_uv_set(map, cmp + 0, w1, 0);
|
|
|
|
evas_map_point_image_uv_set(map, cmp + 1, w2, 0);
|
2017-09-13 00:49:04 -07:00
|
|
|
evas_map_point_image_uv_set(map, cmp + 2, w2, r.h);
|
|
|
|
evas_map_point_image_uv_set(map, cmp + 3, w1, r.h);
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_map_point_calc(Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
int map_no = 0;
|
|
|
|
Efl_Ui_Textpath_Segment *seg;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(pd->segments, seg)
|
|
|
|
{
|
|
|
|
if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
|
|
|
|
{
|
|
|
|
map_no++;
|
|
|
|
}
|
|
|
|
else if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO)
|
|
|
|
{
|
|
|
|
int no = pd->slice_no * seg->length / (double)pd->total_length;
|
2017-09-04 22:19:59 -07:00
|
|
|
if (no == 0) no = 1;
|
2017-08-29 03:04:15 -07:00
|
|
|
map_no += no;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
map_no *= 4;
|
|
|
|
|
|
|
|
return map_no;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_text_draw(Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
Efl_Ui_Textpath_Segment *seg;
|
|
|
|
Evas_Map *map;
|
2017-09-28 22:52:04 -07:00
|
|
|
double slice_unit;
|
2017-09-15 02:37:25 -07:00
|
|
|
int w1, w2;
|
2017-08-29 03:04:15 -07:00
|
|
|
int remained_w;
|
2017-09-28 20:32:10 -07:00
|
|
|
int drawn_slice = 0;
|
2017-08-29 03:04:15 -07:00
|
|
|
int cur_map_point = 0, map_point_no;
|
2017-09-15 02:37:25 -07:00
|
|
|
Eina_Size2D sz;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
2017-09-15 02:37:25 -07:00
|
|
|
sz = efl_gfx_size_get(pd->text_obj);
|
2017-08-29 03:04:15 -07:00
|
|
|
if (pd->autofit)
|
2017-09-15 02:37:25 -07:00
|
|
|
remained_w = sz.w;
|
2017-08-29 03:04:15 -07:00
|
|
|
else
|
|
|
|
remained_w = pd->total_length;
|
|
|
|
slice_unit = (double)pd->slice_no / pd->total_length;
|
|
|
|
|
|
|
|
map_point_no = _map_point_calc(pd);
|
|
|
|
if (map_point_no == 0)
|
|
|
|
{
|
|
|
|
evas_object_map_enable_set(pd->text_obj, EINA_FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
map = evas_map_new(map_point_no);
|
|
|
|
|
|
|
|
w1 = w2 = 0;
|
|
|
|
EINA_INLIST_FOREACH(pd->segments, seg)
|
|
|
|
{
|
|
|
|
int len = seg->length;
|
|
|
|
if (!pd->autofit)
|
2017-09-15 02:37:25 -07:00
|
|
|
len = (double)seg->length * sz.w / (double)pd->total_length;
|
2017-08-29 03:04:15 -07:00
|
|
|
if (remained_w <= 0)
|
|
|
|
break;
|
|
|
|
w2 = w1 + len;
|
2017-09-15 02:37:25 -07:00
|
|
|
if (w2 > sz.w)
|
|
|
|
w2 = sz.w;
|
2017-08-29 03:04:15 -07:00
|
|
|
if (seg->type == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
|
|
|
|
{
|
|
|
|
drawn_slice += 1;
|
|
|
|
_text_on_line_draw(pd, w1, w2, cur_map_point, map, seg->line);
|
|
|
|
cur_map_point += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int slice_no;
|
|
|
|
slice_no = pd->slice_no * seg->length / (double)pd->total_length;
|
|
|
|
if (slice_no == 0)
|
|
|
|
slice_no = len * slice_unit + 1;
|
|
|
|
drawn_slice += slice_no;
|
|
|
|
_segment_draw(pd, slice_no, w1, w2, cur_map_point, map, seg->bezier);
|
|
|
|
cur_map_point += slice_no * 4;
|
|
|
|
}
|
|
|
|
w1 = w2;
|
|
|
|
remained_w -= len;
|
|
|
|
}
|
|
|
|
evas_object_map_enable_set(pd->text_obj, EINA_TRUE);
|
|
|
|
evas_object_map_set(pd->text_obj, map);
|
|
|
|
evas_map_free(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_path_data_get(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Bool set_min)
|
|
|
|
{
|
|
|
|
const Efl_Gfx_Path_Command_Type *cmd;
|
|
|
|
const double *points;
|
|
|
|
Efl_Ui_Textpath_Segment *seg;
|
2017-09-14 20:14:32 -07:00
|
|
|
Eina_Position2D opos;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
EINA_INLIST_FREE(pd->segments, seg)
|
|
|
|
{
|
|
|
|
pd->segments = eina_inlist_remove(pd->segments, EINA_INLIST_GET(seg));
|
|
|
|
free(seg);
|
|
|
|
}
|
|
|
|
|
2017-09-14 20:14:32 -07:00
|
|
|
opos = efl_gfx_position_get(obj);
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
pd->total_length = 0;
|
|
|
|
efl_gfx_path_get(obj, &cmd, &points);
|
|
|
|
if (cmd)
|
|
|
|
{
|
|
|
|
int pos = -1;
|
2017-09-04 19:55:07 -07:00
|
|
|
double px0 = 0.0, py0 = 0.0, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1, px1, py1;
|
2017-09-14 20:14:32 -07:00
|
|
|
Eina_Rect rect = EINA_RECT_ZERO();
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
while (*cmd != EFL_GFX_PATH_COMMAND_TYPE_END)
|
|
|
|
{
|
|
|
|
if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
|
|
|
|
{
|
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
px0 = points[pos] + opos.x;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
py0 = points[pos] + opos.y;
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
else if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO)
|
|
|
|
{
|
|
|
|
Eina_Bezier bz;
|
|
|
|
double bx, by, bw, bh;
|
2017-09-14 20:14:32 -07:00
|
|
|
Eina_Rect brect;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
ctrl_x0 = points[pos] + opos.x;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
ctrl_y0 = points[pos] + opos.y;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
ctrl_x1 = points[pos] + opos.x;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
ctrl_y1 = points[pos] + opos.y;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
px1 = points[pos] + opos.x;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
py1 = points[pos] + opos.y;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
eina_bezier_values_set(&bz, px0, py0, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1, px1, py1);
|
|
|
|
seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
|
|
|
|
if (!seg)
|
|
|
|
{
|
|
|
|
ERR("Failed to allocate segment");
|
|
|
|
px0 = px1;
|
|
|
|
py0 = py1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
seg->length = eina_bezier_length_get(&bz);
|
|
|
|
seg->bezier = bz;
|
|
|
|
seg->type = EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO;
|
|
|
|
pd->segments = eina_inlist_append(pd->segments, EINA_INLIST_GET(seg));
|
|
|
|
pd->total_length += seg->length;
|
|
|
|
|
|
|
|
//move points
|
|
|
|
px0 = px1;
|
|
|
|
py0 = py1;
|
|
|
|
|
|
|
|
eina_bezier_bounds_get(&bz, &bx, &by, &bw, &bh);
|
2017-09-14 20:14:32 -07:00
|
|
|
brect = EINA_RECT(bx, by, bw, bh);
|
|
|
|
eina_rectangle_union(&rect.rect, &brect.rect);
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
else if (*cmd == EFL_GFX_PATH_COMMAND_TYPE_LINE_TO)
|
|
|
|
{
|
2017-09-14 20:14:32 -07:00
|
|
|
Eina_Rect lrect;
|
2017-09-04 19:55:07 -07:00
|
|
|
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
px1 = points[pos] + opos.x;
|
2017-08-29 03:04:15 -07:00
|
|
|
pos++;
|
2017-09-14 20:14:32 -07:00
|
|
|
py1 = points[pos] + opos.y;
|
2017-08-29 03:04:15 -07:00
|
|
|
|
|
|
|
seg = malloc(sizeof(Efl_Ui_Textpath_Segment));
|
|
|
|
if (!seg)
|
|
|
|
{
|
|
|
|
ERR("Failed to allocate segment");
|
|
|
|
px0 = px1;
|
|
|
|
py0 = py1;
|
2017-09-04 20:02:01 -07:00
|
|
|
continue;
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
seg->type = EFL_GFX_PATH_COMMAND_TYPE_LINE_TO;
|
|
|
|
seg->line.start.x = px0;
|
|
|
|
seg->line.start.y = py0;
|
|
|
|
seg->line.end.x = px1;
|
|
|
|
seg->line.end.y = py1;
|
|
|
|
seg->length = sqrt((px1 - px0)*(px1 - px0) + (py1 - py0)*(py1 - py0));
|
|
|
|
pd->segments = eina_inlist_append(pd->segments, EINA_INLIST_GET(seg));
|
|
|
|
pd->total_length += seg->length;
|
|
|
|
|
2017-09-14 20:14:32 -07:00
|
|
|
lrect = EINA_RECT(px0, py0, px1 - px0, py1 - py0);
|
|
|
|
eina_rectangle_union(&rect.rect, &lrect.rect);
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
cmd++;
|
|
|
|
}
|
|
|
|
if (set_min)
|
|
|
|
{
|
2017-09-17 22:35:22 -07:00
|
|
|
efl_gfx_size_hint_min_set(obj, rect.size);
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_sizing_eval(Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
_text_draw(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_textpath_ellipsis_set(Efl_Ui_Textpath_Data *pd, Eina_Bool enabled)
|
|
|
|
{
|
|
|
|
edje_object_part_text_style_user_pop(pd->text_obj, "elm.text");
|
2017-09-27 17:16:02 -07:00
|
|
|
|
2017-08-29 03:04:15 -07:00
|
|
|
if (enabled)
|
2017-09-27 17:16:02 -07:00
|
|
|
edje_object_part_text_style_user_push(pd->text_obj, "elm.text",
|
|
|
|
"DEFAULT='ellipsis=1.0'");
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ellipsis_set(Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
if (!pd->text_obj) return;
|
|
|
|
|
|
|
|
Evas_Coord w = 0, h = 0;
|
|
|
|
Eina_Bool is_ellipsis = EINA_FALSE;
|
|
|
|
const Evas_Object *tb;
|
|
|
|
|
|
|
|
tb = edje_object_part_object_get(pd->text_obj, "elm.text");
|
|
|
|
evas_object_textblock_size_native_get(tb, &w, &h);
|
|
|
|
evas_object_size_hint_min_set(pd->text_obj, w, h);
|
|
|
|
if (pd->ellipsis)
|
|
|
|
{
|
|
|
|
if (w > pd->total_length)
|
|
|
|
{
|
|
|
|
is_ellipsis = EINA_TRUE;
|
|
|
|
w = pd->total_length;
|
|
|
|
}
|
|
|
|
}
|
2017-09-15 02:37:25 -07:00
|
|
|
efl_gfx_size_set(pd->text_obj, EINA_SIZE2D(w, h));
|
2017-08-29 03:04:15 -07:00
|
|
|
_textpath_ellipsis_set(pd, is_ellipsis);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_path_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
EFL_UI_TEXTPATH_DATA_GET(data, sd);
|
|
|
|
|
|
|
|
_path_data_get(data, sd, EINA_TRUE);
|
|
|
|
_sizing_eval(sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_textpath_text_set_internal(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part, const char *text)
|
|
|
|
{
|
|
|
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
|
|
|
|
Eina_Bool ret = EINA_TRUE;
|
|
|
|
|
|
|
|
if (!text) text = "";
|
|
|
|
ret = edje_object_part_text_set(pd->text_obj, part, text);
|
|
|
|
_ellipsis_set(pd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
_sizing_eval(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Textpath_Data *priv)
|
|
|
|
{
|
|
|
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
|
|
|
|
|
|
|
|
efl_canvas_group_add(efl_super(obj, MY_CLASS));
|
|
|
|
elm_widget_sub_object_parent_add(obj);
|
|
|
|
|
|
|
|
priv->text_obj = edje_object_add(evas_object_evas_get(obj));
|
|
|
|
elm_widget_theme_object_set(obj, priv->text_obj, "textpath", "base",
|
|
|
|
elm_widget_style_get(obj));
|
|
|
|
efl_gfx_size_hint_weight_set(priv->text_obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
|
|
efl_gfx_size_hint_align_set(priv->text_obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
|
|
efl_gfx_visible_set(priv->text_obj, EINA_TRUE);
|
|
|
|
|
|
|
|
evas_object_smart_member_add(priv->text_obj, obj);
|
|
|
|
elm_widget_sub_object_add(obj, priv->text_obj);
|
|
|
|
|
|
|
|
efl_event_callback_add(obj, EFL_GFX_PATH_EVENT_CHANGED, _path_changed_cb, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Efl_Object *
|
|
|
|
_efl_ui_textpath_efl_object_constructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
|
|
|
pd->autofit = EINA_TRUE;
|
|
|
|
pd->slice_no = SLICE_DEFAULT_NO;
|
|
|
|
pd->direction = EFL_UI_TEXTPATH_DIRECTION_CW;
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_efl_object_destructor(Eo *obj, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
Efl_Ui_Textpath_Segment *seg;
|
|
|
|
|
|
|
|
if (pd->text) free(pd->text);
|
|
|
|
if (pd->text_obj) evas_object_del(pd->text_obj);
|
|
|
|
EINA_INLIST_FREE(pd->segments, seg)
|
|
|
|
{
|
|
|
|
pd->segments = eina_inlist_remove(pd->segments, EINA_INLIST_GET(seg));
|
|
|
|
free(seg);
|
|
|
|
}
|
|
|
|
|
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_ui_textpath_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *part, const char *text)
|
|
|
|
{
|
|
|
|
return _textpath_text_set_internal(obj, pd, part, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const char *
|
|
|
|
_efl_ui_textpath_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, const char *part)
|
|
|
|
{
|
|
|
|
return edje_object_part_text_get(pd->text_obj, part);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_efl_text_text_set(Eo *obj, Efl_Ui_Textpath_Data *pd, const char *text)
|
|
|
|
{
|
|
|
|
_textpath_text_set_internal(obj, pd, "elm.text", text);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const char *
|
|
|
|
_efl_ui_textpath_efl_text_text_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
return edje_object_part_text_get(pd->text_obj, "elm.text");
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Efl_Ui_Theme_Apply
|
|
|
|
_efl_ui_textpath_elm_widget_theme_apply(Eo *obj, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
Efl_Ui_Theme_Apply ret = EFL_UI_THEME_APPLY_FAILED;
|
|
|
|
|
2017-10-23 22:03:46 -07:00
|
|
|
ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
|
2017-08-29 03:04:15 -07:00
|
|
|
if (!ret) return EFL_UI_THEME_APPLY_FAILED;
|
|
|
|
|
|
|
|
elm_widget_theme_object_set(obj, pd->text_obj, "textpath", "base",
|
|
|
|
elm_widget_style_get(obj));
|
|
|
|
_ellipsis_set(pd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2017-09-14 20:14:32 -07:00
|
|
|
_efl_ui_textpath_efl_gfx_position_set(Eo *obj, Efl_Ui_Textpath_Data *pd, Eina_Position2D pos)
|
2017-08-29 03:04:15 -07:00
|
|
|
{
|
2017-09-14 20:14:32 -07:00
|
|
|
efl_gfx_position_set(efl_super(obj, MY_CLASS), pos);
|
2017-08-29 03:04:15 -07:00
|
|
|
_path_data_get(obj, pd, EINA_FALSE);
|
|
|
|
_text_draw(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2017-09-15 02:37:25 -07:00
|
|
|
_efl_ui_textpath_efl_gfx_size_set(Eo *obj, Efl_Ui_Textpath_Data *pd EINA_UNUSED, Eina_Size2D sz)
|
2017-08-29 03:04:15 -07:00
|
|
|
{
|
2017-09-15 02:37:25 -07:00
|
|
|
efl_gfx_size_set(efl_super(obj, MY_CLASS), sz);
|
2017-08-29 03:04:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_circle_set(Eo *obj, Efl_Ui_Textpath_Data *pd, double x, double y, double radius, double start_angle, Efl_Ui_Textpath_Direction direction)
|
|
|
|
{
|
|
|
|
if (pd->circle.x == x && pd->circle.y == y &&
|
|
|
|
pd->circle.radius == radius &&
|
|
|
|
pd->circle.start_angle == start_angle &&
|
|
|
|
pd->direction == direction &&
|
|
|
|
_map_point_calc(pd) > 0)
|
|
|
|
{
|
|
|
|
ERR("Same circle");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pd->circle.x = x;
|
|
|
|
pd->circle.y = y;
|
|
|
|
pd->circle.radius = radius;
|
|
|
|
pd->circle.start_angle = start_angle;
|
|
|
|
pd->direction = direction;
|
|
|
|
|
|
|
|
efl_gfx_path_reset(obj);
|
|
|
|
if (direction == EFL_UI_TEXTPATH_DIRECTION_CW)
|
|
|
|
{
|
|
|
|
efl_gfx_path_append_arc(obj, x - radius, y - radius, radius * 2,
|
|
|
|
radius * 2, start_angle, -360);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
efl_gfx_path_append_arc(obj, x - radius, y - radius, radius * 2,
|
|
|
|
radius * 2, start_angle, 360);
|
|
|
|
}
|
|
|
|
|
|
|
|
_sizing_eval(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_ui_textpath_autofit_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
return pd->autofit;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_autofit_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Eina_Bool autofit)
|
|
|
|
{
|
|
|
|
if (pd->autofit == autofit) return;
|
|
|
|
pd->autofit = autofit;
|
|
|
|
_sizing_eval(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static int
|
|
|
|
_efl_ui_textpath_slice_number_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
return pd->slice_no;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_slice_number_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, int slice_no)
|
|
|
|
{
|
|
|
|
if (pd->slice_no == slice_no) return;
|
|
|
|
pd->slice_no = slice_no;
|
|
|
|
_sizing_eval(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_textpath_ellipsis_set(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd, Eina_Bool ellipsis)
|
|
|
|
{
|
|
|
|
if (pd->ellipsis == ellipsis) return;
|
|
|
|
pd->ellipsis = ellipsis;
|
|
|
|
|
|
|
|
_ellipsis_set(pd);
|
|
|
|
_sizing_eval(pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_ui_textpath_ellipsis_get(Eo *obj EINA_UNUSED, Efl_Ui_Textpath_Data *pd)
|
|
|
|
{
|
|
|
|
return pd->ellipsis;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Efl.Part begin */
|
2017-09-19 04:02:26 -07:00
|
|
|
ELM_PART_OVERRIDE(efl_ui_textpath, EFL_UI_TEXTPATH, Efl_Ui_Textpath_Data)
|
|
|
|
ELM_PART_OVERRIDE_TEXT_SET(efl_ui_textpath, EFL_UI_TEXTPATH, Efl_Ui_Textpath_Data)
|
|
|
|
ELM_PART_OVERRIDE_TEXT_GET(efl_ui_textpath, EFL_UI_TEXTPATH, Efl_Ui_Textpath_Data)
|
edje/elm: Rename _internal_ to _part_ (EO)
In Edje and Elementary, we have part objects, which are what is returned
by the interface efl_part(). Those objects can't be of an opaque type as
this doesn't work nicely with strongly typed languages such as C++ or
C#. In JS, Lua, C the types are weak and mostly runtime-based so it
doesn't matter much.
As a consequence, the documentation and the types need to look nice in
this EO API. Thus, we remove the abusive term "internal" and explicitly
call all those classes "part" something.
Eventually we want the types to be declared in the EO file so bindings
(C#, C++, ...) can generate the proper access methods, returning the
best possible types.
Note that right now a few of those part types are used in the legacy API
but don't actually need to be exposed externally.
This is kind of a mega commit that does all the renaming at once, but
it's really just a big sed operation. The power of good IDEs :)
Ref T5315
Ref T5306
2017-09-12 21:29:25 -07:00
|
|
|
#include "efl_ui_textpath_part.eo.c"
|
2017-08-29 03:04:15 -07:00
|
|
|
/* Efl.Part end */
|
|
|
|
|
|
|
|
#define EFL_UI_TEXTPATH_EXTRA_OPS \
|
|
|
|
EFL_CANVAS_GROUP_ADD_OPS(efl_ui_textpath)
|
|
|
|
|
|
|
|
#include "efl_ui_textpath.eo.c"
|