1 using System;
  2 using System.Collections;
  3 using System.Windows;
  4 
  5 namespace FileExplorer
  6 {
  7     PathBar* MakePathBar(ImageList* imageList)
  8     {
  9         PathBar* pathBar = new PathBar(PathBarCreateParams(PathBarControlCreateParams(ControlCreateParams().Defaults()))
 10             EmptyViewControlCreateParams(ControlCreateParams().SetDock(Dock.left).SetSize(Size(1000)))
 11             ParentPathSelectorCreateParams(ParentPathSelectorControlCreateParams(ControlCreateParams().Defaults())imageList)
 12             PathDividerCreateParams(PathDividerControlCreateParams(ControlCreateParams().Defaults()))
 13             PathViewCreateParams(PathViewControlCreateParams(ControlCreateParams().SetDock(Dock.fill))));
 14         return pathBar;
 15     }
 16 
 17     public class MainWindow : Window
 18     {
 19         public MainWindow(const string& caption) : base(
 20             WindowCreateParams(WindowControlCreateParams(
 21                 ControlCreateParams().SetWindowClassBackgroundColor(SystemColor.COLOR_WINDOW).SetBackgroundColor(Color.White())
 22                 caption)).Defaults())
 23         {
 24             auto result = imageList.AddImage("computer.bitmap");
 25             if (result.Error())
 26             {
 27                 SetErrorId(result.GetErrorId());
 28                 return;
 29             }
 30             result = imageList.AddImage("hard_drive.bitmap");
 31             if (result.Error())
 32             {
 33                 SetErrorId(result.GetErrorId());
 34                 return;
 35             }
 36             result = imageList.AddImage("folder_closed.bitmap");
 37             if (result.Error())
 38             {
 39                 SetErrorId(result.GetErrorId());
 40                 return;
 41             }
 42             result = imageList.AddImage("folder_opened.bitmap");
 43             if (result.Error())
 44             {
 45                 SetErrorId(result.GetErrorId());
 46                 return;
 47             }
 48             result = imageList.AddImage("file.bitmap");
 49             if (result.Error())
 50             {
 51                 SetErrorId(result.GetErrorId());
 52                 return;
 53             }
 54             result = imageList.AddImage("up.arrow.bitmap");
 55             if (result.Error())
 56             {
 57                 SetErrorId(result.GetErrorId());
 58                 return;
 59             }
 60             auto logicalDrivesResult = GetLogicalDrives();
 61             if (logicalDrivesResult.Error())
 62             {
 63                 SetErrorId(logicalDrivesResult.GetErrorId());
 64                 return;
 65             }
 66             logicalDrives = logicalDrivesResult.Value();
 67             computer.Reset(new ComputerNode());
 68             computer->SetMainWindow(this);
 69             for (const string& driveName : logicalDrives)
 70             {
 71                 UniquePtr<DriveNode> drivePtr(new DriveNode(driveName));
 72                 DriveNode* drive = drivePtr.Get();
 73                 drive->SetRootDirectory(new DirectoryNode(driveName + "/"));
 74                 computer->AddDrive(drivePtr.Release());
 75             }
 76             UniquePtr<PathBar> pathBarPtr(MakePathBar(&imageList));
 77             if (pathBarPtr->Error())
 78             {
 79                 SetErrorId(pathBarPtr->GetErrorId());
 80                 return;
 81             }
 82             pathBar = pathBarPtr.Get();
 83             pathBar->GetParentPathSelector()->ClickEvent().AddHandler(ParentPathSelectorClick);
 84             pathBar->GetPathView()->PathComponentSelectedEvent().AddHandler(PathComponentSelected);
 85             UniquePtr<BorderedControl> borderedControl = new BorderedControl(BorderedControlCreateParams(BorderedControlControlCreateParams(
 86                 ControlCreateParams().SetSize(Size(032)).SetDock(Dock.top)pathBar)pathBarPtr.Release()).
 87                 SetNormalBorderColor(DefaultPathBarFrameColor()));
 88             if (borderedControl->Error())
 89             {
 90                 SetErrorId(borderedControl->GetErrorId());
 91                 return;
 92             }
 93             result = AddChild(borderedControl.Release());
 94             if (result.Error())
 95             {
 96                 SetErrorId(result.GetErrorId());
 97                 return;
 98             }
 99             UniquePtr<SplitContainer> splitContainerPtr(new SplitContainer(Orientation.horizontal500Point()Size()Dock.fillAnchors.none));
100             if (splitContainerPtr->Error())
101             {
102                 SetErrorId(splitContainerPtr->GetErrorId());
103                 return;
104             }
105             splitContainer = splitContainerPtr.Get();
106             result = AddChild(splitContainerPtr.Release());
107             if (result.Error())
108             {
109                 SetErrorId(result.GetErrorId());
110                 return;
111             }
112             UniquePtr<DirectoryTreeView> directoryTreeViewPtr(new DirectoryTreeView(&imageListcomputer.Get()));
113             if (directoryTreeViewPtr->Error())
114             {
115                 SetErrorId(directoryTreeViewPtr->GetErrorId());
116                 return;
117             }
118             directoryTreeView = directoryTreeViewPtr.Get();
119             directoryTreeView->SetMainWindow(this);
120             directoryTreeView->SizeChangedEvent().AddHandler(DirectoryTreeViewSizeChanged);
121             result = splitContainer->Pane1Container()->AddChild(directoryTreeViewPtr.Release());
122             if (result.Error())
123             {
124                 SetErrorId(result.GetErrorId());
125                 return;
126             }
127             UniquePtr<ContentView> contentViewPtr(new ContentView(&imageList));
128             if (contentViewPtr->Error())
129             {
130                 SetErrorId(contentViewPtr->GetErrorId());
131                 return;
132             }
133             contentView = contentViewPtr.Get();
134             contentView->SetMainWindow(this);
135             contentView->SizeChangedEvent().AddHandler(ContentViewSizeChanged);
136             result = splitContainer->Pane2Container()->AddChild(contentViewPtr.Release());
137             if (result.Error())
138             {
139                 SetErrorId(result.GetErrorId());
140                 return;
141             }
142             setSplitterDistance = true;
143         }
144         public inline ContentView* GetContentView() const
145         {
146             return contentView;
147         }
148         public inline DirectoryTreeView* GetDirectoryTreeView() const
149         {
150             return directoryTreeView;
151         }
152         public inline PathBar* GetPathBar() const
153         {
154             return pathBar;
155         }
156         public void AddListViewEventHandlers(ListView* listView)
157         {
158             listView->ItemClickEvent().AddHandler(ListViewItemClick);
159             listView->ItemRightClickEvent().AddHandler(ListViewItemRightClick);
160             listView->ItemDoubleClickEvent().AddHandler(ListViewItemDoubleClick);
161         }
162         [nodiscard]
163         protected override Result<bool> OnShown()
164         {
165             auto result = base->OnShown();
166             if (result.Error()) return result;
167             if (setSplitterDistance)
168             {
169                 setSplitterDistance = false;
170                 Size sz = GetSize();
171                 result = splitContainer->SetSplitterDistance(cast<int>(sz.w * 1.000000 / 3.000000));
172                 if (result.Error()) return result;
173             }
174             return Result<bool>(true);
175         }
176         protected override Result<bool> OnKeyDown(KeyEventArgs& args)
177         {
178             auto result = base->OnKeyDown(args);
179             if (result.Error()) return result;
180             if (!args.handled)
181             {
182                 switch (args.key)
183                 {
184                     case Keys.escape:
185                     {
186                         result = RemoveContextMenu();
187                         if (result.Error()) return result;
188                         args.handled = true;
189                         break;
190                     }
191                 }
192             }
193             return Result<bool>(true);
194         }
195         [nodiscard]
196         protected override Result<bool> MouseUpNotification(MouseEventArgs& args)
197         {
198             if (args.buttons == MouseButtons.lbutton)
199             {
200                 auto result = RemoveContextMenu();
201                 if (result.Error()) return result;
202             }
203             return Result<bool>(true);
204         }
205         private void ListViewItemClick(ListViewItemEventArgs& args)
206         {
207             if (args.item != null)
208             {
209                 ListView* view = args.item->View();
210                 if (view != null)
211                 {
212                     auto result = view->SetSelectedItem(args.item);
213                     if (result.Error())
214                     {
215                         args.errorId = result.GetErrorId();
216                         return;
217                     }
218                 }
219             }
220         }
221         private void ListViewItemRightClick(ListViewItemEventArgs& args)
222         {
223             if (args.item != null)
224             {
225                 ListView* view = args.view;
226                 if (view != null)
227                 {
228                     auto result = view->SetSelectedItem(args.item);
229                     if (result.Error())
230                     {
231                         args.errorId = result.GetErrorId();
232                         return;
233                     }
234                     void* data = args.item->Data();
235                     if (data != null)
236                     {
237                         Node* node = cast<Node*>(data);
238                         UniquePtr<ContextMenu> contextMenu(new ContextMenu());
239                         auto result = node->AddMenuItems(contextMenu.Get()false);
240                         if (result.Error())
241                         {
242                             args.errorId = result.GetErrorId();
243                             return;
244                         }
245                         if (contextMenu->HasMenuItems())
246                         {
247                             view->TranslateContentLocation(args.location);
248                             auto clientToScreenResult = view->ClientToScreen(args.location);
249                             if (clientToScreenResult.Error())
250                             {
251                                 args.errorId = clientToScreenResult.GetErrorId();
252                                 return;
253                             }
254                             Point screenLoc = clientToScreenResult.Value();
255                             result = ShowContextMenu(contextMenu.Release()screenLoc);
256                             if (result.Error())
257                             {
258                                 args.errorId = result.GetErrorId();
259                                 return;
260                             }
261                         }
262                     }
263                 }
264             }
265         }
266         private void ListViewItemDoubleClick(ListViewItemEventArgs& args)
267         {
268             if (args.item != null && args.item->Data() != null)
269             {
270                 Node* node = cast<Node*>(args.item->Data());
271                 auto result = node->ExecuteDefaultAction();
272                 if (result.Error())
273                 {
274                     args.errorId = result.GetErrorId();
275                     return;
276                 }
277             }
278         }
279         private void DirectoryTreeViewSizeChanged(SizeChangedEventArgs& args)
280         {
281             Size sz = directoryTreeView->GetSize();
282             auto result = pathBar->SetEmptyViewWidth(sz.w);
283             if (result.Error())
284             {
285                 args.errorId = result.GetErrorId();
286                 return;
287             }
288         }
289         private void ContentViewSizeChanged(SizeChangedEventArgs& args)
290         {
291             Size sz = contentView->GetSize();
292             auto result = pathBar->SetPathViewMaxWidth(sz.w);
293             if (result.Error())
294             {
295                 args.errorId = result.GetErrorId();
296                 return;
297             }
298         }
299         private void ParentPathSelectorClick(ClickEventArgs& args)
300         {
301             Node* currentNode = pathBar->CurrentNode();
302             if (currentNode == null)
303             {
304                 currentNode = directoryTreeView->SelectedNode();
305             }
306             if (currentNode != null)
307             {
308                 currentNode = currentNode->Parent();
309                 if (currentNode != null)
310                 {
311                     if (currentNode->IsRootDirectory())
312                     {
313                         currentNode = currentNode->Parent();
314                     }
315                 }
316             }
317             if (currentNode != null)
318             {
319                 auto result = currentNode->Open();
320                 if (result.Error())
321                 {
322                     args.errorId = result.GetErrorId();
323                     return;
324                 }
325             }
326         }
327         private void PathComponentSelected(PathComponentEventArgs& args)
328         {
329             PathComponent* pathComponent = args.pathComponent;
330             if (pathComponent != null)
331             {
332                 void* data = pathComponent->Data();
333                 if (data != null)
334                 {
335                     Node* node = cast<Node*>(data);
336                     auto result = node->Open();
337                     if (result.Error())
338                     {
339                         args.errorId = result.GetErrorId();
340                         return;
341                     }
342                 }
343             }
344         }
345         private bool setSplitterDistance;
346         private ImageList imageList;
347         private List<string> logicalDrives;
348         private UniquePtr<ComputerNode> computer;
349         private PathBar* pathBar;
350         private SplitContainer* splitContainer;
351         private DirectoryTreeView* directoryTreeView;
352         private ContentView* contentView;
353     }