hbc/channel/channelapp/source/browser.c
2016-11-23 14:35:12 +09:00

331 lines
7.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <ogcsys.h>
#include <ogc/lwp_watchdog.h>
#include "../config.h"
#include "theme.h"
#include "view.h"
#include "controls.h"
#include "i18n.h"
#include "browser.h"
#define AE_OFFSET 4
#define TRANS_STEPS 20
#define MAX_COLUMNS 4
#define ROWS 5
static bool first_set = true;
static u16 top_offset = 0;
static view *v_browser = NULL;
static int columns_current = 1;
static int columns_new = 1;
static bool inited_widgets = false;
view * browser_init(void) {
v_browser = view_new (AE_OFFSET + (MAX_COLUMNS * ROWS * 2), NULL,
0, 0, 0, 0);
browser_theme_reinit();
return v_browser;
}
void browser_deinit(void) {
view_free(v_browser);
inited_widgets = false;
v_browser = NULL;
}
void browser_theme_reinit(void) {
int i;
if (inited_widgets)
for (i = 0; i < v_browser->widget_count; ++i)
widget_free(&v_browser->widgets[i]);
widget_image (&v_browser->widgets[0], 24, 192, 0,
theme_gfx[THEME_ARROW_LEFT], NULL, true,
theme_gfx[THEME_ARROW_LEFT_FOCUS]);
widget_image (&v_browser->widgets[1],
view_width - 24 - theme_gfx[THEME_ARROW_RIGHT]->w, 192, 0,
theme_gfx[THEME_ARROW_RIGHT], NULL, true,
theme_gfx[THEME_ARROW_RIGHT_FOCUS]);
widget_image (&v_browser->widgets[2],
view_width - 32 - theme_gfx[THEME_GECKO_ACTIVE]->w -
theme_gfx[THEME_LAN_ACTIVE]->w, 412, 0,
theme_gfx[THEME_GECKO_ACTIVE], theme_gfx[THEME_GECKO],
false, NULL);
widget_image (&v_browser->widgets[3],
view_width - 32 - theme_gfx[THEME_GECKO_ACTIVE]->w, 412, 0,
theme_gfx[THEME_LAN_ACTIVE], theme_gfx[THEME_LAN],
false, NULL);
widget_set_flag (&v_browser->widgets[2], WF_ENABLED, false);
widget_set_flag (&v_browser->widgets[3], WF_ENABLED, false);
widget_set_flag (&v_browser->widgets[0], WF_VISIBLE, false);
widget_set_flag (&v_browser->widgets[1], WF_VISIBLE, false);
inited_widgets = true;
}
static void browser_set_top_offset(const app_entry *app) {
u32 i;
if (!app || (entry_count < 1)) {
top_offset = 0;
return;
}
for (i = 0; i < entry_count; ++i)
if (entries[i] == app) {
top_offset = i;
break;
}
top_offset /= columns_new * ROWS;
top_offset *= columns_new * ROWS;
if (top_offset > entry_count - 1)
top_offset -= columns_new * ROWS;
}
void browser_gen_view(browser_action action, const app_entry *app) {
bool less, more;
app_entry *entry;
s8 focus;
u32 i, j;
u16 y;
u8 o1, o2;
s16 xal, xar, x1, x2;
float xm;
float vala = 0;
float val1[MAX_COLUMNS * ROWS];
float val2[MAX_COLUMNS * ROWS];
float stepa = M_TWOPI / TRANS_STEPS;
float step = M_PI / (TRANS_STEPS - 6);
s16 s;
float f1, f2;
switch (action) {
case BA_REMOVE:
break;
case BA_ADD:
case BA_REFRESH:
browser_set_top_offset(app);
break;
case BA_NEXT:
if (entry_count <= top_offset + (columns_new * ROWS))
return;
top_offset += columns_current * ROWS;
break;
case BA_PREV:
if (top_offset < 1)
return;
if (top_offset < columns_current * ROWS)
return;
top_offset -= columns_current * ROWS;
break;
}
if (action == BA_REMOVE) {
less = false;
more = false;
} else {
less = top_offset > 0;
more = entry_count > top_offset + (columns_new * ROWS);
}
memset(val1, 0, sizeof(float) * MAX_COLUMNS * ROWS);
memset(val2, 0, sizeof(float) * MAX_COLUMNS * ROWS);
if (first_set) {
o1 = AE_OFFSET;
o2 = AE_OFFSET + (MAX_COLUMNS * ROWS);
} else {
o1 = AE_OFFSET + (MAX_COLUMNS * ROWS);
o2 = AE_OFFSET;
}
first_set = !first_set;
focus = o2;
xal = v_browser->widgets[0].coords.x;
xar = v_browser->widgets[1].coords.x;
if (columns_current == 1)
x1 = (view_width - theme_gfx[THEME_APP_ENTRY]->w) / 2;
else
x1 = (view_width - (theme_gfx[THEME_GRID_APP_ENTRY]->w *
columns_current)) / 2;
if (columns_new == 1)
x2 = (view_width - theme_gfx[THEME_APP_ENTRY]->w) / 2;
else
x2 = (view_width - (theme_gfx[THEME_GRID_APP_ENTRY]->w *
columns_new)) / 2;
if (action == BA_PREV) {
xm = view_width / 2;
x2 = -view_width + x2;
} else {
xm = -view_width / 2;
x2 = view_width + x2;
}
y = 64;
for (i = 0; i < (MAX_COLUMNS * ROWS); ++i)
widget_free(&v_browser->widgets[o2 + i]);
if (action != BA_REMOVE)
for (i = 0; i < (columns_new * ROWS); ++i) {
if (entry_count > top_offset + i) {
entry = entries[top_offset + i];
if (entry && (entry == app))
focus += i;
if (columns_new == 1)
widget_app_entry(&v_browser->widgets[o2 + i],
x2, y, 0, entry);
else
widget_grid_app_entry(&v_browser->widgets[o2 + i],
x2 + ((i % columns_new) *
theme_gfx[THEME_GRID_APP_ENTRY]->w),
y, 0, entry);
}
if (((i+1) % columns_new) == 0)
y += theme_gfx[THEME_APP_ENTRY]->h;
}
for (i = 0; i < TRANS_STEPS; ++i) {
vala += stepa;
s = roundf (156.0 * (cosf (vala) - 1));
// adjust L/R button positions
v_browser->widgets[0].coords.x = xal + s;
v_browser->widgets[1].coords.x = xar - s;
for (j = 0; j < MAX_COLUMNS * ROWS; ++j) {
if ((i > j / columns_current) &&
(i < TRANS_STEPS - (ROWS - j / columns_current)))
val1[j] += step;
if ((i > j / columns_new) &&
(i < TRANS_STEPS - (ROWS - j / columns_new)))
val2[j] += step;
f1 = roundf (xm * (cosf (val1[j]) - 1));
f2 = roundf (xm * (cosf (val2[j]) - 1));
v_browser->widgets[o1 + j].coords.x = x1 - f1 +
((j % columns_current) * theme_gfx[THEME_GRID_APP_ENTRY]->w);
v_browser->widgets[o2 + j].coords.x = x2 - f2 +
((j % columns_new) * theme_gfx[THEME_GRID_APP_ENTRY]->w);
}
view_plot (v_browser, 0, NULL, NULL, NULL);
if (i == TRANS_STEPS / 2) {
widget_set_flag (&v_browser->widgets[0], WF_VISIBLE, true);
widget_set_flag (&v_browser->widgets[1], WF_VISIBLE, true);
widget_set_flag (&v_browser->widgets[0], WF_VISIBLE, less);
widget_set_flag (&v_browser->widgets[1], WF_VISIBLE, more);
view_set_focus (v_browser, focus);
}
}
for (i = 0; i < (MAX_COLUMNS * ROWS); ++i)
widget_free(&v_browser->widgets[o1 + i]);
columns_current = columns_new;
if (action == BA_REMOVE)
top_offset = 0;
}
void browser_set_focus(u32 bd) {
if (columns_current == 1) {
if (bd & PADS_UP) {
view_set_focus_prev(v_browser);
return;
}
if (bd & PADS_DOWN) {
view_set_focus_next(v_browser);
return;
}
return;
} else {
if (bd & PADS_LEFT) {
view_set_focus_prev(v_browser);
return;
}
if (bd & PADS_RIGHT) {
view_set_focus_next(v_browser);
return;
}
if (bd & PADS_UP) {
view_move_focus(v_browser, -columns_current);
return;
}
if (bd & PADS_DOWN) {
view_move_focus(v_browser, columns_current);
return;
}
return;
}
}
app_entry *browser_sel(void) {
if ((entry_count < 1) || (v_browser->focus < AE_OFFSET))
return NULL;
u32 i;
if (first_set)
i = top_offset + v_browser->focus - AE_OFFSET;
else
i = top_offset + v_browser->focus - (MAX_COLUMNS * ROWS) - AE_OFFSET;
return entries[i];
}
void browser_switch_mode(void) {
const app_entry *app = browser_sel();
int mode = 0;
if (columns_current == 1) {
if (widescreen)
columns_new = 4;
else
columns_new = 3;
mode = 1;
} else {
columns_new = 1;
}
if (v_browser)
browser_gen_view(BA_REFRESH, app);
if (settings.browse_mode != mode)
settings.browse_mode = mode;
}