54a6a6ac24548215390882e0144b8630f71a51f8
[ede] / explorer / src / ExplorerWindow.ec
1 import "Explorer"
2 import "IconBag"
3 import "ToolBar"
4
5 #ifdef _DEBUG
6    define title = "Ecere Explorer (Debug)";
7 #else
8    define title = "Ecere Explorer";
9 #endif
10
11 /*
12 define backgroundColor = Color { 30, 40, 50 }; //Color { 20, 20, 60 };
13 define foregroundColor = lightGray; //white;
14 define selectionColor = lightYellow;
15 define selectionText = Color { 20, 30, 40 };
16 define toolBarBackgroundColor = backgroundColor;//white; //Color { 240, 240, 250 };
17 define toolBarForegroundColor = foregroundColor;//white; //Color { 240, 240, 250 };
18 */
19 define backgroundColor = beige;//white; //Color { 128, 145, 175 }; //200, 224, 224 }; //lightGray;
20 define foregroundColor = black;
21 define selectionColor = app.currentSkin.selectionColor;
22 define selectionText = app.currentSkin.selectionText;
23 define toolBarBackgroundColor = backgroundColor;//white; //Color { 240, 240, 250 };
24 define toolBarForegroundColor = foregroundColor;//white; //Color { 240, 240, 250 };
25
26 enum ExplorerToolId
27 {
28    none,
29    newWindow, goBack, goForward, goUp, goHome,
30    newFile, newFolder,
31    browse,
32    panelTree, panelSearch,
33    addressBar,
34    refresh,
35    viewList, viewDetails, viewIcons, viewCards, viewShowcase, viewTree, viewCustom,
36    previewPictures,
37
38    searchInFileName,
39    inFileNameMatchCase,
40    inFileNameMatchWord,
41    searchInFileContent,
42    inFileContentMatchCase,
43    inFileContentMatchWord,
44    searchInSubDirs,
45    searchStart,
46    searchStop,
47
48    hasHeader
49 };
50
51 class ExplorerWindow : Window
52 {
53    text = title;
54    background = backgroundColor;
55    borderStyle = sizable;
56    hasMaximize = true;
57    hasMinimize = true;
58    hasClose = true;
59    hasMenuBar = true;
60    //tabCycle = true;
61    size = { 840, 480 };
62    minClientSize = { 600, 300 };
63    nativeDecorations = true;
64    tabCycle = true;
65
66    /*
67    bool userMode;
68    bool clipboard;
69
70    int treeSplit;
71    int searchSplit;
72    
73    ExplorerToolId lastViewId;
74 */
75
76    bool treeInitialized;
77    int historyIndex;
78    Array<HistoryItem> history { };
79
80
81    menu = Menu { };
82    
83    Menu fileMenu { menu, "File", f };
84    Menu windowMenu { menu, "Window", w };
85       MenuItem itemNewWindow
86       {
87          windowMenu, "New Window", n;
88          
89          bool NotifySelect(MenuItem selection, Modifiers mods)
90          {
91             ExplorerWindow { }.Create();
92             return true;
93          }
94       };
95
96    IconBag<ExplorerToolId> iconBag
97    {
98       //window = guiApp.desktop;
99       window = this;
100       alphaBlend = true;
101       iconNames =
102       [
103          "<:ecere>emblems/unreadable.png",         /* none */
104
105          "<:ecere>actions/windowNew.png",          /* newWindow */
106          "<:ecere>actions/goPrevious.png",         /* goBack */
107          "<:ecere>actions/goNext.png",             /* goForward */
108          "<:ecere>actions/goUp.png",               /* goUp */
109          "<:ecere>actions/goHome.png",             /* goHome */
110          "<:ecere>mimeTypes/file.png",             /* newFile */
111          "<:ecere>actions/folderNew.png",          /* newFolder */
112
113          ":browse.png",                            /* browse */
114
115          ":panel-tree.png",                        /* panelTree */
116          "<:ecere>actions/editFind.png",           /* panelSearch */
117
118          "",                                       /* addressBar */
119
120          "<:ecere>actions/viewRefresh.png",        /* refresh */
121
122          ":view-list.png",                         /* viewList */
123          ":view-details.png",                      /* viewDetails */
124          ":view-icons.png",                        /* viewIcons */
125          ":view-cards.png",                        /* viewCards */
126          ":view-showcase-right.png",               /* viewShowcase */
127          ":panel-tree.png",                        /* viewTree */
128          ":view-custom.png",                       /* viewCustom */
129          
130          "<:ecere>mimeTypes/image.png",            /* previewPictures */
131
132          "",                                       /* searchInFileName */
133          "<:ecere>emblems/unreadable.png",         /* inFileNameMatchCase */
134          "<:ecere>emblems/unreadable.png",         /* inFileNameMatchWord */
135          "",                                       /* searchInFileContent */
136          "<:ecere>emblems/unreadable.png",         /* inFileContentMatchCase */
137          "<:ecere>emblems/unreadable.png",         /* inFileContentMatchWord */
138          ":browse.png",                            /* searchInSubDirs */
139          "<:ecere>actions/editFind.png",           /* searchStart */
140          "<:ecere>emblems/unreadable.png",         /* searchStop */
141          "<:ecere>emblems/unreadable.png"          /* hasHeader */
142       ];
143    };
144
145    Stacker stack
146    {
147       this;
148       gap = 0;
149       direction = vertical;
150       background = backgroundColor;
151       opacity = 0.0f;
152       tabCycle = true;
153
154       anchor = { left = 0, top = 0, right = 0, bottom = 0 };
155       //moveable = false;
156    };
157
158    ToolBar/*<ExplorerToolId>*/ toolBar
159    {
160       stack, this;
161       size = { h = 32 };
162       //moveable = false;
163       borderStyle = none;
164       background = toolBarBackgroundColor;
165       tabCycle = true;
166
167       iconBag = iconBag;
168
169       void NotifyToolClick(ToolButton button)
170       {
171          ExplorerToolId id = (ExplorerToolId)button.id;
172          switch(id)
173          {
174             case none:
175                break;
176             case newWindow:
177                ExplorerWindow { }.Create();
178                break;
179             case goBack:
180             case goForward:
181                historyIndex += id == goBack ? -1 : 1;
182                GoToHistoryIndex(false, false, false);
183                break;
184             case goHome:
185             {
186                char * home = getenv("HOME");
187                if(home && home[0] && FileExists(home).isDirectory)
188                   GoTo(home, false, false);
189                break;
190             }
191             case goUp:
192             {
193                char * path = view.path;
194                char * newPath = new char[strlen(path)+1];
195                StripLastDirectory(path, newPath);
196                if(!newPath[0])
197                {
198                   newPath[0] = '/';
199                   newPath[1] = 0;
200                }
201                GoTo(newPath, false, false);
202                delete newPath;
203                break;
204             }
205             case newFile:
206                if(CreateNewFileDialog { master = this, parent = parent, currentDirectory = view.path }.Modal() == ok )
207                   Refresh();
208                break;
209             case newFolder:
210                if(CreateDirectoryDialog { master = this, parent = parent, currentDirectory = view.path }.Modal() == ok )
211                   Refresh();
212                break;
213             case panelTree:
214                SearchStop();
215                //ToggleSearchMode(false);
216                tree.visible = button.checked;
217                split.visible = button.checked;
218                if(button.checked)
219                {
220                   split.rightPane = view;
221                   view.anchor = { top = 0, bottom = 0, right = 0 };
222                   GoTo(addressBar.path, false, false);
223                   ReadyTree();
224                }
225                else
226                {
227                   split.rightPane = null;
228                   view.anchor = { left = 2, top = 0, bottom = 0, right = 0 };
229                }
230                //search.visible = !button.checked;
231                panels.size = { panels.size.w, panels.size.h }; // TOFIX : another Stacker fix needed
232                break;
233             case panelSearch:
234                ToggleSearchMode(button.checked);
235
236                //tree.visible = false; //!button.checked;
237                //split.visible = false; //!button.checked;
238                if(button.checked)
239                {
240                   /*split.rightPane = view;
241                   view.anchor = { top = 0, bottom = 0, right = 0 };*/
242                   //split.rightPane = null;
243                   //view.anchor = { left = 2, top = 0, bottom = 0, right = 0 };
244
245                   //SearchStart();
246                   searchInFileName.Activate();
247                }
248                else
249                {
250                   //split.rightPane = null;
251                   //view.anchor = { left = 2, top = 0, bottom = 0, right = 0 };
252
253                   GoTo(addressBar.path, false, false);
254                }
255                //panels.size = { panels.size.w, panels.size.h }; // TOFIX : another Stacker fix needed
256                break;
257             case refresh:
258                Refresh();
259                break;
260             case previewPictures:
261                view.previewPictures = button.checked;
262                view.Refresh();
263                break;
264             case viewList:
265                view.details = false;
266                view.treeBranches = false;
267                view.Refresh();
268                break;
269             case viewDetails:
270                view.details = true;
271                view.treeBranches = false;
272                view.Refresh();
273                break;
274             case viewIcons:
275             case viewCards:
276                //SwitchViews(toolId);
277                view.details = false;
278                view.treeBranches = false;
279                view.Refresh();
280                break;
281             case viewShowcase:
282                view.preview = button.checked;
283                view.Refresh();
284                break;
285             case viewTree:
286                view.treeBranches = button.checked;
287                view.Refresh();
288                break;
289             case hasHeader:
290                view.hasHeader ^= true;
291                break;
292          }
293          view.Activate();
294       }
295    };
296
297    Window { toolBar, size = { w = 8 }, inactive = true };
298    ToolButton goBack { toolBar, this, id = ExplorerToolId::goBack, hotKey = { left, alt = true }, disabled = true };
299    Window { toolBar, size = { w = 2 }, inactive = true };
300    ToolButton goForward { toolBar, this, id = ExplorerToolId::goForward, hotKey = { right, alt = true }, disabled = true };
301    Window { toolBar, size = { w = 2 }, inactive = true };
302    ToolButton refresh { toolBar, this, id = ExplorerToolId::refresh, hotKey = { r, ctrl = true } };
303    Window { toolBar, size = { w = 2 }, inactive = true };
304    ToolButton goHome { toolBar, this, id = ExplorerToolId::goHome, hotKey = { h, ctrl = true } };
305    Window { toolBar, size = { w = 8 }, inactive = true };
306    PathBox addressBar
307    {
308       toolBar, this;
309       size = { 300, 22 }, id = ExplorerToolId::addressBar;
310       typeExpected = directory;
311       borderStyle = deep;
312       background = toolBarBackgroundColor;
313       foreground = toolBarForegroundColor;
314       selectionColor = selectionColor;
315       selectionText = selectionText;
316
317       bool OnKeyDown(Key key, unichar ch)
318       {
319          if((SmartKey)key == enter)
320          {
321             // how to make enter effect a modification
322             // how to implement in PathBox
323          }
324          return true;
325       }
326
327       bool NotifyModified(PathBox pathBox)
328       {
329          GoTo(pathBox.path, false, false);
330          return true;
331       }
332    };
333    FlipStacker { toolBar, spring = previous };
334    Window { toolBar, size = { w = 8 }, inactive = true };
335    ToolButton newFile { toolBar, this, id = ExplorerToolId::newFile, hotKey = { n, ctrl = true } };
336    Window { toolBar, size = { w = 2 }, inactive = true };
337    ToolButton newFolder { toolBar, this, id = ExplorerToolId::newFolder, hotKey = { d, ctrl = true } };
338    Window { toolBar, size = { w = 8 }, inactive = true };
339    ToolButton goUp { toolBar, this, id = ExplorerToolId::goUp, hotKey = { up, alt = true } };
340    Window { toolBar, size = { w = 8 }, inactive = true };
341    //GroupToggleToolButton selectedPanel;
342    ToggleToolButton panelTree   { toolBar, this, id = ExplorerToolId::panelTree, hotKey = { t, ctrl = true }/*, selected = &selectedPanel*//*, checked = true*/ };
343    ToggleToolButton panelSearch { toolBar, this, id = ExplorerToolId::panelSearch, hotKey = { f, ctrl = true }/*, selected = &selectedPanel*/ };
344    //selectedPanel = panelTree;
345    Window { toolBar, size = { w = 8 }, inactive = true };
346    /*OptionToolButton selectedView;
347    OptionToolButton viewList     { toolBar, this, id = ExplorerToolId::viewList, selected = &selectedView, checked = true };
348    OptionToolButton viewDetails  { toolBar, this, id = ExplorerToolId::viewDetails, selected = &selectedView };
349    OptionToolButton viewIcons    { toolBar, this, id = ExplorerToolId::viewIcons, selected = &selectedView };
350    OptionToolButton viewTiles    { toolBar, this, id = ExplorerToolId::viewCards, selected = &selectedView };
351    OptionToolButton viewShowcase { toolBar, this, id = ExplorerToolId::viewShowcase, selected = &selectedView };
352    OptionToolButton viewTree     { toolBar, this, id = ExplorerToolId::viewTree, selected = &selectedView };
353    selectedView = viewList;*/
354    //ToggleToolButton viewList     { toolBar, this, id = ExplorerToolId::viewList, checked = true };
355    ToggleToolButton viewDetails  { toolBar, this, id = ExplorerToolId::viewDetails };
356    //ToggleToolButton viewIcons    { toolBar, this, id = ExplorerToolId::viewIcons };
357    //ToggleToolButton viewTiles    { toolBar, this, id = ExplorerToolId::viewCards };
358    ToggleToolButton viewShowcase { toolBar, this, id = ExplorerToolId::viewShowcase };
359    ToggleToolButton viewTree     { toolBar, this, id = ExplorerToolId::viewTree };
360    Window { toolBar, size = { w = 8 }, inactive = true };
361    ToggleToolButton previewPictures { toolBar, this, id = ExplorerToolId::previewPictures };
362
363    Window { toolBar, size = { w = 8 }, inactive = true };
364    ToolButton hasHeader { toolBar, this, id = ExplorerToolId::hasHeader };
365    Window { toolBar, size = { w = 8 }, inactive = true };
366    ToolButton newWindow { toolBar, this, id = ExplorerToolId::newWindow, hotKey = { w, ctrl = true } };
367    Window { toolBar, size = { w = 8 }, inactive = true };
368
369
370    /*void OnDestroy()
371    {
372       iconBag.window = null;
373       delete iconBag;
374    }*/
375
376    bool OnLoadGraphics()
377    {
378       iconBag.Load();
379       return true;
380    }
381
382    void OnUnloadGraphics()
383    {
384       iconBag.Unload();
385    }
386
387    Stacker panels
388    {
389       stack, this;
390       gap = 0;
391       direction = horizontal;
392       opacity = 0.0f;
393       tabCycle = true;
394
395       anchor.left = 0;
396       //anchor.bottom = 0;
397       anchor.right = 0;
398
399       //size = { h = 400 };
400    };
401
402    FlipStacker flipStack { stack, spring = previous };
403
404    //Window searchSpace { stack, size = { h = 32 }, background = toolBarBackgroundColor, inactive = true, opacity = 0.0f };
405
406    ToolBar/*<ExplorerToolId>*/ searchBar
407    {
408       stack, this;
409       size = { h = 32 };
410       visible = false;
411       //moveable = false;
412       borderStyle = none;
413       background = toolBarBackgroundColor;
414       tabCycle = true;
415       iconBag = iconBag;
416
417       void NotifyToolClick(ToolButton button)
418       {
419          ExplorerToolId id = (ExplorerToolId)button.id;
420          switch(id)
421          {
422             case none:
423                break;
424             case searchStart:
425                SearchStart();
426                break;
427             case searchStop:
428                SearchStop();
429                break;
430          }
431          view.Activate();
432       }
433    };
434
435
436    Window { searchBar, size = { w = 8 }, inactive = true };
437    Label { searchBar, this, labeledWindow = searchInFileName};
438    Window { searchBar, size = { w = 2 }, inactive = true };
439    EditBox searchInFileName
440    {
441       searchBar, this;
442       size = { 200, 22 }, id = ExplorerToolId::searchInFileName;
443       borderStyle = deep;
444       background = toolBarBackgroundColor;
445       foreground = toolBarForegroundColor;
446       selectionColor = selectionColor;
447       selectionText = selectionText;
448       text = "File Name:";
449
450       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
451       {
452          if((SmartKey)key == enter)
453             SearchStart();
454          return true;
455       }
456
457       /*bool NotifyActivate(Window window, bool active, Window previous)
458       {
459          if(active)
460          {
461             toolBar.focusHolder = window;
462          }
463          return true;
464       }*/
465    };
466    Window { searchBar, size = { w = 2 }, inactive = true };
467 #ifndef __WIN32__
468    ToggleToolButton inFileNameMatchCase { searchBar, this, id = ExplorerToolId::inFileNameMatchCase };
469 #endif
470    ToggleToolButton inFileNameMatchWord { searchBar, this, id = ExplorerToolId::inFileNameMatchWord };
471    Window { searchBar, size = { w = 8 }, inactive = true };
472    Label { searchBar, this, labeledWindow = searchInFileContent};
473    Window { searchBar, size = { w = 2 }, inactive = true };
474    EditBox searchInFileContent
475    {
476       searchBar, this;
477       size = { 200, 22 }, id = ExplorerToolId::searchInFileContent;
478       borderStyle = deep;
479       background = toolBarBackgroundColor;
480       foreground = toolBarForegroundColor;
481       selectionColor = selectionColor;
482       selectionText = selectionText;
483       text = "File Content:";
484
485       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
486       {
487          if((SmartKey)key == enter)
488             SearchStart();
489          return true;
490       }
491
492       /*bool NotifyActivate(Window window, bool active, Window previous)
493       {
494          if(active)
495             toolBar.focusHolder = window;
496          return true;
497       }*/
498    };
499    FlipStacker { searchBar, spring = previous };
500    ToggleToolButton inFileContentMatchCase { searchBar, this, id = ExplorerToolId::inFileContentMatchCase };
501    ToggleToolButton inFileContentMatchWord { searchBar, this, id = ExplorerToolId::inFileContentMatchWord };
502    Window { searchBar, size = { w = 8 }, inactive = true };
503    ToggleToolButton searchInSubDirs { searchBar, this, id = ExplorerToolId::searchInSubDirs, checked = true };
504    Window { searchBar, size = { w = 8 }, inactive = true };
505    ToolButton searchStart { searchBar, this, id = ExplorerToolId::searchStart, hotKey = { s, ctrl = true } };
506    Window { searchBar, size = { w = 8 }, inactive = true };
507    ToolButton searchStop { searchBar, this, id = ExplorerToolId::searchStop, hotKey = { escape }, disabled = true; };
508    Window { searchBar, size = { w = 8 }, inactive = true };
509
510
511
512    //Window { searchBar, size = { h = 1 } };
513
514    /*SearchPanel searchPanel
515    {
516       panels, this;
517    };*/
518
519    /*Window hack
520    {
521       panels, this;
522       anchor.top = 0;
523       anchor.bottom = 0;
524       anchor.right = 0;
525       borderStyle = none;
526       background = backgroundColor;
527    };*/
528
529    /*Tree*/FileSystemBox tree//;
530    {
531       panels, this;
532       size = { w = 240 };
533       borderStyle = none;
534       background = backgroundColor;
535       foreground = foregroundColor;
536       selectionColor = selectionColor;
537       selectionText = selectionText;
538       visible = false;
539       anchor.top = 0;
540       anchor.bottom = 0;
541       //anchor = { left = 0, top = 0, bottom = 0 };
542
543       treeBranches = true;
544       foldersOnly = true;
545       autoLoad = false;
546
547       bool NotifyNodeSelect(FileSystemBox box, FileSystemBoxSelection selection)
548       {
549          if(treeInitialized)
550          {
551             FileSystemNode node = selection.node;
552             if(node)
553             {
554                char p[MAX_LOCATION];
555                node.GetPath(p);
556                GoTo(node.path, false, true);
557             }
558          }
559          return true;
560       }
561
562       /*bool NotifyActivate(Window window, bool active, Window previous)
563       {
564          if(active)
565             toolBar.focusHolder = window;
566          return true;
567       }*/
568    };
569
570    PaneSplitter split
571    {
572       panels, this;
573       visible = false;
574       leftPane = tree;//, rightPane = view;
575       split = 300;
576    };
577
578    FileSystemBox view
579    {
580       panels, this;
581       borderStyle = none;
582       background = backgroundColor;
583       foreground = foregroundColor;
584       selectionColor = selectionColor;
585       selectionText = selectionText;
586       anchor.top = 0;
587       anchor.bottom = 0;
588       anchor.right = 0;
589       //anchor = { left = 2, top = 0, bottom = 0, right = 0 };
590
591       locationBox = addressBar;
592       navigateFolders = true;
593       multiSelect = true;
594       autoLoad = false;
595
596       bool NotifyNodeOpen(FileSystemBox box, FileSystemBoxSelection selection)
597       {
598          FileSystemNode node = selection.node;
599          if(node)
600          {
601             if(node.type.isFile)
602             {
603                char path[MAX_LOCATION];
604             #ifndef __WIN32__
605                char command[MAX_LOCATION];
606                node.GetPath(path);
607                /*_FileType t = node.type;
608                if(t == ewsFile || t == epjFile ||
609                      t == ecFile || t == ehFile ||
610                      t == cppFile || t == hppFile ||
611                      t == cFile || t == hFile ||
612                      t == textFile || t == webFile)*/
613                   sprintf(command, "gnome-open \"%s\"", path);
614                /*else
615                   sprintf(command, "%s", path);*/
616                Execute(command);
617             #else
618                node.GetPath(path);
619                ShellOpen(path);
620             #endif
621             }
622             else if(node.type.isFolder)
623                GoTo(node.path, true, false);
624          }
625          UpdateHistoryItem(selection);
626          return true;
627       }
628
629       bool NotifyNodeSelect(FileSystemBox box, FileSystemBoxSelection selection)
630       {
631          UpdateHistoryItem(selection);
632          return true;
633       }
634
635       /*bool NotifyActivate(Window window, bool active, Window previous)
636       {
637          if(active)
638             toolBar.focusHolder = window;
639          return true;
640       }*/
641    };
642
643    FileSystemSearch searchThread
644    {
645       owner = this, fsb = view, tree = tree/*, searchPanel = this*/;
646
647       /*bool ExplorerWindow::NotifyUpdateSearchLocation(FileSystemSearch search, char * location)
648       {
649          char string[MAX_LOCATION + 2048];
650          sprintf(string, "%s (Searching %s)", title, location);
651          PrintLn(string); //view.results.text = string;
652          text = string;
653          return true;
654       }*/
655
656       bool ExplorerWindow::NotifySearchTerminated(FileSystemSearch search)
657       {
658          searchStop.disabled = true;
659          return true;
660       }
661    };
662
663    void ToggleSearchMode(bool inSearch)
664    {
665       SearchStop();
666       //search.visible = inSearch;
667       //panelSearch.checked = inSearch; // <------ this is toggling panelSearch even though it shouldn't
668       //searchSpace.visible = !inSearch;
669       searchBar.visible = inSearch;
670       history[historyIndex].inSearch = inSearch;
671       size = { size.w, size.h };
672       view.pathColumn = inSearch;
673       /*if(inSearch)
674          searchThread.InitResults();*/
675       if(inSearch && /*(*/searchInFileName.contents[0]/* || searchInFileContents.contents[0])*/)
676          SearchStart();
677    }
678
679    void ReadyTree()
680    {
681       if(tree.visible)
682       {
683          if(!treeInitialized)
684          {
685             tree.path = "/"; // this should be available as a parameter
686             treeInitialized = true;
687          }
688          tree.SelectLocation(view.path);
689       }
690    }
691
692    void Refresh()
693    {
694       if(searchBar.visible)
695          SearchStart();
696       else
697       {
698          if(tree.visible)
699             tree.Refresh();
700          view.Refresh();
701       }
702    }
703
704    void GoTo(char * location, bool viewIsAtLocation, bool treeIsAtLocation)
705    {
706       HistoryItem item = null;
707       if(!history.count || fstrcmp(history[historyIndex].path, location))
708       {
709          int c;
710          for(c = 0; c < history.count; c++)
711             if(!fstrcmp(history[c].path, location))
712                break;
713          if(c == history.count)
714          {
715             item = { path = CopyString(location) };
716             if(history.count)
717             {
718                while(historyIndex < history.count-1)
719                {
720                   delete history[history.count-1].path;
721                   history.count--;
722                }
723             }
724             history.Add(item);
725             historyIndex = history.count-1;
726          }
727          else
728             historyIndex = c;
729       }
730       GoToHistoryIndex(viewIsAtLocation, treeIsAtLocation, item != null);
731    }
732
733    void GoToHistoryIndex(bool viewIsAtLocation, bool treeIsAtLocation, bool updateHistoryItem)
734    {
735       HistoryItem item = history[historyIndex];
736
737       goBack.disabled = historyIndex == 0;
738       goForward.disabled = historyIndex == history.count-1;
739       goUp.disabled = !fstrcmp(item.path, "/");
740
741       if(!viewIsAtLocation)
742       {
743          if(item.inSearch != panelSearch.checked)
744          {
745             ToggleSearchMode(item.inSearch);
746             if(item.inSearch)
747                SearchStart();
748          }
749          if(!item.inSearch)
750          /*{
751             //SearchStart();
752          }
753          else*/
754          {
755             view.path = item.path;
756             item.holdRecordingSelection = true;
757             view.SelectMultipleByPath(item.selection);
758          }
759       }
760       if(tree.visible && !treeIsAtLocation)
761          tree.SelectLocation(item.path);
762
763       if(updateHistoryItem)
764          UpdateHistoryItem(view.selection);
765    }
766
767    void UpdateHistoryItem(FileSystemBoxSelection selection)
768    {
769       HistoryItem item = history[historyIndex];
770
771       if(!item.holdRecordingSelection)
772       {
773          if(selection.node || (selection.nodes && selection.nodes.count))
774          {
775             item.selection.Free();
776             if(selection.nodes.count)
777             {
778                for(node : selection.nodes)
779                   item.selection.Add(CopyString(node.path));
780             }
781             else if(selection.node)
782                item.selection.Add(CopyString(selection.node.path));
783          }
784       }
785       else
786          item.holdRecordingSelection = false;
787    }
788
789    void SearchStart()
790    {
791       SearchStop();
792       searchThread.active = true;
793
794       searchThread.optionSubdirs = searchInSubDirs.checked == true;
795       searchThread.optionTree = view.treeBranches; //(options.subdirs.checked && options.tree.checked);
796       searchThread.optionBrowser = tree.visible; //(options.subdirs.checked && options.browser.checked);
797 #ifndef __WIN32__
798       searchThread.optionNameMatchCase = inFileNameMatchCase.checked;
799 #else
800       searchThread.optionNameMatchCase = false;
801 #endif
802       searchThread.optionNameMatchWord = inFileNameMatchWord.checked;
803       searchThread.optionContentMatchCase = inFileContentMatchCase.checked;
804       searchThread.optionContentMatchWord = inFileContentMatchWord.checked;
805
806       strcpy(searchThread.location, view.path);
807       strcpy(searchThread.nameSearch, searchInFileName.contents);
808       strcpy(searchThread.contentSearch, searchInFileContent.contents);
809
810       //actions.startStop.text = "Stop Search";
811       //actions.clear.disabled = false;
812       //view.results.Clear();
813       //view.results.hasHeader = !searchThread.optionTree;
814       //view.results.treeBranches = searchThread.optionTree;
815       //view.browser.Clear();
816       //ToggleBrowserDisplay(searchThread.optionBrowser);
817
818       //view.browser.text = "Browser";
819       /*{
820          char string[MAX_LOCATION + 2048];
821          sprintf(string, "%s (Searching %s)", title, view.path);
822          //PrintLn(string); //view.results.text = string;
823          text = string;
824       }*/
825       searchThread.InitResults();
826       searchThread.Create();
827       searchStop.disabled = false;
828       //Update(null);
829    }
830
831    bool SearchStop()
832    {
833       if(searchThread.active)
834       {
835          searchThread.terminate = true;
836          //searchStop.disabled = true;
837          app.Unlock();
838             searchThread.Wait();
839          app.Lock();
840          return true;
841       }
842       return false;
843    }
844
845    /*ExplorerSearch search
846    {
847       deep, this;
848       visible = false;
849       tabCycle = true;
850       size = Size { 624, 268 };
851       anchor = Anchor { left = 0, top = 0, bottom = 0 };
852    };
853
854    ExplorerViewSearch results;*/
855
856    /*Window viewHolder
857    {
858       parent = deep, master = this;
859       tabCycle = true;
860       anchor = Anchor { top = 0, bottom = 0, right = 0 };
861    };*/
862
863    // Preview / Showcase
864    /*PreviewArea previewArea
865    {
866       panels, this;
867    };*/
868
869    //FlipStacker flipPanels { panels, spring = previous };
870
871    /*bool TreeNotifyBranchSelect(ExplorerTree tree, ExplorerFileBranch branch)
872    {
873       if(branch)
874       {
875          char path[MAX_LOCATION];
876          branch.GetPath(path);
877          toolBar.addressBar.contents = path;
878          view.Load(branch);
879       }
880       return true;
881    }*/
882    
883    /*bool ViewNotifyItemOpen(ExplorerView view, ExplorerFileItem item)
884    {
885       ExplorerFileBranch branch = tree.branch;
886       if(item && branch)
887       {
888          if(item.type.isFolderType)
889          {
890             ExplorerFileBranch child;
891             
892             if(!branch.loaded || !branch.childrenLoaded)
893                BranchLoad(branch, tree.tree);
894
895             for(child = branch.children.first; child; child = child.next)
896                if(!strcmp(child.name, item.name))
897                   break;
898             
899             if(child)
900             {
901                if(branch.row.collapsed)
902                   child.row.collapsed = true;
903                child.EnsureVisible(false);
904                tree.Select(child);
905             }
906          }
907          else
908          {
909             char path[MAX_LOCATION];
910             branch.GetPath(path);
911             PathCat(path, item.name);
912             ShellOpen(path);
913          }
914       }
915    }*/
916
917    /*void SwitchViews(ExplorerToolId viewId)
918    {
919       ExplorerFileBranch branch = tree.branch;
920       view.Destroy(0);
921       switch(viewId)
922       {
923          case viewList:     view = ExplorerViewList     { parent = viewHolder, master = this }; break;
924          case viewDetails:  view = ExplorerViewDetails  { parent = viewHolder, master = this }; break;
925          case viewIcons:    view = ExplorerViewIcons    { parent = viewHolder, master = this }; break;
926          case viewCards:    view = ExplorerViewCards    { parent = viewHolder, master = this }; break;
927          case viewShowcase: view = ExplorerViewShowcase { parent = viewHolder, master = this }; break;
928       }
929       view.tabCycle = true;
930       view.previewPictures = toolBar.previewPictures.checked;
931       view.anchor = Anchor { left = 0, top = 0, bottom = 0, right = 0 };
932       view.NotifyItemOpen = ViewNotifyItemOpen;
933       view.Create();
934       view.Load(branch);
935       lastViewId = viewId;
936    }*/
937
938    /*void SearchLocation(char * location)
939    {
940       GoTo(location);
941       search.location.editBox.contents = location;
942    }*/
943
944    bool OnPostCreate()
945    {
946       //userMode = true;
947       addressBar.path = view.path;
948       ReadyTree();
949       return true;
950    }
951
952    bool OnClose(bool parentClosing)
953    {
954       SearchStop();
955       return true;
956    }
957
958    /*ExplorerWindow()
959    {
960       userMode = false;
961
962       treeSplit = 300;
963       searchSplit = 200;
964
965       view = ExplorerViewList
966       {
967          parent = viewHolder, master = this;
968          tabCycle = true;
969          previewPictures = toolBar.previewPictures.checked;
970          anchor = Anchor { left = 0, top = 0, bottom = 0, right = 0 };
971          NotifyItemOpen = ViewNotifyItemOpen;
972       };
973       lastViewId = viewList;
974       
975       tree.Load();
976       view.Load(tree.root);
977    }*/
978
979    /*void InitTree()
980    {
981    }*/
982
983    /*void InitSearch()
984    {
985    }*/
986 }
987
988 //class TreeFileSystemBox : FileSystemBox { }
989
990 class HistoryItem
991 {
992    char * path;
993    bool holdRecordingSelection;
994    bool inSearch;
995    Array<String> selection { };
996
997    ~HistoryItem()
998    {
999       delete path;
1000    }
1001 }