Files
easy7zip/CPP/7zip/UI/FileManager/BrowseDialog.cpp
Igor Pavlov c99f3ebdd6 9.06 beta
2016-05-28 00:16:00 +01:00

515 lines
11 KiB
C++
Executable File

// BrowseDialog.cpp
#include "StdAfx.h"
#ifdef UNDER_CE
#include "Common/IntToString.h"
#include "Windows/PropVariantConversions.h"
#include "BrowseDialog.h"
#include "LangUtils.h"
#include "PropertyNameRes.h"
#ifndef _SFX
#include "RegistryUtils.h"
#endif
using namespace NWindows;
using namespace NFile;
using namespace NFind;
extern bool g_LVN_ITEMACTIVATE_Support;
static const int kParentIndex = -1;
#ifdef LANG
static CIDLangPair kIDLangPairs[] =
{
{ IDOK, 0x02000702 },
{ IDCANCEL, 0x02000710 }
};
#endif
static bool GetParentPath(const UString &path2, UString &dest, UString &focused)
{
UString path = path2;
dest.Empty();
if (path.IsEmpty())
return false;
if (path.Back() == WCHAR_PATH_SEPARATOR)
path.DeleteBack();
if (path.IsEmpty())
return false;
int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos < 0 || path.Back() == WCHAR_PATH_SEPARATOR)
return false;
focused = path.Mid(pos + 1);
dest = path.Left(pos + 1);
return true;
}
bool CBrowseDialog::OnInit()
{
#ifdef LANG
LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));
#endif
if (!Title.IsEmpty())
SetText(Title);
_list.Attach(GetItem(IDC_BROWSE_LIST));
#ifndef UNDER_CE
_list.SetUnicodeFormat(true);
#endif
#ifndef _SFX
if (ReadSingleClick())
_list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);
_showDots = ReadShowDots();
#endif
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_list.InsertColumn(0, LangStringSpec(IDS_PROP_NAME, 0x02000204), 100);
_list.InsertColumn(1, LangStringSpec(IDS_PROP_MTIME, 0x0200020C), 100);
{
LV_COLUMNW column;
column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
column.fmt = LVCFMT_RIGHT;
column.iSubItem = 2;
UString s = LangStringSpec(IDS_PROP_SIZE, 0x02000207);
column.pszText = (wchar_t *)(const wchar_t *)s;
_list.InsertColumn(2, &column);
// _list.InsertColumn(2, LangStringSpec(IDS_PROP_SIZE, 0x02000207), 100);
}
_list.InsertItem(0, L"12345678901234567");
_list.SetSubItem(0, 1, L"2009-09-09");
_list.SetSubItem(0, 2, L"9999 MB");
for (int i = 0; i < 3; i++)
_list.SetColumnWidthAuto(i);
_list.DeleteAllItems();
UString selectedName;
if (!FolderMode)
{
int pos = Path.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos >= 0 && Path.Back() != WCHAR_PATH_SEPARATOR)
{
selectedName = Path.Mid(pos + 1);
Path = Path.Left(pos + 1);
}
}
_ascending = true;
_sortIndex = 0;
NormalizeSize();
while (Reload(Path, selectedName) != S_OK)
{
UString parent;
if (!GetParentPath(Path, parent, selectedName))
break;
selectedName.Empty();
Path = parent;
}
return CModalDialog::OnInit();
}
bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
{
RECT rect;
GetClientRectOfItem(IDC_BROWSE_PARENT, rect);
mx = rect.left;
my = rect.top;
}
InvalidateRect(NULL);
{
RECT rect;
GetClientRectOfItem(IDC_BROWSE_PATH, rect);
MoveItem(IDC_BROWSE_PATH, rect.left, rect.top, xSize - mx - rect.left, RECT_SIZE_Y(rect));
}
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
MoveItem(IDCANCEL, x, y, bx1, by);
MoveItem(IDOK, x - mx - bx2, y, bx2, by);
{
RECT rect;
GetClientRectOfItem(IDC_BROWSE_LIST, rect);
_list.Move(rect.left, rect.top, xSize - mx - rect.left, y - my - rect.top);
}
return false;
}
static UString ConvertSizeToStringShort(UInt64 value)
{
wchar_t s[32];
wchar_t c = L'\0', c2 = L'\0';
if (value < (UInt64)10000)
{
c = L'\0';
c2 = L'\0';
}
else if (value < ((UInt64)10000 << 10))
{
value >>= 10;
c = L'K';
}
else if (value < ((UInt64)10000 << 20))
{
value >>= 20;
c = L'M';
}
else
{
value >>= 30;
c = L'G';
}
ConvertUInt64ToString(value, s);
int p = MyStringLen(s);
if (c != 0)
s[p++] = L' ';
s[p++] = c;
s[p++] = c2;
s[p++] = L'\0';
return s;
}
int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2)
{
if (lParam1 == kParentIndex) return -1;
if (lParam2 == kParentIndex) return 1;
const CFileInfoW &f1 = _files[(int)lParam1];
const CFileInfoW &f2 = _files[(int)lParam2];
bool isDir1 = f1.IsDir();
bool isDir2 = f2.IsDir();
if (isDir1 && !isDir2) return -1;
if (isDir2 && !isDir1) return 1;
int result = 0;
switch(_sortIndex)
{
case 0: result = f1.Name.CompareNoCase(f2.Name); break;
case 1: result = CompareFileTime(&f1.MTime, &f2.MTime); break;
case 2: result = MyCompare(f1.Size, f2.Size); break;
}
return _ascending ? result: (-result);
}
static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
{
if (lpData == NULL)
return 0;
return ((CBrowseDialog*)lpData)->CompareItems(lParam1, lParam2);
}
static HRESULT GetNormalizedError()
{
HRESULT errorCode = GetLastError();
return (errorCode == 0) ? 1 : errorCode;
}
HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)
{
CEnumeratorW enumerator(pathPrefix + L'*');
CObjectVector<CFileInfoW> files;
for (;;)
{
bool found;
CFileInfoW fi;
if (!enumerator.Next(fi, found))
return GetNormalizedError();
if (!found)
break;
files.Add(fi);
}
Path = pathPrefix;
_files = files;
SetItemText(IDC_BROWSE_PATH, Path);
_list.SetRedraw(false);
_list.DeleteAllItems();
if (!Path.IsEmpty() && Path.Back() != WCHAR_PATH_SEPARATOR)
Path += WCHAR_PATH_SEPARATOR;
LVITEMW item;
int index = 0;
int cursorIndex = -1;
#ifndef _SFX
if (_showDots)
{
UString itemName = L"..";
item.iItem = index;
if (selectedName.IsEmpty())
cursorIndex = item.iItem;
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
int subItem = 0;
item.iSubItem = subItem++;
item.lParam = kParentIndex;
item.pszText = (wchar_t *)(const wchar_t *)itemName;
item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, Path);
if (item.iImage < 0)
item.iImage = 0;
_list.InsertItem(&item);
_list.SetSubItem(index, subItem++, L"");
_list.SetSubItem(index, subItem++, L"");
index++;
}
#endif
for (int i = 0; i < _files.Size(); i++)
{
const CFileInfoW &fi = _files[i];
item.iItem = index;
if (fi.Name.CompareNoCase(selectedName) == 0)
cursorIndex = item.iItem;
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
int subItem = 0;
item.iSubItem = subItem++;
item.lParam = i;
item.pszText = (wchar_t *)(const wchar_t *)fi.Name;
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + fi.Name);
if (item.iImage < 0)
item.iImage = 0;
_list.InsertItem(&item);
{
FILETIME ft;
UString s;
if (FileTimeToLocalFileTime(&fi.MTime, &ft))
s = ConvertFileTimeToString(ft, false, false);
_list.SetSubItem(index, subItem++, s);
}
{
UString s;
if (!fi.IsDir())
s = ConvertSizeToStringShort(fi.Size);
_list.SetSubItem(index, subItem++, s);
}
index++;
}
if (_list.GetItemCount() > 0 && cursorIndex >= 0)
_list.SetItemState_FocusedSelected(cursorIndex);
_list.SortItems(CompareItems2, (LPARAM)this);
if (_list.GetItemCount() > 0 && cursorIndex < 0)
_list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
_list.EnsureVisible(_list.GetFocusedItem(), false);
_list.SetRedraw(true);
return S_OK;
}
HRESULT CBrowseDialog::Reload()
{
UString selectedCur;
int index = _list.GetNextSelectedItem(-1);
if (index >= 0)
{
int fileIndex = GetRealItemIndex(index);
if (fileIndex != kParentIndex)
selectedCur = _files[fileIndex].Name;
}
return Reload(Path, selectedCur);
}
void CBrowseDialog::OpenParentFolder()
{
UString parent, selected;
if (GetParentPath(Path, parent, selected))
Reload(parent, selected);
}
extern UString HResultToMessage(HRESULT errorCode);
bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
{
if (header->hwndFrom != _list)
return false;
switch(header->code)
{
case LVN_ITEMACTIVATE:
if (g_LVN_ITEMACTIVATE_Support)
{
OnItemEnter();
return true;
}
break;
case NM_DBLCLK:
case NM_RETURN: // probabably it's unused
if (!g_LVN_ITEMACTIVATE_Support)
{
OnItemEnter();
return true;
}
break;
case LVN_COLUMNCLICK:
{
int index = LPNMLISTVIEW(header)->iSubItem;
if (index == _sortIndex)
_ascending = !_ascending;
else
{
_ascending = (index == 0);
_sortIndex = index;
}
Reload();
return false;
}
case LVN_KEYDOWN:
{
LRESULT result;
bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result);
return boolResult;
}
}
return false;
}
bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result)
{
bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
result = 0;
switch(keyDownInfo->wVKey)
{
case VK_BACK:
OpenParentFolder();
return true;
case 'R':
if (ctrl)
{
Reload();
return true;
}
return false;
}
return false;
}
bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch(buttonID)
{
case IDC_BROWSE_PARENT:
OpenParentFolder();
return true;
}
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
void CBrowseDialog::ShowError(LPCWSTR s) { MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR); }
void CBrowseDialog::ShowSelectError()
{
ShowError(FolderMode ?
L"You must select some folder":
L"You must select some file");
}
void CBrowseDialog::FinishOnOK()
{
int index = _list.GetNextSelectedItem(-1);
if (index < 0)
{
if (!FolderMode)
{
ShowSelectError();
return;
}
}
else
{
int fileIndex = GetRealItemIndex(index);
if (fileIndex == kParentIndex)
{
OpenParentFolder();
return;
}
const CFileInfoW &file = _files[fileIndex];
if (file.IsDir() != FolderMode)
{
ShowSelectError();
return;
}
Path += file.Name;
}
End(IDOK);
}
void CBrowseDialog::OnItemEnter()
{
int index = _list.GetNextSelectedItem(-1);
if (index < 0)
return;
int fileIndex = GetRealItemIndex(index);
if (fileIndex == kParentIndex)
OpenParentFolder();
else
{
const CFileInfoW &file = _files[fileIndex];
if (!file.IsDir())
{
if (!FolderMode)
FinishOnOK();
else
ShowSelectError();
return;
}
HRESULT res = Reload(Path + file.Name + WCHAR_PATH_SEPARATOR, L"");
if (res != S_OK)
ShowError(HResultToMessage(res));
}
}
void CBrowseDialog::OnOK()
{
if (GetFocus() == _list)
{
OnItemEnter();
return;
}
FinishOnOK();
}
static bool MyBrowse(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath, bool folderMode)
{
CBrowseDialog dialog;
dialog.Title = title;
dialog.Path = initialFolder;
dialog.FolderMode = folderMode;
if (dialog.Create(owner) != IDOK)
return false;
resultPath = dialog.Path;
return true;
}
bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
{
return MyBrowse(owner, title, initialFolder, resultPath, true);
}
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR initialFolder, LPCWSTR, UString &resultPath)
{
return MyBrowse(owner, title, initialFolder, resultPath, false);
}
#endif