From 658ab3fb7fc572231763aa3440beb67d5c600270 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 14 Aug 2015 04:09:35 +0800 Subject: [PATCH 01/22] new docker-place branch --- include/nana/gui/element.hpp | 101 +- include/nana/gui/place.hpp | 16 +- include/nana/gui/programming_interface.hpp | 2 +- source/gui/dragger.cpp | 2 +- source/gui/element.cpp | 250 +++- source/gui/place.cpp | 1326 +++++++++++++------- source/gui/programming_interface.cpp | 4 +- source/gui/widgets/widget.cpp | 2 +- 8 files changed, 1210 insertions(+), 493 deletions(-) diff --git a/include/nana/gui/element.hpp b/include/nana/gui/element.hpp index ee63ecf0..9ffa721d 100644 --- a/include/nana/gui/element.hpp +++ b/include/nana/gui/element.hpp @@ -98,25 +98,31 @@ namespace nana } }; - void add_crook(const std::string& name, const pat::cloneable>&); - crook_interface* const * keeper_crook(const std::string& name); + void add_arrow(const std::string&, const pat::cloneable>&); + arrow_interface* const * cite_arrow(const std::string&); void add_border(const std::string&, const pat::cloneable>&); - border_interface* const * keeper_border(const std::string&); - - void add_arrow(const std::string&, const pat::cloneable>&); - arrow_interface* const * keeper_arrow(const std::string&); + border_interface* const * cite_border(const std::string&); void add_button(const std::string&, const pat::cloneable>&); - element_interface* const* keeper_button(const std::string&); + element_interface* const* cite_button(const std::string&); + + void add_x_icon(const std::string& name, const pat::cloneable>&); + element_interface* const* cite_x_icon(const std::string&); + + void add_crook(const std::string& name, const pat::cloneable>&); + crook_interface* const * cite_crook(const std::string& name); + + void add_cross(const std::string& name, const pat::cloneable>&); + element_interface* const* cite_cross(const std::string&); }; - class crook; - template - void add_crook(const std::string& name) + class arrow; + template + void add_arrow(const std::string& name) { - using factory_t = provider::factory; - provider().add_crook(name, pat::cloneable(factory_t())); + using factory_t = provider::factory; + provider().add_arrow(name, pat::cloneable(factory_t())); } class border; @@ -127,14 +133,6 @@ namespace nana provider().add_border(name, pat::cloneable(factory_t())); } - class arrow; - template - void add_arrow(const std::string& name) - { - using factory_t = provider::factory; - provider().add_arrow(name, pat::cloneable(factory_t())); - } - class button; template void add_button(const std::string& name) @@ -142,6 +140,30 @@ namespace nana using factory_t = provider::factory; provider().add_button(name, pat::cloneable(factory_t())); } + + class x_icon; + template + void add_x_icon(const std::string& name) + { + using factory_t = provider::factory; + provider().add_x_icon(name, pat::cloneable(factory_t())); + } + + class crook; + template + void add_crook(const std::string& name) + { + using factory_t = provider::factory; + provider().add_crook(name, pat::cloneable(factory_t())); + } + + class cross; + template + void add_cross(const std::string& name) + { + using factory_t = provider::factory; + provider().add_cross(name, pat::cloneable(factory_t())); + } }//end namespace element template class facade; @@ -169,9 +191,27 @@ namespace nana bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state) override; private: element::crook_interface::data data_; - element::crook_interface* const * keeper_; + element::crook_interface* const * cite_; }; //end class facade + template<> class facade + : public element::element_interface + { + public: + facade(const char* name = nullptr); + void switch_to(const char*); + + void thickness(unsigned thk); + void size(unsigned size_pixels); + public: + //Implement element_interface + bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; + private: + unsigned thickness_{6}; + unsigned size_{ 14 }; + element::element_interface* const * cite_; + }; + template<> class facade : public element::element_interface @@ -185,7 +225,7 @@ namespace nana //Implement element_interface bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) override; private: - element::border_interface* const * keeper_; + element::border_interface* const * cite_; };//end class facade template<> @@ -207,7 +247,7 @@ namespace nana //Implement element_interface bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) override; private: - element::arrow_interface* const * keeper_; + element::arrow_interface* const * cite_; ::nana::direction dir_{::nana::direction::north}; };//end class facade @@ -222,9 +262,22 @@ namespace nana //Implement element_interface bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; private: - element::element_interface* const * keeper_; + element::element_interface* const * cite_; };//end class facade + template<> + class facade + : public element::element_interface + { + public: + facade(const char* name = nullptr); + void switch_to(const char*); + public: + //Implement element_interface + bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state) override; + private: + element::element_interface* const * cite_; + };//end class facade namespace element { diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index a7e7e0ea..8faedf91 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -109,9 +109,11 @@ namespace nana window window_handle() const; void div(const char* s); ///< Divides the attached widget into fields. + void modify(const char* field_name, const char* div_text); ///< Modifies a specified field. + field_reference field(const char* name);///< Returns a field with the specified name. - void field_visible(const char* filed_name, bool visible); ///< + void dock(const std::string& dockname, Args&& ... args) + { + dock(dockname, std::bind([](window parent, Args && ... args) + { + return std::unique_ptr(new Panel(parent, std::forward(args)...)); + }, std::placeholders::_1, std::forward(args)...)); + } + + void dock(const std::string& dockname, std::function(window)> factory); private: implement * impl_; }; diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 167fd8d8..bfbcd138 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -191,7 +191,7 @@ namespace API } point window_position(window); - void move_window(window, int x, int y); + void move_window(window, const point&); void move_window(window wd, const rectangle&); void bring_top(window, bool activated); diff --git a/source/gui/dragger.cpp b/source/gui/dragger.cpp index dac2c6c8..5bb82baf 100644 --- a/source/gui/dragger.cpp +++ b/source/gui/dragger.cpp @@ -164,7 +164,7 @@ namespace nana if (!t.restrict_area.empty()) _m_check_restrict_area(wdps, API::window_size(t.wd), t.restrict_area); - API::move_window(t.wd, wdps.x, wdps.y); + API::move_window(t.wd, wdps); } } } diff --git a/source/gui/element.cpp b/source/gui/element.cpp index 1852a554..cbccebed 100644 --- a/source/gui/element.cpp +++ b/source/gui/element.cpp @@ -141,7 +141,7 @@ namespace nana } else { - ::nana::color highlighted(static_cast(0x5eb6f7)); + ::nana::color highlighted(0x5e, 0xb6, 0xf7); auto bld_bgcolor = bgcolor; auto bld_fgcolor = fgcolor; switch(es) @@ -156,7 +156,7 @@ namespace nana bld_fgcolor = fgcolor.blend(highlighted, 0.4); break; case element_state::disabled: - bld_bgcolor = bld_fgcolor.from_rgb(0xb2, 0xb7, 0xbc); + bld_bgcolor = bld_fgcolor = nana::color(0xb2, 0xb7, 0xbc); break; default: //Leave things as they are @@ -264,7 +264,7 @@ namespace nana bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, unsigned weight) { graph.rectangle(r, false, static_cast((element_state::focus_hovered == estate || element_state::focus_normal == estate) ? 0x0595E2 : 0x999A9E)); - graph.rectangle(::nana::rectangle(r).pare_off(1), false, bgcolor); + graph.rectangle(::nana::rectangle{r}.pare_off(1), false, bgcolor); return true; } }; @@ -529,6 +529,63 @@ namespace nana return true; } };//end class annex_button + + class x_icon + : public element_interface + { + bool draw(graph_reference graph, const ::nana::color&, const ::nana::color& fgcolor, const rectangle& r, element_state estate) override + { + auto clr = fgcolor; + + switch (estate) + { + case element_state::hovered: + case element_state::pressed: + clr = clr.blend(colors::black, 0.8); + break; + case element_state::disabled: + clr = colors::dark_gray; + default: + break; + } + + graph.set_color(clr); + + const int x = r.x + 4; + const int y = r.y + 4; + + point p1{ x, y }, p2{ x + 7, y + 7 }; + + graph.line(p1, p2); + + ++p1.x; + --p2.y; + graph.line(p1, p2); + + p1.x = x; + ++p1.y; + p2.x = x + 6; + p2.y = y + 7; + graph.line(p1, p2); + + p1.x += 7; + p1.y = y; + p2.x = x; + graph.line(p1, p2); + + p1.x = x + 6; + p2.y = y + 6; + graph.line(p1, p2); + + ++p1.x; + ++p1.y; + ++p2.x; + ++p2.y; + graph.line(p1, p2); + + return true; + } + }; }//end namespace element template @@ -567,7 +624,7 @@ namespace nana spare_.emplace_back(keep_e, keep_f); } - element_t * const * keeper() const + element_t * const * cite() const { return &element_ptr_; } @@ -580,6 +637,9 @@ namespace nana class element_manager : nana::noncopyable, nana::nonmovable { + //VC2012 does not support alias declaration. + //template using factory_interface = element::provider::factory_interface; + template struct item { @@ -613,6 +673,8 @@ namespace nana element::add_arrow("hollow_triangle"); element::add_button(""); //"annex" in default + + element::add_x_icon(""); } return obj; } @@ -624,7 +686,17 @@ namespace nana element::crook_interface * const * crook(const std::string& name) const { - return _m_get(name, crook_).keeper(); + return _m_get(name, crook_).cite(); + } + + void cross(const std::string& name, const pat::cloneable>& factory) + { + _m_add(name, cross_, factory); + } + + element::element_interface* const * cross(const std::string& name) const + { + return _m_get(name, cross_).cite(); } void border(const std::string& name, const pat::cloneable>& factory) @@ -634,7 +706,7 @@ namespace nana element::border_interface * const * border(const std::string& name) const { - return _m_get(name, border_).keeper(); + return _m_get(name, border_).cite(); } void arrow(const std::string& name, const pat::cloneable>& factory) @@ -644,7 +716,7 @@ namespace nana element::arrow_interface * const * arrow(const std::string& name) const { - return _m_get((name.empty() ? "arrowhead" : name), arrow_).keeper(); + return _m_get((name.empty() ? "arrowhead" : name), arrow_).cite(); } void button(const std::string& name, const pat::cloneable>& factory) @@ -654,7 +726,17 @@ namespace nana element::element_interface * const * button(const std::string& name) const { - return _m_get((name.empty() ? "annex" : name), button_).keeper(); + return _m_get((name.empty() ? "annex" : name), button_).cite(); + } + + void x_icon(const std::string& name, const pat::cloneable>& factory) + { + _m_add(name, x_icon_, factory); + } + + element::element_interface * const * x_icon(const std::string& name) const + { + return _m_get(name, x_icon_).cite(); } private: using lock_guard = std::lock_guard; @@ -689,9 +771,11 @@ namespace nana private: mutable std::recursive_mutex mutex_; item crook_; + item cross_; item border_; item arrow_; item button_; + item x_icon_; }; namespace element @@ -702,17 +786,27 @@ namespace nana element_manager::instance().crook(name, factory); } - crook_interface* const * provider::keeper_crook(const std::string& name) + crook_interface* const * provider::cite_crook(const std::string& name) { return element_manager::instance().crook(name); } + void provider::add_cross(const std::string& name, const pat::cloneable>& factory) + { + element_manager::instance().cross(name, factory); + } + + element_interface* const* provider::cite_cross(const std::string& name) + { + return element_manager::instance().cross(name); + } + void provider::add_border(const std::string& name, const pat::cloneable>& factory) { element_manager::instance().border(name, factory); } - border_interface* const * provider::keeper_border(const std::string& name) + border_interface* const * provider::cite_border(const std::string& name) { return element_manager::instance().border(name); } @@ -722,7 +816,7 @@ namespace nana element_manager::instance().arrow(name, factory); } - arrow_interface* const * provider::keeper_arrow(const std::string& name) + arrow_interface* const * provider::cite_arrow(const std::string& name) { return element_manager::instance().arrow(name); } @@ -732,16 +826,26 @@ namespace nana element_manager::instance().button(name, factory); } - element_interface* const* provider::keeper_button(const std::string& name) + element_interface* const* provider::cite_button(const std::string& name) { return element_manager::instance().button(name); } + + void provider::add_x_icon(const std::string& name, const pat::cloneable>& factory) + { + element_manager::instance().x_icon(name, factory); + } + + element_interface* const* provider::cite_x_icon(const std::string& name) + { + return element_manager::instance().x_icon(name); + } }//end namespace element //facades //template<> class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_crook(name ? name : "")) + : cite_(element::provider().cite_crook(name ? name : "")) { data_.check_state = state::unchecked; data_.radio = false; @@ -777,40 +881,120 @@ namespace nana void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_crook(name ? name : ""); + cite_ = element::provider().cite_crook(name ? name : ""); } bool facade::draw(graph_reference graph, const ::nana::color& bgcol, const ::nana::color& fgcol, const nana::rectangle& r, element_state es) { - return (*keeper_)->draw(graph, bgcol, fgcol, r, es, data_); + return (*cite_)->draw(graph, bgcol, fgcol, r, es, data_); } //end class facade + //class facade + facade::facade(const char* name) + : cite_(element::provider().cite_cross(name ? name : "")) + { + + } + + void facade::switch_to(const char* name) + { + cite_ = element::provider().cite_cross(name ? name : ""); + } + + void facade::thickness(unsigned thk) + { + thickness_ = thk; + } + + void facade::size(unsigned size_px) + { + size_ = size_px; + } + + //Implement element_interface + bool facade::draw(graph_reference graph, const ::nana::color&, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state) + { + if (thickness_ + 2 <= size_) + { + int gap = (static_cast(size_) - static_cast(thickness_)) / 2; + + nana::point ps[12]; + ps[0].x = r.x + gap; + ps[1].x = ps[0].x + static_cast(thickness_) - 1; + ps[1].y = ps[0].y = r.y; + + ps[2].x = ps[1].x; + ps[2].y = r.y + gap; + + ps[3].x = ps[2].x + gap; + ps[3].y = ps[2].y; + + ps[4].x = ps[3].x; + ps[4].y = ps[3].y + static_cast(thickness_)-1; + + ps[5].x = ps[1].x; + ps[5].y = ps[4].y; + + ps[6].x = ps[5].x; + ps[6].y = ps[5].y + gap; + + ps[7].x = r.x + gap; + ps[7].y = ps[6].y; + + ps[8].x = ps[7].x; + ps[8].y = ps[4].y; + + ps[9].x = r.x; + ps[9].y = ps[4].y; + + ps[10].x = r.x; + ps[10].y = r.y + gap; + + ps[11].x = r.x + gap; + ps[11].y = r.y + gap; + + graph.set_color(fgcolor.blend(colors::black, true)); + + for (int i = 0; i < 11; ++i) + graph.line(ps[i], ps[i + 1]); + graph.line(ps[11], ps[0]); + + graph.set_color(fgcolor); + + unsigned thk_minus_2 = thickness_ - 2; + graph.rectangle(rectangle{ ps[10].x + 1, ps[10].y + 1, (gap << 1) + thk_minus_2, thk_minus_2 }, true); + graph.rectangle(rectangle{ ps[0].x + 1, ps[0].y + 1, thk_minus_2, (gap << 1) + thk_minus_2 }, true); + } + return true; + } + //end class facade + //class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_border(name ? name : "")) + : cite_(element::provider().cite_border(name ? name : "")) {} void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_border(name ? name : ""); + cite_ = element::provider().cite_border(name ? name : ""); } bool facade::draw(graph_reference graph, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state es) { - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, es, 2); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, es, 2); } //end class facade //class facade facade::facade(const char* name) - : keeper_(element::provider().keeper_arrow(name ? name : "")) + : cite_(element::provider().cite_arrow(name ? name : "")) { } void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_arrow(name ? name : ""); + cite_ = element::provider().cite_arrow(name ? name : ""); } void facade::direction(::nana::direction dir) @@ -822,27 +1006,45 @@ namespace nana bool facade::draw(graph_reference graph, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state estate) { graph.set_color(fgcolor); - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, estate, dir_); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate, dir_); } //end class facade //class facade:: facade::facade(const char* name) - : keeper_(element::provider().keeper_button(name ? name : "")) + : cite_(element::provider().cite_button(name ? name : "")) {} void facade::switch_to(const char* name) { - keeper_ = element::provider().keeper_button(name ? name : ""); + cite_ = element::provider().cite_button(name ? name : ""); } //Implement element_interface bool facade::draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate) { - return (*keeper_)->draw(graph, bgcolor, fgcolor, r, estate); + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate); } //end class facade + + //class facade + facade::facade(const char* name) + : cite_(element::provider().cite_x_icon(name ? name : "")) + {} + + void facade::switch_to(const char* name) + { + cite_ = element::provider().cite_x_icon(name ? name : ""); + } + + //Implement element_interface + bool facade::draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate) + { + return (*cite_)->draw(graph, bgcolor, fgcolor, r, estate); + } + //end class facade + namespace element { void set_bground(const char* name, const pat::cloneable& obj) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index f57df5e5..7a6325ef 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1,4 +1,4 @@ -/** +/* * An Implementation of Place for Layout * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) @@ -8,333 +8,35 @@ * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/gui/place.cpp + * @contributors: qPCR4vir */ -#include + #include #include -#include -#include +#include +#include #include #include #include +#include #include +#include #include -#include -#include +#include //numeric_limits + +#include "place_parts.hpp" namespace nana { namespace place_parts { + //check the name void check_field_name(const char* name) { - //check the name if (*name && (*name != '_' && !(('a' <= *name && *name <= 'z') || ('A' <= *name && *name <= 'Z')))) - throw std::invalid_argument("place.field: bad field name"); + throw std::invalid_argument("nana.place: bad field name"); } - - class splitter_interface - { - public: - virtual ~splitter_interface(){} - }; - - class splitter_dtrigger - : public drawer_trigger - { - }; - - template - class splitter - : public widget_object ::type, splitter_dtrigger>, - public splitter_interface - { - }; - - //number_t is used for storing a number type variable - //such as integer, real and percent. Essentially, percent is a typo of real. - class number_t - { - public: - enum class kind{ none, integer, real, percent }; - - number_t() - : kind_(kind::none) - { - value_.integer = 0; - } - - void reset() - { - kind_ = kind::none; - value_.integer = 0; - } - - bool is_negative() const - { - switch (kind_) - { - case kind::integer: - return (value_.integer < 0); - case kind::real: - case kind::percent: - return (value_.real < 0); - default: - break; - } - return false; - } - - bool is_none() const - { - return (kind::none == kind_); - } - - bool is_not_none() const - { - return (kind::none != kind_); - } - - kind kind_of() const - { - return kind_; - } - - double get_value(int ref_percent) const - { - switch (kind_) - { - case kind::integer: - return value_.integer; - case kind::real: - return value_.real; - case kind::percent: - return value_.real * ref_percent; - default: - break; - } - return 0; - } - - int integer() const - { - if (kind::integer == kind_) - return value_.integer; - return static_cast(value_.real); - } - - double real() const - { - if (kind::integer == kind_) - return value_.integer; - return value_.real; - } - - void assign(int i) - { - kind_ = kind::integer; - value_.integer = i; - } - - void assign(double d) - { - kind_ = kind::real; - value_.real = d; - } - - void assign_percent(double d) - { - kind_ = kind::percent; - value_.real = d / 100; - } - private: - kind kind_; - union valueset - { - int integer; - double real; - }value_; - };//end class number_t - - class margin - { - public: - margin& operator=(margin&& rhs) - { - if (this != &rhs) - { - all_edges_ = rhs.all_edges_; - margins_ = std::move(rhs.margins_); - } - return *this; - } - - void clear() - { - all_edges_ = true; - margins_.clear(); - } - - void push(const number_t& v) - { - margins_.emplace_back(v); - } - - void set_value(const number_t& v) - { - clear(); - margins_.emplace_back(v); - } - - void set_array(const std::vector& v) - { - all_edges_ = false; - margins_ = v; - } - - nana::rectangle area(const ::nana::rectangle& field_area) const - { - if (margins_.empty()) - return field_area; - - auto r = field_area; - if (all_edges_) - { - auto px = static_cast(margins_.back().get_value(static_cast(r.width))); - const auto dbl_px = static_cast(px << 1); - r.x += px; - r.width = (r.width < dbl_px ? 0 : r.width - dbl_px); - - r.y += px; - r.height = (r.height < dbl_px ? 0 : r.height - dbl_px); - } - else - { - int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin - switch (margins_.size()) - { - case 0: break; - case 1: //top - it = 0; - break; - case 2://top,bottom and left,right - it = ib = 0; - il = ir = 1; - break; - default: - il = 3; //left - case 3: //top, right, bottom - it = 0; - ir = 1; - ib = 2; - } - - typedef decltype(r.height) px_type; - auto calc = [](px_type a, px_type b) - { - return (a > b ? a - b : 0); - }; - - if (0 == it) //top - { - auto px = static_cast(margins_[it].get_value(static_cast(field_area.height))); - r.y += px; - r.height = calc(r.height, static_cast(px)); - } - - if (-1 != ib) //bottom - { - auto px = static_cast(margins_[ib].get_value(static_cast(field_area.height))); - r.height = calc(r.height, static_cast(px)); - } - - if (-1 != il) //left - { - auto px = static_cast(margins_[il].get_value(static_cast(field_area.width))); - r.x += px; - r.width = calc(r.width, static_cast(px)); - } - - if (-1 != ir) //right - { - auto px = static_cast(margins_[ir].get_value(static_cast(field_area.width))); - r.width = calc(r.width, static_cast(px)); - } - } - return r; - } - private: - bool all_edges_ = true; - std::vector margins_; - };//end class margin - - class repeated_array - { - public: - - //A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted. - repeated_array() = default; - - repeated_array(repeated_array && other) - : repeated_{other.repeated_}, - values_(std::move(other.values_)) - { - } - - repeated_array& operator=(repeated_array&& other) - { - if(this != &other) - { - repeated_ = other.repeated_; - other.repeated_ = false; - values_ = std::move(other.values_); - } - return *this; - } - - void assign(std::vector&& c) - { - values_ = std::move(c); - } - - bool empty() const - { - return values_.empty(); - } - - void reset() - { - repeated_ = false; - values_.clear(); - } - - void repeated() - { - repeated_ = true; - } - - void push(const number_t& n) - { - values_.emplace_back(n); - } - - number_t at(std::size_t pos) const - { - if (values_.empty()) - return{}; - - if (repeated_) - pos %= values_.size(); - else if (pos >= values_.size()) - return{}; - - return values_[pos]; - } - private: - bool repeated_ = false; - std::vector values_; - }; }//end namespace place_parts typedef place_parts::number_t number_t; @@ -348,8 +50,8 @@ namespace nana enum class token { div_start, div_end, splitter, - identifier, vert, grid, number, array, reparray, - weight, gap, margin, arrange, variable, repeated, min_px, max_px, + identifier, dock, vert, grid, number, array, reparray, + weight, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, collapse, parameters, equal, eof, error @@ -384,6 +86,16 @@ namespace nana return parameters_; } + std::size_t pos() const + { + return (sp_ - divstr_); + } + + std::string pos_str() const + { + return std::to_string(pos()); + } + token read() { sp_ = _m_eat_whitespace(sp_); @@ -415,46 +127,46 @@ namespace nana ++sp_; return token::array; } - - { - //When search the repeated. - bool repeated = false; - - while (true) + else { - sp_ = _m_eat_whitespace(sp_); - auto tk = read(); - if (token::number != tk && token::variable != tk && token::repeated != tk) - _m_throw_error("invalid array element"); + //When search the repeated. + bool repeated = false; - if (!repeated) + while (true) { - switch (tk) + sp_ = _m_eat_whitespace(sp_); + auto tk = read(); + if (token::number != tk && token::variable != tk && token::repeated != tk) + _m_throw_error("invalid array element"); + + if (!repeated) { - case token::number: - array_.push_back(number_); - break; - case token::variable: - array_.push_back({}); - break; - default: - repeated = true; - reparray_.repeated(); - reparray_.assign(std::move(array_)); + switch (tk) + { + case token::number: + array_.push_back(number_); + break; + case token::variable: + array_.push_back({}); + break; + default: + repeated = true; + reparray_.repeated(); + reparray_.assign(std::move(array_)); + } } + + sp_ = _m_eat_whitespace(sp_); + char ch = *sp_++; + + if (ch == ']') + return (repeated ? token::reparray : token::array); + + if (ch != ',') + _m_throw_error("invalid array"); } - - sp_ = _m_eat_whitespace(sp_); - char ch = *sp_++; - - if (ch == ']') - return (repeated ? token::reparray : token::array); - - if (ch != ',') - _m_throw_error("invalid array"); } - } - break; + break; case '(': parameters_.clear(); sp_ = _m_eat_whitespace(sp_ + 1); @@ -497,7 +209,7 @@ namespace nana return token::number; } else - _m_throw_error(*sp_); + _m_throw_error("invalid character '" + std::string(1, *sp_) + "'"); break; default: if ('0' <= *sp_ && *sp_ <= '9') @@ -532,6 +244,8 @@ namespace nana case 'a': return token::max_px; } } + else if ("dock" == idstr_) + return token::dock; else if ("vertical" == idstr_ || "vert" == idstr_) return token::vert; else if ("variable" == idstr_ || "repeated" == idstr_) @@ -556,10 +270,24 @@ namespace nana _m_throw_error("a parameter list is required after 'collapse'"); return token::collapse; } + else if ("left" == idstr_ || "right" == idstr_ || "top" == idstr_ || "bottom" == idstr_) + { + switch (idstr_.front()) + { + case 'l': return token::left; + case 'r': return token::right; + case 't': return token::top; + case 'b': return token::bottom; + } + } return token::identifier; } - _m_throw_error(*sp_); + std::string err = "an invalid character '"; + err += *sp_; + err += "'"; + + _m_throw_error(err); return token::error; //Useless, just for syntax correction. } private: @@ -570,7 +298,7 @@ namespace nana str += '\''; _m_throw_error(str); } - + void _m_throw_error(const std::string& err) { std::stringstream ss; @@ -583,7 +311,7 @@ namespace nana if (token::equal != read()) _m_throw_error("an equal sign is required after '" + idstr_ + "'"); - const char* p = _m_eat_whitespace(sp_); + auto p = _m_eat_whitespace(sp_); auto neg_ptr = p; if ('-' == *p) @@ -696,29 +424,44 @@ namespace nana }; //end class tokenizer } - //struct implement struct place::implement { - class field_impl; + class field_gather; + class field_dock; + class division; class div_arrange; class div_grid; class div_splitter; + class div_dock; + class div_dockpane; window window_handle{nullptr}; event_handle event_size_handle{nullptr}; std::unique_ptr root_division; - std::map fields; + std::map fields; + std::map docks; + + //A temporary pointer used to refer to a specified div object which + //will be deleted in modification process. + std::unique_ptr tmp_replaced; //The following functions are defined behind the definition of class division. //because the class division here is an incomplete type. ~implement(); + + void collocate(); + static division * search_div_name(division* start, const std::string&); std::unique_ptr scan_div(place_parts::tokenizer&); + void check_unique(const division*) const; + + //connect the field/dock with div object + void connect(division* start); }; //end struct implement - class place::implement::field_impl + class place::implement::field_gather : public place::field_interface { public: @@ -732,11 +475,11 @@ namespace nana {} }; - field_impl(place * p) + field_gather(place * p) : place_ptr_(p) {} - ~field_impl() + ~field_gather() { for (auto & e : elements) API::umake_event(e.evt_destroy); @@ -778,7 +521,7 @@ namespace nana { return API::events(wd).destroy.connect([this, wd](const arg_destroy& arg) { - if (erase_element(elements, arg.window_handle)) + for (auto i = elements.begin(), end = elements.end(); i != end; ++i) { if (!API::is_destroying(API::get_parent_window(wd))) place_ptr_->collocate(); @@ -840,12 +583,22 @@ namespace nana std::vector fastened; private: place * place_ptr_; - };//end class field_impl + };//end class field_gather + + class place::implement::field_dock + { + + public: + div_dockpane * attached{ nullptr }; //attached div object + place_parts::dockarea dockarea; //the dockable widget + };//end class field_dock + + class place::implement::division { public: - enum class kind{ arrange, vertical_arrange, grid, splitter }; + enum class kind{ arrange, vertical_arrange, grid, splitter, dock, dockpane}; division(kind k, std::string&& n) : kind_of_division(k), @@ -879,6 +632,50 @@ namespace nana _m_visible_for_child(this, dsp); visible = dsp; display = dsp; + + if (kind::splitter != kind_of_division) + { + //Don't display the previous one, if it is a splitter + auto div = previous(); + if (div && (kind::splitter == div->kind_of_division)) + { + if (dsp) + { + auto leaf = div->previous(); + if (leaf && leaf->display) + div->set_display(true); + } + else + div->set_display(false); + } + + //Don't display the next one, if it is a splitter + if (div_next && (kind::splitter == div_next->kind_of_division)) + { + if (dsp) + { + auto leaf = div_next->div_next; + if (leaf && leaf->display) + div_next->set_display(true); + } + else + div_next->set_display(false); + } + } + else + { + //This is a splitter, it only checks when it is being displayed + if (dsp) + { + auto left = this->previous(); + if (left && !left->display) + left->set_display(true); + + auto right = div_next; + if (right && !right->display) + right->set_display(true); + } + } } bool is_back(const division* div) const @@ -924,6 +721,18 @@ namespace nana { return margin.area(field_area); } + + division * previous() const + { + if (div_owner) + { + for (auto & child : div_owner->children) + if (child->div_next == this) + return child.get(); + } + return nullptr; + + } public: void _m_visible_for_child(division * div, bool vsb) { @@ -943,21 +752,22 @@ namespace nana kind kind_of_division; bool display{ true }; bool visible{ true }; - const std::string name; + ::nana::direction dir{::nana::direction::west}; + std::string name; std::vector> children; - nana::rectangle field_area; + ::nana::rectangle field_area; number_t weight; number_t min_px, max_px; place_parts::margin margin; place_parts::repeated_array gap; - field_impl * field; + field_gather * field; division * div_next, *div_owner; };//end class division template - void place::implement::field_impl::_m_for_each(division * div, Function fn) + void place::implement::field_gather::_m_for_each(division * div, Function fn) { for (auto & up : div->children) //The element of children is unique_ptr fn(up.get()); @@ -1503,23 +1313,28 @@ namespace nana class place::implement::div_splitter : public division { + struct div_block + { + division * div; + int pixels; + double scale; + + div_block(division* d, int px) + : div(d), pixels(px) + {} + }; + enum{splitter_px = 4}; public: div_splitter(place_parts::number_t init_weight) : division(kind::splitter, std::string()), splitter_cursor_(cursor::arrow), - leaf_left_(nullptr), leaf_right_(nullptr), pause_move_collocate_(false), init_weight_(init_weight) { this->weight.assign(splitter_px); } - void set_leaf(bool is_left, division * d) - { - (is_left ? leaf_left_ : leaf_right_) = d; - } - void direction(bool horizontal) { splitter_cursor_ = (horizontal ? cursor::size_we : cursor::size_ns); @@ -1546,8 +1361,8 @@ namespace nana auto px_ptr = &nana::rectangle::width; //Use field_area of leaf, not margin_area. Otherwise splitter would be at wrong position - auto area_left = leaf_left_->field_area; - auto area_right = leaf_right_->field_area; + auto area_left = _m_leaf_left()->field_area; + auto area_right = _m_leaf_right()->field_area; if (nana::cursor::size_we != splitter_cursor_) { @@ -1582,9 +1397,10 @@ namespace nana else if (left_px < 0) left_px = 0; + auto leaf_left = _m_leaf_left(); double imd_rate = 100.0 / area_px; - left_px = static_cast(limit_px(leaf_left_, left_px, area_px)); - leaf_left_->weight.assign_percent(imd_rate * left_px); + left_px = static_cast(limit_px(_m_leaf_left(), left_px, area_px)); + _m_leaf_left()->weight.assign_percent(imd_rate * left_px); auto right_px = static_cast(right_pixels_)-delta; if (right_px > total_pixels) @@ -1592,15 +1408,15 @@ namespace nana else if (right_px < 0) right_px = 0; - right_px = static_cast(limit_px(leaf_right_, right_px, area_px)); - leaf_right_->weight.assign_percent(imd_rate * right_px); + right_px = static_cast(limit_px(_m_leaf_right(), right_px, area_px)); + _m_leaf_right()->weight.assign_percent(imd_rate * right_px); pause_move_collocate_ = true; div_owner->collocate(splitter_.parent()); //After the collocating, the splitter keeps the calculated weight of left division, //and clear the weight of right division. - leaf_right_->weight.reset(); + _m_leaf_right()->weight.reset(); pause_move_collocate_ = false; }); @@ -1612,10 +1428,12 @@ namespace nana { const bool vert = (::nana::cursor::size_we != splitter_cursor_); - rectangle_rotator left(vert, leaf_left_->field_area); - rectangle_rotator right(vert, leaf_right_->field_area); + auto leaf_left = _m_leaf_left(); + auto leaf_right = _m_leaf_right(); + rectangle_rotator left(vert, leaf_left->field_area); + rectangle_rotator right(vert, leaf_right->field_area); auto area_px = right.right() - left.x(); - auto right_px = static_cast(limit_px(leaf_right_, init_weight_.get_value(area_px), static_cast(area_px))); + auto right_px = static_cast(limit_px(leaf_right, init_weight_.get_value(area_px), static_cast(area_px))); auto pos = area_px - right_px - splitter_px; //New position of splitter if (pos < limited_range.x()) @@ -1623,7 +1441,7 @@ namespace nana else if (pos > limited_range.right()) pos = limited_range.right(); - nana::rectangle_rotator sp_r(vert, field_area); + rectangle_rotator sp_r(vert, field_area); sp_r.x_ref() = pos; left.w_ref() = static_cast(pos - left.x()); @@ -1633,17 +1451,17 @@ namespace nana right.w_ref() = static_cast(right_pos - pos - splitter_px); field_area = sp_r.result(); - leaf_left_->field_area = left.result(); - leaf_right_->field_area = right.result(); - leaf_left_->collocate(wd); - leaf_right_->collocate(wd); + leaf_left->field_area = left.result(); + leaf_right->field_area = right.result(); + leaf_left->collocate(wd); + leaf_right->collocate(wd); //Set the leafs' weight rectangle_rotator area(vert, div_owner->field_area); double imd_rate = 100.0 / static_cast(area.w()); - leaf_left_->weight.assign_percent(imd_rate * static_cast(left.w())); - leaf_right_->weight.assign_percent(imd_rate * static_cast(right.w())); + leaf_left->weight.assign_percent(imd_rate * static_cast(left.w())); + leaf_right->weight.assign_percent(imd_rate * static_cast(right.w())); splitter_.move(this->field_area); @@ -1654,40 +1472,53 @@ namespace nana splitter_.move(this->field_area); } private: + division * _m_leaf_left() const + { + return previous(); + } + + division * _m_leaf_right() const + { + return div_next; + } + rectangle_rotator _m_update_splitter_range() { const bool vert = (cursor::size_ns == splitter_cursor_); rectangle_rotator area(vert, div_owner->margin_area()); - rectangle_rotator left(vert, leaf_left_->field_area); - rectangle_rotator right(vert, leaf_right_->field_area); + auto leaf_left = _m_leaf_left(); + auto leaf_right = _m_leaf_right(); + + rectangle_rotator left(vert, leaf_left->field_area); + rectangle_rotator right(vert, leaf_right->field_area); const int left_base = left.x(), right_base = right.right(); int pos = left_base; int endpos = right_base; - if (leaf_left_->min_px.is_not_none()) + if (leaf_left->min_px.is_not_none()) { - auto v = leaf_left_->min_px.get_value(area.w()); + auto v = leaf_left->min_px.get_value(area.w()); pos += static_cast(v); } - if (leaf_left_->max_px.is_not_none()) + if (leaf_left->max_px.is_not_none()) { - auto v = leaf_left_->max_px.get_value(area.w()); + auto v = leaf_left->max_px.get_value(area.w()); endpos = left_base + static_cast(v); } - if (leaf_right_->min_px.is_not_none()) + if (leaf_right->min_px.is_not_none()) { - auto v = leaf_right_->min_px.get_value(area.w()); + auto v = leaf_right->min_px.get_value(area.w()); auto x = right_base - static_cast(v); if (x < endpos) endpos = x; } - if (leaf_right_->max_px.is_not_none()) + if (leaf_right->max_px.is_not_none()) { - auto v = leaf_right_->max_px.get_value(area.w()); + auto v = leaf_right->max_px.get_value(area.w()); auto x = right_base - static_cast(v); if (x > pos) pos = x; @@ -1702,10 +1533,9 @@ namespace nana } private: nana::cursor splitter_cursor_; + bool created_{ false }; place_parts::splitter splitter_; nana::point begin_point_; - division * leaf_left_; - division * leaf_right_; int left_pos_, right_pos_; unsigned left_pixels_, right_pixels_; dragger dragger_; @@ -1713,12 +1543,372 @@ namespace nana place_parts::number_t init_weight_; }; + class place::implement::div_dockpane + : public division, public place_parts::dock_notifier_interface + { + public: + div_dockpane(std::string && name, implement* impl, direction pane_dir) + : division(kind::dockpane, std::move(name)), + impl_ptr_{impl} + { + dir = pane_dir; + } + + ~div_dockpane() + { + if (dockable_field) + { + dockable_field->dockarea.close(); + dockable_field->attached = nullptr; + } + } + + void collocate(window wd) override + { + if (!dockable_field) + { + // + if (name.empty()) + return; + + auto &dock_ptr = impl_ptr_->docks[name]; + if (!dock_ptr) + dock_ptr = new field_dock; + + dock_ptr->attached = this; + dockable_field = dock_ptr; + } + + auto & dockarea = dockable_field->dockarea; + if (!created_) + { + created_ = true; + dockarea.create(wd, this); + } + + + if (!dockarea.empty() && !dockarea.floating()) + { + dockarea.move(this->field_area); + indicator_.r = this->field_area; + } + } + private: + //Implement dock_notifier_interface + void notify_float() override + { + set_display(false); + + impl_ptr_->collocate(); + } + + void notify_dock() override + { + indicator_.docker.reset(); + set_display(true); + impl_ptr_->collocate(); + } + + void notify_move() override + { + if (!_m_indicator()) + { + indicator_.docker.reset(); + return; + } + + if (!indicator_.docker) + { + auto host_size = API::window_size(impl_ptr_->window_handle); + indicator_.docker.reset(new form(impl_ptr_->window_handle, { static_cast(host_size.width) / 2 - 16, static_cast(host_size.height) / 2 - 16, 32, 32 }, form::appear::bald<>())); + drawing dw(indicator_.docker->handle()); + dw.draw([](paint::graphics& graph) + { + graph.rectangle(false, colors::midnight_blue); + graph.rectangle({ 1, 1, 30, 30 }, true, colors::light_sky_blue); + + facade arrow; + arrow.direction(::nana::direction::south); + arrow.draw(graph, colors::light_sky_blue, colors::midnight_blue, { 12, 0, 16, 16 }, element_state::normal); + + rectangle r{ 4, 16, 24, 11 }; + graph.rectangle(r, true, colors::midnight_blue); + + r.x = 5; + r.y = 19; + r.width = 22; + r.height = 7; + graph.rectangle(r, true, colors::button_face); + }); + + indicator_.docker->z_order(nullptr, ::nana::z_order_action::topmost); + indicator_.docker->show(); + + indicator_.docker->events().destroy([this] + { + if (indicator_.dock_area) + { + indicator_.dock_area.reset(); + indicator_.graph.release(); + } + }); + } + + if (_m_dockable()) + { + if (!indicator_.dock_area) + { + indicator_.graph.make(API::window_size(impl_ptr_->window_handle)); + API::window_graphics(impl_ptr_->window_handle, indicator_.graph); + + indicator_.dock_area.reset(new panel(impl_ptr_->window_handle, false)); + indicator_.dock_area->move(indicator_.r); + + ::nana::drawing dw(indicator_.dock_area->handle()); + dw.draw([this](paint::graphics& graph) + { + indicator_.graph.paste(indicator_.r, graph, 0, 0); + + const int border_px = 4; + rectangle r{ graph.size() }; + int right = r.right(); + int bottom = r.bottom(); + + graph.blend(r.pare_off(border_px), colors::blue, 0.3); + + ::nana::color clr = colors::deep_sky_blue; + r.y = 0; + r.height = border_px; + graph.blend(r, clr, 0.5); + r.y = bottom - border_px; + graph.blend(r, clr, 0.5); + + r.x = r.y = 0; + r = graph.size(); + r.width = border_px; + graph.blend(r, clr, 0.5); + r.x = right - border_px; + graph.blend(r, clr, 0.5); + + }); + + //indicator_.dock_area->z_order(nullptr, ::nana::z_order_action::top); //deprecated + API::bring_top(indicator_.dock_area->handle(), false); + indicator_.dock_area->show(); + } + } + else + { + if (indicator_.dock_area) + { + indicator_.dock_area.reset(); + indicator_.graph.release(); + } + } + + } + + void notify_move_stopped() + { + if (_m_dockable() && dockable_field) + dockable_field->dockarea.dock(); + + indicator_.docker.reset(); + } + private: + bool _m_indicator() const + { + ::nana::point pos; + API::calc_screen_point(impl_ptr_->window_handle, pos); + + rectangle r{ pos, API::window_size(impl_ptr_->window_handle) }; + return r.is_hit(API::cursor_position()); + } + + bool _m_dockable() const + { + if (!indicator_.docker) + return false; + + ::nana::point pos; + API::calc_screen_point(indicator_.docker->handle(), pos); + + rectangle r{ pos, API::window_size(indicator_.docker->handle()) }; + return r.is_hit(API::cursor_position()); + } + public: + field_dock * dockable_field{ nullptr }; + private: + implement * impl_ptr_; + bool created_{ false }; + + struct indicator_tag + { + paint::graphics graph; + //panel widget; + rectangle r; + std::unique_ptr> dock_area; + std::unique_ptr
docker; + }indicator_; + }; + + class place::implement::div_dock + : public division + { + public: + div_dock(std::string && name, implement* impl) + : division(kind::dock, std::move(name)) + {} + + void collocate(window wd) override + { + auto area = this->margin_area(); + + unsigned vert_count = 0, horz_count = 0; + unsigned vert_weight = 0, horz_weight = 0; + + bool prev_attr = _m_is_vert(children.front()->dir); + (prev_attr ? horz_count : vert_count) = 1; + + for (auto & child : children) + { + auto is_vert = _m_is_vert(child->dir); + + if (child->weight.is_not_none()) + { + if (is_vert) + vert_weight += static_cast(child->weight.get_value(area.height)); + else + horz_weight += static_cast(child->weight.get_value(area.width)); + } + + if (is_vert == prev_attr) + { + if (is_vert) + ++vert_count; + else + ++horz_count; + } + else + { + if (is_vert) + ++horz_count; + else + ++vert_count; + } + prev_attr = is_vert; + } + if (0 == vert_count) + ++vert_count; + if (0 == horz_count) + ++horz_count; + + double auto_horz_w = double(area.width - horz_weight) / horz_count; + double auto_vert_w = double(area.height - vert_weight) / vert_count; + + double left = area.x; + double right = area.right(); + double top = area.y; + double bottom = area.bottom(); + + for (auto & child : children) + { + double weight; + if (child->weight.is_not_none()) + weight = child->weight.get_value(_m_is_vert(child->dir) ? area.height : area.height); + else + weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); + + ::nana::rectangle child_r; + switch (child->dir) + { + default: + case ::nana::direction::west: + child_r.x = static_cast(left); + child_r.y = static_cast(top); + child_r.width = static_cast(weight); + child_r.height = static_cast(bottom - top); + left += weight; + break; + case ::nana::direction::east: + right -= weight; + child_r.x = static_cast(right); + child_r.y = static_cast(top); + child_r.width = static_cast(weight); + child_r.height = static_cast(bottom - top); + break; + case ::nana::direction::north: + child_r.x = static_cast(left); + child_r.y = static_cast(top); + child_r.width = static_cast(right - left); + child_r.height = static_cast(weight); + top += weight; + break; + case ::nana::direction::south: + child_r.x = static_cast(left); + bottom -= weight; + child_r.y = static_cast(bottom); + child_r.width = static_cast(right - left); + child_r.height = static_cast(weight); + break; + } + + child->field_area = child_r; + child->collocate(wd); + } + } + private: + static bool _m_is_vert(::nana::direction dir) + { + return (dir == ::nana::direction::north || dir == ::nana::direction::south); + } + }; + place::implement::~implement() { API::umake_event(event_size_handle); root_division.reset(); + for (auto & pair : fields) delete pair.second; + + for (auto & dock : docks) + delete dock.second; + } + + void place::implement::collocate() + { + if (root_division && window_handle) + { + root_division->field_area = API::window_size(window_handle); + + if (root_division->field_area.empty()) + return; + + root_division->collocate(window_handle); + + for (auto & field : fields) + { + bool is_show = false; + if (field.second->attached && field.second->attached->visible && field.second->attached->display) + { + is_show = true; + auto div = field.second->attached->div_owner; + while (div) + { + if (!div->visible || !div->display) + { + is_show = false; + break; + } + div = div->div_owner; + } + } + + for (auto & el : field.second->elements) + API::show_window(el.handle, is_show); + } + } } //search_div_name @@ -1755,18 +1945,24 @@ namespace nana std::vector array; std::vector collapses; std::vector> children; + ::nana::direction div_dir = ::nana::direction::west; for (token tk = tknizer.read(); tk != token::eof; tk = tknizer.read()) { bool exit_for = false; switch (tk) { + case token::dock: + if (token::eof != div_type && token::dock != div_type) + throw std::invalid_argument("nana.place: conflict of div type at " + tknizer.pos_str()); + + div_type = token::dock; + break; case token::splitter: //Ignore the splitter when there is not a division. if (!children.empty() && (division::kind::splitter != children.back()->kind_of_division)) { auto splitter = new div_splitter(tknizer.number()); - splitter->set_leaf(true, children.back().get()); children.back()->div_next = splitter; children.emplace_back(splitter); } @@ -1774,12 +1970,9 @@ namespace nana case token::div_start: { auto div = scan_div(tknizer); - if (children.size()) - { + if (!children.empty()) children.back()->div_next = div.get(); - if (division::kind::splitter == children.back()->kind_of_division) - dynamic_cast(*children.back()).set_leaf(false, div.get()); - } + children.emplace_back(div.release()); } break; @@ -1815,7 +2008,7 @@ namespace nana else if (arg.kind_of() == number_t::kind::real) return static_cast(arg.real()); - throw std::runtime_error("place: the type of the "+ nth +" parameter for collapse should be integer."); + throw std::invalid_argument("nana.place: the type of the "+ nth +" parameter for collapse should be integer."); }; ::nana::rectangle col; @@ -1851,7 +2044,7 @@ namespace nana } } else - throw std::runtime_error("place: collapse requires 4 parameters."); + throw std::invalid_argument("nana.place: collapse requires 4 parameters."); break; case token::weight: case token::min_px: case token::max_px: { @@ -1904,13 +2097,22 @@ namespace nana case token::identifier: name = tknizer.idstr(); break; + case token::left: + div_dir = ::nana::direction::west; break; + case token::right: + div_dir = ::nana::direction::east; break; + case token::top: + div_dir = ::nana::direction::north; break; + case token::bottom: + div_dir = ::nana::direction::south; break; default: break; } if (exit_for) break; } - field_impl * attached_field = nullptr; + field_gather * attached_field = nullptr; + field_dock* attached_dock = nullptr; if (name.size()) { //find the field with specified name. @@ -1951,8 +2153,16 @@ namespace nana div = std::move(p); } break; + case token::dock: + //deprecated + // + //if (name.empty()) + // throw std::invalid_argument("nana.place: dock must have a name."); + + div.reset(new div_dock(std::move(name), this)); + break; default: - throw std::runtime_error("nana.place: invalid division type."); + throw std::invalid_argument("nana.place: invalid division type."); } //Requirements for min/max @@ -1999,13 +2209,123 @@ namespace nana if (division::kind::splitter == child->kind_of_division) dynamic_cast(*child).direction(div_type != token::vert); } + + if (token::dock == div_type) + { + //adjust these children for dock division + std::vector> adjusted_children; + for (auto & child : children) + { + adjusted_children.emplace_back(new div_dockpane(std::move(child->name), this, child->dir)); + } + + children.swap(adjusted_children); + } } div->children.swap(children); div->margin = std::move(margin); + div->dir = div_dir; return div; } + void place::implement::check_unique(const division* div) const + { + //The second field_impl is useless. Reuse the map type in order to + //reduce the size of the generated code, becuase std::set + //will create a new template class. + std::map unique; + field_gather tmp(nullptr); + + std::function check_fn; + check_fn = [&check_fn, &unique, &tmp](const implement::division* div) + { + if (!div->name.empty()) + { + auto & ptr = unique[div->name]; + if (ptr) + throw std::invalid_argument("place, the name '" + div->name + "' is redefined."); + ptr = &tmp; + } + + for (auto & child : div->children) + { + check_fn(child.get()); + } + }; + + if (div) + check_fn(div); + } + + //connect the field/dock with div object, + void place::implement::connect(division* start) + { + if (!start) + return; + + //disconnect + for (auto & fd : fields) + { + if (fd.second->attached) + { + fd.second->attached->field = nullptr; + fd.second->attached = nullptr; + } + } + + std::map docks_to_be_closed; + //disconnect + for (auto & dk : docks) + { + if (dk.second->attached) + docks_to_be_closed[dk.first] = dk.second; + } + + std::function check_fn; + check_fn = [&check_fn, this, &docks_to_be_closed](division* div) + { + if (div->name.size()) + { + if (division::kind::dock == div->kind_of_division) + { + auto i = docks.find(div->name); + if (i != docks.end()) + { + docks_to_be_closed.erase(div->name); + auto pane = dynamic_cast(div); + pane->dockable_field = i->second; + pane->dockable_field->attached = pane; + } + } + else + { + auto i = fields.find(div->name); + if (i != fields.end()) + { + div->field = i->second; + div->field->attached = div; + } + } + + } + + for (auto & child : div->children) + { + check_fn(child.get()); + } + }; + + check_fn(start); + + for (auto& e : docks_to_be_closed) + { + e.second->dockarea.close(); + e.second->attached->dockable_field = nullptr; + e.second->attached = nullptr; + } + } + //class place place::place() : impl_(new implement) @@ -2046,8 +2366,141 @@ namespace nana void place::div(const char* s) { place_parts::tokenizer tknizer(s); - impl_->root_division.reset(); //clear atachments div-fields - impl_->scan_div(tknizer).swap(impl_->root_division); + auto div = impl_->scan_div(tknizer); + try + { + impl_->check_unique(div.get()); //may throw if there is a redefined name of field. + impl_->connect(div.get()); + impl_->root_division.reset(); //clear atachments div-fields + impl_->root_division.swap(div); + } + catch (...) + { + //redefined a name of field + throw; + } + } + + void place::modify(const char* name, const char* div_text) + { + if (nullptr == div_text) + throw std::invalid_argument("nana.place: invalid div-text"); + + if (nullptr == name) name = ""; + + //check the name, it throws std::invalid_argument + //if name violate the naming convention. + place_parts::check_field_name(name); + + /* //deprecated + implement::division * div_ptr = nullptr; + implement::field_gather * field_ptr = nullptr; + { + auto i = impl_->fields.find(name); + if (i != impl_->fields.end()) + field_ptr = i->second; + } + + if (field_ptr) + { + //remove the existing div object + div_ptr = field_ptr->attached; + } + else + div_ptr = impl_->search_div_name(impl_->root_division.get(), name); + + if (nullptr == div_ptr) + { + std::string what = "nana::place: field '"; + what += name; + what += "' is not found."; + + throw std::invalid_argument(what); + } + */ + + auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name); + if (!div_ptr) + { + std::string what = "nana::place: field '"; + what += name; + what += "' is not found."; + + throw std::invalid_argument(what); + } + + + std::unique_ptr* replaced = nullptr; + + implement::division * div_owner = div_ptr->div_owner; + implement::division * div_next = div_ptr->div_next; + implement::division * div_bro = nullptr; + if (div_owner) + { + for (auto i = div_owner->children.begin(); i != div_owner->children.end(); ++i) + { + if (i->get() == div_ptr) + { + replaced = &(*i); + break; + } + div_bro = i->get(); + } + } + else + replaced = &(impl_->root_division); + + replaced->swap(impl_->tmp_replaced); + + try + { + place_parts::tokenizer tknizer(div_text); + auto modified = impl_->scan_div(tknizer); + auto modified_ptr = modified.get(); + modified_ptr->name = name; + //modified_ptr->field = field_ptr; + + replaced->swap(modified); + + impl_->check_unique(impl_->root_division.get()); + impl_->connect(impl_->root_division.get()); + impl_->tmp_replaced.reset(); + + modified_ptr->div_owner = div_owner; + modified_ptr->div_next = div_next; + //if (field_ptr) + // field_ptr->attached = modified_ptr; + /* + std::function attach; + attach = [this, &attach](implement::division* div) + { + if (!div->name.empty()) + { + auto i = impl_->fields.find(div->name); + if (impl_->fields.end() != i) + { + if (i->second->attached != div) + { + i->second->attached = div; + div->field = i->second; + } + } + } + + for (auto& child : div->children) + { + attach(child.get()); + } + }; + + attach(impl_->root_division.get()); + */ + } + catch (...) + { + replaced->swap(impl_->tmp_replaced); + throw; + } } place::field_reference place::field(const char* name) @@ -2055,14 +2508,15 @@ namespace nana if (nullptr == name) name = ""; - //May throw std::invalid_argument + //check the name, it throws std::invalid_argument + //if name violate the naming convention. place_parts::check_field_name(name); //get the field with specified name, if no such field with specified name //then create one. auto & p = impl_->fields[name]; if (nullptr == p) - p = new implement::field_impl(this); + p = new implement::field_gather(this); if ((!p->attached) && impl_->root_division) { @@ -2129,33 +2583,7 @@ namespace nana void place::collocate() { - if (impl_->root_division && impl_->window_handle) - { - impl_->root_division->field_area = API::window_size(impl_->window_handle); - impl_->root_division->collocate(impl_->window_handle); - - for (auto & field : impl_->fields) - { - bool is_show = false; - if (field.second->attached && field.second->attached->visible && field.second->attached->display) - { - is_show = true; - auto div = field.second->attached->div_owner; - while (div) - { - if (!div->visible || !div->display) - { - is_show = false; - break; - } - div = div->div_owner; - } - } - - for (auto & el : field.second->elements) - API::show_window(el.handle, is_show); - } - } + impl_->collocate(); } void place::erase(window handle) @@ -2170,7 +2598,7 @@ namespace nana recollocate |= (nullptr != fld.second->attached); } - API::umake_event( fld.second->erase_element(fld.second->fastened, handle)); + API::umake_event(fld.second->erase_element(fld.second->fastened, handle)); } if (recollocate) @@ -2181,5 +2609,25 @@ namespace nana { return field(name); } + + void place::dock(const std::string& name, std::function(window)> factory) + { + //check the name, it throws std::invalid_argument + //if name violate the naming convention. + place_parts::check_field_name(name.data()); + + auto & dock_ptr = impl_->docks[name]; + if (!dock_ptr) + dock_ptr = new implement::field_dock; + + dock_ptr->dockarea.add_factory(std::move(factory)); + + auto div = dynamic_cast(impl_->search_div_name(impl_->root_division.get(), name)); + if (div) + { + dock_ptr->attached = div; + div->dockable_field = dock_ptr; + } + } //end class place }//end namespace nana diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 6a64dc2d..94ca4fe4 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -538,11 +538,11 @@ namespace API return nana::point{}; } - void move_window(window wd, int x, int y) + void move_window(window wd, const point& pos) { auto iwd = reinterpret_cast(wd); internal_scope_guard lock; - if(restrict::window_manager.move(iwd, x, y, false)) + if(restrict::window_manager.move(iwd, pos.x, pos.y, false)) { restrict::core_window_t* update_wd = nullptr; if (iwd->displayed() && iwd->effect.bground) diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index af853b38..c7ecc667 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -305,7 +305,7 @@ namespace nana void widget::_m_move(int x, int y) { - API::move_window(handle(), x, y); + API::move_window(handle(), { x, y }); } void widget::_m_move(const rectangle& r) From 2a53467b24527616c66ec1a4664a81eb957ac656 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 14 Aug 2015 04:13:16 +0800 Subject: [PATCH 02/22] add missing header for docker-place --- source/gui/place_parts.hpp | 563 +++++++++++++++++++++++++++++++++++++ 1 file changed, 563 insertions(+) create mode 100644 source/gui/place_parts.hpp diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp new file mode 100644 index 00000000..3a1b670e --- /dev/null +++ b/source/gui/place_parts.hpp @@ -0,0 +1,563 @@ +/* + * Parts of Class Place + * Nana C++ Library(http://www.nanapro.org) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * @file: nana/gui/place_parts.hpp + */ +#ifndef NANA_GUI_PLACE_PARTS_HPP +#define NANA_GUI_PLACE_PARTS_HPP + +#include +#include +#include +#include +#include + +namespace nana +{ + namespace place_parts + { + class splitter_interface + { + public: + virtual ~splitter_interface(){} + }; + + class splitter_dtrigger + : public drawer_trigger + { + }; + + template + class splitter + : public widget_object ::type, splitter_dtrigger>, + public splitter_interface + { + private: + void _m_complete_creation() override + { + this->caption("place-splitter"); + widget_object ::type, splitter_dtrigger>::_m_complete_creation(); + } + }; + + + class dock_notifier_interface + { + public: + virtual ~dock_notifier_interface() = default; + + virtual void notify_float() = 0; + virtual void notify_dock() = 0; + virtual void notify_move() = 0; + virtual void notify_move_stopped() = 0; + }; + + class dockcaption_dtrigger + : public drawer_trigger + { + public: + private: + virtual void attached(widget_reference, graph_reference graph) override + { + graph.set_color(colors::slate_blue); + graph.set_text_color(colors::white); + } + + void refresh(graph_reference& graph) override + { + graph.rectangle(true, colors::red); + + ::nana::rectangle r{ graph.size() }; + + r.x = r.right() - 20; + r.y = (r.height - 16) / 2; + r.width = r.height = 16; + + button_.draw(graph, colors::red, colors::white, r, element_state::normal); + x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal); + } + public: + ::nana::string caption; + facade button_; + facade x_icon_; + }; + + class dockarea_caption + : public widget_object < category::widget_tag, dockcaption_dtrigger > + {}; + + class dock_page + : public form + { + public: + dock_page(window host, const rectangle& r, const rectangle & tab_r) + : form(host, r, form::appear::bald<>()) + { + tab_form_.reset(new form(handle(), tab_r, form::appear::bald<>())); + + } + private: + std::unique_ptr tab_form_; + }; + + class dockarea + : public widget_object + { + using base_type = widget_object; + + using factory = std::function(window)>; + + 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) + { + notifier_ = notifier; + host_window_ = parent; + base_type::create(parent, true); + this->caption("dockarea"); + caption_.create(*this, true); + caption_.caption("dockarea-caption"); + + this->events().resized([this](const arg_resized& arg) + { + rectangle r{ 0, 0, arg.width, 20 }; + caption_.move(r); + + if (arg.height > 20) + { + r.y = 20; + if (tabbar_) + { + tabbar_->move({ 0, int(arg.height) - 20, arg.width, 20 }); + r.height = arg.height - 40; + } + else + r.height = arg.height - 20; + } + + + for (auto & pn : panels_) + { + if (pn.widget_ptr) + pn.widget_ptr->move(r); + } + }); + + caption_.events().mouse_down([this](const arg_mouse& arg) + { + if (::nana::mouse::left_button == arg.button) + { + moves_.started = true; + moves_.start_pos = API::cursor_position(); + moves_.start_container_pos = (floating() ? container_->pos() : this->pos()); + API::capture_window(caption_, true); + } + }); + + caption_.events().mouse_move([this](const arg_mouse& arg) + { + if (arg.left_button && moves_.started) + { + auto move_pos = API::cursor_position() - moves_.start_pos; + if (!floating()) + { + if (std::abs(move_pos.x) > 4 || abs(move_pos.y) > 4) + float_away(move_pos); + } + else + { + move_pos += moves_.start_container_pos; + API::move_window(container_->handle(), move_pos); + notifier_->notify_move(); + } + } + }); + + caption_.events().mouse_up([this](const arg_mouse& arg) + { + if ((::nana::mouse::left_button == arg.button) && moves_.started) + { + moves_.started = false; + API::capture_window(caption_, false); + notifier_->notify_move_stopped(); + } + }); + + if (panels_.size() > 1) + tabbar_.reset(new tabbar(*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(pn.widget_ptr->caption()); + tabbar_->relate(pos++, pn.widget_ptr->handle()); + } + } + } + } + + void add_factory(factory && fn) + { + panels_.emplace_back(std::move(fn)); + } + + void float_away(const ::nana::point& move_pos) + { + if (container_) + return; + + API::capture_window(caption_, false); + + rectangle r{ pos() + move_pos, size() }; + container_.reset(new form(host_window_, r.pare_off(-1), form::appear::bald<>())); + drawing dw(container_->handle()); + dw.draw([](paint::graphics& graph) + { + graph.rectangle(false, colors::coral); + }); + + API::set_parent_window(handle(), container_->handle()); + this->move({ 1, 1 }); + + container_->show(); + API::capture_window(caption_, true); + + notifier_->notify_float(); + } + + void dock() + { + API::capture_window(caption_, false); + API::set_parent_window(handle(), host_window_); + container_.reset(); + notifier_->notify_dock(); + } + + bool floating() const + { + return (nullptr != container_); + } + private: + window host_window_{nullptr}; + place_parts::dock_notifier_interface* notifier_{ nullptr }; + std::unique_ptr container_; + dockarea_caption caption_; + std::deque panels_; + std::unique_ptr> tabbar_; + + struct moves + { + bool started{ false }; + ::nana::point start_pos; + ::nana::point start_container_pos; + }moves_; + };//class dockarea + + + //number_t is used for storing a number type variable + //such as integer, real and percent. Essentially, percent is a typo of real. + class number_t + { + public: + enum class kind{ none, integer, real, percent }; + + number_t() + : kind_(kind::none) + { + value_.integer = 0; + } + + void reset() + { + kind_ = kind::none; + value_.integer = 0; + } + + bool is_negative() const + { + switch (kind_) + { + case kind::integer: + return (value_.integer < 0); + case kind::real: + case kind::percent: + return (value_.real < 0); + default: + break; + } + return false; + } + + bool is_none() const + { + return (kind::none == kind_); + } + + bool is_not_none() const + { + return (kind::none != kind_); + } + + kind kind_of() const + { + return kind_; + } + + double get_value(int ref_percent) const + { + switch (kind_) + { + case kind::integer: + return value_.integer; + case kind::real: + return value_.real; + case kind::percent: + return value_.real * ref_percent; + default: + break; + } + return 0; + } + + int integer() const + { + if (kind::integer == kind_) + return value_.integer; + return static_cast(value_.real); + } + + double real() const + { + if (kind::integer == kind_) + return value_.integer; + return value_.real; + } + + void assign(int i) + { + kind_ = kind::integer; + value_.integer = i; + } + + void assign(double d) + { + kind_ = kind::real; + value_.real = d; + } + + void assign_percent(double d) + { + kind_ = kind::percent; + value_.real = d / 100; + } + private: + kind kind_; + union valueset + { + int integer; + double real; + }value_; + };//end class number_t + + + class margin + { + public: + margin& operator=(margin&& rhs) + { + if (this != &rhs) + { + all_edges_ = rhs.all_edges_; + margins_ = std::move(rhs.margins_); + } + return *this; + } + + void clear() + { + all_edges_ = true; + margins_.clear(); + } + + void push(const number_t& v) + { + margins_.emplace_back(v); + } + + void set_value(const number_t& v) + { + clear(); + margins_.emplace_back(v); + } + + void set_array(const std::vector& v) + { + all_edges_ = false; + margins_ = v; + } + + nana::rectangle area(const ::nana::rectangle& field_area) const + { + if (margins_.empty()) + return field_area; + + auto r = field_area; + if (all_edges_) + { + auto px = static_cast(margins_.back().get_value(static_cast(r.width))); + const auto dbl_px = static_cast(px << 1); + r.x += px; + r.width = (r.width < dbl_px ? 0 : r.width - dbl_px); + + r.y += px; + r.height = (r.height < dbl_px ? 0 : r.height - dbl_px); + } + else + { + int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin + switch (margins_.size()) + { + case 0: break; + case 1: //top + it = 0; + break; + case 2://top,bottom and left,right + it = ib = 0; + il = ir = 1; + break; + default: + il = 3; //left + case 3: //top, right, bottom + it = 0; + ir = 1; + ib = 2; + } + + typedef decltype(r.height) px_type; + auto calc = [](px_type a, px_type b) + { + return (a > b ? a - b : 0); + }; + + if (0 == it) //top + { + auto px = static_cast(margins_[it].get_value(static_cast(field_area.height))); + r.y += px; + r.height = calc(r.height, static_cast(px)); + } + + if (-1 != ib) //bottom + { + auto px = static_cast(margins_[ib].get_value(static_cast(field_area.height))); + r.height = calc(r.height, static_cast(px)); + } + + if (-1 != il) //left + { + auto px = static_cast(margins_[il].get_value(static_cast(field_area.width))); + r.x += px; + r.width = calc(r.width, static_cast(px)); + } + + if (-1 != ir) //right + { + auto px = static_cast(margins_[ir].get_value(static_cast(field_area.width))); + r.width = calc(r.width, static_cast(px)); + } + } + return r; + } + private: + bool all_edges_ = true; + std::vector margins_; + };//end class margin + + class repeated_array + { + public: + + //A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted. + repeated_array() = default; + + repeated_array(repeated_array && other) + : repeated_{ other.repeated_ }, + values_(std::move(other.values_)) + { + } + + repeated_array& operator=(repeated_array&& other) + { + if (this != &other) + { + repeated_ = other.repeated_; + other.repeated_ = false; + values_ = std::move(other.values_); + } + return *this; + } + + void assign(std::vector&& c) + { + values_ = std::move(c); + } + + bool empty() const + { + return values_.empty(); + } + + void reset() + { + repeated_ = false; + values_.clear(); + } + + void repeated() + { + repeated_ = true; + } + + void push(const number_t& n) + { + values_.emplace_back(n); + } + + number_t at(std::size_t pos) const + { + if (values_.empty()) + return{}; + + if (repeated_) + pos %= values_.size(); + else if (pos >= values_.size()) + return{}; + + return values_[pos]; + } + private: + bool repeated_ = false; + std::vector values_; + }; + }//end namespace place_parts +}//end namespace nana + +#endif //NANA_GUI_PLACE_PARTS_HPP \ No newline at end of file From c859b86a3f8e2b3dcab3692f29b8829bc44f8957 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 15 Aug 2015 06:57:36 +0800 Subject: [PATCH 03/22] fix an issue of dock place --- include/nana/gui/place.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index 8faedf91..bd50bee7 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -129,10 +129,10 @@ namespace nana template void dock(const std::string& dockname, Args&& ... args) { - dock(dockname, std::bind([](window parent, Args && ... args) + dock(dockname, std::bind([](window parent, Args & ... args) { return std::unique_ptr(new Panel(parent, std::forward(args)...)); - }, std::placeholders::_1, std::forward(args)...)); + }, std::placeholders::_1, args...)); } void dock(const std::string& dockname, std::function(window)> factory); From 4323977908aeca47f7631cf004e81b4a61f9cd75 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 17 Aug 2015 01:37:56 +0800 Subject: [PATCH 04/22] change the implementation of pat::cloneable --- include/nana/gui/element.hpp | 43 ++++---- include/nana/gui/widgets/scroll.hpp | 2 +- include/nana/gui/widgets/tabbar.hpp | 2 +- include/nana/gui/widgets/treebox.hpp | 2 +- include/nana/pat/cloneable.hpp | 142 ++++++++++++++++++++------- source/gui/element.cpp | 43 +++++--- source/gui/widgets/categorize.cpp | 2 +- source/gui/widgets/checkbox.cpp | 2 +- source/gui/widgets/date_chooser.cpp | 2 +- source/gui/widgets/tabbar.cpp | 20 ++-- 10 files changed, 183 insertions(+), 77 deletions(-) diff --git a/include/nana/gui/element.hpp b/include/nana/gui/element.hpp index 9ffa721d..599aa87a 100644 --- a/include/nana/gui/element.hpp +++ b/include/nana/gui/element.hpp @@ -27,19 +27,35 @@ namespace nana namespace element { + namespace detail + { + class element_abstract + { + public: + using graph_reference = ::nana::paint::graphics&; + virtual ~element_abstract() = default; + }; + + class factory_abstract + { + public: + virtual ~factory_abstract() = default; + + virtual void destroy(element_abstract *); + }; + } + class element_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - - virtual ~element_interface() = default; virtual bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) = 0; }; class crook_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; using state = checkstate; struct data @@ -47,25 +63,21 @@ namespace nana state check_state; bool radio; }; - - virtual ~crook_interface() = default; + virtual bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state, const data&) = 0; }; class border_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - - virtual ~border_interface() = default; virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, unsigned weight) = 0; }; class arrow_interface + : public detail::element_abstract { public: - using graph_reference = paint::graphics&; - virtual ~arrow_interface() = default; virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, direction) = 0; }; @@ -74,10 +86,10 @@ namespace nana public: template struct factory_interface + : public detail::factory_abstract { virtual ~factory_interface(){} virtual ElementInterface* create() const = 0; - virtual void destroy(ElementInterface*) const = 0; }; template @@ -85,17 +97,12 @@ namespace nana : public factory_interface { public: - typedef factory_interface interface_type; + using interface_type = factory_interface; ElementInterface * create() const override { return (new Element); } - - void destroy(ElementInterface * p) const override - { - delete p; - } }; void add_arrow(const std::string&, const pat::cloneable>&); diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 54a04de0..9a0690da 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -14,7 +14,7 @@ #define NANA_GUI_WIDGET_SCROLL_HPP #include "widget.hpp" -#include +//#include //deprecated #include namespace nana diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 1160c724..69917ca6 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -14,7 +14,7 @@ #ifndef NANA_GUI_WIDGET_TABBAR_HPP #define NANA_GUI_WIDGET_TABBAR_HPP #include "widget.hpp" -#include "../../paint/gadget.hpp" +//#include "../../paint/gadget.hpp" //deprecated #include #include diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index db15a6cd..cd7a6e3e 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -19,7 +19,7 @@ #define NANA_GUI_WIDGETS_TREEBOX_HPP #include "widget.hpp" #include "detail/compset.hpp" -#include +//#include //deprecated #include "detail/tree_cont.hpp" #include #include diff --git a/include/nana/pat/cloneable.hpp b/include/nana/pat/cloneable.hpp index 281c36f2..3651743c 100644 --- a/include/nana/pat/cloneable.hpp +++ b/include/nana/pat/cloneable.hpp @@ -21,36 +21,38 @@ namespace nana{ namespace pat{ namespace detail { + /* template - class cloneable_interface + class cloneable_interface //deprecated { public: - typedef T interface_t; + using interface_t = T; typedef cloneable_interface cloneable_t; + virtual ~cloneable_interface() = default; virtual interface_t& refer() = 0; virtual const interface_t& refer() const = 0; virtual cloneable_t* clone() const = 0; virtual void self_delete() const = 0; }; + */ - + /* template class cloneable_wrapper - : public cloneable_interface + : public cloneable_interface //deprecated { public: - typedef T value_t; - typedef typename cloneable_interface::interface_t interface_t; + using value_type = T; + using interface_t = typename cloneable_interface::interface_t; - cloneable_wrapper() - {} + cloneable_wrapper() = default; - cloneable_wrapper(const value_t& obj) + cloneable_wrapper(const value_type& obj) :object_(obj) {} - cloneable_wrapper(value_t&& rv) + cloneable_wrapper(value_type&& rv) :object_(std::move(rv)) {} @@ -66,17 +68,17 @@ namespace nana{ namespace pat{ virtual interface_t& refer() override { - return object_; + return value_obj_; } virtual const interface_t& refer() const override { - return object_; + return value_obj_; } virtual cloneable_interface* clone() const override { - return (new cloneable_wrapper(object_)); + return (new cloneable_wrapper{ value_obj_ }); } virtual void self_delete() const override @@ -84,28 +86,87 @@ namespace nana{ namespace pat{ (delete this); } private: - value_t object_; + value_type value_obj_; + }; + */ + + class cloneable_interface + { + public: + virtual ~cloneable_interface() = default; + virtual void * get() = 0; + virtual cloneable_interface* clone() const = 0; + virtual void self_delete() const = 0; }; + struct cloneable_interface_deleter + { + void operator()(cloneable_interface * p) + { + if (p) + p->self_delete(); + } + }; + + template + class cloneable_wrapper + : public cloneable_interface + { + public: + using value_type = T; + + cloneable_wrapper() = default; + + cloneable_wrapper(const value_type& obj) + :value_obj_(obj) + {} + + cloneable_wrapper(value_type&& rv) + :value_obj_(std::move(rv)) + {} + + /* + template + cloneable_wrapper(const U& u) //deprecated + : object_(u) + {} + + template + cloneable_wrapper(U&& u) + : object_(std::move(u)) + {} + */ + private: + //Implement cloneable_interface + virtual void* get() override + { + return &value_obj_; + } + + virtual cloneable_interface* clone() const override + { + return (new cloneable_wrapper{ value_obj_ }); + } + + virtual void self_delete() const override + { + (delete this); + } + private: + value_type value_obj_; + }; }//end namespace detail template class cloneable { using base_t = Base; - using interface_t = detail::cloneable_interface < base_t > ; + using cloneable_interface = detail::cloneable_interface; using const_base_ptr = typename std::conditional::type; using const_base_ref = typename std::conditional::type; - struct deleter - { - void operator()(interface_t * p) - { - if(p) - p->self_delete(); - } - }; + template friend class cloneable; struct inner_bool { @@ -125,16 +186,16 @@ namespace nana{ namespace pat{ template::type* = nullptr> cloneable(T&& t) - : cwrapper_(new detail::cloneable_wrapper::type>::type, base_t>(std::forward(t)), deleter()), - fast_ptr_(&(cwrapper_->refer())) + : cwrapper_(new detail::cloneable_wrapper::type>::type>(std::forward(t)), detail::cloneable_interface_deleter()), + fast_ptr_(reinterpret_cast::type>::type*>(cwrapper_->get())) {} cloneable(const cloneable& r) { if(r.cwrapper_) { - cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), deleter()); - fast_ptr_ = &(cwrapper_->refer()); + cwrapper_ = std::move(std::shared_ptr(r.cwrapper_->clone(), detail::cloneable_interface_deleter{})); + fast_ptr_ = reinterpret_cast(cwrapper_->get()); } } @@ -145,12 +206,27 @@ namespace nana{ namespace pat{ r.fast_ptr_ = nullptr; } + template::value>::type* = nullptr> + cloneable(const cloneable& other) + { + if (other) + { + char* value_ptr = reinterpret_cast(other.cwrapper_->get()); + char* base_ptr = reinterpret_cast(other.fast_ptr_); + + auto ptr_diff = std::distance(base_ptr, value_ptr); + + cwrapper_.reset(other.cwrapper_->clone(), detail::cloneable_interface_deleter{}); + fast_ptr_ = reinterpret_cast(reinterpret_cast(cwrapper_->get()) - ptr_diff); + } + } + cloneable & operator=(const cloneable& r) { if((this != &r) && r.cwrapper_) { - cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), deleter()); - fast_ptr_ = &(cwrapper_->refer()); + cwrapper_ = std::shared_ptr(r.cwrapper_->clone(), detail::cloneable_interface_deleter()); + fast_ptr_ = reinterpret_cast(cwrapper_->get()); } return *this; } @@ -159,10 +235,8 @@ namespace nana{ namespace pat{ { if(this != &r) { - cwrapper_ = r.cwrapper_; + cwrapper_ = std::move(r.cwrapper_); fast_ptr_ = r.fast_ptr_; - - r.cwrapper_.reset(); r.fast_ptr_ = nullptr; } return *this; @@ -204,12 +278,12 @@ namespace nana{ namespace pat{ return (fast_ptr_ ? &inner_bool::true_stand : nullptr); } private: - std::shared_ptr cwrapper_; + std::shared_ptr cwrapper_; base_t * fast_ptr_{nullptr}; }; template - using mutable_cloneable = cloneable < T, true > ; + using mutable_cloneable = cloneable; }//end namespace pat }//end namespace nana diff --git a/source/gui/element.cpp b/source/gui/element.cpp index cbccebed..0263338a 100644 --- a/source/gui/element.cpp +++ b/source/gui/element.cpp @@ -28,6 +28,14 @@ namespace nana //Element definitions namespace element { + namespace detail + { + void factory_abstract::destroy(element_abstract* ptr) + { + delete ptr; + } + } + class crook : public crook_interface { @@ -592,8 +600,9 @@ namespace nana class element_object : nana::noncopyable, nana::nonmovable { - typedef ElementInterface element_t; - typedef pat::cloneable> factory_interface; + using element_type = ElementInterface; + using factory_interface = pat::cloneable>; //deprecated + //using factory_interface = pat::cloneable; public: ~element_object() @@ -608,7 +617,8 @@ namespace nana auto keep_e = element_ptr_; factory_ = rhs; - element_ptr_ = factory_->create(); + element_ptr_ = factory_->create(); //deprecated + //element_ptr_ = static_cast(static_cast&>(*factory_).create()); if(nullptr == factory_ || nullptr == element_ptr_) { @@ -624,22 +634,27 @@ namespace nana spare_.emplace_back(keep_e, keep_f); } - element_t * const * cite() const + element_type * const * cite() const { return &element_ptr_; } private: factory_interface factory_; //Keep the factory for destroying the element - element_t * element_ptr_{nullptr}; - std::vector> spare_; + element_type * element_ptr_{nullptr}; + std::vector> spare_; }; class element_manager : nana::noncopyable, nana::nonmovable { - //VC2012 does not support alias declaration. - //template using factory_interface = element::provider::factory_interface; - + /* + template //deprecated + struct item + { + element_object * employee; + std::map>> table; + }; + */ template struct item { @@ -1047,19 +1062,21 @@ namespace nana namespace element { + using brock = ::nana::detail::bedrock; + void set_bground(const char* name, const pat::cloneable& obj) { - detail::bedrock::instance().get_element_store().bground(name, obj); + brock::instance().get_element_store().bground(name, obj); } void set_bground(const char* name, pat::cloneable && obj) { - detail::bedrock::instance().get_element_store().bground(name, std::move(obj)); + brock::instance().get_element_store().bground(name, std::move(obj)); } //class cite cite_bground::cite_bground(const char* name) - : ref_ptr_(detail::bedrock::instance().get_element_store().bground(name)) + : ref_ptr_(brock::instance().get_element_store().bground(name)) { } @@ -1073,7 +1090,7 @@ namespace nana void cite_bground::set(const char* name) { holder_.reset(); - ref_ptr_ = detail::bedrock::instance().get_element_store().bground(name); + ref_ptr_ = brock::instance().get_element_store().bground(name); } bool cite_bground::draw(graph_reference dst, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const nana::rectangle& r, element_state state) diff --git a/source/gui/widgets/categorize.cpp b/source/gui/widgets/categorize.cpp index 4351a719..20afdfbf 100644 --- a/source/gui/widgets/categorize.cpp +++ b/source/gui/widgets/categorize.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +//#include //deprecated #include #include diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 49626834..608f3fa5 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -11,7 +11,7 @@ */ #include -#include +//#include //deprecated #include #include #include diff --git a/source/gui/widgets/date_chooser.cpp b/source/gui/widgets/date_chooser.cpp index 7da5474c..a56a3202 100644 --- a/source/gui/widgets/date_chooser.cpp +++ b/source/gui/widgets/date_chooser.cpp @@ -12,7 +12,7 @@ #include #include -#include +//#include //deprecated #include #include diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 6532bf6e..c4a0e63b 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -112,12 +112,16 @@ namespace nana clr = { 0xF0, 0xF0, 0xF0 }; } graph.rectangle(r, true, bgcolor_); - nana::paint::gadget::cross(graph, x, y, 14, 6, clr); + facade cross; + cross.draw(graph, {}, clr, { x, y, 14, 6 }, element_state::normal); + //nana::paint::gadget::cross(graph, x, y, 14, 6, clr); //deprecated } virtual void close(graph_reference graph, const nana::rectangle& r, state_t sta) { - nana::paint::gadget::close_16_pixels(graph, r.x + (r.width - 16) / 2, r.y + (r.height - 16) / 2, 1, colors::black); + //nana::paint::gadget::close_16_pixels(graph, r.x + (r.width - 16) / 2, r.y + (r.height - 16) / 2, 1, colors::black); //deprecated + facade x_icon; + x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); if(item_renderer::highlight == sta) graph.rectangle(r, false, {0xa0, 0xa0, 0xa0}); } @@ -140,24 +144,28 @@ namespace nana else if (!active) clr = ::nana::color{ 0x92, 0x99, 0xA4 }; - gadget::close_16_pixels(graph, r.x - (16 - r.width) / 2, r.y - (16 - r.height) / 2, 1, clr); + + //gadget::close_16_pixels(graph, r.x - (16 - r.width) / 2, r.y - (16 - r.height) / 2, 1, clr); //deprecated + facade x_icon; + x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); + } virtual void back(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; + //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::west); } virtual void next(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; + //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::east); } virtual void list(graph_reference graph, const nana::rectangle& r, state_t sta) { - using namespace nana::paint::gadget; + //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::south); } private: From 42443dcafd47be64efb59f884a4a73b1a29e4976 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 20 Aug 2015 01:09:29 +0800 Subject: [PATCH 05/22] remove paint::gadget --- build/codeblocks/nana.cbp | 1 - build/codeblocks/nana.depend | 630 ++++++++++++++++++ build/codeblocks/nana.layout | 143 ++-- build/vc2013/nana.vcxproj | 7 +- build/vc2013/nana.vcxproj.filters | 9 +- build/vc2015/nana.sln | 20 +- build/vc2015/nana.vcxproj | 89 +-- build/vc2015/nana.vcxproj.filters | 503 +++++++------- extrlib/readme (2).txt | 1 - extrlib/readme.txt | 2 + include/nana/gui/widgets/scroll.hpp | 3 +- include/nana/gui/widgets/tabbar.hpp | 3 +- include/nana/gui/widgets/treebox.hpp | 1 - include/nana/paint/gadget.hpp | 33 - include/nana/pat/cloneable.hpp | 81 --- source/gui/detail/native_window_interface.cpp | 26 - source/gui/element.cpp | 16 +- source/gui/msgbox.cpp | 6 +- source/gui/place.cpp | 81 +-- source/gui/widgets/categorize.cpp | 1 - source/gui/widgets/checkbox.cpp | 1 - source/gui/widgets/date_chooser.cpp | 1 - source/gui/widgets/menu.cpp | 1 - source/gui/widgets/skeletons/text_editor.cpp | 6 +- source/gui/widgets/tabbar.cpp | 10 +- source/paint/gadget.cpp | 108 --- source/paint/graphics.cpp | 4 +- 27 files changed, 1024 insertions(+), 763 deletions(-) delete mode 100644 extrlib/readme (2).txt delete mode 100644 include/nana/paint/gadget.hpp delete mode 100644 source/paint/gadget.cpp diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp index fb1a1b55..9302ebd6 100644 --- a/build/codeblocks/nana.cbp +++ b/build/codeblocks/nana.cbp @@ -102,7 +102,6 @@ - diff --git a/build/codeblocks/nana.depend b/build/codeblocks/nana.depend index a2318fdf..f7f24eaa 100644 --- a/build/codeblocks/nana.depend +++ b/build/codeblocks/nana.depend @@ -537,3 +537,633 @@ 1399002439 source:d:\privates\nana\release\nana.cpp11\source\gui\detail\element_store.cpp +1363362719 source:d:\git.repo\nana\source\any.cpp + + +1362509572 source:d:\git.repo\nana\source\audio\detail\audio_device.cpp + + + + + + + +1439496157 source:d:\git.repo\nana\source\audio\detail\audio_stream.cpp + + + +1362509721 source:d:\git.repo\nana\source\audio\detail\buffer_preparation.cpp + + + +1353253406 source:d:\git.repo\nana\source\audio\player.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\basic_types.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\charset.cpp + + + + + + + + +1439496157 source:d:\git.repo\nana\source\datetime.cpp + + + + + +1439496157 source:d:\git.repo\nana\source\deploy.cpp + + + + + + + +1439496157 source:d:\git.repo\nana\source\detail\platform_spec_selector.cpp + + "win32/platform_spec.cpp" + "linux_X11/platform_spec.cpp" + +1439496157 d:\git.repo\nana\source\detail\win32\platform_spec.cpp + + + + + +1439496157 d:\git.repo\nana\source\detail\linux_x11\platform_spec.cpp + + + + + + + + + + + + + "msg_dispatcher.hpp" + +1439496157 d:\git.repo\nana\source\detail\linux_x11\msg_dispatcher.hpp + + + + + + + + + + +1365203880 source:d:\git.repo\nana\source\exceptions.cpp + + +1365203878 source:d:\git.repo\nana\source\filesystem\file_iterator.cpp + + +1365203878 source:d:\git.repo\nana\source\filesystem\fs_utility.cpp + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\animation.cpp + + + + + + + + + + + + + + +1423350892 source:d:\git.repo\nana\source\gui\basis.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\basic_window.cpp + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\bedrock_pi.cpp + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\bedrock_selector.cpp + + "win32/bedrock.cpp" + "linux_X11/bedrock.cpp" + +1439496157 d:\git.repo\nana\source\gui\detail\win32\bedrock.cpp + + + + + + + + + + + + + + +1439496157 d:\git.repo\nana\source\gui\detail\linux_x11\bedrock.cpp + + + + + + + + + + +1423350892 source:d:\git.repo\nana\source\gui\detail\color_schemes.cpp + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\drawer.cpp + + + + + + + + +1408986718 source:d:\git.repo\nana\source\gui\detail\element_store.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\events_operation.cpp + + +1439828940 source:d:\git.repo\nana\source\gui\detail\native_window_interface.cpp + + + + + + + "../../paint/detail/image_ico.hpp" + + + +1439496158 d:\git.repo\nana\source\paint\detail\image_ico.hpp + + +1439496157 source:d:\git.repo\nana\source\gui\detail\window_layout.cpp + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\detail\window_manager.cpp + + + + + + + + + + + +1439746409 source:d:\git.repo\nana\source\gui\dragger.cpp + + +1423350892 source:d:\git.repo\nana\source\gui\drawing.cpp + + + + +1439496157 source:d:\git.repo\nana\source\gui\effects.cpp + + + +1439829040 source:d:\git.repo\nana\source\gui\element.cpp + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\filebox.cpp + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\layout_utility.cpp + + +1439496157 source:d:\git.repo\nana\source\gui\msgbox.cpp + + + + + + + + + + + + + + + + + + +1439496157 source:d:\git.repo\nana\source\gui\notifier.cpp + + + + + + + + + + + + +1439746410 source:d:\git.repo\nana\source\gui\programming_interface.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\screen.cpp + + + + + + + +1415011766 source:d:\git.repo\nana\source\gui\state_cursor.cpp + + + + +1439496158 source:d:\git.repo\nana\source\gui\timer.cpp + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\tooltip.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\button.cpp + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\categorize.cpp + + + + + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\checkbox.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\combox.cpp + + + + + + + + + +1439829040 source:d:\git.repo\nana\source\gui\widgets\date_chooser.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\float_listbox.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\form.cpp + + +1408985395 source:d:\git.repo\nana\source\gui\widgets\frame.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\group.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\label.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\listbox.cpp + + + + + + + + + + + + +1439828820 source:d:\git.repo\nana\source\gui\widgets\menu.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\menubar.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\panel.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\picture.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\progress.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\scroll.cpp + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\skeletons\text_editor.cpp + + + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\slider.cpp + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\spinbox.cpp + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\textbox.cpp + + + + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\toolbar.cpp + + + + +1439496158 source:d:\git.repo\nana\source\gui\widgets\treebox.cpp + + + + + + + +1439746410 source:d:\git.repo\nana\source\gui\widgets\widget.cpp + + + + +1408984042 source:d:\git.repo\nana\source\gui\wvl.cpp + + +1425221155 source:d:\git.repo\nana\source\internationalization.cpp + + + + + + + +1423350893 source:d:\git.repo\nana\source\paint\detail\image_process_provider.cpp + + + +1439496158 source:d:\git.repo\nana\source\paint\detail\native_paint_interface.cpp + + + + + + + +1439746289 source:d:\git.repo\nana\source\paint\graphics.cpp + + + + + + + + + + + +1439496158 source:d:\git.repo\nana\source\paint\image.cpp + + + + + + + + + "detail/image_png.hpp" + "detail/image_bmp.hpp" + "detail/image_ico.hpp" + +1439687843 d:\git.repo\nana\source\paint\detail\image_png.hpp + + + + + + +1439496158 d:\git.repo\nana\source\paint\detail\image_bmp.hpp + + + +1376313789 source:d:\git.repo\nana\source\paint\image_process_selector.cpp + + +1439496158 source:d:\git.repo\nana\source\paint\pixel_buffer.cpp + + + + + + + +1423350893 source:d:\git.repo\nana\source\paint\text_renderer.cpp + + + + + +1439496158 source:d:\git.repo\nana\source\system\dataexch.cpp + + + + + + + + + +1387007333 source:d:\git.repo\nana\source\system\platform.cpp + + + + + + + + +1365203879 source:d:\git.repo\nana\source\system\shared_wrapper.cpp + + + + + + +1342280997 source:d:\git.repo\nana\source\system\timepiece.cpp + + + + + +1386165989 source:d:\git.repo\nana\source\threads\pool.cpp + + + + + + + + + + + + + +1365203748 source:d:\git.repo\nana\source\traits.cpp + + +1439496158 source:d:\git.repo\nana\source\unicode_bidi.cpp + + +1439830958 source:d:\git.repo\nana\source\gui\widgets\tabbar.cpp + + + + + + + + diff --git a/build/codeblocks/nana.layout b/build/codeblocks/nana.layout index 92b352dc..587b86f1 100644 --- a/build/codeblocks/nana.layout +++ b/build/codeblocks/nana.layout @@ -1,24 +1,9 @@ - + - - - - - - - - - - - - - - - - + @@ -26,9 +11,9 @@ - + - + @@ -36,66 +21,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - @@ -126,29 +71,89 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj index 610054bc..7ed1c2f9 100644 --- a/build/vc2013/nana.vcxproj +++ b/build/vc2013/nana.vcxproj @@ -243,7 +243,6 @@ - @@ -277,8 +276,8 @@ - - + + @@ -383,4 +382,4 @@ - + \ No newline at end of file diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters index 6ade66c7..e58eb56b 100644 --- a/build/vc2013/nana.vcxproj.filters +++ b/build/vc2013/nana.vcxproj.filters @@ -119,7 +119,7 @@ Source Files\nana\detail\win32 - + Source Files\nana\filesystem @@ -261,9 +261,6 @@ Source Files\nana\paint\detail - - Source Files\nana\paint - Source Files\nana\paint @@ -645,7 +642,7 @@ Header Files\extrlib - + Header Files\filesystem @@ -719,4 +716,4 @@ Header Files\gui\widgets - + \ No newline at end of file diff --git a/build/vc2015/nana.sln b/build/vc2015/nana.sln index eab31ab5..6de06997 100644 --- a/build/vc2015/nana.sln +++ b/build/vc2015/nana.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{25B21068-491B-4A9F-B99F-6C27BF31BAAD}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nana", "nana.vcxproj", "{98091380-2EC4-44B4-82A2-F0A6393BA908}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,14 +13,14 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.ActiveCfg = Debug|x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x64.Build.0 = Debug|x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x86.ActiveCfg = Debug|Win32 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Debug|x86.Build.0 = Debug|Win32 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.ActiveCfg = Release|x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x64.Build.0 = Release|x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x86.ActiveCfg = Release|Win32 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD}.Release|x86.Build.0 = Release|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x64.ActiveCfg = Debug|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x64.Build.0 = Debug|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x86.ActiveCfg = Debug|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Debug|x86.Build.0 = Debug|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x64.ActiveCfg = Release|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x64.Build.0 = Release|x64 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x86.ActiveCfg = Release|Win32 + {98091380-2EC4-44B4-82A2-F0A6393BA908}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/vc2015/nana.vcxproj b/build/vc2015/nana.vcxproj index d4f7f5d3..9b0433bd 100644 --- a/build/vc2015/nana.vcxproj +++ b/build/vc2015/nana.vcxproj @@ -5,24 +5,24 @@ Debug Win32 - - Debug - x64 - Release Win32 + + Debug + x64 + Release x64 - {25B21068-491B-4A9F-B99F-6C27BF31BAAD} + {98091380-2EC4-44B4-82A2-F0A6393BA908} Win32Proj nana - 8.1 + 8.1 @@ -31,12 +31,6 @@ v140 Unicode - - StaticLibrary - true - v140 - Unicode - StaticLibrary false @@ -44,6 +38,12 @@ true Unicode + + StaticLibrary + true + v140 + Unicode + StaticLibrary false @@ -54,46 +54,30 @@ - - + - + - + + + + - - ../bin/ - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ + + ../../include;$(IncludePath) + ..\bin\vc2015\ + lib$(ProjectName) - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - ../bin/ - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ - - - ../bin/ - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ - - - ..\..\include;$(IncludePath) - ..\..\source;$(VC_SourcePath); - ../bin/ - $(ProjectName)_$(PlatformToolset)_$(Configuration)_$(PlatformShortName) - ..\..\..\temp\$(ProjectName)\$(PlatformToolset)_$(Configuration)_$(PlatformShortName)\ + ../../include;$(IncludePath) + ..\bin\vc2015\ + lib$(ProjectName)d @@ -102,17 +86,11 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebug - true - false Windows true - - $(TargetPath) - @@ -120,15 +98,14 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreadedDebug + _DEBUG;_LIB;%(PreprocessorDefinitions) Windows true - $(TargetPath) + $(OutDir)$(TargetName)$(TargetExt) @@ -140,8 +117,6 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - true Windows @@ -149,9 +124,6 @@ true true - - $(TargetPath) - @@ -161,8 +133,7 @@ MaxSpeed true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded + NDEBUG;_LIB;%(PreprocessorDefinitions) Windows @@ -171,7 +142,7 @@ true - $(TargetPath) + $(OutDir)$(TargetName)$(TargetExt) @@ -244,7 +215,6 @@ - @@ -252,7 +222,6 @@ - diff --git a/build/vc2015/nana.vcxproj.filters b/build/vc2015/nana.vcxproj.filters index 81495341..42482ba2 100644 --- a/build/vc2015/nana.vcxproj.filters +++ b/build/vc2015/nana.vcxproj.filters @@ -13,298 +13,289 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - {b0bd11b1-bcbb-4e05-885e-44295bc1a7bb} + + {9630500a-5aca-4625-a11b-1ba83a93895c} - - {aab16aa3-c8d4-4495-8606-1b21ae739ee5} + + {d43db913-0472-45f6-889e-b147a7b3eb7e} - - {c395f107-7102-415b-a019-54e7cf3575af} + + {4e91af62-8e45-41d5-8bb9-1deb850de937} - - {e2569be2-9e68-477d-8b59-e248595de6c7} + + {c575e702-d7d3-48d2-a465-30e51ca72f8d} - - {52ed7f8e-fa48-495e-af1f-4df013205a35} + + {e1fbd69a-2a82-419e-854a-0b5dbd0e0237} - - {87d14798-9015-4162-b9ab-72c741cff063} + + {295ba47e-9dc7-4375-82bc-443b767eb87d} - - {4f8e7d23-9fe1-4409-bb03-2bd0809e606b} + + {b0854b25-60fc-47e2-a9df-5e4f2d28065c} - - {85c9c1bb-d87b-4481-bf3c-7425f680a12d} + + {b3023f5e-2759-409d-b6e8-5ef2fe6601ae} - - {8058b530-86ec-4d72-890d-345aa30db056} + + {2ce139f3-ef8e-48b7-a82a-68003eac75da} - - {87b124cb-408d-460b-a81b-8a788bbae0d9} + + {b9f9a5a8-fd1a-4b99-b530-d8a4c45e62ec} - - {b10db2f1-0542-421a-9e1d-4357e3be5f68} + + {4b04c197-4a1e-41f9-bfa3-d82c18bcad51} - - {59f186c8-f5f8-4499-8e19-f278d4754220} + + {cd6e7f3f-fe5b-44c6-ae8d-15554f926055} - - {5acf1733-47b2-4872-a105-66c7ad15cd39} + + {60f588f2-bdb9-4b1d-9e23-40a73f327283} - - {a81fa10e-1274-44e0-92a0-434fa28f89ae} - - - {e95b4a72-643f-4416-af95-b0bbaf7f0c57} + + {53feb93f-2b86-4bf5-b2f3-f60ef1bbbf76} - - Source Files\nana\audio\detail - - - Source Files\nana\audio\detail - - - Source Files\nana\audio\detail - - - Source Files\nana\audio - - - Source Files\nana\detail\win32 - - - Source Files\nana\filesystem - - - Source Files\nana\filesystem - - - Source Files\nana\gui\detail\win32 - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\widgets\skeletons - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui\widgets - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\gui - - - Source Files\nana\paint\detail - - - Source Files\nana\paint\detail - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\paint - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\system - - - Source Files\nana\threads - - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana + Source Files - Source Files\nana - - - Source Files\nana - - - Source Files\nana - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui\detail - - - Source Files\nana\gui - - - Source Files\nana\gui + Source Files - Source Files\nana + Source Files - - Source Files\nana\gui\detail + + Source Files - - Source Files\nana\gui + + Source Files - - Source Files\nana\gui\widgets + + Source Files\audio\detail + + + Source Files\audio\detail + + + Source Files\audio\detail + + + Source Files\audio + + + Source Files\detail\win32 + + + Source Files\filesystem - Source Files\nana\filesystem + Source Files\filesystem + + + Source Files\filesystem + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail + + + Source Files\gui\detail\win32 + + + Source Files\gui\widgets\skeletons + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets - Source Files\nana\gui\widgets + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui\widgets + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\gui + + + Source Files\threads + + + Source Files\system + + + Source Files\system + + + Source Files\system + + + Source Files\paint\detail + + + Source Files\paint\detail + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint + + + Source Files\paint \ No newline at end of file diff --git a/extrlib/readme (2).txt b/extrlib/readme (2).txt deleted file mode 100644 index 84359ae5..00000000 --- a/extrlib/readme (2).txt +++ /dev/null @@ -1 +0,0 @@ -The libpng.a is for MinGW(Not linux), and other .lib files are for VS2013 \ No newline at end of file diff --git a/extrlib/readme.txt b/extrlib/readme.txt index e5edb297..c54ee0ad 100644 --- a/extrlib/readme.txt +++ b/extrlib/readme.txt @@ -1 +1,3 @@ +The libpng.a is for MinGW(Not linux), and other .lib files are for VS2013 + You can download the precompiled external libraries at http://sourceforge.net/projects/nanapro/files/extrlib/ \ No newline at end of file diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 9a0690da..917a5da5 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -14,7 +14,6 @@ #define NANA_GUI_WIDGET_SCROLL_HPP #include "widget.hpp" -//#include //deprecated #include namespace nana @@ -444,7 +443,7 @@ namespace nana /// @return true if the vlaue is changed. bool make_page_scroll(bool forward) { - return this->make_step(forward, range() - 1); + return this->make_step(forward, static_cast(range() - 1)); } };//end class scroll }//end namespace nana diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 69917ca6..02722d96 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -14,7 +14,6 @@ #ifndef NANA_GUI_WIDGET_TABBAR_HPP #define NANA_GUI_WIDGET_TABBAR_HPP #include "widget.hpp" -//#include "../../paint/gadget.hpp" //deprecated #include #include @@ -30,7 +29,7 @@ namespace nana T & value; arg_tabbar(tabbar& wdg, T& v) - : widget{ wdg }, value{ v } + : widget(wdg), value{ v } {} }; diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index cd7a6e3e..5e317781 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -19,7 +19,6 @@ #define NANA_GUI_WIDGETS_TREEBOX_HPP #include "widget.hpp" #include "detail/compset.hpp" -//#include //deprecated #include "detail/tree_cont.hpp" #include #include diff --git a/include/nana/paint/gadget.hpp b/include/nana/paint/gadget.hpp deleted file mode 100644 index d64c9293..00000000 --- a/include/nana/paint/gadget.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Graphics Gadget Implementation - * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/paint/gadget.hpp - */ - -#ifndef NANA_PAINT_GADGET_HPP -#define NANA_PAINT_GADGET_HPP -#include "graphics.hpp" -#include "image.hpp" -#include - -namespace nana -{ -namespace paint -{ -namespace gadget -{ - void close_16_pixels(::nana::paint::graphics&, int x, int y, unsigned style, const color&); - void cross(::nana::paint::graphics&, int x, int y, unsigned size, unsigned thickness, const nana::color&); - -}//end namespace gadget - -}//end namespace paint -}//end namespace nana - -#endif diff --git a/include/nana/pat/cloneable.hpp b/include/nana/pat/cloneable.hpp index 3651743c..16a9dfcd 100644 --- a/include/nana/pat/cloneable.hpp +++ b/include/nana/pat/cloneable.hpp @@ -21,75 +21,6 @@ namespace nana{ namespace pat{ namespace detail { - /* - template - class cloneable_interface //deprecated - { - public: - using interface_t = T; - typedef cloneable_interface cloneable_t; - - virtual ~cloneable_interface() = default; - virtual interface_t& refer() = 0; - virtual const interface_t& refer() const = 0; - virtual cloneable_t* clone() const = 0; - virtual void self_delete() const = 0; - }; - */ - - /* - template - class cloneable_wrapper - : public cloneable_interface //deprecated - { - public: - using value_type = T; - using interface_t = typename cloneable_interface::interface_t; - - cloneable_wrapper() = default; - - cloneable_wrapper(const value_type& obj) - :object_(obj) - {} - - cloneable_wrapper(value_type&& rv) - :object_(std::move(rv)) - {} - - template - cloneable_wrapper(const U& u) - : object_(u) - {} - - template - cloneable_wrapper(U& u) - :object_(u) - {} - - virtual interface_t& refer() override - { - return value_obj_; - } - - virtual const interface_t& refer() const override - { - return value_obj_; - } - - virtual cloneable_interface* clone() const override - { - return (new cloneable_wrapper{ value_obj_ }); - } - - virtual void self_delete() const override - { - (delete this); - } - private: - value_type value_obj_; - }; - */ - class cloneable_interface { public: @@ -124,18 +55,6 @@ namespace nana{ namespace pat{ cloneable_wrapper(value_type&& rv) :value_obj_(std::move(rv)) {} - - /* - template - cloneable_wrapper(const U& u) //deprecated - : object_(u) - {} - - template - cloneable_wrapper(U&& u) - : object_(std::move(u)) - {} - */ private: //Implement cloneable_interface virtual void* get() override diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index d706b43d..6dd9a583 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -542,32 +542,6 @@ namespace nana{ return false; } - /* - bool native_interface::window_icon(native_window_type wd, const paint::image& big_icon, const paint::image& small_icon) //deprecated - { -#if defined(NANA_WINDOWS) - HICON h_big_icon = paint::image_accessor::icon(big_icon); - HICON h_small_icon = paint::image_accessor::icon(small_icon); - if (h_big_icon || h_small_icon) - { - nana::detail::platform_spec::instance().keep_window_icon(wd, (!big_icon.empty() ? big_icon : small_icon)); - if (h_big_icon) { - ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_BIG, reinterpret_cast(h_big_icon)); - } - if (h_small_icon) { - ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_SMALL, reinterpret_cast(h_small_icon)); - } - return true; - } -#elif defined(NANA_X11) - return window_icon(wd, big_icon); -#endif - return false; - } - */ - - - void native_interface::activate_owner(native_window_type wd) { #if defined(NANA_WINDOWS) diff --git a/source/gui/element.cpp b/source/gui/element.cpp index 0263338a..4271a4d2 100644 --- a/source/gui/element.cpp +++ b/source/gui/element.cpp @@ -272,7 +272,7 @@ namespace nana bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, unsigned weight) { graph.rectangle(r, false, static_cast((element_state::focus_hovered == estate || element_state::focus_normal == estate) ? 0x0595E2 : 0x999A9E)); - graph.rectangle(::nana::rectangle{r}.pare_off(1), false, bgcolor); + graph.rectangle(::nana::rectangle(r).pare_off(1), false, bgcolor); return true; } }; @@ -601,8 +601,7 @@ namespace nana : nana::noncopyable, nana::nonmovable { using element_type = ElementInterface; - using factory_interface = pat::cloneable>; //deprecated - //using factory_interface = pat::cloneable; + using factory_interface = pat::cloneable; public: ~element_object() @@ -617,8 +616,7 @@ namespace nana auto keep_e = element_ptr_; factory_ = rhs; - element_ptr_ = factory_->create(); //deprecated - //element_ptr_ = static_cast(static_cast&>(*factory_).create()); + element_ptr_ = static_cast(static_cast&>(*factory_).create()); if(nullptr == factory_ || nullptr == element_ptr_) { @@ -647,14 +645,6 @@ namespace nana class element_manager : nana::noncopyable, nana::nonmovable { - /* - template //deprecated - struct item - { - element_object * employee; - std::map>> table; - }; - */ template struct item { diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index c514f124..44addaa6 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -959,7 +959,7 @@ namespace nana int inputbox::date::month() const { if (!impl_->wdg_month.empty()) - return impl_->wdg_month.option() + 1; + return static_cast(impl_->wdg_month.option()) + 1; return impl_->month; } @@ -1028,7 +1028,7 @@ namespace nana impl->wdg_day.events().destroy.connect_unignorable([impl] { impl->day = impl->wdg_day.to_int(); - impl->month = impl->wdg_month.option() + 1; + impl->month = static_cast(impl->wdg_month.option()) + 1; }); impl->wdg_year.events().destroy.connect_unignorable([impl] @@ -1040,7 +1040,7 @@ namespace nana { auto month = impl->wdg_month.option() + 1; auto year = impl->wdg_year.to_int(); - int days = ::nana::date::month_days(year, month); + int days = ::nana::date::month_days(year, static_cast(month)); auto day = impl->wdg_day.to_int(); impl->wdg_day.range(1, days, 1); //It resets the current value of wdg_day diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 7a6325ef..aa1f02f8 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -24,6 +24,8 @@ #include #include //numeric_limits +#include //std::abs +#include //std::memset #include "place_parts.hpp" @@ -93,7 +95,13 @@ namespace nana std::string pos_str() const { +#ifdef NANA_MINGW + std::stringstream ss; + ss<(limit_px(_m_leaf_left(), left_px, area_px)); _m_leaf_left()->weight.assign_percent(imd_rate * left_px); @@ -1692,7 +1699,6 @@ namespace nana }); - //indicator_.dock_area->z_order(nullptr, ::nana::z_order_action::top); //deprecated API::bring_top(indicator_.dock_area->handle(), false); indicator_.dock_area->show(); } @@ -2112,7 +2118,6 @@ namespace nana } field_gather * attached_field = nullptr; - field_dock* attached_dock = nullptr; if (name.size()) { //find the field with specified name. @@ -2154,11 +2159,6 @@ namespace nana } break; case token::dock: - //deprecated - // - //if (name.empty()) - // throw std::invalid_argument("nana.place: dock must have a name."); - div.reset(new div_dock(std::move(name), this)); break; default: @@ -2258,7 +2258,7 @@ namespace nana check_fn(div); } - //connect the field/dock with div object, + //connect the field/dock with div object, void place::implement::connect(division* start) { if (!start) @@ -2307,7 +2307,7 @@ namespace nana div->field->attached = div; } } - + } for (auto & child : div->children) @@ -2392,33 +2392,6 @@ namespace nana //if name violate the naming convention. place_parts::check_field_name(name); - /* //deprecated - implement::division * div_ptr = nullptr; - implement::field_gather * field_ptr = nullptr; - { - auto i = impl_->fields.find(name); - if (i != impl_->fields.end()) - field_ptr = i->second; - } - - if (field_ptr) - { - //remove the existing div object - div_ptr = field_ptr->attached; - } - else - div_ptr = impl_->search_div_name(impl_->root_division.get(), name); - - if (nullptr == div_ptr) - { - std::string what = "nana::place: field '"; - what += name; - what += "' is not found."; - - throw std::invalid_argument(what); - } - */ - auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name); if (!div_ptr) { @@ -2434,7 +2407,6 @@ namespace nana implement::division * div_owner = div_ptr->div_owner; implement::division * div_next = div_ptr->div_next; - implement::division * div_bro = nullptr; if (div_owner) { for (auto i = div_owner->children.begin(); i != div_owner->children.end(); ++i) @@ -2444,7 +2416,6 @@ namespace nana replaced = &(*i); break; } - div_bro = i->get(); } } else @@ -2458,7 +2429,6 @@ namespace nana auto modified = impl_->scan_div(tknizer); auto modified_ptr = modified.get(); modified_ptr->name = name; - //modified_ptr->field = field_ptr; replaced->swap(modified); @@ -2468,33 +2438,6 @@ namespace nana modified_ptr->div_owner = div_owner; modified_ptr->div_next = div_next; - //if (field_ptr) - // field_ptr->attached = modified_ptr; - /* - std::function attach; - attach = [this, &attach](implement::division* div) - { - if (!div->name.empty()) - { - auto i = impl_->fields.find(div->name); - if (impl_->fields.end() != i) - { - if (i->second->attached != div) - { - i->second->attached = div; - div->field = i->second; - } - } - } - - for (auto& child : div->children) - { - attach(child.get()); - } - }; - - attach(impl_->root_division.get()); - */ } catch (...) { @@ -2538,7 +2481,7 @@ namespace nana void place::field_visible(const char* name, bool vsb) { if (!name) name = ""; - + //May throw std::invalid_argument place_parts::check_field_name(name); diff --git a/source/gui/widgets/categorize.cpp b/source/gui/widgets/categorize.cpp index 20afdfbf..92fb9743 100644 --- a/source/gui/widgets/categorize.cpp +++ b/source/gui/widgets/categorize.cpp @@ -14,7 +14,6 @@ #include #include #include -//#include //deprecated #include #include diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 608f3fa5..582803cc 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -11,7 +11,6 @@ */ #include -//#include //deprecated #include #include #include diff --git a/source/gui/widgets/date_chooser.cpp b/source/gui/widgets/date_chooser.cpp index a56a3202..b46b29a5 100644 --- a/source/gui/widgets/date_chooser.cpp +++ b/source/gui/widgets/date_chooser.cpp @@ -12,7 +12,6 @@ #include #include -//#include //deprecated #include #include diff --git a/source/gui/widgets/menu.cpp b/source/gui/widgets/menu.cpp index d42f2b79..fd206764 100644 --- a/source/gui/widgets/menu.cpp +++ b/source/gui/widgets/menu.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index e568fbee..29e5a181 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -2250,7 +2250,7 @@ namespace nana{ namespace widgets break; case keyboard::os_end: if (caret.y != nlines - 1) { - caret.y = nlines - 1; + caret.y = static_cast(nlines - 1); changed = true; } break; @@ -2265,7 +2265,7 @@ namespace nana{ namespace widgets }else { if (caret.y != 0) { --caret.y; - caret.x = textbase_.getline(caret.y).size(); + caret.x = static_cast(textbase_.getline(caret.y).size()); changed = true; } } @@ -2309,7 +2309,7 @@ namespace nana{ namespace widgets break; case keyboard::os_end: if (caret.x < lnsz) { - caret.x = lnsz; + caret.x = static_cast(lnsz); changed = true; } break; diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index c4a0e63b..624b5db1 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -97,7 +97,7 @@ namespace nana { int x = r.x + (static_cast(r.width) - 14) / 2; int y = r.y + (static_cast(r.height) - 14) / 2; - + ::nana::color clr; switch(sta) @@ -114,12 +114,10 @@ namespace nana graph.rectangle(r, true, bgcolor_); facade cross; cross.draw(graph, {}, clr, { x, y, 14, 6 }, element_state::normal); - //nana::paint::gadget::cross(graph, x, y, 14, 6, clr); //deprecated } virtual void close(graph_reference graph, const nana::rectangle& r, state_t sta) { - //nana::paint::gadget::close_16_pixels(graph, r.x + (r.width - 16) / 2, r.y + (r.height - 16) / 2, 1, colors::black); //deprecated facade x_icon; x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); if(item_renderer::highlight == sta) @@ -144,8 +142,6 @@ namespace nana else if (!active) clr = ::nana::color{ 0x92, 0x99, 0xA4 }; - - //gadget::close_16_pixels(graph, r.x - (16 - r.width) / 2, r.y - (16 - r.height) / 2, 1, clr); //deprecated facade x_icon; x_icon.draw(graph, {}, colors::black, { r.x + static_cast(r.width - 16) / 2, r.y + static_cast(r.height - 16) / 2, 16, 16 }, element_state::normal); @@ -153,19 +149,16 @@ namespace nana virtual void back(graph_reference graph, const nana::rectangle& r, state_t sta) { - //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::west); } virtual void next(graph_reference graph, const nana::rectangle& r, state_t sta) { - //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::east); } virtual void list(graph_reference graph, const nana::rectangle& r, state_t sta) { - //using namespace nana::paint::gadget; //deprecated _m_draw_arrow(graph, r, sta, direction::south); } private: @@ -1448,7 +1441,6 @@ namespace nana private: void _m_calc_metrics(graph_reference graph, std::forward_list& items) { - const auto height_px = graph.height(); std::vector pxs; unsigned pixels = 0; diff --git a/source/paint/gadget.cpp b/source/paint/gadget.cpp deleted file mode 100644 index c6da79e6..00000000 --- a/source/paint/gadget.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Graphics Gadget Implementation - * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/paint/gadget.cpp - */ - -#include -#include - -namespace nana -{ -namespace paint -{ -namespace gadget -{ - void close_16_pixels(::nana::paint::graphics& graph, int x, int y, unsigned style, const ::nana::color& clr) - { - graph.set_color(clr); - if(0 == style) - { - x += 3; - y += 3; - - graph.line({ x, y }, { x + 9, y + 9 }); - graph.line({ x + 1, y }, { x + 9, y + 8 }); - graph.line({ x, y + 1 }, { x + 8, y + 9 }); - - graph.line({ x + 9, y }, { x, y + 9 }); - graph.line({ x + 8, y }, { x, y + 8 }); - graph.line({ x + 9, y + 1 }, { x + 1, y + 9 }); - } - else - { - x += 4; - y += 4; - - graph.line({ x, y }, { x + 7, y + 7 }); - graph.line({ x + 1, y }, { x + 7, y + 6 }); - graph.line({ x, y + 1 }, { x + 6, y + 7 }); - - graph.line({ x + 7, y }, { x, y + 7 }); - graph.line({ x + 6, y }, { x, y + 6 }); - graph.line({ x + 7, y + 1 }, { x + 1, y + 7 }); - } - } - - void cross(graphics& graph, int x, int y, unsigned size, unsigned thickness, const ::nana::color& clr) - { - if (thickness + 2 <= size) - { - int gap = (size - thickness) / 2; - - nana::point ps[12]; - ps[0].x = x + gap; - ps[1].x = ps[0].x + thickness - 1; - ps[1].y = ps[0].y = y; - - ps[2].x = ps[1].x; - ps[2].y = y + gap; - - ps[3].x = ps[2].x + gap; - ps[3].y = ps[2].y; - - ps[4].x = ps[3].x; - ps[4].y = ps[3].y + thickness - 1; - - ps[5].x = ps[1].x; - ps[5].y = ps[4].y; - - ps[6].x = ps[5].x; - ps[6].y = ps[5].y + gap; - - ps[7].x = x + gap; - ps[7].y = ps[6].y; - - ps[8].x = ps[7].x; - ps[8].y = ps[4].y; - - ps[9].x = x; - ps[9].y = ps[4].y; - - ps[10].x = x; - ps[10].y = y + gap; - - ps[11].x = x + gap; - ps[11].y = y + gap; - - graph.set_color(clr.blend(colors::black, true)); - - for (int i = 0; i < 11; ++i) - graph.line(ps[i], ps[i + 1]); - graph.line(ps[11], ps[0]); - - graph.set_color(clr); - graph.rectangle(rectangle{ ps[10].x + 1, ps[10].y + 1, (gap << 1) + thickness - 2, thickness - 2 }, true); - graph.rectangle(rectangle{ ps[0].x + 1, ps[0].y + 1, thickness - 2, (gap << 1) + thickness - 2 }, true); - } - } -}//end namespace gadget - -}//end namespace paint -}//end namespace nana diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index cba4b272..562d6fac 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -845,13 +845,13 @@ namespace paint BITMAPFILEHEADER bmFileHeader = { 0 }; bmFileHeader.bfType = 0x4d42; //bmp bmFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - bmFileHeader.bfSize = bmFileHeader.bfOffBits + imageBytes; + bmFileHeader.bfSize = bmFileHeader.bfOffBits + static_cast(imageBytes); HANDLE hFile = ::CreateFileW(static_cast(::nana::charset(file_utf8, ::nana::unicode::utf8)).data(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwWrite = 0; ::WriteFile(hFile, &bmFileHeader, sizeof(BITMAPFILEHEADER), &dwWrite, nullptr); ::WriteFile(hFile, &bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER), &dwWrite, nullptr); - ::WriteFile(hFile, pData, imageBytes, &dwWrite, nullptr); + ::WriteFile(hFile, pData, static_cast(imageBytes), &dwWrite, nullptr); ::CloseHandle(hFile); ::DeleteObject(hBmp); From ebd8da13f0a0f395dbbce9749583c65f9ddaf555 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 1 Sep 2015 03:49:38 +0800 Subject: [PATCH 06/22] adjust dockpanes when a dockpane is floating/docking --- include/nana/gui/widgets/tabbar.hpp | 10 +- source/gui/place.cpp | 139 ++++++++++++++++++++++++++-- source/gui/place_parts.hpp | 10 +- source/gui/widgets/tabbar.cpp | 62 ++++++++++++- 4 files changed, 199 insertions(+), 22 deletions(-) diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 02722d96..a788dc29 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -337,8 +337,6 @@ namespace nana namespace nana { - namespace ng - { namespace drawerbase { namespace tabbar_lite @@ -352,7 +350,7 @@ namespace nana driver(); ~driver(); - model* get_model(); + model* get_model() const throw(); private: //Overrides drawer_trigger's method void attached(widget_reference, graph_reference) override; @@ -373,11 +371,15 @@ namespace nana tabbar_lite() = default; tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); + public: //capacity + std::size_t length() const; + + public: //modifiers + void attach(std::size_t pos, window); void push_back(std::string text, ::nana::any par = {}); void push_front(std::string text, ::nana::any par = {}); }; - } } #endif diff --git a/source/gui/place.cpp b/source/gui/place.cpp index aa1f02f8..92033b99 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1602,16 +1602,83 @@ namespace nana } private: //Implement dock_notifier_interface + /* + static div_dockpane* _m_left(div_dockpane* dockpn) + { + for (auto & dv : dockpn->div_owner->children) + { + if (dv->div_next == dockpn) + return static_cast(dv.get()); + } + return nullptr; + } + + ::nana::size _m_calc_space_if_remove(div_dockpane* dockpn) + { + div_owner->field_area; + + auto left = _m_left(dockpn); + while (left && !left->display) + left = _m_left(left); + + auto right = dockpn->div_next; + while (right && !right->display) + right = right->div_next; + + } + */ void notify_float() override { set_display(false); + /* + this->width_percent = field_area.width / div_owner->field_area.width * 100.0; + this->height_percent = field_area.height / div_owner->field_area.height * 100.0; + + + //Re-layout the siblings + double other_px = this->div_owner->field_area.height - this->field_area.height; + for (auto& div : this->div_owner->children) + { + if (!div->display) + continue; + + //deprecated + //auto wgt_percent = div->field_area.height / other_px; + //div->weight.assign_percent(wgt_percent * 100.0); + + //???? other_px issue, have + auto dockpn = dynamic_cast(div.get()); + dockpn->width_percent = div->field_area.width / other_px * 100.0; + dockpn->height_percent = div->field_area.height / other_px * 100.0; + } + + this->weight.assign_percent((double(field_area.height) / this->div_owner->field_area.height) * 100.0); + */ impl_ptr_->collocate(); } void notify_dock() override { indicator_.docker.reset(); + + /* + //Re-layout the siblings + auto px = this->weight.get_value(div_owner->field_area.height); + + double other_px = this->div_owner->field_area.height - px; + + this->weight.assign_percent(px / div_owner->field_area.height * 100); + for (auto& div : this->div_owner->children) + { + if (!div->display) + continue; + + auto px = div->weight.get_value(static_cast(other_px)); + div->weight.assign_percent(px / div_owner->field_area.height * 100); + } + */ + set_display(true); impl_ptr_->collocate(); } @@ -1744,6 +1811,8 @@ namespace nana } public: field_dock * dockable_field{ nullptr }; + double width_percent{ -1 }; //[-1, 100] it's invalid if it is less than zero + double height_percent{ -1 }; //[-1, 100] private: implement * impl_ptr_; bool created_{ false }; @@ -1751,7 +1820,7 @@ namespace nana struct indicator_tag { paint::graphics graph; - //panel widget; + //panel widget; //deprecated rectangle r; std::unique_ptr> dock_area; std::unique_ptr docker; @@ -1766,6 +1835,19 @@ namespace nana : division(kind::dock, std::move(name)) {} + division* front() const + { + auto i = children.cbegin(); + + for (auto i = children.cbegin(); i != children.cend(); ++i) + { + if (i->get()->display) + return i->get(); + } + + return nullptr; + } + void collocate(window wd) override { auto area = this->margin_area(); @@ -1773,20 +1855,30 @@ namespace nana unsigned vert_count = 0, horz_count = 0; unsigned vert_weight = 0, horz_weight = 0; - bool prev_attr = _m_is_vert(children.front()->dir); + bool prev_attr = _m_is_vert(front()->dir); (prev_attr ? horz_count : vert_count) = 1; for (auto & child : children) { - auto is_vert = _m_is_vert(child->dir); + if (!child->display) + continue; - if (child->weight.is_not_none()) + auto child_dv = dynamic_cast(child.get()); + + const auto is_vert = _m_is_vert(child->dir); + + /* + if (is_vert) { - if (is_vert) - vert_weight += static_cast(child->weight.get_value(area.height)); - else - horz_weight += static_cast(child->weight.get_value(area.width)); + if (child_dv->height_percent >= 0) + vert_weight += static_cast(child_dv->height_percent * area.height); } + else + { + if (child_dv->width_percent >= 0) + horz_weight += static_cast(child_dv->width_percent * area.width); + } + */ if (is_vert == prev_attr) { @@ -1819,12 +1911,36 @@ namespace nana for (auto & child : children) { + if (!child->display) + continue; + + auto child_dv = dynamic_cast(child.get()); double weight; + + /* //deprecated if (child->weight.is_not_none()) weight = child->weight.get_value(_m_is_vert(child->dir) ? area.height : area.height); else weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); + if (_m_is_vert(child->dir)) + { + if (child_dv->height_percent >= 0) + weight = child_dv->height_percent * area.height; + else + weight = auto_vert_w; + } + else + { + if (child_dv->width_percent >= 0) + weight = child_dv->width_percent * area.width; + else + weight = auto_horz_w; + } + */ + + weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); + ::nana::rectangle child_r; switch (child->dir) { @@ -2216,7 +2332,12 @@ namespace nana std::vector> adjusted_children; for (auto & child : children) { - adjusted_children.emplace_back(new div_dockpane(std::move(child->name), this, child->dir)); + //ignores weight if it is a dockpane + //internally, width_percent/height_percent are employed for weight + auto dockpn = new div_dockpane(std::move(child->name), this, child->dir); + dockpn->div_next = child->div_next; + dockpn->div_owner = child->div_owner; + adjusted_children.emplace_back(dockpn); } children.swap(adjusted_children); diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 3a1b670e..b90732f5 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -198,7 +198,7 @@ namespace nana }); if (panels_.size() > 1) - tabbar_.reset(new tabbar(*this)); + tabbar_.reset(new tabbar_lite(*this)); std::size_t pos = 0; for (auto & pn : panels_) @@ -208,8 +208,10 @@ namespace nana pn.widget_ptr = pn.factory_fn(*this); if (tabbar_) { - tabbar_->push_back(pn.widget_ptr->caption()); - tabbar_->relate(pos++, pn.widget_ptr->handle()); + 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()); } } } @@ -262,7 +264,7 @@ namespace nana std::unique_ptr container_; dockarea_caption caption_; std::deque panels_; - std::unique_ptr> tabbar_; + std::unique_ptr tabbar_; struct moves { diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 624b5db1..3796a1ac 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1275,8 +1275,6 @@ namespace nana #include namespace nana { - namespace ng - { namespace drawerbase { namespace tabbar_lite @@ -1286,6 +1284,7 @@ namespace nana ::std::string text; ::nana::any value; ::std::pair pos_ends; + ::nana::window attached_window{ nullptr }; item(std::string t, ::nana::any v) : text(std::move(t)), value(std::move(v)) @@ -1361,6 +1360,23 @@ namespace nana return items_; } + void show_attached_window() + { + if (indexes_.active_pos != npos) + { + auto i = items_.cbegin(); + std::advance(i, indexes_.active_pos); + API::show_window(i->attached_window, true); + + std::size_t pos = 0; + for (auto & m : items_) + { + if (pos++ != indexes_.active_pos) + API::show_window(m.attached_window, false); + } + } + } + bool track_pointer(const point& pos) { std::size_t item_pos = 0; @@ -1476,7 +1492,7 @@ namespace nana delete model_; } - model* driver::get_model() + model* driver::get_model() const throw() { return model_; } @@ -1514,10 +1530,12 @@ namespace nana void driver::mouse_down(graph_reference graph, const arg_mouse&) { auto & indexes = model_->get_indexes(); - if (indexes.hovered_pos == model_->npos) + if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos)) return; indexes.active_pos = indexes.hovered_pos; + model_->show_attached_window(); + refresh(graph); API::lazy_refresh(); } @@ -1532,6 +1550,41 @@ namespace nana this->create(parent_wd, r, visible); } + //capacity + std::size_t tabbar_lite::length() const + { + auto& items = get_drawer_trigger().get_model()->items(); + internal_scope_guard lock; + + std::size_t off = 0; + auto i = items.cbegin(), end = items.cend(); + while (i != end) + { + ++i; + ++off; + } + return off; + } + + //modifiers + void tabbar_lite::attach(std::size_t pos_set, window wd) + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + for (auto & m : model->items()) + { + if (0 == pos_set--) + { + m.attached_window = wd; + model->show_attached_window(); + return; + } + } + + throw std::out_of_range("invalid position of tabbar_lite"); + } + void tabbar_lite::push_back(std::string text, ::nana::any any) { auto & items = get_drawer_trigger().get_model()->items(); @@ -1561,5 +1614,4 @@ namespace nana API::refresh_window(handle()); } //end class tabbar - } }//end namespace nana From 33006ddc4dd9872c787e4a76a95c9a1956412672 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 1 Sep 2015 23:37:08 +0800 Subject: [PATCH 07/22] re-collocate when drag the float dockpane over indicato indicatorr --- source/gui/place.cpp | 130 ++++--------------------------------------- 1 file changed, 11 insertions(+), 119 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 92033b99..27124a99 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1574,7 +1574,6 @@ namespace nana { if (!dockable_field) { - // if (name.empty()) return; @@ -1597,64 +1596,14 @@ namespace nana if (!dockarea.empty() && !dockarea.floating()) { dockarea.move(this->field_area); - indicator_.r = this->field_area; + //indicator_.r = this->field_area; //deprecated } } private: //Implement dock_notifier_interface - /* - static div_dockpane* _m_left(div_dockpane* dockpn) - { - for (auto & dv : dockpn->div_owner->children) - { - if (dv->div_next == dockpn) - return static_cast(dv.get()); - } - return nullptr; - } - - ::nana::size _m_calc_space_if_remove(div_dockpane* dockpn) - { - div_owner->field_area; - - auto left = _m_left(dockpn); - while (left && !left->display) - left = _m_left(left); - - auto right = dockpn->div_next; - while (right && !right->display) - right = right->div_next; - - } - */ void notify_float() override { set_display(false); - - /* - this->width_percent = field_area.width / div_owner->field_area.width * 100.0; - this->height_percent = field_area.height / div_owner->field_area.height * 100.0; - - - //Re-layout the siblings - double other_px = this->div_owner->field_area.height - this->field_area.height; - for (auto& div : this->div_owner->children) - { - if (!div->display) - continue; - - //deprecated - //auto wgt_percent = div->field_area.height / other_px; - //div->weight.assign_percent(wgt_percent * 100.0); - - //???? other_px issue, have - auto dockpn = dynamic_cast(div.get()); - dockpn->width_percent = div->field_area.width / other_px * 100.0; - dockpn->height_percent = div->field_area.height / other_px * 100.0; - } - - this->weight.assign_percent((double(field_area.height) / this->div_owner->field_area.height) * 100.0); - */ impl_ptr_->collocate(); } @@ -1662,23 +1611,6 @@ namespace nana { indicator_.docker.reset(); - /* - //Re-layout the siblings - auto px = this->weight.get_value(div_owner->field_area.height); - - double other_px = this->div_owner->field_area.height - px; - - this->weight.assign_percent(px / div_owner->field_area.height * 100); - for (auto& div : this->div_owner->children) - { - if (!div->display) - continue; - - auto px = div->weight.get_value(static_cast(other_px)); - div->weight.assign_percent(px / div_owner->field_area.height * 100); - } - */ - set_display(true); impl_ptr_->collocate(); } @@ -1705,14 +1637,8 @@ namespace nana arrow.direction(::nana::direction::south); arrow.draw(graph, colors::light_sky_blue, colors::midnight_blue, { 12, 0, 16, 16 }, element_state::normal); - rectangle r{ 4, 16, 24, 11 }; - graph.rectangle(r, true, colors::midnight_blue); - - r.x = 5; - r.y = 19; - r.width = 22; - r.height = 7; - graph.rectangle(r, true, colors::button_face); + graph.rectangle({ 4, 16, 24, 11 }, true, colors::midnight_blue); + graph.rectangle({ 5, 19, 22, 7 }, true, colors::button_face); }); indicator_.docker->z_order(nullptr, ::nana::z_order_action::topmost); @@ -1732,16 +1658,19 @@ namespace nana { if (!indicator_.dock_area) { + set_display(true); + impl_ptr_->collocate(); + indicator_.graph.make(API::window_size(impl_ptr_->window_handle)); API::window_graphics(impl_ptr_->window_handle, indicator_.graph); indicator_.dock_area.reset(new panel(impl_ptr_->window_handle, false)); - indicator_.dock_area->move(indicator_.r); + indicator_.dock_area->move(this->field_area); ::nana::drawing dw(indicator_.dock_area->handle()); dw.draw([this](paint::graphics& graph) { - indicator_.graph.paste(indicator_.r, graph, 0, 0); + indicator_.graph.paste(this->field_area, graph, 0, 0); const int border_px = 4; rectangle r{ graph.size() }; @@ -1772,6 +1701,8 @@ namespace nana } else { + set_display(false); + impl_ptr_->collocate(); if (indicator_.dock_area) { indicator_.dock_area.reset(); @@ -1811,8 +1742,6 @@ namespace nana } public: field_dock * dockable_field{ nullptr }; - double width_percent{ -1 }; //[-1, 100] it's invalid if it is less than zero - double height_percent{ -1 }; //[-1, 100] private: implement * impl_ptr_; bool created_{ false }; @@ -1820,8 +1749,7 @@ namespace nana struct indicator_tag { paint::graphics graph; - //panel widget; //deprecated - rectangle r; + //rectangle r; //deprecated std::unique_ptr> dock_area; std::unique_ptr docker; }indicator_; @@ -1867,19 +1795,6 @@ namespace nana const auto is_vert = _m_is_vert(child->dir); - /* - if (is_vert) - { - if (child_dv->height_percent >= 0) - vert_weight += static_cast(child_dv->height_percent * area.height); - } - else - { - if (child_dv->width_percent >= 0) - horz_weight += static_cast(child_dv->width_percent * area.width); - } - */ - if (is_vert == prev_attr) { if (is_vert) @@ -1917,28 +1832,6 @@ namespace nana auto child_dv = dynamic_cast(child.get()); double weight; - /* //deprecated - if (child->weight.is_not_none()) - weight = child->weight.get_value(_m_is_vert(child->dir) ? area.height : area.height); - else - weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); - - if (_m_is_vert(child->dir)) - { - if (child_dv->height_percent >= 0) - weight = child_dv->height_percent * area.height; - else - weight = auto_vert_w; - } - else - { - if (child_dv->width_percent >= 0) - weight = child_dv->width_percent * area.width; - else - weight = auto_horz_w; - } - */ - weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); ::nana::rectangle child_r; @@ -2333,7 +2226,6 @@ namespace nana for (auto & child : children) { //ignores weight if it is a dockpane - //internally, width_percent/height_percent are employed for weight auto dockpn = new div_dockpane(std::move(child->name), this, child->dir); dockpn->div_next = child->div_next; dockpn->div_owner = child->div_owner; From 66d531c520d5b2c47d0a52e63b3a7dffc32a973e Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 6 Sep 2015 22:33:39 +0800 Subject: [PATCH 08/22] add splitbars between dockable panes --- source/gui/place.cpp | 179 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 151 insertions(+), 28 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 27124a99..401f5294 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1592,12 +1592,8 @@ namespace nana dockarea.create(wd, this); } - if (!dockarea.empty() && !dockarea.floating()) - { dockarea.move(this->field_area); - //indicator_.r = this->field_area; //deprecated - } } private: //Implement dock_notifier_interface @@ -1746,10 +1742,10 @@ namespace nana implement * impl_ptr_; bool created_{ false }; - struct indicator_tag + // + struct indicator_rep { paint::graphics graph; - //rectangle r; //deprecated std::unique_ptr> dock_area; std::unique_ptr docker; }indicator_; @@ -1758,9 +1754,74 @@ namespace nana class place::implement::div_dock : public division { + static const unsigned splitter_px = 5; + + class splitter : public panel + { + public: + splitter(window wd, bool vert) + : panel(wd, true), vert_(vert) + { + this->bgcolor(colors::alice_blue); + this->cursor(vert ? ::nana::cursor::size_ns : ::nana::cursor::size_we); + + this->events().mouse_down([this](const arg_mouse& arg) + { + if (arg.button != ::nana::mouse::left_button) + return; + + API::capture_window(this->handle(), true); + auto basepos = API::cursor_position(); + base_pos_.x = (vert_ ? basepos.y : basepos.x); + + basepos = this->pos(); + base_pos_.y = (vert_ ? basepos.y : basepos.x); + }); + + this->events().mouse_up([this] + { + API::capture_window(this->handle(), false); + }); + + this->events().mouse_move([this](const arg_mouse& arg) + { + if (!arg.is_left_button()) + return; + + auto now_pos = API::cursor_position(); + int delta = (vert_ ? now_pos.y : now_pos.x) - base_pos_.x; + int new_pos = base_pos_.y + delta; + if (new_pos < range_.x) + new_pos = range_.x; + else if (new_pos >= range_.y) + new_pos = range_.y - 1; + + now_pos = this->pos(); + if (vert_) + now_pos.y = new_pos; + else + now_pos.x = new_pos; + this->move(now_pos); + }); + } + + void range(int begin, int end) + { + range_.x = begin; + range_.y = end; + } + private: + const bool vert_; + ::nana::point range_; + ::nana::point base_pos_; //x = mouse pos, y = splitter pos + division * left_; + division * right_; + + }; public: + div_dock(std::string && name, implement* impl) - : division(kind::dock, std::move(name)) + : division(kind::dock, std::move(name)), impl_(impl) {} division* front() const @@ -1781,10 +1842,9 @@ namespace nana auto area = this->margin_area(); unsigned vert_count = 0, horz_count = 0; - unsigned vert_weight = 0, horz_weight = 0; - bool prev_attr = _m_is_vert(front()->dir); - (prev_attr ? horz_count : vert_count) = 1; + bool is_first = true; + bool prev_attr; for (auto & child : children) { @@ -1794,21 +1854,18 @@ namespace nana auto child_dv = dynamic_cast(child.get()); const auto is_vert = _m_is_vert(child->dir); + if (is_first) + { + is_first = false; + (is_vert ? horz_count : vert_count) = 1; + prev_attr = is_vert; + } - if (is_vert == prev_attr) - { - if (is_vert) - ++vert_count; - else - ++horz_count; - } + if ((is_vert == prev_attr) == is_vert) + ++vert_count; else - { - if (is_vert) - ++horz_count; - else - ++vert_count; - } + ++horz_count; + prev_attr = is_vert; } if (0 == vert_count) @@ -1816,23 +1873,39 @@ namespace nana if (0 == horz_count) ++horz_count; - double auto_horz_w = double(area.width - horz_weight) / horz_count; - double auto_vert_w = double(area.height - vert_weight) / vert_count; + double auto_horz_w = double(area.width - splitter_px * (horz_count - 1))/ horz_count; + double auto_vert_w = double(area.height - splitter_px * (vert_count - 1)) / vert_count; double left = area.x; double right = area.right(); double top = area.y; double bottom = area.bottom(); + std::map> swp_splitters; + for (auto & child : children) { if (!child->display) continue; auto child_dv = dynamic_cast(child.get()); - double weight; + const bool is_vert = _m_is_vert(child->dir); - weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w); + double weight = (is_vert ? auto_vert_w : auto_horz_w); + + auto div_next = _m_right(child_dv); + + auto & splitter_ptr = swp_splitters[child_dv]; + + auto si = splitters_.find(child_dv); + if (si == splitters_.end()) + { + splitter_ptr.reset(new splitter(impl_->window_handle, is_vert)); + } + else + { + splitter_ptr.swap(si->second); + } ::nana::rectangle child_r; switch (child->dir) @@ -1844,6 +1917,12 @@ namespace nana child_r.width = static_cast(weight); child_r.height = static_cast(bottom - top); left += weight; + if (div_next) + { + splitter_ptr->move(rectangle{child_r.right(), child_r.y, splitter_px, child_r.height}); + splitter_ptr->range(left - weight, right - static_cast(splitter_px)); + left += splitter_px; + } break; case ::nana::direction::east: right -= weight; @@ -1851,6 +1930,12 @@ namespace nana child_r.y = static_cast(top); child_r.width = static_cast(weight); child_r.height = static_cast(bottom - top); + if (div_next) + { + splitter_ptr->move(rectangle{ child_r.x - static_cast(splitter_px), child_r.y, splitter_px, child_r.height }); + splitter_ptr->range(left, right - static_cast(splitter_px) + weight); + right -= splitter_px; + } break; case ::nana::direction::north: child_r.x = static_cast(left); @@ -1858,6 +1943,12 @@ namespace nana child_r.width = static_cast(right - left); child_r.height = static_cast(weight); top += weight; + if (div_next) + { + splitter_ptr->move(rectangle{ child_r.x, child_r.bottom(), child_r.width, splitter_px }); + splitter_ptr->range(top - weight, bottom - static_cast(splitter_px)); + top += splitter_px; + } break; case ::nana::direction::south: child_r.x = static_cast(left); @@ -1865,18 +1956,44 @@ namespace nana child_r.y = static_cast(bottom); child_r.width = static_cast(right - left); child_r.height = static_cast(weight); + if (div_next) + { + bottom -= splitter_px; + splitter_ptr->move(rectangle{ child_r.x, child_r.y - static_cast(splitter_px), child_r.width, splitter_px }); + splitter_ptr->range(top, bottom + weight); + } break; } + + child->field_area = child_r; child->collocate(wd); } + + splitters_.swap(swp_splitters); } private: static bool _m_is_vert(::nana::direction dir) { return (dir == ::nana::direction::north || dir == ::nana::direction::south); } + + static div_dockpane* _m_right(division* dv) + { + dv = dv->div_next; + while (dv) + { + if (dv->display) + return dynamic_cast(dv); + + dv = dv->div_next; + } + return nullptr; + } + private: + implement * const impl_; + std::map> splitters_; }; place::implement::~implement() @@ -2227,11 +2344,17 @@ namespace nana { //ignores weight if it is a dockpane auto dockpn = new div_dockpane(std::move(child->name), this, child->dir); - dockpn->div_next = child->div_next; dockpn->div_owner = child->div_owner; adjusted_children.emplace_back(dockpn); } + division * next = nullptr; + for (auto i = adjusted_children.rbegin(); i != adjusted_children.rend(); ++i) + { + i->get()->div_next = next; + next = i->get(); + } + children.swap(adjusted_children); } } From 651d0f72ddea12e4ce82e53c3e3dfb7c3898d4a7 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 7 Sep 2015 00:24:44 +0800 Subject: [PATCH 09/22] add process of dockpane splitbar --- source/gui/place.cpp | 73 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 401f5294..b7feadbe 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1759,11 +1759,11 @@ namespace nana class splitter : public panel { public: - splitter(window wd, bool vert) - : panel(wd, true), vert_(vert) + splitter(window wd, ::nana::direction dir, division* dock_dv, division* pane_dv) + : panel(wd, true), dir_(dir), dock_dv_(dock_dv), pane_dv_(pane_dv) { this->bgcolor(colors::alice_blue); - this->cursor(vert ? ::nana::cursor::size_ns : ::nana::cursor::size_we); + this->cursor(_m_is_vert(dir_) ? ::nana::cursor::size_ns : ::nana::cursor::size_we); this->events().mouse_down([this](const arg_mouse& arg) { @@ -1772,10 +1772,10 @@ namespace nana API::capture_window(this->handle(), true); auto basepos = API::cursor_position(); - base_pos_.x = (vert_ ? basepos.y : basepos.x); + base_pos_.x = (_m_is_vert(dir_) ? basepos.y : basepos.x); basepos = this->pos(); - base_pos_.y = (vert_ ? basepos.y : basepos.x); + base_pos_.y = (_m_is_vert(dir_) ? basepos.y : basepos.x); }); this->events().mouse_up([this] @@ -1783,13 +1783,13 @@ namespace nana API::capture_window(this->handle(), false); }); - this->events().mouse_move([this](const arg_mouse& arg) + this->events().mouse_move([this, wd](const arg_mouse& arg) { if (!arg.is_left_button()) return; auto now_pos = API::cursor_position(); - int delta = (vert_ ? now_pos.y : now_pos.x) - base_pos_.x; + int delta = (_m_is_vert(dir_) ? now_pos.y : now_pos.x) - base_pos_.x; int new_pos = base_pos_.y + delta; if (new_pos < range_.x) new_pos = range_.x; @@ -1797,11 +1797,36 @@ namespace nana new_pos = range_.y - 1; now_pos = this->pos(); - if (vert_) + if (_m_is_vert(dir_)) now_pos.y = new_pos; else now_pos.x = new_pos; this->move(now_pos); + + auto & px = (_m_is_vert(dir_) ? pane_dv_->field_area.height : pane_dv_->field_area.width); + switch (dir_) + { + case ::nana::direction::west: + case ::nana::direction::north: + if (delta < 0) + px -= static_cast(-delta); + else + px += static_cast(delta); + break; + case ::nana::direction::east: + case ::nana::direction::south: + if (delta < 0) + px += static_cast(-delta); + else + px -= static_cast(delta); + break; + } + + auto dock_px = (_m_is_vert(dir_) ? dock_dv_->field_area.height : dock_dv_->field_area.width); + + pane_dv_->weight.assign_percent(px / dock_px * 100); + + dock_dv_->collocate(wd); }); } @@ -1811,11 +1836,11 @@ namespace nana range_.y = end; } private: - const bool vert_; + const ::nana::direction dir_; + division* const dock_dv_; + division* const pane_dv_; ::nana::point range_; ::nana::point base_pos_; //x = mouse pos, y = splitter pos - division * left_; - division * right_; }; public: @@ -1873,8 +1898,11 @@ namespace nana if (0 == horz_count) ++horz_count; - double auto_horz_w = double(area.width - splitter_px * (horz_count - 1))/ horz_count; - double auto_vert_w = double(area.height - splitter_px * (vert_count - 1)) / vert_count; + //room indicates the size without splitters + ::nana::size room(area.width - splitter_px * (horz_count - 1), area.height - splitter_px * (vert_count - 1)); + + //double auto_horz_w = double(area.width - splitter_px * (horz_count - 1))/ horz_count; + //double auto_vert_w = double(area.height - splitter_px * (vert_count - 1)) / vert_count; double left = area.x; double right = area.right(); @@ -1891,7 +1919,11 @@ namespace nana auto child_dv = dynamic_cast(child.get()); const bool is_vert = _m_is_vert(child->dir); - double weight = (is_vert ? auto_vert_w : auto_horz_w); + double weight; + if (child->weight.is_none()) + weight = (is_vert ? (room.height / double(vert_count)) : (room.width / double(horz_count))); + else + weight = child->weight.get_value(is_vert ? area.height : area.width); auto div_next = _m_right(child_dv); @@ -1900,7 +1932,7 @@ namespace nana auto si = splitters_.find(child_dv); if (si == splitters_.end()) { - splitter_ptr.reset(new splitter(impl_->window_handle, is_vert)); + splitter_ptr.reset(new splitter(impl_->window_handle, child->dir, this, child_dv)); } else { @@ -1965,7 +1997,16 @@ namespace nana break; } - + if (is_vert) + { + room.height -= child_r.height; + --vert_count; + } + else + { + room.width -= child_r.width; + --horz_count; + } child->field_area = child_r; child->collocate(wd); From b453529366a569c17710250162e48c0751ebdd42 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 7 Sep 2015 08:55:49 +0800 Subject: [PATCH 10/22] add process of dockpane's splitbar --- source/gui/place.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index b7feadbe..1f046799 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1776,6 +1776,8 @@ namespace nana basepos = this->pos(); base_pos_.y = (_m_is_vert(dir_) ? basepos.y : basepos.x); + + base_px_ = (_m_is_vert(dir_) ? pane_dv_->field_area.height : pane_dv_->field_area.width); }); this->events().mouse_up([this] @@ -1803,7 +1805,7 @@ namespace nana now_pos.x = new_pos; this->move(now_pos); - auto & px = (_m_is_vert(dir_) ? pane_dv_->field_area.height : pane_dv_->field_area.width); + auto px = base_px_; switch (dir_) { case ::nana::direction::west: @@ -1824,7 +1826,7 @@ namespace nana auto dock_px = (_m_is_vert(dir_) ? dock_dv_->field_area.height : dock_dv_->field_area.width); - pane_dv_->weight.assign_percent(px / dock_px * 100); + pane_dv_->weight.assign_percent(double(px) / double(dock_px) * 100); dock_dv_->collocate(wd); }); @@ -1841,6 +1843,7 @@ namespace nana division* const pane_dv_; ::nana::point range_; ::nana::point base_pos_; //x = mouse pos, y = splitter pos + unsigned base_px_; //weight of div_dockpane when mouse button is been pressing; }; public: From 65a876cc74ab07e6bbf21ff2ec7996bc5fcbcedb Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 7 Sep 2015 09:12:51 +0800 Subject: [PATCH 11/22] the dockpane splitbar is done --- source/gui/place.cpp | 64 +++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 1f046799..6e82a599 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1794,9 +1794,15 @@ namespace nana int delta = (_m_is_vert(dir_) ? now_pos.y : now_pos.x) - base_pos_.x; int new_pos = base_pos_.y + delta; if (new_pos < range_.x) + { new_pos = range_.x; + delta = new_pos - base_pos_.y; + } else if (new_pos >= range_.y) + { new_pos = range_.y - 1; + delta = new_pos - base_pos_.y; + } now_pos = this->pos(); if (_m_is_vert(dir_)) @@ -1922,24 +1928,32 @@ namespace nana auto child_dv = dynamic_cast(child.get()); const bool is_vert = _m_is_vert(child->dir); + auto room_px = (is_vert ? room.height : room.width); + double weight; - if (child->weight.is_none()) - weight = (is_vert ? (room.height / double(vert_count)) : (room.width / double(horz_count))); - else - weight = child->weight.get_value(is_vert ? area.height : area.width); - - auto div_next = _m_right(child_dv); - - auto & splitter_ptr = swp_splitters[child_dv]; - - auto si = splitters_.find(child_dv); - if (si == splitters_.end()) + if (child->weight.is_not_none()) { - splitter_ptr.reset(new splitter(impl_->window_handle, child->dir, this, child_dv)); + weight = child->weight.get_value(is_vert ? area.height : area.width); + if (weight > room_px) + weight = room_px; } else + weight = room_px / double(is_vert ? vert_count : horz_count); + + splitter* split = nullptr; + if (_m_right(child_dv)) { - splitter_ptr.swap(si->second); + //Creates a splitbar if the 'right' leaf is not empty + + auto & splitter_ptr = swp_splitters[child_dv]; + + auto si = splitters_.find(child_dv); + if (si == splitters_.end()) + splitter_ptr.reset(new splitter(impl_->window_handle, child->dir, this, child_dv)); + else + splitter_ptr.swap(si->second); + + split = splitter_ptr.get(); } ::nana::rectangle child_r; @@ -1952,10 +1966,10 @@ namespace nana child_r.width = static_cast(weight); child_r.height = static_cast(bottom - top); left += weight; - if (div_next) + if (split) { - splitter_ptr->move(rectangle{child_r.right(), child_r.y, splitter_px, child_r.height}); - splitter_ptr->range(left - weight, right - static_cast(splitter_px)); + split->move(rectangle{ child_r.right(), child_r.y, splitter_px, child_r.height }); + split->range(left - weight, right - static_cast(splitter_px)); left += splitter_px; } break; @@ -1965,10 +1979,10 @@ namespace nana child_r.y = static_cast(top); child_r.width = static_cast(weight); child_r.height = static_cast(bottom - top); - if (div_next) + if (split) { - splitter_ptr->move(rectangle{ child_r.x - static_cast(splitter_px), child_r.y, splitter_px, child_r.height }); - splitter_ptr->range(left, right - static_cast(splitter_px) + weight); + split->move(rectangle{ child_r.x - static_cast(splitter_px), child_r.y, splitter_px, child_r.height }); + split->range(left, right - static_cast(splitter_px)+weight); right -= splitter_px; } break; @@ -1978,10 +1992,10 @@ namespace nana child_r.width = static_cast(right - left); child_r.height = static_cast(weight); top += weight; - if (div_next) + if (split) { - splitter_ptr->move(rectangle{ child_r.x, child_r.bottom(), child_r.width, splitter_px }); - splitter_ptr->range(top - weight, bottom - static_cast(splitter_px)); + split->move(rectangle{ child_r.x, child_r.bottom(), child_r.width, splitter_px }); + split->range(top - weight, bottom - static_cast(splitter_px)); top += splitter_px; } break; @@ -1991,11 +2005,11 @@ namespace nana child_r.y = static_cast(bottom); child_r.width = static_cast(right - left); child_r.height = static_cast(weight); - if (div_next) + if (split) { bottom -= splitter_px; - splitter_ptr->move(rectangle{ child_r.x, child_r.y - static_cast(splitter_px), child_r.width, splitter_px }); - splitter_ptr->range(top, bottom + weight); + split->move(rectangle{ child_r.x, child_r.y - static_cast(splitter_px), child_r.width, splitter_px }); + split->range(top, bottom + weight); } break; } From edd7de4e8b848f6251613af3c3e8b6519f6e1305 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 10 Sep 2015 23:36:16 +0800 Subject: [PATCH 12/22] fix a color issue --- source/detail/linux_X11/platform_spec.cpp | 4 ++-- source/detail/win32/platform_spec.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/detail/linux_X11/platform_spec.cpp b/source/detail/linux_X11/platform_spec.cpp index 7501158d..0765b46c 100644 --- a/source/detail/linux_X11/platform_spec.cpp +++ b/source/detail/linux_X11/platform_spec.cpp @@ -304,12 +304,12 @@ namespace detail void drawable_impl_type::set_color(const ::nana::color& clr) { - color_ = clr.px_color().value; + color_ = (clr.px_color().value & 0xFFFFFF); } void drawable_impl_type::set_text_color(const ::nana::color& clr) { - text_color_ = clr.px_color().value; + text_color_ = (clr.px_color().value & 0xFFFFFF); update_text_color(); } diff --git a/source/detail/win32/platform_spec.cpp b/source/detail/win32/platform_spec.cpp index cb064545..dcc22037 100644 --- a/source/detail/win32/platform_spec.cpp +++ b/source/detail/win32/platform_spec.cpp @@ -65,12 +65,12 @@ namespace detail void drawable_impl_type::set_color(const ::nana::color& clr) { - color_ = clr.px_color().value; + color_ = (clr.px_color().value & 0xFFFFFF); } void drawable_impl_type::set_text_color(const ::nana::color& clr) { - auto rgb = clr.px_color().value; + auto rgb = (clr.px_color().value & 0xFFFFFF); if (text_color_ != rgb) { ::SetTextColor(context, NANA_RGB(rgb)); From ec098640fd044272252ad2563162a57f7107e1cd Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 13 Sep 2015 19:27:55 +0200 Subject: [PATCH 13/22] Fix Visual Studio 2015 codecvt linker errors Add missing defines --- CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 242a1ea2..3fbd6ed5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,13 @@ if(BIICODE) # we'll use the default config file so we can iliminate the following macro definitions if(MSVC) # More MSVC specific compilation flags - add_definitions(-D_SCL_SECURE_NO_WARNINGS) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_SCL_SECURE_NO_WARNINGS) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + if(MSVC14) + add_definitions(-DSTD_CODECVT_NOT_SUPPORTED) + else() + add_definitions(-DNOT_IMPLEMENTED_KEYWORD_noexcept) + endif() endif() add_biicode_targets() From e97d2cb20f18444a5b3a97d19aa5537c68d5b955 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 14 Sep 2015 01:48:30 +0800 Subject: [PATCH 14/22] fix color issues --- .../nana/detail/linux_X11/platform_spec.hpp | 2 ++ include/nana/detail/win32/platform_spec.hpp | 1 + include/nana/paint/graphics.hpp | 7 +++++-- source/detail/linux_X11/platform_spec.cpp | 10 +++++++++ source/detail/win32/platform_spec.cpp | 5 +++++ source/paint/graphics.cpp | 21 +++++++++++++++++++ source/paint/text_renderer.cpp | 7 +++++-- 7 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/nana/detail/linux_X11/platform_spec.hpp b/include/nana/detail/linux_X11/platform_spec.hpp index ae4a1830..461517f9 100644 --- a/include/nana/detail/linux_X11/platform_spec.hpp +++ b/include/nana/detail/linux_X11/platform_spec.hpp @@ -106,6 +106,8 @@ namespace detail ~drawable_impl_type(); void fgcolor(const ::nana::color&); //deprecated + unsigned get_color() const; + unsigned get_text_color() const; void set_color(const ::nana::color&); void set_text_color(const ::nana::color&); diff --git a/include/nana/detail/win32/platform_spec.hpp b/include/nana/detail/win32/platform_spec.hpp index e8db5fff..3afea077 100644 --- a/include/nana/detail/win32/platform_spec.hpp +++ b/include/nana/detail/win32/platform_spec.hpp @@ -146,6 +146,7 @@ namespace detail void fgcolor(const ::nana::color&); //deprecated unsigned get_color() const; + unsigned get_text_color() const; void set_color(const ::nana::color&); void set_text_color(const ::nana::color&); diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index ad2c8a6c..a194aa7e 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -136,8 +136,11 @@ namespace nana /// @param file_utf8 A UTF-8 string to a filename void save_as_file(const char* file_utf8) const throw(); - void set_color(const ::nana::color&); - void set_text_color(const ::nana::color&); + void set_color(const ::nana::color&); //deprecated, graphics::palette() instead + void set_text_color(const ::nana::color&); //deprecated, graphics::palette() instead + + ::nana::color palette(bool for_text) const; + graphics& palette(bool for_text, const ::nana::color&); unsigned bidi_string(const nana::point&, const char_t *, std::size_t len); unsigned bidi_string(const point& pos, const char*, std::size_t len); diff --git a/source/detail/linux_X11/platform_spec.cpp b/source/detail/linux_X11/platform_spec.cpp index 0765b46c..8d4ff735 100644 --- a/source/detail/linux_X11/platform_spec.cpp +++ b/source/detail/linux_X11/platform_spec.cpp @@ -302,6 +302,16 @@ namespace detail #endif } + unsigned drawable_impl_type::get_color() const + { + return color_; + } + + unsigned drawable_impl_type::get_text_color() const + { + return text_color_; + } + void drawable_impl_type::set_color(const ::nana::color& clr) { color_ = (clr.px_color().value & 0xFFFFFF); diff --git a/source/detail/win32/platform_spec.cpp b/source/detail/win32/platform_spec.cpp index dcc22037..767b843f 100644 --- a/source/detail/win32/platform_spec.cpp +++ b/source/detail/win32/platform_spec.cpp @@ -63,6 +63,11 @@ namespace detail return color_; } + unsigned drawable_impl_type::get_text_color() const + { + return text_color_; + } + void drawable_impl_type::set_color(const ::nana::color& clr) { color_ = (clr.px_color().value & 0xFFFFFF); diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index cba4b272..e95e4ef8 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -874,6 +874,27 @@ namespace paint handle_->set_text_color(col); } + ::nana::color graphics::palette(bool for_text) const + { + if (handle_) + return static_cast(for_text ? handle_->get_text_color() : handle_->get_color()); + + return{}; + } + + graphics& graphics::palette(bool for_text, const ::nana::color& clr) + { + if (handle_) + { + if (for_text) + handle_->set_text_color(clr); + else + handle_->set_color(clr); + } + + return *this; + } + unsigned graphics::bidi_string(const nana::point& pos, const char_t * str, std::size_t len) { auto moved_pos = pos; diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 9fbcf8f6..eaa87349 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -118,11 +118,12 @@ namespace nana { graphics & graph; int x, endpos; - ::nana::color fgcolor; + //::nana::color fgcolor; //deprecated unsigned omitted_pixels; nana::unicode_bidi bidi; std::vector reordered; + /* //deprecated draw_string_omitted(graphics& graph, int x, int endpos, const ::nana::color& fgcolor, bool omitted) : graph(graph), x(x), endpos(endpos), fgcolor(fgcolor) { @@ -132,6 +133,7 @@ namespace nana else this->endpos = x; } + */ draw_string_omitted(graphics& graph, int x, int endpos, bool omitted) : graph(graph), x(x), endpos(endpos) @@ -169,7 +171,8 @@ namespace nana nana::paint::graphics dum_graph({ r.width, r.height }); dum_graph.bitblt(r, graph, pos); - dum_graph.set_text_color(fgcolor); + //dum_graph.set_text_color(fgcolor); //deprecated + dum_graph.set_text_color(graph.palette(true)); dum_graph.string({}, i.begin, len); r.x = pos.x; From 44a067fd519028b104307aa277384ec38de7887f Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 18 Sep 2015 08:19:25 +0800 Subject: [PATCH 15/22] implement dockpane titlebar --- source/gui/place_parts.hpp | 60 +++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index b90732f5..914dc405 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -63,28 +64,60 @@ namespace nana { public: private: - virtual void attached(widget_reference, graph_reference graph) override + virtual void attached(widget_reference wdg, graph_reference graph) override { - graph.set_color(colors::slate_blue); - graph.set_text_color(colors::white); + window_handle_ = wdg; + text_rd_.reset(new paint::text_renderer(graph)); } void refresh(graph_reference& graph) override { - graph.rectangle(true, colors::red); + graph.set_color(static_cast(0x83EB)); + graph.set_text_color(colors::white); + graph.rectangle(true); + + //draw caption + auto text = API::window_caption(window_handle_); + text = L"dockarea-caption"; + text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, true); + + //draw x button + auto r = _m_button_area(); + if (x_pointed_) + graph.rectangle(r, true, colors::red); - ::nana::rectangle r{ graph.size() }; - - r.x = r.right() - 20; + r.x += (r.width - 16) / 2; r.y = (r.height - 16) / 2; - r.width = r.height = 16; - - button_.draw(graph, colors::red, colors::white, r, element_state::normal); x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal); } + + void mouse_move(graph_reference graph, const arg_mouse& arg) override + { + x_pointed_ = _m_button_area().is_hit(arg.pos); + + refresh(graph); + API::lazy_refresh(); + } + + void mouse_leave(graph_reference graph, const arg_mouse&) override + { + x_pointed_ = false; + refresh(graph); + API::lazy_refresh(); + } + private: + ::nana::rectangle _m_button_area() const + { + ::nana::rectangle r{API::window_size(window_handle_)}; + + r.x = r.right() - 20; + r.width = 20; + return r; + } public: - ::nana::string caption; - facade button_; + window window_handle_; + std::unique_ptr text_rd_; + bool x_pointed_{ false }; facade x_icon_; }; @@ -130,7 +163,6 @@ namespace nana base_type::create(parent, true); this->caption("dockarea"); caption_.create(*this, true); - caption_.caption("dockarea-caption"); this->events().resized([this](const arg_resized& arg) { @@ -175,7 +207,7 @@ namespace nana auto move_pos = API::cursor_position() - moves_.start_pos; if (!floating()) { - if (std::abs(move_pos.x) > 4 || abs(move_pos.y) > 4) + if (std::abs(move_pos.x) > 4 || std::abs(move_pos.y) > 4) float_away(move_pos); } else From 5d2127e6131b441ee07c761ab8794243b11a095b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 19 Sep 2015 05:18:15 +0800 Subject: [PATCH 16/22] 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) From 460490040e903d96979133626989ef9652f2fb7a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 20 Sep 2015 23:21:44 +0800 Subject: [PATCH 17/22] improve dockable place add a new API::at_safe_place() --- include/nana/gui/detail/window_manager.hpp | 3 + include/nana/gui/programming_interface.hpp | 2 + include/nana/gui/widgets/tabbar.hpp | 3 + source/gui/detail/linux_X11/bedrock.cpp | 5 +- source/gui/detail/win32/bedrock.cpp | 2 + source/gui/detail/window_manager.cpp | 32 +++++++++++ source/gui/place.cpp | 16 +++++- source/gui/place_parts.hpp | 67 +++++++++++++++++++++- source/gui/programming_interface.cpp | 5 ++ source/gui/widgets/tabbar.cpp | 59 ++++++++++++++++--- 10 files changed, 181 insertions(+), 13 deletions(-) diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index ec91fe1f..857d69e7 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -161,6 +161,9 @@ namespace detail std::vector> shortkeys(core_window_t*, bool with_children); core_window_t* find_shortkey(native_window_type, unsigned long key); + + void set_safe_place(core_window_t* wd, std::function&& fn); + void call_safe_place(unsigned thread_id); private: void _m_disengage(core_window_t*, core_window_t* for_new); void _m_destroy(core_window_t*); diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index bfbcd138..932e35c8 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -298,6 +298,8 @@ namespace API bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled + + void at_safe_place(window, std::function); }//end namespace API }//end namespace nana diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index a788dc29..86556cec 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -379,6 +379,9 @@ namespace nana void push_back(std::string text, ::nana::any par = {}); void push_front(std::string text, ::nana::any par = {}); + + std::size_t selected() const; + void erase(std::size_t pos, bool close_attached = true); }; } diff --git a/source/gui/detail/linux_X11/bedrock.cpp b/source/gui/detail/linux_X11/bedrock.cpp index 3cba6d2b..1260067b 100644 --- a/source/gui/detail/linux_X11/bedrock.cpp +++ b/source/gui/detail/linux_X11/bedrock.cpp @@ -1207,8 +1207,11 @@ namespace detail if(context) context->event_window = pre_event_window; } + auto thread_id = ::nana::system::this_thread_id() + brock.wd_manager.call_safe_place(thread_id); + if(msgwnd) - brock.wd_manager.remove_trash_handle(::nana::system::this_thread_id()); + brock.wd_manager.remove_trash_handle(thread_id); } } diff --git a/source/gui/detail/win32/bedrock.cpp b/source/gui/detail/win32/bedrock.cpp index d8ac543c..e1095345 100644 --- a/source/gui/detail/win32/bedrock.cpp +++ b/source/gui/detail/win32/bedrock.cpp @@ -413,6 +413,7 @@ namespace detail ::DispatchMessage(&msg); } + wd_manager.call_safe_place(tid); wd_manager.remove_trash_handle(tid); if (msg.message == WM_DESTROY && msg.hwnd == native_handle) break; @@ -432,6 +433,7 @@ namespace detail ::DispatchMessage(&msg); } + wd_manager.call_safe_place(tid); wd_manager.remove_trash_handle(tid); }//end while diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index e9581fd1..e272801b 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -44,6 +44,8 @@ namespace detail handle_manager wd_register; paint::image default_icon_big; paint::image default_icon_small; + + std::map>> safe_place; }; //end struct wdm_private_impl @@ -1192,6 +1194,36 @@ namespace detail return nullptr; } + void window_manager::set_safe_place(core_window_t* wd, std::function&& fn) + { + if (fn) + { + std::lock_guard lock(mutex_); + if (!available(wd)) + return; + + impl_->safe_place[wd].emplace_back(std::move(fn)); + } + } + + void window_manager::call_safe_place(unsigned thread_id) + { + std::lock_guard lock(mutex_); + + for (auto i = impl_->safe_place.begin(); i != impl_->safe_place.end();) + { + if (i->first->thread_id == thread_id) + { + for (auto & fn : i->second) + fn(); + + i = impl_->safe_place.erase(i); + } + else + ++i; + } + } + bool check_tree(basic_window* wd, basic_window* const cond) { if (wd == cond) return true; diff --git a/source/gui/place.cpp b/source/gui/place.cpp index ce0351c3..9d9e9698 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1717,13 +1717,27 @@ namespace nana } - void notify_move_stopped() + void notify_move_stopped() override { if (_m_dockable() && dockable_field && dockable_field->dockarea) dockable_field->dockarea->dock(); indicator_.docker.reset(); } + + void request_close() override + { + auto window_handle = dockable_field->dockarea->handle(); + + //a workaround for capture + auto ptr = dockable_field->dockarea.release(); + API::at_safe_place(window_handle, [this, ptr] + { + decltype(dockable_field->dockarea) del(ptr); + }); + + API::close_window(window_handle); + } private: bool _m_indicator() const { diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 621b93aa..62bd8753 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -57,12 +57,19 @@ namespace nana virtual void notify_dock() = 0; virtual void notify_move() = 0; virtual void notify_move_stopped() = 0; + + //a dockarea requests to close the dockpane + virtual void request_close() = 0; }; class dockcaption_dtrigger : public drawer_trigger { public: + void on_close(std::function&& fn) + { + close_fn_ = std::move(fn); + } private: virtual void attached(widget_reference wdg, graph_reference graph) override { @@ -84,10 +91,18 @@ namespace nana //draw x button auto r = _m_button_area(); if (x_pointed_) - graph.rectangle(r, true, colors::red); + { + color xclr = colors::red; + + if(x_state_ == ::nana::mouse_action::pressed) + xclr = xclr.blend(colors::white, 0.8); + + graph.rectangle(r, true, xclr); + } r.x += (r.width - 16) / 2; r.y = (r.height - 16) / 2; + x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal); } @@ -105,6 +120,29 @@ namespace nana refresh(graph); API::lazy_refresh(); } + + void mouse_down(graph_reference graph, const arg_mouse&) override + { + if (!x_pointed_) + return; + + x_state_ = ::nana::mouse_action::pressed; + + refresh(graph); + API::lazy_refresh(); + } + + void mouse_up(graph_reference graph, const arg_mouse&) override + { + if (!x_pointed_) + return; + + x_state_ = ::nana::mouse_action::over; + refresh(graph); + API::lazy_refresh(); + + close_fn_(); + } private: ::nana::rectangle _m_button_area() const { @@ -118,12 +156,21 @@ namespace nana window window_handle_; std::unique_ptr text_rd_; bool x_pointed_{ false }; + ::nana::mouse_action x_state_{ ::nana::mouse_action::normal }; facade x_icon_; + + std::function close_fn_; }; class dockarea_caption : public widget_object < category::widget_tag, dockcaption_dtrigger > - {}; + { + public: + void on_close(std::function fn) + { + get_drawer_trigger().on_close(std::move(fn)); + } + }; class dock_page : public form @@ -158,6 +205,22 @@ namespace nana base_type::create(parent, true); this->caption("dockarea"); caption_.create(*this, true); + caption_.on_close([this] + { + bool destroy_dockarea = false; + try + { + tabbar_->erase(tabbar_->selected()); + destroy_dockarea = (0 == tabbar_->length()); + } + catch (std::out_of_range&) + { + destroy_dockarea = true; + } + + if (destroy_dockarea) + notifier_->request_close(); + }); this->events().resized([this](const arg_resized& arg) { diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 94ca4fe4..5d4901b7 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -1314,5 +1314,10 @@ namespace API internal_scope_guard lock; return (restrict::window_manager.available(iwd) ? iwd->flags.ignore_mouse_focus : false); } + + void at_safe_place(window wd, std::function fn) + { + restrict::window_manager.set_safe_place(reinterpret_cast(wd), std::move(fn)); + } }//end namespace API }//end namespace nana diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 3796a1ac..cb6eb878 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1555,15 +1555,7 @@ namespace nana { auto& items = get_drawer_trigger().get_model()->items(); internal_scope_guard lock; - - std::size_t off = 0; - auto i = items.cbegin(), end = items.cend(); - while (i != end) - { - ++i; - ++off; - } - return off; + return static_cast(std::distance(items.cbegin(), items.cend())); } //modifiers @@ -1613,5 +1605,54 @@ namespace nana items.emplace_front(std::move(text), std::move(any)); API::refresh_window(handle()); } + + std::size_t tabbar_lite::selected() const + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + return model->get_indexes().active_pos; + } + + void tabbar_lite::erase(std::size_t pos, bool close_attached) + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + const auto len = length(); + + if (len <= pos) + throw std::out_of_range("tabbar_lite: out of range"); + + auto active_pos = model->get_indexes().active_pos; + + if (pos == active_pos) + { + if (active_pos + 1 == len) + { + if (active_pos) + --active_pos; + else + active_pos = npos; + } + } + else if (pos < active_pos) + --active_pos; + + model->get_indexes().active_pos = active_pos; + + auto i = model->items().cbefore_begin(); + std::advance(i, pos); + + auto attached_wd = std::next(i)->attached_window; + + model->items().erase_after(i); + + model->show_attached_window(); + API::refresh_window(handle()); + + if (close_attached && attached_wd) + API::close_window(attached_wd); + } //end class tabbar }//end namespace nana From c04751ac1acdd617f45c582b10c5007b408ee7ff Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 20 Sep 2015 23:34:57 +0800 Subject: [PATCH 18/22] remove some compiler warning --- source/gui/place.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 9d9e9698..598bd962 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1980,6 +1980,7 @@ namespace nana } ::nana::rectangle child_r; + double split_range_begin = -1, split_range_end; switch (child->dir) { default: @@ -1992,7 +1993,8 @@ namespace nana if (split) { split->move(rectangle{ child_r.right(), child_r.y, splitter_px, child_r.height }); - split->range(left - weight, right - static_cast(splitter_px)); + split_range_begin = left - weight; + split_range_end = right - static_cast(splitter_px); left += splitter_px; } break; @@ -2005,7 +2007,8 @@ namespace nana if (split) { split->move(rectangle{ child_r.x - static_cast(splitter_px), child_r.y, splitter_px, child_r.height }); - split->range(left, right - static_cast(splitter_px)+weight); + split_range_begin = left; + split_range_end = right - static_cast(splitter_px)+weight; right -= splitter_px; } break; @@ -2018,7 +2021,8 @@ namespace nana if (split) { split->move(rectangle{ child_r.x, child_r.bottom(), child_r.width, splitter_px }); - split->range(top - weight, bottom - static_cast(splitter_px)); + split_range_begin = top - weight; + split_range_end = bottom - static_cast(splitter_px); top += splitter_px; } break; @@ -2032,11 +2036,16 @@ namespace nana { bottom -= splitter_px; split->move(rectangle{ child_r.x, child_r.y - static_cast(splitter_px), child_r.width, splitter_px }); - split->range(top, bottom + weight); + split_range_begin = top; + split_range_end = bottom + weight; } break; } + if (split_range_begin > -0.5) + split->range(static_cast(split_range_begin), static_cast(split_range_end)); + + if (is_vert) { room.height -= child_r.height; From 8dcd7307155a11b3b5ba2719d9912d6a8a23e3b5 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 21 Sep 2015 23:43:00 +0800 Subject: [PATCH 19/22] improve dockpane caption --- include/nana/gui/programming_interface.hpp | 7 +++ include/nana/gui/widgets/combox.hpp | 4 +- include/nana/gui/widgets/listbox.hpp | 4 +- include/nana/gui/widgets/spinbox.hpp | 4 +- include/nana/gui/widgets/tabbar.hpp | 56 +++++++++++++------- include/nana/gui/widgets/textbox.hpp | 4 +- include/nana/gui/widgets/widget.hpp | 14 +++-- source/gui/place.cpp | 2 +- source/gui/place_parts.hpp | 19 ++++++- source/gui/widgets/tabbar.cpp | 60 +++++++++++++++++----- 10 files changed, 132 insertions(+), 42 deletions(-) diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 932e35c8..6de9ba97 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -29,6 +29,13 @@ namespace nana /// Traits for widget classes template struct widget_traits + { + using event_type = typename Widget::event_type; + using scheme_type = typename Widget::scheme_type; + }; + + template<> + struct widget_traits { using event_type = ::nana::general_events; using scheme_type = ::nana::widget_colors; diff --git a/include/nana/gui/widgets/combox.hpp b/include/nana/gui/widgets/combox.hpp index beb1cece..17bb7cfe 100644 --- a/include/nana/gui/widgets/combox.hpp +++ b/include/nana/gui/widgets/combox.hpp @@ -229,7 +229,8 @@ namespace nana nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override; }; - namespace dev + /* + namespace dev //deprecated { template<> struct widget_traits @@ -238,5 +239,6 @@ namespace nana using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ } #endif diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 140d6dd2..652171a4 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -664,14 +664,16 @@ By \a clicking on one header the list get \a reordered, first up, and then down void _m_erase_key(nana::detail::key_interface*); }; + /* namespace dev { template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::listbox::listbox_events; using scheme_type = drawerbase::listbox::scheme; }; } + */ }//end namespace nana #endif diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index 22b780e4..09e64faf 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -110,15 +110,17 @@ namespace nana void _m_caption(::nana::string&&); }; //end class spinbox + /* namespace dev { template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::spinbox::spinbox_events; using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ }//end namespace nana #endif //NANA_GUI_WIDGET_SPINBOX_HPP diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 86556cec..3f412f9b 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -336,13 +336,19 @@ namespace nana namespace nana -{ +{ namespace drawerbase { namespace tabbar_lite { class model; + struct events + : public general_events + { + basic_event selected; + }; + class driver : public drawer_trigger { @@ -364,25 +370,39 @@ namespace nana } }//end namespace drawerbase - class tabbar_lite - : public widget_object + class tabbar_lite + : public widget_object + { + public: + tabbar_lite() = default; + tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); + + public: //capacity + std::size_t length() const; + + public: //modifiers + void attach(std::size_t pos, window); + window attach(std::size_t pos) const; + + void push_back(std::string text, ::nana::any par = {}); + void push_front(std::string text, ::nana::any par = {}); + + std::size_t selected() const; + void erase(std::size_t pos, bool close_attached = true); + }; + + /* + namespace dev + { + /// Traits for widget classes + template<> + struct widget_traits //deprecated { - public: - tabbar_lite() = default; - tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); - - public: //capacity - std::size_t length() const; - - public: //modifiers - void attach(std::size_t pos, window); - - void push_back(std::string text, ::nana::any par = {}); - void push_front(std::string text, ::nana::any par = {}); - - std::size_t selected() const; - void erase(std::size_t pos, bool close_attached = true); + using event_type = drawerbase::tabbar_lite::events; + using scheme_type = ::nana::widget_colors; }; + } + */ } #endif diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index 85bac2a6..4360cd74 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -195,15 +195,17 @@ namespace nana void _m_typeface(const paint::font&) override; }; + /* namespace dev { /// Traits for widget classes template<> - struct widget_traits + struct widget_traits //deprecated { using event_type = drawerbase::textbox::textbox_events; using scheme_type = ::nana::widgets::skeletons::text_editor_scheme; }; } + */ }//end namespace nana #endif diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 0288388e..2da63cda 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -134,7 +134,8 @@ namespace nana protected: typedef DrawerTrigger drawer_trigger_t; public: - using scheme_type = Scheme; + using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, @@ -147,7 +148,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -228,6 +229,7 @@ namespace nana typedef DrawerTrigger drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, scheme_{ API::dev::make_scheme() } @@ -239,7 +241,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -297,6 +299,7 @@ namespace nana typedef DrawerTrigger drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() { @@ -322,7 +325,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } @@ -451,6 +454,7 @@ namespace nana typedef int drawer_trigger_t; public: using scheme_type = Scheme; + using event_type = Events; widget_object() : events_{ std::make_shared() }, scheme_{ API::dev::make_scheme() } @@ -462,7 +466,7 @@ namespace nana API::close_window(handle_); } - Events& events() const + event_type& events() const { return *events_; } diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 598bd962..1e8d96ac 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -2829,7 +2829,7 @@ namespace nana { auto i = impl_->dock_factoris.find(factory); if (i == impl_->dock_factoris.end()) - throw std::invalid_argument("nana::place - invalid factory name(" + factory + ")"); + throw std::invalid_argument("invalid factory name(" + factory + ") of dockpane"); auto dock_ptr = i->second; dock_ptr->attached->set_display(true); diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 62bd8753..accb35c9 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -85,7 +85,6 @@ namespace nana //draw caption auto text = API::window_caption(window_handle_); - text = L"dockarea-caption"; text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, true); //draw x button @@ -303,6 +302,17 @@ namespace nana if (!tabbar_ && panels_.size() > 0) { tabbar_.reset(new tabbar_lite(*this)); + + tabbar_->events().selected.clear(); + tabbar_->events().selected([this] + { + auto handle = tabbar_->attach(tabbar_->selected()); + if (handle) + caption_.caption(API::window_caption(handle)); + else + caption_.caption(::nana::string()); + }); + tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); r.height -= 20; @@ -319,7 +329,12 @@ namespace nana if (tabbar_) { tabbar_->push_back(::nana::charset(wdg->caption())); - tabbar_->attach(panels_.size(), *wdg); + tabbar_->attach(panels_.size(), wdg->handle()); + } + + if (panels_.empty()) + { + caption_.caption(wdg->caption()); } panels_.emplace_back(); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index cb6eb878..959d5ff7 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -344,7 +344,7 @@ namespace nana { if(i < list_.size()) return at_no_bound_check(i); - throw std::out_of_range("Nana.GUI.tabbar::at() is out of range"); + throw std::out_of_range("invalid position of tabbar"); } iterator iterator_at(std::size_t pos) @@ -370,7 +370,7 @@ namespace nana { if(pos < list_.size()) return at_no_bound_check(pos); - throw std::out_of_range("Nana.GUI.tabbar::at() const is out of range"); + throw std::out_of_range("invalid position of tabbar"); } const nana::any& at_no_bound_check(std::size_t pos) const @@ -1345,15 +1345,21 @@ namespace nana using graph_reference = ::nana::paint::graphics&; static const std::size_t npos = static_cast(-1); - void set_widget(widget& wdg) + void set_widget(::nana::tabbar_lite& wdg) { widget_ = &wdg; } - ::nana::dev::widget_traits::scheme_type & scheme() + ::nana::tabbar_lite* widget_ptr() const + { + return widget_; + } + /* + ::nana::dev::widget_traits::scheme_type & scheme() //deprecated { return API::scheme(*widget_); } + */ std::forward_list& items() { @@ -1407,7 +1413,7 @@ namespace nana return indexes_; } private: - widget * widget_{ nullptr }; + ::nana::tabbar_lite * widget_{ nullptr }; std::forward_list items_; indexes indexes_; }; @@ -1421,7 +1427,7 @@ namespace nana { _m_calc_metrics(graph, model.items()); - auto & scheme = model.scheme(); + auto & scheme = model.widget_ptr()->scheme(); //draw background graph.rectangle(true, scheme.background); @@ -1499,7 +1505,7 @@ namespace nana void driver::attached(widget_reference wdg, graph_reference) { - model_->set_widget(wdg); + model_->set_widget(dynamic_cast(wdg)); } //Overrides drawer_trigger's method @@ -1533,11 +1539,17 @@ namespace nana if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos)) return; - indexes.active_pos = indexes.hovered_pos; - model_->show_attached_window(); + if (indexes.active_pos != indexes.hovered_pos) + { + indexes.active_pos = indexes.hovered_pos; + model_->show_attached_window(); - refresh(graph); - API::lazy_refresh(); + refresh(graph); + API::lazy_refresh(); + + event_arg arg; + model_->widget_ptr()->events().selected.emit(arg); + } } //end class driver } @@ -1577,6 +1589,20 @@ namespace nana throw std::out_of_range("invalid position of tabbar_lite"); } + window tabbar_lite::attach(std::size_t pos_set) const + { + auto model = get_drawer_trigger().get_model(); + internal_scope_guard lock; + + for (auto & m : model->items()) + { + if (0 == pos_set--) + return m.attached_window; + } + + throw std::out_of_range("invalid position of tabbar_lite"); + } + void tabbar_lite::push_back(std::string text, ::nana::any any) { auto & items = get_drawer_trigger().get_model()->items(); @@ -1622,10 +1648,12 @@ namespace nana const auto len = length(); if (len <= pos) - throw std::out_of_range("tabbar_lite: out of range"); + throw std::out_of_range("invalid position of tabbar_lite"); auto active_pos = model->get_indexes().active_pos; + //selection_changed is used to determine whether the title will be updated + bool selection_changed = true; if (pos == active_pos) { if (active_pos + 1 == len) @@ -1638,6 +1666,8 @@ namespace nana } else if (pos < active_pos) --active_pos; + else + selection_changed = false; model->get_indexes().active_pos = active_pos; @@ -1653,6 +1683,12 @@ namespace nana if (close_attached && attached_wd) API::close_window(attached_wd); + + if (selection_changed) + { + event_arg arg; + events().selected.emit(arg); + } } //end class tabbar }//end namespace nana From ccb334a907d3f8388d5e326cba08779c085bbc59 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 22 Sep 2015 21:05:50 +0800 Subject: [PATCH 20/22] fix an crash that caused by accessing an non-existing tabbar --- source/gui/place_parts.hpp | 11 +++++------ source/gui/widgets/tabbar.cpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index accb35c9..f82c043e 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -206,16 +206,15 @@ namespace nana caption_.create(*this, true); caption_.on_close([this] { - bool destroy_dockarea = false; - try + bool destroy_dockarea = true; + + if (tabbar_) { tabbar_->erase(tabbar_->selected()); + destroy_dockarea = (0 == tabbar_->length()); } - catch (std::out_of_range&) - { - destroy_dockarea = true; - } + if (destroy_dockarea) notifier_->request_close(); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 959d5ff7..bbaabeeb 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1684,7 +1684,7 @@ namespace nana if (close_attached && attached_wd) API::close_window(attached_wd); - if (selection_changed) + if (selection_changed && (active_pos != npos)) { event_arg arg; events().selected.emit(arg); From 8d4ffa068d086bc885c3e5b6c4b3c5ea8a1ff57c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 22 Sep 2015 23:41:55 +0800 Subject: [PATCH 21/22] improve re-div of a dock place --- source/gui/place.cpp | 51 ++++++++++++++++++++++++++------------ source/gui/place_parts.hpp | 5 +++- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 1e8d96ac..39a72f60 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -468,6 +468,7 @@ namespace nana //connect the field/dock with div object void connect(division* start); + void disconnect(); }; //end struct implement class place::implement::field_gather @@ -2490,15 +2491,7 @@ namespace nana if (!start) return; - //disconnect - for (auto & fd : fields) - { - if (fd.second->attached) - { - fd.second->attached->field = nullptr; - fd.second->attached = nullptr; - } - } + this->disconnect(); std::map docks_to_be_closed; //disconnect @@ -2508,12 +2501,12 @@ namespace nana docks_to_be_closed[dk.first] = dk.second; } - std::function check_fn; - check_fn = [&check_fn, this, &docks_to_be_closed](division* div) + std::function connect_fn; + connect_fn = [&connect_fn, this, &docks_to_be_closed](division* div) { if (div->name.size()) { - if (division::kind::dock == div->kind_of_division) + if (division::kind::dock == div->kind_of_division || division::kind::dockpane == div->kind_of_division) { auto i = docks.find(div->name); if (i != docks.end()) @@ -2521,7 +2514,18 @@ namespace nana docks_to_be_closed.erase(div->name); auto pane = dynamic_cast(div); pane->dockable_field = i->second; + + auto old_pane = pane->dockable_field->attached; + if (old_pane) + { + //old div_dockpane will be deleted + old_pane->dockable_field = nullptr; + div->display = old_pane->display; + } pane->dockable_field->attached = pane; + + if (pane->dockable_field->dockarea) + pane->dockable_field->dockarea->set_notifier(pane); } } else @@ -2538,11 +2542,11 @@ namespace nana for (auto & child : div->children) { - check_fn(child.get()); + connect_fn(child.get()); } }; - check_fn(start); + connect_fn(start); for (auto& e : docks_to_be_closed) { @@ -2552,6 +2556,18 @@ namespace nana } } + void place::implement::disconnect() + { + for (auto & fd : fields) + { + if (fd.second->attached) + { + fd.second->attached->field = nullptr; + fd.second->attached = nullptr; + } + } + } + //class place place::place() : impl_(new implement) @@ -2592,6 +2608,7 @@ namespace nana void place::div(const char* s) { place_parts::tokenizer tknizer(s); + impl_->disconnect(); auto div = impl_->scan_div(tknizer); try { @@ -2816,7 +2833,8 @@ namespace nana 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->create(impl_->window_handle); + dock_ptr->dockarea->set_notifier(dock_ptr->attached); dock_ptr->dockarea->move(dock_ptr->attached->field_area); } dock_ptr->dockarea->add_pane(factory); @@ -2838,7 +2856,8 @@ namespace nana 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->create(impl_->window_handle); + dock_ptr->dockarea->set_notifier(dock_ptr->attached); dock_ptr->dockarea->move(dock_ptr->attached->field_area); } diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index f82c043e..686fc4c3 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -197,9 +197,12 @@ namespace nana std::unique_ptr widget_ptr; }; public: - void create(window parent, place_parts::dock_notifier_interface* notifier) + void set_notifier(place_parts::dock_notifier_interface* notifier) { notifier_ = notifier; + } + void create(window parent) + { host_window_ = parent; base_type::create(parent, true); this->caption("dockarea"); From b6dd03e2d5c1944ab4f90d6c4ffe611570145684 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 23 Sep 2015 23:59:31 +0800 Subject: [PATCH 22/22] some small place fixes --- source/gui/place.cpp | 3 +++ source/gui/place_parts.hpp | 41 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 39a72f60..8654f3aa 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1737,6 +1737,9 @@ namespace nana decltype(dockable_field->dockarea) del(ptr); }); + this->set_display(false); + impl_ptr_->collocate(); + API::close_window(window_handle); } private: diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 686fc4c3..946d03ac 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -301,30 +301,35 @@ namespace nana else r.height = 0; - if (!tabbar_ && panels_.size() > 0) + if (!tabbar_) { - tabbar_.reset(new tabbar_lite(*this)); - - tabbar_->events().selected.clear(); - tabbar_->events().selected([this] + if (panels_.size() > 0) { - auto handle = tabbar_->attach(tabbar_->selected()); - if (handle) - caption_.caption(API::window_caption(handle)); - else - caption_.caption(::nana::string()); - }); + tabbar_.reset(new tabbar_lite(*this)); - tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); - r.height -= 20; + tabbar_->events().selected.clear(); + tabbar_->events().selected([this] + { + auto handle = tabbar_->attach(tabbar_->selected()); + if (handle) + caption_.caption(API::window_caption(handle)); + else + caption_.caption(::nana::string()); + }); - std::size_t pos = 0; - for (auto & pn : panels_) - { - tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); - tabbar_->attach(pos++, *pn.widget_ptr); + 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); + } } } + else + r.height -= 20; auto wdg = fn(*this);