diff --git a/src/Frontend/AutoCompleteManager.cpp b/src/Frontend/AutoCompleteManager.cpp index 7a763868..a12fb3e4 100644 --- a/src/Frontend/AutoCompleteManager.cpp +++ b/src/Frontend/AutoCompleteManager.cpp @@ -49,6 +49,15 @@ void AutoCompleteManager::BuildFromProject(const Project* project) { BuildFromFile(project->GetFile(fileIndex)); } + for (unsigned int directoryIndex = 0; directoryIndex < project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory const *directory = project->GetDirectory(directoryIndex); + + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + BuildFromFile(directory->files[fileIndex]); + } + } // Sort the autocompletions (necessary for binary search). std::sort(m_entries.begin(), m_entries.end()); @@ -66,12 +75,12 @@ void AutoCompleteManager::BuildFromFile(const Project::File* file) } -void AutoCompleteManager::GetMatchingItems(const wxString& prefix, bool member, wxString& items) const +void AutoCompleteManager::GetMatchingItems(const wxString& token, const wxString& prefix, bool member, wxString& items) const { // Autocompletion selection is case insensitive so transform everything // to lowercase. - wxString test = prefix.Lower(); + wxString test = token.Lower(); // Add the items to the list that begin with the specified prefix. This // could be done much fater with a binary search since our items are in @@ -79,7 +88,6 @@ void AutoCompleteManager::GetMatchingItems(const wxString& prefix, bool member, for (unsigned int i = 0; i < m_entries.size(); ++i) { - // Check that the scope is correct. bool inScope = false; @@ -89,7 +97,14 @@ void AutoCompleteManager::GetMatchingItems(const wxString& prefix, bool member, // We've got no way of knowing the type of the variable in Lua (since // variables don't have types, only values have types), so we display // all members if the prefix contains a member selection operator (. or :) - inScope = (m_entries[i].scope.IsEmpty() != member); + if (!m_entries[i].scope.IsEmpty() && member) + { + inScope = m_entries[i].scope == prefix; + } + else + { + inScope = m_entries[i].scope.IsEmpty() != member; + } } if (inScope && m_entries[i].lowerCaseName.StartsWith(test)) diff --git a/src/Frontend/AutoCompleteManager.h b/src/Frontend/AutoCompleteManager.h index 0261ba0e..1711b021 100644 --- a/src/Frontend/AutoCompleteManager.h +++ b/src/Frontend/AutoCompleteManager.h @@ -62,7 +62,7 @@ class AutoCompleteManager * only autocompletions that are members of some scope are included. The return items * string is in the format used by Scintilla to display autocompletions. */ - void GetMatchingItems(const wxString& prefix, bool member, wxString& items) const; + void GetMatchingItems(const wxString& token, const wxString& prefix, bool member, wxString& items) const; private: diff --git a/src/Frontend/BreakpointsWindow.cpp b/src/Frontend/BreakpointsWindow.cpp index fa12fadc..5fbbd8a7 100644 --- a/src/Frontend/BreakpointsWindow.cpp +++ b/src/Frontend/BreakpointsWindow.cpp @@ -95,12 +95,20 @@ BreakpointsWindow::BreakpointsWindow(MainFrame* mainFrame, wxWindowID winid) fgSizer1->Add( m_buttonBar, 0, wxALL|wxEXPAND, 3 ); fgSizer1->Add( m_breakpointList, 0, wxALL|wxEXPAND, 0 ); - + + + SetSizer( fgSizer1 ); Layout(); } +void BreakpointsWindow::SetFontColorSettings(const FontColorSettings& settings) +{ + m_breakpointList->SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_breakpointList->SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor); +} + void BreakpointsWindow::SetProject(Project* project) { m_project = project; @@ -124,6 +132,16 @@ void BreakpointsWindow::UpdateBreakpoints() { AddBreakpointsForFile(m_project->GetFile(i)); } + + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + AddBreakpointsForFile(file); + } + } } m_breakpointList->Thaw(); diff --git a/src/Frontend/BreakpointsWindow.h b/src/Frontend/BreakpointsWindow.h index a86ae191..3af4fb86 100644 --- a/src/Frontend/BreakpointsWindow.h +++ b/src/Frontend/BreakpointsWindow.h @@ -24,6 +24,7 @@ along with Decoda. If not, see . #define BREAKPOINTS_WINDOW_H #include "Project.h" +#include "FontColorSettings.h" #include #include @@ -51,6 +52,11 @@ class BreakpointsWindow : public wxPanel */ BreakpointsWindow(MainFrame* mainFrame, wxWindowID winid); + /** + * Updates the colors of the panel to match the settings + */ + void SetFontColorSettings(const FontColorSettings& settings); + /** * Sets the project we're displaying the breakpoints for. */ diff --git a/src/Frontend/CodeEdit.cpp b/src/Frontend/CodeEdit.cpp index d45356f7..4fe40ba4 100644 --- a/src/Frontend/CodeEdit.cpp +++ b/src/Frontend/CodeEdit.cpp @@ -670,6 +670,7 @@ void CodeEdit::StartAutoCompletion(const wxString& token) // If the token refers to a member, the prefix is the member name. wxString prefix; + wxString newToken; bool member = false; if (GetLexer() == wxSCI_LEX_LUA) @@ -702,8 +703,8 @@ void CodeEdit::StartAutoCompletion(const wxString& token) } int end = std::max(end1, end2); - prefix = token.Right( token.Length() - end ); - + newToken = token.Right(token.Length() - end); + prefix = token.Left(end - 1); } else { @@ -711,15 +712,15 @@ void CodeEdit::StartAutoCompletion(const wxString& token) return; } - if (!member && prefix.Length() < m_minAutoCompleteLength) + if (!member && newToken.Length() < m_minAutoCompleteLength) { // Don't pop up the auto completion if the user hasn't typed in very // much yet. return; } - m_autoCompleteManager->GetMatchingItems(prefix, member, items); - + m_autoCompleteManager->GetMatchingItems(newToken, prefix, member, items); + if (!AutoCompActive() || m_autoCompleteItems != items) { @@ -730,7 +731,7 @@ void CodeEdit::StartAutoCompletion(const wxString& token) if (!items.IsEmpty()) { // Show the autocomplete selection list. - AutoCompShow(prefix.Length(), items); + AutoCompShow(newToken.Length(), items); } else { diff --git a/src/Frontend/FontColorSettings.cpp b/src/Frontend/FontColorSettings.cpp index 49881350..65c83ac7 100644 --- a/src/Frontend/FontColorSettings.cpp +++ b/src/Frontend/FontColorSettings.cpp @@ -25,7 +25,7 @@ along with Decoda. If not, see . #include -const char* FontColorSettings::s_displayItemName[] = { "Default", "Comment", "Keyword", "Operator", "String", "Number", "Error", "Warning", "Selection" }; +const char* FontColorSettings::s_displayItemName[] = { "Default", "Comment", "Keyword", "Operator", "String", "Number", "Error", "Warning", "Selection", "Window" }; FontColorSettings::FontColorSettings() { @@ -77,6 +77,11 @@ FontColorSettings::FontColorSettings() m_colors[DisplayItem_Selection].bold = false; m_colors[DisplayItem_Selection].italic = false; + m_colors[DisplayItem_Window].foreColor = wxColor(255,255,255); + m_colors[DisplayItem_Window].backColor = wxColor(51,51,51); + m_colors[DisplayItem_Window].bold = false; + m_colors[DisplayItem_Window].italic = false; + } unsigned int FontColorSettings::GetNumDisplayItems() const diff --git a/src/Frontend/FontColorSettings.h b/src/Frontend/FontColorSettings.h index d327594c..b8c2c51d 100644 --- a/src/Frontend/FontColorSettings.h +++ b/src/Frontend/FontColorSettings.h @@ -52,6 +52,7 @@ class FontColorSettings DisplayItem_Error, DisplayItem_Warning, DisplayItem_Selection, + DisplayItem_Window, DisplayItem_Last, }; diff --git a/src/Frontend/ListWindow.cpp b/src/Frontend/ListWindow.cpp index a1989adf..3382eb07 100644 --- a/src/Frontend/ListWindow.cpp +++ b/src/Frontend/ListWindow.cpp @@ -49,7 +49,12 @@ ListWindow::ListWindow(MainFrame* mainFrame, wxWindowID winid) imageList->Add( wxMEMORY_BITMAP(Currentline_png) ); AssignImageList(imageList, wxIMAGE_LIST_SMALL); +} +void ListWindow::SetFontColorSettings(const FontColorSettings& settings) +{ + SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor); } void ListWindow::Append(const wxString& name) diff --git a/src/Frontend/ListWindow.h b/src/Frontend/ListWindow.h index b592431d..c45c3dfa 100644 --- a/src/Frontend/ListWindow.h +++ b/src/Frontend/ListWindow.h @@ -26,6 +26,7 @@ along with Decoda. If not, see . #include #include "ListView.h" +#include "FontColorSettings.h" // // Forward declarations. @@ -52,6 +53,11 @@ class ListWindow : public ListView */ ListWindow(MainFrame* mainFrame, wxWindowID winid); + /** + * Updates the colors of the panel to match the settings + */ + void SetFontColorSettings(const FontColorSettings& settings); + /** * Adds an item to the list. */ diff --git a/src/Frontend/MainApp.cpp b/src/Frontend/MainApp.cpp index 60ece961..f77b49c9 100644 --- a/src/Frontend/MainApp.cpp +++ b/src/Frontend/MainApp.cpp @@ -100,7 +100,6 @@ bool MainApp::OnInit() UINT openFilesMessage = RegisterWindowMessage("Decoda_OpenFiles"); // Check to see if another instances is running. - if (!wxApp::OnInit()) { return false; diff --git a/src/Frontend/MainFrame.cpp b/src/Frontend/MainFrame.cpp index c060d579..e239903a 100644 --- a/src/Frontend/MainFrame.cpp +++ b/src/Frontend/MainFrame.cpp @@ -67,6 +67,7 @@ along with Decoda. If not, see . #include #include #include +#include #include #include #include @@ -132,6 +133,7 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame) // Project menu events. EVT_MENU(ID_ProjectAddExistingFile, MainFrame::OnProjectAddExistingFile) + EVT_MENU(ID_ProjectAddDirectory, MainFrame::OnProjectAddDirectory) EVT_MENU(ID_ProjectAddNewFile, MainFrame::OnProjectAddNewFile) EVT_MENU(ID_ProjectSettings, MainFrame::OnProjectSettings) EVT_MENU(ID_FileNewProject, MainFrame::OnFileNewProject) @@ -275,6 +277,7 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame) EVT_COMMAND(wxID_ANY, wxEVT_UPDATE_INFO_EVENT, MainFrame::OnUpdateInfo) EVT_SYMBOL_PARSER( MainFrame::OnSymbolsParsed) + //EVT_SYMBOL_PARSER( MainFrame::OnSymbolsParsed) END_EVENT_TABLE() @@ -455,6 +458,11 @@ MainFrame::MainFrame(const wxString& title, int openFilesMessage, const wxPoint& m_projectExplorer->SetFileContextMenu(m_contextMenu); + m_directoryContextMenu = new wxMenu; + m_directoryContextMenu->Append(ID_ProjectAddNewFile, _("Add New File")); + + m_projectExplorer->SetDirectoryContextMenu(m_directoryContextMenu); + m_notebookTabMenu = new wxMenu; m_notebookTabMenu->Append(ID_NotebookTabSave, _("&Save")); @@ -490,6 +498,7 @@ MainFrame::MainFrame(const wxString& title, int openFilesMessage, const wxPoint& m_symbolParser = new SymbolParser; m_symbolParser->SetEventHandler(this); + m_waitForFinalSymbolParse = false; // Creating a new project will clear this out, so save it. @@ -630,6 +639,7 @@ void MainFrame::InitializeMenu() menuProject->AppendSeparator(); menuProject->Append(ID_ProjectAddNewFile, _("Add Ne&w File...")); menuProject->Append(ID_ProjectAddExistingFile, _("Add Existin&g File...")); + menuProject->Append(ID_ProjectAddDirectory, _("Add Directory...")); menuProject->AppendSeparator(); menuProject->AppendSubMenu(menuRecentProjects, _("&Recent Files...")); menuProject->AppendSeparator(); @@ -709,7 +719,6 @@ void MainFrame::InitializeMenu() menuBar->Append( menuHelp, _("&Help")); SetMenuBar( menuBar ); - } void MainFrame::OnFileNewProject(wxCommandEvent& WXUNUSED(event)) @@ -1056,7 +1065,6 @@ void MainFrame::OnEditFindPrevious(wxCommandEvent& event) void MainFrame::OnEditFindInFiles(wxCommandEvent& event) { - FindInFilesDialog dialog(this); dialog.AddLookIn("Current Project"); @@ -1148,6 +1156,30 @@ void MainFrame::OnEditFindInFiles(wxCommandEvent& event) } } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + if (!file->temporary) + { + + wxString fileName = file->fileName.GetFullPath(); + wxString caseFileName = fileName.Lower(); + + for (unsigned int j = 0; j < fileTypesArray.Count(); ++j) + { + if (caseFileName.Matches(fileTypesArray[j])) + { + fileNames.Add(fileName); + } + } + + } + } + } + baseDirectory = wxFileName(m_project->GetFileName()).GetPath(); } @@ -1257,6 +1289,10 @@ void MainFrame::OnProjectAddNewFile(wxCommandEvent& WXUNUSED(event)) wxFileName projectFileName(m_project->GetFileName()); wxString projectPath = projectFileName.GetPathWithSep(); + wxString selectedName = m_projectExplorer->GetSelectedDirectoryName(); + + if (selectedName.IsEmpty() == false) + projectPath = selectedName; // If the project hasn't been saved yet and we're using source control, // use the path in source control. @@ -1297,20 +1333,28 @@ void MainFrame::OnProjectAddNewFile(wxCommandEvent& WXUNUSED(event)) file.Close(); Project::File* file = m_project->AddFile(fileName.GetFullPath()); - UpdateForNewFile(file); - - if (m_sourceControl.GetIsInitialized() && dialog.GetAddToSourceContrl()) + if (file->localPath.IsEmpty()) { + UpdateForNewFile(file); + + if (m_sourceControl.GetIsInitialized() && dialog.GetAddToSourceContrl()) + { // Add the file to source control. m_sourceControl.AddFiles(std::string(fileName.GetFullPath()), NULL); - } + } - // Update the status for the new files. - UpdateProjectFileStatus(file); + // Update the status for the new files. + UpdateProjectFileStatus(file); + } + else + { + m_projectExplorer->SaveExpansion(); + m_projectExplorer->Rebuild(); + m_projectExplorer->LoadExpansion(); + } // Open the file in the editor. OpenProjectFile(file); - } else { @@ -1354,6 +1398,29 @@ void MainFrame::OnProjectAddExistingFile(wxCommandEvent& WXUNUSED(event)) } +void MainFrame::OnProjectAddDirectory(wxCommandEvent& event) +{ + wxDirDialog dialog(this, _("Add Directory"), m_project->GetBaseDirectory(), wxDD_DEFAULT_STYLE); + + if (dialog.ShowModal() == wxID_OK) + { + Project::Directory *directory = m_project->AddDirectory(dialog.GetPath()); + + m_projectExplorer->InsertDirectory(directory); + + for (Project::File *file : directory->files) + { + m_symbolParser->QueueForParsing(file); + m_autoCompleteManager.BuildFromProject(m_project); + + // Update the status for the new files. + UpdateProjectFileStatus(file); + } + } + + +} + void MainFrame::OnProjectSettings(wxCommandEvent& WXUNUSED(event)) { ShowProjectSettingsDialog(); @@ -3026,6 +3093,22 @@ bool MainFrame::ParseErrorMessage(const wxString& error, wxString& fileName, uns } } + + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + wxString fullName = file->fileName.GetFullPath(); + + if (fullName.EndsWith(partialName)) + { + fileName = fullName; + foundMatch = true; + } + } + } } @@ -3257,14 +3340,14 @@ void MainFrame::OnProjectExplorerItemActivated(wxTreeEvent& event) ProjectExplorerWindow::ItemData* data = m_projectExplorer->GetDataForItem(item); - if (data != NULL && data->file != NULL) + if (data != NULL && data->file != NULL && data->isFile) { - - OpenFile* file = OpenProjectFile(data->file); + Project::File *dataFile = (Project::File *)data->file; + OpenFile* file = OpenProjectFile(dataFile); if (file == NULL) { - wxMessageBox(wxString::Format("The file '%s' could not be opened.", data->file->fileName.GetFullPath())); + wxMessageBox(wxString::Format("The file '%s' could not be opened.", dataFile->fileName.GetFullPath())); } else { @@ -3298,6 +3381,14 @@ void MainFrame::OnProjectExplorerKeyDown(wxTreeEvent& event) } } + std::vector directories; + m_projectExplorer->GetSelectedDirectories(directories); + for (unsigned int i = 0; i < directories.size(); ++i) + { + DeleteProjectDirectory(directories[i]); + alltemp = false; + } + if (alltemp) { // Tell the user why we didn't delete any of the files the selected. @@ -4407,6 +4498,17 @@ MainFrame::OpenFile* MainFrame::OpenProjectFile(Project::File* file) void MainFrame::DeleteProjectFile(Project::File* file) { + if (file->localPath.IsEmpty() == false) + { + wxMessageDialog *dial = new wxMessageDialog(NULL, wxT("Are you sure you want to delete this file?"), wxT("Question"), + wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); + + if (dial->ShowModal() != wxID_YES) + { + return; + } + } + for (unsigned int i = 0; i < m_openFiles.size(); ++i) { @@ -4425,6 +4527,27 @@ void MainFrame::DeleteProjectFile(Project::File* file) } +void MainFrame::DeleteProjectDirectory(Project::Directory* directory) +{ + for (Project::File *file : directory->files) + { + for (unsigned int i = 0; i < m_openFiles.size(); ++i) + { + if (m_openFiles[i]->file == file) + { + m_notebook->DeletePage(i); + m_openFiles.erase(m_openFiles.begin() + i); + RemovePageFromTabOrder(i); + break; + } + } + m_breakpointsWindow->RemoveFile(file); + } + + m_projectExplorer->RemoveDirectory(directory); + m_project->RemoveDirectory(directory); +} + void MainFrame::AddVmToList(unsigned int vm) { @@ -4670,7 +4793,18 @@ void MainFrame::UpdateEditorOptions() } // Set the font of the output window to match the code editor. + m_mgr.GetArtProvider()->SetColor(wxAUI_DOCKART_SASH_COLOUR, m_fontColorSettings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + + m_searchWindow->SetFontColorSettings(m_fontColorSettings); + m_breakpointsWindow->SetFontColorSettings(m_fontColorSettings); + m_projectExplorer->SetFontColorSettings(m_fontColorSettings); m_output->SetFontColorSettings(m_fontColorSettings); + m_watch->SetFontColorSettings(m_fontColorSettings); + m_callStack->SetFontColorSettings(m_fontColorSettings); + m_vmList->SetFontColorSettings(m_fontColorSettings); + + //Have to repaint to get the sash color. + this->Refresh(); // Set the font of the watch window to match the code editor so // that non-ASCII text will be displayed properly. @@ -4869,6 +5003,43 @@ void MainFrame::DeleteAllBreakpoints() m_project->DeleteAllBreakpoints(file); } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + + unsigned int openFileIndex = GetOpenFileIndex(file); + OpenFile* openFile = NULL; + + if (openFileIndex != -1) + { + openFile = m_openFiles[openFileIndex]; + } + + unsigned int scriptIndex = file->scriptIndex; + + for (unsigned int breakpointIndex = 0; breakpointIndex < file->breakpoints.size(); ++breakpointIndex) + { + + unsigned int newLine = file->breakpoints[breakpointIndex]; + + // This file does not have a counterpart in the script debugger, so just + // set the break point "locally". When the debugger encounters the file + // we'll send it the break points. + + if (openFile != NULL) + { + UpdateFileBreakpoint(openFile, newLine, false); + } + + } + + m_project->DeleteAllBreakpoints(file); + } + } + DebugFrontend::Get().RemoveAllBreakPoints(0); m_breakpointsWindow->UpdateBreakpoints(); @@ -5140,6 +5311,24 @@ void MainFrame::OnThreadExit(ThreadEvent& event) } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + + stdext::hash_map::iterator iterator; + iterator = statusMap.find(std::string(file->fileName.GetFullPath())); + + if (iterator != statusMap.end()) + { + SourceControl::Status status = iterator->second; + SetFileStatus(file, status); + } + } + } + m_projectExplorer->UpdateFileImages(); m_fileStatusThread[0]->Wait(); @@ -5403,6 +5592,19 @@ void MainFrame::CleanUpTemporaryFiles() } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + if (file->temporary && GetOpenFileIndex(file) == -1) + { + files.push_back(file); + } + } + } + m_projectExplorer->RemoveFiles(files); for (unsigned int i = 0; i < files.size(); ++i) @@ -5638,6 +5840,16 @@ void MainFrame::UpdateProjectFileStatus() thread->AddFileName(file->fileName.GetFullPath()); } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + Project::File *file = directory->files[fileIndex]; + thread->AddFileName(file->fileName.GetFullPath()); + } + } + if (thread == m_fileStatusThread[0]) { thread->Create(); @@ -6043,6 +6255,23 @@ Project::File* MainFrame::GetFileMatchingSource(const wxFileName& fileName, cons } + for (unsigned int directoryIndex = 0; directoryIndex < m_project->GetNumDirectories(); ++directoryIndex) + { + Project::Directory *directory = m_project->GetDirectory(directoryIndex); + + for (unsigned int i = 0; i < directory->files.size(); ++i) + { + + Project::File* file = directory->files[i]; + + if (file->scriptIndex == -1 && file->fileName.GetFullName().CmpNoCase(fileName.GetFullName()) == 0) + { + return file; + } + + } + } + return NULL; } @@ -6083,9 +6312,12 @@ void MainFrame::OnSymbolsParsed(SymbolParserEvent& event) m_waitForFinalSymbolParse = false; m_statusBar->SetStatusText("", 0); - //Set the project to itself so we can trigger Rebuild() - m_projectExplorer->SetProject(m_project); - + //Rebuild the project and the expansion + m_projectExplorer->SaveExpansion(); + m_projectExplorer->Rebuild(); + m_projectExplorer->LoadExpansion(); + + m_autoCompleteManager.BuildFromProject(m_project); return; } } diff --git a/src/Frontend/MainFrame.h b/src/Frontend/MainFrame.h index c88af491..9b989b65 100644 --- a/src/Frontend/MainFrame.h +++ b/src/Frontend/MainFrame.h @@ -244,6 +244,11 @@ class MainFrame: public wxFrame */ void OnProjectAddExistingFile(wxCommandEvent& event); + /** + * Called when the user selects Project/Add Directory from the menu. + */ + void OnProjectAddDirectory(wxCommandEvent& event); + /** * Called when the user selects Project/Add New File from the menu. */ @@ -1081,6 +1086,11 @@ class MainFrame: public wxFrame */ void DeleteProjectFile(Project::File* file); + /** + * Removes a directory from the project (does not delete the directory on disk). + */ + void DeleteProjectDirectory(Project::Directory* directory); + /** * Updates the break point marker in an open file. If set is enabled the * marker will be added at the specified line, otherwise it will be removed. @@ -1369,6 +1379,7 @@ class MainFrame: public wxFrame ID_EditFind = 16, ID_EditFindNext = 17, ID_ProjectAddExistingFile = 18, + ID_ProjectAddDirectory = 88, ID_ProjectSettings = 19, ID_DebugStart = 20, ID_DebugStop = 21, @@ -1517,6 +1528,7 @@ class MainFrame: public wxFrame SourceControl m_sourceControl; wxMenu* m_contextMenu; + wxMenu* m_directoryContextMenu; wxMenu* m_notebookTabMenu; FileStatusThread* m_fileStatusThread[2]; diff --git a/src/Frontend/OutputWindow.cpp b/src/Frontend/OutputWindow.cpp index e5cb5597..c899bc74 100644 --- a/src/Frontend/OutputWindow.cpp +++ b/src/Frontend/OutputWindow.cpp @@ -46,18 +46,18 @@ void OutputWindow::SetFontColorSettings(const FontColorSettings& settings) // happens often enough for it to really make much difference. Clear(); - SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Default).backColor); + SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); - m_messageAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Default).foreColor); - m_messageAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Default).backColor); - m_messageAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Default)); + m_messageAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor); + m_messageAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_messageAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Window)); m_warningAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Warning).foreColor); - m_warningAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Warning).backColor); + m_warningAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); m_warningAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Warning)); m_errorAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Error).foreColor); - m_errorAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Error).backColor); + m_errorAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); m_errorAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Error)); } diff --git a/src/Frontend/Project.cpp b/src/Frontend/Project.cpp index e32ba8b6..0e0d0fba 100644 --- a/src/Frontend/Project.cpp +++ b/src/Frontend/Project.cpp @@ -28,6 +28,7 @@ along with Decoda. If not, see . #include "Symbol.h" #include +#include #include #include @@ -75,6 +76,17 @@ Project::~Project() ClearVector(m_files[i]->symbols); } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory *directory = m_directories[i]; + for (unsigned int j = 0; j < directory->files.size(); ++j) + { + File *file = directory->files[j]; + + ClearVector(file->symbols); + } + } + ClearVector(m_files); } @@ -281,6 +293,16 @@ const Project::File* Project::GetFile(unsigned int fileIndex) const return m_files[fileIndex]; } +const Project::Directory *Project::GetDirectory(unsigned int dirIndex) const +{ + return m_directories[dirIndex]; +} + +Project::Directory *Project::GetDirectory(unsigned int dirIndex) +{ + return m_directories[dirIndex]; +} + Project::File* Project::GetFileById(unsigned int fileId) { @@ -292,6 +314,18 @@ Project::File* Project::GetFileById(unsigned int fileId) } } + for (unsigned int directoryIndex = 0; directoryIndex < m_directories.size(); ++directoryIndex) + { + Project::Directory *directory = m_directories[directoryIndex]; + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + if (directory->files[fileIndex]->fileId == fileId) + { + return directory->files[fileIndex]; + } + } + } + return NULL; } @@ -301,6 +335,11 @@ unsigned int Project::GetNumFiles() const return m_files.size(); } +unsigned int Project::GetNumDirectories() const +{ + return m_directories.size(); +} + Project::File* Project::AddFile(const wxString& fileName) { @@ -325,14 +364,113 @@ Project::File* Project::AddFile(const wxString& fileName) if (fileName.IsEmpty()) { - file->tempName = CreateTempName(); + file->tempName = CreateTempName(); } + + if (fileName.Contains('\\')) + { + Directory *bestDirectory = nullptr; + int bestCompare = 0; - m_files.push_back(file); + for (Directory *directory : m_directories) + { + int compare = fileName.CompareTo(directory->name); + if (compare > bestCompare) + { + bestDirectory = directory; + bestCompare = compare; + } + } + + if (bestDirectory == nullptr) + { + m_files.push_back(file); + } + else + { + wxFileName localPath(fileName); + localPath.MakeRelativeTo(bestDirectory->name); + + file->localPath = localPath.GetPath(); + + bestDirectory->files.push_back(file); + } + } + else + { + m_files.push_back(file); + } + m_needsSave = true; return file; +} +Project::Directory* Project::AddDirectory(const wxString& directoryStr) +{ + wxString directoryName = directoryStr; + + wxString fullDir; + wxFileName path(directoryName); + path.Normalize(wxPATH_NORM_ALL, m_baseDirectory); + path.MakeRelativeTo(m_baseDirectory); + fullDir = path.GetFullPath(); + + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + if (m_directories[i]->path == fullDir) + { + return NULL; + } + } + + wxDir directory(m_baseDirectory + "\\" + fullDir); + wxArrayString filenames; + + Directory *dir = new Directory; + + if (directory.IsOpened()) + { + wxString dirPath = directory.GetName(); + + wxFileName name(m_baseDirectory + "\\" + fullDir); + name.Normalize(); + + dir->name = name.GetFullPath(); + dir->path = fullDir; + + directory.GetAllFiles(dirPath, &filenames, wxEmptyString, wxDIR_DIRS | wxDIR_FILES); + } + + for (auto &filename : filenames) + { + File* file = new File; + + file->state = CodeState_Normal; + file->scriptIndex = -1; + file->temporary = false; + file->status = Status_None; + file->fileId = ++s_lastFileId; + + wxFileName localPath(filename); + localPath.MakeRelativeTo(dir->name); + + file->localPath = localPath.GetPath(); + file->directoryPath = dir->name; + + file->fileName = filename; + if (file->fileName.IsRelative()) + { + file->fileName.MakeAbsolute(m_baseDirectory); + } + + dir->files.push_back(file); + } + + m_directories.push_back(dir); + m_needsSave = true; + + return dir; } Project::File* Project::AddTemporaryFile(unsigned int scriptIndex) @@ -349,6 +487,7 @@ Project::File* Project::AddTemporaryFile(unsigned int scriptIndex) file->fileName = script->name.c_str(); file->status = Status_None; file->fileId = ++s_lastFileId; + file->localPath = "Debug Temporary Files"; m_files.push_back(file); @@ -393,15 +532,66 @@ void Project::RemoveFile(File* file) { m_needsSave = true; m_needsUserSave = true; + } + + ClearVector(file->symbols); + delete file; + break; } ++iterator; } - - ClearVector(file->symbols); - delete file; + std::vector::iterator dirIterator = m_directories.begin(); + + while (dirIterator != m_directories.end()) + { + iterator = (*dirIterator)->files.begin(); + while (iterator != (*dirIterator)->files.end()) + { + if (file == *iterator) + { + (*dirIterator)->files.erase(iterator); + if (!file->temporary) + { + wxRemoveFile(file->fileName.GetFullPath()); + + m_needsSave = true; + m_needsUserSave = true; + } + break; + } + ++iterator; + } + + ++dirIterator; + } +} + +void Project::RemoveDirectory(Directory* directory) +{ + std::vector::iterator iterator = m_directories.begin(); + + while (iterator != m_directories.end()) + { + if (directory == *iterator) + { + for (File *file : directory->files) + { + ClearVector(file->symbols); + delete file; + } + + m_directories.erase(iterator); + m_needsSave = true; + m_needsUserSave = true; + break; + } + ++iterator; + } + + delete directory; } void Project::CleanUpAfterSession() @@ -412,6 +602,16 @@ void Project::CleanUpAfterSession() m_files[i]->scriptIndex = -1; } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory *directory = m_directories[i]; + for (unsigned int j = 0; j < directory->files.size(); ++j) + { + File *file = directory->files[j]; + + file->scriptIndex = -1; + } + } } Project::File* Project::GetFileForScript(unsigned int scriptIndex) const @@ -425,6 +625,18 @@ Project::File* Project::GetFileForScript(unsigned int scriptIndex) const } } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory *directory = m_directories[i]; + for (unsigned int j = 0; j < directory->files.size(); ++j) + { + File *file = directory->files[j]; + + if (file->scriptIndex == scriptIndex) + return file; + } + } + return NULL; } @@ -440,6 +652,18 @@ Project::File* Project::GetFileForFileName(const wxFileName& fileName) const } } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory *directory = m_directories[i]; + for (unsigned int j = 0; j < directory->files.size(); ++j) + { + File *file = directory->files[j]; + + if (file->fileName.GetFullName().CmpNoCase(fileName.GetFullName()) == 0) + return file; + } + } + return NULL; } @@ -481,6 +705,46 @@ void Project::SetBreakpoint(unsigned int scriptIndex, unsigned int line, bool se } } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory *directory = m_directories[i]; + for (unsigned int j = 0; j < directory->files.size(); ++j) + { + File *file = directory->files[j]; + + if (file->scriptIndex == scriptIndex) + { + + std::vector::iterator iterator; + iterator = std::find(file->breakpoints.begin(), file->breakpoints.end(), line); + + if (set) + { + if (iterator == file->breakpoints.end()) + { + file->breakpoints.push_back(line); + if (!file->temporary) + { + m_needsUserSave = true; + } + } + } + else + { + if (iterator != file->breakpoints.end()) + { + file->breakpoints.erase(iterator); + if (!file->temporary) + { + m_needsUserSave = true; + } + } + } + + } + } + } + } bool Project::ToggleBreakpoint(File* file, unsigned int line) @@ -544,6 +808,16 @@ wxXmlNode* Project::SaveFileNode(const wxString& baseDirectory, const File* file } +wxXmlNode* Project::SaveDirectoryNode(const Directory* dir) +{ + //Convert empty string to current directory. + wxString path = dir->path; + if (path == "") + path = ".\\"; + + return WriteXmlNode("directory", path); +} + wxXmlNode* Project::SaveUserFileNode(const wxString& baseDirectory, const File* file) const { @@ -717,6 +991,67 @@ bool Project::LoadFileNode(const wxString& baseDirectory, wxXmlNode* node) } +bool Project::LoadDirectoryNode(const wxString& baseDirectory, wxXmlNode* node) +{ + if (node->GetName() != "directory") + { + return false; + } + wxString directoryName; + wxArrayString filenames; + + + if (ReadXmlNode(node, "directory", directoryName)) + { + wxString fullDir; + wxFileName path(directoryName); + path.Normalize(wxPATH_NORM_ALL, m_baseDirectory); + path.MakeRelativeTo(m_baseDirectory); + fullDir = path.GetFullPath(); + + wxDir directory(m_baseDirectory + "\\" + fullDir); + + Directory *dir = new Directory; + + if (directory.IsOpened()) + { + wxString dirPath = directory.GetName(); + + wxFileName name(m_baseDirectory + "\\" + fullDir); + name.Normalize(); + + dir->name = name.GetFullPath(); + dir->path = fullDir; + directory.GetAllFiles(dirPath, &filenames, wxEmptyString, wxDIR_DIRS | wxDIR_FILES); + } + + for (auto &filename : filenames) + { + File* file = new File; + + file->state = CodeState_Normal; + file->scriptIndex = -1; + file->temporary = false; + file->status = Status_None; + file->fileId = ++s_lastFileId; + + wxFileName localPath(filename); + localPath.MakeRelativeTo(dir->name); + + file->localPath = localPath.GetPath(); + file->directoryPath = dir->name; + file->fileName = filename; + + dir->files.push_back(file); + } + + m_directories.push_back(dir); + } + + return true; + +} + std::vector Project::GetSortedFileList() { struct SortByDisplayName @@ -765,6 +1100,15 @@ bool Project::SaveGeneralSettings(const wxString& fileName) } } + for (unsigned int i = 0; i < m_directories.size(); ++i) + { + Directory* dir = m_directories[i]; + assert(dir != NULL); + + wxXmlNode* node = SaveDirectoryNode(dir); + root->AddChild(node); + } + return document.Save(fileName); } @@ -876,7 +1220,7 @@ bool Project::LoadGeneralSettings(const wxString& fileName) // Disable logging. wxLogNull logNo; - wxString baseDirectory = wxFileName(fileName).GetPath(); + m_baseDirectory = wxFileName(fileName).GetPath(); wxXmlDocument document; @@ -896,7 +1240,11 @@ bool Project::LoadGeneralSettings(const wxString& fileName) while (node != NULL) { - LoadFileNode(baseDirectory, node); + if (node->GetName() == "file") + LoadFileNode(m_baseDirectory, node); + else if (node->GetName() == "directory") + LoadDirectoryNode(m_baseDirectory, node); + node = node->GetNext(); } @@ -934,4 +1282,9 @@ bool Project::LoadSccNode(wxXmlNode* root) return true; +} + +wxString Project::GetBaseDirectory() const +{ + return m_baseDirectory; } \ No newline at end of file diff --git a/src/Frontend/Project.h b/src/Frontend/Project.h index c74f62dd..8dcbde77 100644 --- a/src/Frontend/Project.h +++ b/src/Frontend/Project.h @@ -30,6 +30,7 @@ along with Decoda. If not, see . #include +#undef RemoveDirectory // // Forward declarations. // @@ -61,6 +62,7 @@ class Project CodeState state; bool temporary; unsigned int scriptIndex; + wxString localPath; wxFileName fileName; std::vector breakpoints; wxString tempName; @@ -70,7 +72,22 @@ class Project unsigned int fileId; // Unique id we use to match up symbol parsing results. std::vector symbols; + wxString directoryPath; + }; + struct Directory + { + ~Directory() + { + for (File *p : files) + { + delete p; + } + } + + wxString path; + wxString name; + std::vector files; }; /** @@ -225,6 +242,11 @@ class Project */ File* AddFile(const wxString& fileName); + /** + * Adds a directory to the project. The new directory is returned. + */ + Directory* AddDirectory(const wxString& fileName); + /** * Adds a script to the project temporarily (during this debug sesssion). The * new file is returned. @@ -242,6 +264,11 @@ class Project */ void RemoveFile(File* file); + /** + * Removes a directory from the project. + */ + void RemoveDirectory(Directory* directory); + /** * Gets the specified file. */ @@ -252,6 +279,17 @@ class Project */ const File* GetFile(unsigned int fileIndex) const; + + /** + * Gets the specified directory. + */ + Directory* GetDirectory(unsigned int dirIndex); + + /** + * Gets the specified directory. + */ + const Directory *GetDirectory(unsigned int dirIndex) const; + /** * Returns the file with the specified file id, or NULL if the file doesn't * exist in the project. @@ -263,6 +301,12 @@ class Project */ unsigned int GetNumFiles() const; + /** + * Gets the number of directories in the project. + */ + unsigned int GetNumDirectories() const; + + /** * Clears the script indices for all of the files. */ @@ -285,6 +329,11 @@ class Project */ void DeleteAllBreakpoints(File* file); + /** + * Gets the base directory path + */ + wxString GetBaseDirectory() const; + private: /** @@ -293,6 +342,12 @@ class Project */ wxXmlNode* SaveFileNode(const wxString& baseDirectory, const File* file); + /** + * Creates a new XML node representing a directory. The directory name is stored + relative to the project. + */ + wxXmlNode* SaveDirectoryNode(const Directory* file); + /** * Creates a new XML node representing the user settings for a file. The * file name is stored relative to the specified base directory. @@ -307,6 +362,8 @@ class Project */ bool LoadFileNode(const wxString& baseDirectory, wxXmlNode* node); + bool LoadDirectoryNode(const wxString& baseDirectory, wxXmlNode* node); + /** * Loads the user data for a file from an XML node. If the XML node is not * a file node, the method returns false. @@ -363,27 +420,28 @@ class Project // Returns vector for temporary internal use std::vector GetSortedFileList(); - static unsigned int s_lastFileId; - - bool m_needsSave; - bool m_needsUserSave; - wxString m_fileName; - - wxString m_commandLine; - wxString m_commandArguments; - wxString m_workingDirectory; - wxString m_symbolsDirectory; - - std::vector m_files; - - unsigned int m_tempIndex; - - wxString m_sccProvider; - wxString m_sccUser; - wxString m_sccProjName; - wxString m_sccLocalPath; - wxString m_sccAuxProjPath; - + static unsigned int s_lastFileId; + + bool m_needsSave; + bool m_needsUserSave; + wxString m_fileName; + + wxString m_commandLine; + wxString m_commandArguments; + wxString m_workingDirectory; + wxString m_symbolsDirectory; + + std::vector m_files; + std::vector m_directories; + + unsigned int m_tempIndex; + + wxString m_sccProvider; + wxString m_sccUser; + wxString m_sccProjName; + wxString m_sccLocalPath; + wxString m_sccAuxProjPath; + wxString m_baseDirectory; }; #endif diff --git a/src/Frontend/ProjectExplorerWindow.cpp b/src/Frontend/ProjectExplorerWindow.cpp index 56ed75ba..2aa301b8 100644 --- a/src/Frontend/ProjectExplorerWindow.cpp +++ b/src/Frontend/ProjectExplorerWindow.cpp @@ -31,6 +31,10 @@ along with Decoda. If not, see . #include #include +#include +#include +WX_DECLARE_STACK(wxTreeItemId, wxStack); + #include #include "res/explorer.xpm" @@ -104,7 +108,7 @@ ProjectExplorerWindow::ProjectExplorerWindow(wxWindow* parent, wxWindowID winid) gSizer2->AddGrowableRow( 0 ); gSizer2->SetFlexibleDirection( wxBOTH ); - m_searchBox = new SearchTextCtrl( this, ID_Filter, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_searchBox = new SearchTextCtrl(this, ID_Filter, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RICH); m_filterButton = new wxBitmapButton( this, ID_FilterButton, wxNullBitmap, wxDefaultPosition, wxSize(18, 17), 0 ); m_filterPopup = NULL; @@ -114,7 +118,7 @@ ProjectExplorerWindow::ProjectExplorerWindow(wxWindow* parent, wxWindowID winid) gSizer1->Add( gSizer2, 1, wxEXPAND, 5 ); - m_tree = new wxTreeCtrl(this, winid, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT | wxTR_MULTIPLE | wxTR_EXTENDED); + m_tree = new wxProjectTree(this, winid, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT | wxTR_MULTIPLE | wxTR_EXTENDED); m_tree->AssignImageList(imageList); // The "best size" for the tree component must be 0 so that the tree control doesn't @@ -135,10 +139,11 @@ ProjectExplorerWindow::ProjectExplorerWindow(wxWindow* parent, wxWindowID winid) m_project = NULL; m_contextMenu = NULL; + m_directoryContextMenu = NULL; m_filterMatchAnywhere = false; + m_hasFilter = false; UpdateFilterButtonImage(); - } ProjectExplorerWindow::~ProjectExplorerWindow() @@ -146,6 +151,22 @@ ProjectExplorerWindow::~ProjectExplorerWindow() delete m_filterImageList; } + +void ProjectExplorerWindow::SetFontColorSettings(const FontColorSettings& settings) +{ + SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_tree->SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + + m_searchBox->SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_searchBox->SetDefaultStyle(wxTextAttr(settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor)); + + m_infoBox->SetFontColorSettings(settings); + + m_itemColor = settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor; + + Rebuild(); +} + void ProjectExplorerWindow::SetFocusToFilter() { // Select all of the text in the box (makes it easy to clear). @@ -156,13 +177,17 @@ void ProjectExplorerWindow::SetFocusToFilter() void ProjectExplorerWindow::SetProject(Project* project) { m_project = project; + m_expandedIds.clear(); Rebuild(); } ProjectExplorerWindow::ItemData* ProjectExplorerWindow::GetDataForItem(wxTreeItemId id) const { - ItemData* data = static_cast(m_tree->GetItemData(id)); - return data; + ItemData* data = nullptr; + if (id.IsOk()) + data =static_cast(m_tree->GetItemData(id)); + + return data; } wxTreeItemId ProjectExplorerWindow::GetSelection() const @@ -184,9 +209,18 @@ wxTreeItemId ProjectExplorerWindow::GetSelection() const void ProjectExplorerWindow::OnFilterTextChanged(wxCommandEvent& event) { - + //No previous filter + if (m_hasFilter == false) + { + SaveExpansion(); + m_hasFilter = true; + } + m_filter = m_searchBox->GetValue(); + if (m_filter.size() == 0) + m_hasFilter = false; + // If the filter begins with a space, we'll match the text anywhere in the // the symbol name. unsigned int filterLength = m_filter.Length(); @@ -198,6 +232,20 @@ void ProjectExplorerWindow::OnFilterTextChanged(wxCommandEvent& event) Rebuild(); + if (filterLength > 0) + { + //Expand all directories + TraverseTree(m_root, [&, this](wxTreeItemId const &item) + { + ItemData* data = static_cast(m_tree->GetItemData(item)); + if (!data || data->isFile == false) + m_tree->Expand(item); + }); + } + else + { + LoadExpansion(); + } } void ProjectExplorerWindow::Rebuild() @@ -210,13 +258,18 @@ void ProjectExplorerWindow::Rebuild() if (m_project != NULL) { + for (unsigned int i = 0; i < m_project->GetNumDirectories(); ++i) + { + RebuildForDirectory(m_project->GetDirectory(i)); + } + for (unsigned int i = 0; i < m_project->GetNumFiles(); ++i) { - RebuildForFile(m_project->GetFile(i)); + RebuildForFile(m_root, m_project->GetFile(i)); } } - m_tree->SortChildren(m_tree->GetRootItem()); + SortTree(m_tree->GetRootItem()); // For whatever reason the unselect event isn't reported properly // after deleting all items, so explicitly clear out the info box. @@ -230,7 +283,23 @@ void ProjectExplorerWindow::Rebuild() } -void ProjectExplorerWindow::RebuildForFile(Project::File* file) +void ProjectExplorerWindow::RebuildForDirectory(Project::Directory *directory) +{ + ItemData* data = new ItemData; + data->file = directory; + data->symbol = NULL; + data->isFile = false; + + wxTreeItemId node = m_tree->AppendItem(m_root, directory->name, 8, 8, data); + m_tree->SetItemTextColour(node, m_itemColor); + + for (Project::File *file : directory->files) + { + RebuildForFile(node, file); + } +} + +void ProjectExplorerWindow::RebuildForFile(wxTreeItemId node, Project::File* file) { // Check if the file passes our filter flags. @@ -262,7 +331,7 @@ void ProjectExplorerWindow::RebuildForFile(Project::File* file) if (m_filter.IsEmpty()) { // Just include the files like the standard Visual Studio project view. - AddFile(m_root, file); + AddFile(node, file); } else { @@ -270,9 +339,9 @@ void ProjectExplorerWindow::RebuildForFile(Project::File* file) // Filter all of the symbols, modules and file name. // Check to see if the file name matches the filter. - if (MatchesFilter(file->fileName.GetFullName(), m_filter)) + if (MatchesFilter(file->fileName.GetFullName(), m_filter) || MatchesFilter(file->localPath, m_filter)) { - AddFile(m_root, file); + AddFile(node, file); } for (unsigned int j = 0; j < file->symbols.size(); ++j) @@ -283,7 +352,7 @@ void ProjectExplorerWindow::RebuildForFile(Project::File* file) // Check to see if the symbol matches the filter. if (MatchesFilter(symbol->name, m_filter)) { - AddSymbol(m_root, file, symbol); + AddSymbol(node, file, symbol); } } @@ -324,15 +393,58 @@ bool ProjectExplorerWindow::MatchesFilter(const wxString& string, const wxString void ProjectExplorerWindow::AddFile(wxTreeItemId parent, Project::File* file) { - ItemData* data = new ItemData; data->file = file; data->symbol = NULL; + data->isFile = true; int image = GetImageForFile(file); + wxTreeItemIdValue cookie; + + bool found = false; + wxString path = file->localPath; + wxString directory = path.BeforeFirst('\\'); + wxTreeItemId node; + wxTreeItemId parentNode = parent; + + if (directory.IsEmpty()) + node = parent; + else + { + while (!directory.IsEmpty()) + { + found = false; + + //Add needed directories for file + node = m_tree->GetFirstChild(parentNode, cookie); + while (node.IsOk()) + { + if (m_tree->GetItemText(node) == directory) + { + found = true; + break; + } + + node = m_tree->GetNextChild(parentNode, cookie); + } + + if (!found) + { + node = m_tree->AppendItem(parentNode, directory, 8, 8, nullptr); + m_tree->SetItemTextColour(node, m_itemColor); + } + + path.Remove(0, directory.size() + 1); + + directory = path.BeforeFirst('\\'); + + parentNode = node; + } - wxTreeItemId fileNode = m_tree->AppendItem(parent, file->GetDisplayName(), image, image, data); + } + wxTreeItemId fileNode = m_tree->AppendItem(node, file->GetDisplayName(), image, image, data); + m_tree->SetItemTextColour(fileNode, m_itemColor); // Add the symbols. stdext::hash_map groups; @@ -351,6 +463,7 @@ void ProjectExplorerWindow::AddFile(wxTreeItemId parent, Project::File* file) if (iterator == groups.end()) { node = m_tree->AppendItem(fileNode, file->symbols[i]->module, Image_Module, Image_Module); + m_tree->SetItemTextColour(node, m_itemColor); groups.insert(std::make_pair(file->symbols[i]->module.ToAscii(), node)); } else @@ -372,6 +485,7 @@ void ProjectExplorerWindow::AddSymbol(wxTreeItemId parent, Project::File* file, ItemData* data = new ItemData; data->file = file; data->symbol = symbol; + data->isFile = true; wxString fullName = symbol->name + " ()"; @@ -380,8 +494,8 @@ void ProjectExplorerWindow::AddSymbol(wxTreeItemId parent, Project::File* file, fullName += " - " + symbol->module; } - m_tree->AppendItem(parent, fullName, Image_Function, Image_Function, data); - + wxTreeItemId node = m_tree->AppendItem(parent, fullName, Image_Function, Image_Function, data); + m_tree->SetItemTextColour(node, m_itemColor); } void ProjectExplorerWindow::OnTreeItemExpanding(wxTreeEvent& event) @@ -429,9 +543,18 @@ void ProjectExplorerWindow::OnTreeItemContextMenu(wxTreeEvent& event) if (itemData != NULL && itemData->file != NULL && itemData->symbol == NULL) { wxTreeEvent copy(event); + copy.SetInt(0); copy.SetEventType(wxEVT_TREE_CONTEXT_MENU); AddPendingEvent(copy); } + //Is a basic directory + else if (itemData == NULL) + { + wxTreeEvent copy(event); + copy.SetInt(1); + copy.SetEventType(wxEVT_TREE_CONTEXT_MENU); + AddPendingEvent(copy); + } } @@ -459,9 +582,9 @@ void ProjectExplorerWindow::OnTreeItemSelectionChanged(wxTreeEvent& event) m_tree->SelectItem(item); ItemData* itemData = GetDataForItem(item); - if (itemData != NULL && itemData->file != NULL) + if (itemData != NULL && itemData->file != NULL && itemData->isFile) { - file = itemData->file; + file = (Project::File *)itemData->file; } } @@ -476,7 +599,6 @@ void ProjectExplorerWindow::OnTreeItemSelectionChanged(wxTreeEvent& event) void ProjectExplorerWindow::GetSelectedFiles(std::vector& selectedFiles) const { - wxArrayTreeItemIds selectedIds; m_tree->GetSelections(selectedIds); @@ -486,18 +608,59 @@ void ProjectExplorerWindow::GetSelectedFiles(std::vector& select ItemData* itemData = GetDataForItem(selectedIds[i]); // Only add the selected item if it's a file. - if (itemData != NULL && itemData->file != NULL && itemData->symbol == NULL) + if (itemData != NULL && itemData->file != NULL && itemData->symbol == NULL && itemData->isFile) { - selectedFiles.push_back(itemData->file); + selectedFiles.push_back((Project::File *)itemData->file); } } } +void ProjectExplorerWindow::GetSelectedDirectories(std::vector& selectedDirectories) const +{ + wxArrayTreeItemIds selectedIds; + m_tree->GetSelections(selectedIds); + + for (unsigned int i = 0; i < selectedIds.Count(); ++i) + { + + ItemData* itemData = GetDataForItem(selectedIds[i]); + + // Only add the selected item if it's a file. + if (itemData != NULL && itemData->file != NULL && itemData->isFile == false) + { + selectedDirectories.push_back((Project::Directory *)itemData->file); + } + + } + +} + +void ProjectExplorerWindow::InsertDirectory(Project::Directory* directory) +{ + RebuildForDirectory(directory); + SortTree(m_tree->GetRootItem()); +} + +void ProjectExplorerWindow::RemoveDirectory(Project::Directory* directory) +{ + for (Project::File *file : directory->files) + { + RemoveFileSymbols(m_tree->GetRootItem(), file); + + if (m_infoBox->GetFile() == file) + { + m_infoBox->SetFile(NULL); + } + } + + RemoveFileSymbols(m_tree->GetRootItem(), (Project::File *)directory); +} + void ProjectExplorerWindow::InsertFile(Project::File* file) { - RebuildForFile(file); - m_tree->SortChildren(m_tree->GetRootItem()); + RebuildForFile(m_root, file); + SortTree(m_tree->GetRootItem()); } void ProjectExplorerWindow::RemoveFile(Project::File* file) @@ -559,7 +722,7 @@ void ProjectExplorerWindow::RemoveFileSymbols(wxTreeItemId node, const stdext::h ItemData* data = static_cast(m_tree->GetItemData(node)); - if (data != NULL && fileSet.find(data->file) != fileSet.end()) + if (data != NULL && data->isFile && fileSet.find((Project::File *)data->file) != fileSet.end()) { m_tree->Delete(node); } @@ -587,6 +750,11 @@ void ProjectExplorerWindow::SetFileContextMenu(wxMenu* contextMenu) m_contextMenu = contextMenu; } +void ProjectExplorerWindow::SetDirectoryContextMenu(wxMenu* contextMenu) +{ + m_directoryContextMenu = contextMenu; +} + int ProjectExplorerWindow::GetImageForFile(const Project::File* file) const { @@ -633,9 +801,9 @@ void ProjectExplorerWindow::UpdateFileImages() ItemData* data = GetDataForItem(item); - if (data != NULL && data->file != NULL && data->symbol == NULL) + if (data != NULL && data->file != NULL && data->symbol == NULL && data->isFile) { - int image = GetImageForFile(data->file); + int image = GetImageForFile((Project::File *)data->file); m_tree->SetItemImage(item, image); m_tree->SetItemImage(item, image, wxTreeItemIcon_Selected); } @@ -650,7 +818,10 @@ void ProjectExplorerWindow::UpdateFileImages() void ProjectExplorerWindow::OnMenu(wxTreeEvent& event) { + if (event.GetInt() == 0) m_tree->PopupMenu(m_contextMenu, event.GetPoint()); + else if (event.GetInt() == 1) + m_tree->PopupMenu(m_directoryContextMenu, event.GetPoint()); } void ProjectExplorerWindow::OnFilterButton(wxCommandEvent& event) @@ -674,16 +845,61 @@ void ProjectExplorerWindow::OnFilterButton(wxCommandEvent& event) void ProjectExplorerWindow::UpdateFile(Project::File* file) { - m_tree->Freeze(); + wxArrayTreeItemIds selectedItems; + m_tree->GetSelections(selectedItems); + + wxTreeItemId fileNode = FindFile(m_tree->GetRootItem(), file); + bool isSelected = m_tree->IsSelected(fileNode); + if (isSelected) + m_tree->UnselectItem(fileNode); + RemoveFileSymbols(m_tree->GetRootItem(), file); - RebuildForFile(file); - m_tree->SortChildren(m_tree->GetRootItem()); + //If only one item is selected, need to remove it later + if (isSelected && selectedItems.size() == 1) + { + selectedItems.clear(); + m_tree->GetSelections(selectedItems); + //fileNode = m_tree->UnselectItem + } - m_tree->Thaw(); + wxTreeItemId node = m_root; + if (file->directoryPath.IsEmpty() == false) + { + wxStack stack; + + wxTreeItemIdValue cookie; + wxTreeItemId temp = m_tree->GetFirstChild(node, cookie); + wxString target = file->directoryPath; + + while (temp.IsOk()) + { + if (m_tree->GetItemText(temp) == target) + break; + + temp = m_tree->GetNextChild(temp, cookie); + } + + if (temp.IsOk() == false) + temp = m_root; + + node = temp; + } + RebuildForFile(node, file); + SortTree(m_tree->GetRootItem()); + if (isSelected) + { + m_tree->SelectItem(FindFile(m_tree->GetRootItem(), file)); + + //Deselect the other node + if (selectedItems.size() == 1) + m_tree->SelectItem(selectedItems[0], false); + } + + m_tree->Thaw(); } void ProjectExplorerWindow::SetFilterFlags(unsigned int filterFlags) @@ -754,4 +970,195 @@ void ProjectExplorerWindow::UpdateFilterButtonImage() m_filterButton->SetBitmapLabel(bitmap); +} + +void ProjectExplorerWindow::SortTree(wxTreeItemId node) +{ + m_tree->SortChildren(node); + + //Sort all childen recursively + wxTreeItemIdValue cookie; + wxTreeItemId temp = m_tree->GetFirstChild(node, cookie); + while (temp.IsOk()) + { + if (m_tree->HasChildren(temp)) + { + SortTree(temp); + } + + temp = m_tree->GetNextChild(temp, cookie); + } +} + +#include +#include + +#define DBOUT( s ) \ +{ \ + std::wostringstream os_; \ + os_ << s; \ + OutputDebugStringW( os_.str().c_str() ); \ +} + + +wxTreeItemId ProjectExplorerWindow::FindFile(wxTreeItemId node, Project::File *file) +{ + ItemData* data = static_cast(m_tree->GetItemData(node)); + if (data && data->isFile && data->file == file) + { + return node; + } + + //Sort all childen recursively + wxTreeItemIdValue cookie; + wxTreeItemId temp = m_tree->GetFirstChild(node, cookie); + while (temp.IsOk()) + { + wxTreeItemId node = FindFile(temp, file); + if (node.IsOk()) + return node; + + temp = m_tree->GetNextChild(temp, cookie); + } + + return wxTreeItemId(); +} + +void ProjectExplorerWindow::TraverseTree(wxTreeItemId node, std::function function) const +{ + //Go through all children in depth first order. + wxTreeItemIdValue cookie; + wxTreeItemId temp = m_tree->GetFirstChild(node, cookie); + while (temp.IsOk()) + { + TraverseTree(temp, function); + function(temp); + + temp = m_tree->GetNextChild(temp, cookie); + } +} + + +void ProjectExplorerWindow::SaveExpansion() +{ + m_expandedIds.clear(); + + //Save all nodes that are expanded + TraverseTree(m_root, [&, this](wxTreeItemId const &item) + { + wxTreeItemId node = m_tree->GetItemParent(item); + ItemData* data = static_cast(m_tree->GetItemData(item)); + + //If the file has a parent and it is expanded, add it to the list + if (node != m_root && node.IsOk() && data && data->isFile && m_tree->IsExpanded(node)) + { + m_expandedIds.push_back(data->file); + } + }); +} + +void ProjectExplorerWindow::LoadExpansion() +{ + //Only expand the previously expanded items. + TraverseTree(m_root, [&, this](wxTreeItemId const &item) + { + ItemData* data = static_cast(m_tree->GetItemData(item)); + for (void* expand_file : m_expandedIds) + { + if (data && data->file == expand_file) + { + wxStack treeStack; + + //Collect all parent nodes + wxTreeItemId node = m_tree->GetItemParent(item); + while (node.IsOk()) + { + if (node != m_root) + treeStack.push(node); + + node = m_tree->GetItemParent(node); + } + + //Expand them in reverse order + while (treeStack.size() > 0) + { + node = treeStack.top(); + treeStack.pop(); + + m_tree->Expand(node); + } + + m_tree->Collapse(item); + } + } + }); +} + +wxString ProjectExplorerWindow::GetSelectedDirectoryName() +{ + wxArrayTreeItemIds array; + m_tree->GetSelections(array); + + if (array.size() != 1) + return wxString(); + + wxTreeItemId selection = array[0]; + + if (selection.IsOk()) + { + ItemData* itemData = GetDataForItem(selection); + + if (itemData == NULL) + { + wxStack treeStack; + + treeStack.push(selection); + + //Collect all parent nodes + wxTreeItemId node = m_tree->GetItemParent(selection); + while (node.IsOk()) + { + if (node != m_root) + treeStack.push(node); + + node = m_tree->GetItemParent(node); + } + + wxString directory; + + //Expand them in reverse order + while (treeStack.size() > 0) + { + node = treeStack.top(); + treeStack.pop(); + + directory += m_tree->GetItemText(node) + '\\'; + } + + return directory; + } + } + + return wxString(); +} + + +IMPLEMENT_DYNAMIC_CLASS(wxProjectTree, wxTreeCtrl); +int wxProjectTree::OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2) +{ + ProjectExplorerWindow::ItemData* data1 = static_cast(GetItemData(item1)); + ProjectExplorerWindow::ItemData* data2 = static_cast(GetItemData(item2)); + + //if (data1 && data2) + //{ + if (data1 && data2) + return GetItemText(item1).Cmp(GetItemText(item2)); + else if (data1 || data2) + { + if (data1) return 1; + else return -1; + } + //} + + return GetItemText(item1).Cmp(GetItemText(item2)); } \ No newline at end of file diff --git a/src/Frontend/ProjectExplorerWindow.h b/src/Frontend/ProjectExplorerWindow.h index 72bb8f8f..f882fb10 100644 --- a/src/Frontend/ProjectExplorerWindow.h +++ b/src/Frontend/ProjectExplorerWindow.h @@ -28,9 +28,11 @@ along with Decoda. If not, see . #include #include #include +#include #include "Project.h" - +#include "FontColorSettings.h" +#undef RemoveDirectory // // Forward declarations. // @@ -45,6 +47,7 @@ class ProjectFilterPopup; */ class ProjectExplorerWindow : public wxPanel { + friend class MainFrame; public: @@ -53,8 +56,9 @@ class ProjectExplorerWindow : public wxPanel */ struct ItemData : public wxTreeItemData { - Project::File* file; + void* file; Symbol* symbol; + bool isFile; }; enum FilterFlag @@ -75,6 +79,12 @@ class ProjectExplorerWindow : public wxPanel */ virtual ~ProjectExplorerWindow(); + + /** + * Updates the colors of the panel to match the settings + */ + void SetFontColorSettings(const FontColorSettings& settings); + /** * Sets the keyboard focus to the filter text box. */ @@ -136,6 +146,18 @@ class ProjectExplorerWindow : public wxPanel */ wxTreeItemId GetSelection() const; + /** + * Adds references for the directory into the explorer view. This should be + * called when a directory is added to the project. + */ + void InsertDirectory(Project::Directory* file); + + /** + * Removes all references to a directory from the explorer view. This should + * be called when a directory is deleted from the project. + */ + void RemoveDirectory(Project::Directory* file); + /** * Adds references for the file into the explorer view. This should be * called when a file is added to the project. @@ -160,12 +182,24 @@ class ProjectExplorerWindow : public wxPanel */ void SetFileContextMenu(wxMenu* menu); + /** + * Sets the menu displays when the user right clicks on a directory. Ownership + * retains with the caller. + */ + void SetDirectoryContextMenu(wxMenu* menu); + /** * Gets a list of all of the files that are currently selected in the tree. * Non-files that are selected are ignored. */ void GetSelectedFiles(std::vector& selectedFiles) const; + + /** + * Gets a list of all of the directories that are currently selected in the tree. + */ + void GetSelectedDirectories(std::vector& selectedDirectories) const; + /** * Updates the images showing the file status. */ @@ -188,6 +222,32 @@ class ProjectExplorerWindow : public wxPanel * explorer window. These are a combination of the FilterFlag enum values. */ unsigned int GetFilterFlags() const; + + /** + * Traverses the tree and calls the function on each item. + */ + void TraverseTree(wxTreeItemId node, std::function function) const; + + /** + * Saves the current state of the tree. + */ + void SaveExpansion(); + + /** + * Loads the expanded state of the tree. + */ + void LoadExpansion(); + + /** + * Rebuilds the entire list in the tree control. This should be done when + * the filter changes. + */ + void Rebuild(); + + /** + * Gets the name of the selected directory. + */ + wxString GetSelectedDirectoryName(); enum ID { @@ -225,15 +285,14 @@ class ProjectExplorerWindow : public wxPanel void RemoveFileSymbols(wxTreeItemId node, const stdext::hash_set& file); /** - * Rebuilds the entire list in the tree control. This should be done when - * the filter changes. + * Adds the items for the file that match the filter into the tree control. */ - void Rebuild(); + void RebuildForFile(wxTreeItemId node, Project::File* file); /** - * Adds the items for the file that match the filter into the tree control. - */ - void RebuildForFile(Project::File* file); + * Adds the items for the file that match the filter into the tree control. + */ + void RebuildForDirectory(Project::Directory *directory); /** * Returns the image that should be used to display the file. @@ -251,6 +310,15 @@ class ProjectExplorerWindow : public wxPanel */ void UpdateFilterButtonImage(); + /** + * Recursively sorts all levels of the tree + */ + void SortTree(wxTreeItemId node); + + /** + * Finds a node in the tree by the file + */ + wxTreeItemId FindFile(wxTreeItemId node, Project::File *file); private: /** @@ -268,27 +336,54 @@ class ProjectExplorerWindow : public wxPanel Image_FileTempCheckedOut = 7, }; - Project* m_project; - - SearchTextCtrl* m_searchBox; - wxString m_filter; - bool m_filterMatchAnywhere; - - wxTreeItemId m_root; - wxTreeCtrl* m_tree; - - wxImageList* m_filterImageList; - wxBitmapButton* m_filterButton; - ProjectFilterPopup* m_filterPopup; - unsigned int m_filterFlags; - - ProjectFileInfoCtrl* m_infoBox; + Project* m_project; + std::vector m_expandedIds; + bool m_hasFilter; + + SearchTextCtrl* m_searchBox; + wxString m_filter; + bool m_filterMatchAnywhere; + + wxTreeItemId m_root; + class wxProjectTree* m_tree; + + wxImageList* m_filterImageList; + wxBitmapButton* m_filterButton; + ProjectFilterPopup* m_filterPopup; + unsigned int m_filterFlags; + + ProjectFileInfoCtrl* m_infoBox; + + wxTreeItemId m_stopExpansion; + + wxMenu* m_contextMenu; + wxMenu* m_directoryContextMenu; + + wxColor m_itemColor; +}; - wxTreeItemId m_stopExpansion; - wxMenu* m_contextMenu; +#include +class wxProjectTree : public wxTreeCtrl +{ + DECLARE_DYNAMIC_CLASS(wxProjectTree); +public: + wxProjectTree() : wxTreeCtrl() + {} + + wxProjectTree(wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxTreeCtrlNameStr) + { + Create(parent, id, pos, size, style, validator, name); + } + + virtual int OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2); }; #endif diff --git a/src/Frontend/ProjectFileInfoCtrl.cpp b/src/Frontend/ProjectFileInfoCtrl.cpp index 33548167..f8bb25e0 100644 --- a/src/Frontend/ProjectFileInfoCtrl.cpp +++ b/src/Frontend/ProjectFileInfoCtrl.cpp @@ -51,6 +51,11 @@ ProjectFileInfoCtrl::ProjectFileInfoCtrl(wxWindow* parent, wxWindowID id) } +void ProjectFileInfoCtrl::SetFontColorSettings(const FontColorSettings& settings) +{ + m_fontColor = settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor; +} + void ProjectFileInfoCtrl::OnPaint(wxPaintEvent& event) { @@ -107,6 +112,7 @@ void ProjectFileInfoCtrl::OnPaint(wxPaintEvent& event) result += path + fileName.GetFullName(); + dc.SetTextForeground(m_fontColor); dc.DrawText(result, s_padding, s_padding); } diff --git a/src/Frontend/ProjectFileInfoCtrl.h b/src/Frontend/ProjectFileInfoCtrl.h index f6b2e74a..647fc666 100644 --- a/src/Frontend/ProjectFileInfoCtrl.h +++ b/src/Frontend/ProjectFileInfoCtrl.h @@ -25,6 +25,7 @@ along with Decoda. If not, see . #include "Project.h" #include +#include "FontColorSettings.h" // // Forward declarations. @@ -45,6 +46,12 @@ class ProjectFileInfoCtrl : public wxControl */ explicit ProjectFileInfoCtrl(wxWindow* parent, wxWindowID id = wxID_ANY); + + /** + * Updates the colors of the panel to match the settings + */ + void SetFontColorSettings(const FontColorSettings& settings); + /** * Called when the info box needs to be repainted. */ @@ -80,6 +87,7 @@ class ProjectFileInfoCtrl : public wxControl const Project::File* m_file; bool m_textIsClipped; + wxColor m_fontColor; }; diff --git a/src/Frontend/SearchWindow.cpp b/src/Frontend/SearchWindow.cpp index ef76c503..59e24b95 100644 --- a/src/Frontend/SearchWindow.cpp +++ b/src/Frontend/SearchWindow.cpp @@ -45,11 +45,11 @@ void SearchWindow::SetFontColorSettings(const FontColorSettings& settings) // happens often enough for it to really make much difference. Clear(); - SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Default).backColor); + SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); - m_messageAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Default).foreColor); - m_messageAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Default).backColor); - m_messageAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Default)); + m_messageAttr.SetTextColour(settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor); + m_messageAttr.SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_messageAttr.SetFont(settings.GetFont(FontColorSettings::DisplayItem_Window)); } void SearchWindow::OnDoubleClick(wxMouseEvent& event) diff --git a/src/Frontend/SymbolParser.cpp b/src/Frontend/SymbolParser.cpp index ee9979e4..e6a66a5f 100644 --- a/src/Frontend/SymbolParser.cpp +++ b/src/Frontend/SymbolParser.cpp @@ -65,6 +65,15 @@ void SymbolParser::SetProject(Project* project) { QueueForParsing( m_project->GetFile(fileIndex) ); } + + for (unsigned int dirIndex = 0; dirIndex < m_project->GetNumDirectories(); ++dirIndex) + { + Project::Directory *directory = m_project->GetDirectory(dirIndex); + for (unsigned int fileIndex = 0; fileIndex < directory->files.size(); ++fileIndex) + { + QueueForParsing(directory->files[fileIndex]); + } + } } } diff --git a/src/Frontend/SymbolParserEvent.h b/src/Frontend/SymbolParserEvent.h index 375c9613..bdac5b3d 100644 --- a/src/Frontend/SymbolParserEvent.h +++ b/src/Frontend/SymbolParserEvent.h @@ -37,7 +37,7 @@ class Symbol; // Event definitions. // -DECLARE_EVENT_TYPE(wxEVT_SYMBOL_PARSER_EVENT, -1) +DECLARE_EVENT_TYPE(wxEVT_SYMBOL_PARSER_EVENT, wxID_ANY) /** * Class for events sent by the symbol parser thread. This doesn't really handle @@ -86,7 +86,7 @@ class SymbolParserEvent : public wxEvent typedef void (wxEvtHandler::*SymbolParserEventFunction)(SymbolParserEvent&); #define EVT_SYMBOL_PARSER(fn) \ - DECLARE_EVENT_TABLE_ENTRY( wxEVT_SYMBOL_PARSER_EVENT, 0, -1, \ + DECLARE_EVENT_TABLE_ENTRY( wxEVT_SYMBOL_PARSER_EVENT, wxID_ANY, wxID_ANY, \ (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( SymbolParserEventFunction, & fn ), (wxObject *) NULL ), #endif \ No newline at end of file diff --git a/src/Frontend/SymbolParserThread.cpp b/src/Frontend/SymbolParserThread.cpp index 1957fa21..df62ab7f 100644 --- a/src/Frontend/SymbolParserThread.cpp +++ b/src/Frontend/SymbolParserThread.cpp @@ -100,7 +100,6 @@ wxThread::ExitCode SymbolParserThread::Entry() // Dispatch the message to event handler. SymbolParserEvent event(m_headItem->fileId, symbols, isLastItem); m_eventHandler->AddPendingEvent(event); - } delete m_headItem; diff --git a/src/Frontend/WatchCtrl.cpp b/src/Frontend/WatchCtrl.cpp index 9772f45c..ae18a2b7 100644 --- a/src/Frontend/WatchCtrl.cpp +++ b/src/Frontend/WatchCtrl.cpp @@ -52,7 +52,12 @@ WatchCtrl::WatchCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const m_vm = 0; m_stackLevel = 0; +} +void WatchCtrl::SetFontColorSettings(const FontColorSettings& settings) +{ + SetBackgroundColour(settings.GetColors(FontColorSettings::DisplayItem_Window).backColor); + m_fontColor = settings.GetColors(FontColorSettings::DisplayItem_Window).foreColor; } void WatchCtrl::SetValueFont(const wxFont& font) @@ -73,7 +78,8 @@ void WatchCtrl::UpdateFont(wxTreeItemId item) SetItemFont( item, m_valueFont ); UpdateFont( GetNextSibling(item) ); - + SetItemTextColour(item, m_fontColor); + wxTreeItemIdValue cookie; wxTreeItemId child = GetFirstChild(item, cookie); diff --git a/src/Frontend/WatchCtrl.h b/src/Frontend/WatchCtrl.h index d97b9233..05cc6831 100644 --- a/src/Frontend/WatchCtrl.h +++ b/src/Frontend/WatchCtrl.h @@ -25,6 +25,7 @@ along with Decoda. If not, see . #include #include "treelistctrl.h" +#include "FontColorSettings.h" // // Forward declarations. @@ -44,6 +45,11 @@ class WatchCtrl : public wxTreeListCtrl WatchCtrl(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HIDE_ROOT | wxTR_FULL_ROW_HIGHLIGHT | wxTR_ROW_LINES | wxTR_HAS_BUTTONS, const wxValidator &validator = wxDefaultValidator, const wxString& name = ""); + /** + * Updates the colors of the panel to match the settings + */ + void SetFontColorSettings(const FontColorSettings& settings); + /** * Parses a compound expression ({ key = value, key = value, etc. }) and adds it's * key value pairs as subitems for the specified item in the tree. @@ -114,7 +120,7 @@ class WatchCtrl : public wxTreeListCtrl float m_columnProportion; wxFont m_valueFont; - + wxColor m_fontColor; }; #endif \ No newline at end of file diff --git a/src/Frontend/res/explorer.xpm b/src/Frontend/res/explorer.xpm index c6fc826c..f3033ece 100644 --- a/src/Frontend/res/explorer.xpm +++ b/src/Frontend/res/explorer.xpm @@ -1,265 +1,369 @@ /* XPM */ -static char *explorer[] = { -/* columns rows colors chars-per-pixel */ -"144 17 242 2", -" c black", -". c #090909", -"X c #110911", -"o c #160916", -"O c #260926", -"+ c #2E092E", -"@ c #380938", -"# c #390939", -"$ c #751C05", -"% c #761C04", -"& c #4C2904", -"* c #512C04", -"= c #6B3A06", -"- c #693C05", -"; c #26680A", -": c #286D0B", -"> c #2C750C", -", c #2E790D", -"< c #2E7D0D", -"1 c #734106", -"2 c #410941", -"3 c #4B094B", -"4 c #4E094E", -"5 c #500950", -"6 c #530953", -"7 c #690969", -"8 c #6A096A", -"9 c #700970", -"0 c #740974", -"q c #750975", -"w c #354963", -"e c #364A64", -"r c #3C4F69", -"t c #3C5069", -"y c #3D5069", -"u c #42556D", -"i c #43566E", -"p c #4A5C73", -"a c #800000", -"s c #801F04", -"d c #A72605", -"f c #CB2F06", -"g c #D53106", -"h c #E93404", -"j c #F83604", -"k c #945E05", -"l c #BF482C", -"z c #DE4013", -"x c #EF5845", -"c c #D5614A", -"v c #31800F", -"b c #32870E", -"n c #348810", -"m c #368E10", -"M c #399113", -"N c #399214", -"B c #3E9818", -"V c #449D1E", -"C c #4BB11F", -"Z c #49AF20", -"A c #4DAE23", -"S c #52AD2C", -"D c #4DB022", -"F c #60BD38", -"G c #65C33D", -"H c #6DCD42", -"J c #FFC005", -"K c #FFE23F", -"L c #88B279", -"P c #FF9B77", -"I c #970997", -"U c #9C099C", -"Y c #9E099E", -"T c #9F099F", -"R c #A409A4", -"E c #AF09AF", -"W c #BD0CBD", -"Q c #B310B3", -"! c #BC13BC", -"~ c #C015C0", -"^ c #C71EC7", -"/ c #CA1BCA", -"( c #C920C9", -") c #CB23CB", -"_ c #D426D4", -"` c #D028D0", -"' c #D630D6", -"] c #D730D7", -"[ c #DA33DA", -"{ c #DF38DF", -"} c magenta", -"| c #E43EE4", -" . c #E641E6", -".. c #E741E7", -"X. c #F24DF2", -"o. c #F450F4", -"O. c #F550F5", -"+. c #F956F9", -"@. c #FB59FB", -"#. c #FE5BFE", -"$. c #FF5EFF", -"%. c #008080", -"&. c cyan", -"*. c #808080", -"=. c #8087B4", -"-. c #93A2B7", -";. c #9CA6B3", -":. c #9DA6B3", -">. c #96A5BA", -",. c #96A5BB", -"<. c #9AA9BF", -"1. c #9EABBE", -"2. c #A0A9B6", -"3. c #A3ACB8", -"4. c #A6AFBA", -"5. c #EEB5AE", -"6. c #9CABC0", -"7. c #9EADC3", -"8. c #A0ACC3", -"9. c #A3AFC6", -"0. c #A7B2C1", -"q. c #A7B3C2", -"w. c #A2B1C7", -"e. c #A5B1C7", -"r. c #A4B3C9", -"t. c #A5B5CB", -"y. c #A8B3C8", -"u. c #AAB5CA", -"i. c #ABB6CB", -"p. c #A9B9CF", -"a. c #AFB9CD", -"s. c #B0BBCD", -"d. c #B3BDCF", -"f. c #ADBDD3", -"g. c #AEBED4", -"h. c #B7C0D2", -"j. c #B7C1D2", -"k. c #B1C1D7", -"l. c #BBC5D4", -"z. c #BCC4D5", -"x. c #B2C2D8", -"c. c #BFC7D8", -"v. c #BCCDF0", -"b. c #C6CCDB", -"n. c #CAD1DB", -"m. c #CBD3DD", -"M. c #CDD5DF", -"N. c #CFD6DF", -"B. c #CED6E0", -"V. c #CFD7E1", -"C. c #CDD6E2", -"Z. c #CADAEE", -"A. c #D0D6E1", -"S. c #D1D9E3", -"D. c #D2D8E3", -"F. c #D3D9E3", -"G. c #D4D9E0", -"H. c #D4DAE1", -"J. c #D2DAE4", -"K. c #D3DBE5", -"L. c #D4DAE4", -"P. c #D5DBE5", -"I. c #D6DBE5", -"U. c #D5DCE7", -"Y. c #D8DCE6", -"T. c #D8DDE6", -"R. c #D9DDE7", -"E. c #DADEE7", -"W. c #D7DEE9", -"Q. c #D7DFEA", -"!. c #DADFE8", -"~. c #C1D0F1", -"^. c #C2D1F1", -"/. c #C5D4F2", -"(. c #C8D5F3", -"). c #CAD7F3", -"_. c #CDD9F4", -"`. c #CEDBF4", -"'. c #D1DDF4", -"]. c #D2DCF5", -"[. c #D3DEF5", -"{. c #DBE0E9", -"}. c #D9E0EB", -"|. c #DDE2EA", -" X c #DEE2EA", -".X c #D9E1EC", -"XX c #DFE3EC", -"oX c #D5E1F6", -"OX c #D8E2F7", -"+X c #DAE4F7", -"@X c #DCE5F7", -"#X c #DEE6F7", -"$X c #DDE6F8", -"%X c #E2E6ED", -"&X c #E3E6ED", -"*X c #E6EBF0", -"=X c #E5EDF6", -"-X c #E9ECF1", -";X c #ECEEF3", -":X c #EDEFF3", -">X c #E0E8F8", -",X c #E1E8F8", -".l.e q.P P P P P P P P P P P P P P 6 +.# P P P P P P P .XVXVXVXVXVXVXbXm. X:.D.P P P P P P x.VXVXVXVXVXVXbX>.l.e q.P P P P P P .XVXVXVXVXVXVXVXm. X;.H.P P P P P P x.VXVXVXVXVXVXvX>.l.e q.P P P P P P .XVXVXVXVXVXVXbXm. X:.H.P P P ", -"P P & K K J J = 1 & & P P P P P P P P P k.VXc.<.<.<.<.vX1.i r w P P P P P P =.=.=.=.=.P P 6 $.o.{ O P P P P P P !.VXXXM.m.M.M.bXM.4.:.:.P P P P P P k.VXc.<.<.<.<.kX1.i t w P P P P P P !.VXXXM.m.M.m.vXM.3.2.;.P P P P P P k.VXc.<.<.<.<.vX1.i r w P P P P P P W.VXXXM.m.M.M.bXM.3.2.:.P P P ", -"P & J J J J = 1 & P P P } P P P P P f.VXVXVXVXVXvXkXZ.%XR.r P P P P P P P P P P P P 6 $.o. ._ ^ X P P P P P W.VXVXVXVXVXbXVX=X:X;X3.P P P P P P f.VXVXVXVXVXvXkXZ.%XR.t P P P P P P W.VXVXVXVXVXVXbX=XaX;X:.P P P P P P f.VXVXVXVXVXvXkXZ.%XR.r P P P P P P W.VXVXVXVXVXVXbX=XaX-X2.P P P ", -"P P J J k 1 & P *.P } a a P P P P p.VXc.<.<.<.<.<.jXfX!.i P P P P P P =.=.=.=.P 6 @.X...[ ( ! Y . P P P P W.VX XM.M.M.M.m.vXkX:X3.P P P P P P p.VXc.<.<.<.<.6.fXhXR.i P P P P P P W.VXXXM.M.M.M.M.vXvX;X3.P P P P P P p.VXc.<.<.<.<.<.jXfX!.u P P P P P P W.VXXXM.M.M.M.M.bXkX:X3.P P P ", -"P P P = - * P P P } a a P P P P P t.VXVXVXVXVXkXjXqXqXD.p P P P P P P P P P P P 3 2 .' ) ! Y . . P P P P J.VXVXVXVXVXVXbXjXkX-X4.P P P P P P t.VXVXVXVXVXkXfXqXqXD.p P P P P P P J.VXVXVXVXVXbXvXkXgX-X4.P P P P P P r.VXVXVXx 5.jXjXqXqXD.p P P P P P P J.VXVXVXx 5.bXbXhXkX-X4.P P P ", -"P P P P & P *.P P P a P P P P P P w.VXc.<.<.<.<.<.<.>XA.i P P P P P P =.=.=.=.P 2 _ + ` ! Y . 9 . P P P P J.VXXXM.M.M.M.M.M.iX-X3.P P P P P P w.VXc.<.<.<.<.<.6.>XA.i P P P P P P D.VXXXM.M.M.M.M.M.tX-X2.P P P P P P r.VXb.x x <.<.<.<.X#Xb.t P P P P P P S.VXx j 5.kXfXfXtXtX%X2.P P P ", -"P P P P P P P P *.P P P P P P P P P P P P <.VXc.6.<.<.<.<.6.].j.w P P P P P P =.=.=.=.P P . E R . 0 8 . P P P P P C.VXXXM.M.M.M.M.M.wX}.:.P P P P L C D B 9.<.<.1.6.<.<.].j.e P P P P L C D B 7.M.C.M.M.m.C.5X X;.P P P P P P 6.x j j c <.<.<.<.].j.e P P P P P P V.x j j c C.M.M.M.qXR.:.P P P ", -"P P P P P P P P P P P P P P P P P P P P >.fXfXqX>XOXoX]._.(.s.w P P P P P P P P P P P P P . I . 8 . P P P P P P m.bXkXgXsXtXwXqX=XXOXoX]._.(.a.w P P P L D H G V v 7.sXtXwXqX5X5XI.;.P P P P x P x j j 5.XOX[.`.)./.~.v.e.w P P P g j j g s jXqXqX5X5X , ; 7.z.j.d.s.i.y.9.7.w P P P P e > , ; 7. X!.R.I.I.K.D.C.;.P P P P f d % OXb.z.d.d.s.i.y.w.8.w P P P P f d $ tX X X}.R.R.I.J.D.A.;.P P P ", -"P P P P P P P P P P P %. P P P P P P P -.w w w w w w e w w w e P P P P P P P P P P P P P P P P P P P P P P P P n.;.;.:.:.:.:.;.:.:.:.:.P P P P P w w w w w w w w w w w w w P P P P P w w w ;.;.;.:.:.;.;.:.;.;.P P P P P % -.w w e e w w w w w w w P P P P P % m.;.:.:.:.;.:.:.;.:.:.;.P P P ", -"P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P " -}; +static char * explorer[] = { +"162 17 349 2", +" c None", +". c #FF9B77", +"+ c #4C2904", +"@ c #FFE23F", +"# c #B2C2D8", +"$ c #AEBED4", +"% c #A9B9CF", +"& c #A4B3C9", +"* c #CDD6E2", +"= c #D9E1EC", +"- c #D7DEE9", +"; c #D5DCE7", +"> c #D2DAE4", +", c #E6EBF0", +"' c #D3DBE5", +") c #D2D8E3", +"! c #7D808F", +"~ c #607790", +"{ c #62768D", +"] c #62768E", +"^ c #5A748F", +"/ c #897F88", +"( c #FFC005", +"_ c #FFFFFF", +": c #9CABC0", +"< c #354963", +"[ c #A7B3C2", +"} c #4B094B", +"| c #CDD5DF", +"1 c #9CA6B3", +"2 c #9EABBE", +"3 c #5D7690", +"4 c #9EB2C5", +"5 c #BCC9D8", +"6 c #B8C5D5", +"7 c #BBC8D7", +"8 c #A5B5C8", +"9 c #8C8087", +"0 c #FE9A77", +"a c #6B3A06", +"b c #F9FBFE", +"c c #96A5BA", +"d c #BBC5D4", +"e c #364A64", +"f c #530953", +"g c #F956F9", +"h c #390939", +"i c #FBFCFE", +"j c #CBD3DD", +"k c #DEE2EA", +"l c #9DA6B3", +"m c #D4DAE1", +"n c #667A91", +"o c #7894AE", +"p c #869FB6", +"q c #839DB5", +"r c #859DB5", +"s c #7491AC", +"t c #476E8F", +"u c #8E7E84", +"v c #8C7D83", +"w c #8B7C83", +"x c #8A7C82", +"y c #8A7E86", +"z c #B08B86", +"A c #734106", +"B c #000000", +"C c #B1C1D7", +"D c #BFC7D8", +"E c #9AA9BF", +"F c #43566E", +"G c #3C4F69", +"H c #8087B4", +"I c #FF5EFF", +"J c #F450F4", +"K c #DF38DF", +"L c #260926", +"M c #DADFE8", +"N c #DFE3EC", +"O c #A6AFBA", +"P c #F6F8FC", +"Q c #3C5069", +"R c #A3ACB8", +"S c #A0A9B6", +"T c #677A92", +"U c #6E8BA7", +"V c #7C97B0", +"W c #809AB1", +"X c #849CB2", +"Y c #89A1B6", +"Z c #91A8BD", +"` c #93A9BE", +" . c #96ACBF", +".. c #99AEC0", +"+. c #9BB0C2", +"@. c #A0B4C6", +"#. c #809BB2", +"$. c #6D7A8D", +"%. c #FF00FF", +"&. c #ADBDD3", +"*. c #CADAEE", +"=. c #E2E6ED", +"-. c #D9DDE7", +";. c #E641E6", +">. c #D426D4", +",. c #C71EC7", +"'. c #110911", +"). c #E5EDF6", +"!. c #EDEFF3", +"~. c #ECEEF3", +"{. c #F0F2F6", +"]. c #E9ECF1", +"^. c #62778F", +"/. c #9FB0C5", +"(. c #C6CFDE", +"_. c #CDD5E0", +":. c #D7DCE3", +"<. c #DDE2E7", +"[. c #E1E8EE", +"}. c #ECEFF5", +"|. c #F0F2F8", +"1. c #F8F9F9", +"2. c #FFFEFD", +"3. c #C1CFDB", +"4. c #6E7687", +"5. c #945E05", +"6. c #808080", +"7. c #800000", +"8. c #F4F7FD", +"9. c #F3F6FC", +"0. c #FB59FB", +"a. c #F24DF2", +"b. c #E741E7", +"c. c #DA33DA", +"d. c #C920C9", +"e. c #BC13BC", +"f. c #9E099E", +"g. c #090909", +"h. c #F4F7FC", +"i. c #42556D", +"j. c #63778F", +"k. c #9AACC2", +"l. c #BCC7D7", +"m. c #C2CDDA", +"n. c #CCD4DD", +"o. c #D2DAE1", +"p. c #D7DFE8", +"q. c #DFE5ED", +"r. c #E4E9F0", +"s. c #EBEFF2", +"t. c #F2F4F5", +"u. c #F6F7F8", +"v. c #B9C8D6", +"w. c #6F7687", +"x. c #693C05", +"y. c #512C04", +"z. c #A5B5CB", +"A. c #EAEFFA", +"B. c #4A5C73", +"C. c #410941", +"D. c #D630D6", +"E. c #CB23CB", +"F. c #F4F6FC", +"G. c #EF5845", +"H. c #EEB5AE", +"I. c #63788F", +"J. c #95A8BF", +"K. c #B3BFD1", +"L. c #B7C3D4", +"M. c #C1CCDA", +"N. c #CBD3DE", +"O. c #D1D9E5", +"P. c #D6DFE7", +"Q. c #E0E5ED", +"R. c #E3E9F0", +"S. c #EBEEF2", +"T. c #FFFFFE", +"U. c #B8C7D3", +"V. c #707688", +"W. c #A2B1C7", +"X. c #E0E8F8", +"Y. c #D0D6E1", +"Z. c #2E092E", +"`. c #D028D0", +" + c #700970", +".+ c #EFF3FB", +"++ c #EDF2FA", +"@+ c #C6CCDB", +"#+ c #E2E8F8", +"$+ c #647890", +"%+ c #8DA4B9", +"&+ c #ACBACD", +"*+ c #B0BCD0", +"=+ c #EAEEF2", +"-+ c #FCFCFB", +";+ c #B7C5D2", +">+ c #9EADC3", +",+ c #EFF3FC", +"'+ c #DDE6F8", +")+ c #380938", +"!+ c #CA1BCA", +"~+ c #BD0CBD", +"{+ c #160916", +"]+ c #B310B3", +"^+ c #740974", +"/+ c #6A096A", +"(+ c #CFD7E1", +"_+ c #E3E6ED", +":+ c #88B279", +"<+ c #E6ECF9", +"[+ c #F83604", +"}+ c #F0F3FB", +"|+ c #DEE6F7", +"1+ c #D1D9E3", +"2+ c #647990", +"3+ c #899FB7", +"4+ c #A3B3C6", +"5+ c #A9B7CA", +"6+ c #B0BDD0", +"7+ c #C1CDDA", +"8+ c #CCD3DD", +"9+ c #F4F6F8", +"0+ c #B3C3CF", +"a+ c #707788", +"b+ c #D2DCF5", +"c+ c #B7C1D2", +"d+ c #AF09AF", +"e+ c #A409A4", +"f+ c #EAF0FA", +"g+ c #D9E0EB", +"h+ c #4BB11F", +"i+ c #4DB022", +"j+ c #3E9818", +"k+ c #A3AFC6", +"l+ c #D5614A", +"m+ c #657991", +"n+ c #8097B1", +"o+ c #9BABC1", +"p+ c #A1B2C5", +"q+ c #A8B7CA", +"r+ c #B1BDD0", +"s+ c #CCD3DE", +"t+ c #D6DFE8", +"u+ c #DEE5EC", +"v+ c #F1F2F7", +"w+ c #B1C0D0", +"x+ c #D8E2F7", +"y+ c #D5E1F6", +"z+ c #CDD9F4", +"A+ c #C8D5F3", +"B+ c #B0BBCD", +"C+ c #970997", +"D+ c #49AF20", +"E+ c #6DCD42", +"F+ c #65C33D", +"G+ c #449D1E", +"H+ c #2E7D0D", +"I+ c #AFB9CD", +"J+ c #31800F", +"K+ c #D6DBE5", +"L+ c #DAE4F7", +"M+ c #D3DEF5", +"N+ c #CEDBF4", +"O+ c #C5D4F2", +"P+ c #7692AE", +"Q+ c #8EA2BB", +"R+ c #98AAC0", +"S+ c #D1D9E4", +"T+ c #E9ECF2", +"U+ c #ADBDCE", +"V+ c #707789", +"W+ c #00FFFF", +"X+ c #93A2B7", +"Y+ c #C1D0F1", +"Z+ c #AAB5CA", +"`+ c #CAD1DB", +" @ c #4DAE23", +".@ c #60BD38", +"+@ c #52AD2C", +"@@ c #399113", +"#@ c #E93404", +"$@ c #BF482C", +"%@ c #718CA9", +"&@ c #839AB5", +"*@ c #8CA1BA", +"=@ c #99AAC0", +"-@ c #C2CCD9", +";@ c #CBD4DF", +">@ c #E0E6EE", +",@ c #A7B9CA", +"'@ c #717889", +")@ c #008080", +"!@ c #BCCDF0", +"~@ c #A5B1C7", +"{@ c #348810", +"]@ c #368E10", +"^@ c #32870E", +"/@ c #286D0B", +"(@ c #CAD7F3", +"_@ c #399214", +":@ c #D53106", +"<@ c #DE4013", +"[@ c #761C04", +"}@ c #801F04", +"|@ c #677B92", +"1@ c #6E88A5", +"2@ c #7D94AF", +"3@ c #8FA2BB", +"4@ c #9BACC2", +"5@ c #A4B4C6", +"6@ c #ADBACD", +"7@ c #B4BFD2", +"8@ c #BCC7D8", +"9@ c #C7D0DC", +"0@ c #D0D7E2", +"a@ c #A6B8CA", +"b@ c #BCC4D5", +"c@ c #A8B3C8", +"d@ c #A0ACC3", +"e@ c #2C750C", +"f@ c #2E790D", +"g@ c #26680A", +"h@ c #B3BDCF", +"i@ c #ABB6CB", +"j@ c #CB2F06", +"k@ c #A72605", +"l@ c #751C05", +"m@ c #637A93", +"n@ c #63829F", +"o@ c #7691AD", +"p@ c #889EB7", +"q@ c #8CA3B8", +"r@ c #94A7BE", +"s@ c #97AAC0", +"t@ c #9EB1C5", +"u@ c #A6B7C8", +"v@ c #B2C0D0", +"w@ c #8BA3BA", +"x@ c #70798C", +"y@ c #7C808F", +"z@ c #657A92", +"A@ c #687A91", +"B@ c #677A91", +"C@ c #667990", +"D@ c #657990", +"E@ c #64788F", +"F@ c #63778E", +"G@ c #5E7791", +"H@ c #8D848D", +". . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . + @ + . . . . . . . . . . . . . # # # # # # $ % & * . . . . . . . . . . . . . . . . . . . . . . . . . . = = = = = = - ; > , . . . . . . . . # # # # # # $ % & * . . . . . . . . = = = = = = - ' > , . . . . . . . . # # # # # # $ % & * . . . . . . . . = = = = = = - - ) , . . . . . . ! ~ { ] ^ / . . . . . . . . . . . ", +". . . . + @ @ ( + . . . . . . . . . . . . # _ _ _ _ _ _ _ : < [ . . . . . . . . . . . . . . . . } . . . . . . . . = _ _ _ _ _ _ _ | 1 ) . . . . . . . # _ _ _ _ _ _ _ : < [ . . . . . . . = _ _ _ _ _ _ _ * 1 ) . . . . . . . # _ _ _ _ _ _ _ 2 < [ . . . . . . . = _ _ _ _ _ _ _ | 1 ) . . . . . 3 4 5 6 7 8 9 . . . . . . . . 0 . ", +". . . + @ @ ( ( a + . . . . . . . . . . . # _ _ _ _ _ _ b c d e [ . . . . . . . . . . . . . . f g h . . . . . . . = _ _ _ _ _ _ i j k l ) . . . . . . # _ _ _ _ _ _ i c d e [ . . . . . . = _ _ _ _ _ _ _ j k 1 m . . . . . . # _ _ _ _ _ _ b c d e [ . . . . . . = _ _ _ _ _ _ i j k l m . . . . n o p q r s t u v v w w x y z . . ", +". . + @ @ ( ( a A + + . . . B . . . . . . C _ D E E E E b 2 F G < . . . . . . H H H H H . . f I J K L . . . . . . M _ N | j | | i | O l l . . . . . . C _ D E E E E P 2 F Q < . . . . . . M _ N | j | j b | R S 1 . . . . . . C _ D E E E E b 2 F G < . . . . . . - _ N | j | | i | R S l . . . . T U V W X Y Z Z ` ...+.@.#.$.. . ", +". + ( ( ( ( a A + B . . . B %.B . . . . . &._ _ _ _ _ b P *.=.-.G . . . . . . . . . . . . f I J ;.>.,.'.. . . . . - _ _ _ _ _ i _ ).!.~.R . . . . . . &._ _ _ _ _ b P *.=.-.Q . . . . . . - _ _ _ _ _ _ i ).{.~.l . . . . . . &._ _ _ _ _ b P *.=.-.G . . . . . . - _ _ _ _ _ _ i ).{.].S . . . . ^./.(._.:.<.[.}.|.1.2._ _ 3.4.. . ", +". . B ( ( 5.A + B . 6.. B %.7.7.B . . . . % _ D E E E E E 8.9.M F . . . . . . H H H H . f 0.a.b.c.d.e.f.g.. . . . - _ k | | | | j b P !.R . . . . . . % _ D E E E E : 9.h.-.F . . . . . . - _ N | | | | | b b ~.R . . . . . . % _ D E E E E E 8.9.M i.. . . . . . - _ N | | | | | i P !.R . . . . j.k.l.m.n.o.p.q.r.s.t.u._ v.w.. . ", +". . . B a x.y.B . . . B %.7.7.B . . . . . z._ _ _ _ _ P 8.A.A.) B.. . . . . . . . . . . } C.;.D.E.e.f.g.g.. . . . > _ _ _ _ _ _ i 8.P ].O . . . . . . z._ _ _ _ _ P 9.A.A.) B.. . . . . . > _ _ _ _ _ i b P F.].O . . . . . . & _ _ _ G.H.8.8.A.A.) B.. . . . . . > _ _ _ G.H.i i h.P ].O . . . . I.J.K.L.M.N.O.P.Q.R.S.t.T.U.V.. . ", +". . . . B + B . 6.. . . B 7.B . . . . . . W._ D E E E E E E X.Y.F . . . . . . H H H H . C.>.Z.`.e.f.g. +g.. . . . > _ N | | | | | | .+].R . . . . . . W._ D E E E E E : X.Y.F . . . . . . ) _ N | | | | | | ++].S . . . . . . & _ @+G.G.E E E E #+) F . . . . . . > _ N G.G.| | | | h.].S . . . . $+%+&+*+L.M.j O.P.Q.r.=+-+;+V.. . ", +". . . . . B . . . . . . . B . . . . . . . >+_ _ P _ ,+A.A.'+#+@+G . . . . . . . . . . . )+!+~+{+]+g.^+/+g.. . . . (+_ _ i _ P 8.h..+.+_+l . . . . . :+:+>+_ b _ ,+A.<+'+#+@+Q . . . . . :+:+>+_ i _ P h.8.++h.=.S . . . . . . >+_ G.[+H.}+A.<+X.|+@+Q . . . . . . 1+_ G.[+H.P 9.9.++++=.S . . . . 2+3+4+5+6+L.7+8+O.P.q.r.9+0+a+. . ", +". . . . . . . . 6.. . . . . . . . . . . . E _ D : E E E E : b+c+< . . . . . . H H H H . . g.d+e+g.^+/+g.. . . . . * _ N | | | | | | f+g+l . . . . :+h+i+j+k+E E 2 : E E b+c+e . . . . :+h+i+j+>+| * | | j * <+k 1 . . . . . . : G.[+[+l+E E E E b+c+e . . . . . . (+G.[+[+l+* | | | A.-.l . . . . m+n+o+p+q+r+L.m.s+O.t+u+v+w+a+. . ", +". . . . . . . . . . . . . B . . . . . . . c 9.9.A.X.x+y+b+z+A+B+< . . . . . . . . . . . . . g.C+g./+g.. . . . . . j i P F.}+++f+A.).#+g+l . . . :+D+E+F+G+H+>+X.x+y+b+z+A+I+< . . . :+i+E+F+G+J+>+}+++f+A.<+<+K+1 . . . . G.. G.[+[+H.#+L+M+b+N+O+B+< . . . . G.. G.[+[+H.++++f+A.<+#+-.l . . . . n P+Q+R+p+q+r+L.m.N.S+p.T+U+V+. . ", +". . . . . . . . 6.. 6.. B W+B . . . . . . X+++D E E : : E E Y+Z+< . . . . . . H H H H H . . . g.g.g.. . . . . . . `+8.k * | * | | j #+K+1 . . . :+ @.@+@@@H+>+E E E E E Y+Z+< . . . :+D+.@+@@@H+>+| | | | | #+K+1 . . . G.[+G.[+#@$@E E E E E E Y+Z+< . . . G.[+G.[+#@$@| | | | | | #+> 1 . . . . n %@&@*@=@p+5+6+L.-@;@S+>@,@'@. . ", +". . . . . . . . . . . B W+)@)@B . . . . . X+#+|+x+b+z+A+O+Y+!@~@< . . . . . . . . . . . . . . . g.. . . . . . . . `+9.,+A.A.<+<+#+#+|+> 1 . . . :+{@@@]@^@/@>+b+z+(@O+Y+!@~@< . . . :+{@_@]@^@/@>+A.<+<+#+#+|+m 1 . . . :@[+[+<@[@X.x+M+N+(@O+Y+!@~@< . . . :@[+[+:@}@8.A.A.<+<+#+#+|+> 1 . . . . |@1@2@&@3@4@5@6@7@8@9@0@Q.a@'@. . ", +". . . . . . . . . . B W+)@)@B . . . . . . X+x+@+b@c+B+B+Z+c@k+d@< . . . . . . . . . . . . . . . . . . . . . . . . `+++k k M -.K+K+) ) * 1 . . . . < e@f@g@>+b@c+h@B+i@c@k+>+< . . . . e e@f@g@>+k M -.K+K+' ) * 1 . . . . j@k@[@x+@+b@h@h@B+i@c@W.d@< . . . . j@k@l@++k k g+-.-.K+> ) Y.1 . . . . m@n@1@%@o@n+p@q@r@s@t@u@v@w@x@. . ", +". . . . . . . . . . . B )@B . . . . . . . X+< < < < < < e < < < e . . . . . . . . . . . . . . . . . . . . . . . . `+1 1 l l l l 1 l l l l . . . . . < < < < < < < < < < < < < . . . . . < < < 1 1 1 l l 1 1 l 1 1 . . . . . [@X+< < e e < < < < < < < . . . . . [@j 1 l l l 1 l l 1 l l 1 . . . . y@z@A@B@B@C@D@D@E@E@E@F@] G@H@. . ", +". . . . . . . . . . . . B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; diff --git a/src/LuaInject/DebugBackend.cpp b/src/LuaInject/DebugBackend.cpp index c7d7c5ce..da61e9fe 100644 --- a/src/LuaInject/DebugBackend.cpp +++ b/src/LuaInject/DebugBackend.cpp @@ -227,7 +227,7 @@ void DebugBackend::Log(const char* fmt, ...) if (GetStartupDirectory(fileName, _MAX_PATH)) { strcat(fileName, "log.txt"); - m_log = fopen("c:/temp/log.txt", "wt"); + m_log = fopen("log.txt", "wt"); } } @@ -697,7 +697,10 @@ void DebugBackend::HookCallback(unsigned long api, lua_State* L, lua_Debug* ar) { m_criticalSection.Enter(); - + + // Log for debugging. + //LogHookEvent(api, L, ar); + if (!lua_checkstack_dll(api, L, 2)) { m_criticalSection.Exit(); @@ -779,9 +782,6 @@ void DebugBackend::HookCallback(unsigned long api, lua_State* L, lua_Debug* ar) lua_pop_dll(api, L, 1); - // Log for debugging. - //LogHookEvent(api, L, ar); - //Only try to downgrade the hook when the debugger is not stepping if(m_mode == Mode_Continue) { @@ -862,15 +862,14 @@ void DebugBackend::HookCallback(unsigned long api, lua_State* L, lua_Debug* ar) if (stop) { BreakFromScript(api, L); - - if(vm->luaJitWorkAround) - { - vm->callStackDepth = GetStackDepth(api, L); - vm->lastStepLine = GetCurrentLine(api, ar); - vm->lastStepScript = scriptIndex; - } } - + + if (vm->luaJitWorkAround) + { + vm->callStackDepth = GetStackDepth(api, L); + vm->lastStepLine = GetCurrentLine(api, ar); + vm->lastStepScript = scriptIndex; + } } else { @@ -2135,10 +2134,8 @@ bool DebugBackend::CallMetaMethod(unsigned long api, lua_State* L, int valueInde if (!lua_isnil_dll(api, L, metaTableIndex)) { - lua_pushstring_dll(api, L, method); - lua_gettable_dll(api, L, metaTableIndex); - + lua_rawget_dll(api, L, metaTableIndex); if (lua_isnil_dll(api, L, -1)) { // The meta-method doesn't exist. @@ -2148,6 +2145,7 @@ bool DebugBackend::CallMetaMethod(unsigned long api, lua_State* L, int valueInde } else { + lua_gettop_dll(api, L); lua_pushvalue_dll(api, L, valueIndex); result = lua_pcall_dll(api, L, 1, numResults, 0); } diff --git a/src/LuaInject/DebugBackend.h b/src/LuaInject/DebugBackend.h index 145ef19b..d889a8d0 100644 --- a/src/LuaInject/DebugBackend.h +++ b/src/LuaInject/DebugBackend.h @@ -580,6 +580,11 @@ class DebugBackend const lua_Debug scriptStack[], unsigned int scriptStackSize, StackEntry unifiedStack[]); + void PrintIndent(); + void Lua_PrintIndex(unsigned long api, lua_State *L, int index); + void Lua_PrintTable(unsigned long api, lua_State *L, int index); + void Lua_stackDump(unsigned long api, lua_State *L); + private: typedef stdext::hash_map StateToVmMap;