diff options
Diffstat (limited to 'CPP/7zip/UI/FileManager/BrowseDialog.cpp')
-rwxr-xr-x | CPP/7zip/UI/FileManager/BrowseDialog.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp new file mode 100755 index 00000000..602b12f3 --- /dev/null +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -0,0 +1,514 @@ +// 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 |