From 1e551f4e557c498e4d33ddda92ecd1a825c5e244 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 18 Dec 2017 22:10:01 +0800 Subject: [PATCH 01/27] add check for C++17 constexpr if --- include/nana/c++defines.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 04b5113f..70db8f8f 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -199,6 +199,11 @@ # define _enable_std_clamp #endif +#undef _nana_cxx_constexpr_if +#if (defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG>= 201703) +# define _nana_cxx_constexpr_if +#endif + #if defined(NANA_WINDOWS) #ifndef _UNICODE From 486e75f3ae63421352b3c82f5849c3ae9492c6c1 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 18 Dec 2017 22:13:03 +0800 Subject: [PATCH 02/27] apply constexpr if --- include/nana/gui/detail/general_events.hpp | 51 ++++++++++++++++++++-- include/nana/gui/programming_interface.hpp | 28 ++++++++++++ source/gui/widgets/spinbox.cpp | 32 +++++++++++++- 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/include/nana/gui/detail/general_events.hpp b/include/nana/gui/detail/general_events.hpp index 5992f1a0..c776678a 100644 --- a/include/nana/gui/detail/general_events.hpp +++ b/include/nana/gui/detail/general_events.hpp @@ -1,7 +1,7 @@ /** * Definition of General Events * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -133,11 +133,25 @@ namespace nana /// Creates an event handler at the beginning of event chain template event_handle connect_front(Function && fn) - { + { +#ifdef _nana_cxx_constexpr_if + if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, fn, false }, true); + } + else if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, [fn](arg_reference) { + fn(); + }, false }, true); + } +#else using prototype = typename std::remove_reference::type; return _m_emplace(new docker(this, factory::value>::build(std::forward(fn)), false), true); +#endif } +#ifndef _nana_cxx_constexpr_if /// It will not get called if stop_propagation() was called. event_handle connect(void (*fn)(arg_reference)) { @@ -145,13 +159,27 @@ namespace nana fn(arg); }); } +#endif /// It will not get called if stop_propagation() was called, because it is set at the end of the chain.. template event_handle connect(Function && fn) { +#ifdef _nana_cxx_constexpr_if + if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, fn, false }, false); + } + else if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, [fn](arg_reference){ + fn(); + }, false }, false); + } +#else using prototype = typename std::remove_reference::type; return _m_emplace(new docker(this, factory::value>::build(std::forward(fn)), false), false); +#endif } /// It will not get called if stop_propagation() was called. @@ -164,10 +192,22 @@ namespace nana /// It will get called because it is unignorable. template event_handle connect_unignorable(Function && fn, bool in_front = false) - { + { +#ifdef _nana_cxx_constexpr_if + if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, fn, true }, in_front); + } + else if constexpr(std::is_invocable_v) + { + return _m_emplace(new docker{ this, [fn](arg_reference) { + fn(); + }, true }, in_front); + } +#else using prototype = typename std::remove_reference::type; - return _m_emplace(new docker(this, factory::value>::build(std::forward(fn)), true), in_front); +#endif } void emit(arg_reference& arg, window window_handle) @@ -210,6 +250,8 @@ namespace nana } } private: + +#ifndef _nana_cxx_constexpr_if template struct factory { @@ -385,6 +427,7 @@ namespace nana }; } }; +#endif }; struct arg_mouse diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 8c0d85fe..b5d3e8c2 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -245,6 +245,19 @@ namespace API if (nullptr == general_evt) throw std::invalid_argument("API::events(): bad parameter window handle, no events object or invalid window handle."); +#ifdef _nana_cxx_constexpr_if + if constexpr(std::is_same_v) + { + return *general_evt; + } + else + { + auto * widget_evt = dynamic_cast(general_evt); + if (nullptr == widget_evt) + throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match."); + return *widget_evt; + } +#else if (std::is_same<::nana::general_events, event_type>::value) return *static_cast(general_evt); @@ -252,6 +265,7 @@ namespace API if (nullptr == widget_evt) throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match."); return *widget_evt; +#endif } template::value>::type* = nullptr> @@ -278,6 +292,19 @@ namespace API if (nullptr == wdg_colors) throw std::invalid_argument("API::scheme(): bad parameter window handle, no events object or invalid window handle."); +#ifdef _nana_cxx_constexpr_if + if constexpr(std::is_same<::nana::widget_geometrics, scheme_type>::value) + { + return *static_cast(wdg_colors); + } + else + { + auto * comp_wdg_colors = dynamic_cast(wdg_colors); + if (nullptr == comp_wdg_colors) + throw std::invalid_argument("API::scheme(): bad template parameter Widget, the widget type and window handle do not match."); + return *comp_wdg_colors; + } +#else if (std::is_same<::nana::widget_geometrics, scheme_type>::value) return *static_cast(wdg_colors); @@ -285,6 +312,7 @@ namespace API if (nullptr == comp_wdg_colors) throw std::invalid_argument("API::scheme(): bad template parameter Widget, the widget type and window handle do not match."); return *comp_wdg_colors; +#endif } point window_position(window); diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 41b592f3..5bf2b342 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -82,10 +82,39 @@ namespace nana bool check_value(const std::string& str) const override { +#ifdef _nana_cxx_constexpr_if + auto i = str.c_str(); + if ('+' == *i || '-' == *i) + ++i; + + if constexpr(std::is_same::value) + { + for (; 0 != *i; ++i) + { + if (*i < '0' || '9' < *i) + return false; + } + } + else + { + bool dot = false; + for (; 0 != *i; ++i) + { + if (('.' == *i) && (!dot)) + { + dot = true; + continue; + } + + if (*i < '0' || '9' < *i) + return false; + } + } +#else if (str.empty()) return true; - auto size = str.size(); + auto const size = str.size(); std::size_t pos = 0; if (str[0] == '+' || str[0] == '-') pos = 1; @@ -115,6 +144,7 @@ namespace nana return false; } } +#endif return true; } From 5f77c73aaafbec8f43f2fe70314978580661c7b2 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 19 Dec 2017 03:30:38 +0800 Subject: [PATCH 03/27] no throw() --- include/nana/gui/programming_interface.hpp | 2 +- include/nana/gui/widgets/combox.hpp | 2 +- include/nana/gui/widgets/group.hpp | 6 +++--- include/nana/gui/widgets/label.hpp | 4 ++-- include/nana/gui/widgets/spinbox.hpp | 2 +- include/nana/gui/widgets/tabbar.hpp | 2 +- include/nana/gui/widgets/textbox.hpp | 2 +- include/nana/gui/widgets/widget.hpp | 8 ++++---- include/nana/paint/graphics.hpp | 2 +- source/gui/programming_interface.cpp | 2 +- source/gui/widgets/combox.cpp | 2 +- source/gui/widgets/group.cpp | 2 +- source/gui/widgets/label.cpp | 4 ++-- source/gui/widgets/spinbox.cpp | 2 +- source/gui/widgets/tabbar.cpp | 2 +- source/gui/widgets/textbox.cpp | 2 +- source/gui/widgets/widget.cpp | 8 ++++---- source/paint/graphics.cpp | 2 +- 18 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index b5d3e8c2..45ca629c 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -80,7 +80,7 @@ namespace API void set_measurer(window, ::nana::dev::widget_content_measurer_interface*); void attach_drawer(widget&, drawer_trigger&); - ::nana::detail::native_string_type window_caption(window) throw(); + ::nana::detail::native_string_type window_caption(window) noexcept; void window_caption(window, ::nana::detail::native_string_type); window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached); diff --git a/include/nana/gui/widgets/combox.hpp b/include/nana/gui/widgets/combox.hpp index fc8e4522..551c65d3 100644 --- a/include/nana/gui/widgets/combox.hpp +++ b/include/nana/gui/widgets/combox.hpp @@ -223,7 +223,7 @@ namespace nana const drawerbase::combox::drawer_impl& _m_impl() const; private: //Overrides widget's virtual functions - native_string_type _m_caption() const throw() override; + native_string_type _m_caption() const noexcept override; void _m_caption(native_string_type&&) override; nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override; }; diff --git a/include/nana/gui/widgets/group.hpp b/include/nana/gui/widgets/group.hpp index 2e264289..1bc4d963 100644 --- a/include/nana/gui/widgets/group.hpp +++ b/include/nana/gui/widgets/group.hpp @@ -63,8 +63,8 @@ namespace nana{ group& enable_format_caption(bool format); - group& collocate() throw(); - group& div(const char* div_str) throw(); + group& collocate() noexcept; + group& div(const char* div_str) noexcept; field_reference operator[](const char* field); template @@ -78,7 +78,7 @@ namespace nana{ void _m_add_child(const char* field, widget*); void _m_init(); void _m_complete_creation() override; - native_string_type _m_caption() const throw() override; + native_string_type _m_caption() const noexcept override; void _m_caption(native_string_type&&) override; private: std::unique_ptr impl_; diff --git a/include/nana/gui/widgets/label.hpp b/include/nana/gui/widgets/label.hpp index ee26383b..09d990e4 100644 --- a/include/nana/gui/widgets/label.hpp +++ b/include/nana/gui/widgets/label.hpp @@ -62,12 +62,12 @@ namespace nana label(window parent, const char* text, bool visible = true) :label(parent, std::string(text),visible) {}; label(window, const rectangle& = {}, bool visible = true); label& transparent(bool); ///< Switchs the label widget to the transparent background mode. - bool transparent() const throw(); + bool transparent() const noexcept; label& format(bool); ///< Switches the format mode of the widget. label& add_format_listener(std::function); /// as same as the HTML "for" attribute of a label - label& click_for(window associated_window) throw(); + label& click_for(window associated_window) noexcept; /// Returns the size of the text. If *allowed_width_in_pixel* is not zero, returns a /// "corrected" size that changes lines to fit the text into the specified width diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index 15cbc694..7815250c 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -113,7 +113,7 @@ namespace nana void modifier(std::string prefix_utf8, std::string suffix_utf8); void modifier(const std::wstring & prefix, const std::wstring& suffix); private: - native_string_type _m_caption() const throw(); + native_string_type _m_caption() const noexcept; void _m_caption(native_string_type&&); }; //end class spinbox }//end namespace nana diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 0e2e2e9c..1c492fae 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -384,7 +384,7 @@ namespace nana driver(); ~driver(); - model* get_model() const throw(); + model* get_model() const noexcept; private: //Overrides drawer_trigger's method void attached(widget_reference, graph_reference) override; diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index 5f6dbc91..ed8d6c91 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -276,7 +276,7 @@ namespace nana std::size_t text_line_count() const noexcept; protected: //Overrides widget's virtual functions - native_string_type _m_caption() const throw() override; + native_string_type _m_caption() const noexcept override; void _m_caption(native_string_type&&) override; void _m_typeface(const paint::font&) override; }; diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 0ee37703..c4834cbf 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -54,9 +54,9 @@ namespace nana window parent() const; - ::std::string caption() const throw(); - ::std::wstring caption_wstring() const throw(); - native_string_type caption_native() const throw(); + ::std::string caption() const noexcept; + ::std::wstring caption_wstring() const noexcept; + native_string_type caption_native() const noexcept; widget& caption(std::string utf8); widget& caption(std::wstring); @@ -130,7 +130,7 @@ namespace nana virtual void _m_complete_creation(); virtual general_events& _m_get_general_events() const = 0; - virtual native_string_type _m_caption() const throw(); + virtual native_string_type _m_caption() const noexcept; virtual void _m_caption(native_string_type&&); virtual nana::cursor _m_cursor() const; virtual void _m_cursor(nana::cursor); diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index 9ce35704..800b88c5 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -149,7 +149,7 @@ namespace nana /// Saves images as a windows bitmap file /// @param file_utf8 A UTF-8 string to a filename - void save_as_file(const char* file_utf8) const throw(); + void save_as_file(const char* file_utf8) const noexcept; ::nana::color palette(bool for_text) const; graphics& palette(bool for_text, const ::nana::color&); diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 22e22cac..1e1fdddd 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -242,7 +242,7 @@ namespace API } } - ::nana::detail::native_string_type window_caption(window wd) throw() + ::nana::detail::native_string_type window_caption(window wd) noexcept { auto const iwd = reinterpret_cast(wd); internal_scope_guard isg; diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index c9b6311d..812c6d44 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -1037,7 +1037,7 @@ namespace nana API::refresh_window(*this); } - auto combox::_m_caption() const throw() -> native_string_type + auto combox::_m_caption() const noexcept -> native_string_type { internal_scope_guard lock; auto editor = _m_impl().editor(); diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index ab8e9e73..63458f8b 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -239,7 +239,7 @@ namespace nana{ _m_init(); } - auto group::_m_caption() const throw() -> native_string_type + auto group::_m_caption() const noexcept -> native_string_type { return impl_->caption.caption_native(); } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 1d436f68..300d0fcc 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -825,7 +825,7 @@ namespace nana return *this; } - bool label::transparent() const throw() + bool label::transparent() const noexcept { return API::is_transparent_background(*this); } @@ -849,7 +849,7 @@ namespace nana return *this; } - label& label::click_for(window associated_window) throw() + label& label::click_for(window associated_window) noexcept { get_drawer_trigger().impl()->for_associated_wd = associated_window; return *this; diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 5bf2b342..5a62b10a 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -764,7 +764,7 @@ namespace nana modifier(to_utf8(prefix), to_utf8(suffix)); } - auto spinbox::_m_caption() const throw() -> native_string_type + auto spinbox::_m_caption() const noexcept -> native_string_type { internal_scope_guard lock; auto editor = get_drawer_trigger().impl()->editor(); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index ad614c09..2337f468 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1533,7 +1533,7 @@ namespace nana delete model_; } - model* driver::get_model() const throw() + model* driver::get_model() const noexcept { return model_; } diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index de6e2dd9..96c927f3 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -785,7 +785,7 @@ namespace drawerbase { } //Override _m_caption for caption() - auto textbox::_m_caption() const throw() -> native_string_type + auto textbox::_m_caption() const noexcept -> native_string_type { internal_scope_guard lock; auto editor = get_drawer_trigger().editor(); diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index 183768ab..bcc239ad 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -54,12 +54,12 @@ namespace nana widget& wdg_; }; - std::string widget::caption() const throw() + std::string widget::caption() const noexcept { return to_utf8(_m_caption()); } - std::wstring widget::caption_wstring() const throw() + std::wstring widget::caption_wstring() const noexcept { #if defined(NANA_WINDOWS) return _m_caption(); @@ -68,7 +68,7 @@ namespace nana #endif } - auto widget::caption_native() const throw() -> native_string_type + auto widget::caption_native() const noexcept -> native_string_type { return _m_caption(); } @@ -282,7 +282,7 @@ namespace nana void widget::_m_complete_creation() {} - auto widget::_m_caption() const throw() -> native_string_type + auto widget::_m_caption() const noexcept -> native_string_type { return API::dev::window_caption(handle()); } diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 62f74016..49857d2e 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -934,7 +934,7 @@ namespace paint impl_->size.width = impl_->size.height = 0; } - void graphics::save_as_file(const char* file_utf8) const throw() + void graphics::save_as_file(const char* file_utf8) const noexcept { if(impl_->handle) { From 9d75d15474653fa5fb20d99089c2d759f22d3648 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Dec 2017 01:28:05 +0800 Subject: [PATCH 04/27] add detection of C++17 folding experssion --- include/nana/c++defines.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 70db8f8f..98c23dc4 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -202,6 +202,7 @@ #undef _nana_cxx_constexpr_if #if (defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG>= 201703) # define _nana_cxx_constexpr_if +# define _nana_cxx_folding_expression #endif From c66895ead61a4b2ed9bd60c5d0b136686d10a617 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Dec 2017 11:53:29 +0800 Subject: [PATCH 05/27] apply C++17 folding expression --- include/nana/gui/msgbox.hpp | 6 ++++++ source/gui/msgbox.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/include/nana/gui/msgbox.hpp b/include/nana/gui/msgbox.hpp index 67840f1a..382bb4d8 100644 --- a/include/nana/gui/msgbox.hpp +++ b/include/nana/gui/msgbox.hpp @@ -240,7 +240,11 @@ namespace nana bool show(Args&& ... args) { std::vector contents; +#ifdef _nana_cxx_folding_expression + (contents.emplace_back(&args), ...); +#else _m_fetch_args(contents, std::forward(args)...); +#endif if (contents.empty()) return false; @@ -270,6 +274,7 @@ namespace nana void min_width_entry_field( unsigned pixels ); private: +#ifndef _nana_cxx_folding_expression void _m_fetch_args(std::vector&); template @@ -278,6 +283,7 @@ namespace nana contents.push_back(&content); _m_fetch_args(contents, std::forward(args)...); } +#endif bool _m_open(std::vector&, bool modal); private: diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index 75ce6a23..36a7c202 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -1294,8 +1294,10 @@ namespace nana min_width_entry_field_pixels_ = pixels; } +#ifndef _nana_cxx_folding_expression void inputbox::_m_fetch_args(std::vector&) {} +#endif bool inputbox::_m_open(std::vector& contents, bool modal) { From 4917b18c705c9468a2810528163d88ae535ec82b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Dec 2017 13:51:32 +0800 Subject: [PATCH 06/27] deprecate std::iterator because of C++17 --- include/nana/c++defines.hpp | 1 + .../gui/widgets/detail/widget_iterator.hpp | 36 +++++++++++++++++++ include/nana/gui/widgets/listbox.hpp | 7 ++-- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 include/nana/gui/widgets/detail/widget_iterator.hpp diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 98c23dc4..fa43923d 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -203,6 +203,7 @@ #if (defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG>= 201703) # define _nana_cxx_constexpr_if # define _nana_cxx_folding_expression +# define _nana_cxx_nested_namespace_definition #endif diff --git a/include/nana/gui/widgets/detail/widget_iterator.hpp b/include/nana/gui/widgets/detail/widget_iterator.hpp new file mode 100644 index 00000000..c78e5d4d --- /dev/null +++ b/include/nana/gui/widgets/detail/widget_iterator.hpp @@ -0,0 +1,36 @@ +/* + * A Widget Iterator Template + * Copyright(C) 2017 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/widgets/detail/widget_iterator.hpp + * @description: widget_iterator is the base class provided to simplify definitions of the required types for widget iterators. + * It is provided because of deprecation of std::iterator in C++17 + */ +#ifndef NANA_GUI_WIDGET_ITERATOR_INCLUDED +#define NANA_GUI_WIDGET_ITERATOR_INCLUDED + +#include //provides std::ptrdiff_t + + +namespace nana { + namespace widgets { + namespace detail + { + template + class widget_iterator + { + using iterator_category = Category; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T * ; + using reference = T & ; + }; + } + } +} + +#endif diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 71280b7e..0137ff51 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -23,6 +23,7 @@ #include "widget.hpp" #include "detail/inline_widget.hpp" +#include "detail/widget_iterator.hpp" #include #include #include @@ -802,7 +803,8 @@ namespace nana /// operate with absolute positions and contain only the position but montain pointers to parts of the real items /// item_proxy self, it references and iterators are not invalidated by sort() class item_proxy - : public std::iterator + //: public std::iterator //deprecated + : public ::nana::widgets::detail::widget_iterator { public: item_proxy(essence*, const index_pair& = index_pair{npos, npos}); @@ -976,7 +978,8 @@ namespace nana }; class cat_proxy - : public std::iterator < std::input_iterator_tag, cat_proxy > + //: public std::iterator //deprecated + : public ::nana::widgets::detail::widget_iterator { public: using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface; From be836b5b480311df1511659337ec62ef1c4befe6 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Dec 2017 00:10:10 +0800 Subject: [PATCH 07/27] apply folding expression and std::optional --- include/nana/c++defines.hpp | 1 + .../widget_content_measurer_interface.hpp | 8 +++-- include/nana/gui/programming_interface.hpp | 2 +- include/nana/internationalization.hpp | 35 +++++++++++++------ include/nana/optional.hpp | 10 +++++- source/gui/programming_interface.cpp | 2 +- source/gui/widgets/button.cpp | 2 +- source/gui/widgets/combox.cpp | 2 +- source/gui/widgets/label.cpp | 2 +- source/gui/widgets/picture.cpp | 2 +- source/internationalization.cpp | 20 ++++++----- 11 files changed, 58 insertions(+), 28 deletions(-) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index fa43923d..80b8e504 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -204,6 +204,7 @@ # define _nana_cxx_constexpr_if # define _nana_cxx_folding_expression # define _nana_cxx_nested_namespace_definition +# define _nana_std_optional #endif diff --git a/include/nana/gui/detail/widget_content_measurer_interface.hpp b/include/nana/gui/detail/widget_content_measurer_interface.hpp index 4f175493..22184c34 100644 --- a/include/nana/gui/detail/widget_content_measurer_interface.hpp +++ b/include/nana/gui/detail/widget_content_measurer_interface.hpp @@ -14,7 +14,11 @@ #define NANA_WIDGET_CONTENT_MEASURER_INTERFACE_HEADER_INCLUDED #include -#include +#ifdef _nana_std_optional +# include +#else +# include +#endif #include namespace nana @@ -35,7 +39,7 @@ namespace nana * @param limit_width True if limits the width, false if limits the height. * @return the size of content. */ - virtual optional measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const = 0; + virtual ::std::optional measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const = 0; /// Returns the extension to the size of widget from content extent /** diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 45ca629c..db7e2ac2 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -461,7 +461,7 @@ namespace API * @return if optional has a value, the first size indicates the content extent, the second size indicates the size of * widget by the content extent. */ - optional> content_extent(window wd, unsigned limited_px, bool limit_width); + std::optional> content_extent(window wd, unsigned limited_px, bool limit_width); }//end namespace API }//end namespace nana diff --git a/include/nana/internationalization.hpp b/include/nana/internationalization.hpp index 4b3e3918..86c31250 100644 --- a/include/nana/internationalization.hpp +++ b/include/nana/internationalization.hpp @@ -34,7 +34,12 @@ namespace nana ::std::string get(std::string msgid_utf8, Args&&... args) const { std::vector arg_strs; + +#ifdef _nana_cxx_folding_expression + (_m_fetch_args(arg_strs, std::forward(args)),...); +#else _m_fetch_args(arg_strs, std::forward(args)...); +#endif auto msgstr = _m_get(std::move(msgid_utf8)); _m_replace_args(msgstr, &arg_strs); @@ -53,25 +58,28 @@ namespace nana std::string _m_get(std::string&& msgid) const; void _m_replace_args(::std::string& str, std::vector<::std::string> * arg_strs) const; - void _m_fetch_args(std::vector&) const; //Termination of _m_fetch_args +#ifndef _nana_cxx_folding_expression + static void _m_fetch_args(std::vector&); //Termination of _m_fetch_args +#endif - void _m_fetch_args(std::vector& v, const char* arg) const; - void _m_fetch_args(std::vector& v, const std::string& arg) const; - void _m_fetch_args(std::vector& v, std::string& arg) const; - void _m_fetch_args(std::vector& v, std::string&& arg) const; - void _m_fetch_args(std::vector& v, const wchar_t* arg) const; - void _m_fetch_args(std::vector& v, const std::wstring& arg) const; - void _m_fetch_args(std::vector& v, std::wstring& arg) const; - void _m_fetch_args(std::vector& v, std::wstring&& arg) const; + static void _m_fetch_args(std::vector& v, const char* arg); + static void _m_fetch_args(std::vector& v, const std::string& arg); + static void _m_fetch_args(std::vector& v, std::string& arg); + static void _m_fetch_args(std::vector& v, std::string&& arg); + static void _m_fetch_args(std::vector& v, const wchar_t* arg); + static void _m_fetch_args(std::vector& v, const std::wstring& arg); + static void _m_fetch_args(std::vector& v, std::wstring& arg); + static void _m_fetch_args(std::vector& v, std::wstring&& arg); template - void _m_fetch_args(std::vector& v, Arg&& arg) const + static void _m_fetch_args(std::vector& v, Arg&& arg) { std::stringstream ss; ss << arg; v.emplace_back(ss.str()); } +#ifndef _nana_cxx_folding_expression template void _m_fetch_args(std::vector& v, const char* arg, Args&&... args) const { @@ -136,6 +144,7 @@ namespace nana v.emplace_back(ss.str()); _m_fetch_args(v, std::forward(args)...); } +#endif };//end class internationalization class i18n_eval @@ -180,7 +189,11 @@ namespace nana i18n_eval(std::string msgid_utf8, Args&&... args) : msgid_(std::move(msgid_utf8)) { +#ifdef _nana_cxx_folding_expression + (_m_fetch_args(std::forward(args)), ...); +#else _m_fetch_args(std::forward(args)...); +#endif } i18n_eval(const i18n_eval&); @@ -193,6 +206,7 @@ namespace nana std::string operator()() const; private: +#ifndef _nana_cxx_folding_expression void _m_fetch_args(){} //Termination of _m_fetch_args template @@ -201,6 +215,7 @@ namespace nana _m_add_args(std::forward(arg)); _m_fetch_args(std::forward(args)...); } +#endif template void _m_add_args(Arg&& arg) diff --git a/include/nana/optional.hpp b/include/nana/optional.hpp index 49b81d88..17b4189e 100644 --- a/include/nana/optional.hpp +++ b/include/nana/optional.hpp @@ -15,8 +15,11 @@ #ifndef NANA_STD_OPTIONAL_HEADER_INCLUDED #define NANA_STD_OPTIONAL_HEADER_INCLUDED -#include #include + +#ifndef _nana_std_optional +#include + namespace nana { namespace detail @@ -361,4 +364,9 @@ namespace nana }; } +namespace std +{ + using nana::optional; +} +#endif //_nana_std_optional #endif diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 1e1fdddd..7aed26a3 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -1450,7 +1450,7 @@ namespace API restrict::wd_manager().set_safe_place(reinterpret_cast(wd), std::move(fn)); } - optional> content_extent(window wd, unsigned limited_px, bool limit_width) + std::optional> content_extent(window wd, unsigned limited_px, bool limit_width) { auto iwd = reinterpret_cast(wd); internal_scope_guard lock; diff --git a/source/gui/widgets/button.cpp b/source/gui/widgets/button.cpp index a01d001b..752f084f 100644 --- a/source/gui/widgets/button.cpp +++ b/source/gui/widgets/button.cpp @@ -27,7 +27,7 @@ namespace nana{ namespace drawerbase : trigger_{ t } {} - optional measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override + std::optional measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override { //Button doesn't provide a support of vfit and hfit if (limit_pixels) diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index 812c6d44..dcaf5c43 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -90,7 +90,7 @@ namespace nana : drw_{ drwimpl } {} - optional measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override + std::optional measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override { //Combox doesn't provide a support of vfit and hfit if (limit_pixels) diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 300d0fcc..bf670c12 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -653,7 +653,7 @@ namespace nana : impl_{ impl } {} - optional measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override + std::optional measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override { //Label now doesn't support to measure content with a specified height. if (graph && ((0 == limit_pixels) || limit_width)) diff --git a/source/gui/widgets/picture.cpp b/source/gui/widgets/picture.cpp index 356072b9..cba8a75c 100644 --- a/source/gui/widgets/picture.cpp +++ b/source/gui/widgets/picture.cpp @@ -74,7 +74,7 @@ namespace nana : impl_{impl} {} - optional measure(graph_reference /*graph*/, unsigned limit_pixels, bool /*limit_width*/) const override + std::optional measure(graph_reference /*graph*/, unsigned limit_pixels, bool /*limit_width*/) const override { //Picture doesn't provide a support of vfit and hfit if (!limit_pixels) diff --git a/source/internationalization.cpp b/source/internationalization.cpp index 87c92437..4252d73c 100644 --- a/source/internationalization.cpp +++ b/source/internationalization.cpp @@ -414,45 +414,47 @@ namespace nana } } - void internationalization::_m_fetch_args(std::vector&) const +#ifndef _nana_cxx_folding_expression + void internationalization::_m_fetch_args(std::vector&) {} +#endif - void internationalization::_m_fetch_args(std::vector& v, const char* arg) const + void internationalization::_m_fetch_args(std::vector& v, const char* arg) { v.emplace_back(arg); } - void internationalization::_m_fetch_args(std::vector& v, const std::string& arg) const + void internationalization::_m_fetch_args(std::vector& v, const std::string& arg) { v.emplace_back(arg); } - void internationalization::_m_fetch_args(std::vector& v, std::string& arg) const + void internationalization::_m_fetch_args(std::vector& v, std::string& arg) { v.emplace_back(arg); } - void internationalization::_m_fetch_args(std::vector& v, std::string&& arg) const + void internationalization::_m_fetch_args(std::vector& v, std::string&& arg) { v.emplace_back(std::move(arg)); } - void internationalization::_m_fetch_args(std::vector& v, const wchar_t* arg) const + void internationalization::_m_fetch_args(std::vector& v, const wchar_t* arg) { v.emplace_back(to_utf8(arg)); } - void internationalization::_m_fetch_args(std::vector& v, const std::wstring& arg) const + void internationalization::_m_fetch_args(std::vector& v, const std::wstring& arg) { v.emplace_back(to_utf8(arg)); } - void internationalization::_m_fetch_args(std::vector& v, std::wstring& arg) const + void internationalization::_m_fetch_args(std::vector& v, std::wstring& arg) { v.emplace_back(to_utf8(arg)); } - void internationalization::_m_fetch_args(std::vector& v, std::wstring&& arg) const + void internationalization::_m_fetch_args(std::vector& v, std::wstring&& arg) { v.emplace_back(to_utf8(arg)); } From 9c1f348a80728d307f7bd797b3ea7f22507d352c Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Mon, 29 Jan 2018 01:35:09 +0100 Subject: [PATCH 08/27] Fix travis test/demos with gcc 4.9 and boost 1.54 --- include/nana/filesystem/filesystem.hpp | 31 ++++++++++++++++++++++ include/nana/filesystem/filesystem_ext.hpp | 11 ++++++++ 2 files changed, 42 insertions(+) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 067586f5..b6c358b7 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -55,6 +55,37 @@ #define NANA_USING_BOOST_FILESYSTEM 1 # include # include +// dont include generic_u8string +// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp +// enable directory_iterator C++11 range-base for +// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp +// but travis come with an oooold version of boost +// NOT enable directory_iterator C++11 range-base for +// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp +namespace boost +{ + namespace filesystem + { + + // enable directory_iterator C++11 range-base for statement use --------------------// + + // begin() and end() are only used by a range-based for statement in the context of + // auto - thus the top-level const is stripped - so returning const is harmless and + // emphasizes begin() is just a pass through. + inline + const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT + { + return iter; + } + inline + directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT + { + return directory_iterator(); + } + + } // namespace filesystem +} + // add boost::filesystem into std::experimental::filesystem namespace std { diff --git a/include/nana/filesystem/filesystem_ext.hpp b/include/nana/filesystem/filesystem_ext.hpp index 2c28acad..3458a198 100644 --- a/include/nana/filesystem/filesystem_ext.hpp +++ b/include/nana/filesystem/filesystem_ext.hpp @@ -16,6 +16,7 @@ #define NANA_FILESYSTEM_EXT_HPP #include +#include namespace nana { @@ -34,6 +35,16 @@ namespace filesystem_ext std::experimental::filesystem::path path_user(); ///< extention ? + /// workaround Boost not having path.generic_u8string() - a good point for http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0251r0.pdf +inline std::string generic_u8string(const std::experimental::filesystem::path& p) +{ +#if NANA_USING_BOOST_FILESYSTEM + return nana::to_utf8(p.generic_wstring()); +#else + return p.generic_u8string(); +#endif +} + inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept { return is_directory(dir.status()); From 48f759e0070944a33a5776543e226af6bcd2f3eb Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 29 May 2018 04:12:53 +0800 Subject: [PATCH 09/27] remove deprecated code --- include/nana/gui/widgets/listbox.hpp | 3 --- source/gui/detail/bedrock_windows.cpp | 27 ------------------- source/gui/place.cpp | 7 ++--- source/gui/widgets/skeletons/content_view.cpp | 6 ----- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 1fe6aeca..36a38f65 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -1215,9 +1215,6 @@ namespace nana unsigned suspension_width{ 8 }; ///< def= . the trigger will set this to the width if ("...") unsigned text_margin{ 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1 - //deprecated - //unsigned header_height { 25 }; ///< def=25 . header height header_size - unsigned item_height_ex{ 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex unsigned header_splitter_area_before{ 2 }; ///< def=2. But 4 is better... IMO unsigned header_splitter_area_after{ 3 }; ///< def=3. But 4 is better... diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index e402a25e..d8769fd9 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -408,16 +408,7 @@ namespace detail if (msg.message == WM_QUIT) break; if ((WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST) || !::IsDialogMessage(native_handle, &msg)) { -#if 0 - auto menu_wd = get_menu(reinterpret_cast(msg.hwnd), true); - if (menu_wd) interior_helper_for_menu(msg, menu_wd); - - ::TranslateMessage(&msg); //deprecated - ::DispatchMessage(&msg); -#else process_msg(this, msg); -#endif - wd_manager().remove_trash_handle(tid); } } @@ -429,15 +420,7 @@ namespace detail { if (-1 != ::GetMessage(&msg, 0, 0, 0)) { -#if 0 - auto menu_wd = get_menu(reinterpret_cast(msg.hwnd), true); - if (menu_wd) interior_helper_for_menu(msg, menu_wd); - - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); -#else process_msg(this, msg); -#endif } wd_manager().call_safe_place(tid); @@ -452,17 +435,7 @@ namespace detail while(context->window_count) { if(-1 != ::GetMessage(&msg, 0, 0, 0)) - { -#if 0 - auto menu_wd = get_menu(reinterpret_cast(msg.hwnd), true); - if(menu_wd) interior_helper_for_menu(msg, menu_wd); - - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); -#else process_msg(this, msg); -#endif - } wd_manager().call_safe_place(tid); wd_manager().remove_trash_handle(tid); diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 5a9982c6..192fbf98 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -2583,9 +2583,8 @@ namespace nana : public division { public: - div_switchable(std::string && name, implement* /*impl*/) noexcept: - division(kind::switchable, std::move(name))//, - //impl_(impl) //deprecated + div_switchable(std::string && name, implement*) noexcept: + division(kind::switchable, std::move(name)) {} private: void collocate(window wd) override @@ -2613,8 +2612,6 @@ namespace nana } } } - private: - //implement * const impl_; //deprecated }; place::implement::~implement() diff --git a/source/gui/widgets/skeletons/content_view.cpp b/source/gui/widgets/skeletons/content_view.cpp index b7d8f722..27899183 100644 --- a/source/gui/widgets/skeletons/content_view.cpp +++ b/source/gui/widgets/skeletons/content_view.cpp @@ -68,12 +68,6 @@ namespace nana { bool drag_started{ false }; point origin; - /* - scrolls enabled_scrolls{scrolls::both}; //deprecated - nana::scroll horz; - nana::scroll vert; - */ - std::shared_ptr cv_scroll; timer tmr; From 6a66b03663631f663a713cc38a81d7796cd52ec3 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 29 May 2018 04:14:01 +0800 Subject: [PATCH 10/27] fix a syntax error --- source/audio/detail/audio_device.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/audio/detail/audio_device.cpp b/source/audio/detail/audio_device.cpp index 73a0ee8b..cf7f4966 100644 --- a/source/audio/detail/audio_device.cpp +++ b/source/audio/detail/audio_device.cpp @@ -65,7 +65,7 @@ namespace nana{namespace audio bool audio_device::empty() const { -#if defined(NANA_POSIX) && not defined(NANA_LINUX) +#if defined(NANA_POSIX) && !defined(NANA_LINUX) return (-1 == handle_); #else return (nullptr == handle_); @@ -305,7 +305,7 @@ namespace nana{namespace audio }//end namespace audio }//end namespace nana -#if defined(NANA_POSIX) && not defined(NANA_LINUX) +#if defined(NANA_POSIX) && !defined(NANA_LINUX) // parse input securely, no-overruns or overflows. static bool match(char *&cursor, const char *pattern, const char *tail) { From d5f8f8b305f9c04972014b6a354b9269eb2d8aa6 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 29 May 2018 05:45:57 +0800 Subject: [PATCH 11/27] improve support of opengl for Linux --- include/nana/gui/programming_interface.hpp | 10 ++++++++++ source/gui/detail/bedrock_posix.cpp | 17 ++++++++++++----- source/gui/programming_interface.cpp | 17 ++++++++++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index cb795e5f..7d7e0538 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -45,6 +45,15 @@ namespace nana namespace API { +#ifdef NANA_X11 + //Some platform specific functions for X11 + namespace x11 + { + /// Returns the connection to the X server + const void* get_display(); + } +#endif + namespace detail { ::nana::widget_geometrics* make_scheme(::nana::detail::scheme_factory_interface&&); @@ -110,6 +119,7 @@ namespace API void draw_shortkey_underline(paint::graphics&, const std::string& text, wchar_t shortkey, std::size_t shortkey_position, const point& text_pos, const color&); }//end namespace dev + /// Returns the widget pointer of the specified window. /* * @param window_handle A handle to a window owning the widget. diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index f72525fd..571b91bc 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -911,11 +911,18 @@ namespace detail case Expose: if(msgwnd->visible && (msgwnd->root_graph->empty() == false)) { - nana::detail::platform_scope_guard psg; - //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. - ::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); - if (!update_area.empty()) - msgwnd->drawer.map(reinterpret_cast(msgwnd), true, &update_area); + nana::detail::platform_scope_guard lock; + if(msgwnd->is_draw_through()) + { + msgwnd->other.attribute.root->draw_through(); + } + else + { + //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. + ::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); + if (!update_area.empty()) + msgwnd->drawer.map(reinterpret_cast(msgwnd), true, &update_area); + } } break; case KeyPress: diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 7ed9883f..da45698b 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -21,6 +21,9 @@ #include #include "../../source/detail/platform_abstraction.hpp" +#ifdef NANA_X11 +# include "../../source/detail/posix/platform_spec.hpp" +#endif namespace nana { @@ -52,6 +55,19 @@ namespace nana } namespace API { +#ifdef NANA_X11 + //Some platform specific functions for X11 + namespace x11 + { + /// Returns the connection to the X server + const void* get_display() + { + auto & spec = nana::detail::platform_spec::instance(); + return spec.open_display(); + } + } +#endif + using basic_window = ::nana::detail::basic_window; using interface_type = ::nana::detail::native_interface; @@ -392,7 +408,6 @@ namespace API } }//end namespace dev - widget* get_widget(window wd) { internal_scope_guard lock; From 24f9aa58a7c10ab02efc31eb1ab51e98e4e02682 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 6 Jun 2018 23:23:49 +0800 Subject: [PATCH 12/27] improve C++ feature test --- include/nana/c++defines.hpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 850113b8..39637097 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -36,10 +36,15 @@ * - STD_TO_STRING_NOT_SUPPORTED (MinGW with GCC < 4.8) * - STD_FILESYSTEM_NOT_SUPPORTED (GCC < 5.3) .... * - CXX_NO_INLINE_NAMESPACE (Visual C++ < 2015) + * + * There are two kinds of flags: + * * _nana_std_xxx indicates that nana provides a standard-like class for workaround of lack of C++ support. + * * _nana_std_has_xxx indicates that nana detects whether a C++ feature is supported. Nana doesn't provide a standard-like class for this missing feature. + * * - _nana_std_make_unique (__cpluscplus < 201402) * - _nana_std_put_time (GCC < 5) * - _nana_std_clamp (Visual C++ < 2017) - */ + */ #ifndef NANA_CXX_DEFINES_INCLUDED #define NANA_CXX_DEFINES_INCLUDED @@ -195,7 +200,6 @@ # define _nana_std_make_unique #endif - //Detects the feature std::clamp //Visual C++ 2017 with /std:c++latest provides the std::clamp #undef _nana_std_clamp @@ -207,12 +211,23 @@ #undef _nana_std_optional -#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG>= 201703)) || \ - (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400)) || \ - (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 701) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201703))) || \ + ((__cplusplus < 201703L) || \ + (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ < 400)) || \ + (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 701)) \ + ) # define _nana_std_optional #endif +#undef _nana_std_has_string_view +#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) || \ + ((__cplusplus >= 201703L) && \ + (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) || \ + (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \ + ) +# define _nana_std_has_string_view +#endif + #if defined(NANA_WINDOWS) #ifndef _UNICODE From 0290e49fbe39ac4cd98db96d6bbe7bca68cf1928 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 03:33:39 +0800 Subject: [PATCH 13/27] let the param of place.div be a string(#298) --- include/nana/gui/place.hpp | 4 ++-- source/gui/place.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index 6ead606d..b0202e4f 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -1,7 +1,7 @@ /* * An Implementation of Place for Layout * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -119,7 +119,7 @@ namespace nana void splitter_renderer(std::function fn); - void div(const char* s); ///< Divides the attached widget into fields. + void div(std::string div_text); ///< Divides the attached widget into fields. const std::string& div() const noexcept; ///< Returns div-text that depends on fields status. void modify(const char* field_name, const char* div_text); ///< Modifies a specified field. diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 192fbf98..715c084d 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -64,8 +64,8 @@ namespace nana eof, error }; - tokenizer(const char* p) noexcept - : divstr_(p), sp_(p) + tokenizer(const char* div_text) noexcept + : divstr_(div_text), sp_(div_text) {} const std::string& idstr() const noexcept @@ -3180,9 +3180,9 @@ namespace nana sp->set_renderer(impl_->split_renderer, true); } - void place::div(const char* s) + void place::div(std::string div_text) { - place_parts::tokenizer tknizer(s); + place_parts::tokenizer tknizer(div_text.c_str()); impl_->disconnect(); auto div = impl_->scan_div(tknizer); try @@ -3190,7 +3190,7 @@ namespace nana impl_->connect(div.get()); //throws if there is a redefined name of field. impl_->root_division.reset(); //clear atachments div-fields impl_->root_division.swap(div); - impl_->div_text.assign(s); + impl_->div_text.swap(div_text); } catch (...) { @@ -3321,7 +3321,7 @@ namespace nana return *p; } - void update_div(std::string& div, const char* field, const char* attr, update_operation operation) + static void update_div(std::string& div, const char* field, const char* attr, update_operation operation) { const auto fieldname_pos = find_idstr(div, field); if (div.npos == fieldname_pos) From 549b3d435351900efd3c3c37e5b7a0697e306e4e Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 03:36:30 +0800 Subject: [PATCH 14/27] fix _nana_std_optional --- include/nana/optional.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nana/optional.hpp b/include/nana/optional.hpp index 1bb8373b..741e0b9f 100644 --- a/include/nana/optional.hpp +++ b/include/nana/optional.hpp @@ -17,7 +17,7 @@ #include -#ifdef _nana_std_optional +#ifndef _nana_std_optional #include #else #include From 34271814056e5ace93ddafce64b877c6353fce17 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 03:41:08 +0800 Subject: [PATCH 15/27] std::string_view --- include/nana/deploy.hpp | 16 +++- .../paint/detail/native_paint_interface.hpp | 7 +- include/nana/paint/graphics.hpp | 12 +++ source/deploy.cpp | 88 ++++++++++++++---- source/gui/programming_interface.cpp | 5 + source/gui/widgets/checkbox.cpp | 4 + source/gui/widgets/label.cpp | 8 ++ source/gui/widgets/skeletons/text_editor.cpp | 17 ++++ source/gui/widgets/treebox.cpp | 4 + .../paint/detail/native_paint_interface.cpp | 91 +++++++++++++++---- source/paint/graphics.cpp | 34 ++++++- source/paint/text_renderer.cpp | 9 ++ 12 files changed, 251 insertions(+), 44 deletions(-) diff --git a/include/nana/deploy.hpp b/include/nana/deploy.hpp index 686bb4ce..c9d12f88 100644 --- a/include/nana/deploy.hpp +++ b/include/nana/deploy.hpp @@ -1,7 +1,7 @@ /* * The Deploy Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,10 @@ #include +#ifdef _nana_std_has_string_view +#include +#endif + namespace nana { /// move to *.h ?? @@ -44,10 +48,15 @@ namespace nana /// Checks whether a specified text is utf8 encoding +#ifdef _nana_std_has_string_view + bool is_utf8(std::string_view str); + void throw_not_utf8(std::string_view str); +#else bool is_utf8(const char* str, std::size_t len); void throw_not_utf8(const std::string& text); void throw_not_utf8(const char*, std::size_t len); void throw_not_utf8(const char*); +#endif /// this text needed change, it needed review ?? bool review_utf8(const std::string& text); @@ -58,7 +67,12 @@ namespace nana const std::string& to_utf8(const std::string&); std::string to_utf8(const std::wstring&); +#ifdef _nana_std_has_string_view + std::wstring to_wstring(std::string_view utf8_str); +#else std::wstring to_wstring(const std::string& utf8_str); +#endif + const std::wstring& to_wstring(const std::wstring& wstr); std::wstring&& to_wstring(std::wstring&& wstr); diff --git a/include/nana/paint/detail/native_paint_interface.hpp b/include/nana/paint/detail/native_paint_interface.hpp index 844427a5..a6cc4534 100644 --- a/include/nana/paint/detail/native_paint_interface.hpp +++ b/include/nana/paint/detail/native_paint_interface.hpp @@ -1,6 +1,6 @@ /* * Platform Implementation - * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -32,8 +32,11 @@ namespace detail //dw color = dw color * fade_rate + bdcolor * (1 - fade_rate) void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t bdcolor, double fade_rate); - nana::size raw_text_extent_size(drawable_type, const wchar_t*, std::size_t len); + nana::size real_text_extent_size(drawable_type, const char*, std::size_t len); + nana::size real_text_extent_size(drawable_type, const wchar_t*, std::size_t len); + nana::size text_extent_size(drawable_type, const char*, std::size_t len); nana::size text_extent_size(drawable_type, const wchar_t*, std::size_t len); + void draw_string(drawable_type, const nana::point&, const wchar_t *, std::size_t len); }//end namespace detail }//end namespace paint diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index f3b33aa5..bea13f4b 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -21,6 +21,10 @@ #include "detail/ptdefs.hpp" +#ifdef _nana_std_has_string_view +#include +#endif + namespace nana { namespace paint @@ -108,12 +112,20 @@ namespace nana void resize(const ::nana::size&); void typeface(const font&); ///< Selects a specified font type into the graphics object. font typeface() const; + +#ifdef _nana_std_has_string_view + ::nana::size text_extent_size(std::string_view text) const; + ::nana::size text_extent_size(std::wstring_view text) const; +#else ::nana::size text_extent_size(const ::std::string&) const; ::nana::size text_extent_size(const char*, std::size_t len) const; + ::nana::size text_extent_size(const wchar_t*) const; ///< Computes the width and height of the specified string of text. ::nana::size text_extent_size(const ::std::wstring&) const; ///< Computes the width and height of the specified string of text. ::nana::size text_extent_size(const wchar_t*, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. ::nana::size text_extent_size(const ::std::wstring&, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. +#endif + ::nana::size glyph_extent_size(const wchar_t*, std::size_t length, std::size_t begin, std::size_t end) const; ::nana::size glyph_extent_size(const ::std::wstring&, std::size_t length, std::size_t begin, std::size_t end) const; bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const; diff --git a/source/deploy.cpp b/source/deploy.cpp index a5050e77..06bbda02 100644 --- a/source/deploy.cpp +++ b/source/deploy.cpp @@ -28,6 +28,42 @@ namespace nana { +#ifdef _nana_std_has_string_view + bool is_utf8(std::string_view str) + { + auto ustr = reinterpret_cast(str.data()); + auto end = ustr + str.size(); + + while (ustr < end) + { + const auto uv = *ustr; + if (uv < 0x80) + { + ++ustr; + continue; + } + + if (uv < 0xC0) + return false; + + if ((uv < 0xE0) && (end - ustr > 1)) + ustr += 2; + else if ((uv < 0xF0) && (end - ustr > 2)) + ustr += 3; + else if ((uv < 0x1F) && (end - ustr > 3)) + ustr += 4; + else + return false; + } + return true; + } + + void throw_not_utf8(std::string_view str) + { + if (!is_utf8(str)) + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(str.data(), str.size())).emit(); + } +#else bool is_utf8(const char* str, std::size_t len) { auto ustr = reinterpret_cast(str); @@ -57,6 +93,23 @@ namespace nana return true; } + void throw_not_utf8(const std::string& text) + { + throw_not_utf8(text.c_str(), text.size()); + } + + void throw_not_utf8(const char* text) + { + throw_not_utf8(text, std::strlen(text)); + } + + void throw_not_utf8(const char* text, std::size_t len) + { + if (!is_utf8(text, len)) + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len)).emit(); + } +#endif + //class utf8_Error #if defined(_MSC_VER) @@ -79,22 +132,6 @@ namespace nana bool utf8_Error::use_throw{ false }; //end class utf8_Error - void throw_not_utf8(const std::string& text) - { - throw_not_utf8(text.c_str(), text.size()); - } - - void throw_not_utf8(const char* text) - { - throw_not_utf8(text, std::strlen(text)); - } - - void throw_not_utf8(const char* text, std::size_t len) - { - if (!is_utf8(text, len)) - return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len) ).emit(); - } - std::string recode_to_utf8(std::string no_utf8) { return nana::charset(std::move(no_utf8)).to_bytes(nana::unicode::utf8); @@ -103,7 +140,11 @@ namespace nana /// this text needed change, it needed review ?? bool review_utf8(const std::string& text) { +#ifdef _nana_std_has_string_view + if (!is_utf8(text)) +#else if (!is_utf8(text.c_str(), text.length())) +#endif { utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit(); return true; /// it needed change, it needed review !! @@ -115,7 +156,11 @@ namespace nana /// this text needed change, it needed review ?? bool review_utf8(std::string& text) { +#ifdef _nana_std_has_string_view + if(!is_utf8(text)) +#else if (!is_utf8(text.c_str(), text.length())) +#endif { utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); text=recode_to_utf8(text); @@ -135,10 +180,21 @@ namespace nana return ::nana::charset(text).to_bytes(::nana::unicode::utf8); } +#ifdef _nana_std_has_string_view + std::wstring to_wstring(std::string_view utf8_str) + { + if (utf8_str.empty()) + return{}; + + return ::nana::charset(std::string{ utf8_str.data(), utf8_str.size() }, unicode::utf8); + } +#else std::wstring to_wstring(const std::string& utf8_str) { return ::nana::charset(utf8_str, ::nana::unicode::utf8); } +#endif + const std::wstring& to_wstring(const std::wstring& wstr) { diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index ed81cef7..374b4250 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -393,8 +393,13 @@ namespace API { if (shortkey) { +#ifdef _nana_std_has_string_view + auto off_x = (shortkey_position ? graph.text_extent_size(std::string_view{ text.c_str(), shortkey_position }).width : 0); + auto key_px = static_cast(graph.text_extent_size(std::wstring_view{ &shortkey, 1 }).width); +#else auto off_x = (shortkey_position ? graph.text_extent_size(text.c_str(), shortkey_position).width : 0); auto key_px = static_cast(graph.text_extent_size(&shortkey, 1).width); +#endif unsigned ascent, descent, inleading; graph.text_metrics(ascent, descent, inleading); diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 7fc20469..66fb22de 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -78,7 +78,11 @@ namespace nana{ namespace drawerbase } //draw crook +#ifdef _nana_std_has_string_view + auto txt_px = graph.text_extent_size(std::wstring_view( L"jN", 2 )).height + 2; +#else auto txt_px = graph.text_extent_size(L"jN", 2).height + 2; +#endif impl_->crook.draw(graph, wdg->bgcolor(), wdg->fgcolor(), rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg)); } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index bf670c12..8168984e 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -83,7 +83,11 @@ namespace nana auto pre_font = graph.typeface(); //used for restoring the font +#ifdef _nana_std_has_string_view + const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view{ L" ", 1 }).height; +#else const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height; +#endif font_ = pre_font; fblock_ = nullptr; @@ -170,7 +174,11 @@ namespace nana auto ft = graph.typeface(); //used for restoring the font +#ifdef _nana_std_has_string_view + const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view(L" ", 1)).height; +#else const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height; +#endif font_ = ft; fblock_ = nullptr; diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 38a4666f..9dc06848 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -3147,7 +3147,11 @@ namespace nana{ namespace widgets maskstr.append(n, mask_char_); return graph_.text_extent_size(maskstr); } +#ifdef _nana_std_has_string_view + return graph_.text_extent_size(std::basic_string_view(str, n)); +#else return graph_.text_extent_size(str, static_cast(n)); +#endif } bool text_editor::_m_adjust_view() @@ -3500,7 +3504,12 @@ namespace nana{ namespace widgets for (auto & ent : reordered) { std::size_t len = ent.end - ent.begin; + +#ifdef _nana_std_has_string_view + unsigned str_w = graph_.text_extent_size(std::wstring_view{ ent.begin, len }).width; +#else unsigned str_w = graph_.text_extent_size(ent.begin, len).width; +#endif if ((text_draw_pos.x + static_cast(str_w) > text_area_.area.x) && (text_draw_pos.x < text_right)) { @@ -3519,7 +3528,11 @@ namespace nana{ namespace widgets for (auto & ent : reordered) { const auto len = ent.end - ent.begin; +#ifdef _nana_std_has_string_view + auto ent_px = graph_.text_extent_size(std::wstring_view(ent.begin, len)).width; +#else auto ent_px = graph_.text_extent_size(ent.begin, len).width; +#endif extra_space = false; @@ -3589,7 +3602,11 @@ namespace nana{ namespace widgets auto pos = text_coord.x + text_len; if (b.x != pos || text_coord.y != b.y) { +#ifdef _nana_std_has_string_view + auto whitespace_w = graph_.text_extent_size(std::wstring_view{ L" ", 1 }).width; +#else auto whitespace_w = graph_.text_extent_size(L" ", 1).width; +#endif graph_.rectangle(::nana::rectangle{ text_draw_pos, { whitespace_w, line_h_pixels } }, true); } } diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 19873e27..c68abb4c 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1163,7 +1163,11 @@ namespace nana virtual unsigned item_height(graph_reference graph) const override { +#ifdef _nana_std_has_string_view + return graph.text_extent_size(std::wstring_view{ L"jH{", 3 }).height + 8; +#else return graph.text_extent_size(L"jH{", 3).height + 8; +#endif } virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 6efb8169..7703747c 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -134,29 +134,80 @@ namespace detail pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y}); } - nana::size raw_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len) + nana::size real_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len) { - if(nullptr == dw || nullptr == text || 0 == len) return nana::size(); + if (dw && text && len) + { + #if defined(NANA_WINDOWS) - ::SIZE size; - if(::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) - return nana::size(size.cx, size.cy); + ::SIZE size; + if (::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) + return nana::size(size.cx, size.cy); #elif defined(NANA_X11) - #if defined(NANA_USE_XFT) - std::string utf8str = to_utf8(std::wstring(text, len)); - XGlyphInfo ext; - XftFont * fs = reinterpret_cast(dw->font->native_handle()); - ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, - reinterpret_cast(const_cast(utf8str.c_str())), utf8str.size(), &ext); - return nana::size(ext.xOff, fs->ascent + fs->descent); - #else - XRectangle ink; - XRectangle logic; - ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), text, len, &ink, &logic); - return nana::size(logic.width, logic.height); - #endif + std::string utf8str = to_utf8(std::wstring(text, len)); +#if defined(NANA_USE_XFT) + XGlyphInfo ext; + XftFont * fs = reinterpret_cast(dw->font->native_handle()); + ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, + reinterpret_cast(const_cast(utf8text.data())), utf8text.size(), &ext); + return nana::size(ext.xOff, fs->ascent + fs->descent); +#else + XRectangle ink; + XRectangle logic; + ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), utf8str.c_str(), utf8str.size(), &ink, &logic); + return nana::size(logic.width, logic.height); #endif - return nana::size(); +#endif + } + return {}; + } + + nana::size real_text_extent_size(drawable_type dw, const char* text, std::size_t len) + { + if (dw && text && len) + { + +#if defined(NANA_WINDOWS) + auto wstr = to_wstring(std::string(text,len)); + ::SIZE size; + if (::GetTextExtentPoint32(dw->context, wstr.c_str(), static_cast(wstr.size()), &size)) + return nana::size(size.cx, size.cy); +#elif defined(NANA_X11) +#if defined(NANA_USE_XFT) + XGlyphInfo ext; + XftFont * fs = reinterpret_cast(dw->font->native_handle()); + ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, + reinterpret_cast(const_cast(text)), len, &ext); + return nana::size(ext.xOff, fs->ascent + fs->descent); +#else + XRectangle ink; + XRectangle logic; + ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), text, len, &ink, &logic); + return nana::size(logic.width, logic.height); +#endif +#endif + } + return {}; + } + + + nana::size text_extent_size(drawable_type dw, const char * text, std::size_t len) + { + if (nullptr == dw || nullptr == text || 0 == len) + return{}; + + nana::size extents = real_text_extent_size(dw, text, len); + + auto const end = text + len; + int tabs = 0; + for (; text != end; ++text) + { + if (*text == '\t') + ++tabs; + } + if (tabs) + extents.width = static_cast(extents.width) - tabs * static_cast(dw->string.tab_pixels - dw->string.whitespace_pixels * dw->string.tab_length); + return extents; } nana::size text_extent_size(drawable_type dw, const wchar_t * text, std::size_t len) @@ -164,7 +215,7 @@ namespace detail if (nullptr == dw || nullptr == text || 0 == len) return{}; - nana::size extents = raw_text_extent_size(dw, text, len); + nana::size extents = real_text_extent_size(dw, text, len); const wchar_t* const end = text + len; int tabs = 0; diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 2d92b435..46b685d1 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -411,8 +411,8 @@ namespace paint impl_->handle = dw.get(); impl_->size = sz; - impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; - impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width; + impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width; + impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width; } } @@ -438,8 +438,9 @@ namespace paint #if defined(NANA_WINDOWS) ::SelectObject(impl_->handle->context, reinterpret_cast(f.impl_->real_font->native_handle())); #endif - impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; - impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width; + + impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width; + impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width; if (impl_->changed == false) impl_->changed = true; @@ -453,6 +454,20 @@ namespace paint return (impl_->handle ? font(impl_->handle) : impl_->font_shadow); } +#ifdef _nana_std_has_string_view + size graphics::text_extent_size(std::string_view text) const + { + throw_not_utf8(text); + return detail::text_extent_size(impl_->handle, text.data(), text.length()); + } + + size graphics::text_extent_size(std::wstring_view text) const + { + return detail::text_extent_size(impl_->handle, text.data(), text.length()); + } + + +#else ::nana::size graphics::text_extent_size(const ::std::string& text) const { throw_not_utf8(text); @@ -483,6 +498,7 @@ namespace paint { return detail::text_extent_size(impl_->handle, str.c_str(), len); } +#endif nana::size graphics::glyph_extent_size(const wchar_t * str, std::size_t len, std::size_t begin, std::size_t end) const { @@ -562,7 +578,11 @@ namespace paint auto const reordered = unicode_reorder(str.c_str(), str.size()); for(auto & i: reordered) { +#ifdef _nana_std_has_string_view + nana::size t = text_extent_size(std::wstring_view( i.begin, i.end - i.begin )); +#else nana::size t = text_extent_size(i.begin, i.end - i.begin); +#endif sz.width += t.width; if(sz.height < t.height) sz.height = t.height; @@ -1011,7 +1031,11 @@ namespace paint for (auto & i : reordered) { string(moved_pos, i.begin, i.end - i.begin); +#ifdef _nana_std_has_string_view + moved_pos.x += static_cast(text_extent_size(std::wstring_view( i.begin, i.end - i.begin )).width); +#else moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); +#endif } return static_cast(moved_pos.x - pos.x); } @@ -1076,7 +1100,7 @@ namespace paint { //Render a part that does not contains a tab detail::draw_string(impl_->handle, pos, str, len); - pos.x += detail::raw_text_extent_size(impl_->handle, str, len).width; + pos.x += detail::real_text_extent_size(impl_->handle, str, len).width; } str = i; diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 07b71e0f..b2848c2f 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -52,6 +52,7 @@ namespace nana { std::size_t len = ent.end - ent.begin; nana::size ts = detail::text_extent_size(dw, ent.begin, len); + if(ts.height > pixels) pixels = ts.height; if(pos.x + static_cast(ts.width) > 0) @@ -128,7 +129,11 @@ namespace nana draw_string_omitted(graphics& graph, int x, int endpos, bool omitted) : graph(graph), x(x), endpos(endpos) { +#ifdef _nana_std_has_string_view + omitted_pixels = (omitted ? graph.text_extent_size(std::string_view{ "...", 3 }).width : 0); +#else omitted_pixels = (omitted ? graph.text_extent_size("...", 3).width : 0); +#endif if (endpos - x > static_cast(omitted_pixels)) this->endpos -= omitted_pixels; else @@ -629,7 +634,11 @@ namespace nana return; } +#ifdef _nana_std_has_string_view + const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width; +#else const auto ellipsis = graph_.text_extent_size("...", 3).width; +#endif std::unique_ptr pixels(new unsigned[text.size()]); graph_.glyph_pixels(text.c_str(), text.size(), pixels.get()); From 7a24df521e32f18789cc3a9d69c74398134ec55a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 03:56:18 +0800 Subject: [PATCH 16/27] fix a compiler error --- source/gui/place.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 715c084d..96d7ac6d 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -3207,7 +3207,7 @@ namespace nana //Contributed by dankan1890(PR#156) enum class update_operation { erase = 0, insert, replace }; - void update_div(std::string& div, const char* field, const char* attr, update_operation operation); + static void update_div(std::string& div, const char* field, const char* attr, update_operation operation); void place::modify(const char* name, const char* div_text) { From 88d395353efc28a085409503d20d9b0e12062cbd Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 15:38:25 +0800 Subject: [PATCH 17/27] fix GCC/Clang compiler errors --- source/paint/detail/native_paint_interface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 7703747c..f14c7a64 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -144,7 +144,7 @@ namespace detail if (::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) return nana::size(size.cx, size.cy); #elif defined(NANA_X11) - std::string utf8str = to_utf8(std::wstring(text, len)); + std::string utf8text = to_utf8(std::wstring(text, len)); #if defined(NANA_USE_XFT) XGlyphInfo ext; XftFont * fs = reinterpret_cast(dw->font->native_handle()); @@ -154,7 +154,7 @@ namespace detail #else XRectangle ink; XRectangle logic; - ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), utf8str.c_str(), utf8str.size(), &ink, &logic); + ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic); return nana::size(logic.width, logic.height); #endif #endif From ffee0e5a3b25eb1c4b6ff6d96a607ed7e64d6357 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 7 Jun 2018 18:02:40 +0800 Subject: [PATCH 18/27] std::string_view --- include/nana/paint/graphics.hpp | 11 +- source/gui/widgets/skeletons/text_editor.cpp | 20 +++ source/paint/graphics.cpp | 136 +++++++++++++++++-- source/paint/text_renderer.cpp | 14 +- 4 files changed, 165 insertions(+), 16 deletions(-) diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index bea13f4b..c0a8f56d 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -1,7 +1,7 @@ /* * Paint Graphics Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -116,6 +116,12 @@ namespace nana #ifdef _nana_std_has_string_view ::nana::size text_extent_size(std::string_view text) const; ::nana::size text_extent_size(std::wstring_view text) const; + + ///Only supports the wide string, because it is very hard to specify the begin and end position in a UTF-8 string. + ::nana::size glyph_extent_size(std::wstring_view text, std::size_t begin, std::size_t end) const; + + bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; + std::unique_ptr glyph_pixels(std::wstring_view text) const; #else ::nana::size text_extent_size(const ::std::string&) const; ::nana::size text_extent_size(const char*, std::size_t len) const; @@ -124,11 +130,12 @@ namespace nana ::nana::size text_extent_size(const ::std::wstring&) const; ///< Computes the width and height of the specified string of text. ::nana::size text_extent_size(const wchar_t*, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. ::nana::size text_extent_size(const ::std::wstring&, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. -#endif ::nana::size glyph_extent_size(const wchar_t*, std::size_t length, std::size_t begin, std::size_t end) const; ::nana::size glyph_extent_size(const ::std::wstring&, std::size_t length, std::size_t begin, std::size_t end) const; + bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const; +#endif ::nana::size bidi_extent_size(const std::wstring&) const; ::nana::size bidi_extent_size(const std::string&) const; diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 9dc06848..d68b2159 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -834,8 +834,12 @@ namespace nana{ namespace widgets if (str_w > pixels) //Indicates the splitting of ts string { std::size_t len = ts.end - ts.begin; +#ifdef _nana_std_has_string_view + auto pxbuf = editor_.graph_.glyph_pixels({ts.begin, len}); +#else std::unique_ptr pxbuf(new unsigned[len]); editor_.graph_.glyph_pixels(ts.begin, len, pxbuf.get()); +#endif auto pxptr = pxbuf.get(); auto pxend = pxptr + len; @@ -3310,8 +3314,12 @@ namespace nana{ namespace widgets if (parser.entities().empty()) return; +#ifdef _nana_std_has_string_view + auto glyph_px = graph_.glyph_pixels({ str, len }); +#else std::unique_ptr glyph_px(new unsigned[len]); graph_.glyph_pixels(str, len, glyph_px.get()); +#endif auto glyphs = glyph_px.get(); auto px_h = line_height(); @@ -3561,8 +3569,12 @@ namespace nana{ namespace widgets unsigned select_pos = static_cast(ent_sbegin != ent.begin ? ent_sbegin - ent.begin : 0); unsigned select_len = static_cast(ent_send - ent_sbegin); +#ifdef _nana_std_has_string_view + auto pxbuf = graph_.glyph_pixels({ ent.begin, static_cast(len) }); +#else std::unique_ptr pxbuf{ new unsigned[len] }; graph_.glyph_pixels(ent.begin, len, pxbuf.get()); +#endif auto head_px = std::accumulate(pxbuf.get(), pxbuf.get() + select_pos, unsigned{}); auto select_px = std::accumulate(pxbuf.get() + select_pos, pxbuf.get() + select_pos + select_len, unsigned{}); @@ -3636,7 +3648,11 @@ namespace nana{ namespace widgets auto len = static_cast(ent.end - ent.begin); std::unique_ptr pxbuf(new unsigned[len]); +#ifdef _nana_std_has_string_view + if (graph_.glyph_pixels({ent.begin, len}, pxbuf.get())) +#else if (graph_.glyph_pixels(ent.begin, len, pxbuf.get())) +#endif { const auto px_end = pxbuf.get() + len; @@ -3695,7 +3711,11 @@ namespace nana{ namespace widgets //Characters of some bidi languages may transform in a word. //RTL std::unique_ptr pxbuf(new unsigned[len]); +#ifdef _nana_std_has_string_view + graph_.glyph_pixels({ent.begin, len}, pxbuf.get()); +#else graph_.glyph_pixels(ent.begin, len, pxbuf.get()); +#endif return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w); } //LTR diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 46b685d1..14a76b0e 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -465,8 +465,116 @@ namespace paint { return detail::text_extent_size(impl_->handle, text.data(), text.length()); } - + nana::size graphics::glyph_extent_size(std::wstring_view text, std::size_t begin, std::size_t end) const + { + end = std::clamp(end, static_cast(0), static_cast(text.size())); + + if (nullptr == impl_->handle || text.empty() || begin >= end) return{}; + + nana::size sz; +#if defined(NANA_WINDOWS) + int * dx = new int[text.size()]; + + SIZE extents; + ::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast(text.size()), 0, 0, dx, &extents); + sz.width = dx[end - 1] - (begin ? dx[begin - 1] : 0); + unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; + const wchar_t * pend = text.data() + end; + for (const wchar_t * p = text.data() + begin; p != pend; ++p) + { + if (*p == '\t') + sz.width += tab_pixels; + } + sz.height = extents.cy; + delete[] dx; +#elif defined(NANA_X11) + sz = text_extent_size(text.substr(begin, end - begin)); +#endif + return sz; + } + + bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const + { + if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == pxbuf) return false; + + if (text.empty()) return true; + + unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; +#if defined(NANA_WINDOWS) + int * dx = new int[text.size()]; + SIZE extents; + ::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast(text.size()), 0, 0, dx, &extents); + + pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]); + + for (std::size_t i = 1; i < text.size(); ++i) + { + pxbuf[i] = (text[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]); + } + delete[] dx; +#elif defined(NANA_X11) && defined(NANA_USE_XFT) + + auto disp = nana::detail::platform_spec::instance().open_display(); + auto xft = reinterpret_cast(impl_->handle->font->native_handle()); + + XGlyphInfo extents; + for (std::size_t i = 0; i < len; ++i) + { + if (text[i] != '\t') + { + FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]); + ::XftGlyphExtents(disp, xft, &glyphs, 1, &extents); + pxbuf[i] = extents.xOff; + } + else + pxbuf[i] = tab_pixels; + } +#endif + return true; + } + + std::unique_ptr graphics::glyph_pixels(std::wstring_view text) const + { + if (nullptr == impl_->handle || nullptr == impl_->handle->context) return {}; + + if (text.empty()) return std::unique_ptr{new unsigned[1]}; + + unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; +#if defined(NANA_WINDOWS) + int * dx = new int[text.size()]; + SIZE extents; + ::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast(text.size()), 0, 0, dx, &extents); + + auto pxbuf = std::unique_ptr{ new unsigned[text.size()] }; + + pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]); + + for (std::size_t i = 1; i < text.size(); ++i) + { + pxbuf[i] = (text[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]); + } + delete[] dx; +#elif defined(NANA_X11) && defined(NANA_USE_XFT) + + auto disp = nana::detail::platform_spec::instance().open_display(); + auto xft = reinterpret_cast(impl_->handle->font->native_handle()); + + XGlyphInfo extents; + for (std::size_t i = 0; i < len; ++i) + { + if (text[i] != '\t') + { + FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]); + ::XftGlyphExtents(disp, xft, &glyphs, 1, &extents); + pxbuf[i] = extents.xOff; + } + else + pxbuf[i] = tab_pixels; + } +#endif + return pxbuf; + } #else ::nana::size graphics::text_extent_size(const ::std::string& text) const { @@ -498,11 +606,10 @@ namespace paint { return detail::text_extent_size(impl_->handle, str.c_str(), len); } -#endif nana::size graphics::glyph_extent_size(const wchar_t * str, std::size_t len, std::size_t begin, std::size_t end) const { - if(len < end) end = len; + if (len < end) end = len; if (nullptr == impl_->handle || nullptr == str || 0 == len || begin >= end) return{}; nana::size sz; @@ -513,13 +620,13 @@ namespace paint sz.width = dx[end - 1] - (begin ? dx[begin - 1] : 0); unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; const wchar_t * pend = str + end; - for(const wchar_t * p = str + begin; p != pend; ++p) + for (const wchar_t * p = str + begin; p != pend; ++p) { - if(*p == '\t') + if (*p == '\t') sz.width += tab_pixels; } sz.height = extents.cy; - delete [] dx; + delete[] dx; #elif defined(NANA_X11) sz = text_extent_size(str + begin, end - begin); #endif @@ -533,8 +640,8 @@ namespace paint bool graphics::glyph_pixels(const wchar_t * str, std::size_t len, unsigned* pxbuf) const { - if(nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == str || nullptr == pxbuf) return false; - if(len == 0) return true; + if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == str || nullptr == pxbuf) return false; + if (len == 0) return true; unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; #if defined(NANA_WINDOWS) @@ -542,22 +649,22 @@ namespace paint SIZE extents; ::GetTextExtentExPoint(impl_->handle->context, str, static_cast(len), 0, 0, dx, &extents); - pxbuf[0] = (str[0] == '\t' ? tab_pixels : dx[0]); + pxbuf[0] = (str[0] == '\t' ? tab_pixels : dx[0]); - for(std::size_t i = 1; i < len; ++i) + for (std::size_t i = 1; i < len; ++i) { pxbuf[i] = (str[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]); } - delete [] dx; + delete[] dx; #elif defined(NANA_X11) && defined(NANA_USE_XFT) auto disp = nana::detail::platform_spec::instance().open_display(); auto xft = reinterpret_cast(impl_->handle->font->native_handle()); XGlyphInfo extents; - for(std::size_t i = 0; i < len; ++i) + for (std::size_t i = 0; i < len; ++i) { - if(str[i] != '\t') + if (str[i] != '\t') { FT_UInt glyphs = ::XftCharIndex(disp, xft, str[i]); ::XftGlyphExtents(disp, xft, &glyphs, 1, &extents); @@ -570,6 +677,9 @@ namespace paint return true; } +#endif + + nana::size graphics::bidi_extent_size(const std::wstring& str) const { nana::size sz; diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index b2848c2f..21a9157a 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -236,7 +236,12 @@ namespace nana std::unique_ptr pixel_buf(new unsigned[len]); //Find the char that should be splitted +#ifdef _nana_std_has_string_view + graph.glyph_pixels({ i.begin, len }, pixel_buf.get()); +#else graph.glyph_pixels(i.begin, len, pixel_buf.get()); +#endif + std::size_t idx_head = 0, idx_splitted; do @@ -456,7 +461,11 @@ namespace nana std::unique_ptr scope_res(new unsigned[len]); auto pxbuf = scope_res.get(); //Find the char that should be splitted +#ifdef _nana_std_has_string_view + graph.glyph_pixels({ i.begin, len }, pxbuf); +#else graph.glyph_pixels(i.begin, len, pxbuf); +#endif std::size_t idx_head = 0, idx_splitted; do @@ -636,12 +645,15 @@ namespace nana #ifdef _nana_std_has_string_view const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width; + + std::unique_ptr pixels(new unsigned[text.size()]); + graph_.glyph_pixels({ text.c_str(), text.size() }, pixels.get()); #else const auto ellipsis = graph_.text_extent_size("...", 3).width; -#endif std::unique_ptr pixels(new unsigned[text.size()]); graph_.glyph_pixels(text.c_str(), text.size(), pixels.get()); +#endif std::size_t substr_len = 0; unsigned substr_px = 0; From fc7743cbe21ec1c9fea86de9647bed3b32b8f685 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 9 Jun 2018 01:21:10 +0800 Subject: [PATCH 19/27] std::string_view --- include/nana/paint/graphics.hpp | 31 ++- source/gui/widgets/button.cpp | 12 +- source/gui/widgets/label.cpp | 13 +- source/gui/widgets/skeletons/text_editor.cpp | 42 ++++- source/gui/widgets/tabbar.cpp | 7 +- .../paint/detail/native_paint_interface.cpp | 4 + source/paint/graphics.cpp | 176 +++++++++++++++--- source/paint/text_renderer.cpp | 34 +++- 8 files changed, 263 insertions(+), 56 deletions(-) diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index c0a8f56d..c50714a3 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -120,8 +120,17 @@ namespace nana ///Only supports the wide string, because it is very hard to specify the begin and end position in a UTF-8 string. ::nana::size glyph_extent_size(std::wstring_view text, std::size_t begin, std::size_t end) const; - bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; + //bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; //deprecated + + /// Returns a buffer which stores the pixel of each charater stored in text. + /** + * @param text The text to be requested. + * @return A buffer which stores the pixel of each character stored in text, its length is same with text's length. If text is empty, it returns a buffer with a senseless value. + */ std::unique_ptr glyph_pixels(std::wstring_view text) const; + + ::nana::size bidi_extent_size(std::string_view utf8_text) const; + ::nana::size bidi_extent_size(std::wstring_view text) const; #else ::nana::size text_extent_size(const ::std::string&) const; ::nana::size text_extent_size(const char*, std::size_t len) const; @@ -135,9 +144,10 @@ namespace nana ::nana::size glyph_extent_size(const ::std::wstring&, std::size_t length, std::size_t begin, std::size_t end) const; bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const; -#endif + ::nana::size bidi_extent_size(const std::wstring&) const; ::nana::size bidi_extent_size(const std::string&) const; +#endif bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const; @@ -180,12 +190,22 @@ namespace nana ::nana::color palette(bool for_text) const; graphics& palette(bool for_text, const ::nana::color&); - unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len); - unsigned bidi_string(const point& pos, const char*, std::size_t len); - void set_pixel(int x, int y, const ::nana::color&); void set_pixel(int x, int y); +#ifdef _nana_std_has_string_view + unsigned bidi_string(const point&, std::string_view utf8str); + unsigned bidi_string(const point& pos, std::wstring_view str); + + void string(const point&, std::string_view utf8str); + void string(const point&, std::string_view utf8str, const nana::color&); + + void string(const point&, std::wstring_view str); + void string(const point&, std::wstring_view str, const nana::color&); +#else + unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len); + unsigned bidi_string(const point& pos, const char*, std::size_t len); + void string(const point&, const std::string& text_utf8); void string(const point&, const std::string& text_utf8, const color&); @@ -193,6 +213,7 @@ namespace nana void string(const point&, const wchar_t*); void string(const point&, const ::std::wstring&); void string(const point&, const ::std::wstring&, const color&); +#endif void line(const point&, const point&); void line(const point&, const point&, const color&); diff --git a/source/gui/widgets/button.cpp b/source/gui/widgets/button.cpp index b7d3214b..c9ba1221 100644 --- a/source/gui/widgets/button.cpp +++ b/source/gui/widgets/button.cpp @@ -1,7 +1,7 @@ /* * A Button Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -262,7 +262,11 @@ namespace nana{ namespace drawerbase if (attr_.omitted) tr.render(pos, txtptr, txtlen, omitted_pixels, true); else +#ifdef _nana_std_has_string_view + graph.bidi_string(pos, { txtptr, txtlen }); +#else graph.bidi_string(pos, txtptr, txtlen); +#endif API::dev::draw_shortkey_underline(graph, mbstr, shortkey, shortkey_pos, pos, text_color); } @@ -277,9 +281,15 @@ namespace nana{ namespace drawerbase } else { +#ifdef _nana_std_has_string_view + graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, { txtptr, txtlen }); + graph.palette(true, color{ colors::gray }); + graph.bidi_string(pos, { txtptr, txtlen }); +#else graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen); graph.palette(true, color{ colors::gray }); graph.bidi_string(pos, txtptr, txtlen); +#endif } } } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 8168984e..7f4f2a4e 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -1,7 +1,7 @@ /* * A Label Control Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-208 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -564,6 +564,16 @@ namespace nana _m_change_font(graph, fblock_ptr); +#ifdef _nana_std_has_string_view + std::wstring_view text_sv{ data_ptr->text() }; + if (text_range.second != text_sv.size()) + { + text_sv = text_sv.substr(text_range.first, text_range.second); + sz = graph.text_extent_size(text_sv); + } + + graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr)); +#else if (text_range.second == data_ptr->text().length()) { graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr)); @@ -575,6 +585,7 @@ namespace nana graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr)); } +#endif _m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr); diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index d68b2159..16963195 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -3309,8 +3309,12 @@ namespace nana{ namespace widgets void text_editor::_m_draw_parse_string(const keyword_parser& parser, bool rtl, ::nana::point pos, const ::nana::color& fgcolor, const wchar_t* str, std::size_t len) const { +#ifdef _nana_std_has_string_view + graph_.string(pos, { str, len }, fgcolor); +#else graph_.palette(true, fgcolor); graph_.string(pos, str, len); +#endif if (parser.entities().empty()) return; @@ -3359,7 +3363,20 @@ namespace nana{ namespace widgets ent_pos.x = pos.x + ent_off; - +#ifdef _nana_std_has_string_view + std::wstring_view ent_sv; + if (rtl) + { + //draw the whole text if it is a RTL text, because Arbic language is transformable. + ent_sv = { str, len }; + } + else + { + ent_sv = { ent_begin, static_cast(ent_end - ent_begin) }; + ent_off = 0; + } + canvas.string({}, ent_sv); +#else if (rtl) { //draw the whole text if it is a RTL text, because Arbic language is transformable. @@ -3370,6 +3387,7 @@ namespace nana{ namespace widgets canvas.string({}, ent_begin, ent_end - ent_begin); ent_off = 0; } +#endif graph_.bitblt(rectangle{ ent_pos, size{ ent_pixels, canvas.height() } }, canvas, point{ ent_off, 0 }); } } @@ -3395,12 +3413,19 @@ namespace nana{ namespace widgets void write_selection(const point& text_pos, unsigned text_px, const wchar_t* text, std::size_t len, bool has_focused) { +#ifdef _nana_std_has_string_view + graph_.rectangle(::nana::rectangle{ text_pos,{ text_px, line_px_ } }, true, + selection_color(false, has_focused)); + + graph_.string(text_pos, { text, len }, selection_color(true, has_focused)); +#else graph_.palette(true, selection_color(true, has_focused)); graph_.rectangle(::nana::rectangle{ text_pos, { text_px, line_px_ } }, true, selection_color(false, has_focused)); graph_.string(text_pos, text, len); +#endif } void rtl_string(point strpos, const wchar_t* str, std::size_t len, std::size_t str_px, unsigned glyph_front, unsigned glyph_selected, bool has_focused) @@ -3414,9 +3439,12 @@ namespace nana{ namespace widgets int sel_xpos = static_cast(str_px - (glyph_front + glyph_selected)); +#ifdef _nana_std_has_string_view + graph.string({ -sel_xpos, 0 }, { str, len }, selection_color(true, has_focused)); +#else graph.palette(true, selection_color(true, has_focused)); - graph.string({ -sel_xpos, 0 }, str, len); +#endif graph_.bitblt(nana::rectangle(strpos.x + sel_xpos, strpos.y, glyph_selected, line_px_), graph); }; private: @@ -3646,11 +3674,11 @@ namespace nana{ namespace widgets unsigned text_editor::_m_char_by_pixels(const unicode_bidi::entity& ent, unsigned pos) const { auto len = static_cast(ent.end - ent.begin); - - std::unique_ptr pxbuf(new unsigned[len]); #ifdef _nana_std_has_string_view - if (graph_.glyph_pixels({ent.begin, len}, pxbuf.get())) + auto pxbuf = graph_.glyph_pixels({ ent.begin, len }); + if (pxbuf) #else + std::unique_ptr pxbuf(new unsigned[len]); if (graph_.glyph_pixels(ent.begin, len, pxbuf.get())) #endif { @@ -3710,10 +3738,10 @@ namespace nana{ namespace widgets { //Characters of some bidi languages may transform in a word. //RTL - std::unique_ptr pxbuf(new unsigned[len]); #ifdef _nana_std_has_string_view - graph_.glyph_pixels({ent.begin, len}, pxbuf.get()); + auto pxbuf = graph_.glyph_pixels({ent.begin, len}); #else + std::unique_ptr pxbuf(new unsigned[len]); graph_.glyph_pixels(ent.begin, len, pxbuf.get()); #endif return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 2337f468..f0a972c9 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1,6 +1,6 @@ /* * A Tabbar Implementation - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -1489,7 +1489,12 @@ namespace nana } graph.rectangle(r, true); +#ifdef _nana_std_has_string_view + graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text); + +#else graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size()); +#endif ++pos; } diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index f14c7a64..91b34a81 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -168,7 +168,11 @@ namespace detail { #if defined(NANA_WINDOWS) +#ifdef _nana_std_has_string_view + auto wstr = to_wstring(std::string_view(text, len)); +#else auto wstr = to_wstring(std::string(text,len)); +#endif ::SIZE size; if (::GetTextExtentPoint32(dw->context, wstr.c_str(), static_cast(wstr.size()), &size)) return nana::size(size.cx, size.cy); diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 14a76b0e..ec2aa75b 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -494,7 +494,8 @@ namespace paint return sz; } - bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const +#if 0 + bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const //deprecated { if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == pxbuf) return false; @@ -533,6 +534,7 @@ namespace paint #endif return true; } +#endif std::unique_ptr graphics::glyph_pixels(std::wstring_view text) const { @@ -575,6 +577,32 @@ namespace paint #endif return pxbuf; } + + ::nana::size graphics::bidi_extent_size(std::string_view utf8str) const + { + return bidi_extent_size(to_wstring(utf8str)); + } + + nana::size graphics::bidi_extent_size(std::wstring_view text) const + { + nana::size sz; + if (impl_->handle && impl_->handle->context && text.size()) + { + auto const reordered = unicode_reorder(text.data(), text.size()); + for (auto & i : reordered) + { +#ifdef _nana_std_has_string_view + nana::size t = text_extent_size(std::wstring_view(i.begin, i.end - i.begin)); +#else + nana::size t = text_extent_size(i.begin, i.end - i.begin); +#endif + sz.width += t.width; + if (sz.height < t.height) + sz.height = t.height; + } + } + return sz; + } #else ::nana::size graphics::text_extent_size(const ::std::string& text) const { @@ -677,24 +705,21 @@ namespace paint return true; } -#endif - - nana::size graphics::bidi_extent_size(const std::wstring& str) const { nana::size sz; - if(impl_->handle && impl_->handle->context && str.size()) + if (impl_->handle && impl_->handle->context && str.size()) { auto const reordered = unicode_reorder(str.c_str(), str.size()); - for(auto & i: reordered) + for (auto & i : reordered) { #ifdef _nana_std_has_string_view - nana::size t = text_extent_size(std::wstring_view( i.begin, i.end - i.begin )); + nana::size t = text_extent_size(std::wstring_view(i.begin, i.end - i.begin)); #else nana::size t = text_extent_size(i.begin, i.end - i.begin); #endif sz.width += t.width; - if(sz.height < t.height) + if (sz.height < t.height) sz.height = t.height; } } @@ -705,6 +730,7 @@ namespace paint { return bidi_extent_size(static_cast(::nana::charset(str, ::nana::unicode::utf8))); } +#endif //end _nana_std_has_string_view bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const { @@ -1133,29 +1159,6 @@ namespace paint return *this; } - unsigned graphics::bidi_string(const nana::point& pos, const wchar_t * str, std::size_t len) - { - auto moved_pos = pos; - - auto const reordered = unicode_reorder(str, len); - for (auto & i : reordered) - { - string(moved_pos, i.begin, i.end - i.begin); -#ifdef _nana_std_has_string_view - moved_pos.x += static_cast(text_extent_size(std::wstring_view( i.begin, i.end - i.begin )).width); -#else - moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); -#endif - } - return static_cast(moved_pos.x - pos.x); - } - - unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len) - { - std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8); - return bidi_string(pos, wstr.data(), wstr.size()); - } - void graphics::set_pixel(int x, int y, const ::nana::color& clr) { if (impl_->handle) @@ -1180,6 +1183,116 @@ namespace paint } } +#ifdef _nana_std_has_string_view + unsigned graphics::bidi_string(const point& pos, std::string_view utf8str) + { + return bidi_string(pos, to_wstring(utf8str)); + } + + unsigned graphics::bidi_string(const nana::point& pos, std::wstring_view str) + { + auto moved_pos = pos; + + auto const reordered = unicode_reorder(str.data(), str.size()); + for (auto & i : reordered) + { + +#ifdef _nana_std_has_string_view + this->string(moved_pos, std::wstring_view{ i.begin, static_cast(i.end - i.begin) }); + moved_pos.x += static_cast(text_extent_size(std::wstring_view(i.begin, i.end - i.begin)).width); +#else + this->string(moved_pos, i.begin, i.end - i.begin); + moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); +#endif + } + return static_cast(moved_pos.x - pos.x); + } + + void graphics::string(const point& pos, std::string_view utf8str) + { + this->string(pos, to_wstring(utf8str)); + } + + void graphics::string(const point& pos, std::string_view utf8str, const nana::color& text_color) + { + palette(true, text_color); + string(pos, utf8str); + } + + void graphics::string(const nana::point& text_pos, std::wstring_view str) + { + if (impl_->handle && !str.empty()) + { +#if defined(NANA_POSIX) + impl_->handle->update_text_color(); +#endif + auto begin = str.data(); + auto const end = begin + str.size(); + auto i = std::find(begin, end, '\t'); + + if (i != end) + { + auto pos = text_pos; + std::size_t tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.tab_pixels; + while (true) + { + auto len = i - begin; + if (len) + { + //Render a part that does not contains a tab + detail::draw_string(impl_->handle, pos, begin, len); + pos.x += detail::real_text_extent_size(impl_->handle, begin, len).width; + } + + begin = i; + while (begin != end && (*begin == '\t')) + ++begin; + + if (begin != end) + { + //Now i_tab is not a tab, but a non-tab character following the previous tabs + pos.x += static_cast(tab_pixels * (begin - i)); + i = std::find(begin, end, '\t'); + } + else + break; + } + } + else + detail::draw_string(impl_->handle, text_pos, str.data(), str.size()); + if (impl_->changed == false) impl_->changed = true; + } + } + + void graphics::string(const point& pos, std::wstring_view str, const nana::color& text_color) + { + palette(true, text_color); + string(pos, str); + } +#else + unsigned graphics::bidi_string(const nana::point& pos, const wchar_t * str, std::size_t len) + { + auto moved_pos = pos; + + auto const reordered = unicode_reorder(str, len); + for (auto & i : reordered) + { + string(moved_pos, i.begin, i.end - i.begin); +#ifdef _nana_std_has_string_view + moved_pos.x += static_cast(text_extent_size(std::wstring_view(i.begin, i.end - i.begin)).width); +#else + moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); +#endif + } + return static_cast(moved_pos.x - pos.x); + } + + unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len) + { + std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8); + return bidi_string(pos, wstr.data(), wstr.size()); + } + void graphics::string(const point& pos, const std::string& text_utf8) { string(pos, to_wstring(text_utf8)); @@ -1248,6 +1361,7 @@ namespace paint palette(true, clr); string(pos, text.data(), text.size()); } +#endif //_nana_std_has_string_view void graphics::line(const nana::point& pos1, const nana::point& pos2) { diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 21a9157a..6f5654dd 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -169,8 +169,12 @@ namespace nana dum_graph.bitblt(r, graph, pos); +#ifdef _nana_std_has_string_view + dum_graph.string({}, { i.begin, len }, graph.palette(true)); +#else dum_graph.palette(true, graph.palette(true)); dum_graph.string({}, i.begin, len); +#endif r.x = pos.x; r.y = top; @@ -233,12 +237,11 @@ namespace nana const std::size_t len = i.end - i.begin; if(len > 1) { - std::unique_ptr pixel_buf(new unsigned[len]); - //Find the char that should be splitted #ifdef _nana_std_has_string_view - graph.glyph_pixels({ i.begin, len }, pixel_buf.get()); + auto pixel_buf = graph.glyph_pixels({ i.begin, len }); #else + std::unique_ptr pixel_buf(new unsigned[len]); graph.glyph_pixels(i.begin, len, pixel_buf.get()); #endif @@ -458,14 +461,16 @@ namespace nana std::size_t len = i.end - i.begin; if(len > 1) { - std::unique_ptr scope_res(new unsigned[len]); - auto pxbuf = scope_res.get(); //Find the char that should be splitted #ifdef _nana_std_has_string_view - graph.glyph_pixels({ i.begin, len }, pxbuf); + auto scope_res = graph.glyph_pixels({ i.begin, len }); + auto pxbuf = scope_res.get(); #else + std::unique_ptr scope_res(new unsigned[len]); + auto pxbuf = scope_res.get(); graph.glyph_pixels(i.begin, len, pxbuf); #endif + std::size_t idx_head = 0, idx_splitted; do @@ -639,15 +644,17 @@ namespace nana break; } +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, text); +#else graph_.bidi_string(pos, text.c_str(), text.size()); +#endif return; } #ifdef _nana_std_has_string_view const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width; - - std::unique_ptr pixels(new unsigned[text.size()]); - graph_.glyph_pixels({ text.c_str(), text.size() }, pixels.get()); + auto pixels = graph_.glyph_pixels({ text.c_str(), text.size() }); #else const auto ellipsis = graph_.text_extent_size("...", 3).width; @@ -674,7 +681,11 @@ namespace nana } while (p != end); pos.x += static_cast(width - ellipsis - substr_px) + ellipsis; +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, { text.c_str() + substr_len, text.size() - substr_len }); +#else graph_.bidi_string(pos, text.c_str() + substr_len, text.size() - substr_len); +#endif pos.x -= ellipsis; } else @@ -691,8 +702,11 @@ namespace nana if (align::center == text_align_ex_) pos.x += (width - substr_px - ellipsis) / 2; - +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, { text.c_str(), substr_len }); +#else graph_.bidi_string(pos, text.c_str(), substr_len); +#endif pos.x += substr_px; } From e47f545b4d7197678dcdc8642f12a6a0c241c594 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 12 Jun 2018 03:03:40 +0800 Subject: [PATCH 20/27] add scheme and caption alignment to group widget. --- include/nana/gui/widgets/group.hpp | 17 ++++++++++- source/gui/widgets/group.cpp | 48 +++++++++++++++++++++++++----- source/gui/widgets/label.cpp | 2 +- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/include/nana/gui/widgets/group.hpp b/include/nana/gui/widgets/group.hpp index 86ca663b..ba48928b 100644 --- a/include/nana/gui/widgets/group.hpp +++ b/include/nana/gui/widgets/group.hpp @@ -22,8 +22,20 @@ #include namespace nana{ + + namespace drawerbase + { + namespace group + { + struct scheme : public nana::widget_geometrics + { + color_proxy border{ colors::gray_border }; + }; + }// end namespace panel + }//end namespace drawerbase + class group - : public panel + : public widget_object { struct implement; public: @@ -53,6 +65,9 @@ namespace nana{ /// Adds an option for user selection checkbox& add_option(::std::string); + /// Modifies the alignment of the title + void caption_align(align position); + /// Enables/disables the radio mode which is single selection group& radio_mode(bool); diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index 23cc287c..f976944a 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -35,6 +35,7 @@ namespace nana{ struct group::implement { label caption; + align caption_align{ align::left }; place place_content; unsigned gap{2}; std::string usr_div_str; @@ -65,10 +66,30 @@ namespace nana{ void update_div() { + const std::size_t padding = 10; caption_dimension = caption.measure(1000); + caption_dimension.width += 1; std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]"; +#if 0 div += "<" + field_title + " weight=" + std::to_string(caption_dimension.width + 1) + ">>"; +#else + div += ""; + else + div += "<>"; //right or center + + div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">"; + + if (align::right == caption_align) + div += ""; + else if (align::center == caption_align) + div += "<>"; + + div += ">"; +#endif div += "<"; if (!usr_div_str.empty()) @@ -97,10 +118,15 @@ namespace nana{ create(parent, r, vsb); } + using groupbase_type = widget_object; + group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb) - : panel(parent, r, vsb), - impl_(new implement(*this, std::move(titel), vsb, gap)) { + this->create(parent, r, vsb); + this->bgcolor(API::bgcolor(parent)); + + impl_.reset(new implement(*this, std::move(titel), vsb, gap)); + impl_->caption.format(formatted); _m_init(); } @@ -128,6 +154,17 @@ namespace nana{ return *impl_->options.back(); } + void group::caption_align(align position) + { + if (position != impl_->caption_align) + { + impl_->caption_align = position; + impl_->update_div(); + impl_->place_content.collocate(); + API::refresh_window(*this); + } + } + group& group::radio_mode(bool enable) { _THROW_IF_EMPTY() @@ -243,7 +280,7 @@ namespace nana{ graph.round_rectangle(rectangle(point(gap_px, top_round_line), nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px) ), - 3, 3, colors::gray_border, true, this->bgcolor()); + 3, 3, this->scheme().border, true, this->bgcolor()); auto opt_r = API::window_rectangle(impl_->caption); if (opt_r) @@ -263,11 +300,8 @@ namespace nana{ void group::_m_complete_creation() { - panel::_m_complete_creation(); - + widget::_m_complete_creation(); impl_->create(handle()); - - _m_init(); } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 7f4f2a4e..790ae3b8 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -1,7 +1,7 @@ /* * A Label Control Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-208 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at From 8ba312d50e066bdd4f307a1edb6562d6c209fe79 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 13 Jun 2018 22:41:56 +0800 Subject: [PATCH 21/27] fix a crash error of improvement of group --- source/gui/widgets/group.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index f976944a..fcb8719b 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -121,8 +121,8 @@ namespace nana{ using groupbase_type = widget_object; group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb) + : group(parent, r, vsb) { - this->create(parent, r, vsb); this->bgcolor(API::bgcolor(parent)); impl_.reset(new implement(*this, std::move(titel), vsb, gap)); From 094830b8a719a5ef5cc4cf916c60a215ead0da38 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 13 Jun 2018 23:18:25 +0800 Subject: [PATCH 22/27] fix a bug that listbox may not be drawn(#317) it doesn't draw if the first column is wider than the width of listbox --- source/gui/widgets/listbox.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 7bdfc2b6..5d9140e1 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -2470,10 +2470,10 @@ namespace nana x += col.width_px; if (x > 0) { + seqs.push_back(col.index); + if (x >= static_cast(lister_w)) break; - - seqs.push_back(col.index); } } return seqs; From b5a9374f8f246d295e40488607599a524643794c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Jun 2018 00:40:22 +0800 Subject: [PATCH 23/27] fix bug that listbox fit_content may not work --- source/gui/widgets/listbox.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 5d9140e1..3b41311d 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -2757,6 +2757,17 @@ namespace nana unsigned es_lister::column_content_pixels(size_type pos) const { unsigned max_px = 0; + + std::unique_ptr graph_helper; + auto graph = ess_->graph; + if (graph->empty()) + { + //Creates a helper if widget graph is empty(when its size is 0). + graph_helper.reset(new paint::graphics{ nana::size{ 5, 5 } }); + graph_helper->typeface(ess_->graph->typeface()); + graph = graph_helper.get(); + } + for (auto & cat : categories_) { for (std::size_t i = 0; i < cat.items.size(); ++i) @@ -2768,14 +2779,14 @@ namespace nana if (pos >= model_cells.size()) continue; - content_px = ess_->graph->text_extent_size(model_cells[pos].text).width; + content_px = graph->text_extent_size(model_cells[pos].text).width; } else { if (pos >= cat.items[i].cells->size()) continue; - content_px = ess_->graph->text_extent_size((*cat.items[i].cells)[pos].text).width; + content_px = graph->text_extent_size((*cat.items[i].cells)[pos].text).width; } if (content_px > max_px) From c0836fbbec37e87b47f339494ee44dd503ad9726 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Jun 2018 01:09:56 +0800 Subject: [PATCH 24/27] new folderbox class --- include/nana/gui/filebox.hpp | 27 +- source/gui/filebox.cpp | 546 +++++++++++++++++++++-------------- 2 files changed, 359 insertions(+), 214 deletions(-) diff --git a/include/nana/gui/filebox.hpp b/include/nana/gui/filebox.hpp index 1800eb9f..a2d0ac73 100644 --- a/include/nana/gui/filebox.hpp +++ b/include/nana/gui/filebox.hpp @@ -1,7 +1,7 @@ /** * Filebox * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -15,6 +15,7 @@ #ifndef NANA_GUI_FILEBOX_HPP #define NANA_GUI_FILEBOX_HPP #include +#include #include #include @@ -80,5 +81,29 @@ namespace nana private: implement * impl_; }; + + class folderbox + { + struct implement; + + folderbox(const folderbox&) = delete; + folderbox& operator=(const folderbox&) = delete; + folderbox(folderbox&&) = delete; + folderbox& operator=(folderbox&&) = delete; + public: + using path_type = std::experimental::filesystem::path; + + folderbox(window owner = nullptr, const path_type& init_path = {}); + ~folderbox(); + + std::optional show() const; + + std::optional operator()() const + { + return show(); + } + private: + implement* impl_; + }; }//end namespace nana #endif diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index ff58039d..163ba3cf 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -1,7 +1,7 @@ /* * Filebox * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -15,18 +15,19 @@ #include #if defined(NANA_WINDOWS) - #include +# include +# include #elif defined(NANA_POSIX) - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include #endif namespace fs = std::experimental::filesystem; @@ -130,6 +131,13 @@ namespace nana } }; public: + enum class mode + { + open_file, //choose an existing file. + write_file, //choose a filename, it can be specified a new filename which doesn't exist. + open_directory, //choose an existing directory. + }; + struct kind { enum t{none, filesystem}; @@ -138,8 +146,10 @@ namespace nana typedef treebox::item_proxy item_proxy; public: - filebox_implement(window owner, bool io_read, const std::string& title) - : form(owner, API::make_center(owner, 630, 440)), io_read_(io_read) + filebox_implement(window owner, mode dialog_mode, const std::string& title, bool pick_directory = false): + form(owner, API::make_center(owner, 630, 440)), + pick_directory_(pick_directory), + mode_(dialog_mode) { internationalization i18n; path_.create(*this); @@ -159,6 +169,7 @@ namespace nana _m_load_cat_path(path); }); + filter_.create(*this); filter_.multi_lines(false); filter_.tip_string(i18n("NANA_FILEBOX_FILTER")); @@ -203,7 +214,7 @@ namespace nana ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70); auto fn_sel_file = [this](const arg_mouse& arg){ - _m_sel_file(arg); + _m_select_file(arg); }; ls_file_.events().dbl_click.connect_unignorable(fn_sel_file); ls_file_.events().mouse_down.connect_unignorable(fn_sel_file); @@ -278,7 +289,11 @@ namespace nana }); lb_file_.create(*this); - lb_file_.i18n(i18n_eval("NANA_FILEBOX_FILE_COLON")); + + const char* idstr = (mode::open_directory == dialog_mode? "NANA_FILEBOX_DIRECTORY_COLON" : "NANA_FILEBOX_FILE_COLON"); + lb_file_.i18n(i18n_eval(idstr)); + lb_file_.text_align(align::right, align_v::center); + tb_file_.create(*this); tb_file_.multi_lines(false); @@ -289,9 +304,13 @@ namespace nana _m_ok(); }); - cb_types_.create(*this); - cb_types_.editable(false); - cb_types_.events().selected.connect_unignorable([this](const arg_combox&){ _m_list_fs(); }); + //Don't create the combox for choose a file extension if the dialog is used for picking a directory. + if(!pick_directory) + { + cb_types_.create(*this); + cb_types_.editable(false); + cb_types_.events().selected.connect_unignorable([this](const arg_combox&){ _m_list_fs(); }); + } btn_ok_.create(*this); btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY")); @@ -313,10 +332,25 @@ namespace nana _m_layout(); _m_init_tree(); - if(0 == title.size()) - this->i18n(i18n_eval(io_read ? "NANA_FILEBOX_OPEN" : "NANA_FILEBOX_SAVE_AS")); + if(title.empty()) + { + const char* idstr{ nullptr }; + switch(dialog_mode) + { + case mode::open_file: + idstr = "NANA_FILEBOX_OPEN"; + break; + case mode::write_file: + idstr = "NANA_FILEBOX_SAVE_AS"; + break; + case mode::open_directory: + idstr = "NANA_FILEBOX_OPEN_DIRECTORY"; + break; + } + this->i18n(i18n_eval(idstr)); + } else - caption(title); + caption(title); } void def_extension(const std::string& ext) @@ -412,16 +446,21 @@ namespace nana "" "" "" - "" + "" ">" "" ">"); place_.field("path")<size())) return true; for(auto & extstr : *extension) @@ -744,7 +786,7 @@ namespace nana return true; } private: - void _m_sel_file(const arg_mouse& arg) + void _m_select_file(const arg_mouse& arg) { auto sel = ls_file_.selected(); if(sel.empty()) @@ -763,7 +805,7 @@ namespace nana } else { - if(false == m.directory) + if((mode::open_directory == mode_) || (false == m.directory)) { selection_.target = addr_.filesystem + m.name; tb_file_.caption(m.name); @@ -816,13 +858,16 @@ namespace nana return; } - if(io_read_) + if(mode::write_file != mode_) { if(fs::file_type::not_found == ftype) { msgbox mb(*this, caption()); mb.icon(msgbox::icon_information); - mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar); + if(mode::open_file != mode_) + mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar); + else + mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar); mb(); return; @@ -892,7 +937,8 @@ namespace nana } } private: - bool io_read_; + bool const pick_directory_; + mode mode_; std::string def_ext_; place place_; @@ -933,224 +979,298 @@ namespace nana #endif //class filebox - struct filebox::implement + struct filebox::implement + { + struct filter { - struct filter - { - std::string des; - std::string type; - }; - - window owner; - bool open_or_save; - - std::string file; - std::string title; - std::string path; - std::vector filters; + std::string des; + std::string type; }; - filebox::filebox(bool is_openmode) - : filebox(nullptr, is_openmode) - { - } + window owner; + bool open_or_save; - filebox::filebox(window owner, bool open) - : impl_(new implement) - { - impl_->owner = owner; - impl_->open_or_save = open; + std::string file; + std::string title; + std::string path; + std::vector filters; + }; + + filebox::filebox(bool is_openmode) + : filebox(nullptr, is_openmode) + { + } + + filebox::filebox(window owner, bool open) + : impl_(new implement) + { + impl_->owner = owner; + impl_->open_or_save = open; #if defined(NANA_WINDOWS) - auto len = ::GetCurrentDirectory(0, nullptr); - if(len) - { - std::wstring path; - path.resize(len + 1); - ::GetCurrentDirectory(len, &(path[0])); - path.resize(len); + auto len = ::GetCurrentDirectory(0, nullptr); + if(len) + { + std::wstring path; + path.resize(len + 1); + ::GetCurrentDirectory(len, &(path[0])); + path.resize(len); - impl_->path = to_utf8(path); - } + impl_->path = to_utf8(path); + } #endif - } + } - filebox::filebox(const filebox& other) - : impl_(new implement(*other.impl_)) - {} + filebox::filebox(const filebox& other) + : impl_(new implement(*other.impl_)) + {} - filebox::~filebox() + filebox::~filebox() + { + delete impl_; + } + + filebox& filebox::operator=(const filebox& other) + { + if (this != &other) + *impl_ = *other.impl_; + return *this; + } + + void filebox::owner(window wd) + { + impl_->owner = wd; + } + + std::string filebox::title(std::string s) + { + impl_->title.swap(s); + return s; + } + + filebox& filebox::init_path(const std::string& ipstr) + { + if(ipstr.empty()) { - delete impl_; + impl_->path.clear(); } - - filebox& filebox::operator=(const filebox& other) + else { - if (this != &other) - *impl_ = *other.impl_; - return *this; + if (fs::is_directory(ipstr)) + impl_->path = ipstr; } + return *this; + } - void filebox::owner(window wd) - { - impl_->owner = wd; - } + filebox& filebox::init_file(const std::string& ifstr) + { + impl_->file = ifstr; + return *this; + } - std::string filebox::title(std::string s) - { - impl_->title.swap(s); - return s; - } + filebox& filebox::add_filter(const std::string& description, const std::string& filetype) + { + implement::filter flt = {description, filetype}; + impl_->filters.push_back(flt); + return *this; + } - filebox& filebox::init_path(const std::string& ipstr) - { - if(ipstr.empty()) - { - impl_->path.clear(); - } - else - { - if (fs::is_directory(ipstr)) - impl_->path = ipstr; - } - return *this; - } - - filebox& filebox::init_file(const std::string& ifstr) - { - impl_->file = ifstr; - return *this; - } - - filebox& filebox::add_filter(const std::string& description, const std::string& filetype) - { - implement::filter flt = {description, filetype}; - impl_->filters.push_back(flt); - return *this; - } - - std::string filebox::path() const - { - return impl_->path; - } + std::string filebox::path() const + { + return impl_->path; + } - std::string filebox::file() const - { - return impl_->file; - } + std::string filebox::file() const + { + return impl_->file; + } - bool filebox::show() const - { + bool filebox::show() const + { #if defined(NANA_WINDOWS) - auto winitfile = to_wstring(impl_->file); - std::wstring wfile(winitfile); - wfile.resize(520); + auto winitfile = to_wstring(impl_->file); + std::wstring wfile(winitfile); + wfile.resize(520); - OPENFILENAME ofn; - memset(&ofn, 0, sizeof ofn); + OPENFILENAME ofn; + memset(&ofn, 0, sizeof ofn); - internal_scope_guard lock; + internal_scope_guard lock; - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = reinterpret_cast(API::root(impl_->owner)); - ofn.lpstrFile = &(wfile[0]); - ofn.nMaxFile = static_cast(wfile.size() - 1); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = reinterpret_cast(API::root(impl_->owner)); + ofn.lpstrFile = &(wfile[0]); + ofn.nMaxFile = static_cast(wfile.size() - 1); - const wchar_t * filter; - std::wstring filter_holder; - std::wstring default_extension; - if(impl_->filters.size()) + const wchar_t * filter; + std::wstring filter_holder; + std::wstring default_extension; + if(impl_->filters.size()) + { + for(auto & f : impl_->filters) { - for(auto & f : impl_->filters) + filter_holder += to_wstring(f.des); + filter_holder += static_cast('\0'); + std::wstring fs = to_wstring(f.type); + std::size_t pos = 0; + while(true) { - filter_holder += to_wstring(f.des); - filter_holder += static_cast('\0'); - std::wstring fs = to_wstring(f.type); - std::size_t pos = 0; - while(true) - { - pos = fs.find(L" ", pos); - if(pos == fs.npos) - break; - fs.erase(pos); - } - filter_holder += fs; - filter_holder += static_cast('\0'); + pos = fs.find(L" ", pos); + if(pos == fs.npos) + break; + fs.erase(pos); + } + filter_holder += fs; + filter_holder += static_cast('\0'); - //Get the default file extentsion - if (default_extension.empty()) + //Get the default file extentsion + if (default_extension.empty()) + { + pos = fs.find_last_of('.'); + if (pos != fs.npos) { - pos = fs.find_last_of('.'); - if (pos != fs.npos) + fs = fs.substr(pos + 1); + if (fs != L"*") { - fs = fs.substr(pos + 1); - if (fs != L"*") - { - default_extension = fs; - ofn.lpstrDefExt = default_extension.data(); - } + default_extension = fs; + ofn.lpstrDefExt = default_extension.data(); } } } - filter = filter_holder.data(); } - else - filter = L"All Files\0*.*\0"; + filter = filter_holder.data(); + } + else + filter = L"All Files\0*.*\0"; - auto wtitle = to_wstring(impl_->title); - auto wpath = to_wstring(impl_->path); - ofn.lpstrFilter = filter; - ofn.lpstrTitle = (wtitle.empty() ? nullptr : wtitle.c_str()); - ofn.nFilterIndex = 0; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = (wpath.empty() ? nullptr : wpath.c_str()); - - if (!impl_->open_or_save) - ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode - ofn.Flags |= OFN_NOCHANGEDIR; + auto wtitle = to_wstring(impl_->title); + auto wpath = to_wstring(impl_->path); + ofn.lpstrFilter = filter; + ofn.lpstrTitle = (wtitle.empty() ? nullptr : wtitle.c_str()); + ofn.nFilterIndex = 0; + ofn.lpstrFileTitle = nullptr; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = (wpath.empty() ? nullptr : wpath.c_str()); + + if (!impl_->open_or_save) + ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode + ofn.Flags |= OFN_NOCHANGEDIR; - { - internal_revert_guard revert; - if (FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn))) - return false; - } - - wfile.resize(std::wcslen(wfile.data())); - impl_->file = to_utf8(wfile); -#elif defined(NANA_POSIX) - filebox_implement fb(impl_->owner, impl_->open_or_save, impl_->title); - - if(impl_->filters.size()) - { - for(auto & f: impl_->filters) - { - std::string fs = f.type; - std::size_t pos = 0; - while(true) - { - pos = fs.find(" ", pos); - if(pos == fs.npos) - break; - fs.erase(pos); - } - fb.add_filter(f.des, fs); - } - } - else - fb.add_filter("All Files", "*.*"); - - fb.load_fs(impl_->path, impl_->file); - - API::modal_window(fb); - if(false == fb.file(impl_->file)) + { + internal_revert_guard revert; + if (FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn))) return false; -#endif - auto tpos = impl_->file.find_last_of("\\/"); - if(tpos != impl_->file.npos) - impl_->path = impl_->file.substr(0, tpos); - else - impl_->path.clear(); + } - return true; - }//end class filebox + wfile.resize(std::wcslen(wfile.data())); + impl_->file = to_utf8(wfile); +#elif defined(NANA_POSIX) + using mode = filebox_implement::mode; + filebox_implement fb(impl_->owner, (impl_->open_or_save ? mode::open_file : mode::write_file), impl_->title); + + if(impl_->filters.size()) + { + for(auto & f: impl_->filters) + { + std::string fs = f.type; + std::size_t pos = 0; + while(true) + { + pos = fs.find(" ", pos); + if(pos == fs.npos) + break; + fs.erase(pos); + } + fb.add_filter(f.des, fs); + } + } + else + fb.add_filter("All Files", "*.*"); + + fb.load_fs(impl_->path, impl_->file); + + API::modal_window(fb); + if(false == fb.file(impl_->file)) + return false; +#endif + auto tpos = impl_->file.find_last_of("\\/"); + if(tpos != impl_->file.npos) + impl_->path = impl_->file.substr(0, tpos); + else + impl_->path.clear(); + + return true; + }//end class filebox + + + //class directory_picker + struct folderbox::implement + { + window owner; + path_type init_path; + }; + + folderbox::folderbox(window owner, const path_type& init_path) + : impl_(new implement) + { + impl_->owner = owner; + impl_->init_path = init_path; + } + + folderbox::~folderbox() + { + delete impl_; + } + + std::optional folderbox::show() const + { +#ifdef NANA_WINDOWS + path_type target; + + CoInitialize(NULL); + IFileDialog *fd(nullptr); + HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&fd)); + if (SUCCEEDED(hr)) + { + IShellItem *init_path{ nullptr }; + hr = SHCreateItemFromParsingName(impl_->init_path.wstring().c_str(), nullptr, IID_PPV_ARGS(&init_path)); + if (SUCCEEDED(hr)) + fd->SetDefaultFolder(init_path); + + fd->SetOptions(FOS_PICKFOLDERS); + fd->Show(reinterpret_cast(API::root(impl_->owner))); // the native handle of the parent nana form goes here + IShellItem *si; + hr = fd->GetResult(&si); // fails if user cancelled + if (SUCCEEDED(hr)) + { + PWSTR pwstr(nullptr); + hr = si->GetDisplayName(SIGDN_FILESYSPATH, &pwstr); + if (SUCCEEDED(hr)) + { + target = pwstr; + // use the c-string pointed to by pwstr here + CoTaskMemFree(pwstr); + } + si->Release(); + } + fd->Release(); + } + CoUninitialize(); + + return target; + +#elif defined(NANA_POSIX) + using mode = filebox_implement::mode; + filebox_implement fb(impl_->owner, mode::open_directory, {}, true); + + fb.load_fs(impl_->init_path, ""); + + API::modal_window(fb); + + std::string path_directory; + if(false == fb.file(path_directory)) + return {}; + + return path_type{path_directory}; +#endif + } }//end namespace nana From feaa0d1ec1c69946216c6134d0d080f2ac3294ed Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Jun 2018 09:18:03 +0800 Subject: [PATCH 25/27] i18n for folderbox --- source/internationalization.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/internationalization.cpp b/source/internationalization.cpp index 4252d73c..6e4a99d5 100644 --- a/source/internationalization.cpp +++ b/source/internationalization.cpp @@ -1,7 +1,7 @@ /* * An Implementation of i18n * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -185,14 +185,17 @@ namespace nana table["NANA_FILEBOX_SAVE_AS"] = "Save As"; table["NANA_FILEBOX_OPEN"] = "Open"; - table["NANA_FILEBOX_DIRECTORY"] = "Directory"; + table["NANA_FILEBOX_OPEN_DIRECTORY"] = "Select A Directory"; table["NANA_FILEBOX_FILE"] = "File"; table["NANA_FILEBOX_FILE_COLON"] = "File:"; + table["NANA_FILEBOX_DIRECTORY"] = "Directory"; + table["NANA_FILEBOX_DIRECTORY_COLON"] = "Directory:"; table["NANA_FILEBOX_ERROR_INVALID_FOLDER_NAME"] = "Please input a valid name for the new folder."; table["NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_EXISTING"] = "The folder is existing, please rename it."; table["NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_FAILED_CREATION"] = "Failed to create the folder, please rename it."; table["NANA_FILEBOX_ERROR_INVALID_FILENAME"] = "The filename is invalid."; table["NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY"] = "The file \"%arg0\"\n is not existing. Please check and retry."; + table["NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY"] = "The directory \"%arg0\"\n is not existing. Please check and retry."; table["NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING"] = "The input file is existing, do you want to overwrite it?"; } }; From 5f703bff4c212afbbf5442bed410830f677d5eb3 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Jun 2018 06:16:19 +0800 Subject: [PATCH 26/27] ensure click event consistency the order of click events generated by mouse and keyboard are different --- include/nana/gui/widgets/checkbox.hpp | 4 ++- source/gui/detail/bedrock_posix.cpp | 41 ++++++++++++------------ source/gui/detail/bedrock_windows.cpp | 46 ++++++++++++++------------- source/gui/widgets/checkbox.cpp | 6 ++-- 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/include/nana/gui/widgets/checkbox.hpp b/include/nana/gui/widgets/checkbox.hpp index e3b31d69..c6f3a064 100644 --- a/include/nana/gui/widgets/checkbox.hpp +++ b/include/nana/gui/widgets/checkbox.hpp @@ -79,7 +79,9 @@ namespace drawerbase void element_set(const char* name); void react(bool want); ///< Enables the reverse check while clicking on the checkbox. bool checked() const; - void check(bool chk); + + /// Checks/unchecks the checkbox + void check(bool state); /// \brief With the radio mode, users make a choice among a set of mutually exclusive, /// related options. Users can choose one and only one option. diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 571b91bc..abb38f11 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -1149,28 +1149,29 @@ namespace detail { msgwnd->set_action(mouse_action::normal); - arg_click click_arg; - click_arg.mouse_args = nullptr; - click_arg.window_handle = reinterpret_cast(msgwnd); + auto retain = msgwnd->annex.events_ptr; - auto retain = msgwnd->annex.events_ptr; - if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) - { - arg_mouse arg; - arg.alt = false; - arg.button = ::nana::mouse::left_button; - arg.ctrl = false; - arg.evt_code = event_code::mouse_up; - arg.left_button = true; - arg.mid_button = false; - arg.pos.x = 0; - arg.pos.y = 0; - arg.window_handle = reinterpret_cast(msgwnd); + arg_click click_arg; + click_arg.mouse_args = nullptr; + click_arg.window_handle = reinterpret_cast(msgwnd); - draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); - wd_manager.do_lazy_refresh(msgwnd, false); - } - pressed_wd_space = nullptr; + arg_mouse arg; + arg.alt = false; + arg.button = ::nana::mouse::left_button; + arg.ctrl = false; + arg.evt_code = event_code::mouse_up; + arg.left_button = true; + arg.mid_button = false; + arg.pos.x = 0; + arg.pos.y = 0; + arg.window_handle = reinterpret_cast(msgwnd); + + draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); + + if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) + wd_manager.do_lazy_refresh(msgwnd, false); + + pressed_wd_space = nullptr; } else { diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index d8769fd9..674fe475 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -1495,38 +1495,40 @@ namespace detail { msgwnd->set_action(mouse_action::normal); + auto retain = msgwnd->annex.events_ptr; + arg_click click_arg; click_arg.mouse_args = nullptr; click_arg.window_handle = reinterpret_cast(msgwnd); - auto retain = msgwnd->annex.events_ptr; - if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) - { - arg_mouse arg; - arg.alt = false; - arg.button = ::nana::mouse::left_button; - arg.ctrl = false; - arg.evt_code = event_code::mouse_up; - arg.left_button = true; - arg.mid_button = false; - arg.pos.x = 0; - arg.pos.y = 0; - arg.window_handle = reinterpret_cast(msgwnd); + arg_mouse arg; + arg.alt = false; + arg.button = ::nana::mouse::left_button; + arg.ctrl = false; + arg.evt_code = event_code::mouse_up; + arg.left_button = true; + arg.mid_button = false; + arg.pos.x = 0; + arg.pos.y = 0; + arg.window_handle = reinterpret_cast(msgwnd); - draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); + draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); + + if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) wd_manager.do_lazy_refresh(msgwnd, false); - } + pressed_wd_space = nullptr; } else { - arg_keyboard arg; - arg.evt_code = event_code::key_release; - arg.window_handle = reinterpret_cast(msgwnd); - arg.key = translate_virtual_key(wParam); - brock.get_key_state(arg); - arg.ignore = false; - brock.emit(event_code::key_release, msgwnd, arg, true, &context); + arg_keyboard keyboard_arg; + keyboard_arg.evt_code = event_code::key_release; + keyboard_arg.window_handle = reinterpret_cast(msgwnd); + keyboard_arg.key = translate_virtual_key(wParam); + brock.get_key_state(keyboard_arg); + keyboard_arg.ignore = false; + + brock.emit(event_code::key_release, msgwnd, keyboard_arg, true, &context); } } } diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 66fb22de..06a5f0ee 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -167,12 +167,12 @@ namespace nana{ namespace drawerbase return (get_drawer_trigger().impl()->crook.checked() != drawerbase::checkbox::crook_state::unchecked); } - void checkbox::check(bool chk) + void checkbox::check(bool state) { using crook_state = drawerbase::checkbox::crook_state; - if (checked() != chk) + if (checked() != state) { - get_drawer_trigger().impl()->crook.check(chk ? crook_state::checked : crook_state::unchecked); + get_drawer_trigger().impl()->crook.check(state ? crook_state::checked : crook_state::unchecked); API::refresh_window(handle()); arg_checkbox arg(this); From a781a8790f3b769fa6229c46c591506befdc52ef Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 24 Jun 2018 15:49:32 +0800 Subject: [PATCH 27/27] remove deprecated code --- include/nana/paint/graphics.hpp | 2 - source/gui/widgets/group.cpp | 8 +--- source/gui/widgets/skeletons/content_view.cpp | 23 ++-------- source/paint/graphics.cpp | 42 ------------------- 4 files changed, 5 insertions(+), 70 deletions(-) diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index c50714a3..4eed26a6 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -120,8 +120,6 @@ namespace nana ///Only supports the wide string, because it is very hard to specify the begin and end position in a UTF-8 string. ::nana::size glyph_extent_size(std::wstring_view text, std::size_t begin, std::size_t end) const; - //bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; //deprecated - /// Returns a buffer which stores the pixel of each charater stored in text. /** * @param text The text to be requested. diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index fcb8719b..e9ece21a 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -71,9 +71,7 @@ namespace nana{ caption_dimension.width += 1; std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]"; -#if 0 - div += "<" + field_title + " weight=" + std::to_string(caption_dimension.width + 1) + ">>"; -#else + div += ""; + div += "><"; if (!usr_div_str.empty()) div += "<" + usr_div_str + ">>"; diff --git a/source/gui/widgets/skeletons/content_view.cpp b/source/gui/widgets/skeletons/content_view.cpp index 27899183..0596b4c6 100644 --- a/source/gui/widgets/skeletons/content_view.cpp +++ b/source/gui/widgets/skeletons/content_view.cpp @@ -85,27 +85,10 @@ namespace nana { cv_scroll(std::make_shared()) { API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) { -#if 0 - scroll_interface * scroll = nullptr; - switch (arg.which) - { - case arg_wheel::wheel::vertical: - scroll = | - break; - case arg_wheel::wheel::horizontal: - scroll = &horz; - break; - default: - //Other button is not unsupported. - return; - } -#else - auto const scroll = cv_scroll->scroll(arg.which); - if (nullptr == scroll) - return; -#endif - if (!API::empty_window(arg.window_handle)) + auto const scroll = cv_scroll->scroll(arg.which); + + if (scroll && (!API::empty_window(arg.window_handle))) { auto align_px = (scroll->value() % scroll->step()); if (align_px) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index ec2aa75b..fbf07358 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -494,48 +494,6 @@ namespace paint return sz; } -#if 0 - bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const //deprecated - { - if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == pxbuf) return false; - - if (text.empty()) return true; - - unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; -#if defined(NANA_WINDOWS) - int * dx = new int[text.size()]; - SIZE extents; - ::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast(text.size()), 0, 0, dx, &extents); - - pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]); - - for (std::size_t i = 1; i < text.size(); ++i) - { - pxbuf[i] = (text[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]); - } - delete[] dx; -#elif defined(NANA_X11) && defined(NANA_USE_XFT) - - auto disp = nana::detail::platform_spec::instance().open_display(); - auto xft = reinterpret_cast(impl_->handle->font->native_handle()); - - XGlyphInfo extents; - for (std::size_t i = 0; i < len; ++i) - { - if (text[i] != '\t') - { - FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]); - ::XftGlyphExtents(disp, xft, &glyphs, 1, &extents); - pxbuf[i] = extents.xOff; - } - else - pxbuf[i] = tab_pixels; - } -#endif - return true; - } -#endif - std::unique_ptr graphics::glyph_pixels(std::wstring_view text) const { if (nullptr == impl_->handle || nullptr == impl_->handle->context) return {};