From 5d2127e6131b441ee07c761ab8794243b11a095b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 19 Sep 2015 05:18:15 +0800 Subject: [PATCH] improve dockpane factory --- include/nana/gui/place.hpp | 7 ++-- source/gui/place.cpp | 73 +++++++++++++++++++++++++++++++++----- source/gui/place_parts.hpp | 65 ++++++++++++++++++++------------- 3 files changed, 109 insertions(+), 36 deletions(-) diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index bd50bee7..2e3676de 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -127,15 +127,16 @@ namespace nana /// Add a panel factory template - void dock(const std::string& dockname, Args&& ... args) + place& dock(const std::string& dockname, const std::string& factory_name, Args&& ... args) { - dock(dockname, std::bind([](window parent, Args & ... args) + return dock(dockname, factory_name, std::bind([](window parent, Args & ... args) { return std::unique_ptr(new Panel(parent, std::forward(args)...)); }, std::placeholders::_1, args...)); } - void dock(const std::string& dockname, std::function(window)> factory); + place& dock(const std::string& dockname, std::string factory_name, std::function(window)> factory); + place& dock_create(const std::string& factory); private: implement * impl_; }; diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 6e82a599..ce0351c3 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -450,6 +450,7 @@ namespace nana std::unique_ptr root_division; std::map fields; std::map docks; + std::map dock_factoris; //A temporary pointer used to refer to a specified div object which //will be deleted in modification process. @@ -597,8 +598,9 @@ namespace nana { public: - div_dockpane * attached{ nullptr }; //attached div object - place_parts::dockarea dockarea; //the dockable widget + div_dockpane * attached{ nullptr }; //attached div object + std::unique_ptr dockarea; //the dockable widget + std::map(window)>> factories; //factories for dockpane };//end class field_dock @@ -1559,13 +1561,14 @@ namespace nana impl_ptr_{impl} { dir = pane_dir; + this->display = false; } ~div_dockpane() { if (dockable_field) { - dockable_field->dockarea.close(); + dockable_field->dockarea.reset(); dockable_field->attached = nullptr; } } @@ -1586,6 +1589,8 @@ namespace nana } auto & dockarea = dockable_field->dockarea; + + /* if (!created_) { created_ = true; @@ -1594,6 +1599,10 @@ namespace nana if (!dockarea.empty() && !dockarea.floating()) dockarea.move(this->field_area); + */ + + if (dockarea && !dockarea->floating()) + dockarea->move(this->field_area); } private: //Implement dock_notifier_interface @@ -1710,8 +1719,8 @@ namespace nana void notify_move_stopped() { - if (_m_dockable() && dockable_field) - dockable_field->dockarea.dock(); + if (_m_dockable() && dockable_field && dockable_field->dockarea) + dockable_field->dockarea->dock(); indicator_.docker.reset(); } @@ -2514,7 +2523,7 @@ namespace nana for (auto& e : docks_to_be_closed) { - e.second->dockarea.close(); + e.second->dockarea.reset(); e.second->attached->dockable_field = nullptr; e.second->attached = nullptr; } @@ -2747,7 +2756,7 @@ namespace nana return field(name); } - void place::dock(const std::string& name, std::function(window)> factory) + place& place::dock(const std::string& name, std::string factory_name, std::function(window)> factory) { //check the name, it throws std::invalid_argument //if name violate the naming convention. @@ -2757,7 +2766,16 @@ namespace nana if (!dock_ptr) dock_ptr = new implement::field_dock; - dock_ptr->dockarea.add_factory(std::move(factory)); + //Register the factory if it has a name + if (!factory_name.empty()) + { + auto i = impl_->dock_factoris.find(factory_name); + if (i != impl_->dock_factoris.end()) + throw std::invalid_argument("nana::place - the specified factory name(" + factory_name + ") already exists"); + + impl_->dock_factoris[factory_name] = dock_ptr; + dock_ptr->factories[factory_name].swap(factory); + } auto div = dynamic_cast(impl_->search_div_name(impl_->root_division.get(), name)); if (div) @@ -2765,6 +2783,45 @@ namespace nana dock_ptr->attached = div; div->dockable_field = dock_ptr; } + + //Create the pane if it has not a name + if (factory_name.empty()) + { + dock_ptr->attached->set_display(true); + impl_->collocate(); + + if (!dock_ptr->dockarea) + { + dock_ptr->dockarea.reset(new ::nana::place_parts::dockarea); + dock_ptr->dockarea->create(impl_->window_handle, dock_ptr->attached); + dock_ptr->dockarea->move(dock_ptr->attached->field_area); + } + dock_ptr->dockarea->add_pane(factory); + } + + return *this; + } + + place& place::dock_create(const std::string& factory) + { + auto i = impl_->dock_factoris.find(factory); + if (i == impl_->dock_factoris.end()) + throw std::invalid_argument("nana::place - invalid factory name(" + factory + ")"); + + auto dock_ptr = i->second; + dock_ptr->attached->set_display(true); + impl_->collocate(); + + if (!dock_ptr->dockarea) + { + dock_ptr->dockarea.reset(new ::nana::place_parts::dockarea); + dock_ptr->dockarea->create(impl_->window_handle, dock_ptr->attached); + dock_ptr->dockarea->move(dock_ptr->attached->field_area); + } + + dock_ptr->dockarea->add_pane(i->second->factories[factory]); + + return *this; } //end class place }//end namespace nana diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 914dc405..621b93aa 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -148,12 +148,7 @@ namespace nana struct panel { - factory factory_fn; std::unique_ptr widget_ptr; - - panel(factory && fn) - : factory_fn(std::move(fn)) - {} }; public: void create(window parent, place_parts::dock_notifier_interface* notifier) @@ -229,29 +224,49 @@ namespace nana } }); - if (panels_.size() > 1) - tabbar_.reset(new tabbar_lite(*this)); - - std::size_t pos = 0; - for (auto & pn : panels_) - { - if (!pn.widget_ptr) - { - pn.widget_ptr = pn.factory_fn(*this); - if (tabbar_) - { - tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); - tabbar_->attach(pos++, pn.widget_ptr->handle()); - //tabbar_->push_back(pn.widget_ptr->caption()); - //tabbar_->relate(pos++, pn.widget_ptr->handle()); - } - } - } } - void add_factory(factory && fn) + void add_pane(factory & fn) { - panels_.emplace_back(std::move(fn)); + rectangle r{ point(), this->size()}; + + //get a rectangle excluding caption + r.y = 20; + if (r.height > 20) + r.height -= 20; + else + r.height = 0; + + if (!tabbar_ && panels_.size() > 0) + { + tabbar_.reset(new tabbar_lite(*this)); + tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); + r.height -= 20; + + std::size_t pos = 0; + for (auto & pn : panels_) + { + tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); + tabbar_->attach(pos++, *pn.widget_ptr); + } + } + + auto wdg = fn(*this); + + if (tabbar_) + { + tabbar_->push_back(::nana::charset(wdg->caption())); + tabbar_->attach(panels_.size(), *wdg); + } + + panels_.emplace_back(); + panels_.back().widget_ptr.swap(wdg); + + for (auto & pn : panels_) + { + if (pn.widget_ptr) + pn.widget_ptr->move(r); + } } void float_away(const ::nana::point& move_pos)