#include "osglobals_gtk.inl"
#include "../osdrawctrl.h"
#include <draw2d/draw.h>
#include <draw2d/dctxh.h>
#include <draw2d/font.h>
#include <draw2d/color.h>
#include <sewer/cassert.h>
#if !defined(__GTK3__)
#error This file is only for GTK Toolkit
#endif
Font *osdrawctrl_font(const DCtx *ctx)
{
unref(ctx);
return font_system(font_regular_size(), 0);
}
uint32_t osdrawctrl_row_padding(const DCtx *ctx)
{
unref(ctx);
return 4;
}
uint32_t osdrawctrl_check_width(const DCtx *ctx)
{
unref(ctx);
return _osglobals_check_width();
}
uint32_t osdrawctrl_check_height(const DCtx *ctx)
{
unref(ctx);
return _osglobals_check_height();
}
ctrl_msel_t osdrawctrl_multisel(const DCtx *ctx, const vkey_t key)
{
unref(ctx);
if (key == ekKEY_LCTRL || key == ekKEY_RCTRL)
return ekCTRL_MSEL_SINGLE;
else if (key == ekKEY_LSHIFT || key == ekKEY_RSHIFT)
return ekCTRL_MSEL_BURST;
return ekCTRL_MSEL_NO;
}
void osdrawctrl_clear(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const enum_t nonused)
{
GtkStyleContext *c = _osglobals_entry_context();
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
gtk_style_context_save(c);
gtk_style_context_set_state(c, GTK_STATE_FLAG_NORMAL);
gtk_render_background(c, cairo, (gdouble)x, (gdouble)y, (gdouble)width, (gdouble)height);
gtk_style_context_restore(c);
unref(nonused);
}
void osdrawctrl_header(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state)
{
static const uint32_t backoffset = 10;
GtkStyleContext *c = _osglobals_button_context();
color_t border = _osglobals_border_color();
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
GtkStateFlags flags = 0;
real32_t r, g, b, a;
switch (state)
{
case ekCTRL_STATE_NORMAL:
case ekCTRL_STATE_BKNORMAL:
flags = GTK_STATE_FLAG_NORMAL;
break;
case ekCTRL_STATE_HOT:
case ekCTRL_STATE_BKHOT:
flags = GTK_STATE_FLAG_PRELIGHT;
break;
case ekCTRL_STATE_PRESSED:
case ekCTRL_STATE_BKPRESSED:
#if GTK_CHECK_VERSION(3, 14, 0)
flags = GTK_STATE_FLAG_CHECKED;
#else
flags = GTK_STATE_FLAG_SELECTED;
#endif
break;
case ekCTRL_STATE_DISABLED:
flags = GTK_STATE_FLAG_INSENSITIVE;
break;
cassert_default();
}
cairo_save(cairo);
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
cairo_rectangle(cairo, (double)x, (double)y, (double)width, (double)height);
cairo_clip(cairo);
gtk_style_context_save(c);
gtk_style_context_set_state(c, flags);
gtk_render_background(c, cairo, (double)x - backoffset, (double)y - backoffset, (double)width + 2 * backoffset, (double)height + backoffset);
gtk_style_context_restore(c);
color_get_rgbaf(border, &r, &g, &b, &a);
cairo_set_source_rgba(cairo, (double)r, (double)g, (double)b, (double)a);
cairo_rectangle(cairo, (double)x, (double)y, (double)width, (double)height);
cairo_stroke(cairo);
cairo_restore(cairo);
}
void osdrawctrl_indicator(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const indicator_t indicator)
{
static const gdouble ind_size = 8;
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
unref(height);
cairo_save(cairo);
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
if (indicator & ekINDDOWN_ARROW)
{
GtkStyleContext *c = _osglobals_table_context();
gtk_render_arrow(c, cairo, 3.14159, (gdouble)(x + width / 2. - ind_size / 2.), y, ind_size);
}
else if (indicator & ekINDUP_ARROW)
{
GtkStyleContext *c = _osglobals_table_context();
gtk_render_arrow(c, cairo, 0, (gdouble)(x + width / 2. - ind_size / 2.), y, ind_size);
}
cairo_restore(cairo);
}
void osdrawctrl_fill(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state)
{
GtkStyleContext *c = _osglobals_table_context();
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
GtkStateFlags flags = 0;
switch (state)
{
case ekCTRL_STATE_NORMAL:
flags = GTK_STATE_FLAG_NORMAL;
break;
case ekCTRL_STATE_HOT:
flags = GTK_STATE_FLAG_PRELIGHT;
break;
case ekCTRL_STATE_PRESSED:
flags = GTK_STATE_FLAG_SELECTED;
break;
case ekCTRL_STATE_BKNORMAL:
flags = GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_BACKDROP;
break;
case ekCTRL_STATE_BKHOT:
flags = GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_BACKDROP;
break;
case ekCTRL_STATE_BKPRESSED:
flags = GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_BACKDROP;
break;
case ekCTRL_STATE_DISABLED:
flags = GTK_STATE_FLAG_INSENSITIVE;
break;
cassert_default();
}
gtk_style_context_save(c);
gtk_style_context_set_state(c, flags);
gtk_render_background(c, cairo, (double)x, (double)y, (double)width, (double)height);
gtk_style_context_restore(c);
}
void osdrawctrl_focus(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state)
{
color_t color = _osglobals_text_color();
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
real32_t pattern[2] = {2.f, 1.f};
real32_t r, g, b, a;
unref(state);
cairo_save(cairo);
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
draw_line_width(ctx, 1);
draw_line_dash(ctx, pattern, 2);
color_get_rgbaf(color, &r, &g, &b, &a);
cairo_set_source_rgba(cairo, (double)r, (double)g, (double)b, (double)a);
cairo_rectangle(cairo, (double)x + 2, (double)y + 2, (double)width - 4, (double)height - 4);
cairo_stroke(cairo);
cairo_restore(cairo);
}
void osdrawctrl_line(DCtx *ctx, const int32_t x0, const int32_t y0, const int32_t x1, const int32_t y1)
{
draw_line_imp(ctx, (real32_t)x0, (real32_t)y0, (real32_t)x1, (real32_t)y1, TRUE);
}
void osdrawctrl_text(DCtx *ctx, const char_t *text, const int32_t x, const int32_t y, const ctrl_state_t state)
{
color_t color = dctx_text_color(ctx);
ellipsis_t ellipsis = dctx_text_trim(ctx);
if (color == kCOLOR_TRANSPARENT)
{
switch (state)
{
case ekCTRL_STATE_NORMAL:
color = _osglobals_text_color();
break;
case ekCTRL_STATE_BKNORMAL:
color = _osglobals_textbackdrop_color();
break;
case ekCTRL_STATE_HOT:
color = _osglobals_hottext_color();
break;
case ekCTRL_STATE_BKHOT:
color = _osglobals_hottextbackdrop_color();
break;
case ekCTRL_STATE_PRESSED:
color = _osglobals_seltext_color();
break;
case ekCTRL_STATE_BKPRESSED:
color = _osglobals_seltextbackdrop_color();
break;
case ekCTRL_STATE_DISABLED:
color = _osglobals_text_color();
break;
cassert_default();
}
}
draw_text_color(ctx, color);
draw_text_trim(ctx, ekELLIPEND);
draw_text_raster(ctx, text, x, y);
draw_text_trim(ctx, ellipsis);
}
void osdrawctrl_image(DCtx *ctx, const Image *image, const int32_t x, const int32_t y, const ctrl_state_t state)
{
draw_image(ctx, image, (real32_t)x, (real32_t)y);
unref(state);
}
static void i_draw_check(cairo_t *cairo, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state, const uint32_t start)
{
GdkPixbuf *bitmap = _osglobals_checks_bitmap();
uint32_t offset = start;
switch (state)
{
case ekCTRL_STATE_NORMAL:
case ekCTRL_STATE_BKNORMAL:
offset += 0;
break;
case ekCTRL_STATE_HOT:
case ekCTRL_STATE_BKHOT:
offset += 1;
break;
case ekCTRL_STATE_PRESSED:
offset += 2;
break;
case ekCTRL_STATE_BKPRESSED:
offset += 3;
break;
case ekCTRL_STATE_DISABLED:
offset += 4;
break;
cassert_default();
}
cassert(width == _osglobals_check_width());
cassert(height == _osglobals_check_height());
gdk_cairo_set_source_pixbuf(cairo, bitmap, (gdouble)x - (gdouble)(offset * width), (gdouble)y);
cairo_rectangle(cairo, (double)x, (double)y, (double)width, (double)height);
cairo_fill(cairo);
}
void osdrawctrl_checkbox(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state)
{
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
i_draw_check(cairo, x, y, width, height, state, 5);
}
void osdrawctrl_uncheckbox(DCtx *ctx, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height, const ctrl_state_t state)
{
cairo_t *cairo = cast(dctx_native(ctx), cairo_t);
i_draw_check(cairo, x, y, width, height, state, 0);
}