/*
* Copyright (C) 2001-2006 Jacek Sieka, arnetheduck on gmail point com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Automatic Directory Listing Search
* Henrik Engstrm, henrikengstrom at home se
*/
#include "stdafx.h"
#include "Resource.h"
#include "../client/DCPlusPlus.h"
#include "../client/Client.h"
#include "ADLSearchFrame.h"
#include "AdlsProperties.h"
#include "LineDlg.h"
#include "../client/version.h"
int ADLSearchFrame::columnIndexes[] = {
COLUMN_ACTIVE_SEARCH_STRING,
COLUMN_SOURCE_TYPE,
COLUMN_DEST_DIR,
COLUMN_MIN_FILE_SIZE,
COLUMN_MAX_FILE_SIZE
};
int ADLSearchFrame::columnSizes[] = {
120,
90,
90,
90,
90
};
static ResourceManager::Strings columnNames[] = {
ResourceManager::ACTIVE_SEARCH_STRING,
ResourceManager::SOURCE_TYPE,
ResourceManager::DESTINATION,
ResourceManager::MIN_SIZE,
ResourceManager::MAX_SIZE,
};
// Frame creation
LRESULT ADLSearchFrame::onCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Create status bar
CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP);
ctrlStatus.Attach(m_hWndStatusBar);
int w[1] = { 0 };
ctrlStatus.SetParts(1, w);
// Create list control
ctrlList.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL | LVS_REPORT | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE, IDC_ADLLIST);
listContainer.SubclassWindow(ctrlList.m_hWnd);
// Ev. set full row select
DWORD styles = LVS_EX_LABELTIP | LVS_EX_CHECKBOXES | LVS_EX_HEADERDRAGDROP;
if (BOOLSETTING(FULL_ROW_SELECT))
styles |= LVS_EX_FULLROWSELECT;
if (BOOLSETTING(SHOW_INFOTIPS))
styles |= LVS_EX_INFOTIP;
if (BOOLSETTING(HIGHLIGHT_MOUSEOVER))
styles |= LVS_EX_UNDERLINEHOT | LVS_EX_ONECLICKACTIVATE;
if(!(WinUtil::getOsMajor() >= 5 && WinUtil::getOsMinor() >= 1 //WinXP & WinSvr2003
|| WinUtil::getOsMajor() >= 6 )) //Vista
{
styles |= 0x00010000;
}
ctrlList.SetExtendedListViewStyle(styles);
// Set background color
ctrlList.SetBkColor(WinUtil::bgColor);
ctrlList.SetTextBkColor(WinUtil::bgColor);
ctrlList.SetTextColor(WinUtil::textColor);
ctrlList.SetFont(WinUtil::font);
// Create listview columns
WinUtil::splitTokens(columnIndexes, SETTING(ADLSEARCHFRAME_ORDER), COLUMN_LAST);
WinUtil::splitTokens(columnSizes, SETTING(ADLSEARCHFRAME_WIDTHS), COLUMN_LAST);
for(int j = 0; j < COLUMN_LAST; j++)
{
int fmt = LVCFMT_LEFT;
ctrlList.InsertColumn(j, CTSTRING_I(columnNames[j]), fmt, columnSizes[j], j);
}
ctrlList.SetColumnOrderArray(COLUMN_LAST, columnIndexes);
// Create buttons
ctrlAdd.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_ADD);
ctrlAdd.SetWindowText(CTSTRING(NEW));
ctrlAdd.SetFont(WinUtil::font);
ctrlEdit.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_EDIT);
ctrlEdit.SetWindowText(CTSTRING(PROPERTIES));
ctrlEdit.SetFont(WinUtil::font);
ctrlRemove.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_REMOVE);
ctrlRemove.SetWindowText(CTSTRING(REMOVE));
ctrlRemove.SetFont(WinUtil::font);
ctrlMoveUp.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_MOVE_UP);
ctrlMoveUp.SetWindowText(CTSTRING(MOVE_UP));
ctrlMoveUp.SetFont(WinUtil::font);
ctrlMoveDown.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_MOVE_DOWN);
ctrlMoveDown.SetWindowText(CTSTRING(MOVE_DOWN));
ctrlMoveDown.SetFont(WinUtil::font);
ctrlHelp.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON , 0, IDC_HELP_FAQ);
ctrlHelp.SetWindowText(CTSTRING(MENU_HELP));
ctrlHelp.SetFont(WinUtil::font);
// iDC++
ctrlFind.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
BS_PUSHBUTTON, 0, IDC_FIND);
ctrlFind.SetWindowText(CTSTRING(FIND));
ctrlFind.SetFont(WinUtil::systemFont);
// iDC++
// Create context menu
contextMenu.CreatePopupMenu();
contextMenu.AppendMenu(MF_STRING, IDC_ADD, CTSTRING(NEW));
contextMenu.AppendMenu(MF_STRING, IDC_REMOVE, CTSTRING(REMOVE));
contextMenu.AppendMenu(MF_STRING, IDC_EDIT, CTSTRING(PROPERTIES));
SettingsManager::getInstance()->addListener(this);
// Load all searches
LoadAll();
WinUtil::SetIcon(m_hWnd, _T("ADLSearch.ico")); // McDC EXTENSION 17
bHandled = FALSE;
return TRUE;
}
// Close window
LRESULT ADLSearchFrame::onClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
if(!closed) {
ADLSearchManager::getInstance()->Save();
SettingsManager::getInstance()->removeListener(this);
closed = true;
WinUtil::setButtonPressed(IDC_FILE_ADL_SEARCH, false);
PostMessage(WM_CLOSE);
return 0;
} else {
WinUtil::saveHeaderOrder(ctrlList, SettingsManager::ADLSEARCHFRAME_ORDER,
SettingsManager::ADLSEARCHFRAME_WIDTHS, COLUMN_LAST, columnIndexes, columnSizes);
bHandled = FALSE;
return 0;
}
}
// Recalculate frame control layout
void ADLSearchFrame::UpdateLayout(BOOL bResizeBars /* = TRUE */)
{
RECT rect;
GetClientRect(&rect);
// Position bars and offset their dimensions
UpdateBarsPosition(rect, bResizeBars);
if(ctrlStatus.IsWindow())
{
CRect sr;
int w[2];
ctrlStatus.GetClientRect(sr);
w[1] = sr.right - 16;
w[0] = max(w[1] - 100, 0);
ctrlStatus.SetParts(2, w);
ctrlStatus.SetText(1, Text::toT(Util::toString(ADLSearchManager::getInstance()->collection.size()) + ' ' + STRING(ITEMS)).c_str());
}
// Position list control
CRect rc = rect;
rc.top += 2;
rc.bottom -= 28;
ctrlList.MoveWindow(rc);
// Position buttons
const long bwidth = 90;
const long bspace = 10;
rc = rect;
rc.bottom -= 2;
rc.top = rc.bottom - 22;
rc.left = 2;
rc.right = rc.left + bwidth;
ctrlAdd.MoveWindow(rc);
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlEdit.MoveWindow(rc);
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlRemove.MoveWindow(rc);
rc.left += bspace;
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlMoveUp.MoveWindow(rc);
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlMoveDown.MoveWindow(rc);
// iDC++
rc.left += bspace;
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlFind.MoveWindow(rc);
// iDC++
rc.left += bspace;
rc.left += bwidth + 2;
rc.right = rc.left + bwidth;
ctrlHelp.MoveWindow(rc);
}
// Keyboard shortcuts
LRESULT ADLSearchFrame::onChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
switch(wParam)
{
case VK_INSERT:
PostMessage(WM_COMMAND, IDC_ADD, 0);
break;
case VK_DELETE:
PostMessage(WM_COMMAND, IDC_REMOVE, 0);
break;
case VK_RETURN:
PostMessage(WM_COMMAND, IDC_EDIT, 0);
break;
default:
bHandled = FALSE;
}
return 0;
}
LRESULT ADLSearchFrame::onContextMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
if(reinterpret_cast<HWND>(wParam) == ctrlList) {
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if(pt.x == -1 && pt.y == -1) {
WinUtil::getContextMenuPos(ctrlList, pt);
}
int status = ctrlList.GetSelectedCount() > 0 ? MFS_ENABLED : MFS_GRAYED;
contextMenu.EnableMenuItem(IDC_EDIT, status);
contextMenu.EnableMenuItem(IDC_REMOVE, status);
contextMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, m_hWnd);
return TRUE;
}
bHandled = FALSE;
return FALSE;
}
// Add new search
LRESULT ADLSearchFrame::onAdd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// Invoke edit dialog with fresh search
ADLSearch search;
ADLSProperties dlg(&search);
if(dlg.DoModal((HWND)*this) == IDOK)
{
// Add new search to the end or if selected, just before
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
for(ADLSearchManager::SearchCollection::iterator x = collection.begin(); x != collection.end(); ++x) {
ADLSearch& searched = *x;
if(searched.searchString.size() == 0) {
continue;
}
if(searched.searchString == search.searchString) {
if(MessageBox(CTSTRINGEX(ADLS_EXISTS), _T(APPNAME) _T(" ") _T(McDCVERSIONSTRING) _T(" [DC++ ") _T(VERSIONSTRING) _T("]"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES) {
break;
} else {
return 0;
}
}
}
int i = ctrlList.GetNextItem(-1, LVNI_SELECTED);
if(i < 0)
{
// Add to end
collection.push_back(search);
i = collection.size() - 1;
}
else
{
// Add before selection
collection.insert(collection.begin() + i, search);
}
// Update list control
int j = i;
while(j < (int)collection.size())
{
UpdateSearch(j++);
}
ctrlList.EnsureVisible(i, FALSE);
UpdateLayout();
}
return 0;
}
// Edit existing search
LRESULT ADLSearchFrame::onEdit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// Get selection info
int i = ctrlList.GetNextItem(-1, LVNI_SELECTED);
if(i < 0)
{
// Nothing selected
return 0;
}
// Edit existing
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
ADLSearch search = collection[i];
// Invoke dialog with selected search
ADLSProperties dlg(&search);
if(dlg.DoModal((HWND)*this) == IDOK)
{
for(ADLSearchManager::SearchCollection::iterator x = collection.begin(); x != collection.end(); ++x) {
ADLSearch& searched = *x;
if(searched.searchString.size() == 0) {
continue;
}
if(searched.searchString == search.searchString) {
if(MessageBox(CTSTRINGEX(ADLS_EXISTS), _T(APPNAME) _T(" ") _T(McDCVERSIONSTRING) _T(" [DC++ ") _T(VERSIONSTRING) _T("]"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES) {
break;
} else {
return 0;
}
}
}
// Update search collection
collection[i] = search;
// Update list control
UpdateSearch(i);
}
return 0;
}
// Remove searches
LRESULT ADLSearchFrame::onRemove(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
// Loop over all selected items
int i;
while((i = ctrlList.GetNextItem(-1, LVNI_SELECTED)) >= 0)
{
collection.erase(collection.begin() + i);
ctrlList.DeleteItem(i);
}
UpdateLayout();
return 0;
}
// Help
LRESULT ADLSearchFrame::onHelpButton(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
HtmlHelp(m_hWnd, WinUtil::getHelpFile().c_str(), HH_HELP_CONTEXT, IDR_ADLSEARCH);
return 0;
}
LRESULT ADLSearchFrame::onHelpKey(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
HtmlHelp(m_hWnd, WinUtil::getHelpFile().c_str(), HH_HELP_CONTEXT, IDR_ADLSEARCH);
return 0;
}
// Move selected entries up one step
LRESULT ADLSearchFrame::onMoveUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
// Get selection
vector<int> sel;
int i = -1;
while((i = ctrlList.GetNextItem(i, LVNI_SELECTED)) >= 0)
{
sel.push_back(i);
}
if(sel.size() < 1)
{
return 0;
}
// Find out where to insert
int i0 = sel[0];
if(i0 > 0)
{
i0 = i0 - 1;
}
// Backup selected searches
ADLSearchManager::SearchCollection backup;
for(i = 0; i < (int)sel.size(); ++i)
{
backup.push_back(collection[sel[i]]);
}
// Erase selected searches
for(i = sel.size() - 1; i >= 0; --i)
{
collection.erase(collection.begin() + sel[i]);
}
// Insert (grouped together)
for(i = 0; i < (int)sel.size(); ++i)
{
collection.insert(collection.begin() + i0 + i, backup[i]);
}
// Update UI
LoadAll();
// Restore selection
for(i = 0; i < (int)sel.size(); ++i)
{
ctrlList.SetItemState(i0 + i, LVNI_SELECTED, LVNI_SELECTED);
}
return 0;
}
// Move selected entries down one step
LRESULT ADLSearchFrame::onMoveDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
// Get selection
vector<int> sel;
int i = -1;
while((i = ctrlList.GetNextItem(i, LVNI_SELECTED)) >= 0)
{
sel.push_back(i);
}
if(sel.size() < 1)
{
return 0;
}
// Find out where to insert
int i0 = sel[sel.size() - 1] + 2;
if(i0 > (int)collection.size())
{
i0 = collection.size();
}
// Backup selected searches
ADLSearchManager::SearchCollection backup;
for(i = 0; i < (int)sel.size(); ++i)
{
backup.push_back(collection[sel[i]]);
}
// Erase selected searches
for(i = sel.size() - 1; i >= 0; --i)
{
collection.erase(collection.begin() + sel[i]);
if(i < i0)
{
i0--;
}
}
// Insert (grouped together)
for(i = 0; i < (int)sel.size(); ++i)
{
collection.insert(collection.begin() + i0 + i, backup[i]);
}
// Update UI
LoadAll();
// Restore selection
for(i = 0; i < (int)sel.size(); ++i)
{
ctrlList.SetItemState(i0 + i, LVNI_SELECTED, LVNI_SELECTED);
}
ctrlList.EnsureVisible(i0, FALSE);
return 0;
}
// Clicked 'Active' check box
LRESULT ADLSearchFrame::onItemChanged(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
NMITEMACTIVATE* item = (NMITEMACTIVATE*)pnmh;
if((item->uChanged & LVIF_STATE) == 0)
return 0;
if((item->uOldState & INDEXTOSTATEIMAGEMASK(0xf)) == 0)
return 0;
if((item->uNewState & INDEXTOSTATEIMAGEMASK(0xf)) == 0)
return 0;
if(item->iItem >= 0)
{
// Set new active status check box
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
ADLSearch& search = collection[item->iItem];
search.isActive = (ctrlList.GetCheckState(item->iItem) != 0);
}
return 0;
}
// Double-click on list control
LRESULT ADLSearchFrame::onDoubleClickList(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
NMITEMACTIVATE* item = (NMITEMACTIVATE*)pnmh;
if(item->iItem >= 0) {
// Treat as onEdit command
PostMessage(WM_COMMAND, IDC_EDIT, 0);
} else if(item->iItem == -1) {
PostMessage(WM_COMMAND, IDC_ADD, 0);
}
return 0;
}
// Load all searches from manager
void ADLSearchFrame::LoadAll()
{
// Clear current contents
ctrlList.DeleteAllItems();
// Load all searches
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
for(unsigned long l = 0; l < collection.size(); l++)
{
UpdateSearch(l, FALSE);
}
}
// Update a specific search item
void ADLSearchFrame::UpdateSearch(int index, BOOL doDelete)
{
ADLSearchManager::SearchCollection& collection = ADLSearchManager::getInstance()->collection;
// Check args
if(index >= (int)collection.size())
{
return;
}
ADLSearch& search = collection[index];
// Delete from list control
if(doDelete)
{
ctrlList.DeleteItem(index);
}
// Generate values
TStringList line;
tstring fs;
line.push_back(Text::toT(search.searchString));
line.push_back(search.SourceTypeToDisplayString(search.sourceType));
line.push_back(Text::toT(search.destDir));
fs = _T("");
if(search.minFileSize >= 0)
{
fs = Text::toT(Util::toString(search.minFileSize));
fs += _T(" ");
fs += search.SizeTypeToDisplayString(search.typeFileSize);
}
line.push_back(fs);
fs = _T("");
if(search.maxFileSize >= 0)
{
fs = Text::toT(Util::toString(search.maxFileSize));
fs += _T(" ");
fs += search.SizeTypeToDisplayString(search.typeFileSize);
}
line.push_back(fs);
// Insert in list control
ctrlList.insert(index, line);
// Update 'Active' check box
ctrlList.SetCheckState(index, search.isActive);
}
void ADLSearchFrame::on(SettingsManagerListener::Save, SimpleXML* /*xml*/) throw() {
bool refresh = false;
if(ctrlList.GetBkColor() != WinUtil::bgColor) {
ctrlList.SetBkColor(WinUtil::bgColor);
ctrlList.SetTextBkColor(WinUtil::bgColor);
refresh = true;
}
if(ctrlList.GetTextColor() != WinUtil::textColor) {
ctrlList.SetTextColor(WinUtil::textColor);
refresh = true;
}
if(refresh == true) {
RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}
LRESULT ADLSearchFrame::onCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)pnmh;
switch(cd->nmcd.dwDrawStage) {
case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT: {
if(BOOLSETTING(COLOR_LINES)) {
if((int)cd->nmcd.dwItemSpec%2 == 0) {
cd->clrTextBk = SETTING(COLOR_IN_LINES);
return CDRF_NEWFONT;
}
}
}
default: return CDRF_DODEFAULT;
}
}
LRESULT ADLSearchFrame::onFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
// Prompt for substring to find
LineDlg dlg;
dlg.title = TSTRING(SEARCH_FOR_FILE);
dlg.description = TSTRING(ENTER_SEARCH_STRING);
dlg.line = Util::emptyStringT;
if(dlg.DoModal() != IDOK)
return 0;
tstring findStr = dlg.line;
if(findStr.empty())
return 0;
int n = ctrlList.find(findStr, -1, false);
if(n != -1) {
ctrlList.SetItemState(n, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED);
ctrlList.EnsureVisible(n, FALSE);
} else {
MessageBox(CTSTRING(NO_MATCHES), CTSTRING(SEARCH_FOR_FILE));
}
return 0;
}
/**
* @file
* $Id: ADLSearchFrame.cpp 110 2006-11-02 20:45:59Z crakter $
*/