5 #include "../../../../C/Sort.h"
\r
7 #include "Common/StringConvert.h"
\r
9 #include "Windows/Menu.h"
\r
10 #include "Windows/PropVariant.h"
\r
11 #include "Windows/PropVariantConversions.h"
\r
13 #include "../../PropID.h"
\r
15 #include "resource.h"
\r
17 #include "LangUtils.h"
\r
19 #include "PropertyName.h"
\r
20 #include "RootFolder.h"
\r
22 using namespace NWindows;
\r
24 static int GetColumnAlign(PROPID propID, VARTYPE varType)
\r
45 return LVCFMT_RIGHT;
\r
54 return LVCFMT_CENTER;
\r
58 HRESULT CPanel::InitColumns()
\r
63 _listView.DeleteAllItems();
\r
64 _selectedStatusVector.Clear();
\r
71 if (_listViewInfo.SortIndex >= 0)
\r
72 sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID;
\r
74 sortID = _listViewInfo.SortID;
\r
76 _ascending = _listViewInfo.Ascending;
\r
78 _properties.Clear();
\r
80 _needSaveInfo = true;
\r
82 UInt32 numProperties;
\r
83 _folder->GetNumberOfProperties(&numProperties);
\r
85 for (i = 0; i < (int)numProperties; i++)
\r
91 RINOK(_folder->GetPropertyInfo(i, &name, &propID, &varType));
\r
93 if (propID == kpidIsDir)
\r
97 prop.Type = varType;
\r
99 prop.Name = GetNameOfProperty(propID, name);
\r
101 prop.IsVisible = true;
\r
103 _properties.Add(prop);
\r
105 // InitColumns2(sortID);
\r
108 if (!_listView.DeleteColumn(0))
\r
112 for (i = 0; i < _listViewInfo.Columns.Size(); i++)
\r
114 const CColumnInfo &columnInfo = _listViewInfo.Columns[i];
\r
115 int index = _properties.FindItemWithID(columnInfo.PropID);
\r
118 CItemProperty &item = _properties[index];
\r
119 item.IsVisible = columnInfo.IsVisible;
\r
120 item.Width = columnInfo.Width;
\r
121 if (columnInfo.IsVisible)
\r
122 item.Order = order++;
\r
126 for (i = 0; i < _properties.Size(); i++)
\r
128 CItemProperty &item = _properties[i];
\r
129 if (item.Order < 0)
\r
130 item.Order = order++;
\r
133 _visibleProperties.Clear();
\r
134 for (i = 0; i < _properties.Size(); i++)
\r
136 const CItemProperty &prop = _properties[i];
\r
137 if (prop.IsVisible)
\r
138 _visibleProperties.Add(prop);
\r
142 _sortID = kpidName;
\r
144 if (_listViewInfo.SortIndex >= 0)
\r
146 int sortIndex = _properties.FindItemWithID(sortID);
\r
147 if (sortIndex >= 0)
\r
148 _sortIndex = sortIndex;
\r
151 _sortID = _listViewInfo.SortID;
\r
153 for (i = 0; i < _visibleProperties.Size(); i++)
\r
160 void CPanel::InsertColumn(int index)
\r
162 const CItemProperty &prop = _visibleProperties[index];
\r
164 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER;
\r
165 column.cx = prop.Width;
\r
166 column.fmt = GetColumnAlign(prop.ID, prop.Type);
\r
167 column.iOrder = prop.Order;
\r
168 column.iSubItem = index;
\r
169 column.pszText = const_cast<wchar_t *>((const wchar_t *)prop.Name);
\r
170 _listView.InsertColumn(index, &column);
\r
173 HRESULT CPanel::RefreshListCtrl()
\r
175 return RefreshListCtrl(UString(), -1, true, UStringVector());
\r
178 int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
\r
181 void CPanel::GetSelectedNames(UStringVector &selectedNames)
\r
183 selectedNames.Clear();
\r
185 CRecordVector<UInt32> indices;
\r
186 GetSelectedItemsIndices(indices);
\r
187 selectedNames.Reserve(indices.Size());
\r
188 for (int i = 0; i < indices.Size(); i++)
\r
189 selectedNames.Add(GetItemRelPath(indices[i]));
\r
192 for (int i = 0; i < _listView.GetItemCount(); i++)
\r
194 const int kSize = 1024;
\r
195 WCHAR name[kSize + 1];
\r
198 item.pszText = name;
\r
199 item.cchTextMax = kSize;
\r
201 item.mask = LVIF_TEXT | LVIF_PARAM;
\r
202 if (!_listView.GetItem(&item))
\r
204 int realIndex = GetRealIndex(item);
\r
205 if (realIndex == kParentIndex)
\r
207 if (_selectedStatusVector[realIndex])
\r
208 selectedNames.Add(item.pszText);
\r
211 selectedNames.Sort();
\r
214 void CPanel::SaveSelectedState(CSelectedState &s)
\r
216 s.FocusedName.Empty();
\r
217 s.SelectedNames.Clear();
\r
218 s.FocusedItem = _listView.GetFocusedItem();
\r
220 if (s.FocusedItem >= 0)
\r
222 int realIndex = GetRealItemIndex(s.FocusedItem);
\r
223 if (realIndex != kParentIndex)
\r
224 s.FocusedName = GetItemRelPath(realIndex);
\r
226 const int kSize = 1024;
\r
227 WCHAR name[kSize + 1];
\r
229 item.iItem = focusedItem;
\r
230 item.pszText = name;
\r
231 item.cchTextMax = kSize;
\r
233 item.mask = LVIF_TEXT;
\r
234 if (_listView.GetItem(&item))
\r
235 focusedName = item.pszText;
\r
239 GetSelectedNames(s.SelectedNames);
\r
242 HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)
\r
244 bool selectFocused = s.SelectFocused;
\r
246 selectFocused = true;
\r
247 return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);
\r
250 HRESULT CPanel::RefreshListCtrlSaveFocused()
\r
252 CSelectedState state;
\r
253 SaveSelectedState(state);
\r
254 return RefreshListCtrl(state);
\r
257 void CPanel::SetFocusedSelectedItem(int index, bool select)
\r
259 UINT state = LVIS_FOCUSED;
\r
261 state |= LVIS_SELECTED;
\r
262 _listView.SetItemState(index, state, state);
\r
263 if (!_mySelectMode && select)
\r
265 int realIndex = GetRealItemIndex(index);
\r
266 if (realIndex != kParentIndex)
\r
267 _selectedStatusVector[realIndex] = true;
\r
271 HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,
\r
272 const UStringVector &selectedNames)
\r
274 _dontShowMode = false;
\r
275 LoadFullPathAndShow();
\r
276 // OutputDebugStringA("=======\n");
\r
277 // OutputDebugStringA("s1 \n");
\r
278 CDisableTimerProcessing timerProcessing(*this);
\r
280 if (focusedPos < 0)
\r
283 _listView.SetRedraw(false);
\r
284 // m_RedrawEnabled = false;
\r
287 ZeroMemory(&item, sizeof(item));
\r
289 _listView.DeleteAllItems();
\r
290 _selectedStatusVector.Clear();
\r
291 // _realIndices.Clear();
\r
292 _startGroupSelect = 0;
\r
294 _selectionIsDefined = false;
\r
296 // m_Files.Clear();
\r
297 // _folder.Release();
\r
305 _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder());
\r
307 CMyComPtr<IFolderSetFlatMode> folderSetFlatMode;
\r
308 _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);
\r
309 if (folderSetFlatMode)
\r
310 folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));
\r
312 RINOK(_folder->LoadItems());
\r
313 RINOK(InitColumns());
\r
315 // OutputDebugString(TEXT("Start Dir\n"));
\r
317 _folder->GetNumberOfItems(&numItems);
\r
319 bool showDots = _showDots && !IsRootFolder();
\r
321 _listView.SetItemCount(numItems + (showDots ? 1 : 0));
\r
323 _selectedStatusVector.Reserve(numItems);
\r
324 int cursorIndex = -1;
\r
326 CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
\r
327 if (!IsFSFolder() || _showRealFileIcons)
\r
328 _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
\r
332 UString itemName = L"..";
\r
333 item.iItem = _listView.GetItemCount();
\r
334 if (itemName.CompareNoCase(focusedName) == 0)
\r
335 cursorIndex = item.iItem;
\r
336 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
\r
338 item.iSubItem = subItem++;
\r
339 item.lParam = kParentIndex;
\r
340 item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
\r
341 UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
\r
342 item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
\r
343 if (item.iImage < 0)
\r
345 if (_listView.InsertItem(&item) == -1)
\r
349 // OutputDebugStringA("S1\n");
\r
351 for (UInt32 i = 0; i < numItems; i++)
\r
353 UString itemName = GetItemName(i);
\r
354 const UString relPath = GetItemRelPath(i);
\r
355 if (relPath.CompareNoCase(focusedName) == 0)
\r
356 cursorIndex = _listView.GetItemCount();
\r
357 bool selected = false;
\r
358 if (selectedNames.FindInSorted(relPath) >= 0)
\r
360 _selectedStatusVector.Add(selected);
\r
362 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
\r
364 if (!_mySelectMode)
\r
367 item.mask |= LVIF_STATE;
\r
368 item.state = LVIS_SELECTED;
\r
372 item.iItem = _listView.GetItemCount();
\r
374 item.iSubItem = subItem++;
\r
377 UString correctedName;
\r
378 if (itemName.Find(L" ") >= 0)
\r
383 int posNew = itemName.Find(L" ", pos);
\r
386 correctedName += itemName.Mid(pos);
\r
389 correctedName += itemName.Mid(pos, posNew - pos);
\r
390 correctedName += L" ... ";
\r
392 while (itemName[++pos] == ' ');
\r
394 item.pszText = const_cast<wchar_t *>((const wchar_t *)correctedName);
\r
397 item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
\r
399 NCOM::CPropVariant prop;
\r
400 RINOK(_folder->GetProperty(i, kpidAttrib, &prop));
\r
402 if (prop.vt == VT_UI4)
\r
403 attrib = prop.ulVal;
\r
404 else if (IsItemFolder(i))
\r
405 attrib |= FILE_ATTRIBUTE_DIRECTORY;
\r
407 bool defined = false;
\r
409 if (folderGetSystemIconIndex)
\r
411 folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
\r
412 defined = (item.iImage > 0);
\r
416 if (_currentFolderPrefix.IsEmpty())
\r
419 GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);
\r
420 item.iImage = iconIndexTemp;
\r
424 item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
\r
427 if (item.iImage < 0)
\r
430 if (_listView.InsertItem(&item) == -1)
\r
431 return E_FAIL; // error
\r
433 // OutputDebugStringA("End2\n");
\r
435 if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
\r
436 SetFocusedSelectedItem(cursorIndex, selectFocused);
\r
437 _listView.SortItems(CompareItems, (LPARAM)this);
\r
438 if (cursorIndex < 0 && _listView.GetItemCount() > 0)
\r
440 if (focusedPos >= _listView.GetItemCount())
\r
441 focusedPos = _listView.GetItemCount() - 1;
\r
442 // we select item only in showDots mode.
\r
443 SetFocusedSelectedItem(focusedPos, showDots);
\r
445 // m_RedrawEnabled = true;
\r
446 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
\r
447 _listView.SetRedraw(true);
\r
448 _listView.InvalidateRect(NULL, true);
\r
449 // OutputDebugStringA("End1\n");
\r
451 _listView.UpdateWindow();
\r
456 void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const
\r
460 int itemIndex = -1;
\r
461 while ((itemIndex = _listView.GetNextItem(itemIndex, LVNI_SELECTED)) != -1)
\r
464 if (_listView.GetItemParam(itemIndex, param))
\r
465 indices.Add(param);
\r
468 for (int i = 0; i < _selectedStatusVector.Size(); i++)
\r
469 if (_selectedStatusVector[i])
\r
471 HeapSort(&indices.Front(), indices.Size());
\r
474 void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
\r
476 GetSelectedItemsIndices(indices);
\r
477 if (!indices.IsEmpty())
\r
479 if (_listView.GetSelectedCount() == 0)
\r
481 int focusedItem = _listView.GetFocusedItem();
\r
482 if (focusedItem >= 0)
\r
484 if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)
\r
486 int realIndex = GetRealItemIndex(focusedItem);
\r
487 if (realIndex != kParentIndex)
\r
488 indices.Add(realIndex);
\r
493 void CPanel::GetAllItemIndices(CRecordVector<UInt32> &indices) const
\r
497 if (_folder->GetNumberOfItems(&numItems) == S_OK)
\r
498 for (UInt32 i = 0; i < numItems; i++)
\r
502 void CPanel::GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const
\r
504 GetOperatedItemIndices(indices);
\r
505 if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1))
\r
506 GetAllItemIndices(indices);
\r
510 void CPanel::GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const
\r
513 int numItems = _listView.GetItemCount();
\r
514 for (int i = 0; i < numItems; i++)
\r
516 int realIndex = GetRealItemIndex(i);
\r
517 if (realIndex >= 0)
\r
518 if (_selectedStatusVector[realIndex])
\r
521 if (indices.IsEmpty())
\r
523 int focusedItem = _listView.GetFocusedItem();
\r
524 if (focusedItem >= 0)
\r
525 indices.Add(focusedItem);
\r
530 void CPanel::EditItem()
\r
532 int focusedItem = _listView.GetFocusedItem();
\r
533 if (focusedItem < 0)
\r
535 int realIndex = GetRealItemIndex(focusedItem);
\r
536 if (realIndex == kParentIndex)
\r
538 if (!IsItemFolder(realIndex))
\r
539 EditItem(realIndex);
\r
542 void CPanel::OpenFocusedItemAsInternal()
\r
544 int focusedItem = _listView.GetFocusedItem();
\r
545 if (focusedItem < 0)
\r
547 int realIndex = GetRealItemIndex(focusedItem);
\r
548 if (IsItemFolder(realIndex))
\r
549 OpenFolder(realIndex);
\r
551 OpenItem(realIndex, true, false);
\r
554 void CPanel::OpenSelectedItems(bool tryInternal)
\r
556 CRecordVector<UInt32> indices;
\r
557 GetOperatedItemIndices(indices);
\r
558 if (indices.Size() > 20)
\r
560 MessageBoxErrorLang(IDS_TOO_MANY_ITEMS, 0x02000606);
\r
564 int focusedItem = _listView.GetFocusedItem();
\r
565 if (focusedItem >= 0)
\r
567 int realIndex = GetRealItemIndex(focusedItem);
\r
568 if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) &&
\r
569 _listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)
\r
570 indices.Insert(0, realIndex);
\r
573 bool dirIsStarted = false;
\r
574 for (int i = 0; i < indices.Size(); i++)
\r
576 UInt32 index = indices[i];
\r
577 // CFileInfo &aFile = m_Files[index];
\r
578 if (IsItemFolder(index))
\r
585 dirIsStarted = true;
\r
589 OpenFolderExternal(index);
\r
593 OpenItem(index, (tryInternal && indices.Size() == 1), true);
\r
597 UString CPanel::GetItemName(int itemIndex) const
\r
599 if (itemIndex == kParentIndex)
\r
601 NCOM::CPropVariant prop;
\r
602 if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)
\r
604 if (prop.vt != VT_BSTR)
\r
606 return prop.bstrVal;
\r
609 UString CPanel::GetItemPrefix(int itemIndex) const
\r
611 if (itemIndex == kParentIndex)
\r
613 NCOM::CPropVariant prop;
\r
614 if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK)
\r
617 if (prop.vt == VT_BSTR)
\r
618 prefix = prop.bstrVal;
\r
622 UString CPanel::GetItemRelPath(int itemIndex) const
\r
624 return GetItemPrefix(itemIndex) + GetItemName(itemIndex);
\r
627 UString CPanel::GetItemFullPath(int itemIndex) const
\r
629 return _currentFolderPrefix + GetItemRelPath(itemIndex);
\r
632 bool CPanel::IsItemFolder(int itemIndex) const
\r
634 if (itemIndex == kParentIndex)
\r
636 NCOM::CPropVariant prop;
\r
637 if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK)
\r
639 if (prop.vt == VT_BOOL)
\r
640 return VARIANT_BOOLToBool(prop.boolVal);
\r
641 if (prop.vt == VT_EMPTY)
\r
646 UINT64 CPanel::GetItemSize(int itemIndex) const
\r
648 if (itemIndex == kParentIndex)
\r
650 NCOM::CPropVariant prop;
\r
651 if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK)
\r
653 if (prop.vt == VT_EMPTY)
\r
655 return ConvertPropVariantToUInt64(prop);
\r
658 void CPanel::ReadListViewInfo()
\r
660 _typeIDString = GetFolderTypeID();
\r
661 if (!_typeIDString.IsEmpty())
\r
662 ::ReadListViewInfo(_typeIDString, _listViewInfo);
\r
665 void CPanel::SaveListViewInfo()
\r
668 for (i = 0; i < _visibleProperties.Size(); i++)
\r
670 CItemProperty &prop = _visibleProperties[i];
\r
671 LVCOLUMN winColumnInfo;
\r
672 winColumnInfo.mask = LVCF_ORDER | LVCF_WIDTH;
\r
673 if (!_listView.GetColumn(i, &winColumnInfo))
\r
675 prop.Order = winColumnInfo.iOrder;
\r
676 prop.Width = winColumnInfo.cx;
\r
679 CListViewInfo viewInfo;
\r
681 // PROPID sortPropID = _properties[_sortIndex].ID;
\r
682 PROPID sortPropID = _sortID;
\r
684 _visibleProperties.Sort();
\r
685 for (i = 0; i < _visibleProperties.Size(); i++)
\r
687 const CItemProperty &prop = _visibleProperties[i];
\r
688 CColumnInfo columnInfo;
\r
689 columnInfo.IsVisible = prop.IsVisible;
\r
690 columnInfo.PropID = prop.ID;
\r
691 columnInfo.Width = prop.Width;
\r
692 viewInfo.Columns.Add(columnInfo);
\r
694 for (i = 0; i < _properties.Size(); i++)
\r
696 const CItemProperty &prop = _properties[i];
\r
697 if (!prop.IsVisible)
\r
699 CColumnInfo columnInfo;
\r
700 columnInfo.IsVisible = prop.IsVisible;
\r
701 columnInfo.PropID = prop.ID;
\r
702 columnInfo.Width = prop.Width;
\r
703 viewInfo.Columns.Add(columnInfo);
\r
707 // viewInfo.SortIndex = viewInfo.FindColumnWithID(sortPropID);
\r
708 viewInfo.SortID = sortPropID;
\r
710 viewInfo.Ascending = _ascending;
\r
711 if (!_listViewInfo.IsEqual(viewInfo))
\r
713 ::SaveListViewInfo(_typeIDString, viewInfo);
\r
714 _listViewInfo = viewInfo;
\r
719 bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result)
\r
721 if (itemActiveate->hdr.hwndFrom == HWND(_listView))
\r
724 ::GetCursorPos(&point);
\r
725 ShowColumnsContextMenu(point.x, point.y);
\r
730 void CPanel::ShowColumnsContextMenu(int x, int y)
\r
734 CMenuDestroyer menuDestroyer(menu);
\r
736 menu.CreatePopup();
\r
738 const int kCommandStart = 100;
\r
739 for (int i = 0; i < _properties.Size(); i++)
\r
741 const CItemProperty &prop = _properties[i];
\r
742 UINT flags = MF_STRING;
\r
743 if (prop.IsVisible)
\r
744 flags |= MF_CHECKED;
\r
746 flags |= MF_GRAYED;
\r
747 menu.AppendItem(flags, kCommandStart + i, prop.Name);
\r
749 int menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY, x, y, _listView);
\r
750 if (menuResult >= kCommandStart && menuResult <= kCommandStart + _properties.Size())
\r
752 int index = menuResult - kCommandStart;
\r
753 CItemProperty &prop = _properties[index];
\r
754 prop.IsVisible = !prop.IsVisible;
\r
756 if (prop.IsVisible)
\r
758 int prevVisibleSize = _visibleProperties.Size();
\r
759 prop.Order = prevVisibleSize;
\r
760 _visibleProperties.Add(prop);
\r
761 InsertColumn(prevVisibleSize);
\r
765 int visibleIndex = _visibleProperties.FindItemWithID(prop.ID);
\r
766 _visibleProperties.Delete(visibleIndex);
\r
768 if (_sortIndex == index)
\r
774 if (_sortID == prop.ID)
\r
776 _sortID = kpidName;
\r
780 _listView.DeleteColumn(visibleIndex);
\r
785 void CPanel::OnReload()
\r
787 HRESULT res = RefreshListCtrlSaveFocused();
\r
789 MessageBoxError(res);
\r
790 OnRefreshStatusBar();
\r
793 void CPanel::OnTimer()
\r
795 if (!_processTimer)
\r
797 CMyComPtr<IFolderWasChanged> folderWasChanged;
\r
798 if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK)
\r
801 if (folderWasChanged->WasChanged(&wasChanged) != S_OK)
\r
803 if (wasChanged == 0)
\r