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(100, 0))),
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(0, 32)).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.horizontal, 500, Point(), Size(), Dock.fill, Anchors.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(&imageList, computer.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 }