#include "stdafx.h" #include "ShortcutDlg.h" #include "PluginInterface.h" #include "resource.h" #include "MenuManager.h" #include "Notepad_plus_msgs.h" ShortcutDlg::ShortcutDlg(HINSTANCE hInst, NppData& nppData, const TCHAR *scriptDirAppend) : m_hTree(NULL), m_hListMenuItems(NULL), m_hListToolbarItems(NULL), m_hComboInitialisation(NULL), m_hImageList(NULL), m_hDefaultImageIndex(0), m_hIcons(NULL), m_iconFolderOpen(0), m_iconFolderClosed(0), m_iconPython(0), m_toolbarItemCount(0), m_menuItemCount(0), m_toolbarColumnWidth(100), m_menuItemColumnWidth(100), m_currentScript(NULL) { Window::init(hInst, nppData._nppHandle); TCHAR temp[MAX_PATH]; ::SendMessage(nppData._nppHandle, NPPM_GETPLUGINSCONFIGDIR, MAX_PATH, reinterpret_cast(temp)); m_userScriptDir = temp; m_userScriptDir.append(scriptDirAppend); ::SendMessage(nppData._nppHandle, NPPM_GETNPPDIRECTORY, MAX_PATH, reinterpret_cast(temp)); m_machineScriptDir = temp; m_machineScriptDir.append(_T("\\plugins")); m_machineScriptDir.append(scriptDirAppend); } void ShortcutDlg::doDialog() { if (!isCreated()) { create(IDD_SCRIPTCONFIG); } clearScripts(); if (BST_CHECKED == ::SendMessage(::GetDlgItem(_hSelf, IDC_RADMACHINE), BM_GETCHECK, 0, 0)) { populateMachineScripts(); } else { populateUserScripts(); } populateCurrentItems(); nonScriptSelected(); goToCenter(); } BOOL CALLBACK ShortcutDlg::run_dlgProc(HWND /* hWnd */, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_INITDIALOG: onInitDialog(); return TRUE; case WM_COMMAND: switch(wParam) { case IDOK: saveConfig(); MenuManager::getInstance()->reconfigure(); //lint -fallthrough case IDCANCEL: display(false); return TRUE; case IDC_RADMACHINE: populateMachineScripts(); break; case IDC_RADUSER: populateUserScripts(); break; case IDC_MENUADD: addMenuItem(); break; case IDC_MENUREMOVE: removeMenuItem(); break; case IDC_TOOLBARADD: addToolbarItem(); break; case IDC_TOOLBARREMOVE: removeToolbarItem(); break; case IDC_TOOLBARSETICON: toolbarSetIcon(); break; default: break; } break; case WM_NOTIFY: { LPNMHDR hdr = reinterpret_cast(lParam); switch(hdr->idFrom) { case IDC_FILETREE: { switch (hdr->code) { case TVN_GETDISPINFO: { LPNMTVDISPINFO lptvdi = reinterpret_cast(lParam); int imageIndex; if (lptvdi->item.mask & (TVIF_IMAGE |TVIF_SELECTEDIMAGE)) { if (lptvdi->item.state & TVIS_EXPANDED) { imageIndex = m_iconFolderOpen; } else { // a non-NULL lParam means it's a python file (with a full path) if (lptvdi->item.lParam) imageIndex = m_iconPython; else imageIndex = m_iconFolderClosed; } if (lptvdi->item.state & TVIS_SELECTED) { lptvdi->item.iSelectedImage = imageIndex; lptvdi->item.mask = TVIF_SELECTEDIMAGE; } else { lptvdi->item.iImage = imageIndex; lptvdi->item.mask = TVIF_IMAGE; } } return TRUE; } // end case TVN_GETDISPINFO case TVN_SELCHANGED: { LPNMTREEVIEW pnmtv = reinterpret_cast(lParam); if (pnmtv->itemNew.lParam) { scriptSelected(); m_currentScript = reinterpret_cast(pnmtv->itemNew.lParam); } else { nonScriptSelected(); m_currentScript = NULL; } } break; default: // Other notifications we can ignore break; } // end switch (hdr->code) } // end case IDC_FILETREE break; default: // Other windows we can ignore break; } // end switch hdr->idFrom } // end case WM_NOTIFY break; default: // Other messages we can ignore break; } // end switch (message) return FALSE; // ::DefWindowProc(hWnd, message, wParam, lParam); } void ShortcutDlg::onInitDialog() { // Set the radio button to default to USER SCRIPTS ::SendMessage(GetDlgItem(_hSelf, IDC_RADUSER), BM_SETCHECK, BST_CHECKED, 0); ::SendMessage(GetDlgItem(_hSelf, IDC_RADMACHINE), BM_SETCHECK, BST_UNCHECKED, 0); m_hTree = ::GetDlgItem(_hSelf, IDC_FILETREE); m_hListMenuItems = ::GetDlgItem(_hSelf, IDC_MENUITEMLIST); m_hListToolbarItems = ::GetDlgItem(_hSelf, IDC_TOOLBARITEMLIST2); m_hComboInitialisation = ::GetDlgItem(_hSelf, IDC_COMBOINITIALISATION); InitCommonControls(); HICON hIcon; // handle to icon // Create a masked image list large enough to hold the icons. m_hIcons = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 3, 0); // Load the icon resources, and add the icons to the image list. hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDERCLOSED)); m_iconFolderClosed = ImageList_AddIcon(m_hIcons, hIcon); hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_FOLDEROPEN)); m_iconFolderOpen = ImageList_AddIcon(m_hIcons, hIcon); hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_PYTHON)); m_iconPython = ImageList_AddIcon(m_hIcons, hIcon); ::SendMessage(m_hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, reinterpret_cast(m_hIcons)); ::SendMessage(m_hTree, TVM_SETIMAGELIST, TVSIL_STATE, reinterpret_cast(m_hIcons)); m_hImageList = ImageList_Create(16, 16, ILC_MASK |ILC_COLOR32, 5, 1); HBITMAP hPython = static_cast(LoadImage(_hInst, MAKEINTRESOURCE(IDB_PYTHON), IMAGE_BITMAP, 0, 0, LR_COLOR | LR_LOADMAP3DCOLORS | LR_DEFAULTSIZE)); m_hDefaultImageIndex = ImageList_Add(m_hImageList, hPython, NULL); ListView_SetImageList(m_hListToolbarItems, m_hImageList, LVSIL_SMALL); LVCOLUMN lvCol; lvCol.cchTextMax = 10; lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; lvCol.iSubItem = 0; lvCol.pszText = _T("Script"); lvCol.fmt = LVCFMT_LEFT; RECT rect; ::GetClientRect(m_hListToolbarItems, &rect); m_toolbarColumnWidth = (size_t)((rect.right - rect.left) - 18); lvCol.cx = (int)m_toolbarColumnWidth; ListView_InsertColumn(m_hListToolbarItems, 0, &lvCol); ::GetClientRect(m_hListToolbarItems, &rect); m_menuItemColumnWidth = (size_t)(rect.right - rect.left); lvCol.cx = (int)m_menuItemColumnWidth; ListView_InsertColumn(m_hListMenuItems, 0, &lvCol); ListView_SetExtendedListViewStyle(m_hListToolbarItems, LVS_EX_FULLROWSELECT); ListView_SetExtendedListViewStyle(m_hListMenuItems, LVS_EX_FULLROWSELECT); ComboBox_AddString(m_hComboInitialisation, _T("LAZY")); ComboBox_AddString(m_hComboInitialisation, _T("ATSTARTUP")); } void ShortcutDlg::clearScripts() { TreeView_DeleteAllItems(m_hTree); m_itemList.erase(m_itemList.begin(), m_itemList.end()); } void ShortcutDlg::populateUserScripts() { clearScripts(); populateScripts(m_userScriptDir); } void ShortcutDlg::populateMachineScripts() { clearScripts(); populateScripts(m_machineScriptDir); } void ShortcutDlg::populateScripts(tstring dir, HTREEITEM parent /* = TVI_ROOT */) { WIN32_FIND_DATA findData; tstring searchPath(dir); searchPath.append(_T("\\*")); HANDLE hFound = FindFirstFile(searchPath.c_str(), &findData); BOOL found = (hFound != INVALID_HANDLE_VALUE) ? TRUE : FALSE; HTREEITEM lastItem = TVI_ROOT; while (found) { if (FILE_ATTRIBUTE_DIRECTORY == (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && _tcscmp(findData.cFileName, _T(".")) && _tcscmp(findData.cFileName, _T(".."))) { searchPath = dir; searchPath.append(_T("\\")); searchPath.append(findData.cFileName); lastItem = addTreeItem(parent, lastItem, NULL, findData.cFileName, true); populateScripts(searchPath, lastItem); } found = FindNextFile(hFound, &findData); } FindClose(hFound); searchPath = dir; searchPath.append(_T("\\*.py")); hFound = FindFirstFile(searchPath.c_str(), &findData); found = (hFound != INVALID_HANDLE_VALUE) ? TRUE : FALSE; while(found) { tstring fullFilename(dir); fullFilename.append(_T("\\")); fullFilename.append(findData.cFileName); size_t length = fullFilename.size() + 1; std::shared_ptr item(new TCHAR[length]); _tcscpy_s(item.get(), length, fullFilename.c_str()); m_itemList.push_back(item); lastItem = addTreeItem(parent, lastItem, item.get(), findData.cFileName, false); found = FindNextFile(hFound, &findData); } FindClose(hFound); } HTREEITEM ShortcutDlg::addTreeItem(HTREEITEM parent, HTREEITEM /* lastItem */, TCHAR *fullPath, TCHAR *text, bool isDirectory) { TV_INSERTSTRUCT tvInsert; tvInsert.hParent = parent; tvInsert.hInsertAfter = TVI_SORT; tvInsert.item.mask = TVIF_TEXT | TVIF_PARAM |TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvInsert.item.lParam = reinterpret_cast(fullPath); tvInsert.item.pszText = text; tvInsert.item.iImage = isDirectory ? I_IMAGECALLBACK : m_iconPython; tvInsert.item.iSelectedImage = isDirectory ? I_IMAGECALLBACK : m_iconPython; return (HTREEITEM)SendMessage(m_hTree, TVM_INSERTITEM, 0, reinterpret_cast(&tvInsert)); } void ShortcutDlg::scriptSelected() { ::EnableWindow(GetDlgItem(_hSelf, IDC_MENUADD), TRUE); ::EnableWindow(GetDlgItem(_hSelf, IDC_TOOLBARADD), TRUE); } void ShortcutDlg::nonScriptSelected() { ::EnableWindow(GetDlgItem(_hSelf, IDC_MENUADD), FALSE); ::EnableWindow(GetDlgItem(_hSelf, IDC_TOOLBARADD), FALSE); } void ShortcutDlg::addMenuItem() { addMenuItem(m_currentScript); m_menuItems.push_back(m_currentScript); } void ShortcutDlg::addMenuItem(const TCHAR *item) { LVITEM lvItem; lvItem.stateMask = LVIS_SELECTED; lvItem.state = 0; lvItem.iItem = (int)(m_menuItemCount++); lvItem.mask = LVIF_TEXT; lvItem.iSubItem = 0; lvItem.state = 0; lvItem.stateMask = 0; TCHAR path[MAX_PATH]; _tcscpy_s(path, MAX_PATH, item); ::PathCompactPath(NULL, path, m_menuItemColumnWidth); lvItem.pszText = path; lvItem.cchTextMax = (int)_tcslen(path); ListView_InsertItem(m_hListMenuItems, &lvItem); } void ShortcutDlg::removeMenuItem() { int index = ListView_GetNextItem(m_hListMenuItems, -1, LVIS_SELECTED); if (index != -1) { ListView_DeleteItem(m_hListMenuItems, index); m_menuItems.erase(m_menuItems.begin() + index); } --m_menuItemCount; } void ShortcutDlg::addToolbarItem() { addToolbarItem(m_currentScript, NULL); m_toolbarItems.push_back(std::pair >(m_currentScript, std::pair(static_cast(NULL), _T("")))); } void ShortcutDlg::addToolbarItem(const TCHAR *item, HBITMAP hBitmap) { int imageIndex; if (NULL == hBitmap) { imageIndex = m_hDefaultImageIndex; } else { imageIndex = ImageList_Add(m_hImageList, hBitmap, NULL); } LVITEM lvItem; lvItem.stateMask = LVIS_SELECTED; lvItem.state = 0; lvItem.iItem = (int)(m_toolbarItemCount++); lvItem.mask = LVIF_TEXT | LVIF_IMAGE; lvItem.iSubItem = 0; lvItem.state = 0; lvItem.stateMask = 0; lvItem.iImage = imageIndex; TCHAR path[MAX_PATH]; _tcscpy_s(path, MAX_PATH, item); ::PathCompactPath(NULL, path, m_toolbarColumnWidth); lvItem.pszText = path; lvItem.cchTextMax = (int)_tcslen(path); ListView_InsertItem(m_hListToolbarItems, &lvItem); //int itemWidth = ListView_GetStringWidth(m_hListToolbarItems, item); //if (itemWidth > m_toolbarColumnWidth) //{ // ListView_SetColumnWidth(m_hListToolbarItems, 0, itemWidth + COLUMN_PADDING)); //} //::SendMessage(m_hListToolbarItems, LB_ADDSTRING, 0, reinterpret_cast(item)); } void ShortcutDlg::removeToolbarItem() { int index = ListView_GetNextItem(m_hListToolbarItems, -1, LVIS_SELECTED); if (index != -1) { ListView_DeleteItem(m_hListToolbarItems, index); m_toolbarItems.erase(m_toolbarItems.begin() + index); } --m_toolbarItemCount; } void ShortcutDlg::populateCurrentItems() { ListView_DeleteAllItems(m_hListMenuItems); ListView_DeleteAllItems(m_hListToolbarItems); ConfigFile* configFile = ConfigFile::getInstance(); configFile->refresh(); m_menuItemCount = 0; m_menuItems = configFile->getMenuItems(); for(ConfigFile::MenuItemsTD::iterator it = m_menuItems.begin(); it != m_menuItems.end(); ++it) { addMenuItem(it->c_str()); } m_toolbarItemCount = 0; m_toolbarItems = configFile->getToolbarItems(); for(ConfigFile::ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) { addToolbarItem(it->first.c_str(), it->second.first); } // Try to select the startup type, if it's not there, then just select the first if (CB_ERR == ComboBox_SelectString(m_hComboInitialisation, 0, configFile->getSetting(_T("STARTUP")).c_str())) { ComboBox_SetCurSel(m_hComboInitialisation, 0); } if (configFile->getSetting(_T("PREFERINSTALLEDPYTHON")) == _T("1")) { CheckDlgButton(_hSelf, IDC_CHECKPREFERINSTALLEDPYTHON, BST_CHECKED); } else { CheckDlgButton(_hSelf, IDC_CHECKPREFERINSTALLEDPYTHON, BST_UNCHECKED); } } void ShortcutDlg::saveConfig() { ConfigFile* configFile = ConfigFile::getInstance(); configFile->clearItems(); for (ConfigFile::MenuItemsTD::iterator it = m_menuItems.begin(); it != m_menuItems.end(); ++it) { configFile->addMenuItem(*it); } for (ConfigFile::ToolbarItemsTD::iterator it = m_toolbarItems.begin(); it != m_toolbarItems.end(); ++it) { configFile->addToolbarItem(it->first, it->second.second); } TCHAR startupBuffer[50]; ComboBox_GetText(m_hComboInitialisation, startupBuffer, 50); configFile->setSetting(_T("STARTUP"), startupBuffer); if (BST_CHECKED == IsDlgButtonChecked(_hSelf, IDC_CHECKPREFERINSTALLEDPYTHON)) { configFile->setSetting(_T("PREFERINSTALLEDPYTHON"), _T("1")); } else { configFile->setSetting(_T("PREFERINSTALLEDPYTHON"), _T("0")); } configFile->save(); } void ShortcutDlg::toolbarSetIcon() { int index = ListView_GetNextItem(m_hListToolbarItems, -1, LVIS_SELECTED); if (index != -1) { OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = _hSelf; tstring configDir(ConfigFile::getInstance()->getConfigDir()); configDir.append(_T("\\PythonScript\\icons")); ofn.lpstrInitialDir = configDir.c_str(); //ofn.lpstrFileTitle = "Choose filename for new script"; ofn.lpstrFile = new TCHAR[MAX_PATH]; ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = MAX_PATH; //lint -e840 Use of nul character in a string literal // This is how it's meant to be used. ofn.lpstrFilter = _T("Icons (*.ico, *.bmp)\0*.ico;*.bmp\0All Files (*.*)\0*.*\0"); //lint +e840 ofn.nFilterIndex = 1; ofn.Flags = OFN_FILEMUSTEXIST; if (GetOpenFileName(&ofn)) { ConfigFile::ToolbarItemsTD::iterator it = m_toolbarItems.begin() + index; it->second.first = static_cast(LoadImage(NULL, ofn.lpstrFile, IMAGE_BITMAP, 16, 16, LR_COLOR | LR_LOADFROMFILE)); it->second.second = ofn.lpstrFile; int imageIndex = ImageList_Add(m_hImageList, it->second.first, NULL); LVITEM lvItem; lvItem.mask = LVIF_IMAGE; lvItem.iItem = index; lvItem.iImage = imageIndex; ListView_SetItem(m_hListToolbarItems, &lvItem); } } }