Guide cleanup
This commit is contained in:
parent
7c5d82e124
commit
2bdeba1b45
4 changed files with 256 additions and 51 deletions
21
src/theme.h
21
src/theme.h
|
|
@ -17,10 +17,31 @@ static const SDL_Color COLOR_PALE_BLUE = {0xcc, 0xd8, 0xf3, 0xff};
|
|||
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_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_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};
|
||||
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};
|
||||
|
||||
#define WINDOW_WIDTH 1280
|
||||
#define WINDOW_HEIGHT 720
|
||||
#define GUIDE_VISIBLE_ROWS 5
|
||||
#define TIMELINE_VISIBLE_SECONDS (90.0 * 60.0)
|
||||
#define GUIDE_INFO_WIDTH 390
|
||||
#define GUIDE_PREVIEW_WIDTH 430
|
||||
#define GUIDE_PREVIEW_HEIGHT 194
|
||||
#define GUIDE_STATUS_HEIGHT 42
|
||||
#define GUIDE_GRID_TOP 212
|
||||
#define GUIDE_FOOTER_HEIGHT 54
|
||||
#define GUIDE_SIDEBAR_WIDTH 246
|
||||
#define GUIDE_X_START 258
|
||||
#define GUIDE_INFO_HEIGHT 184
|
||||
|
||||
#endif
|
||||
|
|
|
|||
284
src/ui.c
284
src/ui.c
|
|
@ -81,6 +81,100 @@ 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) {
|
||||
if (!rect || rect->h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
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_SetRenderDrawColor(renderer, r, g, b, 255);
|
||||
SDL_RenderDrawLine(renderer, rect->x, rect->y + i, rect->x + rect->w, rect->y + i);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_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_RenderFillRect(renderer, rect);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void draw_text_clipped(SDL_Renderer *renderer,
|
||||
TTF_Font *font,
|
||||
const char *text,
|
||||
const SDL_Rect *clip_rect,
|
||||
int x,
|
||||
int y,
|
||||
SDL_Color color) {
|
||||
SDL_Rect previous_clip;
|
||||
SDL_bool had_clip = SDL_RenderIsClipEnabled(renderer);
|
||||
if (had_clip) {
|
||||
SDL_RenderGetClipRect(renderer, &previous_clip);
|
||||
}
|
||||
SDL_RenderSetClipRect(renderer, clip_rect);
|
||||
{
|
||||
SDL_Texture *texture;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
SDL_Rect dst;
|
||||
|
||||
texture = text_to_texture(renderer, font, text, color, &width, &height);
|
||||
if (texture) {
|
||||
dst.x = x;
|
||||
dst.y = y;
|
||||
dst.w = width;
|
||||
dst.h = height;
|
||||
SDL_RenderCopy(renderer, texture, NULL, &dst);
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
}
|
||||
SDL_RenderSetClipRect(renderer, had_clip ? &previous_clip : NULL);
|
||||
}
|
||||
|
||||
static void fit_text_with_ellipsis(TTF_Font *font, const char *text, int max_width, char *out, size_t out_size) {
|
||||
int width = 0;
|
||||
size_t len;
|
||||
|
||||
if (!out || out_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
out[0] = '\0';
|
||||
if (!font || !text || max_width <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TTF_SizeUTF8(font, text, &width, NULL) == 0 && width <= max_width) {
|
||||
snprintf(out, out_size, "%s", text);
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(text);
|
||||
while (len > 0) {
|
||||
snprintf(out, out_size, "%.*s...", (int) len, text);
|
||||
if (TTF_SizeUTF8(font, out, &width, NULL) == 0 && width <= max_width) {
|
||||
return;
|
||||
}
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
snprintf(out, out_size, "...");
|
||||
}
|
||||
|
||||
static void format_time_compact(char *buffer, size_t buffer_size, time_t value) {
|
||||
struct tm local_time;
|
||||
localtime_r(&value, &local_time);
|
||||
strftime(buffer, buffer_size, "%I:%M %p", &local_time);
|
||||
}
|
||||
|
||||
static void fill_rect(SDL_Renderer *renderer, const SDL_Rect *rect, SDL_Color color) {
|
||||
set_draw_color(renderer, color);
|
||||
SDL_RenderFillRect(renderer, rect);
|
||||
|
|
@ -130,13 +224,99 @@ 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_cached_text(renderer, &cache->timeline_day, rect.x + 12, rect.y + 8);
|
||||
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int x = rect.x + (rect.w * i) / segments;
|
||||
draw_cached_text(renderer, &cache->timeline_labels[i], x + 6, rect.y + 10);
|
||||
set_draw_color(renderer, COLOR_SLATE);
|
||||
SDL_RenderDrawLine(renderer, x, rect.y + rect.h - 4, x, rect.y + rect.h + 5 * 76);
|
||||
draw_cached_text(renderer, &cache->timeline_labels[i], x + 8, 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_status_bar(SDL_Renderer *renderer,
|
||||
TTF_Font *font,
|
||||
const Channel *selected_channel,
|
||||
const SDL_Rect *rect,
|
||||
time_t now_wall) {
|
||||
char clock_text[32];
|
||||
char channel_text[160];
|
||||
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
fill_rect(renderer, rect, COLOR_HEADER_SILVER);
|
||||
stroke_rect(renderer, rect, COLOR_GRID_LINE);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_info_panel(SDL_Renderer *renderer,
|
||||
const UiFonts *fonts,
|
||||
const Channel *selected_channel,
|
||||
const SDL_Rect *rect,
|
||||
Uint64 app_start_ticks,
|
||||
Uint64 now_ticks,
|
||||
time_t now_wall) {
|
||||
SDL_Rect accent;
|
||||
SDL_Rect clip_rect;
|
||||
char time_range[64];
|
||||
char end_text[32];
|
||||
char description[384];
|
||||
time_t start_time;
|
||||
time_t end_time;
|
||||
double live_position;
|
||||
|
||||
if (!rect || !selected_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
live_position = channel_live_position_precise(selected_channel, app_start_ticks, now_ticks);
|
||||
start_time = now_wall - (time_t) live_position;
|
||||
end_time = start_time + (time_t) selected_channel->duration_seconds;
|
||||
format_time_compact(time_range, sizeof(time_range), start_time);
|
||||
format_time_compact(end_text, sizeof(end_text), end_time);
|
||||
strncat(time_range, " - ", sizeof(time_range) - strlen(time_range) - 1);
|
||||
strncat(time_range, end_text, sizeof(time_range) - strlen(time_range) - 1);
|
||||
snprintf(description,
|
||||
sizeof(description),
|
||||
"Channel %d presents %s. Source: %s.",
|
||||
selected_channel->number,
|
||||
selected_channel->program_title,
|
||||
selected_channel->file_name);
|
||||
|
||||
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, selected_channel->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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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_GRID_LINE);
|
||||
SDL_RenderDrawLine(renderer, grid_rect->x, y, grid_rect->x + grid_rect->w, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,33 +369,28 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
Uint64 now_ticks,
|
||||
time_t now_wall) {
|
||||
SDL_Rect full = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
SDL_Rect header_card = {0, 0, 390, 168};
|
||||
SDL_Rect preview = {820, 0, 460, 210};
|
||||
SDL_Rect header_row = {0, 210, WINDOW_WIDTH, 42};
|
||||
SDL_Rect grid = {0, 252, WINDOW_WIDTH, WINDOW_HEIGHT - 306};
|
||||
SDL_Rect info_panel = {0, 0, GUIDE_INFO_WIDTH, GUIDE_INFO_HEIGHT};
|
||||
SDL_Rect preview = {WINDOW_WIDTH - GUIDE_PREVIEW_WIDTH, 0, GUIDE_PREVIEW_WIDTH, GUIDE_PREVIEW_HEIGHT};
|
||||
SDL_Rect status_bar = {GUIDE_INFO_WIDTH, 0, WINDOW_WIDTH - GUIDE_INFO_WIDTH, GUIDE_STATUS_HEIGHT};
|
||||
SDL_Rect header_row = {0, GUIDE_GRID_TOP - GUIDE_STATUS_HEIGHT, WINDOW_WIDTH, GUIDE_STATUS_HEIGHT};
|
||||
SDL_Rect grid = {0, GUIDE_GRID_TOP, WINDOW_WIDTH, WINDOW_HEIGHT - GUIDE_GRID_TOP - GUIDE_FOOTER_HEIGHT};
|
||||
int row_height = grid.h / GUIDE_VISIBLE_ROWS;
|
||||
int sidebar_width = 240;
|
||||
int timeline_x = sidebar_width + 8;
|
||||
int timeline_w = WINDOW_WIDTH - timeline_x - 12;
|
||||
int timeline_w = WINDOW_WIDTH - GUIDE_X_START - 20;
|
||||
int start_index = active_channel - 2;
|
||||
char detail[256];
|
||||
|
||||
fill_rect(renderer, &full, COLOR_NAVY_DARK);
|
||||
fill_rect(renderer, &header_card, COLOR_PALE_BLUE);
|
||||
fill_rect(renderer, &preview, COLOR_BLACK);
|
||||
draw_video(renderer, video_texture, texture_width, texture_height, preview);
|
||||
fill_rect(renderer, &header_row, COLOR_SLATE);
|
||||
const Channel *selected_channel = NULL;
|
||||
double pixels_per_minute = timeline_w / 90.0;
|
||||
|
||||
if (channels && channels->count > 0 && active_channel >= 0 && active_channel < channels->count) {
|
||||
const Channel *current = &channels->items[active_channel];
|
||||
snprintf(detail, sizeof(detail), "%.0f min - %s", current->duration_seconds / 60.0, current->file_name);
|
||||
fill_rect(renderer, &(SDL_Rect){0, 0, 390, 38}, COLOR_HIGHLIGHT_YELLOW);
|
||||
draw_cached_text(renderer, &cache->channels[active_channel].name_medium, 26, 52);
|
||||
draw_cached_text(renderer, &cache->channels[active_channel].program_medium_dark, 20, 92);
|
||||
draw_cached_text(renderer, &cache->channels[active_channel].detail_small_dark, 20, 124);
|
||||
draw_cached_text(renderer, &cache->preview_badge, preview.x + preview.w - 126, preview.y + preview.h - 34);
|
||||
selected_channel = &channels->items[active_channel];
|
||||
}
|
||||
|
||||
fill_vertical_gradient(renderer, &full, 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);
|
||||
draw_video(renderer, video_texture, texture_width, texture_height, preview);
|
||||
draw_status_bar(renderer, fonts->medium, selected_channel, &status_bar, now_wall);
|
||||
|
||||
if (cache->timeline_label_slot != now_wall / 60) {
|
||||
char label[32];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
|
|
@ -226,6 +401,7 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
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);
|
||||
|
||||
if (start_index < 0) {
|
||||
start_index = 0;
|
||||
|
|
@ -237,15 +413,15 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
for (int row = 0; row < GUIDE_VISIBLE_ROWS; ++row) {
|
||||
int channel_index = start_index + row;
|
||||
SDL_Rect row_rect = {0, grid.y + row * row_height, WINDOW_WIDTH, row_height};
|
||||
SDL_Rect sidebar = {0, row_rect.y, sidebar_width, row_height};
|
||||
SDL_Rect timeline_rect = {timeline_x, row_rect.y + 6, timeline_w, row_height - 12};
|
||||
SDL_Rect sidebar = {0, row_rect.y, GUIDE_SIDEBAR_WIDTH, row_height};
|
||||
SDL_Rect timeline_rect = {GUIDE_X_START, row_rect.y + 6, timeline_w, row_height - 12};
|
||||
SDL_Rect clip = timeline_rect;
|
||||
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_DEEP_BLUE : COLOR_NAVY_DARK);
|
||||
fill_rect(renderer, &sidebar, is_selected ? COLOR_DEEP_BLUE : COLOR_SLATE);
|
||||
set_draw_color(renderer, COLOR_PALE_BLUE);
|
||||
SDL_RenderDrawLine(renderer, row_rect.x, row_rect.y, row_rect.x + row_rect.w, row_rect.y);
|
||||
fill_rect(renderer, &row_rect, is_selected ? COLOR_SELECTED_ROW : COLOR_UNSELECTED_ROW);
|
||||
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);
|
||||
|
||||
if (!channels || channel_index >= channels->count) {
|
||||
continue;
|
||||
|
|
@ -254,29 +430,43 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
{
|
||||
const Channel *channel = &channels->items[channel_index];
|
||||
double live_position = channel_live_position_precise(channel, app_start_ticks, now_ticks);
|
||||
double pixels_per_second = timeline_w / TIMELINE_VISIBLE_SECONDS;
|
||||
int block_x = timeline_x - (int) (live_position * pixels_per_second);
|
||||
int block_w = (int) (channel->duration_seconds * pixels_per_second);
|
||||
time_t guide_view_start_time = now_wall - (30 * 60);
|
||||
time_t program_start_time = now_wall - (time_t) live_position;
|
||||
int block_x = GUIDE_X_START + (int) (((double) (program_start_time - guide_view_start_time)) / 60.0 * pixels_per_minute);
|
||||
int block_w = (int) ((channel->duration_seconds / 60.0) * pixels_per_minute);
|
||||
SDL_Rect block = {block_x, timeline_rect.y + 4, SDL_max(block_w, 48), timeline_rect.h - 8};
|
||||
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);
|
||||
draw_cached_text(renderer, &cache->channels[channel_index].file_small, 20, row_rect.y + 38);
|
||||
|
||||
fill_rect(renderer, &timeline_rect, COLOR_NAVY_DARK);
|
||||
SDL_RenderSetClipRect(renderer, &clip);
|
||||
fill_rect(renderer, &block, is_selected ? COLOR_HIGHLIGHT_YELLOW : COLOR_DEEP_BLUE);
|
||||
stroke_rect(renderer, &block, COLOR_PALE_BLUE);
|
||||
draw_cached_text(renderer,
|
||||
is_selected ? &cache->channels[channel_index].program_medium_dark
|
||||
: &cache->channels[channel_index].program_small_light,
|
||||
block.x + 10,
|
||||
block.y + 10);
|
||||
fill_rect(renderer, &block, is_selected ? COLOR_BLOCK_SELECTED : COLOR_BLOCK_UNSELECTED);
|
||||
stroke_rect(renderer, &block, is_selected ? COLOR_SELECTION_EDGE : COLOR_PALE_BLUE);
|
||||
fit_text_with_ellipsis(is_selected ? fonts->medium : fonts->small,
|
||||
channel->program_title,
|
||||
title_rect.w,
|
||||
title,
|
||||
sizeof(title));
|
||||
draw_text_clipped(renderer,
|
||||
is_selected ? fonts->medium : fonts->small,
|
||||
title,
|
||||
&title_rect,
|
||||
title_rect.x,
|
||||
title_rect.y,
|
||||
is_selected ? COLOR_TEXT_DARK : COLOR_TEXT_LIGHT);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
stroke_rect(renderer, &timeline_rect, COLOR_SLATE);
|
||||
}
|
||||
}
|
||||
|
||||
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_footer_legend(renderer, cache, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
}
|
||||
|
||||
|
|
@ -299,14 +489,12 @@ int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts,
|
|||
if (text_texture_init(&cache->no_media_title, renderer, fonts->large, "Passport-C Media Player", COLOR_TEXT_LIGHT) != 0 ||
|
||||
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->timeline_day, renderer, fonts->medium, "FRI 6/30", COLOR_TEXT_DARK) != 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_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_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->preview_badge, renderer, fonts->medium, "Nick * 56", COLOR_TEXT_LIGHT) != 0) {
|
||||
text_texture_init(&cache->footer_title, renderer, fonts->medium, "Title", COLOR_TEXT_DARK) != 0) {
|
||||
ui_cache_destroy(cache);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -350,14 +538,12 @@ void ui_cache_destroy(UiCache *cache) {
|
|||
text_texture_destroy(&cache->no_media_title);
|
||||
text_texture_destroy(&cache->no_media_body);
|
||||
text_texture_destroy(&cache->no_media_hint);
|
||||
text_texture_destroy(&cache->timeline_day);
|
||||
text_texture_destroy(&cache->footer_a);
|
||||
text_texture_destroy(&cache->footer_time);
|
||||
text_texture_destroy(&cache->footer_b);
|
||||
text_texture_destroy(&cache->footer_theme);
|
||||
text_texture_destroy(&cache->footer_c);
|
||||
text_texture_destroy(&cache->footer_title);
|
||||
text_texture_destroy(&cache->preview_badge);
|
||||
|
||||
if (cache->timeline_labels) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
|
|
|
|||
2
src/ui.h
2
src/ui.h
|
|
@ -34,14 +34,12 @@ typedef struct UiCache {
|
|||
UiTextTexture no_media_title;
|
||||
UiTextTexture no_media_body;
|
||||
UiTextTexture no_media_hint;
|
||||
UiTextTexture timeline_day;
|
||||
UiTextTexture footer_a;
|
||||
UiTextTexture footer_time;
|
||||
UiTextTexture footer_b;
|
||||
UiTextTexture footer_theme;
|
||||
UiTextTexture footer_c;
|
||||
UiTextTexture footer_title;
|
||||
UiTextTexture preview_badge;
|
||||
UiTextTexture *timeline_labels;
|
||||
time_t timeline_label_slot;
|
||||
UiChannelCache *channels;
|
||||
|
|
|
|||
BIN
src/ui.o
BIN
src/ui.o
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue