1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 #include "stdafx.h" 19 #include "utils.h" 20 #include "FindJava2Dlg.h" 21 #include "afxdialogex.h" 22 #include <atlpath.h> // ATL CPath 23 24 #ifdef _DEBUG 25 #define new DEBUG_NEW 26 #endif 27 28 #define COL_PATH 1 29 30 31 CFindJava2Dlg::CFindJava2Dlg(CWnd* pParent /*=NULL*/) 32 : CDialog(CFindJava2Dlg::IDD, pParent), mSelectedIndex(-1) { 33 m_hIcon = AfxGetApp()->LoadIcon(IDI_ANDROID_ICON); 34 } 35 36 void CFindJava2Dlg::DoDataExchange(CDataExchange* pDX) { 37 CDialog::DoDataExchange(pDX); 38 DDX_Control(pDX, IDC_PATH_LIST, mPathsListCtrl); 39 DDX_Control(pDX, IDOK, mOkButton); 40 } 41 42 BEGIN_MESSAGE_MAP(CFindJava2Dlg, CDialog) 43 ON_WM_PAINT() 44 ON_WM_QUERYDRAGICON() 45 ON_BN_CLICKED(IDC_BUTTON_ADD, &CFindJava2Dlg::OnBnClickedButtonAdd) 46 ON_NOTIFY(NM_CLICK, IDC_PATH_LIST, &CFindJava2Dlg::OnNMClickPathList) 47 ON_NOTIFY(LVN_ITEMCHANGED, IDC_PATH_LIST, &CFindJava2Dlg::OnLvnItemchangedPathList) 48 END_MESSAGE_MAP() 49 50 51 // ----- 52 // CFindJava2Dlg message handlers 53 54 BOOL CFindJava2Dlg::OnInitDialog() { 55 CDialog::OnInitDialog(); 56 57 SetWindowText(getAppName()); 58 59 // Set the icon for this dialog. The framework does this automatically 60 // when the application's main window is not a dialog 61 SetIcon(m_hIcon, TRUE); // Set big icon 62 SetIcon(m_hIcon, FALSE); // Set small icon 63 64 // Initialize list controls 65 mPathsListCtrl.SetExtendedStyle( 66 mPathsListCtrl.GetExtendedStyle() | 67 LVS_EX_CHECKBOXES | 68 LVS_EX_FULLROWSELECT | 69 LVS_EX_GRIDLINES); 70 71 // We want 2 columns: Java version and path 72 mPathsListCtrl.InsertColumn(0, _T("Version"), LVCFMT_RIGHT, 60, 0); 73 mPathsListCtrl.InsertColumn(1, _T("Path"), LVCFMT_LEFT, 386, 0); 74 75 mJavaFinder->findJavaPaths(&mPaths); 76 fillPathsList(); 77 adjustButtons(); 78 79 return TRUE; // return TRUE unless you set the focus to a control 80 } 81 82 // If you add a minimize button to your dialog, you will need the code below 83 // to draw the icon. For MFC applications using the document/view model, 84 // this is automatically done for you by the framework. 85 // [Note: MFC boilerplate, keep as-is] 86 void CFindJava2Dlg::OnPaint() { 87 if (IsIconic()) { 88 CPaintDC dc(this); // device context for painting 89 90 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 91 92 // Center icon in client rectangle 93 int cxIcon = GetSystemMetrics(SM_CXICON); 94 int cyIcon = GetSystemMetrics(SM_CYICON); 95 CRect rect; 96 GetClientRect(&rect); 97 int x = (rect.Width() - cxIcon + 1) / 2; 98 int y = (rect.Height() - cyIcon + 1) / 2; 99 100 // Draw the icon 101 dc.DrawIcon(x, y, m_hIcon); 102 } else { 103 CDialog::OnPaint(); 104 } 105 } 106 107 // The system calls this function to obtain the cursor to display while the user drags 108 // the minimized window. [Note: MFC boilerplate, keep as-is] 109 HCURSOR CFindJava2Dlg::OnQueryDragIcon() { 110 return static_cast<HCURSOR>(m_hIcon); 111 } 112 113 // Button add has been pressed; use file dialog and add path if it's a valid java.exe 114 void CFindJava2Dlg::OnBnClickedButtonAdd() { 115 CFileDialog fileDlg( 116 TRUE, // true=open dialog, false=save-as dialog 117 _T("exe"), // lpszDefExt 118 _T("java.exe"), // lpszFileName 119 OFN_FILEMUSTEXIST || OFN_PATHMUSTEXIST, 120 NULL, // lpszFilter 121 this); // pParentWnd 122 123 if (fileDlg.DoModal() == IDOK) { 124 CString path = fileDlg.GetPathName(); 125 126 CJavaPath javaPath; 127 if (!mJavaFinder->checkJavaPath(path, &javaPath)) { 128 CString msg; 129 if (javaPath.mVersion > 0) { 130 msg.Format(_T("Insufficient Java Version found: expected %s, got %s"), 131 CJavaPath(mJavaFinder->getMinVersion(), CPath()).getVersion(), 132 javaPath.getVersion()); 133 } else { 134 msg.Format(_T("No valid Java Version found for %s"), path); 135 } 136 AfxMessageBox(msg, MB_OK); 137 138 } else { 139 if (mPaths.find(javaPath) == mPaths.end()) { 140 // Path isn't known yet so add it and refresh the list. 141 mPaths.insert(javaPath); 142 fillPathsList(); 143 } 144 145 // Select item in list and set mSelectedIndex 146 selectPath(-1 /*index*/, &javaPath); 147 } 148 } 149 } 150 151 // An item in the list has been selected, select checkmark and set mSelectedIndex. 152 void CFindJava2Dlg::OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult) { 153 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); 154 int index = pNMItemActivate->iItem; 155 selectPath(index, nullptr); 156 *pResult = TRUE; 157 } 158 159 // An item in the list has changed, toggle checkmark as needed. 160 void CFindJava2Dlg::OnLvnItemchangedPathList(NMHDR *pNMHDR, LRESULT *pResult) { 161 *pResult = FALSE; 162 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); 163 164 if ((pNMLV->uChanged & LVIF_STATE) != 0) { 165 // Item's state has changed. Check the selection to see if it needs to be adjusted. 166 int index = pNMLV->iItem; 167 168 UINT oldState = pNMLV->uOldState; 169 UINT newState = pNMLV->uNewState; 170 171 if ((oldState & LVIS_STATEIMAGEMASK) != 0 || (newState & LVIS_STATEIMAGEMASK) != 0) { 172 // Checkbox uses the STATEIMAGE: 1 for unchecked, 2 for checked. 173 // Checkbox is checked when (old/new-state & state-image-mask) == INDEXTOSTATEIMAGEMASK(2). 174 175 bool oldChecked = (oldState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2); 176 bool newChecked = (newState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2); 177 178 if (oldChecked && !newChecked && index == mSelectedIndex) { 179 mSelectedIndex = -1; 180 adjustButtons(); 181 } else if (!oldChecked && newChecked && index != mSelectedIndex) { 182 // Uncheck any checked rows if any 183 for (int n = mPathsListCtrl.GetItemCount() - 1; n >= 0; --n) { 184 if (n != index && mPathsListCtrl.GetCheck(n)) { 185 mPathsListCtrl.SetCheck(n, FALSE); 186 } 187 } 188 189 mSelectedIndex = index; 190 adjustButtons(); 191 } 192 // We handled this case, don't dispatch it further 193 *pResult = TRUE; 194 } 195 } 196 } 197 198 // ----- 199 200 const CJavaPath& CFindJava2Dlg::getSelectedPath() { 201 int i = 0; 202 for (const CJavaPath &p : mPaths) { 203 if (i == mSelectedIndex) { 204 return p; 205 } 206 ++i; 207 } 208 209 return CJavaPath::sEmpty; 210 } 211 212 213 void CFindJava2Dlg::fillPathsList() { 214 mPathsListCtrl.DeleteAllItems(); 215 int index = 0; 216 217 for (const CJavaPath& pv : mPaths) { 218 mPathsListCtrl.InsertItem(index, pv.getVersion()); // column 0 = version 219 mPathsListCtrl.SetItemText(index, COL_PATH, pv.mPath); // column 1 = path 220 mPathsListCtrl.SetCheck(index, mSelectedIndex == index); 221 ++index; 222 } 223 } 224 225 // Checks the given index if valid. Unchecks all other items. 226 // 227 // If index >= 0, it is used to select that item from the ListControl. 228 // Otherwise if path != nullptr, it is used to find the item and select it. 229 // 230 // Side effect: in both cases, mSelectedIndex is set to the matching index or -1. 231 // 232 // If index is invalid and path isn't in the mPaths list, all items are unselected 233 // so calling this with (0, nullptr) will clear the current selection. 234 void CFindJava2Dlg::selectPath(int index, const CJavaPath *path) { 235 236 const CJavaPath *foundPath; 237 // If index is not defined, find the given path in the internal list. 238 // If path is not defined, find its index in the internal list. 239 int i = 0; 240 int n = mPathsListCtrl.GetItemCount(); 241 for (const CJavaPath &p : mPaths) { 242 if (index < 0 && path != nullptr && p == *path) { 243 index = i; 244 foundPath = path; 245 } else if (index == i) { 246 foundPath = &p; 247 } 248 249 // uncheck any marked path 250 if (i != index && i < n && mPathsListCtrl.GetCheck(i)) { 251 mPathsListCtrl.SetCheck(i, FALSE); 252 } 253 254 ++i; 255 } 256 257 mSelectedIndex = index; 258 if (index >= 0 && index <= n) { 259 mPathsListCtrl.SetCheck(index, TRUE); 260 } 261 262 adjustButtons(); 263 } 264 265 void CFindJava2Dlg::adjustButtons() { 266 int n = mPathsListCtrl.GetItemCount(); 267 mOkButton.EnableWindow(mSelectedIndex >= 0 && mSelectedIndex < n); 268 } 269