Start redesign, WIP

* Implement callback animation type
* Framebuffer items now have levels which specify the order of rendering
* Framebuffer items now have parent rectangle which they can't draw outside of
* Rectangles now support alpha blending
This commit is contained in:
Vojtech Bocek
2014-07-02 16:34:39 +02:00
parent c89614d18a
commit 781267384a
9 changed files with 643 additions and 292 deletions

View File

@@ -152,6 +152,12 @@ static void item_anim_on_finished(item_anim *anim)
fb_remove_item(anim->item);
}
static void call_anim_step(call_anim *anim, float interpolated)
{
if(anim->callback)
anim->callback(anim->data, interpolated);
}
static void anim_update(uint32_t diff, void *data)
{
struct anim_list *list = data;
@@ -201,6 +207,16 @@ static void anim_update(uint32_t diff, void *data)
case ANIM_TYPE_ITEM:
item_anim_step((item_anim*)anim, interpolated);
break;
case ANIM_TYPE_CALLBACK:
call_anim_step((call_anim*)anim, interpolated);
break;
}
if(anim->on_step_call)
{
pthread_mutex_unlock(&list->mutex);
anim->on_step_call(anim->on_step_data);
pthread_mutex_lock(&list->mutex);
}
// remove complete animations
@@ -216,7 +232,9 @@ static void anim_update(uint32_t diff, void *data)
switch(it->anim_type)
{
case ANIM_TYPE_ITEM:
pthread_mutex_unlock(&list->mutex);
item_anim_on_finished((item_anim*)anim);
pthread_mutex_lock(&list->mutex);
break;
}
@@ -256,7 +274,7 @@ void anim_stop(void)
pthread_mutex_unlock(&anim_list.mutex);
}
void anim_fb_item_removed(void *item)
void anim_cancel_for(void *fb_item, int only_not_started)
{
if(!anim_list.running)
return;
@@ -265,12 +283,12 @@ void anim_fb_item_removed(void *item)
return;
struct anim_list_it *it, *to_remove;
item_anim *anim;
pthread_mutex_lock(&anim_list.mutex);
for(it = anim_list.first; it; )
{
if(it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == item)
if (it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == fb_item &&
(!only_not_started || it->anim->start_offset != 0))
{
to_remove = it;
it = it->next;
@@ -347,3 +365,38 @@ void item_anim_add(item_anim *anim)
it->anim = (anim_header*)anim;
anim_list_append(it);
}
void item_anim_add_after(item_anim *anim)
{
struct anim_list_it *it;
pthread_mutex_lock(&anim_list.mutex);
for(it = anim_list.first; it; it = it->next)
{
if(it->anim_type == ANIM_TYPE_ITEM && ((item_anim*)it->anim)->item == anim->item)
{
const int u = it->anim->start_offset + it->anim->duration - it->anim->elapsed;
anim->start_offset = imax(anim->start_offset, u);
}
}
pthread_mutex_unlock(&anim_list.mutex);
item_anim_add(anim);
}
call_anim *call_anim_create(void *data, call_anim_callback callback, int duration, int interpolator)
{
call_anim *anim = mzalloc(sizeof(call_anim));
anim->data = data;
anim->callback = callback;
anim->duration = duration;
anim->interpolator = interpolator;
return anim;
}
void call_anim_add(call_anim *anim)
{
struct anim_list_it *it = mzalloc(sizeof(struct anim_list_it));
it->anim_type = ANIM_TYPE_CALLBACK;
it->anim = (anim_header*)anim;
anim_list_append(it);
}

View File

@@ -21,6 +21,7 @@
enum
{
ANIM_TYPE_ITEM,
ANIM_TYPE_CALLBACK,
};
enum
@@ -39,7 +40,9 @@ typedef void (*animation_callback)(void*); // data
uint32_t elapsed; \
int interpolator; \
void *on_finished_data; \
animation_callback on_finished_call;
animation_callback on_finished_call; \
void *on_step_data; \
animation_callback on_step_call;
typedef struct
{
@@ -60,13 +63,27 @@ typedef struct
int targetW, targetH;
} item_anim;
typedef void (*call_anim_callback)(void*, float); // data, interpolated
typedef struct
{
ANIM_HEADER
call_anim_callback callback;
void *data;
} call_anim;
void anim_init(void);
void anim_stop(void);
void anim_fb_item_removed(void *item);
void anim_cancel_for(void *fb_item, int only_not_started);
void anim_push_context(void);
void anim_pop_context(void);
item_anim *item_anim_create(void *fb_item, int duration, int interpolator);
void item_anim_add(item_anim *anim);
void item_anim_add_after(item_anim *anim);
call_anim *call_anim_create(void *data, call_anim_callback callback, int duration, int interpolator);
void call_anim_add(call_anim *anim);
#endif

View File

@@ -44,6 +44,9 @@
#define fb_memset(dst, what, len) android_memset32(dst, what, len)
#else
#define fb_memset(dst, what, len) android_memset16(dst, what, len)
#ifdef HAS_NEON_BLEND
extern void scanline_col32cb16blend_neon(uint16_t *dst, uint32_t *col, size_t ct);
#endif
#endif
@@ -51,15 +54,25 @@ uint32_t fb_width = 0;
uint32_t fb_height = 0;
int fb_rotation = 0; // in degrees, clockwise
fb_item_pos DEFAULT_FB_PARENT = {
.x = 0,
.y = 0,
};
static struct framebuffer fb;
static int fb_frozen = 0;
static int fb_force_generic = 0;
static fb_items_t fb_items = { NULL, NULL, NULL };
static fb_items_t **inactive_ctx = NULL;
static fb_context_t fb_ctx = {
.first_item = NULL,
.msgbox = NULL,
.mutex = PTHREAD_MUTEX_INITIALIZER
};
static fb_context_t **inactive_ctx = NULL;
static uint8_t **fb_rot_helpers = NULL;
static pthread_mutex_t fb_items_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t fb_update_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t fb_draw_thread;
static pthread_mutex_t fb_update_mutex = PTHREAD_MUTEX_INITIALIZER;
static volatile int fb_draw_requested = 0;
static volatile int fb_draw_run = 0;
static volatile int fb_draw_futex = 0;
@@ -179,6 +192,9 @@ int fb_open(int rotation)
fb_dump_info();
#endif
DEFAULT_FB_PARENT.w = fb_width;
DEFAULT_FB_PARENT.h = fb_height;
fb_update();
fb_draw_run = 1;
@@ -344,9 +360,9 @@ int fb_clone(char **buff)
int len = fb.size;
*buff = malloc(len);
pthread_mutex_lock(&fb_items_mutex);
pthread_mutex_lock(&fb_update_mutex);
memcpy(*buff, fb.buffer, len);
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_update_mutex);
return len;
}
@@ -371,6 +387,75 @@ px_type fb_convert_color(uint32_t c)
#endif
}
static void fb_ctx_put_it_before(fb_item_header *new_it, fb_item_header *next_it)
{
if(next_it->prev)
{
next_it->prev->next = new_it;
new_it->prev = next_it->prev;
}
new_it->next = next_it;
next_it->prev = new_it;
}
static void fb_ctx_put_it_after(fb_item_header *new_it, fb_item_header *prev_it)
{
if(prev_it->next)
{
prev_it->next->prev = new_it;
new_it->next = prev_it->next;
}
new_it->prev = prev_it;
prev_it->next = new_it;
}
void fb_ctx_add_item(fb_context_t *ctx, void *item)
{
fb_item_header *h = item;
pthread_mutex_lock(&ctx->mutex);
if(!ctx->first_item)
ctx->first_item = item;
else
{
fb_item_header *itr = ctx->first_item;
while(1)
{
if(itr->level > h->level)
{
fb_ctx_put_it_before(h, itr);
itr = NULL;
break;
}
if(itr->next)
itr = itr->next;
else
break;
}
if(itr)
fb_ctx_put_it_after(h, itr);
}
pthread_mutex_unlock(&ctx->mutex);
}
void fb_ctx_rm_item(fb_context_t *ctx, void *item)
{
fb_item_header *h = item;
pthread_mutex_lock(&ctx->mutex);
if(!h->prev)
ctx->first_item = h->next;
else
h->prev->next = h->next;
if(h->next)
h->next->prev = h->prev;
pthread_mutex_unlock(&ctx->mutex);
}
void fb_remove_item(void *item)
{
switch(((fb_item_header*)item)->type)
@@ -390,7 +475,7 @@ void fb_remove_item(void *item)
void fb_destroy_item(void *item)
{
anim_fb_item_removed(item);
anim_cancel_for(item, 0);
switch(((fb_item_header*)item)->type)
{
@@ -425,30 +510,84 @@ void fb_destroy_item(void *item)
free(item);
}
void fb_draw_rect(fb_rect *r)
{
px_type *bits = fb.buffer + (fb.stride*r->y) + r->x;
px_type color = fb_convert_color(r->color);
const int w = r->w*PIXEL_SIZE;
int i;
for(i = 0; i < r->h; ++i)
{
fb_memset(bits, color, w);
bits += fb.stride;
}
}
static inline int blend_png(int value1, int value2, int alpha) {
int r = (0xFF-alpha)*value1 + alpha*value2;
return (r+1 + (r >> 8)) >> 8; // divide by 255
}
void fb_draw_rect(fb_rect *r)
{
const uint8_t alpha = (r->color >> 24) & 0xFF;
const px_type color = fb_convert_color(r->color);
if(alpha == 0)
return;
#if PIXEL_SIZE == 2
const uint8_t alpha5b = alpha >> 3;
const uint8_t alpha6b = alpha >> 2;
#endif
const int min_x = r->x >= r->parent->x ? 0 : r->parent->x - r->x;
const int min_y = r->y >= r->parent->y ? 0 : r->parent->y - r->y;
const int max_x = imin(r->w, r->parent->x + r->parent->w - r->x);
const int max_y = imin(r->h, r->parent->y + r->parent->h - r->y);
const int rendered_w = max_x - min_x;
const int w = rendered_w*PIXEL_SIZE;
px_type *bits = fb.buffer + (fb.stride*(r->y + min_y)) + r->x + min_x;
int i, x;
uint8_t *comps_bits;
uint8_t *comps_clr = (uint8_t*)&color;
for(i = min_y; i < max_y; ++i)
{
if(alpha == 0xFF)
{
fb_memset(bits, color, w);
bits += fb.stride;
}
// Do the blending
else
{
#ifdef MR_DISABLE_ALPHA
fb_memset(bits, color, w);
bits += fb.stride;
#else
#if PIXEL_SIZE == 4
for(x = 0; x < rendered_w; ++x)
{
comps_bits = (uint8_t*)bits;
comps_bits[PX_IDX_R] = blend_png(comps_bits[PX_IDX_R], comps_clr[PX_IDX_R], alpha);
comps_bits[PX_IDX_G] = blend_png(comps_bits[PX_IDX_G], comps_clr[PX_IDX_G], alpha);
comps_bits[PX_IDX_B] = blend_png(comps_bits[PX_IDX_B], comps_clr[PX_IDX_B], alpha);
comps_bits[PX_IDX_A] = 0xFF;
++bits;
}
#else
#ifdef HAS_NEON_BLEND
scanline_col32cb16blend_neon((uint16_t*)bits, &r->color, rendered_w);
bits += rendered_w;
#else
for(x = 0; x < rendered_w; ++x)
{
*bits = (((31-alpha5b)*(*bits & 0x1F) + (alpha5b*(*img & 0x1F))) / 31) |
((((63-alpha6b)*((*bits & 0x7E0) >> 5) + (alpha6b*((*img & 0x7E0) >> 5))) / 63) << 5) |
((((31-alpha5b)*((*bits & 0xF800) >> 11) + (alpha5b*((*img & 0xF800) >> 11))) / 31) << 11);
++bits;
}
#endif
#endif // PIXEL_SIZE
bits += fb.stride - rendered_w;
#endif // MR_DISABLE_ALPHA
}
}
}
void fb_draw_img(fb_img *i)
{
int y, x;
px_type *bits = fb.buffer + (fb.stride*i->y) + i->x;
px_type *img = i->data;
const int w = i->w*PIXEL_SIZE;
uint8_t alpha;
uint8_t *comps_img, *comps_bits;
@@ -459,13 +598,14 @@ void fb_draw_img(fb_img *i)
const uint8_t max_alpha = 31;
#endif
const int min_x = i->x >= 0 ? 0 : i->x + i->w;
const int min_y = i->y >= 0 ? 0 : i->y + i->h;
const int max_x = imin(i->w, fb_width - i->x);
const int max_y = imin(i->h, fb_height - i->y);
const int min_x = i->x >= i->parent->x ? 0 : i->parent->x - i->x;
const int min_y = i->y >= i->parent->y ? 0 : i->parent->y - i->y;
const int max_x = imin(i->w, i->parent->x + i->parent->w - i->x);
const int max_y = imin(i->h, i->parent->y + i->parent->h - i->y);
const int rendered_w = max_x - min_x;
img = (px_type*)(((uint32_t*)img) + min_y * i->w);
px_type *bits = fb.buffer + (fb.stride*(i->y + min_y)) + i->x + min_x;
px_type *img = (px_type*)(((uint32_t*)i->data) + (min_y * i->w) + min_x);
for(y = min_y; y < max_y; ++y)
{
@@ -517,42 +657,17 @@ void fb_draw_img(fb_img *i)
}
}
int fb_generate_item_id()
int fb_generate_item_id(void)
{
pthread_mutex_lock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
static int id = 0;
int res = id++;
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
return res;
}
fb_img *fb_add_text(int x, int y, uint32_t color, int size, const char *fmt, ...)
{
int ret;
fb_img *res;
char txt[512];
va_list ap;
char *buff = txt;
txt[0] = 0;
va_start(ap, fmt);
ret = vsnprintf(txt, sizeof(txt), fmt, ap);
if(ret >= (int)sizeof(txt))
{
buff = malloc(ret+1);
vsnprintf(buff, ret+1, fmt, ap);
}
va_end(ap);
res = fb_add_text_long(x, y, color, size, buff);
if(ret >= (int)sizeof(txt))
free(buff);
return res;
}
fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justify, const char *fmt, ...)
fb_img *fb_add_text_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *fmt, ...)
{
int ret;
fb_img *res;
@@ -571,29 +686,31 @@ fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justif
}
va_end(ap);
res = fb_add_text_long_justified(x, y, color, size, justify, buff);
res = fb_add_text_long_lvl_justified(level, x, y, color, size, justify, buff);
if(ret >= (int)sizeof(txt))
free(buff);
return res;
}
fb_img *fb_add_text_long_justified(int x, int y, uint32_t color, int size, int justify, const char *text)
fb_img *fb_add_text_long_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *text)
{
fb_img *img = fb_text_create_item(x, y, color, size, justify, text);
if(img)
{
pthread_mutex_lock(&fb_items_mutex);
list_add(img, &fb_items.imgs);
pthread_mutex_unlock(&fb_items_mutex);
img->level = level;
fb_ctx_add_item(&fb_ctx, img);
}
return img;
}
fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color)
fb_rect *fb_add_rect_lvl(int level, int x, int y, int w, int h, uint32_t color)
{
fb_rect *r = malloc(sizeof(fb_rect));
fb_rect *r = mzalloc(sizeof(fb_rect));
r->id = fb_generate_item_id();
r->type = FB_IT_RECT;
r->parent = &DEFAULT_FB_PARENT;
r->level = level;
r->x = x;
r->y = y;
@@ -601,10 +718,7 @@ fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color)
r->h = h;
r->color = color;
pthread_mutex_lock(&fb_items_mutex);
list_add(r, &fb_items.rects);
pthread_mutex_unlock(&fb_items_mutex);
fb_ctx_add_item(&fb_ctx, r);
return r;
}
@@ -631,7 +745,10 @@ void fb_add_rect_notfilled(int x, int y, int w, int h, uint32_t color, int thick
fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data)
{
fb_img *result = mzalloc(sizeof(fb_img));
result->id = fb_generate_item_id();
result->type = FB_IT_IMG;
result->parent = &DEFAULT_FB_PARENT;
result->level = LEVEL_PNG;
result->x = x;
result->y = y;
result->img_type = img_type;
@@ -639,10 +756,7 @@ fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data)
result->w = w;
result->h = h;
pthread_mutex_lock(&fb_items_mutex);
list_add(result, &fb_items.imgs);
pthread_mutex_unlock(&fb_items_mutex);
fb_ctx_add_item(&fb_ctx, result);
return result;
}
@@ -660,9 +774,8 @@ void fb_rm_rect(fb_rect *r)
if(!r)
return;
pthread_mutex_lock(&fb_items_mutex);
list_rm_noreorder(r, &fb_items.rects, &fb_destroy_item);
pthread_mutex_unlock(&fb_items_mutex);
fb_ctx_rm_item(&fb_ctx, r);
fb_destroy_item(r);
}
void fb_rm_text(fb_img *i)
@@ -675,17 +788,16 @@ void fb_rm_img(fb_img *i)
if(!i)
return;
pthread_mutex_lock(&fb_items_mutex);
list_rm_noreorder(i, &fb_items.imgs, &fb_destroy_item);
pthread_mutex_unlock(&fb_items_mutex);
fb_ctx_rm_item(&fb_ctx, i);
fb_destroy_item(i);
}
#define BOX_BORDER (2*DPI_MUL)
#define SHADOW (10*DPI_MUL)
fb_msgbox *fb_create_msgbox(int w, int h, int bgcolor)
{
if(fb_items.msgbox)
return fb_items.msgbox;
if(fb_ctx.msgbox)
return fb_ctx.msgbox;
fb_msgbox *box = mzalloc(sizeof(fb_msgbox));
@@ -704,9 +816,9 @@ fb_msgbox *fb_create_msgbox(int w, int h, int bgcolor)
box->background[2] = fb_add_rect(x+BOX_BORDER, y+BOX_BORDER,
w-BOX_BORDER*2, h-BOX_BORDER*2, bgcolor);
pthread_mutex_lock(&fb_items_mutex);
fb_items.msgbox = box;
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
fb_ctx.msgbox = box;
pthread_mutex_unlock(&fb_ctx.mutex);
return box;
}
@@ -719,7 +831,7 @@ fb_img *fb_msgbox_add_text(int x, int y, int size, char *fmt, ...)
vsnprintf(txt, sizeof(txt), fmt, ap);
va_end(ap);
fb_msgbox *box = fb_items.msgbox;
fb_msgbox *box = fb_ctx.msgbox;
fb_img *t = fb_text_create_item(x, y, WHITE, size, JUSTIFY_LEFT, txt);
@@ -732,9 +844,9 @@ fb_img *fb_msgbox_add_text(int x, int y, int size, char *fmt, ...)
t->x += box->x;
t->y += box->y;
pthread_mutex_lock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
list_add(t, &box->imgs);
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
return t;
}
@@ -743,24 +855,24 @@ void fb_msgbox_rm_text(fb_img *text)
if(!text)
return;
pthread_mutex_lock(&fb_items_mutex);
if(fb_items.msgbox)
list_rm_noreorder(text, &fb_items.msgbox->imgs, &fb_destroy_item);
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
if(fb_ctx.msgbox)
list_rm_noreorder(text, &fb_ctx.msgbox->imgs, &fb_destroy_item);
pthread_mutex_unlock(&fb_ctx.mutex);
}
void fb_destroy_msgbox(void)
{
pthread_mutex_lock(&fb_items_mutex);
if(!fb_items.msgbox)
pthread_mutex_lock(&fb_ctx.mutex);
if(!fb_ctx.msgbox)
{
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
return;
}
fb_msgbox *box = fb_items.msgbox;
fb_items.msgbox = NULL;
pthread_mutex_unlock(&fb_items_mutex);
fb_msgbox *box = fb_ctx.msgbox;
fb_ctx.msgbox = NULL;
pthread_mutex_unlock(&fb_ctx.mutex);
list_clear(&box->imgs, &fb_destroy_item);
@@ -773,10 +885,15 @@ void fb_destroy_msgbox(void)
void fb_clear(void)
{
pthread_mutex_lock(&fb_items_mutex);
list_clear(&fb_items.rects, &fb_destroy_item);
list_clear(&fb_items.imgs, &fb_destroy_item);
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
fb_item_header *it, *next;
for(it = fb_ctx.first_item; it; it = next)
{
next = it->next;
fb_destroy_item(it);
}
fb_ctx.first_item = NULL;
pthread_mutex_unlock(&fb_ctx.mutex);
fb_destroy_msgbox();
@@ -792,9 +909,7 @@ static inline int blend(int value1, int value2) {
return (r+1 + (r >> 8)) >> 8; // divide by 255
}
#else
#ifdef HAS_NEON_BLEND
extern void scanline_col32cb16blend_neon(uint16_t *dst, uint32_t *col, size_t ct);
#else
#ifndef HAS_NEON_BLEND
#define ALPHA5 0x04
#define ALPHA6 0x08
#define BLEND_CLR5 0x03
@@ -841,24 +956,31 @@ void fb_draw_overlay(void)
static void fb_draw(void)
{
uint32_t i;
pthread_mutex_lock(&fb_items_mutex);
fb_item_header *it;
pthread_mutex_lock(&fb_ctx.mutex);
fb_fill(BLACK);
fb_fill(0xFFE0E0E0);
// rectangles
for(i = 0; fb_items.rects && fb_items.rects[i]; ++i)
fb_draw_rect(fb_items.rects[i]);
// images
for(i = 0; fb_items.imgs && fb_items.imgs[i]; ++i)
fb_draw_img(fb_items.imgs[i]);
for(it = fb_ctx.first_item; it; it = it->next)
{
switch(it->type)
{
case FB_IT_RECT:
fb_draw_rect((fb_rect*)it);
break;
case FB_IT_IMG:
fb_draw_img((fb_img*)it);
break;
}
}
// msg box
if(fb_items.msgbox)
if(fb_ctx.msgbox)
{
fb_draw_overlay();
fb_msgbox *box = fb_items.msgbox;
fb_msgbox *box = fb_ctx.msgbox;
for(i = 0; i < ARRAY_SIZE(box->background); ++i)
fb_draw_rect(box->background[i]);
@@ -867,7 +989,7 @@ static void fb_draw(void)
fb_draw_img(box->imgs[i]);
}
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
pthread_mutex_lock(&fb_update_mutex);
fb_update();
@@ -884,16 +1006,16 @@ void fb_freeze(int freeze)
void fb_push_context(void)
{
fb_items_t *ctx = mzalloc(sizeof(fb_items_t));
fb_context_t *ctx = mzalloc(sizeof(fb_context_t));
pthread_mutex_lock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
list_move(&fb_items.rects, &ctx->rects);
list_move(&fb_items.imgs, &ctx->imgs);
ctx->msgbox = fb_items.msgbox;
fb_items.msgbox = NULL;
ctx->first_item = fb_ctx.first_item;
ctx->msgbox = fb_ctx.msgbox;
fb_ctx.first_item = NULL;
fb_ctx.msgbox = NULL;
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
list_add(ctx, &inactive_ctx);
}
@@ -906,15 +1028,14 @@ void fb_pop_context(void)
fb_clear();
int idx = list_item_count(inactive_ctx)-1;
fb_items_t *ctx = inactive_ctx[idx];
fb_context_t *ctx = inactive_ctx[idx];
pthread_mutex_lock(&fb_items_mutex);
pthread_mutex_lock(&fb_ctx.mutex);
list_move(&ctx->rects, &fb_items.rects);
list_move(&ctx->imgs, &fb_items.imgs);
fb_items.msgbox = ctx->msgbox;
fb_ctx.first_item = ctx->first_item;
fb_ctx.msgbox = ctx->msgbox;
pthread_mutex_unlock(&fb_items_mutex);
pthread_mutex_unlock(&fb_ctx.mutex);
list_rm_noreorder(ctx, &inactive_ctx, &free);

View File

@@ -20,6 +20,7 @@
#include <linux/fb.h>
#include <stdarg.h>
#include <pthread.h>
#if defined(RECOVERY_BGRA) || defined(RECOVERY_RGBX)
#define PIXEL_SIZE 4
@@ -103,7 +104,7 @@ enum
SIZE_SMALL = 6,
SIZE_NORMAL = 10,
SIZE_BIG = 13,
SIZE_EXTRA = 18,
SIZE_EXTRA = 15,
};
extern uint32_t fb_width;
@@ -140,16 +141,40 @@ enum
JUSTIFY_RIGHT,
};
#define FB_ITEM_HEAD \
int id; \
int type; \
enum
{
LEVEL_RECT = 0,
LEVEL_PNG = 1,
LEVEL_TEXT = 2,
};
struct fb_item_header;
#define FB_ITEM_POS \
int x, y; \
int w, h;
typedef struct
{
FB_ITEM_POS
} fb_item_pos;
extern fb_item_pos DEFAULT_FB_PARENT;
#define FB_ITEM_HEAD \
FB_ITEM_POS \
int id; \
int type; \
int level; \
fb_item_pos *parent; \
struct fb_item_header *prev; \
struct fb_item_header *next;
struct fb_item_header
{
FB_ITEM_HEAD
} fb_item_header;
};
typedef struct fb_item_header fb_item_header;
typedef struct
{
@@ -193,25 +218,31 @@ typedef struct
typedef struct
{
fb_rect **rects;
fb_img **imgs;
fb_item_header *first_item;
fb_msgbox *msgbox;
} fb_items_t;
pthread_mutex_t mutex;
} fb_context_t;
void fb_remove_item(void *item);
int fb_generate_item_id();
int fb_generate_item_id(void);
fb_img *fb_add_text_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *fmt, ...);
#define fb_add_text_justified(x, y, color, size, justify, fmt, args...) fb_add_text_lvl_justified(LEVEL_TEXT, x, y, color, size, justify, fmt, ##args)
#define fb_add_text(x, y, color, size, fmt, args...) fb_add_text_lvl_justified(LEVEL_TEXT, x, y, color, size, JUSTIFY_LEFT, fmt, ##args)
#define fb_add_text_lvl(level, x, y, color, size, fmt, args...) fb_add_text_lvl_justified(level, x, y, color, size, JUSTIFY_LEFT, fmt, ##args)
fb_img *fb_add_text_long_lvl_justified(int level, int x, int y, uint32_t color, int size, int justify, const char *text);
#define fb_add_text_long(x, y, color, size, text) fb_add_text_long_lvl_justified(LEVEL_TEXT, x, y, color, size, JUSTIFY_LEFT, text)
fb_img *fb_add_text(int x, int y, uint32_t color, int size, const char *fmt, ...);
fb_img *fb_add_text_justified(int x, int y, uint32_t color, int size, int justify, const char *fmt, ...);
fb_img *fb_add_text_long(int x, int y, uint32_t color, int size, const char *text);
fb_img *fb_add_text_long_justified(int x, int y, uint32_t color, int size, int justify, const char *text);
fb_img *fb_text_create_item(int x, int y, uint32_t color, int size, int justify, const char *txt);
void fb_text_set_content(fb_img *img, const char *text);
void fb_text_set_color(fb_img *img, uint32_t color);
void fb_text_drop_cache_unused(void);
void fb_text_destroy(fb_img *i);
fb_rect *fb_add_rect(int x, int y, int w, int h, uint32_t color);
fb_rect *fb_add_rect_lvl(int level, int x, int y, int w, int h, uint32_t color);
#define fb_add_rect(x, y, w, h, color) fb_add_rect_lvl(LEVEL_RECT, x, y, w, h, color)
fb_img *fb_add_img(int x, int y, int w, int h, int img_type, px_type *data);
fb_img *fb_add_png_img(int x, int y, int w, int h, const char *path);
void fb_add_rect_notfilled(int x, int y, int w, int h, uint32_t color, int thickness, fb_rect ***list);
@@ -237,6 +268,9 @@ int fb_clone(char **buff);
void fb_push_context(void);
void fb_pop_context(void);
void fb_ctx_add_item(fb_context_t *ctx, void *item);
void fb_ctx_rm_item(fb_context_t *ctx, void *item);
px_type *fb_png_get(const char *path, int w, int h);
void fb_png_release(px_type *data);
void fb_png_drop_unused(void);

