More guide UI refinement
This commit is contained in:
parent
2bdeba1b45
commit
3e6d29670c
3 changed files with 235 additions and 45 deletions
29
src/theme.h
29
src/theme.h
|
|
@ -18,10 +18,10 @@ static const SDL_Color COLOR_TEXT_LIGHT = {0xf5, 0xf7, 0xfa, 0xff};
|
|||
static const SDL_Color COLOR_TEXT_DARK = {0x0b, 0x11, 0x1d, 0xff};
|
||||
static const SDL_Color COLOR_BLACK = {0x00, 0x00, 0x00, 0xff};
|
||||
static const SDL_Color COLOR_HEADER_SILVER = {0xe6, 0xe6, 0xe6, 0xff};
|
||||
static const SDL_Color COLOR_SELECTED_ROW = {0x06, 0x13, 0x2c, 0xff};
|
||||
static const SDL_Color COLOR_SELECTED_ROW = {0x14, 0x0d, 0x23, 0xff};
|
||||
static const SDL_Color COLOR_UNSELECTED_ROW = {0x33, 0x44, 0x66, 0xff};
|
||||
static const SDL_Color COLOR_GUIDE_TOP = {0x00, 0x33, 0x99, 0xff};
|
||||
static const SDL_Color COLOR_GUIDE_BOTTOM = {0x00, 0x11, 0x33, 0xff};
|
||||
static const SDL_Color COLOR_GUIDE_TOP = {0x4b, 0x3d, 0x8f, 0xff};
|
||||
static const SDL_Color COLOR_GUIDE_BOTTOM = {0x2e, 0x24, 0x5e, 0xff};
|
||||
static const SDL_Color COLOR_GRID_LINE = {0x89, 0xa0, 0xc5, 0xff};
|
||||
static const SDL_Color COLOR_PANEL_TEXT = {0x12, 0x18, 0x24, 0xff};
|
||||
static const SDL_Color COLOR_PANEL_SHADOW = {0x00, 0x00, 0x00, 0x60};
|
||||
|
|
@ -29,6 +29,29 @@ static const SDL_Color COLOR_STATUS_DIVIDER = {0xb0, 0xb8, 0xc7, 0xff};
|
|||
static const SDL_Color COLOR_BLOCK_UNSELECTED = {0x1f, 0x5d, 0xc1, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_SELECTED = {0xff, 0xd7, 0x00, 0xff};
|
||||
static const SDL_Color COLOR_SELECTION_EDGE = {0xff, 0xf1, 0x8b, 0xff};
|
||||
static const SDL_Color COLOR_BORDER_DARK = {0x5b, 0x63, 0x72, 0xff};
|
||||
static const SDL_Color COLOR_GLOSS = {0xff, 0xff, 0xff, 0x80};
|
||||
static const SDL_Color COLOR_RIBBON_TOP = {0x44, 0x2a, 0x88, 0xff};
|
||||
static const SDL_Color COLOR_RIBBON_BOTTOM = {0x1a, 0x1f, 0x63, 0xff};
|
||||
static const SDL_Color COLOR_ROW_TOP = {0x4f, 0x5e, 0x85, 0xff};
|
||||
static const SDL_Color COLOR_ROW_MID = {0x39, 0x49, 0x72, 0xff};
|
||||
static const SDL_Color COLOR_ROW_BOTTOM = {0x25, 0x31, 0x4f, 0xff};
|
||||
static const SDL_Color COLOR_ROW_ACTIVE_TOP = {0x34, 0x24, 0x55, 0xff};
|
||||
static const SDL_Color COLOR_ROW_ACTIVE_MID = {0x18, 0x10, 0x2e, 0xff};
|
||||
static const SDL_Color COLOR_ROW_ACTIVE_BOTTOM = {0x0a, 0x07, 0x16, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_TOP = {0x66, 0x8d, 0xe8, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_MID = {0x3b, 0x69, 0xd5, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_BOTTOM = {0x1a, 0x42, 0x9c, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_ACTIVE_TOP = {0xff, 0xef, 0xa2, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_ACTIVE_MID = {0xff, 0xdb, 0x48, 0xff};
|
||||
static const SDL_Color COLOR_BLOCK_ACTIVE_BOTTOM = {0xd1, 0x9f, 0x00, 0xff};
|
||||
static const SDL_Color COLOR_ACTIVE_TEXT = {0xff, 0xcc, 0x00, 0xff};
|
||||
static const SDL_Color COLOR_ROW_LINE_HI = {0x6a, 0x5c, 0xa9, 0xff};
|
||||
static const SDL_Color COLOR_ROW_LINE_LO = {0x1f, 0x17, 0x43, 0xff};
|
||||
static const SDL_Color COLOR_BUTTON_BAR_TOP = {0xf3, 0xf3, 0xf3, 0xff};
|
||||
static const SDL_Color COLOR_BUTTON_BAR_BOTTOM = {0xc7, 0xcc, 0xd6, 0xff};
|
||||
static const SDL_Color COLOR_PILL_LIGHT = {0xfa, 0xfb, 0xff, 0xff};
|
||||
static const SDL_Color COLOR_PILL_SHADOW = {0x00, 0x00, 0x00, 0x40};
|
||||
|
||||
#define WINDOW_WIDTH 1280
|
||||
#define WINDOW_HEIGHT 720
|
||||
|
|
|
|||
251
src/ui.c
251
src/ui.c
|
|
@ -51,7 +51,7 @@ static SDL_Texture *text_to_texture(SDL_Renderer *renderer, TTF_Font *font, cons
|
|||
return NULL;
|
||||
}
|
||||
|
||||
surface = TTF_RenderUTF8_Blended(font, text, color);
|
||||
surface = TTF_RenderUTF8_Solid(font, text, color);
|
||||
if (!surface) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -81,15 +81,26 @@ static void draw_cached_text(SDL_Renderer *renderer, const UiTextTexture *text_t
|
|||
SDL_RenderCopy(renderer, text_texture->texture, NULL, &dst);
|
||||
}
|
||||
|
||||
static void fill_vertical_gradient(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color top, SDL_Color bottom) {
|
||||
static void fill_three_stop_gradient(SDL_Renderer *renderer,
|
||||
const SDL_Rect *rect,
|
||||
SDL_Color top,
|
||||
SDL_Color middle,
|
||||
SDL_Color bottom) {
|
||||
int split;
|
||||
|
||||
if (!rect || rect->h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
split = rect->h / 2;
|
||||
for (int i = 0; i < rect->h; ++i) {
|
||||
Uint8 r = (Uint8) (top.r + (bottom.r - top.r) * i / SDL_max(rect->h - 1, 1));
|
||||
Uint8 g = (Uint8) (top.g + (bottom.g - top.g) * i / SDL_max(rect->h - 1, 1));
|
||||
Uint8 b = (Uint8) (top.b + (bottom.b - top.b) * i / SDL_max(rect->h - 1, 1));
|
||||
SDL_Color from = i < split ? top : middle;
|
||||
SDL_Color to = i < split ? middle : bottom;
|
||||
int segment_height = i < split ? SDL_max(split, 1) : SDL_max(rect->h - split, 1);
|
||||
int segment_pos = i < split ? i : i - split;
|
||||
Uint8 r = (Uint8) (from.r + (to.r - from.r) * segment_pos / SDL_max(segment_height - 1, 1));
|
||||
Uint8 g = (Uint8) (from.g + (to.g - from.g) * segment_pos / SDL_max(segment_height - 1, 1));
|
||||
Uint8 b = (Uint8) (from.b + (to.b - from.b) * segment_pos / SDL_max(segment_height - 1, 1));
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, 255);
|
||||
SDL_RenderDrawLine(renderer, rect->x, rect->y + i, rect->x + rect->w, rect->y + i);
|
||||
}
|
||||
|
|
@ -107,6 +118,99 @@ static void draw_panel_shadow(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
|||
fill_rect_alpha(renderer, &shadow, COLOR_PANEL_SHADOW);
|
||||
}
|
||||
|
||||
static void draw_gloss_line(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_panel_bevel(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
static void stroke_rect_alpha(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color color) {
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
|
||||
SDL_RenderDrawRect(renderer, rect);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
static void draw_selection_glow(SDL_Renderer *renderer, const SDL_Rect *rect) {
|
||||
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});
|
||||
if (inner.w > 0 && inner.h > 0) {
|
||||
stroke_rect_alpha(renderer, &inner, (SDL_Color){0xff, 0xd7, 0x00, 70});
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_rounded_top_panel(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color fill_color) {
|
||||
SDL_Rect body;
|
||||
SDL_Rect top;
|
||||
|
||||
if (!rect || rect->w < 8 || rect->h < 8) {
|
||||
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};
|
||||
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);
|
||||
|
||||
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);
|
||||
SDL_RenderDrawLine(renderer, rect->x + 1, rect->y + rect->h - 1, rect->x + rect->w - 2, rect->y + rect->h - 1);
|
||||
}
|
||||
|
||||
static void draw_beveled_bar(SDL_Renderer *renderer,
|
||||
const SDL_Rect *rect,
|
||||
SDL_Color top,
|
||||
SDL_Color mid,
|
||||
SDL_Color bottom,
|
||||
SDL_Color top_edge,
|
||||
SDL_Color bottom_edge) {
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
fill_three_stop_gradient(renderer, rect, top, mid, bottom);
|
||||
SDL_SetRenderDrawColor(renderer, top_edge.r, top_edge.g, top_edge.b, 255);
|
||||
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_RenderDrawLine(renderer, rect->x, rect->y + rect->h - 1, rect->x + rect->w - 1, rect->y + rect->h - 1);
|
||||
}
|
||||
|
||||
static void draw_pill_button(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color fill, SDL_Color border) {
|
||||
SDL_Rect shadow;
|
||||
|
||||
if (!rect || rect->w < 10 || rect->h < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
SDL_RenderDrawLine(renderer, rect->x, rect->y + 4, rect->x, rect->y + rect->h - 5);
|
||||
SDL_RenderDrawLine(renderer, rect->x + rect->w - 1, rect->y + 4, rect->x + rect->w - 1, rect->y + rect->h - 5);
|
||||
}
|
||||
|
||||
static void draw_text_clipped(SDL_Renderer *renderer,
|
||||
TTF_Font *font,
|
||||
const char *text,
|
||||
|
|
@ -224,9 +328,18 @@ static void format_clock_label(char *buffer, size_t buffer_size, time_t now, int
|
|||
static void draw_timeline_header_cached(SDL_Renderer *renderer, const UiCache *cache, 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);
|
||||
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int x = rect.x + (rect.w * i) / segments;
|
||||
draw_cached_text(renderer, &cache->timeline_labels[i], x + 8, rect.y + 10);
|
||||
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);
|
||||
SDL_RenderDrawLine(renderer, x, rect.y + rect.h - 2, x, rect.y + rect.h + 5 * 76);
|
||||
}
|
||||
|
|
@ -244,8 +357,13 @@ static void draw_status_bar(SDL_Renderer *renderer,
|
|||
return;
|
||||
}
|
||||
|
||||
fill_rect(renderer, rect, COLOR_HEADER_SILVER);
|
||||
stroke_rect(renderer, rect, COLOR_GRID_LINE);
|
||||
draw_beveled_bar(renderer,
|
||||
rect,
|
||||
COLOR_BUTTON_BAR_TOP,
|
||||
COLOR_HEADER_SILVER,
|
||||
COLOR_BUTTON_BAR_BOTTOM,
|
||||
COLOR_GLOSS,
|
||||
COLOR_BORDER_DARK);
|
||||
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);
|
||||
|
|
@ -278,10 +396,11 @@ static void draw_info_panel(SDL_Renderer *renderer,
|
|||
}
|
||||
|
||||
draw_panel_shadow(renderer, rect);
|
||||
fill_rect(renderer, rect, COLOR_HEADER_SILVER);
|
||||
accent = (SDL_Rect){rect->x, rect->y, rect->w, 36};
|
||||
fill_rect(renderer, &accent, COLOR_HIGHLIGHT_YELLOW);
|
||||
stroke_rect(renderer, rect, COLOR_GRID_LINE);
|
||||
draw_rounded_top_panel(renderer, rect, COLOR_HEADER_SILVER);
|
||||
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);
|
||||
|
||||
live_position = channel_live_position_precise(selected_channel, app_start_ticks, now_ticks);
|
||||
start_time = now_wall - (time_t) live_position;
|
||||
|
|
@ -305,7 +424,11 @@ static void draw_info_panel(SDL_Renderer *renderer,
|
|||
}
|
||||
|
||||
static void draw_grid_background(SDL_Renderer *renderer, const SDL_Rect *grid_rect, int row_height, double pixels_per_minute) {
|
||||
fill_vertical_gradient(renderer, grid_rect, COLOR_GUIDE_TOP, COLOR_GUIDE_BOTTOM);
|
||||
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});
|
||||
|
||||
for (int minute = 0; minute <= 90; minute += 30) {
|
||||
int x = GUIDE_X_START + (int) (minute * pixels_per_minute);
|
||||
|
|
@ -315,32 +438,45 @@ static void draw_grid_background(SDL_Renderer *renderer, const SDL_Rect *grid_re
|
|||
|
||||
for (int row = 0; row <= GUIDE_VISIBLE_ROWS; ++row) {
|
||||
int y = grid_rect->y + row * row_height;
|
||||
set_draw_color(renderer, COLOR_GRID_LINE);
|
||||
set_draw_color(renderer, COLOR_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);
|
||||
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) {
|
||||
SDL_Rect footer = {0, window_height - 54, window_width, 54};
|
||||
SDL_Rect chip = {window_width / 2 - 170, window_height - 40, 24, 24};
|
||||
SDL_Rect chip = {window_width / 2 - 180, window_height - 38, 34, 20};
|
||||
|
||||
fill_rect(renderer, &footer, COLOR_PALE_BLUE);
|
||||
set_draw_color(renderer, COLOR_SLATE);
|
||||
SDL_RenderDrawLine(renderer, footer.x, footer.y, footer.x + footer.w, footer.y);
|
||||
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_rect(renderer, &chip, COLOR_HIGHLIGHT_YELLOW);
|
||||
draw_cached_text(renderer, &cache->footer_a, chip.x + 7, chip.y + 2);
|
||||
draw_cached_text(renderer, &cache->footer_time, chip.x + 34, chip.y + 1);
|
||||
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);
|
||||
|
||||
chip.x += 132;
|
||||
fill_rect(renderer, &chip, COLOR_DEEP_BLUE);
|
||||
draw_cached_text(renderer, &cache->footer_b, chip.x + 7, chip.y + 2);
|
||||
draw_cached_text(renderer, &cache->footer_theme, chip.x + 34, chip.y + 1);
|
||||
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);
|
||||
|
||||
chip.x += 136;
|
||||
fill_rect(renderer, &chip, COLOR_HINT_RED);
|
||||
draw_cached_text(renderer, &cache->footer_c, chip.x + 7, chip.y + 2);
|
||||
draw_cached_text(renderer, &cache->footer_title, chip.x + 34, chip.y + 1);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache) {
|
||||
|
|
@ -384,7 +520,11 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
selected_channel = &channels->items[active_channel];
|
||||
}
|
||||
|
||||
fill_vertical_gradient(renderer, &full, COLOR_GUIDE_TOP, COLOR_GUIDE_BOTTOM);
|
||||
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);
|
||||
draw_panel_shadow(renderer, &preview);
|
||||
fill_rect(renderer, &preview, COLOR_BLACK);
|
||||
|
|
@ -396,7 +536,7 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
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_DARK);
|
||||
text_texture_init(&cache->timeline_labels[i], renderer, fonts->small, label, COLOR_TEXT_LIGHT);
|
||||
}
|
||||
cache->timeline_label_slot = now_wall / 60;
|
||||
}
|
||||
|
|
@ -419,9 +559,21 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
int is_selected = channel_index == active_channel;
|
||||
SDL_Rect inset = {row_rect.x + 4, row_rect.y + 3, row_rect.w - 8, row_rect.h - 6};
|
||||
|
||||
fill_rect(renderer, &row_rect, is_selected ? COLOR_SELECTED_ROW : COLOR_UNSELECTED_ROW);
|
||||
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);
|
||||
fill_rect_alpha(renderer, &inset, (SDL_Color){255, 255, 255, is_selected ? 12 : 6});
|
||||
fill_rect(renderer, &sidebar, is_selected ? COLOR_SELECTED_ROW : COLOR_UNSELECTED_ROW);
|
||||
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);
|
||||
|
||||
if (!channels || channel_index >= channels->count) {
|
||||
continue;
|
||||
|
|
@ -438,13 +590,27 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
SDL_Rect title_rect = {block.x + 8, block.y + 8, block.w - 16, block.h - 16};
|
||||
char title[128];
|
||||
|
||||
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);
|
||||
if (is_selected) {
|
||||
draw_text_clipped(renderer, fonts->medium, channel->name, &sidebar, 20, row_rect.y + 12, COLOR_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);
|
||||
}
|
||||
} 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_cached_text(renderer, &cache->channels[channel_index].file_small, 20, row_rect.y + 38);
|
||||
|
||||
SDL_RenderSetClipRect(renderer, &clip);
|
||||
fill_rect(renderer, &block, is_selected ? COLOR_BLOCK_SELECTED : COLOR_BLOCK_UNSELECTED);
|
||||
stroke_rect(renderer, &block, is_selected ? COLOR_SELECTION_EDGE : COLOR_PALE_BLUE);
|
||||
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);
|
||||
fit_text_with_ellipsis(is_selected ? fonts->medium : fonts->small,
|
||||
channel->program_title,
|
||||
title_rect.w,
|
||||
|
|
@ -463,11 +629,12 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
|
||||
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};
|
||||
stroke_rect(renderer, &highlight, COLOR_SELECTION_EDGE);
|
||||
SDL_RenderDrawRect(renderer, &(SDL_Rect){GUIDE_X_START, highlight.y + 6, timeline_w, row_height - 12});
|
||||
draw_selection_glow(renderer, &highlight);
|
||||
draw_selection_glow(renderer, &(SDL_Rect){GUIDE_X_START, highlight.y + 6, timeline_w, row_height - 12});
|
||||
}
|
||||
|
||||
draw_footer_legend(renderer, cache, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
draw_scanline_overlay(renderer, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
}
|
||||
|
||||
int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts, const ChannelList *channels) {
|
||||
|
|
@ -490,11 +657,11 @@ int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts,
|
|||
text_texture_init(&cache->no_media_body, renderer, fonts->medium, "No channels found in ./media", COLOR_HIGHLIGHT_YELLOW) != 0 ||
|
||||
text_texture_init(&cache->no_media_hint, renderer, fonts->small, "Add MP4 or MKV files to ./media and relaunch.", COLOR_PALE_BLUE) != 0 ||
|
||||
text_texture_init(&cache->footer_a, renderer, fonts->medium, "A", COLOR_TEXT_DARK) != 0 ||
|
||||
text_texture_init(&cache->footer_time, renderer, fonts->medium, "Time", COLOR_TEXT_DARK) != 0 ||
|
||||
text_texture_init(&cache->footer_time, renderer, fonts->small, "TIME", COLOR_TEXT_DARK) != 0 ||
|
||||
text_texture_init(&cache->footer_b, renderer, fonts->medium, "B", COLOR_TEXT_LIGHT) != 0 ||
|
||||
text_texture_init(&cache->footer_theme, renderer, fonts->medium, "Theme", COLOR_TEXT_DARK) != 0 ||
|
||||
text_texture_init(&cache->footer_theme, renderer, fonts->small, "THEME", COLOR_TEXT_DARK) != 0 ||
|
||||
text_texture_init(&cache->footer_c, renderer, fonts->medium, "C", COLOR_TEXT_LIGHT) != 0 ||
|
||||
text_texture_init(&cache->footer_title, renderer, fonts->medium, "Title", COLOR_TEXT_DARK) != 0) {
|
||||
text_texture_init(&cache->footer_title, renderer, fonts->small, "TITLE", COLOR_TEXT_DARK) != 0) {
|
||||
ui_cache_destroy(cache);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
BIN
src/ui.o
BIN
src/ui.o
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue