diff --git a/juci/CMakeLists.txt b/juci/CMakeLists.txt index b8474db..b6f672f 100644 --- a/juci/CMakeLists.txt +++ b/juci/CMakeLists.txt @@ -101,8 +101,6 @@ add_executable(${project_name} #list of every needed file to create the executable juci.h juci.cc - keybindings.h - keybindings.cc menu.h menu.cc source.h diff --git a/juci/api.cc b/juci/api.cc index cf1099d..14acce7 100644 --- a/juci/api.cc +++ b/juci/api.cc @@ -1,16 +1,16 @@ #include "api.h" #include "logging.h" +#include "singletons.h" -Menu::Controller* PluginApi::menu_; -Notebook::Controller* PluginApi::notebook_; +Menu* PluginApi::menu_=nullptr; +Notebook::Controller* PluginApi::notebook_=nullptr; ///////////////////////////// //// API ServiceProvider //// ///////////////////////////// -PluginApi::PluginApi(Menu::Controller& menu_ctl_, - Notebook::Controller& notebook_ctl_) { +PluginApi::PluginApi() { DEBUG("Adding pointers for the API"); - menu_ = &menu_ctl_; - notebook_ = ¬ebook_ctl_; + notebook_ = Singleton::notebook(); + menu_ = Singleton::menu(); DEBUG("Initiating plugins(from plugins.py).."); #ifndef __APPLE__ InitPlugins(); //TODO: fix this @@ -18,11 +18,6 @@ PluginApi::PluginApi(Menu::Controller& menu_ctl_, DEBUG("Plugins initiated.."); } -PluginApi::~PluginApi() { - menu_ = NULL; - notebook_ = NULL; -} - std::string PluginApi::ProjectPath() { int MAXPATHLEN = 50; char temp[MAXPATHLEN]; @@ -69,8 +64,7 @@ void PluginApi::AddMenuElement(std::string plugin_name) { DEBUG("Adding menu element for "+plugin_name); AddMenuXml(plugin_name, "PluginMenu"); std::string plugin_action_name = plugin_name+"Menu"; - menu_->keybindings_.action_group_menu() - ->add(Gtk::Action::create(plugin_action_name, plugin_name)); + Singleton::menu()->action_group->add(Gtk::Action::create(plugin_action_name, plugin_name)); } void PluginApi::AddSubMenuElement(std::string parent_menu, @@ -79,8 +73,7 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, std::string plugin_path, std::string menu_keybinding) { AddSubMenuXml(menu_func_name, parent_menu); - menu_->keybindings_.action_group_menu() - ->add(Gtk::Action::create(menu_func_name, + Singleton::menu()->action_group->add(Gtk::Action::create(menu_func_name, menu_name), Gtk::AccelKey(menu_keybinding), [=]() { @@ -89,9 +82,9 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, } void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = menu_->keybindings_.model_.menu_ui_string(); + std::string temp_menu = Singleton::menu()->ui; std::size_t plugin_menu_pos = temp_menu.find(parent_menu); - // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc + // +2 gets you outside of the tag:<'menu_name'> plugin_menu_pos+=parent_menu.size() +2; std::string menu_prefix = temp_menu.substr(0, plugin_menu_pos); std::string menu_suffix = temp_menu.substr(plugin_menu_pos); @@ -99,23 +92,21 @@ void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { " " " "; - menu_->keybindings_.model_.menu_ui_string_ = - menu_prefix + menu_input + menu_suffix; + Singleton::menu()->ui = menu_prefix + menu_input + menu_suffix; } void PluginApi::AddSubMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = menu_->keybindings_.model_.menu_ui_string(); + std::string temp_menu = Singleton::menu()->ui; std::size_t parent_menu_pos = temp_menu.find(parent_menu); - // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc + // +2 gets you outside of the tag:<'menu_name'> parent_menu_pos+=parent_menu.size() +2; std::string menu_prefix = temp_menu.substr(0, parent_menu_pos); std::string menu_suffix = temp_menu.substr(parent_menu_pos); std::string menu_input =""; - menu_->keybindings_.model_.menu_ui_string_ = - menu_prefix + menu_input + menu_suffix; + Singleton::menu()->ui = menu_prefix + menu_input + menu_suffix; } /////////////////////// @@ -221,7 +212,7 @@ void libjuci::IterToWordEnd(Gtk::TextIter &iter) { Glib::RefPtr libjuci::BufferFromNotebook() { return Glib::RefPtr(PluginApi::notebook_ - ->CurrentTextView().get_buffer()); + ->CurrentSourceView()->get_buffer()); } Gtk::TextIter libjuci::IterFromNotebook() { diff --git a/juci/api.h b/juci/api.h index 900d206..3f97710 100644 --- a/juci/api.h +++ b/juci/api.h @@ -12,9 +12,8 @@ //////////////////// class PluginApi { public: - PluginApi(Menu::Controller&, Notebook::Controller&); - ~PluginApi(); - static Menu::Controller* menu_; + PluginApi(); + static Menu* menu_; static Notebook::Controller* notebook_; static void InitPlugins(); static std::string ProjectPath(); diff --git a/juci/config.cc b/juci/config.cc index 9fa2a69..7302984 100644 --- a/juci/config.cc +++ b/juci/config.cc @@ -1,8 +1,10 @@ +#include "singletons.h" #include "config.h" #include "logging.h" +#include +#include -MainConfig::MainConfig() : - keybindings_cfg() { +MainConfig::MainConfig() { INFO("Reading config file"); boost::property_tree::json_parser::read_json("config.json", cfg_); INFO("Config file read"); @@ -13,7 +15,7 @@ MainConfig::MainConfig() : } void MainConfig::GenerateSource() { - auto source_cfg=Singletons::Config::source(); + auto source_cfg=Singleton::Config::source(); DEBUG("Fetching source cfg"); // boost::property_tree::ptree auto source_json = cfg_.get_child("source"); @@ -58,39 +60,49 @@ void MainConfig::GenerateSource() { } void MainConfig::GenerateTerminalCommands() { + auto terminal_cfg=Singleton::Config::terminal(); boost::property_tree::ptree source_json = cfg_.get_child("project"); boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands"); boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands"); for (auto &i : compile_commands_json) { - terminal_cfg.compile_commands.emplace_back(i.second.get_value()); + terminal_cfg->compile_commands.emplace_back(i.second.get_value()); } for (auto &i : run_commands_json) { - terminal_cfg.run_command=(i.second.get_value()); //TODO: run_commands array->one run_command? + terminal_cfg->run_command=(i.second.get_value()); //TODO: run_commands array->one run_command? } } void MainConfig::GenerateKeybindings() { + auto menu=Singleton::menu(); DEBUG("Fetching keybindings"); std::string line; std::ifstream menu_xml("menu.xml"); if (menu_xml.is_open()) { while (getline(menu_xml, line)) - keybindings_cfg.AppendXml(line); + menu->ui+=line; } boost::property_tree::ptree keys_json = cfg_.get_child("keybindings"); - for (auto &i : keys_json) - keybindings_cfg.key_map()[i.first] = i.second.get_value(); + for (auto &i : keys_json) { + auto key=i.second.get_value(); +#ifdef __APPLE__ + auto pos=key.find(""); + if(pos!=std::string::npos) + key.replace(pos, 9, ""); +#endif + menu->key_map[i.first] = key; + } DEBUG("Keybindings fetched"); } void MainConfig::GenerateDirectoryFilter() { + auto dir_cfg=Singleton::Config::directories(); DEBUG("Fetching directory filter"); boost::property_tree::ptree dir_json = cfg_.get_child("directoryfilter"); boost::property_tree::ptree ignore_json = dir_json.get_child("ignore"); boost::property_tree::ptree except_json = dir_json.get_child("exceptions"); for ( auto &i : except_json ) - dir_cfg.AddException(i.second.get_value()); + dir_cfg->AddException(i.second.get_value()); for ( auto &i : ignore_json ) - dir_cfg.AddIgnore(i.second.get_value()); + dir_cfg->AddIgnore(i.second.get_value()); DEBUG("Directory filter fetched"); } diff --git a/juci/config.h b/juci/config.h index c6913fc..9729467 100644 --- a/juci/config.h +++ b/juci/config.h @@ -2,19 +2,9 @@ #define JUCI_CONFIG_H_ #include #include -#include -#include -#include "singletons.h" -#include "keybindings.h" -#include "source.h" -#include "directories.h" -#include "terminal.h" class MainConfig { public: - Terminal::Config terminal_cfg; - Keybindings::Config keybindings_cfg; - Directories::Config dir_cfg; MainConfig(); void PrintMenu(); void GenerateSource(); diff --git a/juci/config.json b/juci/config.json index 42effbb..efc9003 100644 --- a/juci/config.json +++ b/juci/config.json @@ -58,6 +58,8 @@ "edit_undo": "z", "edit_redo": "y", "edit_find": "f", + "goto_declaration": "d", + "goto_method": "m", "compile_and_run": "r", "compile": "r" }, diff --git a/juci/directories.cc b/juci/directories.cc index 6e8ca9e..65a28dd 100644 --- a/juci/directories.cc +++ b/juci/directories.cc @@ -1,8 +1,8 @@ #include "directories.h" #include "logging.h" +#include "singletons.h" -Directories::Controller::Controller(Directories::Config& cfg) : - config_(cfg) { +Directories::Controller::Controller() { DEBUG("adding treeview to scrolledwindow"); m_ScrolledWindow.add(m_TreeView); m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); @@ -29,10 +29,10 @@ open_folder(const boost::filesystem::path& dir_path) { bool Directories::Controller::IsIgnored(std::string path) { DEBUG("Checking if file-/directory is filtered"); std::transform(path.begin(), path.end(), path.begin(), ::tolower); - if (config().IsException(path)) { + if (Singleton::Config::directories()->IsException(path)) { return false; } - if (config().IsIgnored(path)) { + if (Singleton::Config::directories()->IsIgnored(path)) { return true; } return false; @@ -156,12 +156,6 @@ GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_na return "no project name"; } -Directories::Config::Config() { -} -Directories::Config::Config(Directories::Config& cfg) : - ignore_list_(cfg.ignore_list()), exception_list_(cfg.exception_list()) { -} - void Directories::Config::AddIgnore(std::string filter) { ignore_list_.push_back(filter); } diff --git a/juci/directories.h b/juci/directories.h index ff7d195..c6363c5 100644 --- a/juci/directories.h +++ b/juci/directories.h @@ -14,8 +14,6 @@ namespace Directories { class Config { public: - Config(Config &original); - Config(); std::vector ignore_list() { return ignore_list_; } std::vector exception_list() { return exception_list_; } void AddIgnore(std::string filter); @@ -43,10 +41,8 @@ namespace Directories { class Controller { public: Controller(); - Controller(Directories::Config& cfg); View& view() { return view_;} Model& model() { return model_;} - Directories::Config& config() { return config_;} Gtk::ScrolledWindow& widget() {return m_ScrolledWindow;} void open_folder(const boost::filesystem::path& dir_path); void list_dirs(const boost::filesystem::path& dir_path, @@ -64,7 +60,6 @@ namespace Directories { private: View view_; Model model_; - Directories::Config config_; protected: void on_treeview_row_activated(const Gtk::TreeModel::Path& path, diff --git a/juci/juci.cc b/juci/juci.cc index f19e7da..4ca0558 100644 --- a/juci/juci.cc +++ b/juci/juci.cc @@ -1,4 +1,5 @@ #include "juci.h" +#include "singletons.h" void init_logging() { add_common_attributes(); @@ -36,11 +37,11 @@ void Juci::on_activate() { window->show(); if(directory!="") { //TODO: use the following instead, window->notebook.open_directory(directory); - window->notebook.project_path=directory; - window->notebook.directories.open_folder(directory); + Singleton::notebook()->project_path=directory; + Singleton::notebook()->directories.open_folder(directory); } for(auto &f: files) - window->notebook.OnOpenFile(f); + Singleton::notebook()->open_file(f); } int main(int argc, char *argv[]) { diff --git a/juci/keybindings.cc b/juci/keybindings.cc deleted file mode 100644 index 2408155..0000000 --- a/juci/keybindings.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "keybindings.h" - -Keybindings::Model::Model(Keybindings::Config &config) : - menu_ui_string_(config.menu_xml()) { - /* hidden_ui_string_ = - " " - " " - " " - " " - " ";*/ -} - -Keybindings::Model::~Model() { -} - -Keybindings::Controller::Controller(Keybindings::Config &config) : - config_(config), model_(config) { - action_group_menu_ = Gtk::ActionGroup::create(); - ui_manager_menu_ = Gtk::UIManager::create(); - action_group_hidden_ = Gtk::ActionGroup::create(); - ui_manager_hidden_ = Gtk::UIManager::create(); -} - -Keybindings::Controller::~Controller() { -} - -void Keybindings::Controller::BuildMenu() { - try { - ui_manager_menu_->add_ui_from_string(model_.menu_ui_string()); - } - catch (const Glib::Error &ex) { - std::cerr << "building menu failed" << ex.what(); - } - ui_manager_menu_->insert_action_group(action_group_menu_); -} -void Keybindings::Controller::BuildHiddenMenu() { - try { - ui_manager_hidden_->add_ui_from_string(model_.hidden_ui_string()); - } - catch (const Glib::Error &ex) { - std::cerr << "building hidden menu failed" << ex.what(); - } - ui_manager_hidden_->insert_action_group(action_group_hidden_); -} - -Keybindings::Config::Config(Keybindings::Config &original) { - SetMenu(original.menu_xml()); - SetKeyMap(original.key_map()); -} - -Keybindings::Config::Config() { - menu_xml_ = ""; - } - -void Keybindings::Config::AppendXml(std::string &child) { - menu_xml_ += child; -} - -void Keybindings::Config::SetMenu(std::string &menu_xml) { - menu_xml_ = menu_xml; -} - -void Keybindings::Config::SetKeyMap(std::unordered_map &key_map) { - key_map_ = key_map; -} diff --git a/juci/keybindings.h b/juci/keybindings.h deleted file mode 100644 index eafccd5..0000000 --- a/juci/keybindings.h +++ /dev/null @@ -1,66 +0,0 @@ -//juCi++ class that holds every keybinding. -#ifndef JUCI_KEYBINDINGS_H_ -#define JUCI_KEYBINDINGS_H_ - -#include -#include "gtkmm.h" -#include -//#include "config.h" //TODO :: remove? - -namespace Keybindings { - - class Config { - public: - Config(Config &original); - Config(); - std::string& menu_xml() { return menu_xml_; } - std::unordered_map& key_map() { return key_map_; } - void AppendXml(std::string &child); - void SetMenu(std::string &menu_xml); - void SetKeyMap(std::unordered_map &key_map); - private: - std::unordered_map key_map_; - std::string menu_xml_; - std::string hidden_ui_string_; - };//Config - - class Model { - public: - Model(Keybindings::Config &config); - virtual ~Model(); - std::string menu_ui_string() { return menu_ui_string_; } - std::string hidden_ui_string() { return hidden_ui_string_; } - //private: - std::string menu_ui_string_; - std::string hidden_ui_string_; - }; // Model - - class Controller { - public: - explicit Controller(Keybindings::Config &config); - virtual ~Controller(); - Glib::RefPtr action_group_menu() { - return action_group_menu_; - }; - Glib::RefPtr ui_manager_menu() { - return ui_manager_menu_; - }; - Glib::RefPtr action_group_hidden() { - return action_group_hidden_; - }; - Glib::RefPtr ui_manager_hidden() { - return ui_manager_hidden_; - }; - void BuildMenu(); - void BuildHiddenMenu(); - // protected: - Glib::RefPtr ui_manager_menu_; - Glib::RefPtr action_group_menu_; - Glib::RefPtr ui_manager_hidden_; - Glib::RefPtr action_group_hidden_; - // private: - Keybindings::Config config_; - Keybindings::Model model_; - };//Controller -} -#endif // JUCI_KEYBINDINGS_H_ diff --git a/juci/menu.cc b/juci/menu.cc index 0f09906..a613492 100644 --- a/juci/menu.cc +++ b/juci/menu.cc @@ -1,76 +1,37 @@ #include "menu.h" +#include -Menu::View::View(Gtk::Orientation orientation) : - view_(orientation) { - Gtk::MenuBar menutest; - view_.pack_end(menutest); -} -Gtk::Box &Menu::View::view( - Glib::RefPtr ui_manager) { - view_.pack_start(*ui_manager->get_widget("/MenuBar"), Gtk::PACK_SHRINK); - return view_; -} +Menu::Menu() : box(Gtk::ORIENTATION_VERTICAL) { + action_group = Gtk::ActionGroup::create(); + ui_manager = Gtk::UIManager::create(); -Menu::Controller::Controller(Keybindings::Controller& keybindings) : - menu_view_(Gtk::ORIENTATION_VERTICAL), - keybindings_(keybindings) { - keybindings_.action_group_menu()->add(Gtk::Action::create("FileNew", - "New File")); - keybindings_.action_group_menu()->add(Gtk::Action::create("EditMenu", - Gtk::Stock::EDIT)); - keybindings_.action_group_menu()->add(Gtk::Action::create("WindowMenu", - "_Window")); - keybindings_.action_group_menu()->add(Gtk::Action::create("WindowSplitWindow", - "Split window"), - Gtk::AccelKey(keybindings_.config_ - .key_map()["split_window"]),//"S"), - [this]() { - OnWindowSplitWindow(); - }); - keybindings_.action_group_menu()->add(Gtk::Action::create("ProjectMenu", - "P_roject")); - keybindings_.action_group_menu()->add(Gtk::Action::create("PluginMenu", - "_Plugins")); - keybindings_.action_group_menu()->add(Gtk::Action::create("HelpMenu", - Gtk::Stock::HELP)); - keybindings_.action_group_menu()->add(Gtk::Action::create("HelpAbout", - Gtk::Stock::ABOUT), - [this]() { - OnHelpAbout(); - }); - keybindings_.action_group_hidden()->add(Gtk::Action::create("Test"), - Gtk::AccelKey("K"), - [this]() { - OnHelpAbout(); - }); - //keybindings_.BuildMenu(); // moved to window.cc - keybindings_.BuildHiddenMenu(); - } // Controller -Gtk::Box &Menu::Controller::view() { - return menu_view_.view(keybindings_.ui_manager_menu()); -} -void Menu::Controller::OnPluginAddSnippet() { - //TODO(Forgi add you snippet magic code) - std::cout << "Add snippet" << std::endl; - //juci_api::py::LoadPlugin("snippet"); -} -void Menu::Controller::OnFileOpenFile() { - std::cout << "Open file clicked" << std::endl; - //TODO(Oyvang) Legg til funksjon + action_group->add(Gtk::Action::create("FileNew", "New File")); + action_group->add(Gtk::Action::create("EditMenu", Gtk::Stock::EDIT)); + action_group->add(Gtk::Action::create("WindowMenu", "_Window")); + action_group->add(Gtk::Action::create("WindowSplitWindow", "Split window"), Gtk::AccelKey(key_map["split_window"]), [this]() { + }); + action_group->add(Gtk::Action::create("ProjectMenu", "P_roject")); + action_group->add(Gtk::Action::create("SourceMenu", "_Source")); + action_group->add(Gtk::Action::create("PluginMenu", "_Plugins")); + action_group->add(Gtk::Action::create("HelpMenu", Gtk::Stock::HELP)); + action_group->add(Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT), [this]() { + }); } -void Menu::Controller::OnEditCut() { - std::cout << "Clicked cut" << std::endl; - //TODO(Oyvang) Legg til funksjon -} -void Menu::Controller::OnEditFind() { - std::cout << "Clicked find" << std::endl; - //TODO(Oyvang) Legg til funksjon + +Gtk::Widget& Menu::get_widget() { + return *ui_manager->get_widget("/MenuBar"); } -void Menu::Controller::OnWindowSplitWindow() { - std::cout << "Clicked split window" << std::endl; - //TODO(Oyvang) Legg til funksjon + +Gtk::Menu& Menu::get_source_menu() { + return *(Gtk::Menu*)ui_manager->get_widget("/MenuBar/SourceMenu"); } -void Menu::Controller::OnHelpAbout() { - std::cout << "Clicked about" << std::endl; - //TODO(Oyvang) Legg til funksjon + +void Menu::build() { + try { + ui_manager->add_ui_from_string(ui); + } + catch (const Glib::Error &ex) { + std::cerr << "building menu failed" << ex.what(); + } + ui_manager->insert_action_group(action_group); } diff --git a/juci/menu.h b/juci/menu.h index f743999..40e3cb3 100644 --- a/juci/menu.h +++ b/juci/menu.h @@ -1,36 +1,21 @@ #ifndef JUCI_MENU_H_ #define JUCI_MENU_H_ -#include -#include "gtkmm.h" -#include "keybindings.h" +#include +#include +#include -namespace Menu { - class View { - public: - explicit View(Gtk::Orientation orient); - Gtk::Box &view(Glib::RefPtr ui_manager); - protected: - Gtk::Box view_; - }; // class View - class Controller { - public: - explicit Controller(Keybindings::Controller& keybindings); - Gtk::Box &view(); - - Keybindings::Controller &keybindings_; - View menu_view_; - void OnFileNewEmptyfile(); - void OnFileNewCCFile(); - void OnFileNewHeaderFile(); - void OnFileOpenFile(); - void OnFileOpenFolder(); - void OnPluginAddSnippet(); - void OnWindowCloseTab(); - void OnEditCut(); - void OnEditFind(); - void OnWindowSplitWindow(); - void OnHelpAbout(); - }; // class Controller -} // namespace Menu +class Menu { +public: + Menu(); + Gtk::Widget& get_widget(); + Gtk::Menu& get_source_menu(); + void build(); + + Gtk::Box box; + std::unordered_map key_map; + std::string ui; + Glib::RefPtr ui_manager; + Glib::RefPtr action_group; +}; #endif // JUCI_MENU_H_ diff --git a/juci/menu.xml b/juci/menu.xml index 18f82e3..d9937d8 100644 --- a/juci/menu.xml +++ b/juci/menu.xml @@ -16,8 +16,12 @@ - - + + + + + + diff --git a/juci/notebook.cc b/juci/notebook.cc index 1398225..da6202d 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -1,124 +1,99 @@ #include #include "notebook.h" #include "logging.h" +#include "singletons.h" #include // c-library +#include //TODO: remove +using namespace std; //TODO: remove Notebook::View::View() { pack2(notebook); set_position(120); } -Notebook::Controller::Controller(Keybindings::Controller& keybindings, - Terminal::Controller& terminal, - Directories::Config& dir_cfg) : - terminal(terminal), - directories(dir_cfg) { +Notebook::Controller::Controller() : + directories() { INFO("Create notebook"); - refClipboard_ = Gtk::Clipboard::get(); + Gsv::init(); + clipboard = Gtk::Clipboard::get(); view.pack1(directories.widget(), true, true); - CreateKeybindings(keybindings); + CreateKeybindings(); INFO("Notebook Controller Success"); } // Constructor -void Notebook::Controller::CreateKeybindings(Keybindings::Controller - &keybindings) { +void Notebook::Controller::CreateKeybindings() { + auto menu=Singleton::menu(); INFO("Notebook create signal handlers"); - directories.m_TreeView.signal_row_activated() - .connect(sigc::mem_fun(*this, - &Notebook::Controller::OnDirectoryNavigation)); + directories.m_TreeView.signal_row_activated().connect(sigc::mem_fun(*this, &Notebook::Controller::OnDirectoryNavigation)); - keybindings.action_group_menu()-> - add(Gtk::Action::create("FileMenu", - Gtk::Stock::FILE)); + menu->action_group->add(Gtk::Action::create("FileMenu", Gtk::Stock::FILE)); - keybindings.action_group_menu()-> - add(Gtk::Action::create("FileNewFile", - "New file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["new_file"]), - [this]() { - OnFileNewFile(); - }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("WindowCloseTab", - "Close tab"), - Gtk::AccelKey(keybindings.config_ - .key_map()["close_tab"]), - [this]() { - OnCloseCurrentPage(); - }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditFind", - "Find"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_find"]), - [this]() { + menu->action_group->add(Gtk::Action::create("FileNewFile", "New file"), Gtk::AccelKey(menu->key_map["new_file"]), [this]() { + OnFileNewFile(); + }); + menu->action_group->add(Gtk::Action::create("WindowCloseTab", "Close tab"), Gtk::AccelKey(menu->key_map["close_tab"]), [this]() { + OnCloseCurrentPage(); + }); + menu->action_group->add(Gtk::Action::create("EditFind", "Find"), Gtk::AccelKey(menu->key_map["edit_find"]), [this]() { entry.show_search(""); - }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditCopy", - "Copy"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_copy"]), - - [this]() { - if (Pages() != 0) { - CurrentTextView().get_buffer()->copy_clipboard(refClipboard_); - } - }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditCut", - "Cut"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_cut"]), - [this]() { + }); + menu->action_group->add(Gtk::Action::create("EditCopy", "Copy"), Gtk::AccelKey(menu->key_map["edit_copy"]), [this]() { + if (Pages() != 0) { + CurrentSourceView()->get_buffer()->copy_clipboard(clipboard); + } + }); + menu->action_group->add(Gtk::Action::create("EditCut", "Cut"), Gtk::AccelKey(menu->key_map["edit_cut"]), [this]() { if (Pages() != 0) { - CurrentTextView().get_buffer()->cut_clipboard(refClipboard_); + CurrentSourceView()->get_buffer()->cut_clipboard(clipboard); } - }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditPaste", - "Paste"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_paste"]), - [this]() { + }); + menu->action_group->add(Gtk::Action::create("EditPaste", "Paste"), Gtk::AccelKey(menu->key_map["edit_paste"]), [this]() { if (Pages() != 0) { - CurrentTextView().get_buffer()->paste_clipboard(refClipboard_); + CurrentSourceView()->get_buffer()->paste_clipboard(clipboard); } - }); + }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditUndo", - "Undo"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_undo"]), - [this]() { + menu->action_group->add(Gtk::Action::create("EditUndo", "Undo"), Gtk::AccelKey(menu->key_map["edit_undo"]), [this]() { INFO("On undo"); - Glib::RefPtr undo_manager = - CurrentTextView().get_source_buffer()->get_undo_manager(); - if (Pages() != 0 && undo_manager->can_undo()) { - undo_manager->undo(); - } - INFO("Done undo"); - } - ); + Glib::RefPtr undo_manager = CurrentSourceView()->get_source_buffer()->get_undo_manager(); + if (Pages() != 0 && undo_manager->can_undo()) { + undo_manager->undo(); + } + INFO("Done undo"); + }); - keybindings.action_group_menu()-> - add(Gtk::Action::create("EditRedo", - "Redo"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_redo"]), - [this]() { - INFO("On Redo"); - Glib::RefPtr undo_manager = - CurrentTextView().get_source_buffer()->get_undo_manager(); - if (Pages() != 0 && undo_manager->can_redo()) { - undo_manager->redo(); - } - INFO("Done Redo"); - }); + menu->action_group->add(Gtk::Action::create("EditRedo", "Redo"), Gtk::AccelKey(menu->key_map["edit_redo"]), [this]() { + INFO("On Redo"); + Glib::RefPtr undo_manager = + CurrentSourceView()->get_source_buffer()->get_undo_manager(); + if (Pages() != 0 && undo_manager->can_redo()) { + undo_manager->redo(); + } + INFO("Done Redo"); + }); + + menu->action_group->add(Gtk::Action::create("SourceGotoDeclaration", "Go to declaration"), Gtk::AccelKey(menu->key_map["goto_declaration"]), [this]() { + if(CurrentPage()!=-1) { + if(CurrentSourceView()->get_declaration_location) { + auto location=CurrentSourceView()->get_declaration_location(); + if(location.first.size()>0) { + open_file(location.first); + CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); + CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + } + } + } + }); + + menu->action_group->add(Gtk::Action::create("SourceGotoMethod", "Go to method"), Gtk::AccelKey(menu->key_map["goto_method"]), [this]() { + if(CurrentPage()!=-1) { + if(CurrentSourceView()->goto_method) { + CurrentSourceView()->goto_method(); + } + } + }); entry.button_apply_set_filename.signal_clicked().connect([this]() { std::string filename=entry(); @@ -132,7 +107,7 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller else { std::ofstream f(p.string().c_str()); if(f) { - OnOpenFile(boost::filesystem::canonical(p).string()); + open_file(boost::filesystem::canonical(p).string()); if(project_path!="") directories.open_folder(project_path); //TODO: Do refresh instead } @@ -162,56 +137,49 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller INFO("Notebook signal handlers sucsess"); } -Notebook::Controller::~Controller() { - INFO("Notebook destructor"); - for (auto &i : editor_vec_) delete i; - for (auto &i : scrolledtext_vec_) delete i; -} - -void Notebook::Controller::OnOpenFile(std::string path) { +void Notebook::Controller::open_file(std::string path) { INFO("Notebook open file"); INFO("Notebook create page"); - text_vec_.emplace_back(new Source::Controller(path, project_path, terminal)); - scrolledtext_vec_.push_back(new Gtk::ScrolledWindow()); - editor_vec_.push_back(new Gtk::HBox()); - scrolledtext_vec_.back()->add(*text_vec_.back()->view); - editor_vec_.back()->pack_start(*scrolledtext_vec_.back(), true, true); - size_t pos = path.find_last_of("/\\"); // TODO #windows - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().append_page(*editor_vec_.back(), filename); - Notebook().show_all_children(); - Notebook().set_current_page(Pages()-1); - Notebook().set_focus_child(*text_vec_.back()->view); - //Add star on tab label when the page is not saved: - //TODO: instead use Gtk::TextBuffer::set_modified and Gtk::TextBuffer::get_modified - text_vec_.back()->buffer()->signal_changed().connect([this]() { - if(text_vec_.at(CurrentPage())->is_saved) { - std::string path=CurrentTextView().file_path; - size_t pos = path.find_last_of("/\\"); - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().set_tab_label_text(*(Notebook().get_nth_page(CurrentPage())), filename+"*"); + for(int c=0;cview->file_path) { + view.notebook.set_current_page(c); + return; } - text_vec_.at(CurrentPage())->is_saved=false; + } + source_views.emplace_back(new Source(path, project_path)); + scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); + hboxes.emplace_back(new Gtk::HBox()); + scrolled_windows.back()->add(*source_views.back()->view); + hboxes.back()->pack_start(*scrolled_windows.back(), true, true); + + boost::filesystem::path file_path(source_views.back()->view->file_path); + std::string title=file_path.filename().string(); + view.notebook.append_page(*hboxes.back(), title); + view.notebook.show_all_children(); + view.notebook.set_current_page(Pages()-1); + view.notebook.set_focus_child(*source_views.back()->view); + CurrentSourceView()->get_buffer()->set_modified(false); + //Add star on tab label when the page is not saved: + CurrentSourceView()->get_buffer()->signal_modified_changed().connect([this]() { + boost::filesystem::path file_path(CurrentSourceView()->file_path); + std::string title=file_path.filename().string(); + if(CurrentSourceView()->get_buffer()->get_modified()) + title+="*"; + view.notebook.set_tab_label_text(*(view.notebook.get_nth_page(CurrentPage())), title); }); } void Notebook::Controller::OnCloseCurrentPage() { INFO("Notebook close page"); if (Pages() != 0) { - if(!text_vec_.at(CurrentPage())->is_saved){ + if(CurrentSourceView()->get_buffer()->get_modified()){ AskToSaveDialog(); } int page = CurrentPage(); - Notebook().remove_page(page); - delete scrolledtext_vec_.at(page); - delete editor_vec_.at(page); - text_vec_.erase(text_vec_.begin()+ page); - scrolledtext_vec_.erase(scrolledtext_vec_.begin()+page); - editor_vec_.erase(editor_vec_.begin()+page); + view.notebook.remove_page(page); + source_views.erase(source_views.begin()+ page); + scrolled_windows.erase(scrolled_windows.begin()+page); + hboxes.erase(hboxes.begin()+page); } } void Notebook::Controller::OnFileNewFile() { @@ -220,10 +188,10 @@ void Notebook::Controller::OnFileNewFile() { void Notebook::Controller::search(bool forward) { INFO("Notebook search"); - auto start = CurrentTextView().search_start; - auto end = CurrentTextView().search_end; + auto start = CurrentSourceView()->search_start; + auto end = CurrentSourceView()->search_end; // fetch buffer and greate settings - auto buffer = CurrentTextView().get_source_buffer(); + auto buffer = CurrentSourceView()->get_source_buffer(); auto settings = gtk_source_search_settings_new(); // get search text from entry gtk_source_search_settings_set_search_text(settings, entry().c_str()); @@ -247,9 +215,9 @@ void Notebook::Controller::search(bool forward) { end.gobj()); } buffer->apply_tag_by_name("search", start, end); - CurrentTextView().scroll_to(end); - CurrentTextView().search_start = start; - CurrentTextView().search_end = end; + CurrentSourceView()->scroll_to(end); + CurrentSourceView()->search_start = start; + CurrentSourceView()->search_end = end; } void Notebook::Controller @@ -269,45 +237,39 @@ void Notebook::Controller std::stringstream sstm; sstm << row[directories.view().m_col_path]; std::string file = sstm.str(); - OnOpenFile(file); + open_file(file); } } } -Source::View& Notebook::Controller::CurrentTextView() { +Source::View* Notebook::Controller::CurrentSourceView() { INFO("Getting sourceview"); - return *text_vec_.at(CurrentPage())->view; + return source_views.at(CurrentPage())->view.get(); } int Notebook::Controller::CurrentPage() { - return Notebook().get_current_page(); + return view.notebook.get_current_page(); } int Notebook::Controller::Pages() { - return Notebook().get_n_pages(); -} -Gtk::Notebook& Notebook::Controller::Notebook() { - return view.notebook; + return view.notebook.get_n_pages(); } bool Notebook::Controller:: OnSaveFile() { - std::string path=CurrentTextView().file_path; + std::string path=CurrentSourceView()->file_path; return OnSaveFile(path); } bool Notebook::Controller:: OnSaveFile(std::string path) { INFO("Notebook save file with path"); - if (path != "") { + if (path != "" && CurrentSourceView()->get_buffer()->get_modified()) { std::ofstream file; file.open (path); - file << CurrentTextView().get_buffer()->get_text(); + file << CurrentSourceView()->get_buffer()->get_text(); file.close(); - CurrentTextView().file_path=path; - size_t pos = path.find_last_of("/\\"); - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().set_tab_label_text(*Notebook().get_nth_page(CurrentPage()), filename); - text_vec_.at(CurrentPage())->is_saved=true; + boost::filesystem::path path(CurrentSourceView()->file_path); + std::string title=path.filename().string(); + view.notebook.set_tab_label_text(*view.notebook.get_nth_page(CurrentPage()), title); + CurrentSourceView()->get_buffer()->set_modified(false); return true; } return false; @@ -350,7 +312,7 @@ void Notebook::Controller::AskToSaveDialog() { false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); dialog.set_secondary_text( "Do you want to save: " + - CurrentTextView().file_path+" ?"); + CurrentSourceView()->file_path+" ?"); DEBUG("AskToSaveDialog: run dialog"); int result = dialog.run(); diff --git a/juci/notebook.h b/juci/notebook.h index 8ff76b1..9c1f507 100644 --- a/juci/notebook.h +++ b/juci/notebook.h @@ -11,8 +11,6 @@ #include #include #include "clangmm.h" -#include "keybindings.h" -#include "terminal.h" namespace Notebook { class View : public Gtk::Paned { @@ -22,20 +20,16 @@ namespace Notebook { }; class Controller { public: - Controller(Keybindings::Controller& keybindings, - Terminal::Controller& terminal, - Directories::Config& dir_cfg); - ~Controller(); - Source::View& CurrentTextView(); + Controller(); + Source::View* CurrentSourceView(); int CurrentPage(); - Gtk::Notebook& Notebook(); void OnCloseCurrentPage(); void OnFileNewFile(); bool OnSaveFile(); bool OnSaveFile(std::string path); void OnDirectoryNavigation(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); - void OnOpenFile(std::string filename); + void open_file(std::string filename); int Pages(); void search(bool forward); View view; @@ -43,18 +37,14 @@ namespace Notebook { std::string project_path; Directories::Controller directories; //Todo: make private after creating open_directory() Entry entry; - std::vector > text_vec_; + std::vector > source_views; private: - void CreateKeybindings(Keybindings::Controller& keybindings); + void CreateKeybindings(); void AskToSaveDialog(); - Glib::RefPtr m_refBuilder; - Glib::RefPtr refActionGroup; - Terminal::Controller& terminal; - std::vector scrolledtext_vec_; - std::vector editor_vec_; - std::list listTargets_; - Glib::RefPtr refClipboard_; + std::vector > scrolled_windows; + std::vector > hboxes; + Glib::RefPtr clipboard; }; // class controller } // namespace Notebook #endif // JUCI_NOTEBOOK_H_ diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 18e9f1a..6bee4cb 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -1,14 +1,21 @@ #include "selectiondialog.h" +#include -SelectionDialog::SelectionDialog(Gtk::TextView& text_view): text_view(text_view) {} +namespace sigc { + SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE +} -void SelectionDialog::show() { - if(rows.size()==0) - return; - - window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); +SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, bool popup): text_view(text_view), popup(popup) {} + +void SelectionDialogBase::init() { + if(popup) + window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); + else + window=std::unique_ptr(new Gtk::Dialog()); scrolled_window=std::unique_ptr(new Gtk::ScrolledWindow()); list_view_text=std::unique_ptr(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_BROWSE)); + search_entry=std::unique_ptr(new Gtk::Entry()); + list_view_text->set_search_entry(*search_entry); window->set_default_size(0, 0); window->property_decorated()=false; @@ -24,43 +31,40 @@ void SelectionDialog::show() { last_selected=-1; - list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { - if(shown) { - select(); - } - }); list_view_text->signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true); list_view_text->signal_realize().connect([this](){ resize(); }); - show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); list_view_text->clear_items(); - for (auto &i : rows) { - list_view_text->append(i.first); - } - +} + +void SelectionDialogBase::append(const std::string& row) { + list_view_text->append(row); +} + +void SelectionDialogBase::show() { scrolled_window->add(*list_view_text); - window->add(*scrolled_window); - + if(popup) + window->add(*scrolled_window); + else { + auto dialog=(Gtk::Dialog*)window.get(); + dialog->get_vbox()->pack_start(*search_entry, false, false); + dialog->get_vbox()->pack_start(*scrolled_window, true, true); + dialog->set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); + } if(rows.size()>0) { list_view_text->get_selection()->select(*list_view_text->get_model()->children().begin()); list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); } - + move(); - window->show_all(); + search_entry->show(); shown=true; - row_in_entry=false; - auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); - if(text.size()>0) { - search_entry.set_text(text); - list_view_text->set_search_entry(search_entry); - } } -void SelectionDialog::hide() { +void SelectionDialogBase::hide() { shown=false; window->hide(); if(tooltips) @@ -69,7 +73,172 @@ void SelectionDialog::hide() { on_hide(); } -void SelectionDialog::select(bool hide_window) { +void SelectionDialogBase::cursor_changed() { + auto selected=list_view_text->get_selected(); + if(selected.size()>0) { + if(selected[0]!=last_selected || last_selected==-1) { + if(tooltips) + tooltips->hide(); + auto row = rows.at(list_view_text->get_text(selected[0])); + if(row.second.size()>0) { + tooltips=std::unique_ptr(new Tooltips()); + auto tooltip_text=row.second; + auto get_tooltip_buffer=[this, tooltip_text]() { + auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); + //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) + tooltip_buffer->insert_at_cursor(tooltip_text); + return tooltip_buffer; + }; + tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); + tooltips->show(true); + } + } + } + else if(tooltips) + tooltips->hide(); + if(selected.size()>0) + last_selected=selected[0]; + else + last_selected=-1; +} + +void SelectionDialogBase::move() { + INFO("SelectionDialog set position"); + Gdk::Rectangle rectangle; + text_view.get_iter_location(start_mark->get_iter(), rectangle); + int buffer_x=rectangle.get_x(); + int buffer_y=rectangle.get_y()+rectangle.get_height(); + int window_x, window_y; + text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); + int root_x, root_y; + text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); + window->move(root_x, root_y+1); //TODO: replace 1 with some margin +} + +void SelectionDialogBase::resize() { + INFO("SelectionDialog set size"); + + if(list_view_text->get_realized()) { + int row_width=0, row_height; + Gdk::Rectangle rect; + list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); + row_width=rect.get_width(); + row_height=rect.get_height(); + + row_width+=rect.get_x()*2; //TODO: Add correct margin x and y + row_height+=rect.get_y()*2; + + if(row_width>text_view.get_width()/2) + row_width=text_view.get_width()/2; + else + scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); + + int window_height=std::min(row_height*(int)rows.size(), row_height*10); + if(!popup) + window_height+=search_entry->get_height(); + window->resize(row_width, window_height); + } +} + +SelectionDialog::SelectionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, false) {} + +void SelectionDialog::show() { + SelectionDialogBase::show(); + std::shared_ptr search_key(new std::string()); + auto filter_model=Gtk::TreeModelFilter::create(list_view_text->get_model()); + filter_model->set_visible_func([this, search_key](const Gtk::TreeModel::const_iterator& iter){ + std::string row_lc; + iter->get_value(0, row_lc); + auto search_key_lc=*search_key; + std::transform(row_lc.begin(), row_lc.end(), row_lc.begin(), ::tolower); + std::transform(search_key_lc.begin(), search_key_lc.end(), search_key_lc.begin(), ::tolower); + if(row_lc.find(search_key_lc)!=std::string::npos) + return true; + return false; + }); + list_view_text->set_model(filter_model); + list_view_text->set_search_equal_func([this](const Glib::RefPtr& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) { + return false; + }); + search_entry->signal_changed().connect([this, search_key, filter_model](){ + *search_key=search_entry->get_text(); + filter_model->refilter(); + list_view_text->set_search_entry(*search_entry); //TODO:Report the need of this to GTK's git (bug) + }); + search_entry->signal_event().connect([this, search_key, filter_model](GdkEvent* event) { + if(event->type==GDK_KEY_PRESS) { + auto key=(GdkEventKey*)event; + if(key->keyval==GDK_KEY_Down) { + auto it=list_view_text->get_selection()->get_selected(); + if(it) { + it++; + if(it) { + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + } + } + else + list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); + return true; + } + if(key->keyval==GDK_KEY_Up) { + auto it=list_view_text->get_selection()->get_selected(); + if(it) { + it--; + if(it) { + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + } + } + return true; + } + } + return false; + }); + auto activate=[this](){ + if(on_select && list_view_text->get_selected().size()>0) { + auto it=list_view_text->get_selection()->get_selected(); + std::string row; + it->get_value(0, row); + std::string selected = rows.at(row).first; + on_select(selected); + } + window->hide(); + }; + search_entry->signal_activate().connect([this, activate](){ + activate(); + }); + list_view_text->signal_row_activated().connect([this, activate](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + activate(); + }); + window->signal_focus_out_event().connect([this](GdkEventFocus*){ + window->hide(); + return true; + }); + list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); +} + +CompletionDialog::CompletionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, true) {} + +void CompletionDialog::show() { + SelectionDialogBase::show(); + + show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); + + list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + if(shown) { + select(); + } + }); + + auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); + if(text.size()>0) { + search_entry->set_text(text); + list_view_text->set_search_entry(*search_entry); + } + + row_in_entry=false; +} + +void CompletionDialog::select(bool hide_window) { row_in_entry=true; auto selected=list_view_text->get_selected(); std::pair select; @@ -97,7 +266,7 @@ void SelectionDialog::select(bool hide_window) { } } -bool SelectionDialog::on_key_release(GdkEventKey* key) { +bool CompletionDialog::on_key_release(GdkEventKey* key) { if(key->keyval==GDK_KEY_Down || key->keyval==GDK_KEY_Up) return false; @@ -107,15 +276,15 @@ bool SelectionDialog::on_key_release(GdkEventKey* key) { else { auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); if(text.size()>0) { - search_entry.set_text(text); - list_view_text->set_search_entry(search_entry); + search_entry->set_text(text); + list_view_text->set_search_entry(*search_entry); } cursor_changed(); } return false; } -bool SelectionDialog::on_key_press(GdkEventKey* key) { +bool CompletionDialog::on_key_press(GdkEventKey* key) { if((key->keyval>=GDK_KEY_0 && key->keyval<=GDK_KEY_9) || (key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) || (key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) || @@ -136,8 +305,7 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { if(it) { it++; if(it) { - list_view_text->get_selection()->select(it); - list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); } } select(false); @@ -149,8 +317,7 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { if(it) { it--; if(it) { - list_view_text->get_selection()->select(it); - list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); } } select(false); @@ -164,68 +331,3 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { hide(); return false; } - -void SelectionDialog::cursor_changed() { - auto selected=list_view_text->get_selected(); - if(selected.size()>0) { - if(selected[0]!=last_selected || last_selected==-1) { - if(tooltips) - tooltips->hide(); - auto row = rows.at(list_view_text->get_text(selected[0])); - if(row.second.size()>0) { - tooltips=std::unique_ptr(new Tooltips()); - auto tooltip_text=row.second; - auto get_tooltip_buffer=[this, tooltip_text]() { - auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); - //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) - tooltip_buffer->insert_at_cursor(tooltip_text); - return tooltip_buffer; - }; - tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); - tooltips->show(true); - } - } - } - else if(tooltips) - tooltips->hide(); - if(selected.size()>0) - last_selected=selected[0]; - else - last_selected=-1; -} - -void SelectionDialog::move() { - INFO("SelectionDialog set position"); - Gdk::Rectangle rectangle; - text_view.get_iter_location(start_mark->get_iter(), rectangle); - int buffer_x=rectangle.get_x(); - int buffer_y=rectangle.get_y()+rectangle.get_height(); - int window_x, window_y; - text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); - int root_x, root_y; - text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); - window->move(root_x, root_y+1); //TODO: replace 1 with some margin -} - -void SelectionDialog::resize() { - INFO("SelectionDialog set size"); - - if(list_view_text->get_realized()) { - int row_width=0, row_height; - Gdk::Rectangle rect; - list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); - row_width=rect.get_width(); - row_height=rect.get_height(); - - row_width+=rect.get_x()*2; //TODO: Add correct margin x and y - row_height+=rect.get_y()*2; - - if(row_width>text_view.get_width()/2) - row_width=text_view.get_width()/2; - else - scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); - - int window_height=std::min(row_height*(int)rows.size(), row_height*10); - window->resize(row_width, window_height); - } -} diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index b497d6c..d55d9a3 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -5,35 +5,55 @@ #include "logging.h" #include "tooltips.h" -class SelectionDialog { +class SelectionDialogBase { public: - SelectionDialog(Gtk::TextView& text_view); - void show(); - void hide(); - bool close(GdkEventFocus*); - void move(); - bool on_key_release(GdkEventKey* key); - bool on_key_press(GdkEventKey* key); - std::function on_hide; + SelectionDialogBase(Gtk::TextView& text_view, bool popup); + virtual void init(); //TODO: use constructor instead of init + virtual void append(const std::string& row); + virtual void show(); + virtual void hide(); + virtual void move(); - std::map > rows; + std::map > rows; //TODO: remove, instead add on_select. Also remember to destroy start_mark in destructor + std::function on_hide; bool shown=false; Glib::RefPtr start_mark; -private: - void resize(); - void select(bool hide_window=true); - void cursor_changed(); - - Gtk::Entry search_entry; - int show_offset; - bool row_in_entry; +protected: + virtual void resize(); + virtual void cursor_changed(); Gtk::TextView& text_view; std::unique_ptr window; std::unique_ptr scrolled_window; std::unique_ptr list_view_text; + std::unique_ptr search_entry; std::unique_ptr tooltips; int last_selected; +private: + bool popup; +}; + +class SelectionDialog : public SelectionDialogBase { +public: + SelectionDialog(Gtk::TextView& text_view); + void init() {SelectionDialogBase::init();} + void show(); + std::function on_select; +}; + +class CompletionDialog : public SelectionDialogBase { +public: + CompletionDialog(Gtk::TextView& text_view); + void init() {SelectionDialogBase::init();} + void show(); + bool on_key_release(GdkEventKey* key); + bool on_key_press(GdkEventKey* key); + +private: + void select(bool hide_window=true); + + int show_offset; + bool row_in_entry; }; #endif // JUCI_SELECTIONDIALOG_H_ \ No newline at end of file diff --git a/juci/singletons.cc b/juci/singletons.cc index eaa2909..d2c82f8 100644 --- a/juci/singletons.cc +++ b/juci/singletons.cc @@ -1,3 +1,24 @@ #include "singletons.h" -std::unique_ptr Singletons::Config::source_=std::unique_ptr(new Source::Config()); +std::unique_ptr Singleton::Config::source_=std::unique_ptr(new Source::Config()); +std::unique_ptr Singleton::Config::terminal_=std::unique_ptr(new Terminal::Config()); +std::unique_ptr Singleton::Config::directories_=std::unique_ptr(new Directories::Config()); + +std::unique_ptr Singleton::terminal_=std::unique_ptr(); +std::unique_ptr Singleton::notebook_=std::unique_ptr(); +std::unique_ptr Singleton::menu_=std::unique_ptr(); +Terminal::Controller *Singleton::terminal() { + if(!terminal_) + terminal_=std::unique_ptr(new Terminal::Controller()); + return terminal_.get(); +} +Notebook::Controller *Singleton::notebook() { + if(!notebook_) + notebook_=std::unique_ptr(new Notebook::Controller()); + return notebook_.get(); +} +Menu *Singleton::menu() { + if(!menu_) + menu_=std::unique_ptr(new Menu()); + return menu_.get(); +} \ No newline at end of file diff --git a/juci/singletons.h b/juci/singletons.h index 6098094..09cd50a 100644 --- a/juci/singletons.h +++ b/juci/singletons.h @@ -1,20 +1,32 @@ #ifndef JUCI_SINGLETONS_H_ #define JUCI_SINGLETONS_H_ -#include "keybindings.h" #include "source.h" #include "directories.h" #include "terminal.h" +#include "notebook.h" +#include "menu.h" -namespace Singletons { +class Singleton { +public: class Config { public: - static Source::Config *source() { - return source_.get(); - } + static Source::Config *source() {return source_.get();} + static Terminal::Config *terminal() {return terminal_.get();} + static Directories::Config *directories() {return directories_.get();} private: static std::unique_ptr source_; + static std::unique_ptr terminal_; + static std::unique_ptr directories_; }; -} + + static Terminal::Controller *terminal(); + static Notebook::Controller *notebook(); + static Menu *menu(); +private: + static std::unique_ptr terminal_; + static std::unique_ptr notebook_; + static std::unique_ptr menu_; +}; #endif // JUCI_SINGLETONS_H_ diff --git a/juci/source.cc b/juci/source.cc index 17e1378..d2c7804 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -8,6 +8,9 @@ #include #include "singletons.h" +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -27,23 +30,34 @@ bool Source::Config::legal_extension(std::string e) const { ////////////// Source::View::View(const std::string& file_path, const std::string& project_path): file_path(file_path), project_path(project_path) { - Gsv::init(); set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); - set_show_line_numbers(Singletons::Config::source()->show_line_numbers); - set_highlight_current_line(Singletons::Config::source()->highlight_current_line); + set_show_line_numbers(Singleton::Config::source()->show_line_numbers); + set_highlight_current_line(Singleton::Config::source()->highlight_current_line); sourcefile s(file_path); get_source_buffer()->get_undo_manager()->begin_not_undoable_action(); get_source_buffer()->set_text(s.get_content()); get_source_buffer()->get_undo_manager()->end_not_undoable_action(); search_start = search_end = this->get_buffer()->end(); - override_font(Pango::FontDescription(Singletons::Config::source()->font)); + override_font(Pango::FontDescription(Singleton::Config::source()->font)); - override_background_color(Gdk::RGBA(Singletons::Config::source()->background)); - override_background_color(Gdk::RGBA(Singletons::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); - for (auto &item : Singletons::Config::source()->tags) { + override_background_color(Gdk::RGBA(Singleton::Config::source()->background)); + override_background_color(Gdk::RGBA(Singleton::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); + for (auto &item : Singleton::Config::source()->tags) { get_source_buffer()->create_tag(item.first)->property_foreground() = item.second; } + + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); + signal_size_allocate().connect([this](Gtk::Allocation& allocation){ + if(!after_user_input) + scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); + }); + + signal_event().connect([this](GdkEvent* event){ + if(event->type==GDK_KEY_PRESS || event->type==GDK_BUTTON_PRESS || event->type==GDK_SCROLL) + after_user_input=true; + return false; + }); } string Source::View::get_line(size_t line_number) { @@ -64,10 +78,10 @@ string Source::View::get_line_before_insert() { //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { - auto config=Singletons::Config::source(); + auto config=Singleton::Config::source(); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); //Indent as in next or previous line - if(key->keyval==GDK_KEY_Return && key->state==0) { + if(key->keyval==GDK_KEY_Return && key->state==0 && !get_buffer()->get_has_selection()) { int line_nr=get_source_buffer()->get_insert()->get_iter().get_line(); string line(get_line_before_insert()); std::smatch sm; @@ -124,7 +138,7 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return true; } //"Smart" backspace key - else if(key->keyval==GDK_KEY_BackSpace) { + else if(key->keyval==GDK_KEY_BackSpace && !get_buffer()->get_has_selection()) { Gtk::TextIter insert_it=get_source_buffer()->get_insert()->get_iter(); int line_nr=insert_it.get_line(); if(line_nr>0) { @@ -142,17 +156,14 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return Gsv::View::on_key_press_event(key); } -////////////////// -//// ClangView /// -////////////////// -clang::Index Source::ClangView::clang_index(0, 0); +///////////////////////// +//// ClangViewParse /// +///////////////////////// +clang::Index Source::ClangViewParse::clang_index(0, 0); -Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): -Source::View(file_path, project_path), terminal(terminal), -parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { - similar_tokens_tag=get_buffer()->create_tag(); - similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; - +Source::ClangViewParse::ClangViewParse(const std::string& file_path, const std::string& project_path): +Source::View(file_path, project_path), +parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { int start_offset = get_source_buffer()->begin().get_offset(); int end_offset = get_source_buffer()->end().get_offset(); auto buffer_map=get_buffer_map(); @@ -185,7 +196,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go=true; }); - parsing_in_progress=this->terminal.print_in_progress("Parsing "+file_path); + parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); parse_done.connect([this](){ if(parse_thread_mapped) { if(parsing_mutex.try_lock()) { @@ -228,16 +239,12 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { start_reparse(); type_tooltips.hide(); diagnostic_tooltips.hide(); - if(last_similar_tokens_tagged!="") { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_tokens_tagged=""; - } }); - get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::on_mark_set), false); + get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } -Source::ClangView::~ClangView() { +Source::ClangViewParse::~ClangViewParse() { //TODO: Is it possible to stop the clang-process in progress? parsing_in_progress->cancel("canceled"); parse_thread_stop=true; @@ -247,7 +254,7 @@ Source::ClangView::~ClangView() { parsing_mutex.unlock(); } -void Source::ClangView:: +void Source::ClangViewParse:: init_syntax_highlighting(const std::map &buffers, int start_offset, @@ -260,13 +267,13 @@ init_syntax_highlighting(const std::map clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path)->second.size()-1); } -std::map Source::ClangView::get_buffer_map() const { +std::map Source::ClangViewParse::get_buffer_map() const { std::map buffer_map; buffer_map[file_path]=get_source_buffer()->get_text().raw(); return buffer_map; } -void Source::ClangView::start_reparse() { +void Source::ClangViewParse::start_reparse() { parse_thread_mapped=false; clang_readable=false; delayed_reparse_connection.disconnect(); @@ -276,14 +283,13 @@ void Source::ClangView::start_reparse() { }, 1000); } -int Source::ClangView::reparse(const std::map &buffer) { +int Source::ClangViewParse::reparse(const std::map &buffer) { int status = clang_tu->ReparseTranslationUnit(buffer); clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path)->second.size()-1); return status; } -std::vector Source::ClangView:: -get_compilation_commands() { +std::vector Source::ClangViewParse::get_compilation_commands() { clang::CompilationDatabase db(project_path); clang::CompileCommands commands(file_path, db); std::vector cmds = commands.get_commands(); @@ -299,20 +305,19 @@ get_compilation_commands() { return arguments; } -void Source::ClangView::update_syntax() { +void Source::ClangViewParse::update_syntax() { std::vector ranges; for (auto &token : *clang_tokens) { - auto range_data=token.source_range.get_range_data(); - if(token.kind()==0) // PunctuationToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, (int) token.get_cursor().get_kind()); - else if(token.kind()==1) // KeywordToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 702); - else if(token.kind()==2) // IdentifierToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, (int) token.get_cursor().get_kind()); - else if(token.kind()==3) // LiteralToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 109); - else if(token.kind()==4) // CommentToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 705); + if(token.get_kind()==0) // PunctuationToken + ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); + else if(token.get_kind()==1) // KeywordToken + ranges.emplace_back(token.offsets.first, token.offsets.second, 702); + else if(token.get_kind()==2) // IdentifierToken + ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); + else if(token.get_kind()==3) // LiteralToken + ranges.emplace_back(token.offsets.first, token.offsets.second, 109); + else if(token.get_kind()==4) // CommentToken + ranges.emplace_back(token.offsets.first, token.offsets.second, 705); } if (ranges.empty() || ranges.size() == 0) { return; @@ -322,25 +327,25 @@ void Source::ClangView::update_syntax() { for (auto &range : ranges) { std::string type = std::to_string(range.kind); try { - Singletons::Config::source()->types.at(type); + Singleton::Config::source()->types.at(type); } catch (std::exception) { continue; } Gtk::TextIter begin_iter = buffer->get_iter_at_offset(range.start_offset); Gtk::TextIter end_iter = buffer->get_iter_at_offset(range.end_offset); - buffer->apply_tag_by_name(Singletons::Config::source()->types.at(type), + buffer->apply_tag_by_name(Singleton::Config::source()->types.at(type), begin_iter, end_iter); } } -void Source::ClangView::update_diagnostics() { +void Source::ClangViewParse::update_diagnostics() { diagnostic_tooltips.clear(); auto diagnostics=clang_tu->get_diagnostics(); for(auto &diagnostic: diagnostics) { - if(diagnostic.range.path==file_path) { - auto start=get_buffer()->get_iter_at_offset(diagnostic.range.start_offset); - auto end=get_buffer()->get_iter_at_offset(diagnostic.range.end_offset); + if(diagnostic.path==file_path) { + auto start=get_buffer()->get_iter_at_offset(diagnostic.offsets.first); + auto end=get_buffer()->get_iter_at_offset(diagnostic.offsets.second); std::string diagnostic_tag_name; if(diagnostic.severity<=CXDiagnostic_Warning) diagnostic_tag_name="diagnostic_warning"; @@ -372,30 +377,27 @@ void Source::ClangView::update_diagnostics() { } } -void Source::ClangView::update_types() { +void Source::ClangViewParse::update_types() { type_tooltips.clear(); for(auto &token: *clang_tokens) { if(token.has_type()) { - auto range_data=token.source_range.get_range_data(); - if(range_data.path==file_path) { - auto start=get_buffer()->get_iter_at_offset(range_data.start_offset); - auto end=get_buffer()->get_iter_at_offset(range_data.end_offset); - auto get_tooltip_buffer=[this, &token]() { - auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); - tooltip_buffer->insert_at_cursor("Type: "+token.get_type()); - auto brief_comment=token.get_brief_comments(); - if(brief_comment!="") - tooltip_buffer->insert_at_cursor("\n\n"+brief_comment+"."); - return tooltip_buffer; - }; - - type_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); - } + auto start=get_buffer()->get_iter_at_offset(token.offsets.first); + auto end=get_buffer()->get_iter_at_offset(token.offsets.second); + auto get_tooltip_buffer=[this, &token]() { + auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); + tooltip_buffer->insert_at_cursor("Type: "+token.get_type()); + auto brief_comment=token.get_brief_comments(); + if(brief_comment!="") + tooltip_buffer->insert_at_cursor("\n\n"+brief_comment+"."); + return tooltip_buffer; + }; + + type_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); } } } -bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) { +bool Source::ClangViewParse::on_motion_notify_event(GdkEventMotion* event) { delayed_tooltips_connection.disconnect(); if(clang_readable) { Gdk::Rectangle rectangle(event->x, event->y, 1, 1); @@ -411,7 +413,7 @@ bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) { return Source::View::on_motion_notify_event(event); } -void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark) { +void Source::ClangViewParse::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark) { if(get_buffer()->get_has_selection() && mark->get_name()=="selection_bound") delayed_tooltips_connection.disconnect(); @@ -434,44 +436,17 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c }, 500); type_tooltips.hide(); diagnostic_tooltips.hide(); - - bool found=false; - if(clang_readable) { - for(auto &token: *clang_tokens) { - if(token.has_type()) { - auto range_data=token.source_range.get_range_data(); - auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); - if(range_data.path==file_path && insert_offset>=range_data.start_offset && insert_offset<=range_data.end_offset) { - found=true; - auto referenced_usr_and_token_spelling=token.get_cursor().get_referenced_usr()+token.get_token_spelling(); - if(last_similar_tokens_tagged!=referenced_usr_and_token_spelling) { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - auto offsets=clang_tokens->get_similar_token_offsets(token); - for(auto &offset: offsets) { - get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); - } - last_similar_tokens_tagged=referenced_usr_and_token_spelling; - break; - } - } - } - } - } - if(!found && last_similar_tokens_tagged!="") { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_tokens_tagged=""; - } } } -bool Source::ClangView::on_focus_out_event(GdkEventFocus* event) { +bool Source::ClangViewParse::on_focus_out_event(GdkEventFocus* event) { delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); return Source::View::on_focus_out_event(event); } -bool Source::ClangView::on_scroll_event(GdkEventScroll* event) { +bool Source::ClangViewParse::on_scroll_event(GdkEventScroll* event) { delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); @@ -480,8 +455,11 @@ bool Source::ClangView::on_scroll_event(GdkEventScroll* event) { //Clang indentation //TODO: replace indentation methods with a better implementation or maybe use libclang -bool Source::ClangView::on_key_press_event(GdkEventKey* key) { - auto config=Singletons::Config::source(); +bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { + if(get_buffer()->get_has_selection()) { + return Source::View::on_key_press_event(key); + } + auto config=Singleton::Config::source(); const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$"); const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); const std::regex no_bracket_no_para_statement_regex(std::string("^(")+config->tab_char+"*)(else|try|do) *$"); @@ -568,33 +546,33 @@ bool Source::ClangView::on_key_press_event(GdkEventKey* key) { ////////////////////////////// //// ClangViewAutocomplete /// ////////////////////////////// -Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): -Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { - selection_dialog.on_hide=[this](){ +Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): +Source::ClangViewParse(file_path, project_path), completion_dialog(*this), autocomplete_cancel_starting(false) { + completion_dialog.on_hide=[this](){ start_reparse(); }; get_buffer()->signal_changed().connect([this](){ - if(selection_dialog.shown) + if(completion_dialog.shown) delayed_reparse_connection.disconnect(); start_autocomplete(); }); get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ if(mark->get_name()=="insert") { autocomplete_cancel_starting=true; - if(selection_dialog.shown) { - selection_dialog.hide(); + if(completion_dialog.shown) { + completion_dialog.hide(); } } }); signal_scroll_event().connect([this](GdkEventScroll* event){ - if(selection_dialog.shown) - selection_dialog.hide(); + if(completion_dialog.shown) + completion_dialog.hide(); return false; }, false); signal_key_release_event().connect([this](GdkEventKey* key){ - if(selection_dialog.shown) { - if(selection_dialog.on_key_release(key)) + if(completion_dialog.shown) { + if(completion_dialog.on_key_release(key)) return true; } @@ -604,25 +582,25 @@ Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), a bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { last_keyval=key->keyval; - if(selection_dialog.shown) { - if(selection_dialog.on_key_press(key)) + if(completion_dialog.shown) { + if(completion_dialog.on_key_press(key)) return true; } - return ClangView::on_key_press_event(key); + return ClangViewParse::on_key_press_event(key); } bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { - if(selection_dialog.shown) { - selection_dialog.hide(); + if(completion_dialog.shown) { + completion_dialog.hide(); } - return Source::ClangView::on_focus_out_event(event); + return Source::ClangViewParse::on_focus_out_event(event); } void Source::ClangViewAutocomplete::start_autocomplete() { - const std::regex autocomplete_keys("[a-zA-Z0-9_>\\.:]"); - std::smatch sm; - if(!std::regex_match(std::string()+(char)last_keyval, sm, autocomplete_keys)) { + if(!((last_keyval>='0' && last_keyval<='9') || + (last_keyval>='a' && last_keyval<='z') || (last_keyval>='A' && last_keyval<='Z') || + last_keyval=='_' || last_keyval=='>' || last_keyval=='.' || last_keyval==':')) { autocomplete_cancel_starting=true; return; } @@ -630,11 +608,12 @@ void Source::ClangViewAutocomplete::start_autocomplete() { if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) { const std::regex in_specified_namespace("^(.*[a-zA-Z0-9_\\)])(->|\\.|::)([a-zA-Z0-9_]*)$"); const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); + std::smatch sm; if(std::regex_match(line, sm, in_specified_namespace)) { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { autocomplete(); } else if(last_keyval=='.' && autocomplete_starting) @@ -644,13 +623,13 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { autocomplete(); } } else autocomplete_cancel_starting=true; - if(autocomplete_starting || selection_dialog.shown) + if(autocomplete_starting || completion_dialog.shown) delayed_reparse_connection.disconnect(); } } @@ -665,14 +644,15 @@ void Source::ClangViewAutocomplete::autocomplete() { autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_starting=false; if(!autocomplete_cancel_starting) { - if(selection_dialog.start_mark) - get_buffer()->delete_mark(selection_dialog.start_mark); + if(completion_dialog.start_mark) + get_buffer()->delete_mark(completion_dialog.start_mark); auto start_iter=get_buffer()->get_insert()->get_iter(); for(size_t c=0;ccreate_mark(start_iter); + completion_dialog.start_mark=get_buffer()->create_mark(start_iter); std::map > rows; + completion_dialog.init(); for (auto &data : *ac_data) { std::stringstream ss; std::string return_value; @@ -689,13 +669,15 @@ void Source::ClangViewAutocomplete::autocomplete() { if (ss_str.length() > 0) { // if length is 0 the result is empty auto pair=std::pair(ss_str, data.brief_comments); rows[ss.str() + " --> " + return_value] = pair; + completion_dialog.append(ss.str() + " --> " + return_value); } } if (rows.empty()) { rows["No suggestions found..."] = std::pair(); + completion_dialog.append("No suggestions found..."); } - selection_dialog.rows=std::move(rows); - selection_dialog.show(); + completion_dialog.rows=std::move(rows); + completion_dialog.show(); } else start_autocomplete(); @@ -732,7 +714,7 @@ get_autocomplete_suggestions(int line_number, int column, std::mapcreate_tag(); + similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; + + get_buffer()->signal_changed().connect([this]() { + if(last_similar_tokens_tagged!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_tokens_tagged=""; + } + }); + + get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ + if(mark->get_name()=="insert") { + bool found=false; + if(clang_readable) { + for(auto &token: *clang_tokens) { + if(token.has_type()) { + auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); + if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { + found=true; + auto referenced=token.get_cursor().get_referenced(); + if(referenced) { + auto usr_and_spelling=referenced.get_usr()+token.get_spelling(); + if(last_similar_tokens_tagged!=usr_and_spelling) { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + auto offsets=clang_tokens->get_similar_token_offsets(token); + for(auto &offset: offsets) { + get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + } + last_similar_tokens_tagged=usr_and_spelling; + break; + } + } + } + } + } + } + if(!found && last_similar_tokens_tagged!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_tokens_tagged=""; + } + } + }); + + get_declaration_location=[this](){ + std::pair location; + if(clang_readable) { + for(auto &token: *clang_tokens) { + if(token.has_type()) { + auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); + if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { + auto referenced=token.get_cursor().get_referenced(); + if(referenced) { + location.first=referenced.get_source_location().get_path(); + location.second=referenced.get_source_location().get_offset(); + break; + } + } + } + } + } + return location; + }; + + goto_method=[this](){ + if(clang_readable) { + if(selection_dialog.start_mark) + get_buffer()->delete_mark(selection_dialog.start_mark); + selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); + std::map > rows; + selection_dialog.init(); + auto methods=clang_tokens->get_cxx_methods(); + if(methods.size()==0) + return; + for(auto &method: methods) { + rows[method.first]=std::pair(std::to_string(method.second), ""); + selection_dialog.append(method.first); + } + selection_dialog.rows=std::move(rows); + selection_dialog.on_select=[this](std::string selected) { + auto offset=stoul(selected); + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset)); + scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); + delayed_tooltips_connection.disconnect(); + }; + selection_dialog.show(); + } + }; +} + +//////////////// +//// Source //// +//////////////// -// Source::Controller::Controller() -// Constructor for Controller -Source::Controller::Controller(const std::string& file_path, std::string project_path, Terminal::Controller& terminal) { +Source::Source(const std::string& file_path, std::string project_path) { if(project_path=="") { project_path=boost::filesystem::path(file_path).parent_path().string(); } - if (Singletons::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) - view=std::unique_ptr(new ClangViewAutocomplete(file_path, project_path, terminal)); + if (Singleton::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) + view=std::unique_ptr(new ClangView(file_path, project_path)); else view=std::unique_ptr(new GenericView(file_path, project_path)); INFO("Source Controller with childs constructed"); } - -Glib::RefPtr Source::Controller::buffer() { - return view->get_source_buffer(); -} diff --git a/juci/source.h b/juci/source.h index 7a2a05a..6a2c75b 100644 --- a/juci/source.h +++ b/juci/source.h @@ -14,7 +14,8 @@ #include "tooltips.h" #include "selectiondialog.h" -namespace Source { +class Source { +public: class Config { public: bool legal_extension(std::string e) const ; @@ -51,6 +52,10 @@ namespace Source { std::string file_path; std::string project_path; Gtk::TextIter search_start, search_end; + + std::function()> get_declaration_location; + std::function goto_method; + bool after_user_input=false; protected: bool on_key_press_event(GdkEventKey* key); }; // class View @@ -59,25 +64,24 @@ namespace Source { public: GenericView(const std::string& file_path, const std::string& project_path): View(file_path, project_path) {} - protected: - bool on_key_press_event(GdkEventKey* key) { - return Source::View::on_key_press_event(key); - } }; - class ClangView : public View { + class ClangViewParse : public View { public: - ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); - ~ClangView(); + ClangViewParse(const std::string& file_path, const std::string& project_path); + ~ClangViewParse(); protected: void start_reparse(); bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); std::unique_ptr clang_tu; - std::map get_buffer_map() const; std::mutex parsing_mutex; + std::unique_ptr clang_tokens; + bool clang_readable=false; sigc::connection delayed_reparse_connection; + sigc::connection delayed_tooltips_connection; private: + std::map get_buffer_map() const; // inits the syntax highligthing on file open void init_syntax_highlighting(const std::map &buffers, @@ -91,16 +95,10 @@ namespace Source { Tooltips type_tooltips; bool on_motion_notify_event(GdkEventMotion* event); void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); - sigc::connection delayed_tooltips_connection; - Glib::RefPtr similar_tokens_tag; - std::string last_similar_tokens_tagged; bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; - std::unique_ptr clang_tokens; - bool clang_readable=false; std::vector get_compilation_commands(); - Terminal::Controller& terminal; std::shared_ptr parsing_in_progress; Glib::Dispatcher parse_done; @@ -112,17 +110,17 @@ namespace Source { std::atomic parse_thread_mapped; std::atomic parse_thread_stop; }; - - class ClangViewAutocomplete : public ClangView { + + class ClangViewAutocomplete : public ClangViewParse { public: - ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); + ClangViewAutocomplete(const std::string& file_path, const std::string& project_path); protected: bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); private: void start_autocomplete(); void autocomplete(); - SelectionDialog selection_dialog; + CompletionDialog completion_dialog; std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); Glib::Dispatcher autocomplete_done; sigc::connection autocomplete_done_connection; @@ -133,14 +131,23 @@ namespace Source { std::mutex prefix_mutex; }; - class Controller { + class ClangViewRefactor : public ClangViewAutocomplete { public: - Controller(const std::string& file_path, std::string project_path, Terminal::Controller& terminal); - Glib::RefPtr buffer(); - - bool is_saved = true; - - std::unique_ptr view; - }; // class Controller -} // namespace Source + ClangViewRefactor(const std::string& file_path, const std::string& project_path); + private: + Glib::RefPtr similar_tokens_tag; + std::string last_similar_tokens_tagged; + SelectionDialog selection_dialog; + }; + + class ClangView : public ClangViewRefactor { + public: + ClangView(const std::string& file_path, const std::string& project_path): + ClangViewRefactor(file_path, project_path) {} + }; + + Source(const std::string& file_path, std::string project_path); + + std::unique_ptr view; +}; // class Source #endif // JUCI_SOURCE_H_ diff --git a/juci/sourcefile.h b/juci/sourcefile.h index 608ea05..2afc263 100644 --- a/juci/sourcefile.h +++ b/juci/sourcefile.h @@ -4,20 +4,18 @@ #include #include -using namespace std; - class sourcefile { public: - explicit sourcefile(const string &filename); - vector get_lines(); - string get_content(); - string get_line(int line_number); - int save(const string &text); + explicit sourcefile(const std::string &filename); + std::vector get_lines(); + std::string get_content(); + std::string get_line(int line_number); + int save(const std::string &text); private: - void open(const string &filename); - vector lines; - string filename; + void open(const std::string &filename); + std::vector lines; + std::string filename; }; #endif // JUCI_SOURCEFILE_H_ diff --git a/juci/terminal.cc b/juci/terminal.cc index cce7496..1e25e92 100644 --- a/juci/terminal.cc +++ b/juci/terminal.cc @@ -1,10 +1,11 @@ #include "terminal.h" #include #include "logging.h" +#include "singletons.h" -Terminal::InProgress::InProgress(Controller& terminal, const std::string& start_msg): terminal(terminal), stop(false) { +Terminal::InProgress::InProgress(const std::string& start_msg): stop(false) { waiting_print.connect([this](){ - this->terminal.print(line_nr-1, "."); + Singleton::terminal()->print(line_nr-1, "."); }); start(start_msg); } @@ -16,7 +17,7 @@ Terminal::InProgress::~InProgress() { } void Terminal::InProgress::start(const std::string& msg) { - line_nr=this->terminal.print(msg+"...\n"); + line_nr=Singleton::terminal()->print(msg+"...\n"); wait_thread=std::thread([this](){ size_t c=0; while(!stop) { @@ -31,14 +32,14 @@ void Terminal::InProgress::start(const std::string& msg) { void Terminal::InProgress::done(const std::string& msg) { if(!stop) { stop=true; - this->terminal.print(line_nr-1, msg); + Singleton::terminal()->print(line_nr-1, msg); } } void Terminal::InProgress::cancel(const std::string& msg) { if(!stop) { stop=true; - this->terminal.print(line_nr-1, msg); + Singleton::terminal()->print(line_nr-1, msg); } } @@ -48,9 +49,13 @@ Terminal::View::View(){ add(scrolled_window); } -Terminal::Controller::Controller(Terminal::Config& cfg) : - config(cfg) { +Terminal::Controller::Controller() { folder_command_ = ""; + view.text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ + auto end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end()); + view.text_view.scroll_to(end); + view.text_view.get_buffer()->delete_mark(end); + }); } void Terminal::Controller::SetFolderCommand( boost::filesystem::path @@ -65,7 +70,7 @@ void Terminal::Controller::Compile(){ view.text_view.get_buffer()->set_text(""); DEBUG("Terminal: Compile: running cmake command"); - std::vector commands = config.compile_commands; + std::vector commands = Singleton::Config::terminal()->compile_commands; for (size_t it = 0; it < commands.size(); ++it) { ExecuteCommand(commands.at(it), "r"); @@ -79,16 +84,14 @@ void Terminal::Controller::Run(std::string executable) { print("juCi++ execute: " + executable + "\n"); DEBUG("Terminal: Compile: running run command: "); DEBUG_VAR(executable); - ExecuteCommand("cd "+config.run_command + "; ./"+executable, "r"); + ExecuteCommand("cd "+Singleton::Config::terminal()->run_command + "; ./"+executable, "r"); print("\n"); } int Terminal::Controller::print(std::string message){ INFO("Terminal: PrintMessage"); view.text_view.get_buffer()->insert(view.text_view.get_buffer()->end(), "> "+message); - auto mark_end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end()); - view.text_view.scroll_to(mark_end); - return mark_end->get_iter().get_line(); + return view.text_view.get_buffer()->end().get_line(); } void Terminal::Controller::print(int line_nr, std::string message){ @@ -100,7 +103,7 @@ void Terminal::Controller::print(int line_nr, std::string message){ } std::shared_ptr Terminal::Controller::print_in_progress(std::string start_msg) { - std::shared_ptr in_progress=std::shared_ptr(new Terminal::InProgress(*this, start_msg)); + std::shared_ptr in_progress=std::shared_ptr(new Terminal::InProgress(start_msg)); return in_progress; } diff --git a/juci/terminal.h b/juci/terminal.h index 317e43e..a5e779b 100644 --- a/juci/terminal.h +++ b/juci/terminal.h @@ -27,13 +27,12 @@ namespace Terminal { //Temporary solution for displaying functions in progress, and when they are done. class InProgress { public: - InProgress(Controller& terminal, const std::string& start_msg); + InProgress(const std::string& start_msg); ~InProgress(); void done(const std::string& msg); void cancel(const std::string& msg); private: void start(const std::string& msg); - Controller& terminal; int line_nr; std::atomic stop; Glib::Dispatcher waiting_print; @@ -42,7 +41,7 @@ namespace Terminal { class Controller { public: - Controller(Terminal::Config& cfg); + Controller(); void SetFolderCommand(boost::filesystem::path CMake_path); void Run(std::string executable); void Compile(); @@ -51,7 +50,6 @@ namespace Terminal { std::shared_ptr print_in_progress(std::string start_msg); Terminal::View view; private: - Terminal::Config& config; void ExecuteCommand(std::string command, std::string mode); bool OnButtonRealeaseEvent(GdkEventKey* key); bool ExistInConsole(std::string string); diff --git a/juci/tooltips.cc b/juci/tooltips.cc index 01d05f5..62b9476 100644 --- a/juci/tooltips.cc +++ b/juci/tooltips.cc @@ -46,7 +46,7 @@ void Tooltip::adjust(bool disregard_drawn) { tooltip_widget=std::unique_ptr(new Gtk::TextView(this->get_buffer())); tooltip_widget->set_editable(false); - tooltip_widget->override_background_color(Gdk::RGBA(Singletons::Config::source()->background_tooltips)); + tooltip_widget->override_background_color(Gdk::RGBA(Singleton::Config::source()->background_tooltips)); window->add(*tooltip_widget); auto layout=Pango::Layout::create(tooltip_widget->get_pango_context()); diff --git a/juci/window.cc b/juci/window.cc index e281538..cdf27d0 100644 --- a/juci/window.cc +++ b/juci/window.cc @@ -1,128 +1,86 @@ #include "window.h" #include "logging.h" +#include "singletons.h" Window::Window() : - window_box_(Gtk::ORIENTATION_VERTICAL), - main_config(), - keybindings(main_config.keybindings_cfg), - terminal(main_config.terminal_cfg), - notebook(keybindings, terminal, - main_config.dir_cfg), - menu(keybindings), - api(menu, notebook) { + window_box_(Gtk::ORIENTATION_VERTICAL) { INFO("Create Window"); set_title("juCi++"); set_default_size(600, 400); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK); add(window_box_); - keybindings.action_group_menu()->add(Gtk::Action::create("FileQuit", - "Quit juCi++"), - Gtk::AccelKey(keybindings.config_ - .key_map()["quit"]), - [this]() { - OnWindowHide(); - }); - keybindings.action_group_menu()->add(Gtk::Action::create("FileOpenFile", - "Open file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["open_file"]), - [this]() { - OnOpenFile(); - }); - keybindings.action_group_menu()->add(Gtk::Action::create("FileOpenFolder", - "Open folder"), - Gtk::AccelKey(keybindings.config_ - .key_map()["open_folder"]), - [this]() { - OnFileOpenFolder(); - }); - keybindings. - action_group_menu()-> - add(Gtk::Action::create("FileSaveAs", - "Save as"), - Gtk::AccelKey(keybindings.config_ - .key_map()["save_as"]), - [this]() { + auto menu=Singleton::menu(); + menu->action_group->add(Gtk::Action::create("FileQuit", "Quit juCi++"), Gtk::AccelKey(menu->key_map["quit"]), [this]() { + OnWindowHide(); + }); + menu->action_group->add(Gtk::Action::create("FileOpenFile", "Open file"), Gtk::AccelKey(menu->key_map["open_file"]), [this]() { + OnOpenFile(); + }); + menu->action_group->add(Gtk::Action::create("FileOpenFolder", "Open folder"), Gtk::AccelKey(menu->key_map["open_folder"]), [this]() { + OnFileOpenFolder(); + }); + menu->action_group->add(Gtk::Action::create("FileSaveAs", "Save as"), Gtk::AccelKey(menu->key_map["save_as"]), [this]() { SaveFileAs(); }); - keybindings. - action_group_menu()-> - add(Gtk::Action::create("FileSave", - "Save"), - Gtk::AccelKey(keybindings.config_ - .key_map()["save"]), - [this]() { + menu->action_group->add(Gtk::Action::create("FileSave", "Save"), Gtk::AccelKey(menu->key_map["save"]), [this]() { SaveFile(); }); - keybindings. - action_group_menu()-> - add(Gtk::Action::create("ProjectCompileAndRun", - "Compile And Run"), - Gtk::AccelKey(keybindings.config_ - .key_map()["compile_and_run"]), - [this]() { + menu->action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu->key_map["compile_and_run"]), [this]() { SaveFile(); if (running.try_lock()) { - std::thread execute([=]() { - std::string path = notebook.CurrentTextView().file_path; + std::thread execute([this]() { + std::string path = Singleton::notebook()->CurrentSourceView()->file_path; size_t pos = path.find_last_of("/\\"); if(pos != std::string::npos) { path.erase(path.begin()+pos,path.end()); - terminal.SetFolderCommand(path); + Singleton::terminal()->SetFolderCommand(path); } - terminal.Compile(); - std::string executable = notebook.directories. + Singleton::terminal()->Compile(); + std::string executable = Singleton::notebook()->directories. GetCmakeVarValue(path,"add_executable"); - terminal.Run(executable); + Singleton::terminal()->Run(executable); running.unlock(); }); execute.detach(); } }); - keybindings. - action_group_menu()-> - add(Gtk::Action::create("ProjectCompile", - "Compile"), - Gtk::AccelKey(keybindings.config_ - .key_map()["compile"]), - [this]() { - SaveFile(); - if (running.try_lock()) { - std::thread execute([=]() { - std::string path = notebook.CurrentTextView().file_path; - size_t pos = path.find_last_of("/\\"); - if(pos != std::string::npos){ - path.erase(path.begin()+pos,path.end()); - terminal.SetFolderCommand(path); - } - terminal.Compile(); - running.unlock(); - }); - execute.detach(); + menu->action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu->key_map["compile"]), [this]() { + SaveFile(); + if (running.try_lock()) { + std::thread execute([this]() { + std::string path = Singleton::notebook()->CurrentSourceView()->file_path; + size_t pos = path.find_last_of("/\\"); + if(pos != std::string::npos){ + path.erase(path.begin()+pos,path.end()); + Singleton::terminal()->SetFolderCommand(path); } + Singleton::terminal()->Compile(); + running.unlock(); }); + execute.detach(); + } + }); - add_accel_group(keybindings.ui_manager_menu()->get_accel_group()); - add_accel_group(keybindings.ui_manager_hidden()->get_accel_group()); - keybindings.BuildMenu(); + add_accel_group(menu->ui_manager->get_accel_group()); + menu->build(); - window_box_.pack_start(menu.view(), Gtk::PACK_SHRINK); + window_box_.pack_start(menu->get_widget(), Gtk::PACK_SHRINK); - window_box_.pack_start(notebook.entry, Gtk::PACK_SHRINK); + window_box_.pack_start(Singleton::notebook()->entry, Gtk::PACK_SHRINK); paned_.set_position(300); - paned_.pack1(notebook.view, true, false); - paned_.pack2(terminal.view, true, true); + paned_.pack1(Singleton::notebook()->view, true, false); + paned_.pack2(Singleton::terminal()->view, true, true); window_box_.pack_end(paned_); show_all_children(); INFO("Window created"); } // Window constructor void Window::OnWindowHide() { - for(size_t c=0;csource_views.size();c++) + Singleton::notebook()->OnCloseCurrentPage(); //TODO: This only works on one page at the momemt. Change to Singleton::notebook()->close_page(page_nr); hide(); } void Window::OnFileOpenFolder() { @@ -141,8 +99,8 @@ void Window::OnFileOpenFolder() { case(Gtk::RESPONSE_OK): { std::string project_path=dialog.get_filename(); - notebook.project_path=project_path; - notebook.directories.open_folder(project_path); + Singleton::notebook()->project_path=project_path; + Singleton::notebook()->directories.open_folder(project_path); break; } case(Gtk::RESPONSE_CANCEL): @@ -190,7 +148,7 @@ void Window::OnOpenFile() { switch (result) { case(Gtk::RESPONSE_OK): { std::string path = dialog.get_filename(); - notebook.OnOpenFile(path); + Singleton::notebook()->open_file(path); break; } case(Gtk::RESPONSE_CANCEL): { @@ -203,20 +161,19 @@ void Window::OnOpenFile() { } bool Window::SaveFile() { - if(notebook.OnSaveFile()) { - terminal.print("File saved to: " + - notebook.CurrentTextView().file_path+"\n"); + if(Singleton::notebook()->OnSaveFile()) { + Singleton::terminal()->print("File saved to: " + + Singleton::notebook()->CurrentSourceView()->file_path+"\n"); return true; } - terminal.print("File not saved"); return false; } bool Window::SaveFileAs() { - if(notebook.OnSaveFile(notebook.OnSaveFileAs())){ - terminal.print("File saved to: " + - notebook.CurrentTextView().file_path+"\n"); + if(Singleton::notebook()->OnSaveFile(Singleton::notebook()->OnSaveFileAs())){ + Singleton::terminal()->print("File saved to: " + + Singleton::notebook()->CurrentSourceView()->file_path+"\n"); return true; } - terminal.print("File not saved"); + Singleton::terminal()->print("File not saved"); return false; } diff --git a/juci/window.h b/juci/window.h index 782029a..2dce670 100644 --- a/juci/window.h +++ b/juci/window.h @@ -3,7 +3,6 @@ #include "api.h" #include "config.h" -#include "terminal.h" #include @@ -15,10 +14,6 @@ public: virtual ~Window() { } MainConfig main_config; - Keybindings::Controller keybindings; - Menu::Controller menu; - Notebook::Controller notebook; - Terminal::Controller terminal; PluginApi api; private: