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
CFindJava2Dlg(CWnd * pParent)31 CFindJava2Dlg::CFindJava2Dlg(CWnd* pParent /*=NULL*/)
32 : CDialog(CFindJava2Dlg::IDD, pParent), mSelectedIndex(-1) {
33 m_hIcon = AfxGetApp()->LoadIcon(IDI_ANDROID_ICON);
34 }
35
DoDataExchange(CDataExchange * pDX)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
BEGIN_MESSAGE_MAP(CFindJava2Dlg,CDialog)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]
OnPaint()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]
OnQueryDragIcon()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
OnBnClickedButtonAdd()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.
OnNMClickPathList(NMHDR * pNMHDR,LRESULT * pResult)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.
OnLvnItemchangedPathList(NMHDR * pNMHDR,LRESULT * pResult)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
getSelectedPath()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
fillPathsList()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.
selectPath(int index,const CJavaPath * path)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
adjustButtons()265 void CFindJava2Dlg::adjustButtons() {
266 int n = mPathsListCtrl.GetItemCount();
267 mOkButton.EnableWindow(mSelectedIndex >= 0 && mSelectedIndex < n);
268 }
269