[RAPPS] Making checkboxes useful WIP
[reactos.git] / reactos / base / applications / rapps / gui.cpp
index 01ce7d9..0a5a925 100644 (file)
@@ -102,35 +102,50 @@ class CAvailableAppView
 
     static VOID InsertLanguageInfo_RichEdit(CAvailableApplicationInfo* Info)
     {
+        if (!Info->HasLanguageInfo())
+        {
+            return;
+        }
+
         const INT nTranslations = Info->Languages.GetSize();
         ATL::CStringW szLangInfo;
         ATL::CStringW szLoadedTextAvailability;
         ATL::CStringW szLoadedAInfoText;
+
         szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
 
+        //TODO: replace those hardcoded strings
         if (Info->HasNativeLanguage())
         {
             szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
+            if (nTranslations > 1)
+            {
+                szLangInfo.Format(L" (+%d more)", nTranslations - 1);
+            }
+            else
+            {
+                szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
+                szLangInfo = L" (" + szLangInfo + L")";
+            }
         }
         else if (Info->HasEnglishLanguage())
         {
             szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
+            if (nTranslations > 1)
+            {
+                szLangInfo.Format(L" (+%d available)", nTranslations - 1);
+            }
+            else
+            {
+                szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
+                szLangInfo = L" (" + szLangInfo + L")";
+            }
         }
         else
         {
             szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION);
         }
 
-        if (nTranslations > 1)
-        {
-            szLangInfo.Format(L" (+%d more)", nTranslations - 1);
-        }
-        else
-        {
-            szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
-            szLangInfo = L" (" + szLangInfo + L")";
-        }
-
         InsertRichEditText(szLoadedAInfoText, CFE_BOLD);
         InsertRichEditText(szLoadedTextAvailability, NULL);
         InsertRichEditText(szLangInfo, CFE_ITALIC);
@@ -164,6 +179,7 @@ class CMainToolbar :
     WCHAR szInstallBtn[MAX_STR_LEN];
     WCHAR szUninstallBtn[MAX_STR_LEN];
     WCHAR szModifyBtn[MAX_STR_LEN];
+    WCHAR szSelectAll[MAX_STR_LEN];
 
     VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
     {
@@ -183,7 +199,7 @@ class CMainToolbar :
         DeleteObject(hImage);
     }
 
