Skip to content

Commit

Permalink
Add coverflow menu style.
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyTolene committed Dec 1, 2024
1 parent 49d29f8 commit ef48b30
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 19 deletions.
6 changes: 3 additions & 3 deletions applications/main/lfrfid/views/lfrfid_view_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {

canvas_draw_str(canvas, 77, 29, "ASK");
canvas_draw_icon(canvas, 70, 22, &I_ButtonRight_4x7);
canvas_draw_icon_animation(canvas, 102, 21, model->icon);
canvas_draw_icon_animation(canvas, 102, 21, 100, 100, model->icon);

canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 77, 43, "PSK");
Expand All @@ -35,7 +35,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {

canvas_draw_str(canvas, 77, 43, "PSK");
canvas_draw_icon(canvas, 70, 36, &I_ButtonRight_4x7);
canvas_draw_icon_animation(canvas, 102, 35, model->icon);
canvas_draw_icon_animation(canvas, 102, 35, 100, 100, model->icon);

canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 77, 29, "ASK");
Expand All @@ -47,7 +47,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
} else {
canvas_draw_str(canvas, 77, 35, "PSK");
}
canvas_draw_icon_animation(canvas, 102, 27, model->icon);
canvas_draw_icon_animation(canvas, 102, 27, 100, 100, model->icon);
}

