diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index c7d20ad1..d84dc158 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -168,7 +168,7 @@ namespace nana void insert(std::size_t, native_string_type&&, nana::any&&); std::size_t length() const; bool close_fly(bool); - void attach(std::size_t, window); + window attach(std::size_t, window, bool drop_other); 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&); @@ -306,12 +306,19 @@ namespace nana API::update_window(*this); } - void attach(std::size_t pos, window attach_wd) + /// Attach a window to a specified tab. When the tab is activated, tabbar shows the attached window. + /** + * @param pos The position of tab to set the attached window. + * @param attach_wd A handle to the window to be set. + * @param drop_other Drop the attached windows of other tabs whose attach windows are equal to the parameter attach_wd. If drop_other is true, the other tabs attached windows equal to attach_wd will be dropped. + * @return A handle to the last attached window of specified tab. + */ + window attach(std::size_t pos, window attach_wd, bool drop_other = true) { if (attach_wd && API::empty_window(attach_wd)) throw std::invalid_argument("tabbar.attach: invalid window handle"); - this->get_drawer_trigger().attach(pos, attach_wd); + return this->get_drawer_trigger().attach(pos, attach_wd, drop_other); } void erase(std::size_t pos) diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 9e1c05e0..d16b6451 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -585,9 +585,17 @@ namespace nana { if(pos < list_.size() && (pos != basis_.active)) { - API::show_window(iterator_at(pos)->relative, true); - if(basis_.active < list_.size()) - API::show_window(iterator_at(basis_.active)->relative, false); + auto & tab_act = *iterator_at(pos); + API::show_window(tab_act.relative, true); + if (basis_.active < list_.size()) + { + auto & tab_deact = *iterator_at(basis_.active); + + //Don't hide the relative window if it is equal to active relative window. + //The tabbar allows a window to be attached to multiple tabs(pass false to DropOther of attach method) + if (tab_deact.relative != tab_act.relative) + API::show_window(tab_deact.relative, false); + } basis_.active = pos; track(); @@ -603,13 +611,27 @@ namespace nana return basis_.active; } - void attach(std::size_t pos, window wd) + window attach(std::size_t pos, window wd, bool drop_other) { if (pos >= list_.size()) throw std::out_of_range("tabbar: invalid position"); - iterator_at(pos)->relative = wd; + auto & tab = *iterator_at(pos); + auto old = tab.relative; + + if (drop_other) + { + //Drop the relative windows which are equal to wd. + for (auto & t : list_) + { + if (wd == t.relative) + t.relative = nullptr; + } + } + + tab.relative = wd; API::show_window(wd, basis_.active == pos); + return old; } bool tab_color(std::size_t pos, bool is_bgcolor, const ::nana::color& clr) @@ -1181,9 +1203,9 @@ namespace nana return layouter_->toolbox_object().close_fly(fly); } - void trigger::attach(std::size_t pos, window wd) + window trigger::attach(std::size_t pos, window wd, bool drop_other) { - layouter_->attach(pos, wd); + return layouter_->attach(pos, wd, drop_other); } void trigger::erase(std::size_t pos)