aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-04-27 16:06:42 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-04-27 16:06:42 +0200
commit00d22febd2c73f5ccb058ca2211294b1a1d99e9c (patch)
tree02612dd2181b5e1abafc0da663f1141dfb05adff
parentdd855b6091c1eb9835cd2466ed2e225dd4f850a4 (diff)
downloadEpisodeBrowser-00d22febd2c73f5ccb058ca2211294b1a1d99e9c.tar.gz
Press left/right to select next/previous unwatched episode.
-rw-r--r--c/defs.h1
-rw-r--r--c/episodelistview.c60
-rw-r--r--pl/track_episodes.pl18
3 files changed, 78 insertions, 1 deletions
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)
+ ).