canvas_set_font(canvas, FontSecondary);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const char* const menu_style_names[MenuStyleCount] = {
"C64",
"Compact",
"MNTM",
"CoverFlow",
};
static void momentum_app_scene_interface_mainmenu_menu_style_changed(VariableItem* item) {
MomentumApp* app = variable_item_get_context(item);
Expand Down
22 changes: 19 additions & 3 deletions applications/services/gui/canvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,21 +298,37 @@ void canvas_draw_icon_animation(
Canvas* canvas,
int32_t x,
int32_t y,
int32_t width_scale,
int32_t height_scale,
IconAnimation* icon_animation) {
furi_check(canvas);
furi_check(icon_animation);
// Ensure scale % is > 0
furi_assert(width_scale > 0 && height_scale > 0);
// Ensure scale % is <= 100; animated icons > 100% don't look good
furi_assert(width_scale <= 100 && height_scale <= 100);

x += canvas->offset_x;
y += canvas->offset_y;

uint8_t* icon_data = NULL;
compress_icon_decode(
canvas->compress_icon, icon_animation_get_data(icon_animation), &icon_data);
canvas->compress_icon,
icon_animation_get_data(icon_animation),
&icon_data
);

int32_t width = icon_animation_get_width(icon_animation);
int32_t height = icon_animation_get_height(icon_animation);
int32_t width_scaled = (width * width_scale) / 100;
int32_t height_scaled = (height * height_scale) / 100;

canvas_draw_u8g2_bitmap(
&canvas->fb,
x,
y,
icon_animation_get_width(icon_animation),
icon_animation_get_height(icon_animation),
width_scaled,
height_scaled,
icon_data,
IconRotation0);
}
Expand Down
4 changes: 4 additions & 0 deletions applications/services/gui/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,16 @@ void canvas_draw_icon_ex(
* @param canvas Canvas instance
* @param x x coordinate
* @param y y coordinate
* @param width_scale scaled (%) width of icon
* @param height_scale scaled (%) height of icon
* @param icon_animation IconAnimation instance
*/
void canvas_draw_icon_animation(
Canvas* canvas,
int32_t x,
int32_t y,
int32_t width_scale,
int32_t height_scale,
IconAnimation* icon_animation);

/** Draw icon at position defined by x,y.
Expand Down
2 changes: 1 addition & 1 deletion applications/services/gui/modules/loading.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static void loading_draw_callback(Canvas* canvas, void* _model) {

canvas_draw_icon(canvas, x, y, &A_Loading_24);

canvas_draw_icon_animation(canvas, x, y, model->icon);
canvas_draw_icon_animation(canvas, x, y, 100, 100, model->icon);
}

static bool loading_input_callback(InputEvent* event, void* context) {
Expand Down
146 changes: 137 additions & 9 deletions applications/services/gui/modules/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,15 @@ static void menu_centered_icon(
size_t x,
size_t y,
size_t width,
size_t height) {
size_t height,
size_t width_scale,
size_t height_scale) {
canvas_draw_icon_animation(
canvas,
x + (width - item->icon->icon->width) / 2,
y + (height - item->icon->icon->height) / 2,
width_scale,
height_scale,
item->icon);
}

Expand Down Expand Up @@ -107,7 +111,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
canvas_set_font(canvas, i == 1 ? FontPrimary : FontSecondary);
shift_position = (position + items_count + i - 1) % items_count;
item = MenuItemArray_get(model->items, shift_position);
menu_centered_icon(canvas, item, 4, 3 + 22 * i, 14, 14);
menu_centered_icon(canvas, item, 4, 3 + 22 * i, 14, 14, 100, 100);
menu_get_name(item, name, false);
size_t scroll_counter = menu_scroll_counter(model, i == 1);
elements_scrollable_text_line(
Expand Down Expand Up @@ -142,7 +146,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
canvas_set_color(canvas, ColorWhite);
}
item = MenuItemArray_get(model->items, item_i);
menu_centered_icon(canvas, item, x_off, y_off, 40, 20);
menu_centered_icon(canvas, item, x_off, y_off, 40, 20, 100, 100);
menu_get_name(item, name, true);
size_t scroll_counter = menu_scroll_counter(model, selected);
elements_scrollable_text_line_centered(
Expand Down Expand Up @@ -202,7 +206,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
elements_slightly_rounded_frame(
canvas, pos_x - width / 2, pos_y - height / 2, width, height);
}
menu_centered_icon(canvas, item, pos_x - 7, pos_y - 7, 14, 14);
menu_centered_icon(canvas, item, pos_x - 7, pos_y - 7, 14, 14, 100, 100);
}
elements_scrollbar_horizontal(canvas, 0, 64, 128, position, items_count);
break;
Expand Down Expand Up @@ -250,7 +254,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
pos_x += (width + 1) * i + (i < 0 ? -6 : 6);
}
canvas_draw_frame(canvas, pos_x - width / 2, pos_y - height / 2, width, height);
menu_centered_icon(canvas, item, pos_x - 7, pos_y - 7, 14, 14);
menu_centered_icon(canvas, item, pos_x - 7, pos_y - 7, 14, 14, 100, 100);
}
elements_scrollbar_horizontal(canvas, 0, 64, 128, position, items_count);
break;
Expand Down Expand Up @@ -279,7 +283,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
canvas_set_color(canvas, ColorWhite);
}
item = MenuItemArray_get(model->items, item_i);
menu_centered_icon(canvas, item, 0, y_off, 16, 16);
menu_centered_icon(canvas, item, 0, y_off, 16, 16, 100, 100);
menu_get_name(item, name, true);
size_t scroll_counter = menu_scroll_counter(model, selected);
elements_scrollable_text_line(
Expand Down Expand Up @@ -422,7 +426,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
MenuItem* item = MenuItemArray_get(model->items, position);
menu_get_name(item, name, true);
elements_bold_rounded_frame(canvas, 42, 23, 35, 33);
menu_centered_icon(canvas, item, 43, 24, 35, 32);
menu_centered_icon(canvas, item, 43, 24, 35, 32, 100, 100);
canvas_draw_frame(canvas, 0, 0, 128, 64);

uint8_t startY = 15;
Expand All @@ -442,6 +446,126 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
}
break;
}
case MenuStyleCoverFlow: {
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);

// Draw frames
canvas_set_bitmap_mode(canvas, true);
canvas_draw_frame(canvas, 0, 0, 128, 64);
canvas_draw_frame(canvas, 44, 2, 40, 40);

// Draw left side albums
canvas_draw_line(canvas, 6, 40, 17, 35);
canvas_draw_line(canvas, 19, 40, 30, 35);
canvas_draw_line(canvas, 32, 40, 43, 35);
canvas_draw_line(canvas, 6, 3, 17, 8);
canvas_draw_line(canvas, 19, 3, 30, 8);
canvas_draw_line(canvas, 32, 3, 43, 8);
canvas_draw_line(canvas, 18, 2, 18, 41);
canvas_draw_line(canvas, 31, 2, 31, 41);
canvas_draw_line(canvas, 5, 2, 5, 41);
canvas_draw_line(canvas, 4, 8, 1, 7);
canvas_draw_line(canvas, 5, 35, 1, 36);

// Draw right side albums
canvas_draw_line(canvas, 95, 40, 84, 35);
canvas_draw_line(canvas, 108, 40, 97, 35);
canvas_draw_line(canvas, 121, 40, 110, 35);
canvas_draw_line(canvas, 84, 8, 95, 3);
canvas_draw_line(canvas, 97, 8, 108, 3);
canvas_draw_line(canvas, 110, 8, 121, 3);
canvas_draw_line(canvas, 96, 2, 96, 41);
canvas_draw_line(canvas, 109, 2, 109, 41);
canvas_draw_line(canvas, 122, 2, 122, 41);
canvas_draw_line(canvas, 123, 8, 126, 7);
canvas_draw_line(canvas, 123, 35, 126, 36);

const int32_t pos_x_center = 128 / 2;
const int32_t pos_y_center = 64 / 2;
const int32_t pos_y_offset = 10;
const int32_t icon_size = 20;
const int32_t side_icon_width = icon_size / 2;
const int32_t padding_center_icon = 14;
const int32_t spacing_between_icons = 3;
const int32_t scale_base = 100;

MenuItem* center_item = NULL;

// Draw 7 icons, where index 0 is the center icon
// [-3, -2, -1, 0, 1, 2, 3]
for (int8_t i = -3; i <= 3; i++) {
shift_position = (position + items_count + i) % items_count;
item = MenuItemArray_get(model->items, shift_position);

int32_t pos_x = pos_x_center;
int32_t pos_y = pos_y_center;

int32_t scale_width = scale_base;
int32_t scale_height = scale_base;

if (i < 0) {
// Left sided icons
pos_x -= padding_center_icon;
pos_x -= ((-i) * (side_icon_width + spacing_between_icons));
pos_x -= (side_icon_width / 2) / 2;
pos_y = (pos_y_center - icon_size / 2) - pos_y_offset;
scale_width = 50;
} else if (i > 0) {
// Right sided icons
pos_x += padding_center_icon;
pos_x += (i * (side_icon_width + spacing_between_icons));
pos_x -= side_icon_width;
pos_y = (pos_y_center - icon_size / 2) - pos_y_offset;
scale_width = 50;
} else if (i == 0) {
// Center icon
pos_x -= icon_size / 2;
pos_y = (pos_y_center - (icon_size / 2)) - pos_y_offset;
// Scaling > 100% doesn't look good, keep 100% for now
scale_width = scale_base; // TODO: 200%
scale_height = scale_base; // TODO: 200%
// Save center item pointer for later
center_item = item;
}

// Draw the icon
menu_centered_icon(
canvas,
item,
pos_x,
pos_y,
icon_size,
icon_size,
scale_width,
scale_height
);
}

// Draw label for center item
if (center_item) {
FuriString* name = furi_string_alloc();
menu_get_name(center_item, name, false);
elements_scrollable_text_line_centered(
canvas,
pos_x_center,
(pos_y_center + icon_size / 2) + pos_y_offset,
126,
name,
0,
false,
true
);
furi_string_free(name);
}

// Add scrollbar element
elements_scrollbar_horizontal(
canvas, 0, 60, 128, position, items_count
);

break;
}
default:
break;
}
Expand Down Expand Up @@ -818,7 +942,9 @@ static void menu_process_left(Menu* menu) {
position = position - 8;
}
break;

case MenuStyleCoverFlow:
position = (position + count - 1) % count;
break;
default:
break;
}
Expand Down Expand Up @@ -882,7 +1008,9 @@ static void menu_process_right(Menu* menu) {
position = position - 8;
}
break;

case MenuStyleCoverFlow:
position = (position + 1) % count;
break;
default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static void clock_settings_alarm_draw_callback(Canvas* canvas, void* ctx) {
ClockSettingsAlramModel* model = ctx;
char buffer[64] = {};

canvas_draw_icon_animation(canvas, 5, 6, model->icon);
canvas_draw_icon_animation(canvas, 5, 6, 100, 100, model->icon);

canvas_set_font(canvas, FontBigNumbers);
snprintf(buffer, sizeof(buffer), "%02u:%02u", model->now.hour, model->now.minute);
Expand Down
2 changes: 2 additions & 0 deletions lib/momentum/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ typedef enum {
MenuStyleC64,
MenuStyleCompact,
MenuStyleMNTM,
MenuStyleCoverFlow,
MenuStyleCount,
} MenuStyle;


typedef enum {
SpiDefault, // CS on pa4
SpiExtra, // CS on pc3
Expand Down
2 changes: 1 addition & 1 deletion targets/f18/api_symbols.csv
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ Function,+,canvas_draw_dot,void,"Canvas*, int32_t, int32_t"
Function,+,canvas_draw_frame,void,"Canvas*, int32_t, int32_t, size_t, size_t"
Function,+,canvas_draw_glyph,void,"Canvas*, int32_t, int32_t, uint16_t"
Function,+,canvas_draw_icon,void,"Canvas*, int32_t, int32_t, const Icon*"
Function,+,canvas_draw_icon_animation,void,"Canvas*, int32_t, int32_t, IconAnimation*"
Function,+,canvas_draw_icon_animation,void,"Canvas*, int32_t, int32_t, int32_t, int32_t, IconAnimation*"
Function,+,canvas_draw_icon_ex,void,"Canvas*, int32_t, int32_t, const Icon*, IconRotation"
Function,+,canvas_draw_line,void,"Canvas*, int32_t, int32_t, int32_t, int32_t"
Function,+,canvas_draw_rbox,void,"Canvas*, int32_t, int32_t, size_t, size_t, size_t"
Expand Down
2 changes: 1 addition & 1 deletion targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ Function,+,canvas_draw_dot,void,"Canvas*, int32_t, int32_t"
Function,+,canvas_draw_frame,void,"Canvas*, int32_t, int32_t, size_t, size_t"
Function,+,canvas_draw_glyph,void,"Canvas*, int32_t, int32_t, uint16_t"
Function,+,canvas_draw_icon,void,"Canvas*, int32_t, int32_t, const Icon*"
Function,+,canvas_draw_icon_animation,void,"Canvas*, int32_t, int32_t, IconAnimation*"
Function,+,canvas_draw_icon_animation,void,"Canvas*, int32_t, int32_t, int32_t, int32_t, IconAnimation*"
Function,+,canvas_draw_icon_ex,void,"Canvas*, int32_t, int32_t, const Icon*, IconRotation"
Function,+,canvas_draw_line,void,"Canvas*, int32_t, int32_t, int32_t, int32_t"
Function,+,canvas_draw_rbox,void,"Canvas*, int32_t, int32_t, size_t, size_t, size_t"
Expand Down

0 comments on commit ef48b30

Please sign in to comment.