-    HIMAGELIST InitImageList(VOID)
+    HIMAGELIST InitImageList()
     {
         HIMAGELIST hImageList;
 
@@ -202,6 +218,7 @@ class CMainToolbar :
         AddImageToImageList(hImageList, IDI_INSTALL);
         AddImageToImageList(hImageList, IDI_UNINSTALL);
         AddImageToImageList(hImageList, IDI_MODIFY);
+        AddImageToImageList(hImageList, IDI_CHECK_ALL);
         AddImageToImageList(hImageList, IDI_REFRESH);
         AddImageToImageList(hImageList, IDI_UPDATE_DB);
         AddImageToImageList(hImageList, IDI_SETTINGS);
@@ -257,17 +274,19 @@ public:
             { 0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szInstallBtn },
             { 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szUninstallBtn },
             { 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szModifyBtn },
-            { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
-            { 3, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
-            { 4, ID_RESETDB,   TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, 0},
-            { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
-            { 5, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
-            { 6, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 }
+            { 3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE,{0}, 0, (INT_PTR) szSelectAll},
+            {-1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
+            { 4, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
+            { 5, ID_RESETDB,   TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
+            {-1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
+            { 6, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
+            { 7, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
         };
 
         LoadStringW(hInst, IDS_INSTALL, szInstallBtn, _countof(szInstallBtn));
         LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, _countof(szUninstallBtn));
         LoadStringW(hInst, IDS_MODIFY, szModifyBtn, _countof(szModifyBtn));
+        LoadStringW(hInst, IDS_SELECT_ALL, szSelectAll, _countof(szSelectAll));
 
         m_hWnd = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL,
                                  WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST,
@@ -309,12 +328,14 @@ class CAppsListView :
         int iSubItem;
     };
 
-public:
+    BOOL bHasAllChecked;
     BOOL bAscending;
 
-    CAppsListView()
+public:
+    CAppsListView() :
+        bAscending(TRUE),
+        bHasAllChecked(FALSE)
     {
-        bAscending = TRUE;
     }
 
     VOID ColumnClick(LPNMLISTVIEW pnmv)
@@ -329,7 +350,7 @@ public:
     PVOID GetLParam(INT Index)
     {
         INT ItemIndex;
-        LVITEM Item;
+        LVITEMW Item;
 
         if (Index == -1)
         {
@@ -359,13 +380,13 @@ public:
 
     BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
     {
-        LV_COLUMN Column;
+        LV_COLUMNW Column;
 
         ZeroMemory(&Column, sizeof(Column));
 
         Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
         Column.iSubItem = Index;
-        Column.pszText = (LPTSTR) lpText;
+        Column.pszText = lpText;
         Column.cx = Width;
         Column.fmt = Format;
 
@@ -428,11 +449,41 @@ public:
         HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
 
         if (hwnd)
-            SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
+        {
+            SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+        }
 
         return hwnd;
     }
 
+    BOOL GetCheckState(INT item)
+    {
+        return (BOOL) GetItemState(item, LVIS_STATEIMAGEMASK);
+    }
+
+    VOID SetCheckState(INT item, BOOL fCheck)
+    {
+        SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
+    }
+
+    VOID CheckAll()
+    {
+        bHasAllChecked = !bHasAllChecked;
+        SetCheckState(-1, bHasAllChecked);
+    }
+
+    ATL::CAtlList<PAPPLICATION_INFO> GetCheckedItems()
+    {
+        ATL::CAtlList<PAPPLICATION_INFO> list;
+        for (INT i = 0; i != -1; i = GetNextItem(i, LVNI_ALL))
+        {
+            if (GetCheckState(i) != FALSE)
+            {
+                list.AddTail((PAPPLICATION_INFO) GetItemData(i));
+            }
+        }
+        return list;
+    }
 };
 
 class CSideTreeView :
@@ -529,23 +580,24 @@ class CMainWindow :
     CUiWindow<CRichEdit> * m_RichEdit;
 
     CUiWindow<CSearchBar> * m_SearchBar;
+    CAvailableApps m_AvailableApps;
 
     LPWSTR pLink;
 
-    BOOL SearchEnabled;
-
-    CAvailableApps m_AvailableApps;
+    INT nSelectedApps;
 
+    BOOL bSearchEnabled;
+    BOOL bUpdating;
 public:
     CMainWindow() :
         m_ClientPanel(NULL),
         pLink(NULL),
-        SearchEnabled(TRUE)
+        bSearchEnabled(FALSE)
     {
     }
-private:
 
-    VOID InitApplicationsList(VOID)
+private:
+    VOID InitApplicationsList()
     {
         ATL::CStringW szText;
 
@@ -559,7 +611,8 @@ private:
         szText.LoadStringW(hInst, IDS_APP_DESCRIPTION);
         m_ListView->AddColumn(3, szText, 250, LVCFMT_LEFT);
 
-        UpdateApplicationsList(ENUM_ALL_COMPONENTS);
+        // Unnesesary since the list updates on every TreeView selection
+        // UpdateApplicationsList(ENUM_ALL_COMPONENTS);
     }
 
     HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
@@ -567,7 +620,7 @@ private:
         return m_TreeView->AddCategory(hRootItem, TextIndex, IconIndex);
     }
 
-    VOID InitCategoriesList(VOID)
+    VOID InitCategoriesList()
     {
         HTREEITEM hRootItem;
 
@@ -673,7 +726,7 @@ private:
         return m_HSplitter->Create(m_hWnd) != NULL;
     }
 
-    BOOL CreateSearchBar(VOID)
+    BOOL CreateSearchBar()
     {
         m_SearchBar = new CUiWindow<CSearchBar>();
         m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
@@ -686,7 +739,8 @@ private:
 
     BOOL CreateLayout()
     {
-        bool b = TRUE;
+        BOOL b = TRUE;
+        bUpdating = TRUE;
 
         m_ClientPanel = new CUiPanel();
         m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
@@ -724,6 +778,7 @@ private:
             m_VSplitter->m_Margin.bottom = rBottom.bottom - rBottom.top;
         }
 
+        bUpdating = FALSE;
         return b;
     }
 
@@ -731,16 +786,13 @@ private:
     {
         if (CreateLayout())
         {
-            ATL::CStringW szBuffer1, szBuffer2;
 
             InitApplicationsList();
-
             InitCategoriesList();
 
-            szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
-            szBuffer1.Format(szBuffer2, m_ListView->GetItemCount());
+            nSelectedApps = 0;
+            UpdateStatusBarText();
 
-            m_StatusBar->SetText(szBuffer1);
             return TRUE;
         }
 
@@ -968,6 +1020,13 @@ private:
                         if (IS_AVAILABLE_ENUM(SelectedEnumType))
                             CAvailableAppView::ShowAvailableAppInfo(ItemIndex);
                     }
+                    /* Check if the item is checked */
+                    if ((pnic->uNewState & LVIS_STATEIMAGEMASK) && !bUpdating)
+                    {
+                        BOOL checked = m_ListView->GetCheckState(pnic->iItem);
+                        nSelectedApps += (checked) ? 1 : -1;
+                        UpdateStatusBarText();
+                    }
                 }
             }
             break;
@@ -997,7 +1056,7 @@ private:
                 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
                 {
                     /* this won't do anything if the program is already installed */
-                    SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0);
+                    SendMessageW(hwnd, WM_COMMAND, ID_INSTALL, 0);
                 }
             }
             break;
@@ -1053,9 +1112,10 @@ private:
             if (wParam == SEARCH_TIMER_ID)
             {
                 ::KillTimer(hwnd, SEARCH_TIMER_ID);
-                UpdateApplicationsList(-1);
+                if (bSearchEnabled)
+                    UpdateApplicationsList(-1);
             }
-            break;
+        break;
         }
 
         return FALSE;
@@ -1088,7 +1148,7 @@ private:
         }
     }
 
-    BOOL IsSelectedNodeInstalled(void)
+    BOOL IsSelectedNodeInstalled()
     {
         HTREEITEM hSelectedItem = m_TreeView->GetSelection();
         TV_ITEM tItem;
@@ -1125,7 +1185,7 @@ private:
                 m_SearchBar->GetWindowTextW(szWndText);
                 if (szBuf == szWndText)
                 {
-                    SearchEnabled = FALSE;
+                    bSearchEnabled = FALSE;
                     m_SearchBar->SetWindowTextW(L"");
                 }
             }
@@ -1137,7 +1197,7 @@ private:
                 if (szBuf.IsEmpty())
                 {
                     szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
-                    SearchEnabled = FALSE;
+                    bSearchEnabled = FALSE;
                     m_SearchBar->SetWindowTextW(szBuf.GetString());
                 }
             }
