#include #include "../../cmc.h" #include "list.h" void cmc_list_pane_init(struct cmc_list_pane *lp, struct cmc_ui *ui) { al_array_init(lp->tabs); lp->selected = -1; cmc_now_playing_init(&lp->np); lp->ui = ui; } bool cmc_list_pane_layout(struct cmc_list_pane *lp, struct ncplane *parent) { if (lp->n) ncplane_destroy(lp->n); struct ncplane_options nopts = { 0 }; u32 height = ncplane_dim_y(parent); nopts.rows = height; nopts.cols = ncplane_dim_x(parent); lp->n = ncplane_create(parent, &nopts); lp->page_length = height - 9; cmc_now_playing_layout(&lp->np, lp->n, lp->page_length); return true; } void cmc_list_pane_add_list(struct cmc_list_pane *lp, struct cmc_list *list) { struct cmc_list_tab tab = { 0 }; tab.list = list; tab.selected = list->current; al_array_push(lp->tabs, tab); if (lp->selected == -1) { lp->selected = lp->tabs.count - 1; } } bool cmc_list_pane_handle_input(struct cmc_list_pane *lp, struct ncinput *input) { if (lp->selected == -1) return false; struct cmc_list_tab *tab = &al_array_at(lp->tabs, lp->selected); s32 count = (s32)tab->list->entries.count; bool leader = tab->leader_pressed; if (cmc_ui_consider_input(input, false)) { tab->leader_pressed = false; } switch (input->id) { case 'g': CONSIDER_INPUT(); if (leader) { if (tab->move.active) { if (tab->move.offset != -tab->move.selected) { tab->move.offset = -tab->move.selected; return true; } } else if (tab->selected != 0) { tab->selected = 0; return true; } } else { tab->leader_pressed = true; } break; case 'G': CONSIDER_INPUT(); if (tab->move.active) { if (tab->move.offset != count - 1 - tab->move.selected) { tab->move.offset = count - 1 - tab->move.selected; return true; } } else if (tab->selected != count - 1) { tab->selected = count - 1; return true; } break; case 'f': CONSIDER_INPUT_REPEAT(); if (tab->move.active) { if (tab->selected + tab->move.offset < count - lp->page_length) { tab->move.offset += lp->page_length; return true; } else if (tab->move.offset != count - 1 - tab->move.selected) { tab->move.offset = count - 1 - tab->move.selected; return true; } } else { if (tab->selected < count - lp->page_length) { tab->selected += lp->page_length; return true; } else if (tab->selected != count - 1) { tab->selected = count - 1; return true; } } break; case 'b': CONSIDER_INPUT_REPEAT(); if (tab->move.active) { if (tab->selected + tab->move.offset > lp->page_length) { tab->move.offset -= lp->page_length; return true; } else if (tab->move.offset != -tab->selected) { tab->move.offset = -tab->selected; return true; } } else { if (tab->selected > lp->page_length) { tab->selected -= lp->page_length; return true; } else if (tab->selected != 0) { tab->selected = 0; return true; } } break; case 'j': CONSIDER_INPUT_REPEAT(); if (tab->move.active) { if (tab->selected + tab->move.offset < count - 1) { tab->move.offset++; return true; } } else { if (tab->selected < count - 1) { tab->selected++; return true; } } break; case 'k': CONSIDER_INPUT_REPEAT(); if (tab->move.active) { if (tab->selected + tab->move.offset > 0) { tab->move.offset--; return true; } } else { if (tab->selected > 0) { tab->selected--; return true; } } break; case 'i': CONSIDER_INPUT(); if (!tab->move.active) { tab->move.active = true; tab->move.selected = tab->selected; tab->move.offset = 0; return true; } break; case NCKEY_ESC: CONSIDER_INPUT(); if (tab->move.active) { tab->move.active = false; return true; } break; case NCKEY_RETURN: CONSIDER_INPUT(); if (tab->move.active) { tab->move.active = false; return true; } else if (tab->selected != tab->list->current) { camu_client_skipto(&lp->ui->c->client, &tab->list->name, tab->selected); } break; case NCKEY_BUTTON1: /* CONSIDER_INPUT(); if (input->x < 0 || input->y < 0) return false; u32 x = (u32)input->x; u32 y = (u32)input->y; ui->last_mouse_x = x; ui->last_mouse_y = y; u64 now = nn_get_timestamp(); u64 last = ui->last_mouse_ts; if (last != (u64)-1 && now - last < 100000) { return false; } ui->last_mouse_ts = now; u32 width = ncplane_dim_x(ui->lp.n); u32 height = ncplane_dim_y(ui->lp.n); if (x >= 2 && x <= width && y > height - 3) { // @TODO: Make this defined, more to nowplaying. struct cmc_list_entry *entry = al_array_at(tab->list->entries, tab->list->current); u64 pos = ((x - 2) / (f64)(width - 2)) * entry->duration; camu_client_seek(&ui->c->client, &tab->list->name, entry->id, pos); } */ break; } return false; } static struct cmc_list_entry *tab_current_entry(struct cmc_list_tab *tab) { if (tab->list->current >= 0) { return al_array_at(tab->list->entries, tab->list->current); } return NULL; } bool cmc_list_pane_tick(struct cmc_list_pane *lp) { bool tick = false; if (lp->selected != -1) { struct cmc_list_tab *tab = &al_array_at(lp->tabs, lp->selected); if (tab->list->meta_changed) { tab->list->meta_changed = false; tick = true; } tick |= cmc_now_playing_tick(&lp->np, tab_current_entry(tab)); } return tick; } void cmc_list_pane_clear(struct cmc_list_pane *lp) { ncplane_erase(lp->n); cmc_now_playing_clear(&lp->np); } static void render_list_entries(struct cmc_list_pane *lp, struct cmc_list_tab *tab, s32 max_height) { struct cmc_list *list = tab->list; struct ncplane *n = lp->n; s32 tracked = tab->move.active ? tab->move.selected + tab->move.offset : tab->selected; s32 count = (s32)list->entries.count; s32 midpoint = max_height / 2; s32 rounded = (max_height + 1) / 2; s32 top, end; if (tracked < midpoint) { top = 0; end = MIN(top + max_height, count); } else if (tracked + rounded >= count) { top = MAX(count - max_height, 0); end = count; } else { top = tracked - midpoint; end = tracked + rounded; } s32 index; struct cmc_list_entry *entry; for (s32 i = top; i < end; i++) { index = i; if (tab->move.active) { if (index == tracked) { index = tab->move.selected; } else { if (index > tracked) index--; if (index >= tab->move.selected) index++; } } entry = al_array_at(list->entries, index); bool on_current = list->current >= 0 && index == list->current; bool styled = i == tracked; if (styled) { ncplane_set_styles(n, NCSTYLE_BOLD); ncplane_set_fg_palindex(n, 4); } s32 y = i - top; char *c_str = al_str_to_c_str(&entry->brief); if (tab->move.active && i == tracked) { ncplane_putstr_yx(n, y, 0, c_str); } else if (on_current) { ncplane_putchar_yx(n, y, 1, '>'); ncplane_putstr_yx(n, y, 3, c_str); } else { ncplane_putstr_yx(n, y, 1, c_str); } al_free(c_str); if (styled) { ncplane_set_styles(n, NCSTYLE_NONE); ncplane_set_fg_default(n); } } } void cmc_list_pane_render(struct cmc_list_pane *lp) { ncplane_erase(lp->n); cmc_now_playing_erase(&lp->np); if (lp->selected == -1) return; struct cmc_list_tab *tab = &al_array_at(lp->tabs, lp->selected); render_list_entries(lp, tab, lp->page_length); cmc_now_playing_render(&lp->np, tab_current_entry(tab)); }