ui: add cairo-text widget
This commit is contained in:
parent
1219ec1563
commit
98885e34a3
@ -60,6 +60,7 @@ src = [
|
|||||||
'src/widgets/cairo-box.c',
|
'src/widgets/cairo-box.c',
|
||||||
'src/widgets/cairo-window.c',
|
'src/widgets/cairo-window.c',
|
||||||
'src/widgets/cairo-image.c',
|
'src/widgets/cairo-image.c',
|
||||||
|
'src/widgets/cairo-text.c',
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
wayland_targets]
|
wayland_targets]
|
||||||
|
|
||||||
|
@ -13,10 +13,19 @@
|
|||||||
#include "widgets/cairo-window.h"
|
#include "widgets/cairo-window.h"
|
||||||
#include "widgets/cairo-box.h"
|
#include "widgets/cairo-box.h"
|
||||||
#include "widgets/cairo-image.h"
|
#include "widgets/cairo-image.h"
|
||||||
|
#include "widgets/cairo-text.h"
|
||||||
|
|
||||||
#define DEF_SURF_W 600
|
#define DEF_SURF_W 600
|
||||||
#define DEF_SURF_H 400
|
#define DEF_SURF_H 400
|
||||||
|
|
||||||
|
#define LOREM "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n" \
|
||||||
|
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n" \
|
||||||
|
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \n" \
|
||||||
|
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in \n" \
|
||||||
|
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n" \
|
||||||
|
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia \n" \
|
||||||
|
"deserunt mollit anim id est laborum."
|
||||||
|
|
||||||
struct _DiyaLockSession
|
struct _DiyaLockSession
|
||||||
{
|
{
|
||||||
DiyaObject parent;
|
DiyaObject parent;
|
||||||
@ -314,13 +323,13 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
|
|||||||
NULL);
|
NULL);
|
||||||
diya_cairo_container_add(box, hbox);
|
diya_cairo_container_add(box, hbox);
|
||||||
|
|
||||||
|
|
||||||
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
|
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
|
||||||
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
|
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
|
||||||
"vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
|
"vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
|
||||||
"hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
|
"hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
|
||||||
"stroke", &stroke,
|
"stroke", &stroke,
|
||||||
"padding", &padding,
|
"padding", &padding,
|
||||||
|
"corner-radius", 10.0,
|
||||||
NULL);
|
NULL);
|
||||||
diya_cairo_container_add(box, hbox);
|
diya_cairo_container_add(box, hbox);
|
||||||
|
|
||||||
@ -328,7 +337,26 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
|
|||||||
2.0,
|
2.0,
|
||||||
{ 0.0, 0.0, 1.0, 1.0 }
|
{ 0.0, 0.0, 1.0, 1.0 }
|
||||||
};
|
};
|
||||||
DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
|
diya_color_t fill = { 1.0,1.0,1.0,1.0 };
|
||||||
|
diya_color_t color = { 0.0,0.0,0.0,1.0 };
|
||||||
|
|
||||||
|
DiyaCairoText *text = g_object_new(DIYA_TYPE_CAIRO_TEXT,
|
||||||
|
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
|
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
|
"stroke", &stroke,
|
||||||
|
"padding", &padding,
|
||||||
|
"corner-radius", 5.0,
|
||||||
|
"fill", &fill,
|
||||||
|
"color", &color,
|
||||||
|
"font-size", 11,
|
||||||
|
"font-family", "Monospace",
|
||||||
|
"halign", DIYA_CAIRO_WIDGET_ALIGN_START,
|
||||||
|
"valign", DIYA_CAIRO_WIDGET_ALIGN_START,
|
||||||
|
NULL);
|
||||||
|
diya_cairo_text_set_text(text, LOREM);
|
||||||
|
diya_cairo_widget_set_size(text, 600, 400);
|
||||||
|
diya_cairo_container_add(hbox, text);
|
||||||
|
/*DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
|
||||||
"file",
|
"file",
|
||||||
"/home/diya/test.jpg",
|
"/home/diya/test.jpg",
|
||||||
"stroke",
|
"stroke",
|
||||||
@ -336,7 +364,7 @@ static void diya_lock_session_ui(DiyaCairoWindow * window)
|
|||||||
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
NULL);
|
NULL);
|
||||||
diya_cairo_container_add(hbox, image);
|
diya_cairo_container_add(hbox, image);*/
|
||||||
|
|
||||||
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
|
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
|
||||||
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
|
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
|
||||||
|
@ -92,6 +92,7 @@ static void cairo_box_update(gpointer object)
|
|||||||
diya_rect_t space = diya_cairo_widget_get_extent(object);
|
diya_rect_t space = diya_cairo_widget_get_extent(object);
|
||||||
diya_offset_t * padding;
|
diya_offset_t * padding;
|
||||||
diya_stroke_t * stroke;
|
diya_stroke_t * stroke;
|
||||||
|
diya_rect_t * default_extent;
|
||||||
g_object_get(object,"padding", &padding, "stroke", &stroke, NULL);
|
g_object_get(object,"padding", &padding, "stroke", &stroke, NULL);
|
||||||
gint stroke_size = ceil(stroke->size);
|
gint stroke_size = ceil(stroke->size);
|
||||||
gpointer item;
|
gpointer item;
|
||||||
@ -110,7 +111,7 @@ static void cairo_box_update(gpointer object)
|
|||||||
}
|
}
|
||||||
G_LIST_FOREACH(item, children)
|
G_LIST_FOREACH(item, children)
|
||||||
{
|
{
|
||||||
g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL);
|
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
|
||||||
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
|
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
|
||||||
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
|
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
|
||||||
{
|
{
|
||||||
@ -120,9 +121,11 @@ static void cairo_box_update(gpointer object)
|
|||||||
n_extended++;
|
n_extended++;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
occupied_space += cwidth;
|
occupied_space += cwidth;
|
||||||
break;
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
occupied_space += default_extent->width;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -135,9 +138,11 @@ static void cairo_box_update(gpointer object)
|
|||||||
n_extended++;
|
n_extended++;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
occupied_space += cheight;
|
occupied_space += cheight;
|
||||||
break;
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
occupied_space += default_extent->height;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -149,7 +154,7 @@ static void cairo_box_update(gpointer object)
|
|||||||
|
|
||||||
G_LIST_FOREACH(item, children)
|
G_LIST_FOREACH(item, children)
|
||||||
{
|
{
|
||||||
g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL);
|
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
|
||||||
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
|
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
|
||||||
|
|
||||||
diya_rect_t rect = {0};
|
diya_rect_t rect = {0};
|
||||||
@ -166,7 +171,6 @@ static void cairo_box_update(gpointer object)
|
|||||||
off_x += rect.width;
|
off_x += rect.width;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
rect.width = cwidth;
|
rect.width = cwidth;
|
||||||
if(!DIYA_IS_CAIRO_BOX(item))
|
if(!DIYA_IS_CAIRO_BOX(item))
|
||||||
{
|
{
|
||||||
@ -174,6 +178,14 @@ static void cairo_box_update(gpointer object)
|
|||||||
}
|
}
|
||||||
off_x += cwidth;
|
off_x += cwidth;
|
||||||
break;
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
rect.width = default_extent->width;
|
||||||
|
if(!DIYA_IS_CAIRO_BOX(item))
|
||||||
|
{
|
||||||
|
rect.height = default_extent->height;
|
||||||
|
}
|
||||||
|
off_x += default_extent->width;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -188,7 +200,6 @@ static void cairo_box_update(gpointer object)
|
|||||||
off_y += rect.height;
|
off_y += rect.height;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
rect.height = cheight;
|
rect.height = cheight;
|
||||||
if(!DIYA_IS_CAIRO_BOX(item))
|
if(!DIYA_IS_CAIRO_BOX(item))
|
||||||
{
|
{
|
||||||
@ -196,6 +207,14 @@ static void cairo_box_update(gpointer object)
|
|||||||
}
|
}
|
||||||
off_y += cheight;
|
off_y += cheight;
|
||||||
break;
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
rect.height = default_extent->height;
|
||||||
|
if(!DIYA_IS_CAIRO_BOX(item))
|
||||||
|
{
|
||||||
|
rect.width = default_extent->width;
|
||||||
|
}
|
||||||
|
off_y += default_extent->height;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ static gboolean diya_cairo_image_draw(gpointer object, cairo_t * context)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y);
|
//g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y);
|
||||||
|
|
||||||
if(color->a > 0)
|
if(color->a > 0)
|
||||||
{
|
{
|
||||||
|
367
src/widgets/cairo-text.c
Normal file
367
src/widgets/cairo-text.c
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "cairo-text.h"
|
||||||
|
|
||||||
|
#define FONT "Sans Bold 10"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_PROP,
|
||||||
|
C_TEXT,
|
||||||
|
C_FONT_FAMILY,
|
||||||
|
C_FONT_SIZE,
|
||||||
|
C_FONT_STYLE,
|
||||||
|
C_FONT_WEIGHT,
|
||||||
|
C_COLOR,
|
||||||
|
C_WRAP,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
typedef struct _DiyaCairoTextPrivate
|
||||||
|
{
|
||||||
|
DiyaCairoWidget parent_object;
|
||||||
|
|
||||||
|
gchar *text;
|
||||||
|
gchar *family;
|
||||||
|
int size;
|
||||||
|
guint style;
|
||||||
|
guint wrap;
|
||||||
|
guint weight;
|
||||||
|
diya_color_t color;
|
||||||
|
} DiyaCairoTextPrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoText, diya_cairo_text, DIYA_TYPE_CAIRO_WIDGET)
|
||||||
|
|
||||||
|
static void diya_cairo_text_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
g_debug("diya_cairo_text_dispose: %s", diya_object_to_string(object));
|
||||||
|
if (priv->text)
|
||||||
|
{
|
||||||
|
g_free(priv->text);
|
||||||
|
}
|
||||||
|
if (priv->family)
|
||||||
|
{
|
||||||
|
g_free(priv->family);
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_cairo_text_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_text_init(DiyaCairoText *self)
|
||||||
|
{
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
priv->text = NULL;
|
||||||
|
priv->family = NULL;
|
||||||
|
priv->size = 10;
|
||||||
|
priv->style = DIYA_CAIRO_FONT_STYLE_NORMAL;
|
||||||
|
priv->weight = DIYA_CAIRO_FONT_WEIGHT_NORMAL;
|
||||||
|
priv->wrap = DIYA_CAIRO_TEXT_WRAP_WORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_text_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case C_TEXT:
|
||||||
|
if (priv->text)
|
||||||
|
{
|
||||||
|
g_free(priv->text);
|
||||||
|
}
|
||||||
|
priv->text = g_strdup(g_value_get_pointer(value));
|
||||||
|
break;
|
||||||
|
case C_FONT_FAMILY:
|
||||||
|
if (priv->family)
|
||||||
|
{
|
||||||
|
g_free(priv->family);
|
||||||
|
}
|
||||||
|
priv->family = g_strdup(g_value_get_pointer(value));
|
||||||
|
break;
|
||||||
|
case C_FONT_SIZE:
|
||||||
|
priv->size = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case C_FONT_STYLE:
|
||||||
|
priv->style = g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case C_WRAP:
|
||||||
|
priv->wrap = g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case C_FONT_WEIGHT:
|
||||||
|
priv->weight = g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case C_COLOR:
|
||||||
|
memcpy(&priv->color,g_value_get_pointer(value), sizeof(priv->color));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_text_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case C_TEXT:
|
||||||
|
g_value_set_pointer(value, priv->text);
|
||||||
|
break;
|
||||||
|
case C_FONT_FAMILY:
|
||||||
|
g_value_set_pointer(value, priv->family);
|
||||||
|
break;
|
||||||
|
case C_FONT_SIZE:
|
||||||
|
g_value_set_int(value, priv->size);
|
||||||
|
break;
|
||||||
|
case C_FONT_STYLE:
|
||||||
|
g_value_set_uint(value, priv->style);
|
||||||
|
break;
|
||||||
|
case C_WRAP:
|
||||||
|
g_value_set_uint(value, priv->wrap);
|
||||||
|
break;
|
||||||
|
case C_FONT_WEIGHT:
|
||||||
|
g_value_set_uint(value, priv->weight);
|
||||||
|
break;
|
||||||
|
case C_COLOR:
|
||||||
|
g_value_set_pointer(value, &priv->color);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PangoFontDescription *diya_cairo_text_get_pango_font_desc(DiyaCairoText *self)
|
||||||
|
{
|
||||||
|
PangoFontDescription *desc = pango_font_description_new();
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
if (priv->family)
|
||||||
|
{
|
||||||
|
pango_font_description_set_family(desc, priv->family);
|
||||||
|
}
|
||||||
|
pango_font_description_set_size(desc, priv->size * PANGO_SCALE);
|
||||||
|
pango_font_description_set_style(desc, priv->style);
|
||||||
|
pango_font_description_set_weight(desc, priv->weight);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean diya_cairo_text_draw(gpointer object, cairo_t *context)
|
||||||
|
{
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
if(!diya_cairo_widget_is_damaged(object) || !diya_cairo_widget_is_visible(object))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_text_parent_class)->draw(object, context);
|
||||||
|
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
|
||||||
|
diya_rect_dump("diya_cairo_text_draw: ", &view_port);
|
||||||
|
|
||||||
|
if(diya_rect_is_empty(&view_port))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cairo_save(context);
|
||||||
|
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
|
||||||
|
cairo_clip(context);
|
||||||
|
|
||||||
|
diya_rect_t extent = diya_cairo_widget_get_extent(object);
|
||||||
|
g_warning("diya_cairo_widget_get_extent: width %d, %d", extent.width, extent.height);
|
||||||
|
diya_offset_t * padding, *margin;
|
||||||
|
diya_stroke_t *stroke;
|
||||||
|
diya_color_t *color;
|
||||||
|
guint halign, valign;
|
||||||
|
g_object_get(object,
|
||||||
|
"stroke", &stroke,
|
||||||
|
"halign", &halign,
|
||||||
|
"valign", &valign,
|
||||||
|
"margin", &margin,
|
||||||
|
"padding", &padding,
|
||||||
|
"color", &color,
|
||||||
|
NULL);
|
||||||
|
gint stroke_size = ceil(stroke->size);
|
||||||
|
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
|
||||||
|
|
||||||
|
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
|
||||||
|
cairo_set_source_rgba(context, color->r, color->g, color->b, color->a);
|
||||||
|
int display_w = extent.width - padding->left - padding->right - margin->left - margin->right - 2*stroke_size;
|
||||||
|
int display_h = extent.height - padding->top - padding->bottom - margin->top - margin->bottom - 2*stroke_size;
|
||||||
|
int off_x = padding->left + margin->left + stroke_size;
|
||||||
|
int off_y = padding->top + margin->top + stroke_size;
|
||||||
|
|
||||||
|
PangoLayout *layout = pango_cairo_create_layout(context);
|
||||||
|
// take into account my padding setting
|
||||||
|
pango_layout_set_text(layout, priv->text, -1);
|
||||||
|
pango_layout_set_font_description(layout, desc);
|
||||||
|
pango_layout_set_width(layout,display_w*PANGO_SCALE);
|
||||||
|
pango_layout_set_height(layout, display_h*PANGO_SCALE);
|
||||||
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
|
pango_layout_set_wrap(layout, priv->wrap);
|
||||||
|
switch(halign)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_START:
|
||||||
|
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
|
||||||
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_END:
|
||||||
|
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PangoRectangle text_rect = {0};
|
||||||
|
pango_layout_get_extents(layout, NULL, &text_rect);
|
||||||
|
pango_extents_to_pixels(&text_rect, NULL);
|
||||||
|
// draw text
|
||||||
|
switch (valign)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
|
||||||
|
off_y += (display_h - text_rect.height)/ 2;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_END:
|
||||||
|
off_y += display_h - text_rect.height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cairo_move_to(context, gpos.x + off_x, gpos.y + off_y);
|
||||||
|
pango_cairo_update_layout(context, layout);
|
||||||
|
pango_cairo_show_layout(context, layout);
|
||||||
|
|
||||||
|
cairo_restore(context);
|
||||||
|
pango_font_description_free(desc);
|
||||||
|
g_object_unref(layout);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_text_content_size(gpointer object, int *width, int *height)
|
||||||
|
{
|
||||||
|
diya_offset_t* padding, *margin;
|
||||||
|
diya_stroke_t * stroke;
|
||||||
|
diya_rect_t * def_xtent;
|
||||||
|
guint hspace,vspace;
|
||||||
|
g_object_get(object,
|
||||||
|
"padding", &padding,
|
||||||
|
"margin", &margin,
|
||||||
|
"stroke", &stroke,
|
||||||
|
"hspace", &hspace,
|
||||||
|
"vspace", &vspace,
|
||||||
|
"default-extent", &def_xtent,
|
||||||
|
NULL);
|
||||||
|
gint stroke_size = ceil(stroke->size) * 2;
|
||||||
|
*width = padding->left + padding->right + margin->left + margin->right + stroke_size;
|
||||||
|
*height = padding->top + padding->bottom + margin->top + margin->bottom + stroke_size;
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
// diya_rect_t default_extent = DIYA_CAIRO_WIDGET_GET_CLASS(object)->default_extent(object);
|
||||||
|
int text_width = 0;
|
||||||
|
int text_height = 0;
|
||||||
|
if (priv->text)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||||
|
cairo_t *context = cairo_create(surface);
|
||||||
|
PangoLayout *layout = pango_cairo_create_layout(context);
|
||||||
|
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
|
||||||
|
pango_layout_set_font_description(layout, desc);
|
||||||
|
pango_layout_set_text(layout, priv->text, -1);
|
||||||
|
pango_layout_set_width(layout, -1);
|
||||||
|
pango_layout_set_height(layout, -1);
|
||||||
|
pango_layout_set_single_paragraph_mode(layout, FALSE);
|
||||||
|
//pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
|
||||||
|
PangoRectangle rect = {0};
|
||||||
|
pango_layout_get_extents(layout, NULL, &rect);
|
||||||
|
pango_extents_to_pixels(&rect, NULL);
|
||||||
|
//rect.width += 4;
|
||||||
|
text_width = rect.width;
|
||||||
|
text_height = rect.height;
|
||||||
|
cairo_destroy(context);
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
pango_font_description_free(desc);
|
||||||
|
g_object_unref(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (hspace)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
*width = def_xtent->width;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*width += text_width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (vspace)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
*height = def_xtent->height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*height += text_height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_text_class_init(DiyaCairoTextClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
|
||||||
|
|
||||||
|
class->set_text = diya_cairo_text_set_text;
|
||||||
|
class->get_text = diya_cairo_text_get_text;
|
||||||
|
|
||||||
|
wclass->draw = diya_cairo_text_draw;
|
||||||
|
wclass->content_size = diya_cairo_text_content_size;
|
||||||
|
|
||||||
|
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoText");
|
||||||
|
gobject_class->dispose = diya_cairo_text_dispose;
|
||||||
|
gobject_class->set_property = diya_cairo_text_set_property;
|
||||||
|
gobject_class->get_property = diya_cairo_text_get_property;
|
||||||
|
|
||||||
|
g_prop[C_TEXT] = g_param_spec_pointer("text", NULL, "text content", G_PARAM_READWRITE);
|
||||||
|
g_prop[C_FONT_FAMILY] = g_param_spec_pointer("font-family", NULL, "text font face", G_PARAM_READWRITE);
|
||||||
|
g_prop[C_COLOR] = g_param_spec_pointer("color", NULL, "text color", G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_prop[C_FONT_STYLE] = g_param_spec_uint(
|
||||||
|
"font-style", NULL, "text font style",
|
||||||
|
DIYA_CAIRO_FONT_STYLE_NORMAL,
|
||||||
|
DIYA_CAIRO_FONT_STYLE_ITALIC,
|
||||||
|
DIYA_CAIRO_FONT_STYLE_NORMAL,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
g_prop[C_FONT_WEIGHT] = g_param_spec_uint(
|
||||||
|
"font-weight", NULL, "text font weight",
|
||||||
|
PANGO_WEIGHT_THIN,
|
||||||
|
PANGO_WEIGHT_ULTRAHEAVY,
|
||||||
|
DIYA_CAIRO_FONT_WEIGHT_NORMAL,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
g_prop[C_FONT_SIZE] = g_param_spec_int(
|
||||||
|
"font-size", NULL, "text font size",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
10,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
g_prop[C_WRAP] = g_param_spec_uint(
|
||||||
|
"wrap", NULL, "text wrap mode",
|
||||||
|
DIYA_CAIRO_TEXT_WRAP_WORD,
|
||||||
|
DIYA_CAIRO_TEXT_WRAP_WORD_CHAR,
|
||||||
|
DIYA_CAIRO_TEXT_WRAP_WORD,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, g_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_text_set_text(gpointer object, const gchar *text)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_TEXT(object));
|
||||||
|
g_object_set(object, "text", text, NULL);
|
||||||
|
}
|
||||||
|
const gchar *diya_cairo_text_get_text(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_TEXT(object));
|
||||||
|
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
|
||||||
|
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
|
||||||
|
return priv->text;
|
||||||
|
}
|
31
src/widgets/cairo-text.h
Normal file
31
src/widgets/cairo-text.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef CAIRO_TEXT_H
|
||||||
|
#define CAIRO_TEXT_H
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
#include "cairo-widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DIYA_CAIRO_FONT_STYLE_NORMAL PANGO_STYLE_NORMAL
|
||||||
|
#define DIYA_CAIRO_FONT_STYLE_ITALIC PANGO_STYLE_ITALIC
|
||||||
|
#define DIYA_CAIRO_FONT_STYLE_OBLIQUE PANGO_STYLE_OBLIQUE
|
||||||
|
|
||||||
|
#define DIYA_CAIRO_FONT_WEIGHT_NORMAL PANGO_WEIGHT_NORMAL
|
||||||
|
#define DIYA_CAIRO_FONT_WEIGHT_BOLD PANGO_WEIGHT_BOLD
|
||||||
|
|
||||||
|
#define DIYA_CAIRO_TEXT_WRAP_WORD PANGO_WRAP_WORD
|
||||||
|
#define DIYA_CAIRO_TEXT_WRAP_CHAR PANGO_WRAP_CHAR
|
||||||
|
#define DIYA_CAIRO_TEXT_WRAP_WORD_CHAR PANGO_WRAP_WORD_CHAR
|
||||||
|
|
||||||
|
#define DIYA_TYPE_CAIRO_TEXT (diya_cairo_text_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (DiyaCairoText, diya_cairo_text, DIYA, CAIRO_TEXT, DiyaCairoWidget)
|
||||||
|
|
||||||
|
|
||||||
|
struct _DiyaCairoTextClass
|
||||||
|
{
|
||||||
|
DiyaCairoWidgetClass parent_class;
|
||||||
|
void (*set_text)(gpointer object, const gchar* text);
|
||||||
|
const gchar* (*get_text)(gpointer object);
|
||||||
|
};
|
||||||
|
|
||||||
|
void diya_cairo_text_set_text(gpointer object, const gchar* text);
|
||||||
|
const gchar* diya_cairo_text_get_text(gpointer object);
|
||||||
|
#endif
|
@ -51,6 +51,7 @@ enum
|
|||||||
CW_MARGIN,
|
CW_MARGIN,
|
||||||
CW_FILL,
|
CW_FILL,
|
||||||
CW_STROKE,
|
CW_STROKE,
|
||||||
|
CW_CORNER_RADIUS,
|
||||||
CW_N_PROPERTIES
|
CW_N_PROPERTIES
|
||||||
};
|
};
|
||||||
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
|
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
|
||||||
@ -70,6 +71,8 @@ typedef struct _DiyaCairoWidgetPrivate
|
|||||||
guint16 hspace;
|
guint16 hspace;
|
||||||
guint16 vspace;
|
guint16 vspace;
|
||||||
|
|
||||||
|
gdouble corner_radius;
|
||||||
|
|
||||||
diya_offset_t margin;
|
diya_offset_t margin;
|
||||||
diya_offset_t padding;
|
diya_offset_t padding;
|
||||||
|
|
||||||
@ -166,6 +169,9 @@ static void diya_cairo_widget_set_property(GObject *object, guint property_id, c
|
|||||||
assert(ptr);
|
assert(ptr);
|
||||||
priv->stroke = *(diya_stroke_t*) ptr;
|
priv->stroke = *(diya_stroke_t*) ptr;
|
||||||
break;
|
break;
|
||||||
|
case CW_CORNER_RADIUS:
|
||||||
|
priv->corner_radius = g_value_get_double(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -214,6 +220,9 @@ static void diya_cairo_widget_get_property(GObject *object, guint property_id, G
|
|||||||
case CW_STROKE:
|
case CW_STROKE:
|
||||||
g_value_set_pointer(value, &priv->stroke);
|
g_value_set_pointer(value, &priv->stroke);
|
||||||
break;
|
break;
|
||||||
|
case CW_CORNER_RADIUS:
|
||||||
|
g_value_set_double(value, priv->corner_radius);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -241,6 +250,7 @@ static void diya_cairo_widget_init(DiyaCairoWidget *self)
|
|||||||
memset(&priv->fill, 0, sizeof(priv->fill));
|
memset(&priv->fill, 0, sizeof(priv->fill));
|
||||||
|
|
||||||
priv->damaged = TRUE;
|
priv->damaged = TRUE;
|
||||||
|
priv->corner_radius = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
|
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
|
||||||
@ -277,6 +287,12 @@ diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
|
|||||||
if(priv->parent_widget)
|
if(priv->parent_widget)
|
||||||
{
|
{
|
||||||
diya_rect_t parent_view = diya_cairo_widget_get_view_port(priv->parent_widget);
|
diya_rect_t parent_view = diya_cairo_widget_get_view_port(priv->parent_widget);
|
||||||
|
diya_offset_t* padding;
|
||||||
|
g_object_get(priv->parent_widget,"padding", &padding, NULL);
|
||||||
|
parent_view.x += padding->left;
|
||||||
|
parent_view.y += padding->top;
|
||||||
|
parent_view.width -= (padding->left + padding->right);
|
||||||
|
parent_view.height -= (padding->top + padding->bottom);
|
||||||
if(!diya_rect_overlap(&view, &parent_view))
|
if(!diya_rect_overlap(&view, &parent_view))
|
||||||
{
|
{
|
||||||
view.x = view.y = view.width = view.height = 0;
|
view.x = view.y = view.width = view.height = 0;
|
||||||
@ -298,8 +314,6 @@ diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
|
|||||||
|
|
||||||
static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
|
static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
|
||||||
{
|
{
|
||||||
(void) context;
|
|
||||||
|
|
||||||
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
if(!priv->damaged)
|
if(!priv->damaged)
|
||||||
@ -325,11 +339,25 @@ static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
|
|||||||
//cairo_move_to(context, (double)gpos.x +, (double)gpos.y);
|
//cairo_move_to(context, (double)gpos.x +, (double)gpos.y);
|
||||||
guint stroke_size = ceil(priv->stroke.size);
|
guint stroke_size = ceil(priv->stroke.size);
|
||||||
guint half_stroke_size = ceil(priv->stroke.size / 2.0);
|
guint half_stroke_size = ceil(priv->stroke.size / 2.0);
|
||||||
cairo_rectangle(context,
|
|
||||||
gpos.x + priv->margin.left + half_stroke_size,
|
double width = (double)(priv->extent.width - priv->margin.left - priv->margin.right - stroke_size);
|
||||||
gpos.y + priv->margin.top + half_stroke_size,
|
int height = (double)(priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size);
|
||||||
priv->extent.width - priv->margin.left - priv->margin.right - stroke_size,
|
int x = (double)(gpos.x + priv->margin.left + half_stroke_size);
|
||||||
priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size);
|
int y = (double)(gpos.y + priv->margin.top + half_stroke_size);
|
||||||
|
if(priv->corner_radius > 0)
|
||||||
|
{
|
||||||
|
double degrees = M_PI / 180.0;
|
||||||
|
cairo_new_sub_path(context);
|
||||||
|
cairo_arc (context, x + width - priv->corner_radius, y + priv->corner_radius, priv->corner_radius, -90 * degrees, 0);
|
||||||
|
cairo_arc (context, x + width - priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 0, 90 * degrees);
|
||||||
|
cairo_arc (context, x + priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 90 * degrees, 180 * degrees);
|
||||||
|
cairo_arc (context, x + priv->corner_radius, y + priv->corner_radius, priv->corner_radius, 180 * degrees, 270 * degrees);
|
||||||
|
cairo_close_path (context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_rectangle(context,x,y,width,height);
|
||||||
|
}
|
||||||
if(priv->fill.a > 0)
|
if(priv->fill.a > 0)
|
||||||
{
|
{
|
||||||
cairo_set_source_rgba(context, priv->fill.r, priv->fill.g, priv->fill.b, priv->fill.a);
|
cairo_set_source_rgba(context, priv->fill.r, priv->fill.g, priv->fill.b, priv->fill.a);
|
||||||
@ -361,7 +389,7 @@ static void diya_cairo_widget_update(gpointer object)
|
|||||||
assert(DIYA_IS_CAIRO_WIDGET(object));
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
gint stroke_size = ceil(priv->stroke.size) *2;
|
||||||
if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN)
|
if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -394,11 +422,10 @@ static void diya_cairo_widget_update(gpointer object)
|
|||||||
width = space.width;
|
width = space.width;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
width = cwidth;
|
width = cwidth;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
width = priv->default_extent.width + priv->margin.left + priv->margin.right;
|
width = priv->default_extent.width + priv->margin.left + priv->margin.right + stroke_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,11 +435,10 @@ static void diya_cairo_widget_update(gpointer object)
|
|||||||
height = space.height;
|
height = space.height;
|
||||||
break;
|
break;
|
||||||
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
|
||||||
height = cheight;
|
height = cheight;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
height = priv->default_extent.height + priv->margin.top + priv->margin.bottom;
|
height = priv->default_extent.height + priv->margin.top + priv->margin.bottom + stroke_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,6 +602,12 @@ static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class)
|
|||||||
INT_MAX,
|
INT_MAX,
|
||||||
0,
|
0,
|
||||||
G_PARAM_WRITABLE);
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_CORNER_RADIUS] = g_param_spec_double(
|
||||||
|
"corner-radius", NULL, "Corner radius",
|
||||||
|
0,
|
||||||
|
DBL_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
base_class->to_string = diya_cairo_widget_to_string;
|
base_class->to_string = diya_cairo_widget_to_string;
|
||||||
|
|
||||||
@ -717,7 +749,7 @@ static void diya_cairo_container_dispose(GObject* object)
|
|||||||
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
|
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
|
||||||
g_debug("diya_cairo_container_dispose: %s", diya_object_to_string(object));
|
g_debug("diya_cairo_container_dispose: %s", diya_object_to_string(object));
|
||||||
g_list_free_full(priv->children, g_object_unref);
|
g_list_free_full(priv->children, g_object_unref);
|
||||||
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_cairo_container_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_cairo_container_init(DiyaCairoContainer *self)
|
static void diya_cairo_container_init(DiyaCairoContainer *self)
|
||||||
|
@ -102,7 +102,6 @@ struct _DiyaCairoWidgetClass
|
|||||||
diya_rect_t (*default_extent)(gpointer);
|
diya_rect_t (*default_extent)(gpointer);
|
||||||
diya_rect_t (*view_port)(gpointer);
|
diya_rect_t (*view_port)(gpointer);
|
||||||
gboolean (*damaged)(gpointer);
|
gboolean (*damaged)(gpointer);
|
||||||
|
|
||||||
const gchar* name;
|
const gchar* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user