/* * 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); }