Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / FileManager / PanelItems.cpp
1 // PanelItems.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "../../../../C/Sort.h"\r
6 \r
7 #include "Common/StringConvert.h"\r
8 \r
9 #include "Windows/Menu.h"\r
10 #include "Windows/PropVariant.h"\r
11 #include "Windows/PropVariantConversions.h"\r
12 \r
13 #include "../../PropID.h"\r
14 \r
15 #include "resource.h"\r
16 \r
17 #include "LangUtils.h"\r
18 #include "Panel.h"\r
19 #include "PropertyName.h"\r
20 #include "RootFolder.h"\r
21 \r
22 using namespace NWindows;\r
23 \r
24 static int GetColumnAlign(PROPID propID, VARTYPE varType)\r
25 {\r
26   switch(propID)\r
27   {\r
28     case kpidCTime:\r
29     case kpidATime:\r
30     case kpidMTime:\r
31       return LVCFMT_LEFT;\r
32   }\r
33   switch(varType)\r
34   {\r
35     case VT_UI1:\r
36     case VT_I2:\r
37     case VT_UI2:\r
38     case VT_I4:\r
39     case VT_INT:\r
40     case VT_UI4:\r
41     case VT_UINT:\r
42     case VT_I8:\r
43     case VT_UI8:\r
44     case VT_BOOL:\r
45       return LVCFMT_RIGHT;\r
46     \r
47     case VT_EMPTY:\r
48     case VT_I1:\r
49     case VT_FILETIME:\r
50     case VT_BSTR:\r
51       return LVCFMT_LEFT;\r
52     \r
53     default:\r
54       return LVCFMT_CENTER;\r
55   }\r
56 }\r
57 \r
58 HRESULT CPanel::InitColumns()\r
59 {\r
60   if (_needSaveInfo)\r
61     SaveListViewInfo();\r
62 \r
63   _listView.DeleteAllItems();\r
64   _selectedStatusVector.Clear();\r
65 \r
66   ReadListViewInfo();\r
67 \r
68 \r
69   PROPID sortID;\r
70   /*\r
71   if (_listViewInfo.SortIndex >= 0)\r
72     sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID;\r
73   */\r
74   sortID  = _listViewInfo.SortID;\r
75 \r
76   _ascending = _listViewInfo.Ascending;\r
77 \r
78   _properties.Clear();\r
79 \r
80   _needSaveInfo = true;\r
81 \r
82   UInt32 numProperties;\r
83   _folder->GetNumberOfProperties(&numProperties);\r
84   int i;\r
85   for (i = 0; i < (int)numProperties; i++)\r
86   {\r
87     CMyComBSTR name;\r
88     PROPID propID;\r
89     VARTYPE varType;\r
90 \r
91     RINOK(_folder->GetPropertyInfo(i, &name, &propID, &varType));\r
92 \r
93     if (propID == kpidIsDir)\r
94       continue;\r
95 \r
96     CItemProperty prop;\r
97     prop.Type = varType;\r
98     prop.ID = propID;\r
99     prop.Name = GetNameOfProperty(propID, name);\r
100     prop.Order = -1;\r
101     prop.IsVisible = true;\r
102     prop.Width = 100;\r
103     _properties.Add(prop);\r
104   }\r
105   // InitColumns2(sortID);\r
106 \r
107   for (;;)\r
108     if (!_listView.DeleteColumn(0))\r
109       break;\r
110 \r
111   int order = 0;\r
112   for (i = 0; i < _listViewInfo.Columns.Size(); i++)\r
113   {\r
114     const CColumnInfo &columnInfo = _listViewInfo.Columns[i];\r
115     int index = _properties.FindItemWithID(columnInfo.PropID);\r
116     if (index >= 0)\r
117     {\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
123       continue;\r
124     }\r
125   }\r
126   for (i = 0; i < _properties.Size(); i++)\r
127   {\r
128     CItemProperty &item = _properties[i];\r
129     if (item.Order < 0)\r
130       item.Order = order++;\r
131   }\r
132 \r
133   _visibleProperties.Clear();\r
134   for (i = 0; i < _properties.Size(); i++)\r
135   {\r
136     const CItemProperty &prop = _properties[i];\r
137     if (prop.IsVisible)\r
138       _visibleProperties.Add(prop);\r
139   }\r
140 \r
141   // _sortIndex = 0;\r
142   _sortID = kpidName;\r
143   /*\r
144   if (_listViewInfo.SortIndex >= 0)\r
145   {\r
146     int sortIndex = _properties.FindItemWithID(sortID);\r
147     if (sortIndex >= 0)\r
148       _sortIndex = sortIndex;\r
149   }\r
150   */\r
151   _sortID = _listViewInfo.SortID;\r
152 \r
153   for (i = 0; i < _visibleProperties.Size(); i++)\r
154   {\r
155     InsertColumn(i);\r
156   }\r
157   return S_OK;\r
158 }\r
159 \r
160 void CPanel::InsertColumn(int index)\r
161 {\r
162   const CItemProperty &prop = _visibleProperties[index];\r
163   LV_COLUMNW column;\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
171 }\r
172 \r
173 HRESULT CPanel::RefreshListCtrl()\r
174 {\r
175   return RefreshListCtrl(UString(), -1, true, UStringVector());\r
176 }\r
177 \r
178 int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);\r
179 \r
180 \r
181 void CPanel::GetSelectedNames(UStringVector &selectedNames)\r
182 {\r
183   selectedNames.Clear();\r
184 \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
190 \r
191   /*\r
192   for (int i = 0; i < _listView.GetItemCount(); i++)\r
193   {\r
194     const int kSize = 1024;\r
195     WCHAR name[kSize + 1];\r
196     LVITEMW item;\r
197     item.iItem = i;\r
198     item.pszText = name;\r
199     item.cchTextMax  = kSize;\r
200     item.iSubItem = 0;\r
201     item.mask = LVIF_TEXT | LVIF_PARAM;\r
202     if (!_listView.GetItem(&item))\r
203       continue;\r
204     int realIndex = GetRealIndex(item);\r
205     if (realIndex == kParentIndex)\r
206       continue;\r
207     if (_selectedStatusVector[realIndex])\r
208       selectedNames.Add(item.pszText);\r
209   }\r
210   */\r
211   selectedNames.Sort();\r
212 }\r
213 \r
214 void CPanel::SaveSelectedState(CSelectedState &s)\r
215 {\r
216   s.FocusedName.Empty();\r
217   s.SelectedNames.Clear();\r
218   s.FocusedItem = _listView.GetFocusedItem();\r
219   {\r
220     if (s.FocusedItem >= 0)\r
221     {\r
222       int realIndex = GetRealItemIndex(s.FocusedItem);\r
223       if (realIndex != kParentIndex)\r
224         s.FocusedName = GetItemRelPath(realIndex);\r
225         /*\r
226         const int kSize = 1024;\r
227         WCHAR name[kSize + 1];\r
228         LVITEMW item;\r
229         item.iItem = focusedItem;\r
230         item.pszText = name;\r
231         item.cchTextMax  = kSize;\r
232         item.iSubItem = 0;\r
233         item.mask = LVIF_TEXT;\r
234         if (_listView.GetItem(&item))\r
235         focusedName = item.pszText;\r
236       */\r
237     }\r
238   }\r
239   GetSelectedNames(s.SelectedNames);\r
240 }\r
241 \r
242 HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)\r
243 {\r
244   bool selectFocused = s.SelectFocused;\r
245   if (_mySelectMode)\r
246     selectFocused = true;\r
247   return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);\r
248 }\r
249 \r
250 HRESULT CPanel::RefreshListCtrlSaveFocused()\r
251 {\r
252   CSelectedState state;\r
253   SaveSelectedState(state);\r
254   return RefreshListCtrl(state);\r
255 }\r
256 \r
257 void CPanel::SetFocusedSelectedItem(int index, bool select)\r
258 {\r
259   UINT state = LVIS_FOCUSED;\r
260   if (select)\r
261     state |= LVIS_SELECTED;\r
262   _listView.SetItemState(index, state, state);\r
263   if (!_mySelectMode && select)\r
264   {\r
265     int realIndex = GetRealItemIndex(index);\r
266     if (realIndex != kParentIndex)\r
267       _selectedStatusVector[realIndex] = true;\r
268   }\r
269 }\r
270 \r
271 HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,\r
272     const UStringVector &selectedNames)\r
273 {\r
274   _dontShowMode = false;\r
275   LoadFullPathAndShow();\r
276   // OutputDebugStringA("=======\n");\r
277   // OutputDebugStringA("s1 \n");\r
278   CDisableTimerProcessing timerProcessing(*this);\r
279 \r
280   if (focusedPos < 0)\r
281     focusedPos = 0;\r
282 \r
283   _listView.SetRedraw(false);\r
284   // m_RedrawEnabled = false;\r
285 \r
286   LVITEMW item;\r
287   ZeroMemory(&item, sizeof(item));\r
288   \r
289   _listView.DeleteAllItems();\r
290   _selectedStatusVector.Clear();\r
291   // _realIndices.Clear();\r
292   _startGroupSelect = 0;\r
293 \r
294   _selectionIsDefined = false;\r
295   \r
296   // m_Files.Clear();\r
297   // _folder.Release();\r
298 \r
299   if (!_folder)\r
300   {\r
301     // throw 1;\r
302     SetToRootFolder();\r
303   }\r
304   \r
305   _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder());\r
306 \r
307   CMyComPtr<IFolderSetFlatMode> folderSetFlatMode;\r
308   _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);\r
309   if (folderSetFlatMode)\r
310     folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));\r
311 \r
312   RINOK(_folder->LoadItems());\r
313   RINOK(InitColumns());\r
314 \r
315   // OutputDebugString(TEXT("Start Dir\n"));\r
316   UInt32 numItems;\r
317   _folder->GetNumberOfItems(&numItems);\r
318 \r
319   bool showDots = _showDots && !IsRootFolder();\r
320 \r
321   _listView.SetItemCount(numItems + (showDots ? 1 : 0));\r
322 \r
323   _selectedStatusVector.Reserve(numItems);\r
324   int cursorIndex = -1;\r
325 \r
326   CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;\r
327   if (!IsFSFolder() || _showRealFileIcons)\r
328     _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);\r
329 \r
330   if (showDots)\r
331   {\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
337     int subItem = 0;\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
344       item.iImage = 0;\r
345     if (_listView.InsertItem(&item) == -1)\r
346       return E_FAIL;\r
347   }\r
348   \r
349   // OutputDebugStringA("S1\n");\r
350 \r
351   for (UInt32 i = 0; i < numItems; i++)\r
352   {\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
359       selected = true;\r
360     _selectedStatusVector.Add(selected);\r
361 \r
362     item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\r
363 \r
364     if (!_mySelectMode)\r
365       if (selected)\r
366       {\r
367         item.mask |= LVIF_STATE;\r
368         item.state = LVIS_SELECTED;\r
369       }\r
370   \r
371     int subItem = 0;\r
372     item.iItem = _listView.GetItemCount();\r
373     \r
374     item.iSubItem = subItem++;\r
375     item.lParam = i;\r
376     \r
377     UString correctedName;\r
378     if (itemName.Find(L"     ") >= 0)\r
379     {\r
380       int pos = 0;\r
381       for (;;)\r
382       {\r
383         int posNew = itemName.Find(L"     ", pos);\r
384         if (posNew < 0)\r
385         {\r
386           correctedName += itemName.Mid(pos);\r
387           break;\r
388         }\r
389         correctedName += itemName.Mid(pos, posNew - pos);\r
390         correctedName += L" ... ";\r
391         pos = posNew;\r
392         while (itemName[++pos] == ' ');\r
393       }\r
394       item.pszText = const_cast<wchar_t *>((const wchar_t *)correctedName);\r
395     }\r
396     else\r
397       item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);\r
398 \r
399     NCOM::CPropVariant prop;\r
400     RINOK(_folder->GetProperty(i, kpidAttrib, &prop));\r
401     UInt32 attrib = 0;\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
406 \r
407     bool defined  = false;\r
408 \r
409     if (folderGetSystemIconIndex)\r
410     {\r
411       folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);\r
412       defined = (item.iImage > 0);\r
413     }\r
414     if (!defined)\r
415     {\r
416       if (_currentFolderPrefix.IsEmpty())\r
417       {\r
418         int iconIndexTemp;\r
419         GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);\r
420         item.iImage = iconIndexTemp;\r
421       }\r
422       else\r
423       {\r
424         item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);\r
425       }\r
426     }\r
427     if (item.iImage < 0)\r
428       item.iImage = 0;\r
429 \r
430     if (_listView.InsertItem(&item) == -1)\r
431       return E_FAIL; // error\r
432   }\r
433   // OutputDebugStringA("End2\n");\r
434 \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
439   {\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
444   }\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
450   /*\r
451   _listView.UpdateWindow();\r
452   */\r
453   return S_OK;\r
454 }\r
455 \r
456 void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const\r
457 {\r
458   indices.Clear();\r
459   /*\r
460   int itemIndex = -1;\r
461   while ((itemIndex = _listView.GetNextItem(itemIndex, LVNI_SELECTED)) != -1)\r
462   {\r
463     LPARAM param;\r
464     if (_listView.GetItemParam(itemIndex, param))\r
465       indices.Add(param);\r
466   }\r
467   */\r
468   for (int i = 0; i < _selectedStatusVector.Size(); i++)\r
469     if (_selectedStatusVector[i])\r
470       indices.Add(i);\r
471   HeapSort(&indices.Front(), indices.Size());\r
472 }\r
473 \r
474 void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const\r
475 {\r
476   GetSelectedItemsIndices(indices);\r
477   if (!indices.IsEmpty())\r
478     return;\r
479   if (_listView.GetSelectedCount() == 0)\r
480     return;\r
481   int focusedItem = _listView.GetFocusedItem();\r
482   if (focusedItem >= 0)\r
483   {\r
484     if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED)\r
485     {\r
486       int realIndex = GetRealItemIndex(focusedItem);\r
487       if (realIndex != kParentIndex)\r
488         indices.Add(realIndex);\r
489     }\r
490   }\r
491 }\r
492 \r
493 void CPanel::GetAllItemIndices(CRecordVector<UInt32> &indices) const\r
494 {\r
495   indices.Clear();\r
496   UInt32 numItems;\r
497   if (_folder->GetNumberOfItems(&numItems) == S_OK)\r
498     for (UInt32 i = 0; i < numItems; i++)\r
499       indices.Add(i);\r
500 }\r
501 \r
502 void CPanel::GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const\r
503 {\r
504   GetOperatedItemIndices(indices);\r
505   if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1))\r
506     GetAllItemIndices(indices);\r
507 }\r
508 \r
509 /*\r
510 void CPanel::GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const\r
511 {\r
512   indices.Clear();\r
513   int numItems = _listView.GetItemCount();\r
514   for (int i = 0; i < numItems; i++)\r
515   {\r
516     int realIndex = GetRealItemIndex(i);\r
517     if (realIndex >= 0)\r
518       if (_selectedStatusVector[realIndex])\r
519         indices.Add(i);\r
520   }\r
521   if (indices.IsEmpty())\r
522   {\r
523     int focusedItem = _listView.GetFocusedItem();\r
524       if (focusedItem >= 0)\r
525         indices.Add(focusedItem);\r
526   }\r
527 }\r
528 */\r
529 \r
530 void CPanel::EditItem()\r
531 {\r
532   int focusedItem = _listView.GetFocusedItem();\r
533   if (focusedItem < 0)\r
534     return;\r
535   int realIndex = GetRealItemIndex(focusedItem);\r
536   if (realIndex == kParentIndex)\r
537     return;\r
538   if (!IsItemFolder(realIndex))\r
539     EditItem(realIndex);\r
540 }\r
541 \r
542 void CPanel::OpenFocusedItemAsInternal()\r
543 {\r
544   int focusedItem = _listView.GetFocusedItem();\r
545   if (focusedItem < 0)\r
546     return;\r
547   int realIndex = GetRealItemIndex(focusedItem);\r
548   if (IsItemFolder(realIndex))\r
549     OpenFolder(realIndex);\r
550   else\r
551     OpenItem(realIndex, true, false);\r
552 }\r
553 \r
554 void CPanel::OpenSelectedItems(bool tryInternal)\r
555 {\r
556   CRecordVector<UInt32> indices;\r
557   GetOperatedItemIndices(indices);\r
558   if (indices.Size() > 20)\r
559   {\r
560     MessageBoxErrorLang(IDS_TOO_MANY_ITEMS, 0x02000606);\r
561     return;\r
562   }\r
563   \r
564   int focusedItem = _listView.GetFocusedItem();\r
565   if (focusedItem >= 0)\r
566   {\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
571   }\r
572 \r
573   bool dirIsStarted = false;\r
574   for (int i = 0; i < indices.Size(); i++)\r
575   {\r
576     UInt32 index = indices[i];\r
577     // CFileInfo &aFile = m_Files[index];\r
578     if (IsItemFolder(index))\r
579     {\r
580       if (!dirIsStarted)\r
581       {\r
582         if (tryInternal)\r
583         {\r
584           OpenFolder(index);\r
585           dirIsStarted = true;\r
586           break;\r
587         }\r
588         else\r
589           OpenFolderExternal(index);\r
590       }\r
591     }\r
592     else\r
593       OpenItem(index, (tryInternal && indices.Size() == 1), true);\r
594   }\r
595 }\r
596 \r
597 UString CPanel::GetItemName(int itemIndex) const\r
598 {\r
599   if (itemIndex == kParentIndex)\r
600     return L"..";\r
601   NCOM::CPropVariant prop;\r
602   if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)\r
603     throw 2723400;\r
604   if (prop.vt != VT_BSTR)\r
605     throw 2723401;\r
606   return prop.bstrVal;\r
607 }\r
608 \r
609 UString CPanel::GetItemPrefix(int itemIndex) const\r
610 {\r
611   if (itemIndex == kParentIndex)\r
612     return UString();\r
613   NCOM::CPropVariant prop;\r
614   if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK)\r
615     throw 2723400;\r
616   UString prefix;\r
617   if (prop.vt == VT_BSTR)\r
618     prefix = prop.bstrVal;\r
619   return prefix;\r
620 }\r
621 \r
622 UString CPanel::GetItemRelPath(int itemIndex) const\r
623 {\r
624   return GetItemPrefix(itemIndex) + GetItemName(itemIndex);\r
625 }\r
626 \r
627 UString CPanel::GetItemFullPath(int itemIndex) const\r
628 {\r
629   return _currentFolderPrefix + GetItemRelPath(itemIndex);\r
630 }\r
631 \r
632 bool CPanel::IsItemFolder(int itemIndex) const\r
633 {\r
634   if (itemIndex == kParentIndex)\r
635     return true;\r
636   NCOM::CPropVariant prop;\r
637   if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK)\r
638     throw 2723400;\r
639   if (prop.vt == VT_BOOL)\r
640     return VARIANT_BOOLToBool(prop.boolVal);\r
641   if (prop.vt == VT_EMPTY)\r
642     return false;\r
643   return false;\r
644 }\r
645 \r
646 UINT64 CPanel::GetItemSize(int itemIndex) const\r
647 {\r
648   if (itemIndex == kParentIndex)\r
649     return 0;\r
650   NCOM::CPropVariant prop;\r
651   if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK)\r
652     throw 2723400;\r
653   if (prop.vt == VT_EMPTY)\r
654     return 0;\r
655   return ConvertPropVariantToUInt64(prop);\r
656 }\r
657 \r
658 void CPanel::ReadListViewInfo()\r
659 {\r
660   _typeIDString = GetFolderTypeID();\r
661   if (!_typeIDString.IsEmpty())\r
662     ::ReadListViewInfo(_typeIDString, _listViewInfo);\r
663 }\r
664 \r
665 void CPanel::SaveListViewInfo()\r
666 {\r
667   int i;\r
668   for (i = 0; i < _visibleProperties.Size(); i++)\r
669   {\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
674       throw 1;\r
675     prop.Order = winColumnInfo.iOrder;\r
676     prop.Width = winColumnInfo.cx;\r
677   }\r
678 \r
679   CListViewInfo viewInfo;\r
680   \r
681   // PROPID sortPropID = _properties[_sortIndex].ID;\r
682   PROPID sortPropID = _sortID;\r
683   \r
684   _visibleProperties.Sort();\r
685   for (i = 0; i < _visibleProperties.Size(); i++)\r
686   {\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
693   }\r
694   for (i = 0; i < _properties.Size(); i++)\r
695   {\r
696     const CItemProperty &prop = _properties[i];\r
697     if (!prop.IsVisible)\r
698     {\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
704     }\r
705   }\r
706   \r
707   // viewInfo.SortIndex = viewInfo.FindColumnWithID(sortPropID);\r
708   viewInfo.SortID = sortPropID;\r
709 \r
710   viewInfo.Ascending = _ascending;\r
711   if (!_listViewInfo.IsEqual(viewInfo))\r
712   {\r
713     ::SaveListViewInfo(_typeIDString, viewInfo);\r
714     _listViewInfo = viewInfo;\r
715   }\r
716 }\r
717 \r
718 \r
719 bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result)\r
720 {\r
721   if (itemActiveate->hdr.hwndFrom == HWND(_listView))\r
722     return false;\r
723   POINT point;\r
724   ::GetCursorPos(&point);\r
725   ShowColumnsContextMenu(point.x, point.y);\r
726   result = TRUE;\r
727   return true;\r
728 }\r
729 \r
730 void CPanel::ShowColumnsContextMenu(int x, int y)\r
731 {\r
732 \r
733   CMenu menu;\r
734   CMenuDestroyer menuDestroyer(menu);\r
735 \r
736   menu.CreatePopup();\r
737 \r
738   const int kCommandStart = 100;\r
739   for (int i = 0; i < _properties.Size(); i++)\r
740   {\r
741     const CItemProperty &prop = _properties[i];\r
742     UINT flags =  MF_STRING;\r
743     if (prop.IsVisible)\r
744       flags |= MF_CHECKED;\r
745     if (i == 0)\r
746       flags |= MF_GRAYED;\r
747     menu.AppendItem(flags, kCommandStart + i, prop.Name);\r
748   }\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
751   {\r
752     int index = menuResult - kCommandStart;\r
753     CItemProperty &prop = _properties[index];\r
754     prop.IsVisible = !prop.IsVisible;\r
755 \r
756     if (prop.IsVisible)\r
757     {\r
758       int prevVisibleSize = _visibleProperties.Size();\r
759       prop.Order = prevVisibleSize;\r
760       _visibleProperties.Add(prop);\r
761       InsertColumn(prevVisibleSize);\r
762     }\r
763     else\r
764     {\r
765       int visibleIndex = _visibleProperties.FindItemWithID(prop.ID);\r
766       _visibleProperties.Delete(visibleIndex);\r
767       /*\r
768       if (_sortIndex == index)\r
769       {\r
770         _sortIndex = 0;\r
771         _ascending = true;\r
772       }\r
773       */\r
774       if (_sortID == prop.ID)\r
775       {\r
776         _sortID = kpidName;\r
777         _ascending = true;\r
778       }\r
779 \r
780       _listView.DeleteColumn(visibleIndex);\r
781     }\r
782   }\r
783 }\r
784 \r
785 void CPanel::OnReload()\r
786 {\r
787   HRESULT res = RefreshListCtrlSaveFocused();\r
788   if (res != S_OK)\r
789     MessageBoxError(res);\r
790   OnRefreshStatusBar();\r
791 }\r
792 \r
793 void CPanel::OnTimer()\r
794 {\r
795   if (!_processTimer)\r
796     return;\r
797   CMyComPtr<IFolderWasChanged> folderWasChanged;\r
798   if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK)\r
799     return;\r
800   Int32 wasChanged;\r
801   if (folderWasChanged->WasChanged(&wasChanged) != S_OK)\r
802     return;\r
803   if (wasChanged == 0)\r
804     return;\r
805   OnReload();\r
806 }\r