/* | |
* Copyright (C) 2014 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
#include "stdafx.h" | |
#include "utils.h" | |
#include "FindJava2Dlg.h" | |
#include "afxdialogex.h" | |
#include <atlpath.h> // ATL CPath | |
#ifdef _DEBUG | |
#define new DEBUG_NEW | |
#endif | |
#define COL_PATH 1 | |
CFindJava2Dlg::CFindJava2Dlg(CWnd* pParent /*=NULL*/) | |
: CDialog(CFindJava2Dlg::IDD, pParent), mSelectedIndex(-1) { | |
m_hIcon = AfxGetApp()->LoadIcon(IDI_ANDROID_ICON); | |
} | |
void CFindJava2Dlg::DoDataExchange(CDataExchange* pDX) { | |
CDialog::DoDataExchange(pDX); | |
DDX_Control(pDX, IDC_PATH_LIST, mPathsListCtrl); | |
DDX_Control(pDX, IDOK, mOkButton); | |
} | |
BEGIN_MESSAGE_MAP(CFindJava2Dlg, CDialog) | |
ON_WM_PAINT() | |
ON_WM_QUERYDRAGICON() | |
ON_BN_CLICKED(IDC_BUTTON_ADD, &CFindJava2Dlg::OnBnClickedButtonAdd) | |
ON_NOTIFY(NM_CLICK, IDC_PATH_LIST, &CFindJava2Dlg::OnNMClickPathList) | |
ON_NOTIFY(LVN_ITEMCHANGED, IDC_PATH_LIST, &CFindJava2Dlg::OnLvnItemchangedPathList) | |
END_MESSAGE_MAP() | |
// ----- | |
// CFindJava2Dlg message handlers | |
BOOL CFindJava2Dlg::OnInitDialog() { | |
CDialog::OnInitDialog(); | |
SetWindowText(getAppName()); | |
// Set the icon for this dialog. The framework does this automatically | |
// when the application's main window is not a dialog | |
SetIcon(m_hIcon, TRUE); // Set big icon | |
SetIcon(m_hIcon, FALSE); // Set small icon | |
// Initialize list controls | |
mPathsListCtrl.SetExtendedStyle( | |
mPathsListCtrl.GetExtendedStyle() | | |
LVS_EX_CHECKBOXES | | |
LVS_EX_FULLROWSELECT | | |
LVS_EX_GRIDLINES); | |
// We want 2 columns: Java version and path | |
mPathsListCtrl.InsertColumn(0, _T("Version"), LVCFMT_RIGHT, 60, 0); | |
mPathsListCtrl.InsertColumn(1, _T("Path"), LVCFMT_LEFT, 386, 0); | |
mJavaFinder->findJavaPaths(&mPaths); | |
fillPathsList(); | |
adjustButtons(); | |
return TRUE; // return TRUE unless you set the focus to a control | |
} | |
// If you add a minimize button to your dialog, you will need the code below | |
// to draw the icon. For MFC applications using the document/view model, | |
// this is automatically done for you by the framework. | |
// [Note: MFC boilerplate, keep as-is] | |
void CFindJava2Dlg::OnPaint() { | |
if (IsIconic()) { | |
CPaintDC dc(this); // device context for painting | |
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); | |
// Center icon in client rectangle | |
int cxIcon = GetSystemMetrics(SM_CXICON); | |
int cyIcon = GetSystemMetrics(SM_CYICON); | |
CRect rect; | |
GetClientRect(&rect); | |
int x = (rect.Width() - cxIcon + 1) / 2; | |
int y = (rect.Height() - cyIcon + 1) / 2; | |
// Draw the icon | |
dc.DrawIcon(x, y, m_hIcon); | |
} else { | |
CDialog::OnPaint(); | |
} | |
} | |
// The system calls this function to obtain the cursor to display while the user drags | |
// the minimized window. [Note: MFC boilerplate, keep as-is] | |
HCURSOR CFindJava2Dlg::OnQueryDragIcon() { | |
return static_cast<HCURSOR>(m_hIcon); | |
} | |
// Button add has been pressed; use file dialog and add path if it's a valid java.exe | |
void CFindJava2Dlg::OnBnClickedButtonAdd() { | |
CFileDialog fileDlg( | |
TRUE, // true=open dialog, false=save-as dialog | |
_T("exe"), // lpszDefExt | |
_T("java.exe"), // lpszFileName | |
OFN_FILEMUSTEXIST || OFN_PATHMUSTEXIST, | |
NULL, // lpszFilter | |
this); // pParentWnd | |
if (fileDlg.DoModal() == IDOK) { | |
CString path = fileDlg.GetPathName(); | |
CJavaPath javaPath; | |
if (!mJavaFinder->checkJavaPath(path, &javaPath)) { | |
CString msg; | |
if (javaPath.mVersion > 0) { | |
msg.Format(_T("Insufficient Java Version found: expected %s, got %s"), | |
CJavaPath(mJavaFinder->getMinVersion(), CPath()).getVersion(), | |
javaPath.getVersion()); | |
} else { | |
msg.Format(_T("No valid Java Version found for %s"), path); | |
} | |
AfxMessageBox(msg, MB_OK); | |
} else { | |
if (mPaths.find(javaPath) == mPaths.end()) { | |
// Path isn't known yet so add it and refresh the list. | |
mPaths.insert(javaPath); | |
fillPathsList(); | |
} | |
// Select item in list and set mSelectedIndex | |
selectPath(-1 /*index*/, &javaPath); | |
} | |
} | |
} | |
// An item in the list has been selected, select checkmark and set mSelectedIndex. | |
void CFindJava2Dlg::OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult) { | |
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); | |
int index = pNMItemActivate->iItem; | |
selectPath(index, nullptr); | |
*pResult = TRUE; | |
} | |
// An item in the list has changed, toggle checkmark as needed. | |
void CFindJava2Dlg::OnLvnItemchangedPathList(NMHDR *pNMHDR, LRESULT *pResult) { | |
*pResult = FALSE; | |
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); | |
if ((pNMLV->uChanged & LVIF_STATE) != 0) { | |
// Item's state has changed. Check the selection to see if it needs to be adjusted. | |
int index = pNMLV->iItem; | |
UINT oldState = pNMLV->uOldState; | |
UINT newState = pNMLV->uNewState; | |
if ((oldState & LVIS_STATEIMAGEMASK) != 0 || (newState & LVIS_STATEIMAGEMASK) != 0) { | |
// Checkbox uses the STATEIMAGE: 1 for unchecked, 2 for checked. | |
// Checkbox is checked when (old/new-state & state-image-mask) == INDEXTOSTATEIMAGEMASK(2). | |
bool oldChecked = (oldState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2); | |
bool newChecked = (newState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2); | |
if (oldChecked && !newChecked && index == mSelectedIndex) { | |
mSelectedIndex = -1; | |
adjustButtons(); | |
} else if (!oldChecked && newChecked && index != mSelectedIndex) { | |
// Uncheck any checked rows if any | |
for (int n = mPathsListCtrl.GetItemCount() - 1; n >= 0; --n) { | |
if (n != index && mPathsListCtrl.GetCheck(n)) { | |
mPathsListCtrl.SetCheck(n, FALSE); | |
} | |
} | |
mSelectedIndex = index; | |
adjustButtons(); | |
} | |
// We handled this case, don't dispatch it further | |
*pResult = TRUE; | |
} | |
} | |
} | |
// ----- | |
const CJavaPath& CFindJava2Dlg::getSelectedPath() { | |
int i = 0; | |
for (const CJavaPath &p : mPaths) { | |
if (i == mSelectedIndex) { | |
return p; | |
} | |
++i; | |
} | |
return CJavaPath::sEmpty; | |
} | |
void CFindJava2Dlg::fillPathsList() { | |
mPathsListCtrl.DeleteAllItems(); | |
int index = 0; | |
for (const CJavaPath& pv : mPaths) { | |
mPathsListCtrl.InsertItem(index, pv.getVersion()); // column 0 = version | |
mPathsListCtrl.SetItemText(index, COL_PATH, pv.mPath); // column 1 = path | |
mPathsListCtrl.SetCheck(index, mSelectedIndex == index); | |
++index; | |
} | |
} | |
// Checks the given index if valid. Unchecks all other items. | |
// | |
// If index >= 0, it is used to select that item from the ListControl. | |
// Otherwise if path != nullptr, it is used to find the item and select it. | |
// | |
// Side effect: in both cases, mSelectedIndex is set to the matching index or -1. | |
// | |
// If index is invalid and path isn't in the mPaths list, all items are unselected | |
// so calling this with (0, nullptr) will clear the current selection. | |
void CFindJava2Dlg::selectPath(int index, const CJavaPath *path) { | |
const CJavaPath *foundPath; | |
// If index is not defined, find the given path in the internal list. | |
// If path is not defined, find its index in the internal list. | |
int i = 0; | |
int n = mPathsListCtrl.GetItemCount(); | |
for (const CJavaPath &p : mPaths) { | |
if (index < 0 && path != nullptr && p == *path) { | |
index = i; | |
foundPath = path; | |
} else if (index == i) { | |
foundPath = &p; | |
} | |
// uncheck any marked path | |
if (i != index && i < n && mPathsListCtrl.GetCheck(i)) { | |
mPathsListCtrl.SetCheck(i, FALSE); | |
} | |
++i; | |
} | |
mSelectedIndex = index; | |
if (index >= 0 && index <= n) { | |
mPathsListCtrl.SetCheck(index, TRUE); | |
} | |
adjustButtons(); | |
} | |
void CFindJava2Dlg::adjustButtons() { | |
int n = mPathsListCtrl.GetItemCount(); | |
mOkButton.EnableWindow(mSelectedIndex >= 0 && mSelectedIndex < n); | |
} |