[RAPPS_NEW]
[reactos.git] / reactos / base / applications / rapps_new / gui.cpp
1 /* PROJECT: ReactOS CE Applications Manager
2 * LICENSE: GPL - See COPYING in the top level directory
3 * AUTHORS: David Quintana <gigaherz@gmail.com>
4 */
5
6 #include "rapps.h"
7
8 #include <shlobj_undoc.h>
9 #include <shlguid_undoc.h>
10
11 #include <atlbase.h>
12 #include <atlcom.h>
13 #include <atlwin.h>
14 #include <wininet.h>
15 #include <shellutils.h>
16
17 #include <rosctrls.h>
18
19 #include "rosui.h"
20
21 PWSTR pLink = NULL;
22
23 HWND hListView = NULL;
24
25 VOID UpdateApplicationsList(INT EnumType);
26 VOID MainWndOnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
27 BOOL IsSelectedNodeInstalled(void);
28 VOID FreeInstalledAppList(VOID);
29
30 class CUiRichEdit :
31 public CUiWindow< CWindowImplBaseT<CWindow> >
32 {
33 BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
34 {
35 theResult = 0;
36 return FALSE;
37 }
38
39 public:
40 VOID SetRangeFormatting(LONG Start, LONG End, DWORD dwEffects)
41 {
42 CHARFORMAT2 CharFormat;
43
44 SendMessageW(EM_SETSEL, Start, End);
45
46 ZeroMemory(&CharFormat, sizeof(CHARFORMAT2));
47
48 CharFormat.cbSize = sizeof(CHARFORMAT2);
49 CharFormat.dwMask = dwEffects;
50 CharFormat.dwEffects = dwEffects;
51
52 SendMessageW(EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM) &CharFormat);
53
54 SendMessageW(EM_SETSEL, End, End + 1);
55 }
56
57 LONG GetTextLen(VOID)
58 {
59 GETTEXTLENGTHEX TxtLenStruct;
60
61 TxtLenStruct.flags = GTL_NUMCHARS;
62 TxtLenStruct.codepage = 1200;
63
64 return (LONG) SendMessageW(EM_GETTEXTLENGTHEX, (WPARAM) &TxtLenStruct, 0);
65 }
66
67 /*
68 * Insert text (without cleaning old text)
69 * Supported effects:
70 * - CFM_BOLD
71 * - CFM_ITALIC
72 * - CFM_UNDERLINE
73 * - CFM_LINK
74 */
75 VOID InsertText(LPCWSTR lpszText, DWORD dwEffects)
76 {
77 SETTEXTEX SetText;
78 LONG Len = GetTextLen();
79
80 /* Insert new text */
81 SetText.flags = ST_SELECTION;
82 SetText.codepage = 1200;
83
84 SendMessageW(EM_SETTEXTEX, (WPARAM) &SetText, (LPARAM) lpszText);
85
86 SetRangeFormatting(Len, Len + wcslen(lpszText),
87 (dwEffects == CFM_LINK) ? (PathIsURLW(lpszText) ? dwEffects : 0) : dwEffects);
88 }
89
90 /*
91 * Clear old text and add new
92 */
93 VOID SetText(LPCWSTR lpszText, DWORD dwEffects)
94 {
95 SetWindowTextW(L"");
96 InsertText(lpszText, dwEffects);
97 }
98
99 VOID OnLink(ENLINK *Link)
100 {
101 switch (Link->msg)
102 {
103 case WM_LBUTTONUP:
104 case WM_RBUTTONUP:
105 {
106 if (pLink) HeapFree(GetProcessHeap(), 0, pLink);
107
108 pLink = (PWSTR) HeapAlloc(GetProcessHeap(), 0,
109 (max(Link->chrg.cpMin, Link->chrg.cpMax) -
110 min(Link->chrg.cpMin, Link->chrg.cpMax) + 1) * sizeof(WCHAR));
111 if (!pLink)
112 {
113 /* TODO: Error message */
114 return;
115 }
116
117 SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
118 SendMessageW(EM_GETSELTEXT, 0, (LPARAM) pLink);
119
120 ShowPopupMenu(m_hWnd, IDR_LINKMENU, -1);
121 }
122 break;
123 }
124 }
125
126 HWND Create(HWND hwndParent)
127 {
128 LoadLibraryW(L"riched20.dll");
129
130 HWND hwnd = CreateWindowExW(0,
131 L"RichEdit20W",
132 NULL,
133 WS_CHILD | WS_VISIBLE | ES_MULTILINE |
134 ES_LEFT | ES_READONLY,
135 205, 28, 465, 100,
136 hwndParent,
137 NULL,
138 hInst,
139 NULL);
140
141 SubclassWindow(hwnd);
142
143 if (hwnd)
144 {
145 SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
146 SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
147 SendMessageW(EM_SETEVENTMASK, 0, ENM_LINK | ENM_MOUSEEVENTS);
148 SendMessageW(EM_SHOWSCROLLBAR, SB_VERT, TRUE);
149 }
150
151 return hwnd;
152 }
153
154 };
155
156 class CUiListView :
157 public CUiWindow<CListView>
158 {
159 struct SortContext
160 {
161 CUiListView * lvw;
162 int iSubItem;
163 };
164
165 public:
166 BOOL bAscending;
167
168 CUiListView()
169 {
170 bAscending = TRUE;
171 }
172
173 VOID ColumnClick(LPNMLISTVIEW pnmv)
174 {
175 SortContext ctx = { this, pnmv->iSubItem };
176
177 SortItems(s_CompareFunc, &ctx);
178
179 bAscending = !bAscending;
180 }
181
182 PVOID GetLParam(INT Index)
183 {
184 INT ItemIndex;
185 LVITEM Item;
186
187 if (Index == -1)
188 {
189 ItemIndex = (INT) SendMessage(LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
190 if (ItemIndex == -1)
191 return NULL;
192 }
193 else
194 {
195 ItemIndex = Index;
196 }
197
198 ZeroMemory(&Item, sizeof(LVITEM));
199
200 Item.mask = LVIF_PARAM;
201 Item.iItem = ItemIndex;
202 if (!GetItem(&Item))
203 return NULL;
204
205 return (PVOID) Item.lParam;
206 }
207
208 BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
209 {
210 LV_COLUMN Column;
211
212 ZeroMemory(&Column, sizeof(LV_COLUMN));
213
214 Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
215 Column.iSubItem = Index;
216 Column.pszText = (LPTSTR) lpText;
217 Column.cx = Width;
218 Column.fmt = Format;
219
220 return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
221 }
222
223 INT AddItem(INT ItemIndex, INT IconIndex, LPWSTR lpText, LPARAM lParam)
224 {
225 LV_ITEMW Item;
226
227 ZeroMemory(&Item, sizeof(LV_ITEM));
228
229 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
230 Item.pszText = lpText;
231 Item.lParam = lParam;
232 Item.iItem = ItemIndex;
233 Item.iImage = IconIndex;
234
235 return InsertItem(&Item);
236 }
237
238 static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
239 {
240 SortContext * ctx = ((SortContext*) lParamSort);
241 return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem);
242 }
243
244 INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
245 {
246 WCHAR Item1[MAX_STR_LEN], Item2[MAX_STR_LEN];
247 LVFINDINFO IndexInfo;
248 INT Index;
249
250 IndexInfo.flags = LVFI_PARAM;
251
252 IndexInfo.lParam = lParam1;
253 Index = FindItem(-1, &IndexInfo);
254 GetItemText(Index, iSubItem, Item1, sizeof(Item1) / sizeof(WCHAR));
255
256 IndexInfo.lParam = lParam2;
257 Index = FindItem(-1, &IndexInfo);
258 GetItemText(Index, iSubItem, Item2, sizeof(Item2) / sizeof(WCHAR));
259
260 if (bAscending)
261 return wcscmp(Item2, Item1);
262 else
263 return wcscmp(Item1, Item2);
264
265 return 0;
266 }
267
268 HWND Create(HWND hwndParent)
269 {
270 RECT r = { 205, 28, 465, 250 };
271 DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS;
272 HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0);
273
274 HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
275
276 if (hwnd)
277 SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
278
279 return hwnd;
280 }
281
282 };
283
284 class CUiStatusBar :
285 public CUiWindow<CStatusBar>
286 {
287 };
288
289 class CUiMainWindow :
290 public CWindowImpl<CUiMainWindow, CWindow, CFrameWinTraits>
291 {
292 CUiPanel * m_ClientPanel;
293
294 CUiWindow<> * m_Toolbar;
295 CUiWindow<> * m_TreeView;
296 CUiWindow<> * m_SearchBar;
297 CUiStatusBar * m_StatusBar;
298 CUiListView * m_ListView;
299 CUiRichEdit * m_RichEdit;
300 CUiSplitPanel * m_VSplitter;
301 CUiSplitPanel * m_HSplitter;
302
303 HIMAGELIST hImageTreeView;
304
305 VOID InitApplicationsList(VOID)
306 {
307 WCHAR szText[MAX_STR_LEN];
308
309 /* Add columns to ListView */
310 LoadStringW(hInst, IDS_APP_NAME, szText, _countof(szText));
311 m_ListView->AddColumn(0, szText, 200, LVCFMT_LEFT);
312
313 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, _countof(szText));
314 m_ListView->AddColumn(1, szText, 90, LVCFMT_RIGHT);
315
316 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, _countof(szText));
317 m_ListView->AddColumn(3, szText, 250, LVCFMT_LEFT);
318
319 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
320 }
321
322 HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
323 {
324 WCHAR szText[MAX_STR_LEN];
325 INT Index;
326 HICON hIcon;
327
328 hIcon = (HICON) LoadImage(hInst,
329 MAKEINTRESOURCE(IconIndex),
330 IMAGE_ICON,
331 TREEVIEW_ICON_SIZE,
332 TREEVIEW_ICON_SIZE,
333 LR_CREATEDIBSECTION);
334
335 Index = ImageList_AddIcon(hImageTreeView, hIcon);
336 DestroyIcon(hIcon);
337
338 LoadStringW(hInst, TextIndex, szText, _countof(szText));
339
340 return TreeViewAddItem(hRootItem, szText, Index, Index, TextIndex);
341 }
342
343 VOID InitCategoriesList(VOID)
344 {
345 HTREEITEM hRootItem1, hRootItem2;
346
347 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
348 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
349 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
350
351 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
352 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
353 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
354 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
355 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
356 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
357 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
358 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
359 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
360 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
361 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
362 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
363 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
364 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
365 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
366 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
367
368 (VOID) TreeView_SetImageList(hTreeView, hImageTreeView, TVSIL_NORMAL);
369
370 (VOID) TreeView_Expand(hTreeView, hRootItem2, TVE_EXPAND);
371 (VOID) TreeView_Expand(hTreeView, hRootItem1, TVE_EXPAND);
372
373 (VOID) TreeView_SelectItem(hTreeView, hRootItem1);
374 }
375
376 BOOL CreateStatusBar()
377 {
378 m_StatusBar = new CUiStatusBar();
379 m_StatusBar->m_VerticalAlignment = UiAlign_RightBtm;
380 m_StatusBar->m_HorizontalAlignment = UiAlign_Stretch;
381 m_ClientPanel->Children().Append(m_StatusBar);
382
383 return m_StatusBar->Create(m_hWnd, (HMENU)IDC_STATUSBAR) != NULL;
384 }
385
386 BOOL CreateToolbar()
387 {
388 // TODO: WRAPPER
389 m_Toolbar = new CUiWindow<>();
390 m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop;
391 m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch;
392 m_ClientPanel->Children().Append(m_Toolbar);
393
394 CreateToolBar(m_hWnd);
395 m_Toolbar->m_hWnd = hToolBar;
396
397 return hToolBar != NULL;
398 }
399
400 BOOL CreateTreeView()
401 {
402 // TODO: WRAPPER
403 m_TreeView = new CUiWindow<>();
404 m_TreeView->m_VerticalAlignment = UiAlign_Stretch;
405 m_TreeView->m_HorizontalAlignment = UiAlign_Stretch;
406 m_VSplitter->First().Append(m_TreeView);
407
408 ::CreateTreeView(m_hWnd);
409 m_TreeView->m_hWnd = hTreeView;
410
411 return hTreeView != NULL;
412 }
413
414 BOOL CreateListView()
415 {
416 m_ListView = new CUiListView();
417 m_ListView->m_VerticalAlignment = UiAlign_Stretch;
418 m_ListView->m_HorizontalAlignment = UiAlign_Stretch;
419 m_HSplitter->First().Append(m_ListView);
420
421 hListView = m_ListView->Create(m_hWnd);
422 return hListView != NULL;
423 }
424
425 BOOL CreateRichEdit()
426 {
427 m_RichEdit = new CUiRichEdit();
428 m_RichEdit->m_VerticalAlignment = UiAlign_Stretch;
429 m_RichEdit->m_HorizontalAlignment = UiAlign_Stretch;
430 m_HSplitter->Second().Append(m_RichEdit);
431
432 return m_RichEdit->Create(m_hWnd) != NULL;
433 }
434
435 BOOL CreateVSplitter()
436 {
437 m_VSplitter = new CUiSplitPanel();
438 m_VSplitter->m_VerticalAlignment = UiAlign_Stretch;
439 m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch;
440 m_VSplitter->m_DynamicFirst = FALSE;
441 m_VSplitter->m_Horizontal = FALSE;
442 m_VSplitter->m_MinFirst = 240;
443 m_VSplitter->m_MinSecond = 300;
444 m_ClientPanel->Children().Append(m_VSplitter);
445
446 return m_VSplitter->Create(m_hWnd) != NULL;
447 }
448
449 BOOL CreateHSplitter()
450 {
451 m_HSplitter = new CUiSplitPanel();
452 m_HSplitter->m_VerticalAlignment = UiAlign_Stretch;
453 m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch;
454 m_HSplitter->m_DynamicFirst = TRUE;
455 m_HSplitter->m_Horizontal = TRUE;
456 m_HSplitter->m_Pos = 32768;
457 m_HSplitter->m_MinFirst = 300;
458 m_HSplitter->m_MinSecond = 80;
459 m_VSplitter->Second().Append(m_HSplitter);
460
461 return m_HSplitter->Create(m_hWnd) != NULL;
462 }
463
464 BOOL CreateSearchBar(VOID)
465 {
466 WCHAR szBuf[MAX_STR_LEN];
467
468 // TODO: WRAPPER
469 m_SearchBar = new CUiWindow<>();
470 m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
471 m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm;
472 m_SearchBar->m_Margin.top = 6;
473 m_SearchBar->m_Margin.right = 6;
474 //m_ClientPanel->Children().Append(m_SearchBar);
475
476 hSearchBar = CreateWindowExW(WS_EX_CLIENTEDGE,
477 L"Edit",
478 NULL,
479 WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
480 0,
481 0,
482 200,
483 22,
484 m_Toolbar->m_hWnd,
485 (HMENU) 0,
486 hInst,
487 0);
488
489 m_SearchBar->m_hWnd = hSearchBar;
490
491 m_SearchBar->SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
492
493 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
494 m_SearchBar->SetWindowTextW(szBuf);
495
496 return hSearchBar != NULL;
497 }
498
499 BOOL CreateLayout()
500 {
501 bool b = TRUE;
502
503 m_ClientPanel = new CUiPanel();
504 m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
505 m_ClientPanel->m_HorizontalAlignment = UiAlign_Stretch;
506
507 // Top level
508 b = b && CreateStatusBar();
509 b = b && CreateToolbar();
510 b = b && CreateSearchBar();
511 b = b && CreateVSplitter();
512
513 // Inside V Splitter
514 b = b && CreateHSplitter();
515 b = b && CreateTreeView();
516
517 // Inside H Splitter
518 b = b && CreateListView();
519 b = b && CreateRichEdit();
520
521 if (b)
522 {
523 RECT rTop;
524 RECT rBottom;
525
526 /* Size status bar */
527 m_StatusBar->SendMessage(WM_SIZE, 0, 0);
528
529 /* Size tool bar */
530 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
531
532 ::GetWindowRect(m_Toolbar->m_hWnd, &rTop);
533 ::GetWindowRect(m_StatusBar->m_hWnd, &rBottom);
534
535 m_VSplitter->m_Margin.left = 3;
536 m_VSplitter->m_Margin.right = 3;
537 m_VSplitter->m_Margin.top = rTop.bottom - rTop.top + 3;
538 m_VSplitter->m_Margin.bottom = rBottom.bottom-rBottom.top + 3;
539 }
540
541 return b;
542 }
543
544 BOOL InitControls()
545 {
546 /* Create image list */
547 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
548 GetSystemColorDepth() | ILC_MASK,
549 0, 1);
550
551 if (CreateLayout())
552 {
553 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
554
555 InitApplicationsList();
556
557 InitCategoriesList();
558
559 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, _countof(szBuffer2));
560 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
561 szBuffer2,
562 m_ListView->GetItemCount());
563 m_StatusBar->SetText(szBuffer1);
564 return TRUE;
565 }
566
567 return FALSE;
568 }
569
570 VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
571 {
572 /* Size status bar */
573 m_StatusBar->SendMessage(WM_SIZE, 0, 0);
574
575 /* Size tool bar */
576 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
577
578
579 RECT r = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
580
581 HDWP hdwp = NULL;
582
583 int count = m_ClientPanel->CountSizableChildren();
584 hdwp = BeginDeferWindowPos(count);
585 hdwp = m_ClientPanel->OnParentSize(r, hdwp);
586 EndDeferWindowPos(hdwp);
587
588 // TODO: Sub-layouts for children of children
589 count = m_SearchBar->CountSizableChildren();
590 hdwp = BeginDeferWindowPos(count);
591 hdwp = m_SearchBar->OnParentSize(r, hdwp);
592 EndDeferWindowPos(hdwp);
593 }
594
595 BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
596 {
597 theResult = 0;
598 switch (Msg)
599 {
600 case WM_CREATE:
601 if (!InitControls())
602 PostMessage(hwnd, WM_CLOSE, 0, 0);
603 break;
604
605 case WM_DESTROY:
606 {
607 ShowWindow(SW_HIDE);
608 SaveSettings(hwnd);
609
610 FreeLogs();
611
612 FreeCachedAvailableEntries();
613
614 if (IS_INSTALLED_ENUM(SelectedEnumType))
615 FreeInstalledAppList();
616
617 if (hImageTreeView)
618 ImageList_Destroy(hImageTreeView);
619
620 delete m_ClientPanel;
621
622 PostQuitMessage(0);
623 return 0;
624 }
625
626 case WM_COMMAND:
627 MainWndOnCommand(hwnd, wParam, lParam);
628 break;
629
630 case WM_NOTIFY:
631 {
632 LPNMHDR data = (LPNMHDR) lParam;
633
634 switch (data->code)
635 {
636 case TVN_SELCHANGED:
637 {
638 if (data->hwndFrom == hTreeView)
639 {
640 switch (((LPNMTREEVIEW) lParam)->itemNew.lParam)
641 {
642 case IDS_INSTALLED:
643 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
644 break;
645
646 case IDS_APPLICATIONS:
647 UpdateApplicationsList(ENUM_APPLICATIONS);
648 break;
649
650 case IDS_UPDATES:
651 UpdateApplicationsList(ENUM_UPDATES);
652 break;
653
654 case IDS_AVAILABLEFORINST:
655 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
656 break;
657
658 case IDS_CAT_AUDIO:
659 UpdateApplicationsList(ENUM_CAT_AUDIO);
660 break;
661
662 case IDS_CAT_DEVEL:
663 UpdateApplicationsList(ENUM_CAT_DEVEL);
664 break;
665
666 case IDS_CAT_DRIVERS:
667 UpdateApplicationsList(ENUM_CAT_DRIVERS);
668 break;
669
670 case IDS_CAT_EDU:
671 UpdateApplicationsList(ENUM_CAT_EDU);
672 break;
673
674 case IDS_CAT_ENGINEER:
675 UpdateApplicationsList(ENUM_CAT_ENGINEER);
676 break;
677
678 case IDS_CAT_FINANCE:
679 UpdateApplicationsList(ENUM_CAT_FINANCE);
680 break;
681
682 case IDS_CAT_GAMES:
683 UpdateApplicationsList(ENUM_CAT_GAMES);
684 break;
685
686 case IDS_CAT_GRAPHICS:
687 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
688 break;
689
690 case IDS_CAT_INTERNET:
691 UpdateApplicationsList(ENUM_CAT_INTERNET);
692 break;
693
694 case IDS_CAT_LIBS:
695 UpdateApplicationsList(ENUM_CAT_LIBS);
696 break;
697
698 case IDS_CAT_OFFICE:
699 UpdateApplicationsList(ENUM_CAT_OFFICE);
700 break;
701
702 case IDS_CAT_OTHER:
703 UpdateApplicationsList(ENUM_CAT_OTHER);
704 break;
705
706 case IDS_CAT_SCIENCE:
707 UpdateApplicationsList(ENUM_CAT_SCIENCE);
708 break;
709
710 case IDS_CAT_TOOLS:
711 UpdateApplicationsList(ENUM_CAT_TOOLS);
712 break;
713
714 case IDS_CAT_VIDEO:
715 UpdateApplicationsList(ENUM_CAT_VIDEO);
716 break;
717 }
718 }
719
720 HMENU mainMenu = GetMenu(hwnd);
721 HMENU lvwMenu = GetMenu(m_ListView->m_hWnd);
722
723 /* Disable/enable items based on treeview selection */
724 if (IsSelectedNodeInstalled())
725 {
726 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_ENABLED);
727 EnableMenuItem(mainMenu, ID_INSTALL, MF_GRAYED);
728 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_ENABLED);
729 EnableMenuItem(mainMenu, ID_MODIFY, MF_ENABLED);
730
731 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_ENABLED);
732 EnableMenuItem(lvwMenu, ID_INSTALL, MF_GRAYED);
733 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_ENABLED);
734 EnableMenuItem(lvwMenu, ID_MODIFY, MF_ENABLED);
735
736 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
737 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_INSTALL, FALSE);
738 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
739 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_MODIFY, TRUE);
740 }
741 else
742 {
743 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_GRAYED);
744 EnableMenuItem(mainMenu, ID_INSTALL, MF_ENABLED);
745 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_GRAYED);
746 EnableMenuItem(mainMenu, ID_MODIFY, MF_GRAYED);
747
748 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_GRAYED);
749 EnableMenuItem(lvwMenu, ID_INSTALL, MF_ENABLED);
750 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_GRAYED);
751 EnableMenuItem(lvwMenu, ID_MODIFY, MF_GRAYED);
752
753 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
754 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_INSTALL, TRUE);
755 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
756 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_MODIFY, FALSE);
757 }
758 }
759 break;
760
761 case LVN_ITEMCHANGED:
762 {
763 LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
764
765 if (pnic->hdr.hwndFrom == m_ListView->m_hWnd)
766 {
767 /* Check if this is a valid item
768 * (technically, it can be also an unselect) */
769 INT ItemIndex = pnic->iItem;
770 if (ItemIndex == -1 ||
771 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
772 {
773 break;
774 }
775
776 /* Check if the focus has been moved to another item */
777 if ((pnic->uChanged & LVIF_STATE) &&
778 (pnic->uNewState & LVIS_FOCUSED) &&
779 !(pnic->uOldState & LVIS_FOCUSED))
780 {
781 if (IS_INSTALLED_ENUM(SelectedEnumType))
782 ShowInstalledAppInfo(ItemIndex);
783 if (IS_AVAILABLE_ENUM(SelectedEnumType))
784 ShowAvailableAppInfo(ItemIndex);
785 }
786 }
787 }
788 break;
789
790 case LVN_COLUMNCLICK:
791 {
792 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
793
794 m_ListView->ColumnClick(pnmv);
795 }
796 break;
797
798 case NM_CLICK:
799 {
800 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
801 {
802 if (IS_INSTALLED_ENUM(SelectedEnumType))
803 ShowInstalledAppInfo(-1);
804 if (IS_AVAILABLE_ENUM(SelectedEnumType))
805 ShowAvailableAppInfo(-1);
806 }
807 }
808 break;
809
810 case NM_DBLCLK:
811 {
812 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
813 {
814 /* this won't do anything if the program is already installed */
815 SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0);
816 }
817 }
818 break;
819
820 case NM_RCLICK:
821 {
822 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
823 {
824 ShowPopupMenu(m_ListView->m_hWnd, 0, ID_INSTALL);
825 }
826 }
827 break;
828
829 case EN_LINK:
830 m_RichEdit->OnLink((ENLINK*) lParam);
831 break;
832
833 case TTN_GETDISPINFO:
834 ToolBarOnGetDispInfo((LPTOOLTIPTEXT) lParam);
835 break;
836 }
837 }
838 break;
839
840 case WM_SIZE:
841 OnSize(hwnd, wParam, lParam);
842 break;
843
844 case WM_SIZING:
845 {
846 LPRECT pRect = (LPRECT) lParam;
847
848 if (pRect->right - pRect->left < 565)
849 pRect->right = pRect->left + 565;
850
851 if (pRect->bottom - pRect->top < 300)
852 pRect->bottom = pRect->top + 300;
853
854 return TRUE;
855 }
856
857 case WM_SYSCOLORCHANGE:
858 {
859 /* Forward WM_SYSCOLORCHANGE to common controls */
860 m_ListView->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
861 SendMessage(hTreeView, WM_SYSCOLORCHANGE, 0, 0);
862 SendMessage(hToolBar, WM_SYSCOLORCHANGE, 0, 0);
863 m_ListView->SendMessage(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
864 }
865 break;
866 }
867
868 return FALSE;
869 }
870
871 public:
872 CUiMainWindow() :
873 m_ClientPanel(NULL),
874 hImageTreeView(NULL)
875 {
876
877 }
878
879 static ATL::CWndClassInfo& GetWndClassInfo()
880 {
881 DWORD csStyle = CS_VREDRAW |CS_HREDRAW;
882 static ATL::CWndClassInfo wc =
883 {
884 { sizeof(WNDCLASSEX), csStyle, StartWindowProc,
885 0, 0, NULL,
886 LoadIcon(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCE(IDI_MAIN)),
887 LoadCursor(NULL, IDC_ARROW),
888 (HBRUSH) (COLOR_BTNFACE + 1), NULL,
889 L"RAppsWnd", NULL },
890 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
891 };
892 return wc;
893 }
894
895 HWND Create()
896 {
897 WCHAR szWindowName[MAX_STR_LEN];
898
899 LoadStringW(hInst, IDS_APPTITLE, szWindowName, _countof(szWindowName));
900
901 RECT r = {
902 (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
903 (SettingsInfo.bSaveWndPos ? SettingsInfo.Top : CW_USEDEFAULT),
904 (SettingsInfo.bSaveWndPos ? SettingsInfo.Width : 680),
905 (SettingsInfo.bSaveWndPos ? SettingsInfo.Height : 450)
906 };
907 r.right += r.left;
908 r.bottom += r.top;
909
910 return CWindowImpl::Create(NULL, r, szWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
911 }
912
913 CUiStatusBar * GetStatusBar()
914 {
915 return m_StatusBar;
916 }
917
918 CUiListView * GetListView()
919 {
920 return m_ListView;
921 }
922
923 CUiRichEdit * GetRichEdit()
924 {
925 return m_RichEdit;
926 }
927 };
928
929 CUiMainWindow * g_MainWindow;
930
931 HWND CreateMainWindow()
932 {
933 g_MainWindow = new CUiMainWindow();
934 return g_MainWindow->Create();
935 }
936
937 DWORD_PTR ListViewGetlParam(INT item)
938 {
939 return g_MainWindow->GetListView()->GetItemData(item);
940 }
941
942 VOID SetStatusBarText(PCWSTR szText)
943 {
944 g_MainWindow->GetStatusBar()->SetText(szText);
945 }
946
947 INT ListViewAddItem(INT ItemIndex, INT IconIndex, PWSTR lpName, LPARAM lParam)
948 {
949 return g_MainWindow->GetListView()->AddItem(ItemIndex, IconIndex, lpName, lParam);
950 }
951
952 VOID NewRichEditText(PCWSTR szText, DWORD flags)
953 {
954 g_MainWindow->GetRichEdit()->SetText(szText, flags);
955 }
956
957 VOID InsertRichEditText(PCWSTR szText, DWORD flags)
958 {
959 g_MainWindow->GetRichEdit()->InsertText(szText, flags);
960 }