From 00d22febd2c73f5ccb058ca2211294b1a1d99e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Wed, 27 Apr 2022 16:06:42 +0200 Subject: Press left/right to select next/previous unwatched episode. --- c/defs.h | 1 + c/episodelistview.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pl/track_episodes.pl | 18 +++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/c/defs.h b/c/defs.h index 14b7626..1e463dd 100644 --- a/c/defs.h +++ b/c/defs.h @@ -21,6 +21,7 @@ LRESULT ElvHandleNotify(LPARAM); void ElvRedraw(void); void ElvSetTop(int); void ElvSelectRecent(void); +void ElvSelectUnwatched(int); void ElvUpdate(void); void ElvUpdateItem(LPLVITEM); diff --git a/c/episodelistview.c b/c/episodelistview.c index 08bd0db..ad32b81 100644 --- a/c/episodelistview.c +++ b/c/episodelistview.c @@ -80,6 +80,20 @@ ElvHandleNotify(LPARAM lParam) s: ElvDoSort(); break; } + case LVN_KEYDOWN: /* Navigate episodes by keyboard. */ + { + LPNMLVKEYDOWN lpNmLvKd; + lpNmLvKd = (LPNMLVKEYDOWN)lParam; + switch (lpNmLvKd->wVKey) { + case VK_LEFT: + ElvSelectUnwatched(-1); + break; + case VK_RIGHT: + ElvSelectUnwatched(1); + break; + } + break; + } case NM_CUSTOMDRAW: /* Make unwatched episodes bold. */ { LPNMLVCUSTOMDRAW lpLvCd; @@ -196,6 +210,51 @@ s: ListView_SetItemState(HElv, -1, LVIF_STATE, LVIS_SELECTED); DlvShowEpisode(iEpisode); } +/* Select next/previous unwatched episode. */ +void +ElvSelectUnwatched(int iDir) +{ + int bShift, i, iEpNew, iItemNew; + LVFINDINFO lvfi; + LVITEM lviFocus; + term_t t; + + /* Get focused episode. */ + lviFocus.mask = LVIF_PARAM; + lviFocus.iItem = -1; + while ((lviFocus.iItem = ListView_GetNextItem( + HElv, lviFocus.iItem, LVNI_FOCUSED)) != -1) { + if (!ListView_GetItem(HElv, &lviFocus)) continue; + } + + i = 0; + lvfi.flags = LVFI_PARAM; + lvfi.lParam = lviFocus.lParam; + bShift = GetAsyncKeyState(VK_SHIFT); + + do { + t = T(2); + PI(t,lvfi.lParam) return; + P("track_episodes",iDir > 0? "next_unwatched": "previous_unwatched",2,t) + return; + GI(t+1,&iEpNew) return; + + lvfi.lParam = iEpNew; + if ((iItemNew = ListView_FindItem(HElv, -1, &lvfi)) != -1) { + if (!bShift) { + ListView_SetItemState(HElv, -1, + LVIF_STATE, LVIS_SELECTED); + } + ListView_SetItemState(HElv, iItemNew, + LVIS_SELECTED|LVIS_FOCUSED, + LVIS_SELECTED|LVIS_FOCUSED); + ElvRedraw(); + ListView_EnsureVisible(HElv, iItemNew, TRUE); + return; + } + } while (i++ < 1000); +} + /* Sort list view items, iSort being the 1-based index of the column * to sort by. If iSort is negative, the order is descending. */ int CALLBACK @@ -288,6 +347,7 @@ ElvUpdate() /* Save focus. */ iEpFocus = 0; + lvi.iItem = -1; while ((lvi.iItem = ListView_GetNextItem( HElv, lvi.iItem, LVNI_FOCUSED)) != -1) { if (!ListView_GetItem(HElv, &lvi)) continue; diff --git a/pl/track_episodes.pl b/pl/track_episodes.pl index f18e85c..1973a75 100644 --- a/pl/track_episodes.pl +++ b/pl/track_episodes.pl @@ -2,7 +2,9 @@ toggle_episode/1, forget_episode/1, most_recently_watched/1, - watched/1]). + watched/1, + next_unwatched/2, + previous_unwatched/2]). :- use_module(library(dcg/basics)). :- use_module(library(registry)). @@ -94,3 +96,17 @@ most_recently_watched(Ep) :- watched(Ep) :- episode_watched(Ep, true). + +next_unwatched(Ep0, Ep) :- + Ep1 is Ep0 + 1, + ( \+ watched(Ep1) + -> Ep = Ep1 + ; next_unwatched(Ep1, Ep) + ). + +previous_unwatched(Ep0, Ep) :- + Ep1 is Ep0 - 1, + ( \+ watched(Ep1) + -> Ep = Ep1 + ; previous_unwatched(Ep1, Ep) + ). -- cgit v1.2.3