#include #include #include #include #include "resource.h" #include "defs.h" extern HFONT g_GUIFontBold; HWND gElv_hWnd; WNDPROC g_PrevElvProc; int g_iSelectedItem = -1; /* Remembered after refresh. */ HWND ElvCreate(HWND hWnd) { HWND hListView; LVCOLUMN lvc; gElv_hWnd = hWnd; hListView = LvCreate(hWnd, (HMENU)IDC_EPISODELISTVIEW); lvc.mask = LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; lvc.iSubItem = 0; lvc.pszText = TEXT("#"); lvc.cx = 42; ListView_InsertColumn(hListView, 0, &lvc); lvc.iSubItem = 1; lvc.pszText = TEXT("Title"); lvc.cx = 500; ListView_InsertColumn(hListView, 1, &lvc); ElvUpdate(); ElvSelectRecent(); return hListView; } LRESULT ElvHandleNotify(LPARAM lParam) { NMLISTVIEW *pNmLv; pNmLv = (NMLISTVIEW *)lParam; switch (pNmLv->hdr.code) { case LVN_ITEMCHANGED: if ((pNmLv->uChanged & LVIF_STATE) && (pNmLv->uNewState & LVIS_FOCUSED)) { g_iSelectedItem = pNmLv->iItem; ElvUpdateName(pNmLv->iItem, pNmLv->lParam); DlvShowEpisode(pNmLv->lParam); } break; case NM_CUSTOMDRAW: { NMLVCUSTOMDRAW *pLvCd; pLvCd = (NMLVCUSTOMDRAW *)lParam; switch (pLvCd->nmcd.dwDrawStage) { case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: if (!Watched(pLvCd->nmcd.lItemlParam)) { SelectObject(pLvCd->nmcd.hdc, g_GUIFontBold); return CDRF_NEWFONT; } break; } break; } case NM_DBLCLK: { term_t t; t = PL_new_term_refs(1); if (!PL_put_integer(t+0, ElvItemEpisode(g_iSelectedItem))) break; PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate("open_episode", 1, "local_episodes"), t); break; } case NM_RCLICK: { DWORD dwPos; NMITEMACTIVATE *pNmItem; extern HMENU g_hPopupMenu; dwPos = GetMessagePos(); TrackPopupMenu(g_hPopupMenu, TPM_RIGHTBUTTON, LOWORD(dwPos), HIWORD(dwPos), 0, gElv_hWnd, NULL); break; } } return 0; } int ElvItemEpisode(int iItem) { HWND hListView; LVITEM lvi; hListView = GetDlgItem(gElv_hWnd, IDC_EPISODELISTVIEW); lvi.mask = LVIF_PARAM; lvi.iItem = iItem; lvi.iSubItem = 0; if (!ListView_GetItem(hListView, &lvi)) return -1; return lvi.lParam; } /* Select most recent episode. */ void ElvSelectRecent() { fid_t f; HWND hListView; int iEpisode, iItem; LVFINDINFO lvfi; term_t t; f = PL_open_foreign_frame(); /* Needed? */ t = PL_new_term_refs(1); if (!PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate("most_recently_watched", 1, "track_episodes"), t)) goto end; if (!PL_get_integer(t+0, &iEpisode)) goto end; hListView = GetDlgItem(gElv_hWnd, IDC_EPISODELISTVIEW); lvfi.flags = LVFI_PARAM; lvfi.lParam = iEpisode; iItem = ListView_FindItem(hListView, -1, &lvfi); if (iItem == -1) goto end; ListView_EnsureVisible(hListView, iItem, TRUE); ListView_SetItemState(hListView, iItem, LVIS_SELECTED, LVIS_SELECTED); g_iSelectedItem = iItem; ElvUpdateName(iItem, iEpisode); DlvShowEpisode(iEpisode); end: PL_discard_foreign_frame(f); } /* Update episode list. */ void ElvUpdate() { fid_t f; HWND hListView; int iTop; LVITEM lviEpisode, lviName; qid_t q; term_t t; hListView = GetDlgItem(gElv_hWnd, IDC_EPISODELISTVIEW); SendMessage(hListView, WM_SETREDRAW, FALSE, 0); iTop = ListView_GetTopIndex(hListView); ListView_DeleteAllItems(hListView); lviEpisode.mask = LVIF_TEXT|LVIF_PARAM; lviName.mask = LVIF_TEXT; f = PL_open_foreign_frame(); t = PL_new_term_refs(2); PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate("update_tracked_episodes", 0, "track_episodes"), t); q = PL_open_query(NULL, PL_Q_NORMAL, PL_predicate("episode_file", 2, "local_episodes"), t); for (int i = 0; PL_next_solution(q); i++) { char *szName; int cb, iEpisode, iItem, r; TCHAR *tszEpisode, *tszName; term_t t2; /* Lookup episode name. */ if (!PL_get_integer(t+0, &iEpisode)) goto close; t2 = PL_new_term_refs(3); if(!PL_put_integer(t2+0, iEpisode)) continue; r = PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate("lookup_episode_local", 3, "episode_data"), t2); /* Format episode, name strings. */ tszName = NULL; if (r && PL_get_atom_chars(t2+1, &szName)) { tszName = TSZFromSZ(szName, CP_UTF8); if (!tszName) continue; } cb = 100; tszEpisode = malloc(cb*sizeof(TCHAR)); if (!tszEpisode) continue; _stprintf_s(tszEpisode, cb, TEXT("%d"), iEpisode); /* Insert item. */ lviEpisode.iItem = i; lviEpisode.iSubItem = 0; lviEpisode.pszText = tszEpisode; lviEpisode.lParam = iEpisode; ListView_InsertItem(hListView, &lviEpisode); if (tszName) { lviName.iItem = i; lviName.iSubItem = 1; lviName.pszText = tszName; ListView_SetItem(hListView, &lviName); } free(tszName); free(tszEpisode); } if (g_iSelectedItem != -1) { int iLast; iLast = ListView_GetItemCount(hListView)-1; ListView_EnsureVisible(hListView, iLast, TRUE); ListView_EnsureVisible(hListView, iTop, TRUE); ListView_SetItemState(hListView, g_iSelectedItem, LVIS_SELECTED, LVIS_SELECTED); } close: SendMessage(hListView, WM_SETREDRAW, TRUE, 0); PL_cut_query(q); PL_discard_foreign_frame(f); } /* Update episode name. */ void ElvUpdateName(int iItem, int iEpisode) { char *szName; HWND hListView; TCHAR *tszName; term_t t; t = PL_new_term_refs(3); if (!PL_put_integer(t+0, iEpisode)) return; PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate("lookup_episode", 3, "episode_data"), t); if (!PL_get_atom_chars(t+1, &szName)) return; tszName = TSZFromSZ(szName, CP_UTF8); if (!tszName) return; hListView = GetDlgItem(gElv_hWnd, IDC_EPISODELISTVIEW); ListView_SetItemText(hListView, iItem, 1, tszName); }