diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 2ed73ab4..2b7193cf 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -40,7 +40,9 @@ namespace nana : arg_tabbar({wdg, v}) {} - bool remove = true; + bool remove = true; ///< determines whether to remove the item + bool close_attach_window = true; ///< determines whether to close the attached window. It is ignored if remove is false + }; namespace drawerbase @@ -51,11 +53,11 @@ namespace nana struct tabbar_events : public general_events { - typedef T value_type; + using value_type = T; basic_event> added; basic_event> activated; - basic_event> removed; + basic_event> removed; }; class event_agent_interface @@ -64,7 +66,7 @@ namespace nana virtual ~event_agent_interface() = default; virtual void added(std::size_t) = 0; virtual void activated(std::size_t) = 0; - virtual bool removed(std::size_t) = 0; + virtual bool removed(std::size_t, bool & close_attached) = 0; }; class item_renderer @@ -98,7 +100,7 @@ namespace nana : public event_agent_interface { public: - typedef ::nana::arg_tabbar arg_tabbar; + using arg_tabbar = ::nana::arg_tabbar; event_agent(::nana::tabbar& tb, DrawerTrigger & dtr) : tabbar_(tb), drawer_trigger_(dtr) @@ -119,14 +121,16 @@ namespace nana tabbar_.events().activated.emit(arg_tabbar({ tabbar_, tabbar_[pos]})); } - bool removed(std::size_t pos) override + bool removed(std::size_t pos, bool & close_attach) override { if (pos != npos) { ::nana::arg_tabbar_removed arg(tabbar_, tabbar_[pos]); tabbar_.events().removed.emit(arg); + close_attach = arg.close_attach_window; return arg.remove; } + close_attach = true; return true; } private: @@ -140,8 +144,6 @@ namespace nana : public drawer_trigger { public: - //enum toolbox_button_t{ButtonAdd, ButtonScroll, ButtonList, ButtonClose}; //deprecated - enum class kits { add, @@ -159,10 +161,11 @@ namespace nana const pat::cloneable & ext_renderer() const; void ext_renderer(const pat::cloneable&); void set_event_agent(event_agent_interface*); - void push_back(const nana::string&, const nana::any&); + void insert(std::size_t, nana::string&&, nana::any&&); std::size_t length() const; bool close_fly(bool); - void relate(size_t, window); + void attach(std::size_t, window); + void erase(std::size_t); void tab_color(std::size_t, bool is_bgcolor, const ::nana::color&); void tab_image(size_t, const nana::paint::image&); void text(std::size_t, const nana::string&); @@ -198,7 +201,7 @@ namespace nana struct button_close{}; ///< The type identifies the close button of the tabbar's toolbox. //This template class is deprecated, it will be removed in 1.3 - /// A template class identifies the buttons of the tabbar's toolbox. Refer to notes for more details. + /// A template class identifies the buttons of the tabbar's toolbox. Refer to notes for more details. template struct button_container { @@ -270,7 +273,7 @@ namespace nana void close_fly(bool fly) /// Draw or not a close button in each tab. { - if(this->get_drawer_trigger().close_fly(fly)) + if (this->get_drawer_trigger().close_fly(fly)) API::refresh_window(this->handle()); } @@ -289,16 +292,57 @@ namespace nana return this->get_drawer_trigger().length(); } - void push_back(const nana::string& text) /// Append a new item. + void append(const std::string& text, window attach_wd, value_type value = {}) { - auto & t = this->get_drawer_trigger(); - t.push_back(text, value_type()); + this->append(static_cast(nana::charset(text, nana::unicode::utf8)), attach_wd); + } + + void append(const std::wstring& text, window attach_wd, value_type value = {}) + { + this->get_drawer_trigger().insert(::nana::npos, std::wstring(text), std::move(value)); + if (attach_wd) + { + auto pos = this->get_drawer_trigger().length(); + relate(pos, attach_wd); + } + API::update_window(*this); } + void push_back(nana::string text) /// Append a new item. + { + this->get_drawer_trigger().insert(::nana::npos, std::move(text), value_type()); + API::update_window(*this); + } + + void insert(std::size_t pos, const std::string& text, const value_type& value = {}) + { + this->insert(pos, static_cast(nana::charset(text, nana::unicode::utf8)), value); + } + + void insert(std::size_t pos, const std::wstring& text, const value_type& value = {}) + { + if (pos > length()) + throw std::out_of_range("tabbar::insert invalid position"); + + this->get_drawer_trigger().insert(pos, std::wstring(text), value_type(value)); + API::update_window(*this); + } + + //deprecated from 1.2.1, removed from 1.3 void relate(std::size_t pos, window wd) /// Binds a window to an item specified by pos, if the item is selected, shows the window, otherwise, hides it. { - this->get_drawer_trigger().relate(pos, wd); + this->get_drawer_trigger().attach(pos, wd); + } + + void attach(std::size_t pos, window wd) + { + this->get_drawer_trigger().attach(pos, wd); + } + + void erase(std::size_t pos) + { + this->get_drawer_trigger().erase(pos); } void tab_bgcolor(std::size_t i, const ::nana::color& clr) diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index c0acd9f3..d2a8cb2a 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -30,6 +30,12 @@ namespace nana ::nana::color bgcolor; ::nana::color fgcolor; + + item_t() = default; + + item_t(nana::string&& text, any && value) + : text(std::move(text)), value(std::move(value)) + {} }; class def_renderer @@ -414,13 +420,13 @@ namespace nana evt_agent_ = evt; } - void push_back(const nana::string& text, const nana::any & value) + void insert(std::size_t pos, nana::string&& text, nana::any&& value) { - item_t m; - m.text = text; - m.value = value; - list_.push_back(m); - activate(static_cast(list_.size() - 1)); + if (pos >= list_.size()) + pos = list_.size(); + + list_.emplace(iterator_at(pos), std::move(text), std::move(value)); + this->activate(pos); render(); } @@ -433,9 +439,13 @@ namespace nana { if(pos < list_.size()) { - if ((nullptr == evt_agent_) || evt_agent_->removed(pos)) + bool close_attach = true; + if ((nullptr == evt_agent_) || evt_agent_->removed(pos, close_attach)) { - API::show_window(iterator_at(pos)->relative, false); + if (close_attach) + API::close_window(iterator_at(pos)->relative); + else + API::show_window(iterator_at(pos)->relative, false); list_.erase(iterator_at(pos)); _m_adjust(); @@ -593,7 +603,7 @@ namespace nana return basis_.active; } - void relate(std::size_t pos, window wd) + void attach(std::size_t pos, window wd) { if(pos < list_.size()) { @@ -1152,9 +1162,9 @@ namespace nana layouter_->event_agent(evt); } - void trigger::push_back(const nana::string& text, const nana::any& value) + void trigger::insert(std::size_t pos, nana::string&& text, nana::any&& value) { - layouter_->push_back(text, value); + layouter_->insert(pos, std::move(text), std::move(value)); } std::size_t trigger::length() const @@ -1167,9 +1177,14 @@ namespace nana return layouter_->toolbox_object().close_fly(fly); } - void trigger::relate(std::size_t i, window wd) + void trigger::attach(std::size_t pos, window wd) { - layouter_->relate(i, wd); + layouter_->attach(pos, wd); + } + + void trigger::erase(std::size_t pos) + { + layouter_->erase(pos); } void trigger::tab_color(std::size_t i, bool is_bgcolor, const ::nana::color& clr)