1 #pragma once
2 
3 #include "rapps.h"
4 #include "rosui.h"
5 #include "crichedit.h"
6 #include "asyncinet.h"
7 
8 #include <shlobj_undoc.h>
9 #include <shlguid_undoc.h>
10 
11 #include <atlbase.h>
12 #include <atlcom.h>
13 #include <atltypes.h>
14 #include <atlwin.h>
15 #include <wininet.h>
16 #include <shellutils.h>
17 #include <ui/rosctrls.h>
18 #include <gdiplus.h>
19 #include <math.h>
20 
21 extern HICON g_hDefaultPackageIcon;
22 
23 // default broken-image icon size
24 #define BROKENIMG_ICON_SIZE 96
25 
26 // the boundary of w/h ratio of scrnshot preview window
27 #define SCRNSHOT_MAX_ASPECT_RAT 2.5
28 
29 // padding between scrnshot preview and richedit (in pixel)
30 #define INFO_DISPLAY_PADDING 10
31 
32 // minimum width of richedit
33 #define RICHEDIT_MIN_WIDTH 160
34 
35 // padding between controls in toolbar
36 #define TOOLBAR_PADDING 6
37 
38 // user-defined window message
39 #define WM_RAPPS_DOWNLOAD_COMPLETE                                                                                     \
40     (WM_USER + 1) // notify download complete. wParam is error code, and lParam is a pointer to ScrnshotDownloadParam
41 #define WM_RAPPS_RESIZE_CHILDREN (WM_USER + 2) // ask parent window to resize children.
42 #define WM_RAPPSLIST_ASYNCICON (WM_APP + 0)
43 
44 enum SCRNSHOT_STATUS
45 {
46     SCRNSHOT_PREV_EMPTY,   // show nothing
47     SCRNSHOT_PREV_LOADING, // image is loading (most likely downloading)
48     SCRNSHOT_PREV_IMAGE,   // display image from a file
49     SCRNSHOT_PREV_FAILED   // image can not be shown (download failure or wrong image)
50 };
51 
52 #define TIMER_LOADING_ANIMATION 1 // Timer ID
53 
54 #define LOADING_ANIMATION_PERIOD 3 // Animation cycling period (in seconds)
55 #define LOADING_ANIMATION_FPS 18   // Animation Frame Per Second
56 
57 #define PI 3.1415927
58 
59 // retrieve the value using a mask
60 #define STATEIMAGETOINDEX(x) (((x)&LVIS_STATEIMAGEMASK) >> 12)
61 
62 // for listview with extend style LVS_EX_CHECKBOXES, State image 1 is the unchecked box, and state image 2 is the
63 // checked box. see this: https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles
64 #define STATEIMAGE_UNCHECKED 1
65 #define STATEIMAGE_CHECKED 2
66 
67 class CMainWindow;
68 
69 enum APPLICATION_VIEW_TYPE
70 {
71     AppViewTypeAvailableApps,
72     AppViewTypeInstalledApps
73 };
74 
75 typedef struct __ScrnshotDownloadParam
76 {
77     LONGLONG ID;
78     HANDLE hFile;
79     HWND hwndNotify;
80     CStringW DownloadFileName;
81 } ScrnshotDownloadParam;
82 
83 class CAppRichEdit : public CUiWindow<CRichEdit>
84 {
85   public:
86     VOID
87     LoadAndInsertText(UINT uStringID, const CStringW &szText, DWORD TextFlags);
88     VOID
89     LoadAndInsertText(UINT uStringID, DWORD StringFlags);
90     VOID
91     InsertTextWithString(UINT StringID, const CStringW &Text, DWORD TextFlags);
92 };
93 
94 int
95 ScrnshotDownloadCallback(pASYNCINET AsyncInet, ASYNC_EVENT Event, WPARAM wParam, LPARAM lParam, VOID *Extension);
96 
97 class CAppScrnshotPreview : public CWindowImpl<CAppScrnshotPreview>
98 {
99   private:
100     CStringW m_BasePath;
101     SCRNSHOT_STATUS ScrnshotPrevStauts = SCRNSHOT_PREV_EMPTY;
102     Gdiplus::Image *pImage = NULL;
103     HICON hBrokenImgIcon = NULL;
104     BOOL bLoadingTimerOn = FALSE;
105     int LoadingAnimationFrame = 0;
106     int BrokenImgSize = BROKENIMG_ICON_SIZE;
107     pASYNCINET AsyncInet = NULL;
108     LONGLONG ContentID = 0; // used to determine whether image has been switched when download complete. Increase by 1
109                             // each time the content of this window changed
110     CStringW TempImagePath; // currently displayed temp file
111 
112     BOOL
113     ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
114 
115     VOID
116     DisplayLoading();
117     VOID
118     DisplayFailed();
119     BOOL
120     DisplayFile(LPCWSTR lpszFileName);
121     VOID
122     SetStatus(SCRNSHOT_STATUS Status);
123 
124     VOID
125     PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd);
126     float
127     GetLoadingDotWidth(int width, int height);
128     float
129     GetFrameDotShift(int Frame, int width, int height);
130 
131   public:
132     static ATL::CWndClassInfo &
133     GetWndClassInfo();
134 
135     HWND
136     Create(HWND hParent);
137     VOID
138     PreviousDisplayCleanup();
139     VOID
140     DisplayEmpty();
141     BOOL
142     DisplayImage(LPCWSTR lpszLocation);
143 
144     // calculate requested window width by given height
145     int
146     GetRequestedWidth(int Height);
147 
148     CAppScrnshotPreview(const CStringW &BasePath);
149     ~CAppScrnshotPreview();
150 };
151 
152 class CAppInfoDisplay : public CUiWindow<CWindowImpl<CAppInfoDisplay>>
153 {
154     LPWSTR pLink = NULL;
155 
156   private:
157     BOOL
158     ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
159     VOID
160     OnLink(ENLINK *Link);
161 
162     VOID
163     ResizeChildren();
164     VOID
165     ResizeChildren(int Width, int Height);
166 
167   public:
168     CAppRichEdit *RichEdit = NULL;
169     CAppScrnshotPreview *ScrnshotPrev = NULL;
170 
171     static ATL::CWndClassInfo &
172     GetWndClassInfo();
173 
174     HWND
175     Create(HWND hwndParent);
176 
177     VOID
178     ShowAppInfo(CAppInfo *Info);
179     void
180     SetWelcomeText(bool bAppwiz);
181     VOID
182     OnCommand(WPARAM wParam, LPARAM lParam);
183 
184     ~CAppInfoDisplay();
185 };
186 
187 class CAppsListView : public CUiWindow<CWindowImpl<CAppsListView, CListView>>
188 {
189     struct SortContext
190     {
191         CAppsListView *lvw;
192         INT iSubItem;
193     };
194 
195     BOOL bIsAscending = TRUE;
196     bool bHasCheckboxes = false;
197 
198     INT ItemCount = 0;
199     INT CheckedItemCount = 0;
200     INT ColumnCount = 0;
201 
202     INT nLastHeaderID = -1;
203 
204     APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeAvailableApps;
205 
206     HIMAGELIST m_hImageListView = NULL;
207     CStringW m_Watermark;
208 
209     BEGIN_MSG_MAP(CAppsListView)
210     MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
211     MESSAGE_HANDLER(WM_RAPPSLIST_ASYNCICON, OnAsyncIcon)
212     END_MSG_MAP()
213 
214     LRESULT
215     OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
216     LRESULT
217     OnAsyncIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
218 
219   public:
220     CAppsListView();
221     ~CAppsListView();
222 
223     VOID
224     SetWatermark(const CStringW &Text);
225 
226     void
227     ShowCheckboxes(bool bShow);
228 
229     VOID
230     ColumnClick(LPNMLISTVIEW pnmv);
231 
232     BOOL
233     AddColumn(INT Index, CStringW &Text, INT Width, INT Format);
234     void
235     DeleteColumn(INT Index);
236 
237     INT
238     AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam);
239 
240     HIMAGELIST
241     GetImageList(int iImageList);
242 
243     static INT CALLBACK
244     s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
245 
246     INT
247     CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem);
248 
249     HWND
250     Create(HWND hwndParent);
251 
252     BOOL
253     GetCheckState(INT item);
254     VOID
255     SetCheckState(INT item, BOOL fCheck);
256     VOID
257     CheckAll();
258 
259     PVOID
260     GetFocusedItemData();
261 
262     BOOL
263     SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
264     BOOL
265     SetViewMode(DWORD ViewMode);
266 
267     BOOL
268     AddApplication(CAppInfo *AppInfo, BOOL InitialCheckState);
269 
270     // this function is called when parent window receiving an notification about checkstate changing
271     VOID
272     ItemCheckStateNotify(int iItem, BOOL bCheck);
273 };
274 
275 class CMainToolbar : public CUiWindow<CToolbar<>>
276 {
277     const INT m_iToolbarHeight;
278     DWORD m_dButtonsWidthMax;
279 
280     VOID
281     AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex);
282 
283     HIMAGELIST
284     InitImageList();
285 
286   public:
287     CMainToolbar();
288 
289     VOID
290     OnGetDispInfo(LPTOOLTIPTEXT lpttt);
291 
292     HWND
293     Create(HWND hwndParent);
294 
295     void
296     ShowButtonCaption(bool bShow);
297 
298     void
299     UpdateMaxButtonsWidth();
300 
301     DWORD
302     GetMaxButtonsWidth() const;
303 };
304 
305 class CSearchBar : public CWindow
306 {
307   public:
308     const INT m_Width;
309     const INT m_Height;
310 
311     CSearchBar();
312 
313     VOID
314     SetText(LPCWSTR lpszText);
315 
316     HWND
317     Create(HWND hwndParent);
318 };
319 
320 class CComboBox : public CWindow
321 {
322     // ID refers to different types of view
323     enum
324     {
325         m_AppDisplayTypeDetails,
326         m_AppDisplayTypeList,
327         m_AppDisplayTypeTile
328     };
329 
330     // string ID for different. this should correspond with the enum above.
331     const UINT m_TypeStringID[3] = {IDS_APP_DISPLAY_DETAILS, IDS_APP_DISPLAY_LIST, IDS_APP_DISPLAY_TILE};
332 
333     const int m_DefaultSelectType = m_AppDisplayTypeDetails;
334 
335   public:
336     int m_Width;
337     int m_Height;
338 
339     CComboBox();
340 
341     HWND
342     Create(HWND hwndParent);
343 };
344 
345 class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>>
346 {
347   private:
348     CUiPanel *m_Panel = NULL;
349     CMainToolbar *m_Toolbar = NULL;
350     CUiWindow<CComboBox> *m_ComboBox = NULL;
351     CUiWindow<CSearchBar> *m_SearchBar = NULL;
352     CAppsListView *m_ListView = NULL;
353     CAppInfoDisplay *m_AppsInfo = NULL;
354     CUiSplitPanel *m_HSplitter = NULL;
355     CMainWindow *m_MainWindow = NULL;
356     APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeAvailableApps;
357 
358     BOOL
359     ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
360 
361     BOOL
362     CreateToolbar();
363     BOOL
364     CreateSearchBar();
365     BOOL
366     CreateComboBox();
367     BOOL
368     CreateHSplitter();
369     BOOL
370     CreateListView();
371     BOOL
372     CreateAppInfoDisplay();
373 
374     VOID
375     OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
376     VOID
377     OnCommand(WPARAM wParam, LPARAM lParam);
378 
379   public:
380     CApplicationView(CMainWindow *MainWindow);
381     ~CApplicationView();
382 
383     static ATL::CWndClassInfo &
384     GetWndClassInfo();
385 
386     HWND
387     Create(HWND hwndParent);
388     void
389     SetRedraw(BOOL bRedraw);
390     void
391     SetFocusOnSearchBar();
392     BOOL
393     SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
394 
395     BOOL
396     AddApplication(CAppInfo *InstAppInfo, BOOL InitialCheckState);
397     VOID
398     SetWatermark(const CStringW &Text);
399 
400     void
401     CheckAll();
402     PVOID
403     GetFocusedItemData();
404     int
405     GetItemCount();
406     VOID
407     AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList);
408 
409     struct RESTORELISTSELECTION {
410         LVITEMW Item;
411         WCHAR Name[MAX_PATH];
412     };
413     VOID
414     GetRestoreListSelectionData(RESTORELISTSELECTION &Restore);
415     VOID
416     RestoreListSelection(const RESTORELISTSELECTION &Restore);
417 
418     // this function is called when a item of listview get focus.
419     // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
420     VOID
421     ItemGetFocus(LPVOID CallbackParam);
422 
423     // this function is called when a item of listview is checked/unchecked
424     // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
425     VOID
426     ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam);
427 };
428