@@ -1147,9 +1207,9 @@ private:
             {
                 ATL::CStringW szWndText;
 
-                if (!SearchEnabled)
+                if (!bSearchEnabled)
                 {
-                    SearchEnabled = TRUE;
+                    bSearchEnabled = TRUE;
                     break;
                 }
 
@@ -1232,12 +1292,16 @@ private:
         case ID_ABOUT:
             ShowAboutDialog();
             break;
+
+        case ID_CHECK_ALL:
+            m_ListView->CheckAll();
+            break;
         }
     }
 
-    VOID FreeInstalledAppList(VOID)
+    VOID FreeInstalledAppList()
     {
-        INT Count = ListView_GetItemCount(hListView) - 1;
+        INT Count = m_ListView->GetItemCount() - 1;
         PINSTALLED_INFO Info;
 
         while (Count >= 0)
@@ -1335,33 +1399,45 @@ private:
         return TRUE;
     }
 
+    VOID UpdateStatusBarText()
+    {
+        if (m_StatusBar)
+        {
+            ATL::CStringW szBuffer1, szBuffer2;
+
+            szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
+            szBuffer1.Format(szBuffer2, m_ListView->GetItemCount(), nSelectedApps);
+            m_StatusBar->SetText(szBuffer1);
+        }
+    }
 
     VOID UpdateApplicationsList(INT EnumType)
     {
         ATL::CStringW szBuffer1, szBuffer2;
         HIMAGELIST hImageListView;
+        bUpdating = TRUE;
 
-        m_ListView->SendMessageW(WM_SETREDRAW, FALSE, 0);
+        m_ListView->SetRedraw(FALSE);
 
+        nSelectedApps = 0;
         if (EnumType < 0) EnumType = SelectedEnumType;
 
         if (IS_INSTALLED_ENUM(SelectedEnumType))
             FreeInstalledAppList();
 
-        (VOID) ListView_DeleteAllItems(hListView);
+        m_ListView->DeleteAllItems();
 
         /* Create new ImageList */
         hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
                                           LISTVIEW_ICON_SIZE,
                                           GetSystemColorDepth() | ILC_MASK,
                                           0, 1);
-        HIMAGELIST hImageListBuf = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
+        HIMAGELIST hImageListBuf = m_ListView->SetImageList(hImageListView, LVSIL_SMALL);
         if (hImageListBuf)
         {
             ImageList_Destroy(hImageListBuf);
         }
 
-
         if (IS_AVAILABLE_ENUM(EnumType))
         {
             /* Enum available applications */
@@ -1370,17 +1446,16 @@ private:
 
         SelectedEnumType = EnumType;
 
-        szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
-        szBuffer1.Format(szBuffer2, ListView_GetItemCount(hListView));
-        SetStatusBarText(szBuffer1);
+        UpdateStatusBarText();
 
         SetWelcomeText();
 
         /* set automatic column width for program names if the list is not empty */
-        if (ListView_GetItemCount(hListView) > 0)
-            ListView_SetColumnWidth(hListView, 0, LVSCW_AUTOSIZE);
+        if (m_ListView->GetItemCount() > 0)
+            ListView_SetColumnWidth(m_ListView->GetWindow(), 0, LVSCW_AUTOSIZE);
 
-        SendMessageW(hListView, WM_SETREDRAW, TRUE, 0);
+        bUpdating = FALSE;
+        m_ListView->SetRedraw(TRUE);
     }
 
 public: