Theme tweaks
This commit is contained in:
parent
c840dc0134
commit
215439621c
7 changed files with 794 additions and 110 deletions
330
src/ui.c
330
src/ui.c
|
|
@ -43,6 +43,36 @@ static void set_draw_color(SDL_Renderer *renderer, SDL_Color color) {
|
|||
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
static SDL_Color color_with_alpha(SDL_Color color, Uint8 alpha) {
|
||||
color.a = alpha;
|
||||
return color;
|
||||
}
|
||||
|
||||
static SDL_Color blend_color(SDL_Color from, SDL_Color to, int weight_to_255) {
|
||||
SDL_Color blended;
|
||||
int weight_from = 255 - weight_to_255;
|
||||
|
||||
blended.r = (Uint8) ((from.r * weight_from + to.r * weight_to_255) / 255);
|
||||
blended.g = (Uint8) ((from.g * weight_from + to.g * weight_to_255) / 255);
|
||||
blended.b = (Uint8) ((from.b * weight_from + to.b * weight_to_255) / 255);
|
||||
blended.a = 255;
|
||||
return blended;
|
||||
}
|
||||
|
||||
static int color_luma(SDL_Color color) {
|
||||
return (299 * color.r + 587 * color.g + 114 * color.b) / 1000;
|
||||
}
|
||||
|
||||
static SDL_Color readable_text_color(SDL_Color background) {
|
||||
return color_luma(background) < 120 ? COLOR_TEXT_LIGHT : COLOR_TEXT_DARK;
|
||||
}
|
||||
|
||||
static SDL_Color secondary_text_color(SDL_Color primary, SDL_Color background) {
|
||||
SDL_Color secondary = blend_color(primary, background, 110);
|
||||
secondary.a = 255;
|
||||
return secondary;
|
||||
}
|
||||
|
||||
static SDL_Texture *text_to_texture(SDL_Renderer *renderer, TTF_Font *font, const char *text, SDL_Color color, int *width, int *height) {
|
||||
SDL_Surface *surface;
|
||||
SDL_Texture *texture;
|
||||
|
|
@ -92,6 +122,9 @@ static void fill_three_stop_gradient(SDL_Renderer *renderer,
|
|||
return;
|
||||
}
|
||||
|
||||
top = blend_color(top, middle, 140);
|
||||
bottom = blend_color(bottom, middle, 140);
|
||||
|
||||
split = rect->h / 2;
|
||||
for (int i = 0; i < rect->h; ++i) {
|
||||
SDL_Color from = i < split ? top : middle;
|
||||
|
|
@ -115,23 +148,23 @@ static void fill_rect_alpha(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Co
|
|||
|
||||
static void draw_panel_shadow(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
SDL_Rect shadow = {rect->x + 6, rect->y + 6, rect->w, rect->h};
|
||||
fill_rect_alpha(renderer, &shadow, COLOR_PANEL_SHADOW);
|
||||
fill_rect_alpha(renderer, &shadow, color_with_alpha(COLOR_PANEL_SHADOW, 48));
|
||||
}
|
||||
|
||||
static void draw_gloss_line(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
static void draw_gloss_line(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color gloss_color) {
|
||||
SDL_Rect gloss = {rect->x + 4, rect->y + 1, SDL_max(rect->w - 8, 0), 2};
|
||||
if (gloss.w > 0) {
|
||||
fill_rect_alpha(renderer, &gloss, COLOR_GLOSS);
|
||||
fill_rect_alpha(renderer, &gloss, gloss_color);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_panel_bevel(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
static void draw_panel_bevel(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color gloss_color) {
|
||||
SDL_Rect top_white = {rect->x + 8, rect->y, SDL_max(rect->w - 16, 0), 1};
|
||||
SDL_Rect top_black = {rect->x + 8, rect->y + 1, SDL_max(rect->w - 16, 0), 1};
|
||||
|
||||
if (top_white.w > 0) {
|
||||
fill_rect_alpha(renderer, &top_white, (SDL_Color){255, 255, 255, 128});
|
||||
fill_rect_alpha(renderer, &top_black, (SDL_Color){0, 0, 0, 51});
|
||||
fill_rect_alpha(renderer, &top_white, color_with_alpha(gloss_color, 72));
|
||||
fill_rect_alpha(renderer, &top_black, (SDL_Color){0, 0, 0, 28});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,37 +175,36 @@ static void stroke_rect_alpha(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_
|
|||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
static void draw_selection_glow(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
static void draw_selection_glow(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color edge) {
|
||||
SDL_Rect outer = *rect;
|
||||
SDL_Rect inner = {rect->x + 1, rect->y + 1, rect->w - 2, rect->h - 2};
|
||||
stroke_rect_alpha(renderer, &outer, (SDL_Color){0xff, 0xd7, 0x00, 120});
|
||||
stroke_rect_alpha(renderer, &outer, color_with_alpha(edge, 62));
|
||||
if (inner.w > 0 && inner.h > 0) {
|
||||
stroke_rect_alpha(renderer, &inner, (SDL_Color){0xff, 0xd7, 0x00, 70});
|
||||
stroke_rect_alpha(renderer, &inner, color_with_alpha(edge, 34));
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_rounded_top_panel(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color fill_color) {
|
||||
static void draw_rounded_top_panel(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color fill_color, SDL_Color border_color, int radius) {
|
||||
SDL_Rect body;
|
||||
SDL_Rect top;
|
||||
|
||||
if (!rect || rect->w < 8 || rect->h < 8) {
|
||||
if (!rect || rect->w < radius || rect->h < radius) {
|
||||
return;
|
||||
}
|
||||
|
||||
body = (SDL_Rect){rect->x, rect->y + 8, rect->w, rect->h - 8};
|
||||
top = (SDL_Rect){rect->x + 8, rect->y, rect->w - 16, 8};
|
||||
body = (SDL_Rect){rect->x, rect->y + radius, rect->w, rect->h - radius};
|
||||
top = (SDL_Rect){rect->x + radius, rect->y, rect->w - radius * 2, radius};
|
||||
fill_rect(renderer, &body, fill_color);
|
||||
fill_rect(renderer, &top, fill_color);
|
||||
fill_rect(renderer, &(SDL_Rect){rect->x + 4, rect->y + 2, rect->w - 8, 6}, fill_color);
|
||||
fill_rect(renderer, &(SDL_Rect){rect->x + 2, rect->y + 4, rect->w - 4, 4}, fill_color);
|
||||
fill_rect(renderer, &(SDL_Rect){rect->x + 1, rect->y + 6, rect->w - 2, 2}, fill_color);
|
||||
fill_rect(renderer, &(SDL_Rect){rect->x + radius / 2, rect->y + 2, rect->w - radius, radius - 2}, fill_color);
|
||||
fill_rect(renderer, &(SDL_Rect){rect->x + 2, rect->y + radius / 2, rect->w - 4, radius / 2}, fill_color);
|
||||
|
||||
set_draw_color(renderer, COLOR_BORDER_DARK);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 8, rect->y, rect->x + rect->w - 9, rect->y);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 4, rect->y + 2, rect->x + 5, rect->y + 1);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w - 6, rect->y + 1, rect->x + rect->w - 5, rect->y + 2);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 1, rect->y + 6, rect->x + 1, rect->y + rect->h - 2);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w - 2, rect->y + 6, rect->x + rect->w - 2, rect->y + rect->h - 2);
|
||||
set_draw_color(renderer, border_color);
|
||||
SDL_RenderDrawLine(renderer, rect->x + radius, rect->y, rect->x + rect->w - radius - 1, rect->y);
|
||||
SDL_RenderDrawLine(renderer, rect->x + radius / 2, rect->y + 2, rect->x + radius / 2 + 1, rect->y + 1);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w - radius / 2 - 2, rect->y + 1, rect->x + rect->w - radius / 2 - 1, rect->y + 2);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 1, rect->y + radius - 2, rect->x + 1, rect->y + rect->h - 2);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w - 2, rect->y + radius - 2, rect->x + rect->w - 2, rect->y + rect->h - 2);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 1, rect->y + rect->h - 1, rect->x + rect->w - 2, rect->y + rect->h - 1);
|
||||
}
|
||||
|
||||
|
|
@ -188,13 +220,17 @@ static void draw_beveled_bar(SDL_Renderer *renderer,
|
|||
}
|
||||
|
||||
fill_three_stop_gradient(renderer, rect, top, mid, bottom);
|
||||
SDL_SetRenderDrawColor(renderer, top_edge.r, top_edge.g, top_edge.b, 255);
|
||||
top_edge = blend_color(top_edge, mid, 170);
|
||||
bottom_edge = blend_color(bottom_edge, mid, 170);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, top_edge.r, top_edge.g, top_edge.b, 110);
|
||||
SDL_RenderDrawLine(renderer, rect->x, rect->y, rect->x + rect->w - 1, rect->y);
|
||||
SDL_SetRenderDrawColor(renderer, bottom_edge.r, bottom_edge.g, bottom_edge.b, 255);
|
||||
SDL_SetRenderDrawColor(renderer, bottom_edge.r, bottom_edge.g, bottom_edge.b, 110);
|
||||
SDL_RenderDrawLine(renderer, rect->x, rect->y + rect->h - 1, rect->x + rect->w - 1, rect->y + rect->h - 1);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
static void draw_pill_button(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color fill, SDL_Color border) {
|
||||
static void draw_pill_button(SDL_Renderer *renderer, const GuideTheme *theme, const SDL_Rect *rect, SDL_Color fill, SDL_Color border) {
|
||||
SDL_Rect shadow;
|
||||
|
||||
if (!rect || rect->w < 10 || rect->h < 10) {
|
||||
|
|
@ -202,8 +238,8 @@ static void draw_pill_button(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_C
|
|||
}
|
||||
|
||||
shadow = (SDL_Rect){rect->x + 2, rect->y + 2, rect->w, rect->h};
|
||||
fill_rect_alpha(renderer, &shadow, COLOR_PILL_SHADOW);
|
||||
draw_beveled_bar(renderer, rect, COLOR_PILL_LIGHT, fill, fill, COLOR_GLOSS, border);
|
||||
fill_rect_alpha(renderer, &shadow, theme->pill_shadow);
|
||||
draw_beveled_bar(renderer, rect, theme->pill_light, fill, fill, theme->gloss, border);
|
||||
set_draw_color(renderer, border);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 4, rect->y, rect->x + rect->w - 5, rect->y);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 4, rect->y + rect->h - 1, rect->x + rect->w - 5, rect->y + rect->h - 1);
|
||||
|
|
@ -325,58 +361,63 @@ static void format_clock_label(char *buffer, size_t buffer_size, time_t now, int
|
|||
strftime(buffer, buffer_size, "%I:%M %p", &local_time);
|
||||
}
|
||||
|
||||
static void draw_timeline_header_cached(SDL_Renderer *renderer, const UiCache *cache, SDL_Rect rect) {
|
||||
static void draw_timeline_header_cached(SDL_Renderer *renderer, const UiCache *cache, const GuideTheme *theme, SDL_Rect rect) {
|
||||
int segments = 4;
|
||||
|
||||
draw_beveled_bar(renderer,
|
||||
&rect,
|
||||
COLOR_RIBBON_TOP,
|
||||
(SDL_Color){0x36, 0x2d, 0x83, 0xff},
|
||||
COLOR_RIBBON_BOTTOM,
|
||||
COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
theme->ribbon_top,
|
||||
theme->ribbon_mid,
|
||||
theme->ribbon_bottom,
|
||||
theme->gloss,
|
||||
theme->panel_border);
|
||||
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int x = rect.x + (rect.w * i) / segments;
|
||||
int centered_x = x - cache->timeline_labels[i].width / 2;
|
||||
draw_cached_text(renderer, &cache->timeline_labels[i], centered_x, rect.y + 10);
|
||||
set_draw_color(renderer, COLOR_GRID_LINE);
|
||||
set_draw_color(renderer, theme->grid_line);
|
||||
SDL_RenderDrawLine(renderer, x, rect.y + rect.h - 2, x, rect.y + rect.h + 5 * 76);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_status_bar(SDL_Renderer *renderer,
|
||||
TTF_Font *font,
|
||||
const GuideTheme *theme,
|
||||
const Channel *selected_channel,
|
||||
const SDL_Rect *rect,
|
||||
time_t now_wall) {
|
||||
char clock_text[32];
|
||||
char channel_text[160];
|
||||
SDL_Color text_color;
|
||||
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
text_color = readable_text_color(theme->status_mid);
|
||||
|
||||
draw_beveled_bar(renderer,
|
||||
rect,
|
||||
COLOR_BUTTON_BAR_TOP,
|
||||
COLOR_HEADER_SILVER,
|
||||
COLOR_BUTTON_BAR_BOTTOM,
|
||||
COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
blend_color(theme->status_top, theme->status_mid, 220),
|
||||
theme->status_mid,
|
||||
blend_color(theme->status_bottom, theme->status_mid, 220),
|
||||
color_with_alpha(theme->gloss, 36),
|
||||
theme->panel_border);
|
||||
format_time_compact(clock_text, sizeof(clock_text), now_wall);
|
||||
draw_text_clipped(renderer, font, clock_text, rect, rect->x + 12, rect->y + 10, COLOR_PANEL_TEXT);
|
||||
set_draw_color(renderer, COLOR_STATUS_DIVIDER);
|
||||
draw_text_clipped(renderer, font, clock_text, rect, rect->x + 12, rect->y + 10, text_color);
|
||||
set_draw_color(renderer, theme->status_divider);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w / 2, rect->y + 8, rect->x + rect->w / 2, rect->y + rect->h - 8);
|
||||
|
||||
if (selected_channel) {
|
||||
snprintf(channel_text, sizeof(channel_text), "%s %d", selected_channel->name, selected_channel->number);
|
||||
draw_text_clipped(renderer, font, channel_text, rect, rect->x + rect->w - 260, rect->y + 10, COLOR_PANEL_TEXT);
|
||||
draw_text_clipped(renderer, font, channel_text, rect, rect->x + rect->w - 260, rect->y + 10, text_color);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_info_panel(SDL_Renderer *renderer,
|
||||
const UiFonts *fonts,
|
||||
const GuideTheme *theme,
|
||||
const Channel *selected_channel,
|
||||
const SDL_Rect *rect,
|
||||
Uint64 app_start_ticks,
|
||||
|
|
@ -397,11 +438,11 @@ static void draw_info_panel(SDL_Renderer *renderer,
|
|||
}
|
||||
|
||||
draw_panel_shadow(renderer, rect);
|
||||
draw_rounded_top_panel(renderer, rect, COLOR_HEADER_SILVER);
|
||||
draw_rounded_top_panel(renderer, rect, theme->panel_fill, theme->panel_border, theme->rounded_radius > 0 ? theme->rounded_radius : 8);
|
||||
accent = (SDL_Rect){rect->x + 1, rect->y + 1, rect->w - 2, 38};
|
||||
fill_rect(renderer, &accent, COLOR_HEADER_SILVER);
|
||||
draw_panel_bevel(renderer, rect);
|
||||
stroke_rect(renderer, rect, COLOR_BORDER_DARK);
|
||||
fill_rect(renderer, &accent, theme->panel_fill);
|
||||
draw_panel_bevel(renderer, rect, theme->gloss);
|
||||
stroke_rect(renderer, rect, theme->panel_border);
|
||||
|
||||
program = channel_resolve_program(selected_channel, app_start_ticks, now_ticks, &program_seek, NULL);
|
||||
if (!program) {
|
||||
|
|
@ -419,66 +460,73 @@ static void draw_info_panel(SDL_Renderer *renderer,
|
|||
selected_channel->description[0] != '\0' ? selected_channel->description : "Local programming lineup.");
|
||||
|
||||
clip_rect = (SDL_Rect){rect->x + 16, rect->y + 12, rect->w - 32, rect->h - 24};
|
||||
draw_text_clipped(renderer, fonts->large, selected_channel->name, &clip_rect, rect->x + 18, rect->y + 44, COLOR_PANEL_TEXT);
|
||||
draw_text_clipped(renderer, fonts->medium, program->program_title, &clip_rect, rect->x + 18, rect->y + 88, COLOR_PANEL_TEXT);
|
||||
draw_text_clipped(renderer, fonts->small, time_range, &clip_rect, rect->x + 18, rect->y + 124, COLOR_PANEL_TEXT);
|
||||
draw_text_clipped(renderer, fonts->small, description, &clip_rect, rect->x + 18, rect->y + 148, COLOR_PANEL_TEXT);
|
||||
draw_text_clipped(renderer, fonts->large, selected_channel->name, &clip_rect, rect->x + 18, rect->y + 44, theme->panel_text);
|
||||
draw_text_clipped(renderer, fonts->medium, program->program_title, &clip_rect, rect->x + 18, rect->y + 88, theme->panel_text);
|
||||
draw_text_clipped(renderer, fonts->small, time_range, &clip_rect, rect->x + 18, rect->y + 124, theme->panel_text);
|
||||
draw_text_clipped(renderer, fonts->small, description, &clip_rect, rect->x + 18, rect->y + 148, theme->panel_text);
|
||||
}
|
||||
|
||||
static void draw_grid_background(SDL_Renderer *renderer, const SDL_Rect *grid_rect, int row_height, double pixels_per_minute) {
|
||||
static void draw_grid_background(SDL_Renderer *renderer, const GuideTheme *theme, const SDL_Rect *grid_rect, int row_height, double pixels_per_minute) {
|
||||
fill_three_stop_gradient(renderer,
|
||||
grid_rect,
|
||||
(SDL_Color){0x34, 0x26, 0x88, 0xff},
|
||||
(SDL_Color){0x1b, 0x2f, 0x8f, 0xff},
|
||||
(SDL_Color){0x00, 0x11, 0x33, 0xff});
|
||||
theme->background_top,
|
||||
theme->background_mid,
|
||||
theme->background_bottom);
|
||||
|
||||
for (int minute = 0; minute <= 90; minute += 30) {
|
||||
int x = GUIDE_X_START + (int) (minute * pixels_per_minute);
|
||||
set_draw_color(renderer, COLOR_GRID_LINE);
|
||||
set_draw_color(renderer, theme->grid_line);
|
||||
SDL_RenderDrawLine(renderer, x, grid_rect->y, x, grid_rect->y + grid_rect->h);
|
||||
}
|
||||
|
||||
for (int row = 0; row <= GUIDE_VISIBLE_ROWS; ++row) {
|
||||
int y = grid_rect->y + row * row_height;
|
||||
set_draw_color(renderer, COLOR_ROW_LINE_HI);
|
||||
set_draw_color(renderer, theme->row_line_hi);
|
||||
SDL_RenderDrawLine(renderer, grid_rect->x, y, grid_rect->x + grid_rect->w, y);
|
||||
if (y + row_height - 1 <= grid_rect->y + grid_rect->h) {
|
||||
set_draw_color(renderer, COLOR_ROW_LINE_LO);
|
||||
set_draw_color(renderer, theme->row_line_lo);
|
||||
SDL_RenderDrawLine(renderer, grid_rect->x, y + row_height - 1, grid_rect->x + grid_rect->w, y + row_height - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_footer_legend(SDL_Renderer *renderer, const UiCache *cache, int window_width, int window_height) {
|
||||
static void draw_footer_legend(SDL_Renderer *renderer,
|
||||
const UiFonts *fonts,
|
||||
const GuideTheme *theme,
|
||||
int window_width,
|
||||
int window_height) {
|
||||
SDL_Rect footer = {0, window_height - 54, window_width, 54};
|
||||
SDL_Rect chip = {window_width / 2 - 180, window_height - 38, 34, 20};
|
||||
SDL_Color footer_text = readable_text_color(theme->footer_mid);
|
||||
|
||||
fill_three_stop_gradient(renderer, &footer, COLOR_BUTTON_BAR_TOP, COLOR_HEADER_SILVER, COLOR_BUTTON_BAR_BOTTOM);
|
||||
draw_gloss_line(renderer, &footer);
|
||||
stroke_rect(renderer, &footer, COLOR_BORDER_DARK);
|
||||
fill_three_stop_gradient(renderer,
|
||||
&footer,
|
||||
blend_color(theme->footer_top, theme->footer_mid, 240),
|
||||
theme->footer_mid,
|
||||
blend_color(theme->footer_bottom, theme->footer_mid, 240));
|
||||
draw_gloss_line(renderer, &footer, color_with_alpha(theme->gloss, 20));
|
||||
stroke_rect(renderer, &footer, theme->panel_border);
|
||||
|
||||
draw_pill_button(renderer, &chip, COLOR_HIGHLIGHT_YELLOW, COLOR_BORDER_DARK);
|
||||
draw_cached_text(renderer, &cache->footer_a, chip.x + 11, chip.y + 1);
|
||||
draw_cached_text(renderer, &cache->footer_time, chip.x + 42, chip.y - 1);
|
||||
draw_pill_button(renderer, theme, &chip, theme->panel_fill, theme->panel_border);
|
||||
draw_text_clipped(renderer, fonts->medium, "A", &footer, chip.x + 11, chip.y + 1, footer_text);
|
||||
draw_text_clipped(renderer, fonts->small, "TIME", &footer, chip.x + 42, chip.y - 1, footer_text);
|
||||
|
||||
chip.x += 144;
|
||||
draw_pill_button(renderer, &chip, COLOR_BLOCK_UNSELECTED, COLOR_BORDER_DARK);
|
||||
draw_cached_text(renderer, &cache->footer_b, chip.x + 11, chip.y + 1);
|
||||
draw_cached_text(renderer, &cache->footer_theme, chip.x + 42, chip.y - 1);
|
||||
draw_pill_button(renderer, theme, &chip, theme->block_mid, theme->panel_border);
|
||||
draw_text_clipped(renderer, fonts->medium, "B", &footer, chip.x + 11, chip.y + 1, footer_text);
|
||||
draw_text_clipped(renderer, fonts->small, "THEME", &footer, chip.x + 42, chip.y - 1, footer_text);
|
||||
|
||||
chip.x += 150;
|
||||
draw_pill_button(renderer, &chip, COLOR_HINT_RED, COLOR_BORDER_DARK);
|
||||
draw_cached_text(renderer, &cache->footer_c, chip.x + 11, chip.y + 1);
|
||||
draw_cached_text(renderer, &cache->footer_title, chip.x + 42, chip.y - 1);
|
||||
draw_pill_button(renderer, theme, &chip, theme->row_active_mid, theme->panel_border);
|
||||
draw_text_clipped(renderer, fonts->medium, "C", &footer, chip.x + 11, chip.y + 1, footer_text);
|
||||
draw_text_clipped(renderer, fonts->small, "TITLE", &footer, chip.x + 42, chip.y - 1, footer_text);
|
||||
}
|
||||
|
||||
static void draw_scanline_overlay(SDL_Renderer *renderer, int width, int height) {
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 26);
|
||||
for (int y = 0; y < height; y += 2) {
|
||||
SDL_RenderDrawLine(renderer, 0, y, width, y);
|
||||
}
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
static void draw_scanline_overlay(SDL_Renderer *renderer, int width, int height, const GuideTheme *theme) {
|
||||
(void) renderer;
|
||||
(void) width;
|
||||
(void) height;
|
||||
(void) theme;
|
||||
}
|
||||
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache, int window_width, int window_height) {
|
||||
|
|
@ -506,6 +554,7 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
int texture_height,
|
||||
int window_width,
|
||||
int window_height,
|
||||
const GuideTheme *theme,
|
||||
const UiFonts *fonts,
|
||||
UiCache *cache,
|
||||
const ChannelList *channels,
|
||||
|
|
@ -535,26 +584,26 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
|
||||
fill_three_stop_gradient(renderer,
|
||||
&full,
|
||||
(SDL_Color){0x2a, 0x2e, 0x8f, 0xff},
|
||||
COLOR_GUIDE_TOP,
|
||||
COLOR_GUIDE_BOTTOM);
|
||||
draw_info_panel(renderer, fonts, selected_channel, &info_panel, app_start_ticks, now_ticks, now_wall);
|
||||
theme->background_top,
|
||||
theme->background_mid,
|
||||
theme->background_bottom);
|
||||
draw_info_panel(renderer, fonts, theme, selected_channel, &info_panel, app_start_ticks, now_ticks, now_wall);
|
||||
draw_panel_shadow(renderer, &preview);
|
||||
fill_rect(renderer, &preview, COLOR_BLACK);
|
||||
draw_video(renderer, video_texture, texture_width, texture_height, preview);
|
||||
draw_status_bar(renderer, fonts->medium, selected_channel, &status_bar, now_wall);
|
||||
draw_status_bar(renderer, fonts->medium, theme, selected_channel, &status_bar, now_wall);
|
||||
|
||||
if (cache->timeline_label_slot != now_wall / 60) {
|
||||
char label[32];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
format_clock_label(label, sizeof(label), now_wall, (int) ((TIMELINE_VISIBLE_SECONDS / 60.0 / 4) * i));
|
||||
text_texture_destroy(&cache->timeline_labels[i]);
|
||||
text_texture_init(&cache->timeline_labels[i], renderer, fonts->small, label, COLOR_TEXT_LIGHT);
|
||||
text_texture_init(&cache->timeline_labels[i], renderer, fonts->small, label, theme->ribbon_text);
|
||||
}
|
||||
cache->timeline_label_slot = now_wall / 60;
|
||||
}
|
||||
draw_timeline_header_cached(renderer, cache, header_row);
|
||||
draw_grid_background(renderer, &grid, row_height, pixels_per_minute);
|
||||
draw_timeline_header_cached(renderer, cache, theme, header_row);
|
||||
draw_grid_background(renderer, theme, &grid, row_height, pixels_per_minute);
|
||||
|
||||
if (start_index < 0) {
|
||||
start_index = 0;
|
||||
|
|
@ -574,19 +623,19 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
|
||||
draw_beveled_bar(renderer,
|
||||
&row_rect,
|
||||
is_selected ? COLOR_ROW_ACTIVE_TOP : COLOR_ROW_TOP,
|
||||
is_selected ? COLOR_ROW_ACTIVE_MID : COLOR_ROW_MID,
|
||||
is_selected ? COLOR_ROW_ACTIVE_BOTTOM : COLOR_ROW_BOTTOM,
|
||||
COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
is_selected ? theme->row_active_top : theme->row_top,
|
||||
is_selected ? theme->row_active_mid : theme->row_mid,
|
||||
is_selected ? theme->row_active_bottom : theme->row_bottom,
|
||||
theme->gloss,
|
||||
theme->panel_border);
|
||||
fill_rect_alpha(renderer, &inset, (SDL_Color){255, 255, 255, is_selected ? 12 : 6});
|
||||
draw_beveled_bar(renderer,
|
||||
&sidebar,
|
||||
is_selected ? COLOR_ROW_ACTIVE_TOP : COLOR_ROW_TOP,
|
||||
is_selected ? COLOR_ROW_ACTIVE_MID : COLOR_ROW_MID,
|
||||
is_selected ? COLOR_ROW_ACTIVE_BOTTOM : COLOR_ROW_BOTTOM,
|
||||
COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
is_selected ? theme->row_active_top : theme->row_top,
|
||||
is_selected ? theme->row_active_mid : theme->row_mid,
|
||||
is_selected ? theme->row_active_bottom : theme->row_bottom,
|
||||
theme->gloss,
|
||||
theme->panel_border);
|
||||
|
||||
if (!channels || channel_index >= channels->count) {
|
||||
continue;
|
||||
|
|
@ -616,26 +665,36 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
title_rect = (SDL_Rect){block.x + 8, block.y + 8, block.w - 16, block.h - 16};
|
||||
|
||||
if (is_selected) {
|
||||
draw_text_clipped(renderer, fonts->medium, channel->name, &sidebar, 20, row_rect.y + 12, COLOR_ACTIVE_TEXT);
|
||||
draw_text_clipped(renderer, fonts->medium, channel->name, &sidebar, 20, row_rect.y + 12, theme->row_active_text);
|
||||
{
|
||||
char number[16];
|
||||
snprintf(number, sizeof(number), "%d", channel->number);
|
||||
draw_text_clipped(renderer, fonts->medium, number, &sidebar, 176, row_rect.y + 12, COLOR_ACTIVE_TEXT);
|
||||
draw_text_clipped(renderer, fonts->medium, number, &sidebar, 176, row_rect.y + 12, theme->row_active_text);
|
||||
}
|
||||
} else {
|
||||
draw_cached_text(renderer, &cache->channels[channel_index].name_medium, 20, row_rect.y + 12);
|
||||
draw_cached_text(renderer, &cache->channels[channel_index].number_medium, 176, row_rect.y + 12);
|
||||
draw_text_clipped(renderer, fonts->medium, channel->name, &sidebar, 20, row_rect.y + 12, theme->row_text);
|
||||
{
|
||||
char number[16];
|
||||
snprintf(number, sizeof(number), "%d", channel->number);
|
||||
draw_text_clipped(renderer, fonts->medium, number, &sidebar, 176, row_rect.y + 12, theme->row_text);
|
||||
}
|
||||
}
|
||||
draw_text_clipped(renderer, fonts->small, program->file_name, &sidebar, 20, row_rect.y + 38, COLOR_PALE_BLUE);
|
||||
draw_text_clipped(renderer,
|
||||
fonts->small,
|
||||
program->file_name,
|
||||
&sidebar,
|
||||
20,
|
||||
row_rect.y + 38,
|
||||
secondary_text_color(theme->row_text, is_selected ? theme->row_active_mid : theme->row_mid));
|
||||
|
||||
SDL_RenderSetClipRect(renderer, &clip);
|
||||
draw_beveled_bar(renderer,
|
||||
&block,
|
||||
is_selected ? COLOR_BLOCK_ACTIVE_TOP : COLOR_BLOCK_TOP,
|
||||
is_selected ? COLOR_BLOCK_ACTIVE_MID : COLOR_BLOCK_MID,
|
||||
is_selected ? COLOR_BLOCK_ACTIVE_BOTTOM : COLOR_BLOCK_BOTTOM,
|
||||
is_selected ? COLOR_SELECTION_EDGE : COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
is_selected ? theme->block_active_top : theme->block_top,
|
||||
is_selected ? theme->block_active_mid : theme->block_mid,
|
||||
is_selected ? theme->block_active_bottom : theme->block_bottom,
|
||||
is_selected ? theme->selection_edge : theme->gloss,
|
||||
theme->panel_border);
|
||||
fit_text_with_ellipsis(is_selected ? fonts->medium : fonts->small,
|
||||
program->program_title,
|
||||
title_rect.w,
|
||||
|
|
@ -647,19 +706,70 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
&title_rect,
|
||||
title_rect.x,
|
||||
title_rect.y,
|
||||
is_selected ? COLOR_TEXT_DARK : COLOR_TEXT_LIGHT);
|
||||
is_selected ? theme->block_active_text : theme->block_text);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_channel && active_channel >= 0 && start_index <= active_channel && active_channel < start_index + GUIDE_VISIBLE_ROWS) {
|
||||
SDL_Rect highlight = {0, grid.y + (active_channel - start_index) * row_height, window_width, row_height};
|
||||
draw_selection_glow(renderer, &highlight);
|
||||
draw_selection_glow(renderer, &(SDL_Rect){guide_x_start, highlight.y + (int) (6 * scale_y), timeline_w, row_height - (int) (12 * scale_y)});
|
||||
draw_selection_glow(renderer, &highlight, theme->selection_edge);
|
||||
draw_selection_glow(renderer, &(SDL_Rect){guide_x_start, highlight.y + (int) (6 * scale_y), timeline_w, row_height - (int) (12 * scale_y)}, theme->selection_edge);
|
||||
}
|
||||
|
||||
draw_footer_legend(renderer, cache, window_width, window_height);
|
||||
draw_scanline_overlay(renderer, window_width, window_height);
|
||||
draw_footer_legend(renderer, fonts, theme, window_width, window_height);
|
||||
draw_scanline_overlay(renderer, window_width, window_height, theme);
|
||||
}
|
||||
|
||||
void ui_render_theme_picker(SDL_Renderer *renderer,
|
||||
const UiFonts *fonts,
|
||||
int window_width,
|
||||
int window_height,
|
||||
const GuideTheme *active_theme,
|
||||
int current_theme_index,
|
||||
int selected_theme_index) {
|
||||
SDL_Rect overlay = {0, 0, window_width, window_height};
|
||||
SDL_Rect modal = {window_width / 2 - 250, window_height / 2 - 180, 500, 360};
|
||||
SDL_Rect title_bar = {modal.x, modal.y, modal.w, 38};
|
||||
|
||||
(void) current_theme_index;
|
||||
fill_rect_alpha(renderer, &overlay, (SDL_Color){0, 0, 0, 120});
|
||||
draw_panel_shadow(renderer, &modal);
|
||||
draw_rounded_top_panel(renderer, &modal, active_theme->panel_fill, active_theme->panel_border, active_theme->rounded_radius > 0 ? active_theme->rounded_radius : 8);
|
||||
fill_rect(renderer, &(SDL_Rect){modal.x, modal.y + 38, modal.w, modal.h - 38}, active_theme->footer_mid);
|
||||
draw_beveled_bar(renderer, &title_bar, active_theme->ribbon_top, active_theme->ribbon_mid, active_theme->ribbon_bottom, active_theme->gloss, active_theme->panel_border);
|
||||
draw_text_clipped(renderer, fonts->medium, "THEME SELECT", &modal, modal.x + 16, modal.y + 10, active_theme->ribbon_text);
|
||||
|
||||
for (int i = 0; i < GUIDE_THEME_COUNT; ++i) {
|
||||
SDL_Rect item = {modal.x + 18, modal.y + 52 + i * 28, modal.w - 36, 24};
|
||||
SDL_Rect swatch = {modal.x + modal.w - 118, item.y + 4, 92, 14};
|
||||
char label[96];
|
||||
const GuideTheme *theme = &GUIDE_THEMES[i];
|
||||
|
||||
if (i == selected_theme_index) {
|
||||
draw_beveled_bar(renderer, &item, theme->row_active_top, theme->row_active_mid, theme->row_active_bottom, theme->gloss, theme->panel_border);
|
||||
draw_selection_glow(renderer, &item, theme->selection_edge);
|
||||
}
|
||||
|
||||
snprintf(label, sizeof(label), "%c %s", i == selected_theme_index ? '>' : ' ', theme->name);
|
||||
draw_text_clipped(renderer,
|
||||
fonts->small,
|
||||
label,
|
||||
&item,
|
||||
item.x + 8,
|
||||
item.y + 4,
|
||||
i == selected_theme_index ? theme->row_active_text : active_theme->panel_text);
|
||||
fill_three_stop_gradient(renderer, &swatch, theme->background_top, theme->background_mid, theme->background_bottom);
|
||||
stroke_rect(renderer, &swatch, theme->panel_border);
|
||||
}
|
||||
|
||||
draw_text_clipped(renderer,
|
||||
fonts->small,
|
||||
"ENTER APPLY ESC CANCEL B CLOSE",
|
||||
&modal,
|
||||
modal.x + 18,
|
||||
modal.y + modal.h - 28,
|
||||
active_theme->panel_text);
|
||||
}
|
||||
|
||||
int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts, const ChannelList *channels) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue