express/src/bin/grid.c

385 lines
9.1 KiB
C
Raw Normal View History

#include "private.h"
#include "grid.h"
#include "config.h"
typedef struct _Grid_Att Grid_Att;
struct _Grid_Att
{
unsigned char fg, bg;
unsigned short bold : 1;
unsigned short faint : 1;
#if defined(SUPPORT_ITALIC)
unsigned short italic : 1;
#endif
#if defined(SUPPORT_DBLWIDTH)
unsigned short dblwidth : 1;
#endif
unsigned short underline : 1;
unsigned short blink : 1;
unsigned short blink2 : 1;
unsigned short inverse : 1;
unsigned short invisible : 1;
unsigned short strike : 1;
unsigned short fg256 : 1;
unsigned short bg256 : 1;
unsigned short fgintense : 1;
unsigned short bgintense : 1;
unsigned short autowrapped : 1;
unsigned short newline : 1;
unsigned short tab : 1;
#if defined(SUPPORT_80_132_COLUMNS)
unsigned short is_80_132_mode_allowed : 1;
#endif
};
typedef struct _Grid_Cell Grid_Cell;
struct _Grid_Cell
{
int codepoint;
Grid_Att att;
};
typedef struct _Grid Grid;
struct _Grid
{
Evas_Object_Smart_Clipped_Data __clipped_data;
Evas *evas;
Evas_Object *win;
Evas_Object *o_event;
int w, h;
Grid_Cell *cells;
struct
{
int size, chw, chh;
const char *name;
} font;
struct
{
int w, h;
Evas_Object *obj;
} grid;
struct
{
Eina_Bool active : 1;
} selection;
Ecore_Timer *delayed_size_tmr;
};
/* local function prototypes */
static void _smart_size(Evas_Object *obj, int w, int h, Eina_Bool force);
/* local variables */
static Evas_Smart *_smart = NULL;
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
/* local functions */
static Eina_Bool
_cb_delayed_size(void *data)
{
Grid *sd;
Evas_Object *obj;
Evas_Coord w = 0, h = 0;
obj = data;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
sd->delayed_size_tmr = NULL;
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
_smart_size(obj, (w / sd->font.chw), (h / sd->font.chh), EINA_FALSE);
return EINA_FALSE;
}
static void
_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
{
Evas_Event_Mouse_Down *ev;
ev = event;
if (ev->button != 3) return;
evas_object_smart_callback_call(data, "options", NULL);
}
static void
_cb_key_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
{
Evas_Event_Key_Down *ev;
ev = event;
if ((!evas_key_modifier_is_set(ev->modifiers, "Alt")) &&
(evas_key_modifier_is_set(ev->modifiers, "Control")) &&
(!evas_key_modifier_is_set(ev->modifiers, "Shift")))
{
if ((!strcmp(ev->key, "Prior")) || (!strcmp(ev->key, "Up")))
evas_object_smart_callback_call(data, "prev", NULL);
else if ((!strcmp(ev->key, "Next")) || (!strcmp(ev->key, "Down")))
evas_object_smart_callback_call(data, "next", NULL);
}
}
static void
_selection_set(Evas_Object *obj, Eina_Bool enabled)
{
Grid *sd;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
if (sd->selection.active == enabled) return;
sd->selection.active = enabled;
if (enabled)
evas_object_smart_callback_call(sd->win, "selection,on", NULL);
else
evas_object_smart_callback_call(sd->win, "selection,off", NULL);
}
static void
_smart_add(Evas_Object *obj)
{
Grid *sd;
/* try to allocate space for smart data */
if (!(sd = calloc(1, sizeof(Grid)))) return;
evas_object_smart_data_set(obj, sd);
_parent_sc.add(obj);
sd->evas = evas_object_evas_get(obj);
/* create textgrid */
sd->grid.obj = evas_object_textgrid_add(sd->evas);
evas_object_pass_events_set(sd->grid.obj, EINA_TRUE);
evas_object_propagate_events_set(sd->grid.obj, EINA_FALSE);
evas_object_smart_member_add(sd->grid.obj, obj);
evas_object_show(sd->grid.obj);
sd->o_event = evas_object_rectangle_add(sd->evas);
evas_object_repeat_events_set(sd->o_event, EINA_TRUE);
evas_object_color_set(sd->o_event, 0, 0, 0, 0);
evas_object_smart_member_add(sd->o_event, obj);
evas_object_show(sd->o_event);
/* TODO: finish callbacks */
evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_MOUSE_DOWN,
_cb_mouse_down, obj);
evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_KEY_DOWN,
_cb_key_down, obj);
}
static void
_smart_del(Evas_Object *obj)
{
Grid *sd;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
/* delete the size timer */
if (sd->delayed_size_tmr) ecore_timer_del(sd->delayed_size_tmr);
/* delete animator */
/* if (sd->anim) ecore_animator_del(sd->anim); */
/* delete objects */
if (sd->grid.obj) evas_object_del(sd->grid.obj);
if (sd->o_event) evas_object_del(sd->o_event);
if (sd->font.name) eina_stringshare_del(sd->font.name);
/* free grid cells */
if (sd->cells) free(sd->cells);
_parent_sc.del(obj);
}
static void
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
{
Grid *sd;
Evas_Coord ow, oh;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
/* get geometry of the object */
evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
if ((ow == w) && (oh == h)) return;
evas_object_smart_changed(obj);
if (!sd->delayed_size_tmr)
sd->delayed_size_tmr = ecore_timer_add(0.0, _cb_delayed_size, obj);
else
ecore_timer_reset(sd->delayed_size_tmr);
// ecore_timer_delay(sd->delayed_size_tmr, 0.0);
evas_object_resize(sd->o_event, ow, oh);
}
static void
_smart_move(Evas_Object *obj, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED)
{
evas_object_smart_changed(obj);
}
static void
_smart_calculate(Evas_Object *obj)
{
Grid *sd;
Evas_Coord ox, oy, ow, oh;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
evas_object_move(sd->grid.obj, ox, oy);
evas_object_resize(sd->grid.obj, sd->grid.w * sd->font.chw,
sd->grid.h * sd->font.chh);
evas_object_move(sd->o_event, ox, oy);
evas_object_resize(sd->o_event, ow, oh);
}
static void
_smart_init(void)
{
static Evas_Smart_Class sc;
evas_object_smart_clipped_smart_set(&_parent_sc);
sc = _parent_sc;
sc.name = "grid";
sc.version = EVAS_SMART_CLASS_VERSION;
sc.add = _smart_add;
sc.del = _smart_del;
sc.resize = _smart_resize;
sc.move = _smart_move;
sc.calculate = _smart_calculate;
_smart = evas_smart_class_new(&sc);
}
static void
_smart_size(Evas_Object *obj, int w, int h, Eina_Bool force)
{
Grid *sd;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
if (w < 1) w = 1;
if (h < 1) h = 1;
if (!force)
{
if ((w == sd->grid.w) && (h == sd->grid.h)) return;
}
evas_event_freeze(sd->evas);
sd->grid.w = w;
sd->grid.h = h;
evas_object_textgrid_size_set(sd->grid.obj, sd->grid.w, sd->grid.h);
evas_object_size_hint_min_set(obj, sd->font.chw, sd->font.chh);
evas_object_size_hint_request_set(obj, sd->font.chw * sd->grid.w,
sd->font.chh * sd->grid.h);
_selection_set(obj, EINA_FALSE);
/* TODO: call grid resize function to allocate cells */
_smart_calculate(obj);
evas_event_thaw(sd->evas);
}
/* external functions */
Evas_Object *
_grid_add(Evas *evas)
{
Evas_Object *obj;
Grid *sd;
if (!_smart) _smart_init();
obj = evas_object_smart_add(evas, _smart);
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return obj;
sd->w = 80;
sd->h = 24;
sd->cells = calloc(1, sizeof(Grid_Cell) * sd->w * sd->h);
if (!sd->cells) goto err;
_grid_update(obj);
_smart_size(obj, sd->w, sd->h, EINA_FALSE);
return obj;
err:
free(sd);
return obj;
}
void
_grid_update(Evas_Object *obj)
{
Grid *sd;
Evas_Coord w = 0, h = 0;
Evas_Coord ow = 0, oh = 0;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
if (sd->font.name) eina_stringshare_del(sd->font.name);
sd->font.name = NULL;
if (_ex_cfg->font.bitmap)
{
char buff[PATH_MAX];
snprintf(buff, sizeof(buff), "%s/fonts/%s",
elm_app_data_dir_get(), _ex_cfg->font.name);
sd->font.name = eina_stringshare_add(buff);
}
else
sd->font.name = eina_stringshare_add(_ex_cfg->font.name);
sd->font.size = _ex_cfg->font.size;
evas_object_scale_set(sd->grid.obj, elm_config_scale_get());
evas_object_textgrid_font_set(sd->grid.obj, sd->font.name, sd->font.size);
evas_object_textgrid_cell_size_get(sd->grid.obj, &w, &h);
if (w < 1) w = 1;
if (h < 1) h = 1;
sd->font.chw = w;
sd->font.chh = h;
evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
_smart_size(obj, ow / w, oh / h, EINA_TRUE);
}
void
_grid_window_set(Evas_Object *obj, Evas_Object *win)
{
Grid *sd;
/* try to get the objects smart data */
if (!(sd = evas_object_smart_data_get(obj))) return;
sd->win = win;
}