Home | History | Annotate | Download | only in src
      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