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;