1 /*
2  * This file is licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  */
6 
7 #include "workspacebrowserf.h" // class's header file
8 
9 #include <sdk.h>
10 #ifndef CB_PRECOMP
11     #include <wx/intl.h>
12     #include <wx/treectrl.h>
13     #include <wx/listctrl.h>
14     #include <wx/sizer.h>
15     #include <wx/stattext.h>
16     #include <wx/choice.h>
17     #include <wx/menu.h>
18     #include <wx/splitter.h>
19     #include <wx/button.h>
20     #include <wx/utils.h> // wxBusyCursor
21     #include <wx/tipwin.h>
22     #include <wx/tokenzr.h>
23     #include <wx/combobox.h>
24     #include <wx/settings.h>
25     #include <wx/choicdlg.h>
26 
27     #include <cbproject.h>
28     #include <cbeditor.h>
29     #include <configmanager.h>
30     #include <editormanager.h>
31     #include <globals.h>
32     #include <manager.h>
33     #include <pluginmanager.h>
34     #include <projectmanager.h>
35     #include <cbstyledtextctrl.h>
36 #endif
37 
38 #include "nativeparserf.h"
39 #include "fortranproject.h"
40 
41 namespace {
42     int idMenuJumpToImplementation = wxNewId();
43     int idMenuRefreshTree = wxNewId();
44     int idMenuForceReparse = wxNewId();
45     int idMenuDoNotSort = wxNewId();
46     int idMenuSortAlphabetically = wxNewId();
47     int idMenuTopTree = wxNewId();
48     int idMenuBottomTree = wxNewId();
49     int idCmbSearch = wxNewId();
50     int idBtnHome = wxNewId();
51     int idCmbView = wxNewId();
52 }
53 
BEGIN_EVENT_TABLE(WorkspaceBrowserF,wxPanel)54 BEGIN_EVENT_TABLE(WorkspaceBrowserF, wxPanel)
55     // m_TreeBottom
56     EVT_TREE_ITEM_ACTIVATED(idMenuBottomTree, WorkspaceBrowserF::OnTreeItemDoubleClick)
57     EVT_TREE_ITEM_RIGHT_CLICK(idMenuBottomTree, WorkspaceBrowserF::OnTreeItemRightClick)
58     // m_TreeTop
59     EVT_TREE_ITEM_ACTIVATED(idMenuTopTree, WorkspaceBrowserF::OnTreeItemDoubleClick)
60     EVT_TREE_ITEM_RIGHT_CLICK(idMenuTopTree, WorkspaceBrowserF::OnTreeItemRightClick)
61     EVT_TREE_SEL_CHANGED(idMenuTopTree, WorkspaceBrowserF::OnTreeItemSelected)
62     EVT_TREE_ITEM_EXPANDING(idMenuTopTree, WorkspaceBrowserF::OnTreeItemExpanding)
63     EVT_TREE_ITEM_COLLAPSING(idMenuTopTree, WorkspaceBrowserF::OnTreeItemCollapsing)
64 
65     EVT_TEXT_ENTER(idCmbSearch, WorkspaceBrowserF::OnSearch)
66     EVT_COMBOBOX(idCmbSearch, WorkspaceBrowserF::OnSearch)
67 
68     EVT_BUTTON(idBtnHome, WorkspaceBrowserF::OnMakeVisible)
69 
70     EVT_MENU(idMenuJumpToImplementation, WorkspaceBrowserF::OnJumpTo)
71     EVT_MENU(idMenuRefreshTree, WorkspaceBrowserF::OnRefreshTree)
72     EVT_MENU(idMenuForceReparse, WorkspaceBrowserF::OnForceReparse)
73     EVT_CHOICE(idCmbView, WorkspaceBrowserF::OnViewScope)
74 
75     EVT_MENU(idMenuDoNotSort, WorkspaceBrowserF::OnChangeSort)
76     EVT_MENU(idMenuSortAlphabetically, WorkspaceBrowserF::OnChangeSort)
77     EVT_MENU(idMenuBottomTree, WorkspaceBrowserF::OnChangeMode)
78 END_EVENT_TABLE()
79 
80 
81 // class constructor
82 WorkspaceBrowserF::WorkspaceBrowserF(wxWindow* parent, NativeParserF* np, ParserF* par)
83     : m_NativeParser(np),
84       m_TreeForPopupMenu(0),
85       m_pParser(par),
86       m_pActiveProject(0),
87       m_pBrowserBuilder(0)
88 {
89     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
90 
91     m_BrowserOptions.visibleBottomTree = cfg->ReadBool(_T("/visible_bottom_tree"), true);
92     m_BrowserOptions.sortAlphabetically = cfg->ReadBool(_T("/browser_sort_alphabetically"), true);
93     m_BrowserOptions.showLocalVariables = cfg->ReadBool(_T("/browser_show_local_variables"), true);
94     m_BrowserOptions.showIncludeSeparately = cfg->ReadBool(_T("/browser_show_include_files_separately"), true);
95 
96     Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("WorkspaceBrowserF"));
97     CreateControlsWBF();
98 
99     if (platform::windows)
100         m_Search->SetWindowStyle(wxTE_PROCESS_ENTER); // it's a must on windows to catch EVT_TEXT_ENTER
101 
102     int filter = cfg->ReadInt(_T("/browser_display_filter"), bdfWorkspace);
103     m_CmbViewWBF->SetSelection(filter);
104     m_BrowserOptions.displayFilter = (BrowserDisplayFilter)filter;
105 
106     // if the classbrowser is put under the control of a wxFlatNotebook,
107     // somehow the main panel is like "invisible" :/
108     // so we force the correct color for the panel here...
109     m_WBFMainPanel->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
110 }
111 
112 
CreateControlsWBF()113 void WorkspaceBrowserF::CreateControlsWBF()
114 {
115     const int imageSize = Manager::Get()->GetImageSize(Manager::UIComponent::Main);
116     const int uiScaleFactor = Manager::Get()->GetUIScaleFactor(Manager::UIComponent::Main);
117     wxString prefix = ConfigManager::GetDataFolder() +
118                       wxString::Format(wxT("/FortranProject.zip#zip:images/%dx%d/"), imageSize, imageSize);
119     wxBitmap bmp_makevisible = cbLoadBitmapScaled(prefix + _T("fprojectmakevisible.png"), wxBITMAP_TYPE_PNG, uiScaleFactor);
120 
121     wxBoxSizer* BoxSizer1;
122     wxBoxSizer* BoxSizer2;
123     wxBoxSizer* BoxSizer3;
124     wxBoxSizer* BoxSizer4;
125     wxFlexGridSizer* FlexGridSizer1;
126     wxStaticText* StaticText1;
127     wxStaticText* StaticText2;
128 
129     BoxSizer1 = new wxBoxSizer(wxVERTICAL);
130     m_WBFMainPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("WBFMainPanel"));
131     BoxSizer2 = new wxBoxSizer(wxVERTICAL);
132     FlexGridSizer1 = new wxFlexGridSizer(2, 2, 2, 2);
133     FlexGridSizer1->AddGrowableCol(1);
134     StaticText1 = new wxStaticText(m_WBFMainPanel, wxID_ANY, _("View:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
135     FlexGridSizer1->Add(StaticText1, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
136     BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
137     m_CmbViewWBF = new wxChoice(m_WBFMainPanel, idCmbView, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("cmbViewWBF"));
138     m_CmbViewWBF->Append(_("Current file\'s symbols"));
139     m_CmbViewWBF->Append(_("Active project\'s symbols"));
140     m_CmbViewWBF->SetSelection( m_CmbViewWBF->Append(_("All local symbols (workspace)")) );
141     BoxSizer3->Add(m_CmbViewWBF, 1, wxEXPAND, 0);
142     m_BtnHome = new wxBitmapButton(m_WBFMainPanel, idBtnHome, bmp_makevisible, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator, _T("btnHome"));
143     m_BtnHome->SetDefault();
144     BoxSizer3->Add(m_BtnHome, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
145     FlexGridSizer1->Add(BoxSizer3, 1, wxALL|wxEXPAND, 0);
146     StaticText2 = new wxStaticText(m_WBFMainPanel, wxID_ANY, _("Search:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT2"));
147     FlexGridSizer1->Add(StaticText2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
148     BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
149     m_Search = new wxComboBox(m_WBFMainPanel, idCmbSearch, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_DROPDOWN|wxTE_PROCESS_ENTER, wxDefaultValidator, _T("cmbSearchWBF"));
150     BoxSizer4->Add(m_Search, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
151     FlexGridSizer1->Add(BoxSizer4, 1, wxALL|wxEXPAND, 0);
152     BoxSizer2->Add(FlexGridSizer1, 0, wxALL|wxEXPAND, 4);
153     m_SplitterWin = new wxSplitterWindow(m_WBFMainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE, _T("splitterWinWBF"));
154     m_SplitterWin->SetSashGravity(0.5);
155     m_TreeTop = new wxTreeCtrl(m_SplitterWin, idMenuTopTree, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE, wxDefaultValidator, _T("treeAllWBF"));
156     m_TreeBottom = new wxTreeCtrl(m_SplitterWin, idMenuBottomTree, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT|wxTR_DEFAULT_STYLE, wxDefaultValidator, _T("treeMembersWBF"));
157     m_SplitterWin->SplitHorizontally(m_TreeTop, m_TreeBottom);
158     BoxSizer2->Add(m_SplitterWin, 1, wxALL|wxEXPAND, 0);
159     m_WBFMainPanel->SetSizer(BoxSizer2);
160     BoxSizer2->Fit(m_WBFMainPanel);
161     BoxSizer2->SetSizeHints(m_WBFMainPanel);
162     BoxSizer1->Add(m_WBFMainPanel, 1, wxALL|wxEXPAND, 0);
163     SetSizer(BoxSizer1);
164     BoxSizer1->Fit(this);
165     BoxSizer1->SetSizeHints(this);
166 }
167 
168 // class destructor
~WorkspaceBrowserF()169 WorkspaceBrowserF::~WorkspaceBrowserF()
170 {
171     int pos = m_SplitterWin->GetSashPosition();
172     Manager::Get()->GetConfigManager(_T("fortran_project"))->Write(_T("/splitter_pos"), pos);
173     int filter = m_CmbViewWBF->GetSelection();
174     Manager::Get()->GetConfigManager(_T("fortran_project"))->Write(_T("/browser_display_filter"), filter);
175 
176     if (m_pBrowserBuilder)
177     {
178         delete m_pBrowserBuilder;
179     }
180 }
181 
UpdateSash()182 void WorkspaceBrowserF::UpdateSash()
183 {
184     int pos = Manager::Get()->GetConfigManager(_T("fortran_project"))->ReadInt(_T("/splitter_pos"), 250);
185     m_SplitterWin->SetSashPosition(pos, false);
186 }
187 
UpdateView()188 void WorkspaceBrowserF::UpdateView()
189 {
190     m_pActiveProject = 0;
191     m_ActiveFilename.Clear();
192     if (Manager::IsAppShuttingDown())
193         return;
194 
195     if (m_pParser)
196     {
197         m_pActiveProject = Manager::Get()->GetProjectManager()->GetActiveProject();
198         cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
199         if (ed)
200             m_ActiveFilename = ed->GetFilename();
201 
202         if (m_pActiveProject)
203             BuildTree();
204         else if (m_pBrowserBuilder)
205             m_pBrowserBuilder->DeleteTopRootChildren();
206     }
207     else
208         m_TreeTop->DeleteAllItems();
209 
210 }
211 
ShowMenu(wxTreeCtrl * tree,wxTreeItemId id,cb_unused const wxPoint & pt)212 void WorkspaceBrowserF::ShowMenu(wxTreeCtrl* tree, wxTreeItemId id, cb_unused const wxPoint& pt)
213 {
214 // NOTE: local variables are tricky! If you build two local menus
215 // and attach menu B to menu A, on function exit both menu A and menu B
216 // will be destroyed. But when destroying menu A, menu B will be destroyed
217 // again. Its already-freed memory will be accessed, generating a segfault.
218 
219 // A safer approach is to make all menus heap-based, and delete the topmost
220 // on exit.
221 
222     m_TreeForPopupMenu = tree;
223     if ( !id.IsOk() )
224         return;
225 
226 #if wxUSE_MENUS
227     wxString caption;
228     wxMenu *menu=new wxMenu(wxEmptyString);
229 
230     TreeDataF* ctd = (TreeDataF*)tree->GetItemData(id);
231     if (ctd)
232     {
233         if (ctd->m_SpecialFolder==sfToken)
234         {
235             menu->Append(idMenuJumpToImplementation, _("Jump to &implementation"));
236         }
237     }
238 
239     if (tree == m_TreeTop)
240     {
241         // only in top tree
242         if (menu->GetMenuItemCount() != 0)
243             menu->AppendSeparator();
244 
245         menu->Append(idMenuRefreshTree, _("&Refresh tree"));
246 
247         if (id == m_TreeTop->GetRootItem())
248         {
249             menu->Append(idMenuForceReparse, _("Re-&parse now"));
250         }
251     }
252     menu->AppendSeparator();
253     menu->AppendCheckItem(idMenuDoNotSort, _("Do not sort"));
254     menu->Check(idMenuDoNotSort, !m_BrowserOptions.sortAlphabetically);
255     menu->AppendCheckItem(idMenuSortAlphabetically, _("Sort alphabetically"));
256     menu->Check(idMenuSortAlphabetically, m_BrowserOptions.sortAlphabetically);
257 
258     menu->AppendSeparator();
259     menu->AppendCheckItem(idMenuBottomTree, _("Display bottom tree"));
260     menu->Check(idMenuBottomTree, m_BrowserOptions.visibleBottomTree);
261 
262 
263     if (menu->GetMenuItemCount() != 0)
264         PopupMenu(menu);
265     delete menu; // Prevents memory leak
266 #endif // wxUSE_MENUS
267 }
268 
269 // events
270 
OnTreeItemRightClick(wxTreeEvent & event)271 void WorkspaceBrowserF::OnTreeItemRightClick(wxTreeEvent& event)
272 {
273     wxTreeCtrl* tree = (wxTreeCtrl*)event.GetEventObject();
274     tree->SelectItem(event.GetItem());
275     ShowMenu(tree, event.GetItem(), event.GetPoint());// + tree->GetPosition());
276 }
277 
JumpToToken(TokenF * pToken)278 void WorkspaceBrowserF::JumpToToken(TokenF* pToken)
279 {
280     if (pToken)
281     {
282         LineAddress jumpStart;
283         LineAddress jumpFinish;
284         if(cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor())
285         {
286             cbStyledTextCtrl* control = ed->GetControl();
287             int curLine = control->LineFromPosition(control->GetCurrentPos());
288             jumpStart.Init(ed->GetFilename(), curLine, false);
289         }
290         EditorManager* edMan = Manager::Get()->GetEditorManager();
291         if (cbEditor* ed = edMan->Open(pToken->m_Filename))
292         {
293             ed->GotoLine(pToken->m_LineStart - 1);
294             wxFocusEvent ev(wxEVT_SET_FOCUS);
295             ev.SetWindow(this);
296 #if wxCHECK_VERSION(3, 0, 0)
297             ed->GetControl()->GetEventHandler()->AddPendingEvent(ev);
298 #else
299             ed->GetControl()->AddPendingEvent(ev);
300 #endif
301 
302             // Track jump history
303             cbStyledTextCtrl* control = ed->GetControl();
304             int curLine = control->LineFromPosition(control->GetCurrentPos());
305             jumpFinish.Init(ed->GetFilename(), curLine, true);
306 
307             m_NativeParser->GetJumpTracker()->TakeJump(jumpStart, jumpFinish);
308             m_NativeParser->GetFortranProject()->CheckEnableToolbar();
309         }
310         else
311         {
312             cbMessageBox(wxString::Format(_("Declaration not found: %s"), pToken->m_DisplayName.c_str()), _("Warning"), wxICON_WARNING);
313         }
314     }
315 }
316 
OnJumpTo(cb_unused wxCommandEvent & event)317 void WorkspaceBrowserF::OnJumpTo(cb_unused wxCommandEvent& event)
318 {
319     wxTreeCtrl* tree = m_TreeForPopupMenu;
320     wxTreeItemId id = tree->GetSelection();
321     TreeDataF* ctd = (TreeDataF*)tree->GetItemData(id);
322     if (ctd && ctd->m_pToken)
323     {
324         JumpToToken(ctd->m_pToken);
325     }
326 }
327 
OnTreeItemDoubleClick(wxTreeEvent & event)328 void WorkspaceBrowserF::OnTreeItemDoubleClick(wxTreeEvent& event)
329 {
330     wxTreeCtrl* tree = (wxTreeCtrl*)event.GetEventObject();
331     wxTreeItemId id = event.GetItem();
332     TreeDataF* ctd = (TreeDataF*)tree->GetItemData(id);
333     if (ctd && ctd->m_pToken)
334     {
335         JumpToToken(ctd->m_pToken);
336     }
337 }
338 
OnRefreshTree(cb_unused wxCommandEvent & event)339 void WorkspaceBrowserF::OnRefreshTree(cb_unused wxCommandEvent& event)
340 {
341     UpdateView();
342 }
343 
OnForceReparse(cb_unused wxCommandEvent & event)344 void WorkspaceBrowserF::OnForceReparse(cb_unused wxCommandEvent& event)
345 {
346     if (m_NativeParser)
347     {
348         switch (m_BrowserOptions.displayFilter)
349         {
350         case bdfWorkspace:
351         {
352             m_NativeParser->ForceReparseWorkspace();
353             break;
354         }
355         case bdfProject:
356         {
357 // NOTE (darius#1#): Force reparse workspace, just because currently only the workspace parsing is running on a secondary thread.
358             //m_NativeParser->ReparseProject(m_pActiveProject);
359             m_NativeParser->ForceReparseWorkspace();
360             UpdateView();
361             break;
362         }
363         case bdfFile:
364         {
365             wxString pFN;
366             if (m_pActiveProject)
367                 pFN = m_pActiveProject->GetFilename();
368             m_NativeParser->ReparseFile(pFN, m_ActiveFilename);
369             UpdateView();
370             break;
371         }
372         }
373     }
374 }
375 
OnViewScope(wxCommandEvent & event)376 void WorkspaceBrowserF::OnViewScope(wxCommandEvent& event)
377 {
378     m_BrowserOptions.displayFilter = (BrowserDisplayFilter)event.GetSelection();
379     UpdateView();
380 }
381 
OnChangeSort(wxCommandEvent & event)382 void WorkspaceBrowserF::OnChangeSort(wxCommandEvent& event)
383 {
384     if (event.GetId() == idMenuDoNotSort)
385         m_BrowserOptions.sortAlphabetically = !event.IsChecked();
386     else if (event.GetId() == idMenuSortAlphabetically)
387         m_BrowserOptions.sortAlphabetically = event.IsChecked();
388     UpdateView();
389 
390     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
391     cfg->Write(_T("/browser_sort_alphabetically"),m_BrowserOptions.sortAlphabetically);
392 }
393 
OnChangeMode(wxCommandEvent & event)394 void WorkspaceBrowserF::OnChangeMode(wxCommandEvent& event)
395 {
396     if (event.GetId() == idMenuBottomTree)
397     {
398         m_BrowserOptions.visibleBottomTree = event.IsChecked();
399 
400         ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
401         cfg->Write(_T("/visible_bottom_tree"), m_BrowserOptions.visibleBottomTree);
402     }
403     UpdateView();
404 }
405 
FindMatchTokens(wxString search,TokensArrayF & result)406 size_t WorkspaceBrowserF::FindMatchTokens(wxString search, TokensArrayF& result)
407 {
408     size_t count=0;
409     switch (m_BrowserOptions.displayFilter)
410     {
411     case bdfFile:
412     {
413         count = m_pParser->FindMatchTokens(m_ActiveFilename, search, result);
414         break;
415     }
416     case bdfProject:
417     {
418         for (FilesList::iterator it = m_pActiveProject->GetFilesList().begin(); it != m_pActiveProject->GetFilesList().end(); ++it)
419         {
420             ProjectFile* pf = *it;
421             count = m_pParser->FindMatchTokens(pf->file.GetFullPath(), search, result);
422         }
423         break;
424     }
425     case bdfWorkspace:
426     {
427         ProjectsArray* projects = Manager::Get()->GetProjectManager()->GetProjects();
428         for (size_t i=0; i < projects->GetCount(); ++i)
429         {
430             cbProject* project = projects->Item(i);
431             for (FilesList::iterator it = project->GetFilesList().begin(); it != project->GetFilesList().end(); ++it)
432             {
433                 ProjectFile* pf = *it;
434                 count = m_pParser->FindMatchTokens(pf->file.GetFullPath(), search, result);
435             }
436         }
437         break;
438     }
439     }
440     return count;
441 }
442 
OnSearch(cb_unused wxCommandEvent & event)443 void WorkspaceBrowserF::OnSearch(cb_unused wxCommandEvent& event)
444 {
445     wxString search = m_Search->GetValue();
446     if (search.IsEmpty())
447         return;
448 
449     TokenF* token = 0;
450     TokensArrayF result;
451     size_t count = FindMatchTokens(search, result);
452 
453     size_t j=0;
454     while (j < count)
455     {
456         if ((result.Item(j)->m_TokenKind == tkVariable) ||
457             (result.Item(j)->m_TokenKind == tkCallFunction) ||
458             (result.Item(j)->m_TokenKind == tkCallSubroutine))
459         {
460             result.RemoveAt(j);
461             count--;
462         }
463         else
464         {
465             j++;
466         }
467     }
468 
469     if (count == 0)
470     {
471         cbMessageBox(_("No matches were found: ") + search, _("Search failed"));
472         return;
473     }
474     else if (count == 1)
475     {
476         token = *result.begin();
477     }
478     else if (count > 1)
479     {
480         wxArrayString selections;
481         for (size_t i=0; i<count; ++i)
482         {
483             wxString inf = result.Item(i)->m_DisplayName;;
484             wxFileName fn = wxFileName(result.Item(i)->m_Filename);
485             inf << _T("::") << result.Item(i)->GetTokenKindString() << _T(", ") << fn.GetFullName() << _T(" : ");
486             inf << wxString::Format(_T("%d"), int(result.Item(i)->m_LineStart));
487             selections.Add(inf);
488         }
489         int sel = wxGetSingleChoiceIndex(_("Please make a selection:"), _("Multiple matches"), selections);
490         if (sel == -1)
491             return;
492         token = result.Item(sel);
493     }
494 
495     // store the search in the combobox
496     if (m_Search->FindString(token->m_DisplayName) == wxNOT_FOUND)
497         m_Search->Append(token->m_DisplayName);
498 
499     JumpToToken(token);
500     m_pBrowserBuilder->SelectItem(token);
501 }
502 
BuildTree()503 void WorkspaceBrowserF::BuildTree()
504 {
505     if (Manager::IsAppShuttingDown())
506         return;
507 
508     // create the WorkspaceBrowserBuilder if needed
509     if (!m_pBrowserBuilder)
510     {
511         m_pBrowserBuilder = new WorkspaceBrowserBuilder(m_pParser, m_TreeTop, m_TreeBottom);
512     }
513 
514     if (m_BrowserOptions.visibleBottomTree)
515     {
516         m_SplitterWin->SplitHorizontally(m_TreeTop, m_TreeBottom);
517         m_TreeBottom->Show(true);
518     }
519     else
520     {
521         m_SplitterWin->Unsplit();
522         m_TreeBottom->Show(false);
523     }
524 
525     // build tree
526     m_pBrowserBuilder->Init(
527         m_ActiveFilename,
528         m_pActiveProject,
529         m_BrowserOptions);
530 } // end of BuildTree
531 
OnTreeItemSelected(wxTreeEvent & event)532 void WorkspaceBrowserF::OnTreeItemSelected(wxTreeEvent& event)
533 {
534     if (Manager::IsAppShuttingDown())
535         return;
536 
537     if (m_pBrowserBuilder)
538     {
539         if (!m_pBrowserBuilder->SelectNode(event.GetItem()))
540             return;
541     }
542     event.Allow();
543 
544     EditorManager* edMan = Manager::Get()->GetEditorManager();
545     if (!edMan)
546         return;
547     cbEditor* ed = edMan->GetBuiltinActiveEditor();
548     if (!ed)
549         return;
550     cbStyledTextCtrl* control = ed->GetControl();
551     int currentLine = control->GetCurrentLine() + 1;
552     wxString activeFilename = ed->GetFilename();
553     if (activeFilename.IsEmpty())
554         return;
555     MarkSymbol(UnixFilename(activeFilename), currentLine);
556 }
557 
OnTreeItemExpanding(wxTreeEvent & event)558 void WorkspaceBrowserF::OnTreeItemExpanding(wxTreeEvent& event)
559 {
560     if (Manager::IsAppShuttingDown())
561         return;
562 
563     m_pBrowserBuilder->ExpandTopNode(event.GetItem());
564 }
565 
OnTreeItemCollapsing(wxTreeEvent & event)566 void WorkspaceBrowserF::OnTreeItemCollapsing(wxTreeEvent& event)
567 {
568     m_pBrowserBuilder->CollapsTopNode(event.GetItem());
569     //event.Allow();
570 }
571 
GetTokenKindImageIdx(TokenF * token)572 int WorkspaceBrowserF::GetTokenKindImageIdx(TokenF* token)
573 {
574     if (m_pBrowserBuilder)
575         return m_pBrowserBuilder->GetTokenKindImageIdx(token);
576     return 0;
577 }
578 
MarkSymbol(wxString filename,int line)579 void WorkspaceBrowserF::MarkSymbol(wxString filename, int line)
580 {
581     if (m_pBrowserBuilder)
582     {
583         m_pBrowserBuilder->MarkSymbol(filename, line);
584     }
585 }
586 
SelectSymbol(wxString filename,int line)587 void WorkspaceBrowserF::SelectSymbol(wxString filename, int line)
588 {
589     if (m_pBrowserBuilder)
590     {
591         m_pBrowserBuilder->SelectSymbol(filename, line);
592     }
593 }
594 
RereadOptions()595 void WorkspaceBrowserF::RereadOptions()
596 {
597     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
598     if (cfg->ReadBool(_("/use_symbols_browser"), true))
599     {
600         m_BrowserOptions.visibleBottomTree = cfg->ReadBool(_("/visible_bottom_tree"), true);
601         m_BrowserOptions.sortAlphabetically = cfg->ReadBool(_("/browser_sort_alphabetically"), true);
602         m_BrowserOptions.showLocalVariables = cfg->ReadBool(_T("/browser_show_local_variables"), true);
603         m_BrowserOptions.showIncludeSeparately = cfg->ReadBool(_T("/browser_show_include_files_separately"), true);
604         UpdateView();
605     }
606 }
607 
DeleteAllItems()608 void WorkspaceBrowserF::DeleteAllItems()
609 {
610     m_TreeTop->DeleteAllItems();
611     m_TreeBottom->DeleteAllItems();
612 }
613 
OnMakeVisible(cb_unused wxCommandEvent & event)614 void WorkspaceBrowserF::OnMakeVisible(cb_unused wxCommandEvent& event)
615 {
616     if (m_pBrowserBuilder)
617     {
618         m_pBrowserBuilder->MakeVisibleCurrent();
619     }
620 }
621 
OnMenuEditPaste(wxCommandEvent & event)622 void WorkspaceBrowserF::OnMenuEditPaste(wxCommandEvent& event)
623 {
624     wxWindow* pFocused = wxWindow::FindFocus();
625     if (!pFocused)
626     {
627         event.Skip();
628         return;
629     }
630 
631     if (pFocused == m_Search)
632         m_Search->Paste();
633     else
634         event.Skip();
635 
636     return;
637 }
638 
SetActiveProject(cbProject * prj)639 void WorkspaceBrowserF::SetActiveProject(cbProject* prj)
640 {
641     m_pActiveProject = prj;
642     if (m_pBrowserBuilder)
643     {
644         m_pBrowserBuilder->SetActiveProject(prj);
645     }
646 }
647 
648 
649