From 619db418ff9780ccb2c37752df2e7dbbdbf8c69f Mon Sep 17 00:00:00 2001 From: Tim Warren Date: Fri, 5 Jun 2015 16:50:52 -0400 Subject: [PATCH] FilePane and Close All but this context menu item on tabs --- src/widgets/EditPane.cpp | 30 +++++------- src/widgets/EditPane.h | 1 - src/widgets/FilePane.cpp | 94 ++++++++++++++++++++++++++++++++++++ src/widgets/FilePane.h | 24 +++++++++ src/widgets/MainFrame.cpp | 15 ++++++ src/widgets/PrefPane.cpp | 56 ++++++++++----------- src/widgets/TabContainer.cpp | 63 ++++++++++++++++++++---- src/widgets/TabContainer.h | 2 + src/widgets/widget.h | 3 ++ 9 files changed, 232 insertions(+), 56 deletions(-) create mode 100644 src/widgets/FilePane.cpp create mode 100644 src/widgets/FilePane.h diff --git a/src/widgets/EditPane.cpp b/src/widgets/EditPane.cpp index c7162c5..3f5462d 100644 --- a/src/widgets/EditPane.cpp +++ b/src/widgets/EditPane.cpp @@ -259,25 +259,19 @@ bool EditPane::FileWritable() */ void EditPane::BindEvents() { - Bind(wxEVT_STC_MARGINCLICK, &EditPane::OnMarginClick, this, wxID_ANY); - Bind(wxEVT_STC_CHARADDED, &EditPane::OnCharAdded, this, wxID_ANY); -} - -/** - * Code folding event handler - * - * @param wxStyledTextEvent& event - * @return void - */ -void EditPane::OnMarginClick(wxStyledTextEvent& event) -{ - if (event.GetMargin() == MARGIN_FOLD) { - int lineClick = this->LineFromPosition (event.GetPosition()); - int levelClick = this->GetFoldLevel (lineClick); - if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0) { - this->ToggleFold (lineClick); + // Code folding event handler + this->Bind(wxEVT_STC_MARGINCLICK, [=](wxStyledTextEvent& event) { + if (event.GetMargin() == MARGIN_FOLD) + { + int lineClick = this->LineFromPosition (event.GetPosition()); + int levelClick = this->GetFoldLevel (lineClick); + if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0) { + this->ToggleFold (lineClick); + } } - } + }, wxID_ANY); + + this->Bind(wxEVT_STC_CHARADDED, &EditPane::OnCharAdded, this, wxID_ANY); } /** diff --git a/src/widgets/EditPane.h b/src/widgets/EditPane.h index 5552905..2bc0136 100644 --- a/src/widgets/EditPane.h +++ b/src/widgets/EditPane.h @@ -30,7 +30,6 @@ private: bool FileReadable(); bool FileWritable(); void BindEvents(); - void OnMarginClick(wxStyledTextEvent &event); void OnCharAdded(wxStyledTextEvent &event); void SetTheme(string theme_name); void _ApplyTheme(JsonValue &lexer_map); diff --git a/src/widgets/FilePane.cpp b/src/widgets/FilePane.cpp new file mode 100644 index 0000000..ee20e9d --- /dev/null +++ b/src/widgets/FilePane.cpp @@ -0,0 +1,94 @@ +#include "widget.h" + +extern MainFrame *Glob_main_frame; + +enum CustomFilePaneEventIds { + myFP_ID_OPEN = (wxID_HIGHEST * 2), + myFP_ID_RENAME, + myFP_ID_DELETE +}; + +/** + * Constructor + * @param parent + * @param id + * @param dir + * @param pos + * @param size + * @param style + * @param filter + */ +FilePane::FilePane( + wxWindow* parent, + const wxWindowID id, + const wxString &dir, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &filter +) : wxGenericDirCtrl(parent, id, dir, pos, size, style, filter) +{ + this->CreateContextMenu(); + this->BindEvents(); + + this->SetDefaultPath(wxStandardPaths::Get().GetDocumentsDir()); + this->SetPath(this->GetDefaultPath()); +} + +/** + * Destructor + */ +FilePane::~FilePane() +{ + delete this->contextMenu; +} + +/** + * Bind event handlers + * + * @return void + */ +void FilePane::BindEvents() +{ + // Open files on double-click or enter + this->Bind(wxEVT_DIRCTRL_FILEACTIVATED, [=](wxTreeEvent&) { + wxLogDebug("File activated event fired"); + this->OpenSelectedFiles(); + }, wxID_ANY); + + // Context Menu + this->Bind(wxEVT_TREE_ITEM_RIGHT_CLICK, [=](wxTreeEvent&) { + this->PopupMenu(this->contextMenu); + }, wxID_ANY); + + // Open file(s) + this->Bind(wxEVT_MENU, [=](wxCommandEvent&) { + this->OpenSelectedFiles(); + }, myFP_ID_OPEN); +} + +/** + * Create the filePane Context Menu + * + * @return void + */ +void FilePane::CreateContextMenu() +{ + this->contextMenu = new wxMenu(); + this->contextMenu->Append(myFP_ID_OPEN, "&Open Ctrl+Shift+O", "Open the selected file(s)"); + //this->contextMenu->Append(myFP_ID_RENAME, "&Rename Ctrl+Shift+R", "Rename the selected file"); + //this->contextMenu->Append(myFP_ID_DELETE, "Delete", "Delete the selected file"); +} + +/** + * Open the files that are currently selected in the file pane in the current + * editor window + * + * @return void + */ +void FilePane::OpenSelectedFiles() +{ + wxArrayString paths; + this->GetPaths(paths); + Glob_main_frame->OpenFiles(paths); +} \ No newline at end of file diff --git a/src/widgets/FilePane.h b/src/widgets/FilePane.h new file mode 100644 index 0000000..5e65229 --- /dev/null +++ b/src/widgets/FilePane.h @@ -0,0 +1,24 @@ +#ifndef TYRO_FILE_PANE_H +#define TYRO_FILE_PANE_H + +class FilePane : public wxGenericDirCtrl { +public: + FilePane( + wxWindow *parent, + const wxWindowID id = wxID_ANY, + const wxString &dir = wxDirDialogDefaultFolderStr, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = wxDIRCTRL_EDIT_LABELS | wxDIRCTRL_MULTIPLE, + const wxString &filter = wxEmptyString + ); + ~FilePane(); +private: + wxMenu *contextMenu = nullptr; + void BindEvents(); + void CreateContextMenu(); + void OpenSelectedFiles(); +}; + +#endif /* TYRO_FILE_PANE_H */ + diff --git a/src/widgets/MainFrame.cpp b/src/widgets/MainFrame.cpp index f05cfb7..e03904c 100644 --- a/src/widgets/MainFrame.cpp +++ b/src/widgets/MainFrame.cpp @@ -8,6 +8,7 @@ extern TyroMenu *Glob_menu_bar; extern PrefPane *Glob_pref_pane; extern wxStatusBar *Glob_status_bar; static TabContainer *notebook = nullptr; +static FilePane *filePane = nullptr; // Frame icon #include "../../resources/xpm/tyro.xpm" @@ -21,6 +22,8 @@ MainFrame::MainFrame(wxFrame *frame, const wxString &title) // Create the tab container notebook = new TabContainer(this); + filePane = new FilePane(this); + // Set the frame icon wxIcon app_icon(tyro_icon); this->SetIcon(app_icon); @@ -45,6 +48,7 @@ MainFrame::~MainFrame() wxLogDebug("Main Frame Destructor Called."); delete notebook; delete toolBar; + delete filePane; wxDELETE(this->findDlg); wxDELETE(this->findData); @@ -76,6 +80,16 @@ void MainFrame::DoLayout() .Resizable(true); this->manager->AddPane(toolBar, toolBarPaneInfo); + wxAuiPaneInfo filePaneInfo; + filePaneInfo.Left() + .MinSize(225, 550) + .TopDockable(false) + .BottomDockable(false) + .RightDockable(true) + .LeftDockable(true) + .Resizable(true); + this->manager->AddPane(filePane, filePaneInfo); + wxAuiPaneInfo notebookPaneInfo; notebookPaneInfo.CenterPane(); this->manager->AddPane(notebook, notebookPaneInfo); @@ -162,6 +176,7 @@ void MainFrame::BindEvents() Bind(wxEVT_MENU, &MainFrame::OnSave, this, wxID_SAVE); Bind(wxEVT_MENU, &MainFrame::OnSaveAs, this, wxID_SAVEAS); Bind(wxEVT_MENU, &MainFrame::OnCloseTab, this, wxID_CLOSE); + Bind(wxEVT_MENU, &TabContainer::OnCloseAllButThis, notebook, myID_CLOSE_ALL_BUT_THIS); Bind(wxEVT_MENU, &TabContainer::OnCloseAll, notebook, myID_CLOSE_ALL); Bind(wxEVT_MENU, &MainFrame::OnQuit, this, wxID_EXIT); diff --git a/src/widgets/PrefPane.cpp b/src/widgets/PrefPane.cpp index d0a28bf..2f41f04 100644 --- a/src/widgets/PrefPane.cpp +++ b/src/widgets/PrefPane.cpp @@ -15,6 +15,13 @@ public: wxSizer *sizer = new wxBoxSizer(wxVERTICAL); + // Font size will have to wait until wxWidgets 3.0.3, where font widgets + // will actually work + /*wxFontPickerCtrl *fontPicker = new wxFontPickerCtrl(this, wxID_ANY); + wxSizer *fontSizer = new wxBoxSizer(wxHORIZONTAL); + fontSizer->Add(fontPicker, wxSizerFlags().Border()); + sizer->Add(fontSizer, wxSizerFlags().Border());*/ + sizer->Add(showLineNumbers, wxSizerFlags().Border()); sizer->Add(showIndentGuides, wxSizerFlags().Border()); sizer->Add(showCodeFolding, wxSizerFlags().Border()); @@ -25,9 +32,24 @@ public: // On supported platforms if (wxPreferencesEditor::ShouldApplyChangesImmediately()) { - showLineNumbers->Bind(wxEVT_CHECKBOX, &GeneralPrefPanePage::ToggleShowLineNumbers, this, myID_PREFS_LINE_NUMBERS); - showIndentGuides->Bind(wxEVT_CHECKBOX, &GeneralPrefPanePage::ToggleShowIndentGuides, this, myID_PREFS_IDENT_GUIDES); - showCodeFolding->Bind(wxEVT_CHECKBOX, &GeneralPrefPanePage::ToggleShowCodeFolding, this, myID_PREFS_CODE_FOLDING); + showLineNumbers->Bind(wxEVT_CHECKBOX, [=] (wxCommandEvent &event) { + Glob_config->Write("show_line_numbers", event.IsChecked()); + this->frame->OnPrefsChanged(event); + Glob_config->Flush(); + }, myID_PREFS_LINE_NUMBERS); + + showIndentGuides->Bind(wxEVT_CHECKBOX, [=] (wxCommandEvent &event) { + Glob_config->Write("show_indent_guides", event.IsChecked()); + this->frame->OnPrefsChanged(event); + Glob_config->Flush(); + }, myID_PREFS_IDENT_GUIDES); + + + showCodeFolding->Bind(wxEVT_CHECKBOX, [=] (wxCommandEvent &event) { + Glob_config->Write("show_code_folding", event.IsChecked()); + this->frame->OnPrefsChanged(event); + Glob_config->Flush(); + }, myID_PREFS_CODE_FOLDING); } } @@ -74,31 +96,9 @@ public: private: MainFrame *frame; - wxCheckBox *showLineNumbers; - wxCheckBox *showIndentGuides; - wxCheckBox *showCodeFolding; - - void ToggleShowLineNumbers(wxCommandEvent &event) - { - - Glob_config->Write("show_line_numbers", event.IsChecked()); - this->frame->OnPrefsChanged(event); - Glob_config->Flush(); - } - - void ToggleShowIndentGuides(wxCommandEvent &event) - { - Glob_config->Write("show_indent_guides", event.IsChecked()); - this->frame->OnPrefsChanged(event); - Glob_config->Flush(); - } - - void ToggleShowCodeFolding(wxCommandEvent &event) - { - Glob_config->Write("show_code_folding", event.IsChecked()); - this->frame->OnPrefsChanged(event); - Glob_config->Flush(); - } + wxCheckBox *showLineNumbers = nullptr; + wxCheckBox *showIndentGuides = nullptr; + wxCheckBox *showCodeFolding = nullptr; }; class GeneralPrefPane: public wxStockPreferencesPage { diff --git a/src/widgets/TabContainer.cpp b/src/widgets/TabContainer.cpp index 655e9dd..48ca4af 100644 --- a/src/widgets/TabContainer.cpp +++ b/src/widgets/TabContainer.cpp @@ -6,6 +6,8 @@ extern TyroMenu *Glob_menu_bar; extern wxStatusBar *Glob_status_bar; + +static vector editors; static unsigned long untitled_document_count = 0; /** @@ -27,10 +29,10 @@ TabContainer::TabContainer( { this->parent = (MainFrame *) parent; - Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &TabContainer::OnClose, this, wxID_ANY); - Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSED, &TabContainer::OnClosed, this, wxID_ANY); - Bind(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, &TabContainer::OnTabContextMenu, this, wxID_ANY); - Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, &TabContainer::OnTabSwitch, this, wxID_ANY); + this->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &TabContainer::OnClose, this, wxID_ANY); + this->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSED, &TabContainer::OnClosed, this, wxID_ANY); + this->Bind(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, &TabContainer::OnTabContextMenu, this, wxID_ANY); + this->Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, &TabContainer::OnTabSwitch, this, wxID_ANY); } /** @@ -41,6 +43,16 @@ TabContainer::~TabContainer() wxLogDebug("TabContainer destructor called"); } +/** + * Create a new editor instance for a new tab + * + * @return EditPane* + */ +EditPane* TabContainer::NewEditor() +{ + return new EditPane(this); +} + /** * Add a new blank document * @@ -54,9 +66,7 @@ void TabContainer::AddTab() caption.Printf("Untitled %lu", untitled_document_count); - EditPane *editor = new EditPane(this); - - this->AddPage(editor, caption, true); + this->AddPage(this->NewEditor(), caption, true); } /** @@ -76,7 +86,7 @@ void TabContainer::AddTab(wxString filePath) } wxString caption= fileName.GetFullName(); - EditPane *editor = new EditPane(this); + EditPane *editor = this->NewEditor(); if (editor->Load(filePath)) { @@ -150,7 +160,7 @@ void TabContainer::OnClose(wxAuiNotebookEvent &event) return event.Veto(); } } - }; + } } /** @@ -180,6 +190,7 @@ void TabContainer::OnTabContextMenu(wxAuiNotebookEvent &WXUNUSED(event)) wxMenu *contextMenu = new wxMenu(); contextMenu->Append(wxID_CLOSE, "&Close\tCtrl+W", "Close the current tab"); contextMenu->Append(myID_CLOSE_ALL, "C&lose All\tShift+Ctrl+W", "Close all open documents."); + contextMenu->Append(myID_CLOSE_ALL_BUT_THIS, "Close All but this\tCtrl+Shift+Alt+W", "Close all open documents, except the one selected"); this->PopupMenu(contextMenu); } @@ -195,6 +206,40 @@ void TabContainer::OnCloseAll(wxCommandEvent &WXUNUSED(event)) this->parent->EnableEditControls(false); } +/** + * Close all tabs but the one selected + * + * @param wxCommandEvent& event + * @return void + */ +void TabContainer::OnCloseAllButThis(wxCommandEvent &WXUNUSED(event)) +{ + auto ind = this->GetSelection(); + wxString curr_tooltip = this->GetPageToolTip(ind); + wxString curr_caption = this->GetPageText(ind); + size_t page_count = this->GetPageCount(); + + this->Freeze(); + + // Do the loop in this order, as the indices change + // when tabs are removed + size_t i = page_count; + + while(i > 0) + { + i--; + // Identify the current tab by the caption and tooltip + // If they don't match, remove the tab + if ( + curr_tooltip == this->GetPageToolTip(i) && + curr_caption == this->GetPageText(i) + ) continue; + + this->RemovePage(i); + } + this->Thaw(); +} + /** * Update menu state when switching tabs * diff --git a/src/widgets/TabContainer.h b/src/widgets/TabContainer.h index 8fb0b7d..10866dc 100644 --- a/src/widgets/TabContainer.h +++ b/src/widgets/TabContainer.h @@ -28,8 +28,10 @@ public: EditPane *GetCurrentEditor(); EditPane *GetEditor(size_t page_idx); void OnCloseAll(wxCommandEvent &event); + void OnCloseAllButThis(wxCommandEvent &event); private: MainFrame *parent = nullptr; + EditPane *NewEditor(); void OnTabSwitch(wxAuiNotebookEvent &event); void OnClose(wxAuiNotebookEvent &event); void OnClosed(wxAuiNotebookEvent &event); diff --git a/src/widgets/widget.h b/src/widgets/widget.h index 35334e6..2331ba4 100644 --- a/src/widgets/widget.h +++ b/src/widgets/widget.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include // Tyro includes #include "TyroMenu.h" @@ -20,6 +22,7 @@ #include "TabContainer.h" #include "MainFrame.h" #include "PrefPane.h" +#include "FilePane.h" #endif /* TYRO_WIDGET_H */