713 lines
17 KiB
C
713 lines
17 KiB
C
|
#include <cairo/cairo.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include "btk-cell.h"
|
||
|
#include "btk-log.h"
|
||
|
#include "btk-cell-render.c"
|
||
|
|
||
|
void
|
||
|
btk_cell_set_button(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
char *label,
|
||
|
void (*func)(void))
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, 1);
|
||
|
c->group = BTK_CELL_GROUP_DYNAMIC;
|
||
|
c->type = BTK_CELL_TYPE_BUTTON;
|
||
|
c->lh = 1;
|
||
|
c->label = label;
|
||
|
|
||
|
NEW_PP(btk_pp_button_t, c->pp);
|
||
|
PP_BUTTON(c)->func = func;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_editor(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
unsigned int ch,
|
||
|
char *text,
|
||
|
unsigned int text_w)
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, ch);
|
||
|
c->group = BTK_CELL_GROUP_FIELD;
|
||
|
c->type = BTK_CELL_TYPE_EDITOR;
|
||
|
c->lh = 0;
|
||
|
c->label = "no data";
|
||
|
|
||
|
NEW_PP(btk_pp_editor_t, c->pp);
|
||
|
PP_EDITOR(c)->text = text;
|
||
|
PP_EDITOR(c)->text_w = text_w;
|
||
|
PP_EDITOR(c)->caret = 0;
|
||
|
PP_EDITOR(c)->caret_2d.x = 0;
|
||
|
PP_EDITOR(c)->caret_2d.y = 0;
|
||
|
PP_EDITOR(c)->scroll = 0;
|
||
|
PP_EDITOR(c)->par = NULL;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_empty(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
unsigned int ch)
|
||
|
{
|
||
|
c->group = BTK_CELL_GROUP_PASSIVE;
|
||
|
c->type = BTK_CELL_TYPE_EMPTY;
|
||
|
c->state = BTK_CELL_STATE_INITIAL;
|
||
|
c->ca.x = cx;
|
||
|
c->ca.y = cy;
|
||
|
c->ca.w = cw;
|
||
|
c->ca.h = ch;
|
||
|
c->lh = 0;
|
||
|
c->pp = NULL;
|
||
|
c->fd = NULL;
|
||
|
c->label = NULL;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_mark(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
int justify,
|
||
|
char *label)
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, 1);
|
||
|
c->type = BTK_CELL_TYPE_MARK;
|
||
|
c->lh = 1;
|
||
|
c->label = label;
|
||
|
|
||
|
NEW_PP(btk_pp_mark_t, c->pp);
|
||
|
PP_MARK(c)->justify = justify;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_input(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
char *text,
|
||
|
unsigned int text_w)
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, 1);
|
||
|
c->group = BTK_CELL_GROUP_DYNAMIC;
|
||
|
c->type = BTK_CELL_TYPE_INPUT;
|
||
|
c->lh = 1;
|
||
|
c->label = "-/-";
|
||
|
|
||
|
NEW_PP(btk_pp_input_t, c->pp);
|
||
|
PP_INPUT(c)->text = text;
|
||
|
PP_INPUT(c)->text_w = text_w;
|
||
|
PP_INPUT(c)->caret = 0;
|
||
|
PP_INPUT(c)->scroll = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_list(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
unsigned int ch,
|
||
|
char **items,
|
||
|
unsigned int *items_n,
|
||
|
unsigned int items_w,
|
||
|
int **filter,
|
||
|
int **order,
|
||
|
int **spot,
|
||
|
void (*func_trigger)(int),
|
||
|
void (*func_sel)(int))
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, ch);
|
||
|
c->group = BTK_CELL_GROUP_FIELD;
|
||
|
c->type = BTK_CELL_TYPE_LIST;
|
||
|
c->label = "no data";
|
||
|
|
||
|
NEW_PP(btk_pp_list_t, c->pp);
|
||
|
PP_LIST(c)->items = items;
|
||
|
PP_LIST(c)->items_n = items_n;
|
||
|
PP_LIST(c)->items_w = items_w;
|
||
|
PP_LIST(c)->item_sel = -1;
|
||
|
PP_LIST(c)->filter = filter;
|
||
|
PP_LIST(c)->order = order;
|
||
|
PP_LIST(c)->spot = spot;
|
||
|
PP_LIST(c)->scroll = 0;
|
||
|
PP_LIST(c)->func_trigger = func_trigger;
|
||
|
PP_LIST(c)->func_sel = func_sel;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_switch(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
char *label,
|
||
|
void (*func)(int, btk_arg_t),
|
||
|
btk_arg_t func_args)
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, 1);
|
||
|
c->group = BTK_CELL_GROUP_DYNAMIC;
|
||
|
c->type = BTK_CELL_TYPE_SWITCH;
|
||
|
c->lh = 1;
|
||
|
c->label = label;
|
||
|
|
||
|
NEW_PP(btk_pp_switch_t, c->pp);
|
||
|
PP_SWITCH(c)->func = func;
|
||
|
PP_SWITCH(c)->func_args = func_args;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_set_table(btk_cell_t *c,
|
||
|
unsigned int cx,
|
||
|
unsigned int cy,
|
||
|
unsigned int cw,
|
||
|
unsigned int ch,
|
||
|
char *header, /* must be same item_w as items */
|
||
|
char **items,
|
||
|
unsigned int items_w,
|
||
|
unsigned int cols_n,
|
||
|
unsigned int *rows_n,
|
||
|
int *cols_ena,
|
||
|
unsigned int *cols_cw,
|
||
|
unsigned int sc,
|
||
|
int **filter,
|
||
|
int **order,
|
||
|
int **spot,
|
||
|
void (*func_trigger)(int),
|
||
|
void (*func_sel)(int))
|
||
|
{
|
||
|
btk_cell_set_empty(c, cx, cy, cw, ch);
|
||
|
c->group = BTK_CELL_GROUP_FIELD;
|
||
|
c->type = BTK_CELL_TYPE_TABLE;
|
||
|
c->label = "no data";
|
||
|
|
||
|
NEW_PP(btk_pp_table_t, c->pp);
|
||
|
PP_TABLE(c)->header = header;
|
||
|
PP_TABLE(c)->items = items;
|
||
|
PP_TABLE(c)->items_w = items_w;
|
||
|
PP_TABLE(c)->rows_n = rows_n;
|
||
|
PP_TABLE(c)->cols_n = cols_n;
|
||
|
PP_TABLE(c)->row_sel = -1;
|
||
|
PP_TABLE(c)->cols_ena = cols_ena;
|
||
|
PP_TABLE(c)->cols_cw = cols_cw;
|
||
|
PP_TABLE(c)->sc = sc;
|
||
|
PP_TABLE(c)->tw = 0;
|
||
|
PP_TABLE(c)->filter = filter;
|
||
|
PP_TABLE(c)->order = order;
|
||
|
PP_TABLE(c)->spot = spot;
|
||
|
PP_TABLE(c)->scroll.x = 0;
|
||
|
PP_TABLE(c)->scroll.y = 0;
|
||
|
PP_TABLE(c)->func_trigger = func_trigger;
|
||
|
PP_TABLE(c)->func_sel = func_sel;
|
||
|
|
||
|
PP_TABLE(c)->cols_pw = (unsigned int*)malloc(cols_n * sizeof(int));
|
||
|
PP_TABLE(c)->cols_px = (unsigned int*)malloc(cols_n * sizeof(int));
|
||
|
}
|
||
|
|
||
|
/****************************************************************************************/
|
||
|
|
||
|
void
|
||
|
btk_cell_button_trigger(btk_cell_t *c, int button)
|
||
|
{
|
||
|
if (button == 1 && PP_BUTTON(c)->func)
|
||
|
PP_BUTTON(c)->func();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_destroy(btk_cell_t *c)
|
||
|
{
|
||
|
if (c->pp) {
|
||
|
switch (c->type) {
|
||
|
case BTK_CELL_TYPE_TABLE:
|
||
|
free(PP_TABLE(c)->cols_pw);
|
||
|
free(PP_TABLE(c)->cols_px);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_EDITOR:
|
||
|
btk_text_destroy_par(PP_EDITOR(c)->par);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
free(c->pp);
|
||
|
}
|
||
|
free(c);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_draw(btk_cell_t *c, cairo_t *c_ctx)
|
||
|
{
|
||
|
if (!c)
|
||
|
return;
|
||
|
if ((c->state & BTK_CELL_STATE_HIDDEN))
|
||
|
return;
|
||
|
|
||
|
switch(c->type) {
|
||
|
case BTK_CELL_TYPE_MARK:
|
||
|
render_mark(c, c_ctx);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_BUTTON:
|
||
|
render_button(c, c_ctx);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_SWITCH:
|
||
|
render_switch(c, c_ctx);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_LIST:
|
||
|
render_list(c);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_TABLE:
|
||
|
render_table(c);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_INPUT:
|
||
|
render_input(c, c_ctx);
|
||
|
break;
|
||
|
case BTK_CELL_TYPE_EDITOR:
|
||
|
render_editor(c);
|
||
|
break;
|
||
|
default:
|
||
|
fill_cell(c, c_ctx, btk_cl_empty);
|
||
|
break;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_editor_input_button(btk_cell_t *c, int button, int combo, btk_pos_t pt)
|
||
|
{
|
||
|
/* scrolling if appropriate button is clicked */
|
||
|
switch (button) {
|
||
|
case 1:
|
||
|
break;
|
||
|
case 4:
|
||
|
PP_EDITOR(c)->scroll -= btk_scroll_speed;
|
||
|
return;
|
||
|
case 5:
|
||
|
PP_EDITOR(c)->scroll += btk_scroll_speed;
|
||
|
return;
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* caret positioning */
|
||
|
if (pt.x < label_offset.x || pt.x >= c->pa.w - label_offset.x ||
|
||
|
pt.y < label_offset.y - glyph.h)
|
||
|
return;
|
||
|
|
||
|
PP_EDITOR(c)->caret_2d.x = (pt.x - label_offset.x) / glyph.w;
|
||
|
PP_EDITOR(c)->caret_2d.y = (pt.y - label_offset.y + PP_EDITOR(c)->scroll + glyph.h) / (glyph.h + btk_text_spacing);
|
||
|
PP_EDITOR(c)->caret_2d = btk_text_guard_2d_caret(PP_EDITOR(c)->par, PP_EDITOR(c)->caret_2d);
|
||
|
PP_EDITOR(c)->caret = btk_text_caret_2dto1d(PP_EDITOR(c)->par, PP_EDITOR(c)->caret_2d);
|
||
|
//btk_text_caret_1dto2d(PP_EDITOR(c)->par, PP_EDITOR(c)->caret);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_editor_input_key(btk_cell_t *c, uint32_t key)
|
||
|
{
|
||
|
btk_pp_editor_t *pp = PP_EDITOR(c);
|
||
|
int caret_type, modif = 0;
|
||
|
|
||
|
switch (key) {
|
||
|
case 0xff08:
|
||
|
pp->caret -= btk_text_del_char(pp->text, pp->caret, 0);
|
||
|
caret_type = 0;
|
||
|
modif = 1;
|
||
|
break;
|
||
|
case 0xff50:
|
||
|
pp->caret_2d.x = 0;
|
||
|
caret_type = 1;
|
||
|
break;
|
||
|
case 0xff51:
|
||
|
pp->caret--;
|
||
|
caret_type = 0;
|
||
|
break;
|
||
|
case 0xff52:
|
||
|
pp->caret_2d.y--;
|
||
|
caret_type = 1;
|
||
|
break;
|
||
|
case 0xff53:
|
||
|
pp->caret++;
|
||
|
caret_type = 0;
|
||
|
break;
|
||
|
case 0xff54:
|
||
|
pp->caret_2d.y++;
|
||
|
caret_type = 1;
|
||
|
break;
|
||
|
case 0xff57:
|
||
|
pp->caret_2d.x = pp->text_w;
|
||
|
caret_type = 1;
|
||
|
break;
|
||
|
case 0xffff:
|
||
|
btk_text_del_char(pp->text, pp->caret, 1);
|
||
|
caret_type = 0;
|
||
|
modif = 1;
|
||
|
break;
|
||
|
case 0xff0d:
|
||
|
pp->caret += btk_text_insert_char(pp->text, '\n', pp->caret, pp->text_w);
|
||
|
caret_type = 0;
|
||
|
modif = 1;
|
||
|
break;
|
||
|
case 0xff09:
|
||
|
pp->caret += btk_text_insert_char(pp->text, '\t', pp->caret, pp->text_w);
|
||
|
caret_type = 0;
|
||
|
modif = 1;
|
||
|
break;
|
||
|
default :
|
||
|
/* only allow ascii printable chars */
|
||
|
if (key < 32 || key >= 127)
|
||
|
return;
|
||
|
pp->caret += btk_text_insert_char(pp->text, key, pp->caret, pp->text_w);
|
||
|
caret_type = 0;
|
||
|
modif = 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (modif) {
|
||
|
btk_cell_editor_update_text(c);
|
||
|
}
|
||
|
|
||
|
if (caret_type) {
|
||
|
pp->caret_2d = btk_text_guard_2d_caret(pp->par, pp->caret_2d);
|
||
|
pp->caret = btk_text_caret_2dto1d(pp->par, pp->caret_2d);
|
||
|
} else {
|
||
|
pp->caret = btk_text_guard_1d_caret(pp->text, pp->caret);
|
||
|
pp->caret_2d = btk_text_caret_1dto2d(pp->par, pp->caret);
|
||
|
}
|
||
|
|
||
|
/* modify scroll to show caret if needed */
|
||
|
if (pp->caret_2d.y * (glyph.h + btk_text_spacing) < pp->scroll)
|
||
|
pp->scroll = pp->caret_2d.y * (glyph.h + btk_text_spacing);
|
||
|
if (pp->caret_2d.y * (glyph.h + btk_text_spacing) >= pp->scroll + c->pa.h - 2 * label_offset.y) {
|
||
|
pp->scroll = (pp->caret_2d.y + 1) * (glyph.h + btk_text_spacing) - c->pa.h + label_offset.y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_editor_reset_caret(btk_cell_t*c)
|
||
|
{
|
||
|
PP_EDITOR(c)->caret = 0;
|
||
|
PP_EDITOR(c)->caret_2d.x = 0;
|
||
|
PP_EDITOR(c)->caret_2d.y = 0;
|
||
|
PP_EDITOR(c)->scroll = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_editor_update_text(btk_cell_t *c)
|
||
|
{
|
||
|
btk_pp_editor_t *pp = PP_EDITOR(c);
|
||
|
int max_n = (c->pa.w - 2 * label_offset.x) / glyph.w + 1;
|
||
|
|
||
|
if (!pp->text)
|
||
|
return;
|
||
|
|
||
|
if (pp->par)
|
||
|
btk_text_destroy_par(pp->par);
|
||
|
|
||
|
pp->par = btk_text_get_par(pp->text, max_n);
|
||
|
pp->caret_2d = btk_text_caret_1dto2d(pp->par, pp->caret);
|
||
|
|
||
|
/* modify scroll to show caret if needed */
|
||
|
if (pp->caret_2d.y * (glyph.h + btk_text_spacing) < pp->scroll)
|
||
|
pp->scroll = pp->caret_2d.y * (glyph.h + btk_text_spacing);
|
||
|
if (pp->caret_2d.y * (glyph.h + btk_text_spacing) >= pp->scroll + c->pa.h - label_offset.y) {
|
||
|
pp->scroll = (pp->caret_2d.y + 1) * (glyph.h + btk_text_spacing) - c->pa.h + label_offset.y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
btk_field_t*
|
||
|
btk_cell_field_create(cairo_surface_t *c_srf, btk_area_t a)
|
||
|
{
|
||
|
btk_field_t *f = (btk_field_t *)malloc(sizeof(btk_field_t));
|
||
|
f->c_srf = cairo_surface_create_for_rectangle(c_srf, a.x, a.y, a.w, a.h);
|
||
|
f->c_ctx = cairo_create(f->c_srf);
|
||
|
|
||
|
cairo_set_font_options(f->c_ctx, font_opt);
|
||
|
cairo_set_font_size(f->c_ctx, btk_font_size);
|
||
|
cairo_select_font_face(f->c_ctx,
|
||
|
btk_font_name,
|
||
|
CAIRO_FONT_SLANT_NORMAL,
|
||
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_field_destroy(btk_field_t *f)
|
||
|
{
|
||
|
if (!f)
|
||
|
return;
|
||
|
|
||
|
cairo_destroy(f->c_ctx);
|
||
|
cairo_surface_destroy(f->c_srf);
|
||
|
free(f);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_input_button(btk_cell_t *c, int button, int combo, btk_pos_t pt)
|
||
|
{
|
||
|
if (button != 1)
|
||
|
return;
|
||
|
|
||
|
if (pt.x >= 2 * label_offset.x + glyph.w && pt.x < c->pa.w - label_offset.x)
|
||
|
PP_INPUT(c)->caret = (pt.x - 2 * label_offset.x - glyph.w) /
|
||
|
glyph.w + PP_INPUT(c)->scroll;
|
||
|
|
||
|
int text_n = strlen(PP_INPUT(c)->text);
|
||
|
if (PP_INPUT(c)->caret < 0)
|
||
|
PP_INPUT(c)->caret = 0;
|
||
|
if (PP_INPUT(c)->caret > text_n)
|
||
|
PP_INPUT(c)->caret = text_n;
|
||
|
|
||
|
/* TODO combo clicks selections */
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_input_input_key(btk_cell_t *c, uint32_t key)
|
||
|
{
|
||
|
btk_pp_input_t *pp = PP_INPUT(c);
|
||
|
|
||
|
switch (key) {
|
||
|
case 0xff08:
|
||
|
pp->caret -= btk_text_del_char(pp->text, pp->caret, 0);
|
||
|
break;
|
||
|
case 0xff50:
|
||
|
pp->caret = 0;
|
||
|
break;
|
||
|
case 0xff51:
|
||
|
pp->caret--;
|
||
|
break;
|
||
|
case 0xff53:
|
||
|
pp->caret++;
|
||
|
break;
|
||
|
case 0xff57:
|
||
|
pp->caret = pp->text_w;
|
||
|
break;
|
||
|
case 0xffff:
|
||
|
btk_text_del_char(pp->text, pp->caret, 1);
|
||
|
break;
|
||
|
default :
|
||
|
/* only allow ascii printable chars */
|
||
|
if (key < 32 || key >= 127)
|
||
|
return;
|
||
|
pp->caret += btk_text_insert_char(pp->text, key, pp->caret, pp->text_w);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int text_n = strlen(pp->text);
|
||
|
if (pp->caret < 0)
|
||
|
pp->caret = 0;
|
||
|
if (pp->caret > text_n)
|
||
|
pp->caret = text_n;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_input_reset_caret(btk_cell_t *c)
|
||
|
{
|
||
|
PP_INPUT(c)->caret = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_list_deselect(btk_cell_t *c)
|
||
|
{
|
||
|
PP_LIST(c)->item_sel = -1;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_list_input_button(btk_cell_t *c, int button, int combo, btk_pos_t pt)
|
||
|
{
|
||
|
btk_pp_list_t *pp = PP_LIST(c);
|
||
|
int prev_sel = pp->item_sel;
|
||
|
|
||
|
/* scrolling if appropriate button is clicked */
|
||
|
switch (button) {
|
||
|
case 4:
|
||
|
pp->scroll -= btk_scroll_speed;
|
||
|
return;
|
||
|
case 5:
|
||
|
pp->scroll += btk_scroll_speed;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* filter out remaining unwanted inputs */
|
||
|
if (button != 1)
|
||
|
return;
|
||
|
|
||
|
/* find item under pointer */
|
||
|
pp->item_sel = (pt.y + pp->scroll) / (btk_cp.h + btk_frame);
|
||
|
|
||
|
/* deselect if out of bounds */
|
||
|
if (pp->item_sel < 0 || pp->item_sel >= *(pp->items_n))
|
||
|
pp->item_sel = -1;
|
||
|
|
||
|
/* adjust scrolling so that select item is displayed in full */
|
||
|
// TODO
|
||
|
|
||
|
/* on selection change, exec sel func */
|
||
|
if (prev_sel != pp->item_sel && pp->func_sel)
|
||
|
pp->func_sel(pp->item_sel);
|
||
|
|
||
|
/* if double click, exec trigger func */
|
||
|
if (combo == 2 && pp->func_trigger)
|
||
|
pp->func_trigger(pp->item_sel);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
btk_cell_list_get_sel(btk_cell_t *c)
|
||
|
{
|
||
|
return PP_LIST(c)->item_sel;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_setup_font(cairo_t *c_ctx)
|
||
|
{
|
||
|
font_opt = cairo_font_options_create();
|
||
|
cairo_font_options_set_subpixel_order(font_opt, CAIRO_SUBPIXEL_ORDER_DEFAULT);
|
||
|
cairo_font_options_set_antialias(font_opt, CAIRO_ANTIALIAS_NONE);
|
||
|
cairo_font_options_set_hint_style(font_opt, CAIRO_HINT_STYLE_SLIGHT);
|
||
|
cairo_font_options_set_hint_metrics(font_opt, CAIRO_HINT_METRICS_ON);
|
||
|
|
||
|
cairo_set_font_options(c_ctx, font_opt);
|
||
|
cairo_set_font_size(c_ctx, btk_font_size);
|
||
|
cairo_select_font_face(c_ctx,
|
||
|
btk_font_name,
|
||
|
CAIRO_FONT_SLANT_NORMAL,
|
||
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||
|
|
||
|
cairo_font_extents_t fe;
|
||
|
cairo_font_extents(c_ctx, &fe);
|
||
|
glyph.h = fe.height;
|
||
|
glyph.w = fe.max_x_advance;
|
||
|
label_offset.x = (btk_cp.h - fe.ascent) / 2 + btk_text_offset_tweak.x;
|
||
|
label_offset.y = (btk_cp.h - fe.ascent) / 2 + btk_text_offset_tweak.y + fe.ascent;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_switch_toggle(btk_cell_t *c, int button)
|
||
|
{
|
||
|
if (button != 1)
|
||
|
return;
|
||
|
|
||
|
c->state ^= BTK_CELL_STATE_ON;
|
||
|
if (PP_SWITCH(c)->func)
|
||
|
PP_SWITCH(c)->func(((c->state & BTK_CELL_STATE_ON) >> 4), PP_SWITCH(c)->func_args);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_table_deselect(btk_cell_t *c)
|
||
|
{
|
||
|
PP_TABLE(c)->row_sel = -1;
|
||
|
}
|
||
|
|
||
|
char*
|
||
|
btk_cell_table_get_item(btk_cell_t *c, int col, int row)
|
||
|
{
|
||
|
if (col < 0 || row < 0 || col >= PP_TABLE(c)->cols_n || row >= *(PP_TABLE(c)->rows_n))
|
||
|
return NULL;
|
||
|
|
||
|
return *(PP_TABLE(c)->items) +
|
||
|
PP_TABLE(c)->items_w * (col + row * PP_TABLE(c)->cols_n);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_table_input_button(btk_cell_t *c, int button, int combo, btk_pos_t pt)
|
||
|
{
|
||
|
btk_pp_table_t *pp = PP_TABLE(c);
|
||
|
int prev_sel = pp->row_sel;
|
||
|
|
||
|
/* scrolling if appropriate button is clicked */
|
||
|
switch (button) {
|
||
|
case 4:
|
||
|
pp->scroll.y -= btk_scroll_speed;
|
||
|
return;
|
||
|
case 5:
|
||
|
pp->scroll.y += btk_scroll_speed;
|
||
|
return;
|
||
|
case 6:
|
||
|
pp->scroll.x -= btk_scroll_speed;
|
||
|
return;
|
||
|
case 7:
|
||
|
pp->scroll.x += btk_scroll_speed;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* TODO ugly af block, to redo */
|
||
|
/* if click on header */
|
||
|
if (pt.y < btk_cp.h) {
|
||
|
int ena;
|
||
|
/* find clicked column */
|
||
|
for (int i = 0; i < pp->cols_n; i++) {
|
||
|
ena = pp->cols_ena ? pp->cols_ena[i] : 1;
|
||
|
if (ena && pt.x > pp->cols_px[i] && pt.x <= pp->cols_px[i] + pp->cols_pw[i]) {
|
||
|
switch (button) {
|
||
|
case 1:
|
||
|
pp->cols_cw[i]++;
|
||
|
break;
|
||
|
case 2:
|
||
|
/* TODO sorting ? */
|
||
|
break;
|
||
|
case 3:
|
||
|
pp->cols_cw[i] -= pp->cols_cw[i] > 1 ? 1 : 0;
|
||
|
}
|
||
|
btk_cell_table_update_geometry(c);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* remaining item list actions */
|
||
|
/* filter out unwanted inputs */
|
||
|
if (button != 1)
|
||
|
return;
|
||
|
|
||
|
/* find item under pointer */
|
||
|
pp->row_sel = (pt.y + pp->scroll.y) / (btk_cp.h + btk_frame) -1;
|
||
|
|
||
|
/* deselect if out of bounds */
|
||
|
if (pp->row_sel < 0 || pp->row_sel >= *(pp->rows_n))
|
||
|
pp->row_sel = -1;
|
||
|
|
||
|
/* on selection change, exec sel func */
|
||
|
if (prev_sel != pp->row_sel && pp->func_sel)
|
||
|
pp->func_sel(pp->row_sel);
|
||
|
|
||
|
/* if double click, exec trigger func */
|
||
|
if (combo == 2 && pp->func_trigger)
|
||
|
pp->func_trigger(pp->row_sel);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
btk_cell_table_update_geometry(btk_cell_t *c)
|
||
|
{
|
||
|
btk_pp_table_t *pp = PP_TABLE(c);
|
||
|
unsigned int cw = 0; /* width in cell units */
|
||
|
unsigned int pw = 0; /* total minimum pixel width */
|
||
|
unsigned int ew = 0; /* extra width if tw > minimum width */
|
||
|
int ena;
|
||
|
|
||
|
/* calculate extra width in pixels */
|
||
|
for (int i = 0; i < pp->cols_n; i++) {
|
||
|
ena = pp->cols_ena ? pp->cols_ena[i] : 1;
|
||
|
cw += ena ? pp->cols_cw[i] : 0;
|
||
|
}
|
||
|
pw = cw * (btk_cp.w + btk_frame) - btk_frame;
|
||
|
ew = pw < c->pa.w ? c->pa.w - pw : 0;
|
||
|
pp->tw = pw + ew;
|
||
|
|
||
|
/* calculate each columns widths in pixels */
|
||
|
for (int i = 0; i < pp->cols_n; i++) {
|
||
|
pp->cols_pw[i] = pp->cols_cw[i] * (btk_cp.w + btk_frame) - btk_frame;
|
||
|
pp->cols_pw[i] += pp->sc == i ? ew : 0;
|
||
|
}
|
||
|
|
||
|
/* calculate columns positions */
|
||
|
int pos = 0;
|
||
|
for (int i = 0; i < pp->cols_n; i++) {
|
||
|
pp->cols_px[i] = pos;
|
||
|
ena = pp->cols_ena ? pp->cols_ena[i] : 1;
|
||
|
pos += ena ? pp->cols_pw[i] + btk_frame : 0;
|
||
|
}
|
||
|
}
|