View File

@@ -281,11 +281,6 @@ static void destroy_line(struct text_line *line)
free(line);
}
fb_img *fb_add_text_long(int x, int y, uint32_t color, int size, const char *text)
{
return fb_add_text_long_justified(x, y, color, size, JUSTIFY_LEFT, text);
}
typedef struct
{
char *text;
@@ -298,7 +293,10 @@ typedef struct
fb_img *fb_text_create_item(int x, int y, uint32_t color, int size, int justify, const char *text)
{
fb_img *result = mzalloc(sizeof(fb_img));
result->id = fb_generate_item_id();
result->parent = &DEFAULT_FB_PARENT;
result->type = FB_IT_IMG;
result->level = LEVEL_TEXT;
result->x = x;
result->y = y;
result->img_type = FB_IMG_TYPE_TEXT;

View File

@@ -25,10 +25,11 @@
#include "multirom_ui.h"
#include "workers.h"
#include "input.h"
#include "animation.h"
#define MARK_W (10*DPI_MUL)
#define MARK_H (50*DPI_MUL)
#define PADDING (20*DPI_MUL)
#define PADDING (25*DPI_MUL)
#define LINE_W (2*DPI_MUL)
#define SCROLL_DIST (20*DPI_MUL)
#define OVERSCROLL_H (130*DPI_MUL)
@@ -68,7 +69,8 @@ void listview_init_ui(listview *view)
{
int x = view->x + view->w - PADDING/2 - LINE_W/2;
fb_rect *scroll_line = fb_add_rect(x, view->y, LINE_W, view->h, GRAYISH);
fb_rect *scroll_line = fb_add_rect(x, view->y, LINE_W, view->h, GRAY);
scroll_line->parent = view;
list_add(scroll_line, &view->ui_items);
view->keyact_item_selected = -1;
@@ -76,6 +78,12 @@ void listview_init_ui(listview *view)
view->touch.id = -1;
view->touch.last_y = -1;
if(!view->bg_rect)
{
view->bg_rect = fb_add_rect(view->x, view->y, view->w - PADDING, view->h, 0xFFE0E0E0);
view->bg_rect->parent = view;
}
add_touch_handler(&listview_touch_handler, view);
}
@@ -91,6 +99,7 @@ void listview_destroy(listview *view)
fb_rm_rect(view->scroll_mark);
fb_rm_rect(view->overscroll_marks[0]);
fb_rm_rect(view->overscroll_marks[1]);
fb_rm_rect(view->bg_rect);
free(view);
}
@@ -101,6 +110,7 @@ listview_item *listview_add_item(listview *view, int id, void *data)
it->id = id;
it->data = data;
it->flags = 0;
it->parent_rect = view;
if(!view->items)
keyaction_add(view->x, view->y, listview_keyaction_call, view);
@@ -126,9 +136,9 @@ void listview_update_ui(listview *view)
for(i = 0; view->items && view->items[i]; ++i)
{
it = view->items[i];
it_h = (*view->item_height)(it->data);
it_h = (*view->item_height)(it);
visible = (int)(view->pos <= y && y+it_h-view->pos <= view->h);
visible = (int)(view->pos <= y+it_h && y-view->pos <= view->h);
if(!visible && (it->flags & IT_VISIBLE))
(*view->item_hide)(it->data);
@@ -160,11 +170,14 @@ void listview_enable_scroll(listview *view, int enable)
if(enable)
{
int x = view->x + view->w - PADDING/2 - MARK_W/2;
view->scroll_mark = fb_add_rect(x, view->y, MARK_W, MARK_H, GRAYISH);
view->scroll_mark = fb_add_rect(x, view->y, MARK_W, MARK_H, GRAY);
view->scroll_mark->parent = view;
view->overscroll_marks[0] = fb_add_rect(view->x, view->y, 0, OVERSCROLL_MARK_H, CLR_SECONDARY);
view->overscroll_marks[0]->parent = view;
view->overscroll_marks[1] = fb_add_rect(view->x, view->y+view->h-OVERSCROLL_MARK_H,
0, OVERSCROLL_MARK_H, CLR_SECONDARY);
view->overscroll_marks[1]->parent = view;
workers_add(listview_bounceback, view);
}
else
@@ -223,6 +236,8 @@ int listview_touch_handler(touch_event *ev, void *data)
if(view->touch.hover)
{
view->touch.hover->flags |= IT_HOVER;
view->touch.hover->touchX = ev->x;
view->touch.hover->touchY = ev->y;
listview_update_ui(view);
}
listview_keyaction_call(view, KEYACT_CLEAR);
@@ -280,6 +295,8 @@ void listview_select_item(listview *view, listview_item *it)
view->selected->flags &= ~(IT_SELECTED);
it->flags |= IT_SELECTED;
view->bg_rect->color = 0xFFE0E0E0;
view->selected = it;
}
@@ -324,10 +341,10 @@ int listview_ensure_visible(listview *view, listview_item *it)
{
if(it == view->items[i])
break;
y += view->item_height(view->items[i]->data);
y += view->item_height(view->items[i]);
}
int last_h = view->items[i] ? view->item_height(view->items[i]->data) : 0;
int last_h = view->items[i] ? view->item_height(view->items[i]) : 0;
if((y + last_h) - view->pos > view->h)
view->pos = (y + last_h) - view->h;
@@ -355,7 +372,7 @@ listview_item *listview_item_at(listview *view, int y_pos)
for(i = 0; view->items && view->items[i]; ++i)
{
it = view->items[i];
it_h = (*view->item_height)(it->data);
it_h = (*view->item_height)(it);
if(y < y_pos && y+it_h > y_pos)
return it;
@@ -427,9 +444,9 @@ void listview_update_keyact_frame(listview *view)
int i;
int y = view->y;
for(i = 0; i < view->keyact_item_selected && view->items[i]; ++i)
y += view->item_height(view->items[i]->data);
y += view->item_height(view->items[i]);
int h = view->item_height(view->items[i]->data);
int h = view->item_height(view->items[i]);
y -= view->pos;
// top
@@ -447,11 +464,13 @@ void listview_update_keyact_frame(listview *view)
listview_update_ui(view);
}
#define ROM_ITEM_H (100*DPI_MUL)
#define ROM_ITEM_H (110*DPI_MUL)
#define ROM_ITEM_GROW (40*DPI_MUL)
#define ROM_BOX_PADDING (5*DPI_MUL)
#define ROM_ITEM_SEL_W (8*DPI_MUL)
#define ROM_ICON_PADDING (12*DPI_MUL)
#define ROM_ICON_PADDING (20*DPI_MUL)
#define ROM_ICON_H (ROM_ITEM_H-(ROM_ICON_PADDING*2))
#define ROM_TEXT_PADDING (100*DPI_MUL)
#define ROM_TEXT_PADDING (130*DPI_MUL)
typedef struct
{
char *text;
@@ -459,10 +478,14 @@ typedef struct
char *icon_path;
fb_text *text_it;
fb_text *part_it;
fb_rect *bottom_line;
fb_rect *hover_rect;
fb_rect *sel_rect;
fb_rect *sel_rect_sh;
fb_text *click_text;
fb_rect *click_text_rect;
fb_img *icon;
int hover_removed;
int it_sel_size;
} rom_item_data;
void *rom_item_create(const char *text, const char *partition, const char *icon)
@@ -471,6 +494,7 @@ void *rom_item_create(const char *text, const char *partition, const char *icon)
memset(data, 0, sizeof(rom_item_data));
data->text = strdup(text);
data->it_sel_size = ROM_ITEM_H;
if(partition)
data->partition = strdup(partition);
if(icon)
@@ -478,52 +502,205 @@ void *rom_item_create(const char *text, const char *partition, const char *icon)
return data;
}
static void rom_item_null_rect(void *data)
{
fb_rect **rect = data;
*rect = NULL;
}
static void rom_item_grow(void *it_v)
{
listview_item *it = it_v;
rom_item_data *d = (rom_item_data*)it->data;
d->sel_rect_sh->x = d->sel_rect->x+5;
d->sel_rect_sh->y = d->sel_rect->y+5;
d->sel_rect_sh->w = d->sel_rect->w;
d->sel_rect_sh->h = d->sel_rect->h;
//d->it_sel_size = d->sel_rect->h;
//listview_update_ui((listview*)it->parent_rect);
}
static void rom_item_shrink(void *it_v, float interpolated)
{
listview_item *it = it_v;
rom_item_data *d = (rom_item_data*)it->data;
if(d->sel_rect_sh)
{
d->sel_rect_sh->h = d->sel_rect->h;
d->sel_rect_sh->y = d->sel_rect->y+5;
}
d->it_sel_size = (ROM_ITEM_H + ROM_ITEM_GROW) - ROM_ITEM_GROW*interpolated;
listview_update_ui((listview*)it->parent_rect);
}
static void rom_item_shrink_finished(void *it_v)
{
listview_item *it = it_v;
rom_item_data *d = (rom_item_data*)it->data;
fb_rm_rect(d->sel_rect);
fb_rm_rect(d->sel_rect_sh);
fb_rm_text(d->click_text);
fb_rm_rect(d->click_text_rect);
d->sel_rect = NULL;
d->sel_rect_sh = NULL;
d->click_text = NULL;
d->click_text_rect = NULL;
}
static void rom_item_alpha(void *it_v, float interpolated)
{
listview_item *it = it_v;
rom_item_data *d = (rom_item_data*)it->data;
uint32_t alpha = 0xFF*interpolated;
if(d->hover_removed)
alpha = 0xFF - alpha;
alpha <<= 24;
d->sel_rect->color = (d->sel_rect->color & ~(0xFF << 24)) | alpha;
d->sel_rect_sh->color = (d->sel_rect_sh->color & ~(0xFF << 24)) | alpha;
}
static void rom_item_alpha_finished(void *it_v)
{
listview_item *it = it_v;
rom_item_data *d = (rom_item_data*)it->data;
d->sel_rect_sh->color = (d->sel_rect_sh->color & ~(0xFF << 24)) | (0xFF << 24);
}
void rom_item_draw(int x, int y, int w, listview_item *it)
{
rom_item_data *d = (rom_item_data*)it->data;
const int item_h = rom_item_height(it);
if(!d->text_it)
{
d->text_it = fb_add_text(x+ROM_TEXT_PADDING, 0, WHITE, SIZE_BIG, d->text);
d->bottom_line = fb_add_rect(x, 0, w, 1, 0xFF1B1B1B);
d->text_it = fb_add_text(x+ROM_TEXT_PADDING, 0, BLACK, SIZE_BIG, d->text);
d->text_it->parent = it->parent_rect;
if(d->icon_path)
{
d->icon = fb_add_png_img(x+ROM_ICON_PADDING, 0, ROM_ICON_H, ROM_ICON_H, d->icon_path);
d->icon->parent = it->parent_rect;
}
if(d->partition)
{
d->part_it = fb_add_text(x+ROM_TEXT_PADDING, 0, GRAY, SIZE_SMALL, d->partition);
d->part_it->parent = it->parent_rect;
}
}
center_text(d->text_it, -1, y, -1, ROM_ITEM_H);
d->bottom_line->y = y+ROM_ITEM_H-2;
center_text(d->text_it, -1, y, -1, item_h);
if(d->icon)
d->icon->y = y + (ROM_ITEM_H/2 - ROM_ICON_H/2);
d->icon->y = y + (item_h/2 - ROM_ICON_H/2);
if(d->part_it)
d->part_it->y = d->text_it->y + SIZE_BIG*16 + 2;
if(it->flags & IT_HOVER)
/* if(it->flags & IT_HOVER)
{
if(!d->hover_rect)
d->hover_rect = fb_add_rect(x, 0, w, rom_item_height(it->data), CLR_SECONDARY);
d->hover_rect->y = y;
{
d->hover_rect = fb_add_rect(it->touchX, it->touchY, 1, 1, 0xFFE0E0E0);
INFO("touch %dx%d\n", it->touchX, it->touchY);
d->hover_rect->parent = it->parent_rect;
item_anim *anim = item_anim_create(d->hover_rect, 300, INTERPOLATOR_DECELERATE);
anim->start_offset = 150;
anim->targetX = x;
anim->targetY = y;
anim->targetW = w;
anim->targetH = item_h;
item_anim_add(anim);
d->hover_removed = 0;
}
else
d->hover_rect->y = y;
}
else if(d->hover_rect)
{
fb_rm_rect(d->hover_rect);
d->hover_rect = NULL;
}
if(!d->hover_removed)
{
anim_cancel_for(d->hover_rect, 1);
item_anim *anim = item_anim_create(d->hover_rect, 100, INTERPOLATOR_ACCELERATE);
anim->targetX = it->touchX;
anim->targetY = it->touchY;
anim->targetW = 0;
anim->targetH = 0;
anim->destroy_item_when_finished = 1;
anim->on_finished_data = &d->hover_rect;
anim->on_finished_call = rom_item_null_rect;
item_anim_add_after(anim);
d->hover_removed = 1;
}
else
{
d->hover_rect->y = y;
}
}*/
if(it->flags & IT_SELECTED)
{
if(!d->sel_rect)
d->sel_rect = fb_add_rect(x, 0, ROM_ITEM_SEL_W, ROM_ITEM_H, CLR_PRIMARY);
d->sel_rect->y = y;
{
d->sel_rect_sh = fb_add_rect(x+7, y+7, w, item_h, GRAYISH & ~(0xFF << 24));
d->sel_rect = fb_add_rect(x+7, y+7, w, item_h, WHITE & ~(0xFF << 24));
d->sel_rect->parent = it->parent_rect;
call_anim *canim = call_anim_create(it, rom_item_alpha, 300, INTERPOLATOR_DECELERATE);
call_anim_add(canim);
item_anim *anim = item_anim_create(d->sel_rect, 150, INTERPOLATOR_DECELERATE);
anim->start_offset = 0;
anim->targetX = d->sel_rect->x-7;
anim->targetY = d->sel_rect->y-7;
item_anim_add(anim);
d->click_text = fb_add_text_lvl(11, 0, fb_height, BLACK, SIZE_EXTRA, "Tap again to boot this system");
center_text(d->click_text, 0, -1, fb_width, -1);
d->click_text->y += d->click_text->h;
d->click_text_rect = fb_add_rect_lvl(10, 0, fb_height, fb_width-80, d->click_text->h+200, WHITE);
d->click_text_rect->x = fb_width/2 - d->click_text_rect->w/2;
anim = item_anim_create(d->click_text, 400, INTERPOLATOR_DECELERATE);
anim->targetY = fb_height - d->click_text->h*1.5 - 40;
item_anim_add(anim);
anim = item_anim_create(d->click_text_rect, 400, INTERPOLATOR_DECELERATE);
anim->targetY = fb_height - d->click_text->h*2.5 - 40;
item_anim_add(anim);
d->hover_removed = 0;
}
else
{
/*d->sel_rect_sh->y = y+5;
d->sel_rect->y = y;*/
}
//d->click_text->y = d->text_it->y + d->text_it->h + 15;
}
else if(d->sel_rect)
else if(d->sel_rect && !d->hover_removed)
{
fb_rm_rect(d->sel_rect);
d->sel_rect = NULL;
d->hover_removed = 1;
call_anim *canim = call_anim_create(it, rom_item_alpha, 200, INTERPOLATOR_ACCELERATE);
canim->on_finished_data = it;
canim->on_finished_call = rom_item_shrink_finished;
call_anim_add(canim);
item_anim *anim = item_anim_create(d->sel_rect, 200, INTERPOLATOR_ACCELERATE);
anim->targetX = d->sel_rect->x+7;
anim->targetY = d->sel_rect->y+7;
item_anim_add(anim);
anim = item_anim_create(d->click_text, 200, INTERPOLATOR_DECELERATE);
anim->targetY = fb_height;
item_anim_add(anim);
}
}
@@ -535,20 +712,20 @@ void rom_item_hide(void *data)
fb_rm_text(d->text_it);
fb_rm_text(d->part_it);
fb_rm_rect(d->bottom_line);
fb_rm_rect(d->hover_rect);
fb_rm_rect(d->sel_rect);
fb_rm_rect(d->sel_rect_sh);
fb_rm_img(d->icon);
d->text_it = NULL;
d->part_it = NULL;
d->bottom_line = NULL;
d->hover_rect = NULL;
d->sel_rect = NULL;
d->sel_rect_sh = NULL;
d->icon = NULL;
}
int rom_item_height(void *data)
int rom_item_height(listview_item *it)
{
return ROM_ITEM_H;
}

View File

@@ -33,6 +33,8 @@ typedef struct
int id;
void *data;
int flags;
fb_item_header *parent_rect;
int touchX, touchY;
} listview_item;
typedef struct
@@ -47,8 +49,7 @@ typedef struct
typedef struct
{
int x, y;
int w, h;
FB_ITEM_POS
int pos; // scroll pos
int fullH; // height of all items
@@ -58,12 +59,13 @@ typedef struct
void (*item_draw)(int, int, int, listview_item *); // x, y, w, item
void (*item_hide)(void*); // data
int (*item_height)(void*); // data
int (*item_height)(listview_item *); // data, item
void (*item_destroy)(listview_item *);
void (*item_selected)(listview_item *, listview_item *); // prev, now
void (*item_confirmed)(listview_item *); // item - confirmed by keyaction
fb_item_header **ui_items;
fb_rect *bg_rect;
fb_rect *scroll_mark;
fb_rect *overscroll_marks[2];
fb_rect **keyact_frame;
@@ -94,7 +96,7 @@ int listview_keyaction_call(void *data, int act);
void *rom_item_create(const char *text, const char *partition, const char *icon);
void rom_item_draw(int x, int y, int w, listview_item *it);
void rom_item_hide(void *data);
int rom_item_height(void *data);
int rom_item_height(listview_item *it);
void rom_item_destroy(listview_item *it);
#endif
#endif

View File

@@ -258,7 +258,7 @@ void multirom_ui_setup_colors(int clr, uint32_t *primary, uint32_t *secondary)
{
static const int clrs[][2] = {
// Primary, Secondary - OxAAGGBBRR
{ LBLUE, LBLUE2 }, // CLRS_BLUE
{ 0xFF2F2FF7, 0xFF2F2FF7}, // CLRS_BLUE
{ 0xFFCC66AA, 0xFFCC89B6 }, // CLRS_PURPLE
{ 0xFF00BD8A, 0xFF51F2C9 }, // CLRS_GREEN
{ 0xFF008AFF, 0xFF51AEFF }, // CLRS_ORANGE
@@ -367,10 +367,10 @@ void multirom_ui_fill_rom_list(listview *view, int mask)
select = it;
}
if(select)
/* if(select)
listview_select_item(view, select);
else if(view->items != NULL)
listview_select_item(view, view->items[0]);
listview_select_item(view, view->items[0]);*/
}
int multirom_ui_touch_handler(touch_event *ev, void *data)
@@ -486,9 +486,6 @@ void *multirom_ui_tab_rom_init(int tab_type)
t->list->item_selected = &multirom_ui_tab_rom_selected;
t->list->item_confirmed = &multirom_ui_tab_rom_confirmed;
t->boot_btn = mzalloc(sizeof(button));
list_add(t->boot_btn, &t->buttons);
cur_theme->tab_rom_init(themes_info->data, t, tab_type);
listview_init_ui(t->list);
@@ -509,10 +506,6 @@ void *multirom_ui_tab_rom_init(int tab_type)
int has_roms = (int)(t->list->items == NULL);
multirom_ui_tab_rom_set_empty((void*)t, has_roms);
t->boot_btn->clicked = &multirom_ui_tab_rom_boot_btn;
button_init_ui(t->boot_btn, "Boot", SIZE_BIG);
button_enable(t->boot_btn, !has_roms);
if(tab_type == TAB_USB)
{
multirom_set_usb_refresh_handler(&multirom_ui_refresh_usb_handler);
@@ -535,8 +528,6 @@ void multirom_ui_tab_rom_destroy(void *data)
listview_destroy(t->list);
fb_rm_text(t->rom_name);
if(t->usb_prog)
progdots_destroy(t->usb_prog);
@@ -655,10 +646,6 @@ void multirom_ui_tab_rom_set_empty(void *data, int empty)
tab_data_roms *t = (tab_data_roms*)data;
int width = cur_theme->get_tab_width(themes_info->data);
static const char *str[] = { "Select ROM to boot:", "No ROMs in this location!" };
fb_text_set_content(t->title_text, str[empty]);
center_text(t->title_text, t->list->x, -1, width, -1);
if(t->boot_btn)
button_enable(t->boot_btn, !empty);

View File

@@ -26,10 +26,12 @@
#include "../log.h"
#include "../animation.h"
#define HEADER_HEIGHT (75*DPI_MUL)
#define HEADER_HEIGHT (110*DPI_MUL)
#define STATUS_HEIGHT (33*DPI_MUL)
#define TABS_HEIGHT (HEADER_HEIGHT - STATUS_HEIGHT)
#define MIRI_W (90*DPI_MUL)
#define ROMS_FOOTER_H (130*DPI_MUL)
#define ROMS_HEADER_H (90*DPI_MUL)
#define ROMS_HEADER_H (20*DPI_MUL)
#define BOOTBTN_W (280*DPI_MUL)
#define BOOTBTN_H (80*DPI_MUL)
@@ -45,6 +47,10 @@
#define CLRBTN_TOTAL (CLRBTN_W+CLRBTN_B)
#define CLRBTN_Y (1150*DPI_MUL)
#define SELECTED_RECT_H (10*DPI_MUL)
#define COLOR_HIGHLIGHT 0xFF2F2FF7
static button *pong_btn = NULL;
static void destroy(multirom_theme_data *t)
{
@@ -64,26 +70,42 @@ static void init_header(multirom_theme_data *t)
static const char *str[] = { "Internal", "USB", "Misc", "MultiROM" };
fb_text *title = fb_add_text(0, 0, WHITE, SIZE_EXTRA, str[3]);
center_text(title, 0, 0, x, HEADER_HEIGHT);
// header background
fb_add_rect(0, 0, fb_width, HEADER_HEIGHT, CLR_PRIMARY);
//fb_add_rect(0, HEADER_HEIGHT, fb_width, (2*DPI_MUL), 0xFF7F07BC);
//fb_text *title = fb_add_text(0, 0, WHITE, SIZE_NORMAL, str[3]);
//center_text(title, 0, 0, x, STATUS_HEIGHT);
int maxW = 0;
for(i = 0; i < TAB_COUNT; ++i)
{
tab_texts[i] = fb_add_text(0, 0, WHITE, SIZE_BIG, str[i]);
maxW = imax(maxW, tab_texts[i]->w);
}
maxW += (30*DPI_MUL);
x = fb_width/2 - (maxW*TAB_COUNT)/2;
fb_img *l = fb_add_png_img((20*DPI_MUL), HEADER_HEIGHT/2 - MIRI_W/2, MIRI_W, MIRI_W, "/realdata/media/multirom/miri.png");
pong_btn = mzalloc(sizeof(button));
pong_btn->w = x;
pong_btn->h = HEADER_HEIGHT;
pong_btn->x = l->x;
pong_btn->y = l->y;
pong_btn->w = l->w;
pong_btn->h = l->h;
pong_btn->clicked = &multirom_ui_start_pong;
button_init_ui(pong_btn, NULL, 0);
for(i = 0; i < TAB_COUNT; ++i)
{
tab_texts[i] = fb_add_text(0, 0, WHITE, SIZE_NORMAL, str[i]);
center_text(tab_texts[i], x, 0, TAB_BTN_WIDTH, HEADER_HEIGHT);
fb_add_rect(x, 0, 2, HEADER_HEIGHT, WHITE);
center_text(tab_texts[i], x, 0, maxW, HEADER_HEIGHT);
tab_btns[i] = malloc(sizeof(button));
memset(tab_btns[i], 0, sizeof(button));
tab_btns[i]->x = x;
tab_btns[i]->w = TAB_BTN_WIDTH;
tab_btns[i]->y = 0;
tab_btns[i]->w = maxW;
tab_btns[i]->h = HEADER_HEIGHT;
tab_btns[i]->action = i;
tab_btns[i]->clicked = &multirom_ui_switch;
@@ -91,65 +113,34 @@ static void init_header(multirom_theme_data *t)
keyaction_add(tab_btns[i]->x, tab_btns[i]->y, button_keyaction_call, tab_btns[i]);
x += TAB_BTN_WIDTH;
x += maxW;
}
fb_add_rect(0, HEADER_HEIGHT, fb_width, 2, WHITE);
}
static void header_select(multirom_theme_data *t, int tab)
{
int i;
for(i = 0; i < TAB_COUNT; ++i)
fb_text_set_color(t->tab_texts[i], (i == tab) ? BLACK : WHITE);
const int TAB_BTN_WIDTH = fb_width*0.21;
const int TAB_BTN_WIDTH = t->tab_btns[0]->w;
int dest_x = t->tab_btns[tab]->x;
if(!t->selected_tab_rect)
t->selected_tab_rect = fb_add_rect(0, 0, TAB_BTN_WIDTH, HEADER_HEIGHT, WHITE);
t->selected_tab_rect = fb_add_rect(dest_x, HEADER_HEIGHT-SELECTED_RECT_H, TAB_BTN_WIDTH, SELECTED_RECT_H, WHITE);
else
{
anim_cancel_for(t->selected_tab_rect, 0);
t->selected_tab_rect->x = fb_width - (TAB_BTN_WIDTH * (TAB_COUNT - tab));
item_anim *anim = item_anim_create(t->selected_tab_rect, 150, INTERPOLATOR_DECELERATE);
anim->targetX = dest_x;
item_anim_add(anim);
}
}
static void tab_rom_init(multirom_theme_data *t, tab_data_roms *d, int tab_type)
{
int base_y = fb_height-ROMS_FOOTER_H;
d->rom_name = fb_add_text(0, 0, WHITE, SIZE_NORMAL, "");
d->list->x = ROMS_HEADER_H;
d->list->y = HEADER_HEIGHT+ROMS_HEADER_H;
d->list->w = fb_width;
d->list->h = fb_height - d->list->y - ROMS_FOOTER_H-20;
// header
d->title_text = fb_add_text(0, 0, CLR_PRIMARY, SIZE_BIG, "W");
center_text(d->title_text, -1, HEADER_HEIGHT, -1, ROMS_HEADER_H);
list_add(d->title_text, &d->ui_elements);
// footer
fb_rect *sep = fb_add_rect(0, fb_height-ROMS_FOOTER_H, fb_width, 2, CLR_PRIMARY);
list_add(sep, &d->ui_elements);
// boot btn
d->boot_btn->x = fb_width - BOOTBTN_W - 20;
d->boot_btn->y = base_y + (ROMS_FOOTER_H-BOOTBTN_H)/2;
d->boot_btn->w = BOOTBTN_W;
d->boot_btn->h = BOOTBTN_H;
keyaction_add(d->boot_btn->x, d->boot_btn->y, button_keyaction_call, d->boot_btn);
}
static void animation_finished(void *data)
{
fb_img *t = fb_add_text(50, HEADER_HEIGHT, CLR_PRIMARY, SIZE_BIG, "Finished!");
tab_data_misc *d = data;
list_add(t, &d->ui_elements);
fb_request_draw();
item_anim *anim = item_anim_create(t, 3000, INTERPOLATOR_LINEAR);
anim->targetY = fb_height - t->h - 20;
anim->targetX = fb_width - t->w;
item_anim_add(anim);
d->list->w = fb_width - ROMS_HEADER_H*2;
d->list->h = fb_height - d->list->y - ROMS_HEADER_H;
}
static void tab_misc_init(multirom_theme_data *t, tab_data_misc *d, int color_scheme)
@@ -157,34 +148,6 @@ static void tab_misc_init(multirom_theme_data *t, tab_data_misc *d, int color_sc
int x = fb_width/2 - MISCBTN_W/2;
int y = 270*DPI_MUL;
fb_rect *rt = fb_add_rect(20*DPI_MUL, y, 0, 0, WHITE);
list_add(rt, &d->ui_elements);
item_anim *anim = item_anim_create(rt, 200, INTERPOLATOR_DECELERATE);
anim->targetW = fb_width - 40*DPI_MUL;
item_anim_add(anim);
anim = item_anim_create(rt, 400, INTERPOLATOR_OVERSHOOT);
anim->start_offset = 200;
anim->targetH = fb_height - y - 200*DPI_MUL;
item_anim_add(anim);
anim = item_anim_create(rt, 200, INTERPOLATOR_ACCELERATE);
anim->start_offset = 3000;
anim->targetH = 10*DPI_MUL;
item_anim_add(anim);
anim = item_anim_create(rt, 500, INTERPOLATOR_ACCELERATE);
anim->start_offset = 3200;
anim->targetX = 20*DPI_MUL + (fb_width - 40*DPI_MUL);
anim->targetW = 0;
anim->on_finished_data = d;
anim->on_finished_call = animation_finished;
item_anim_add(anim);
return;
button *b = mzalloc(sizeof(button));
b->x = x;
b->y = y;
@@ -285,8 +248,7 @@ static int get_tab_height(multirom_theme_data *t)
static void set_rom_name(tab_data_roms *d, const char *name)
{
fb_text_set_content(d->rom_name, name);
center_text(d->rom_name, 0, fb_height-ROMS_FOOTER_H, fb_width-BOOTBTN_W-20, ROMS_FOOTER_H);
}
const struct multirom_theme theme_info_portrait = {