Merge branch 'develop'

This commit is contained in:
Jinhao 2018-06-25 03:21:34 +08:00
commit 719bceb616
53 changed files with 1437 additions and 534 deletions

View File

@ -36,10 +36,15 @@
* - STD_TO_STRING_NOT_SUPPORTED (MinGW with GCC < 4.8) * - STD_TO_STRING_NOT_SUPPORTED (MinGW with GCC < 4.8)
* - STD_FILESYSTEM_NOT_SUPPORTED (GCC < 5.3) .... * - STD_FILESYSTEM_NOT_SUPPORTED (GCC < 5.3) ....
* - CXX_NO_INLINE_NAMESPACE (Visual C++ < 2015) * - CXX_NO_INLINE_NAMESPACE (Visual C++ < 2015)
* - _enable_std_make_unique (__cpluscplus < 201402) *
* - _enable_std_put_time (GCC < 5) * There are two kinds of flags:
* - _enable_std_clamp (Visual C++ < 2017) * * _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 #ifndef NANA_CXX_DEFINES_INCLUDED
#define NANA_CXX_DEFINES_INCLUDED #define NANA_CXX_DEFINES_INCLUDED
@ -145,7 +150,7 @@
# if ((__GNUC__ < 5) ) # if ((__GNUC__ < 5) )
# define _enable_std_put_time # define _nana_std_put_time
# endif # endif
# if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) ) # if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
@ -189,20 +194,38 @@
//Detects the feature std::make_unique //Detects the feature std::make_unique
//std::make_unique has been provided by Visual C++ 2013 and later //std::make_unique has been provided by Visual C++ 2013 and later
#undef _enable_std_make_unique #undef _nana_std_make_unique
#if (defined(__clang__) && (__cplusplus < 201305L || (__cplusplus == 201305L && (__clang_major__ * 100 + __clang_minor__ < 304 )))) \ #if (defined(__clang__) && (__cplusplus < 201305L || (__cplusplus == 201305L && (__clang_major__ * 100 + __clang_minor__ < 304 )))) \
|| ((!defined(__clang__)) && defined(__GNUC__) && __cplusplus < 201300L) || ((!defined(__clang__)) && defined(__GNUC__) && __cplusplus < 201300L)
# define _enable_std_make_unique # define _nana_std_make_unique
#endif #endif
//Detects the feature std::clamp //Detects the feature std::clamp
//Visual C++ 2017 with /std:c++latest provides the std::clamp //Visual C++ 2017 with /std:c++latest provides the std::clamp
#undef _enable_std_clamp #undef _nana_std_clamp
#if (defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201403L)) \ #if (defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201403L)) \
|| (defined(__clang__) && (__cplusplus < 201406L)) \ || (defined(__clang__) && (__cplusplus < 201406L)) \
|| (defined(__GNUC__) && (!defined(__clang__)) && (__cplusplus < 201703)) || (defined(__GNUC__) && (!defined(__clang__)) && (__cplusplus < 201703))
# define _enable_std_clamp # define _nana_std_clamp
#endif
#undef _nana_std_optional
#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 #endif

View File

@ -1,7 +1,7 @@
/* /*
* The Deploy Implementation * The Deploy Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -23,6 +23,10 @@
#include <stdexcept> #include <stdexcept>
#ifdef _nana_std_has_string_view
#include <string_view>
#endif
namespace nana namespace nana
{ {
/// move to *.h ?? /// move to *.h ??
@ -44,10 +48,15 @@ namespace nana
/// Checks whether a specified text is utf8 encoding /// 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); bool is_utf8(const char* str, std::size_t len);
void throw_not_utf8(const std::string& text); void throw_not_utf8(const std::string& text);
void throw_not_utf8(const char*, std::size_t len); void throw_not_utf8(const char*, std::size_t len);
void throw_not_utf8(const char*); void throw_not_utf8(const char*);
#endif
/// this text needed change, it needed review ?? /// this text needed change, it needed review ??
bool review_utf8(const std::string& text); bool review_utf8(const std::string& text);
@ -58,7 +67,12 @@ namespace nana
const std::string& to_utf8(const std::string&); const std::string& to_utf8(const std::string&);
std::string to_utf8(const std::wstring&); 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); std::wstring to_wstring(const std::string& utf8_str);
#endif
const std::wstring& to_wstring(const std::wstring& wstr); const std::wstring& to_wstring(const std::wstring& wstr);
std::wstring&& to_wstring(std::wstring&& wstr); std::wstring&& to_wstring(std::wstring&& wstr);

View File

@ -35,14 +35,14 @@ namespace filesystem_ext
std::experimental::filesystem::path path_user(); ///< extention ? 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 /// 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) inline std::string generic_u8string(const std::experimental::filesystem::path& p)
{ {
#if NANA_USING_BOOST_FILESYSTEM #if NANA_USING_BOOST_FILESYSTEM
return nana::to_utf8(p.generic_wstring()); return nana::to_utf8(p.generic_wstring());
#else #else
return p.generic_u8string(); return p.generic_u8string();
#endif #endif
} }
inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept

View File

@ -133,11 +133,25 @@ namespace nana
/// Creates an event handler at the beginning of event chain /// Creates an event handler at the beginning of event chain
template<typename Function> template<typename Function>
event_handle connect_front(Function && fn) event_handle connect_front(Function && fn)
{ {
#ifdef __cpp_if_constexpr
if constexpr(std::is_invocable_v<Function, arg_reference>)
{
return _m_emplace(new docker{ this, fn, false }, true);
}
else if constexpr(std::is_invocable_v<Function>)
{
return _m_emplace(new docker{ this, [fn](arg_reference) {
fn();
}, false }, true);
}
#else
using prototype = typename std::remove_reference<Function>::type; using prototype = typename std::remove_reference<Function>::type;
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), true); return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), true);
#endif
} }
#ifndef __cpp_if_constexpr
/// It will not get called if stop_propagation() was called. /// It will not get called if stop_propagation() was called.
event_handle connect(void (*fn)(arg_reference)) event_handle connect(void (*fn)(arg_reference))
{ {
@ -145,13 +159,27 @@ namespace nana
fn(arg); fn(arg);
}); });
} }
#endif
/// It will not get called if stop_propagation() was called, because it is set at the end of the chain.. /// It will not get called if stop_propagation() was called, because it is set at the end of the chain..
template<typename Function> template<typename Function>
event_handle connect(Function && fn) event_handle connect(Function && fn)
{ {
#ifdef __cpp_if_constexpr
if constexpr(std::is_invocable_v<Function, arg_reference>)
{
return _m_emplace(new docker{ this, fn, false }, false);
}
else if constexpr(std::is_invocable_v<Function>)
{
return _m_emplace(new docker{ this, [fn](arg_reference){
fn();
}, false }, false);
}
#else
using prototype = typename std::remove_reference<Function>::type; using prototype = typename std::remove_reference<Function>::type;
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), false); return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), false), false);
#endif
} }
/// It will not get called if stop_propagation() was called. /// It will not get called if stop_propagation() was called.
@ -164,10 +192,22 @@ namespace nana
/// It will get called because it is unignorable. /// It will get called because it is unignorable.
template<typename Function> template<typename Function>
event_handle connect_unignorable(Function && fn, bool in_front = false) event_handle connect_unignorable(Function && fn, bool in_front = false)
{ {
#ifdef __cpp_if_constexpr
if constexpr(std::is_invocable_v<Function, arg_reference>)
{
return _m_emplace(new docker{ this, fn, true }, in_front);
}
else if constexpr(std::is_invocable_v<Function>)
{
return _m_emplace(new docker{ this, [fn](arg_reference) {
fn();
}, true }, in_front);
}
#else
using prototype = typename std::remove_reference<Function>::type; using prototype = typename std::remove_reference<Function>::type;
return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), true), in_front); return _m_emplace(new docker(this, factory<prototype, std::is_bind_expression<prototype>::value>::build(std::forward<Function>(fn)), true), in_front);
#endif
} }
void emit(arg_reference& arg, window window_handle) void emit(arg_reference& arg, window window_handle)
@ -210,6 +250,8 @@ namespace nana
} }
} }
private: private:
#ifndef __cpp_if_constexpr
template<typename Fn, bool IsBind> template<typename Fn, bool IsBind>
struct factory struct factory
{ {
@ -385,6 +427,7 @@ namespace nana
}; };
} }
}; };
#endif
}; };
struct arg_mouse struct arg_mouse

View File

@ -35,7 +35,7 @@ namespace nana
* @param limit_width True if limits the width, false if limits the height. * @param limit_width True if limits the width, false if limits the height.
* @return the size of content. * @return the size of content.
*/ */
virtual optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const = 0; virtual ::std::optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const = 0;
/// Returns the extension to the size of widget from content extent /// Returns the extension to the size of widget from content extent
/** /**

View File

@ -1,7 +1,7 @@
/** /**
* Filebox * Filebox
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -15,6 +15,7 @@
#ifndef NANA_GUI_FILEBOX_HPP #ifndef NANA_GUI_FILEBOX_HPP
#define NANA_GUI_FILEBOX_HPP #define NANA_GUI_FILEBOX_HPP
#include <nana/gui/basis.hpp> #include <nana/gui/basis.hpp>
#include <nana/filesystem/filesystem.hpp>
#include <vector> #include <vector>
#include <utility> #include <utility>
@ -80,5 +81,29 @@ namespace nana
private: private:
implement * impl_; 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<path_type> show() const;
std::optional<path_type> operator()() const
{
return show();
}
private:
implement* impl_;
};
}//end namespace nana }//end namespace nana
#endif #endif

View File

@ -240,7 +240,11 @@ namespace nana
bool show(Args&& ... args) bool show(Args&& ... args)
{ {
std::vector<abstract_content*> contents; std::vector<abstract_content*> contents;
#ifdef __cpp_fold_expressions
(contents.emplace_back(&args), ...);
#else
_m_fetch_args(contents, std::forward<Args>(args)...); _m_fetch_args(contents, std::forward<Args>(args)...);
#endif
if (contents.empty()) if (contents.empty())
return false; return false;
@ -270,6 +274,7 @@ namespace nana
void min_width_entry_field( unsigned pixels ); void min_width_entry_field( unsigned pixels );
private: private:
#ifndef __cpp_fold_expressions
void _m_fetch_args(std::vector<abstract_content*>&); void _m_fetch_args(std::vector<abstract_content*>&);
template<typename ...Args> template<typename ...Args>
@ -278,6 +283,7 @@ namespace nana
contents.push_back(&content); contents.push_back(&content);
_m_fetch_args(contents, std::forward<Args>(args)...); _m_fetch_args(contents, std::forward<Args>(args)...);
} }
#endif
bool _m_open(std::vector<abstract_content*>&, bool modal); bool _m_open(std::vector<abstract_content*>&, bool modal);
private: private:

View File

@ -1,7 +1,7 @@
/* /*
* An Implementation of Place for Layout * An Implementation of Place for Layout
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -119,7 +119,7 @@ namespace nana
void splitter_renderer(std::function<void(window, paint::graphics&, mouse_action)> fn); void splitter_renderer(std::function<void(window, paint::graphics&, mouse_action)> 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. 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. void modify(const char* field_name, const char* div_text); ///< Modifies a specified field.

View File

@ -45,6 +45,15 @@ namespace nana
namespace API 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 namespace detail
{ {
::nana::widget_geometrics* make_scheme(::nana::detail::scheme_factory_interface&&); ::nana::widget_geometrics* make_scheme(::nana::detail::scheme_factory_interface&&);
@ -80,7 +89,7 @@ namespace API
void set_measurer(window, ::nana::dev::widget_content_measurer_interface*); void set_measurer(window, ::nana::dev::widget_content_measurer_interface*);
void attach_drawer(widget&, drawer_trigger&); 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); void window_caption(window, ::nana::detail::native_string_type);
window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached); window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached);
@ -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&); 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 }//end namespace dev
/// Returns the widget pointer of the specified window. /// Returns the widget pointer of the specified window.
/* /*
* @param window_handle A handle to a window owning the widget. * @param window_handle A handle to a window owning the widget.
@ -245,6 +255,19 @@ namespace API
if (nullptr == general_evt) if (nullptr == general_evt)
throw std::invalid_argument("API::events(): bad parameter window handle, no events object or invalid window handle."); throw std::invalid_argument("API::events(): bad parameter window handle, no events object or invalid window handle.");
#ifdef __cpp_if_constexpr
if constexpr(std::is_same_v<event_type, ::nana::general_events>)
{
return *general_evt;
}
else
{
auto * widget_evt = dynamic_cast<event_type*>(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) if (std::is_same<::nana::general_events, event_type>::value)
return *static_cast<event_type*>(general_evt); return *static_cast<event_type*>(general_evt);
@ -252,6 +275,7 @@ namespace API
if (nullptr == widget_evt) if (nullptr == widget_evt)
throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match."); throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match.");
return *widget_evt; return *widget_evt;
#endif
} }
template<typename EventArg, typename std::enable_if<std::is_base_of< ::nana::event_arg, EventArg>::value>::type* = nullptr> template<typename EventArg, typename std::enable_if<std::is_base_of< ::nana::event_arg, EventArg>::value>::type* = nullptr>
@ -278,6 +302,19 @@ namespace API
if (nullptr == wdg_colors) if (nullptr == wdg_colors)
throw std::invalid_argument("API::scheme(): bad parameter window handle, no events object or invalid window handle."); throw std::invalid_argument("API::scheme(): bad parameter window handle, no events object or invalid window handle.");
#ifdef __cpp_if_constexpr
if constexpr(std::is_same<::nana::widget_geometrics, scheme_type>::value)
{
return *static_cast<scheme_type*>(wdg_colors);
}
else
{
auto * comp_wdg_colors = dynamic_cast<scheme_type*>(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) if (std::is_same<::nana::widget_geometrics, scheme_type>::value)
return *static_cast<scheme_type*>(wdg_colors); return *static_cast<scheme_type*>(wdg_colors);
@ -285,6 +322,7 @@ namespace API
if (nullptr == comp_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."); throw std::invalid_argument("API::scheme(): bad template parameter Widget, the widget type and window handle do not match.");
return *comp_wdg_colors; return *comp_wdg_colors;
#endif
} }
point window_position(window); point window_position(window);
@ -302,7 +340,7 @@ namespace API
size window_outline_size(window); size window_outline_size(window);
void window_outline_size(window, const size&); void window_outline_size(window, const size&);
nana::optional<rectangle> window_rectangle(window); ::std::optional<rectangle> window_rectangle(window);
bool get_window_rectangle(window, rectangle&); bool get_window_rectangle(window, rectangle&);
bool track_window_size(window, const size&, bool true_for_max); ///< Sets the minimum or maximum tracking size of a window. bool track_window_size(window, const size&, bool true_for_max); ///< Sets the minimum or maximum tracking size of a window.
void window_enabled(window, bool); void window_enabled(window, bool);
@ -424,7 +462,7 @@ namespace API
bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state
bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled
void at_safe_place(window, std::function<void()>); void at_safe_place(window, ::std::function<void()>);
/// Returns a widget content extent size /// Returns a widget content extent size
/** /**
@ -435,7 +473,7 @@ namespace API
* @return if optional has a value, the first size indicates the content extent, the second size indicates the size of * @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. * widget by the content extent.
*/ */
optional<std::pair<::nana::size, ::nana::size>> content_extent(window wd, unsigned limited_px, bool limit_width); ::std::optional<std::pair<::nana::size, ::nana::size>> content_extent(window wd, unsigned limited_px, bool limit_width);
unsigned screen_dpi(bool x_requested); unsigned screen_dpi(bool x_requested);
}//end namespace API }//end namespace API

View File

@ -79,7 +79,9 @@ namespace drawerbase
void element_set(const char* name); void element_set(const char* name);
void react(bool want); ///< Enables the reverse check while clicking on the checkbox. void react(bool want); ///< Enables the reverse check while clicking on the checkbox.
bool checked() const; 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, /// \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. /// related options. Users can choose one and only one option.

View File

@ -223,7 +223,7 @@ namespace nana
const drawerbase::combox::drawer_impl& _m_impl() const; const drawerbase::combox::drawer_impl& _m_impl() const;
private: private:
//Overrides widget's virtual functions //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_caption(native_string_type&&) override;
nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override; nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override;
}; };

View File

@ -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 <cstddef> //provides std::ptrdiff_t
namespace nana {
namespace widgets {
namespace detail
{
template<typename Category, typename T>
class widget_iterator
{
using iterator_category = Category;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T * ;
using reference = T & ;
};
}
}
}
#endif

View File

@ -22,8 +22,20 @@
#include <nana/gui/widgets/checkbox.hpp> #include <nana/gui/widgets/checkbox.hpp>
namespace nana{ 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 class group
: public panel<true> : public widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>
{ {
struct implement; struct implement;
public: public:
@ -53,6 +65,9 @@ namespace nana{
/// Adds an option for user selection /// Adds an option for user selection
checkbox& add_option(::std::string); 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 /// Enables/disables the radio mode which is single selection
group& radio_mode(bool); group& radio_mode(bool);
@ -83,7 +98,7 @@ namespace nana{
void _m_add_child(const char* field, widget*); void _m_add_child(const char* field, widget*);
void _m_init(); void _m_init();
void _m_complete_creation() override; 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; void _m_caption(native_string_type&&) override;
private: private:
std::unique_ptr<implement> impl_; std::unique_ptr<implement> impl_;

View File

@ -62,12 +62,12 @@ namespace nana
label(window parent, const char* text, bool visible = true) :label(parent, std::string(text),visible) {}; label(window parent, const char* text, bool visible = true) :label(parent, std::string(text),visible) {};
label(window, const rectangle& = {}, bool visible = true); label(window, const rectangle& = {}, bool visible = true);
label& transparent(bool); ///< Switchs the label widget to the transparent background mode. 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& format(bool); ///< Switches the format mode of the widget.
label& add_format_listener(std::function<void(command, const std::string&)>); label& add_format_listener(std::function<void(command, const std::string&)>);
/// as same as the HTML "for" attribute of a label /// 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 /// 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 /// "corrected" size that changes lines to fit the text into the specified width

View File

@ -23,6 +23,7 @@
#include "widget.hpp" #include "widget.hpp"
#include "detail/inline_widget.hpp" #include "detail/inline_widget.hpp"
#include "detail/widget_iterator.hpp"
#include <nana/pat/abstract_factory.hpp> #include <nana/pat/abstract_factory.hpp>
#include <nana/concepts.hpp> #include <nana/concepts.hpp>
#include <nana/key_type.hpp> #include <nana/key_type.hpp>
@ -808,7 +809,8 @@ namespace nana
/// operate with absolute positions and contain only the position but montain pointers to parts of the real items /// 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() /// item_proxy self, it references and iterators are not invalidated by sort()
class item_proxy class item_proxy
: public std::iterator<std::input_iterator_tag, item_proxy> //: public std::iterator<std::input_iterator_tag, item_proxy> //deprecated
: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, item_proxy>
{ {
public: public:
item_proxy(essence*, const index_pair& = index_pair{npos, npos}); item_proxy(essence*, const index_pair& = index_pair{npos, npos});
@ -982,7 +984,8 @@ namespace nana
}; };
class cat_proxy class cat_proxy
: public std::iterator < std::input_iterator_tag, cat_proxy > //: public std::iterator<std::input_iterator_tag, cat_proxy> //deprecated
: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, cat_proxy>
{ {
public: public:
using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface; using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface;
@ -1215,9 +1218,6 @@ namespace nana
unsigned suspension_width{ 8 }; ///< def= . the trigger will set this to the width if ("...") 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 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 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_before{ 2 }; ///< def=2. But 4 is better... IMO
unsigned header_splitter_area_after{ 3 }; ///< def=3. But 4 is better... unsigned header_splitter_area_after{ 3 }; ///< def=3. But 4 is better...

View File

@ -116,7 +116,7 @@ namespace nana
void modifier(std::string prefix_utf8, std::string suffix_utf8); void modifier(std::string prefix_utf8, std::string suffix_utf8);
void modifier(const std::wstring & prefix, const std::wstring& suffix); void modifier(const std::wstring & prefix, const std::wstring& suffix);
private: private:
native_string_type _m_caption() const throw(); native_string_type _m_caption() const noexcept;
void _m_caption(native_string_type&&); void _m_caption(native_string_type&&);
}; //end class spinbox }; //end class spinbox
}//end namespace nana }//end namespace nana

View File

@ -383,7 +383,7 @@ namespace nana
driver(); driver();
~driver(); ~driver();
model* get_model() const throw(); model* get_model() const noexcept;
private: private:
//Overrides drawer_trigger's method //Overrides drawer_trigger's method
void attached(widget_reference, graph_reference) override; void attached(widget_reference, graph_reference) override;

View File

@ -276,7 +276,7 @@ namespace nana
std::size_t text_line_count() const noexcept; std::size_t text_line_count() const noexcept;
protected: protected:
//Overrides widget's virtual functions //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_caption(native_string_type&&) override;
void _m_typeface(const paint::font&) override; void _m_typeface(const paint::font&) override;
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override; std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;

View File

@ -54,9 +54,9 @@ namespace nana
window parent() const; window parent() const;
::std::string caption() const throw(); ::std::string caption() const noexcept;
::std::wstring caption_wstring() const throw(); ::std::wstring caption_wstring() const noexcept;
native_string_type caption_native() const throw(); native_string_type caption_native() const noexcept;
widget& caption(std::string utf8); widget& caption(std::string utf8);
widget& caption(std::wstring); widget& caption(std::wstring);
@ -132,7 +132,7 @@ namespace nana
virtual void _m_complete_creation(); virtual void _m_complete_creation();
virtual general_events& _m_get_general_events() const = 0; 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 void _m_caption(native_string_type&&);
virtual nana::cursor _m_cursor() const; virtual nana::cursor _m_cursor() const;
virtual void _m_cursor(nana::cursor); virtual void _m_cursor(nana::cursor);

View File

@ -34,7 +34,12 @@ namespace nana
::std::string get(std::string msgid_utf8, Args&&... args) const ::std::string get(std::string msgid_utf8, Args&&... args) const
{ {
std::vector<std::string> arg_strs; std::vector<std::string> arg_strs;
#ifdef __cpp_fold_expressions
(_m_fetch_args(arg_strs, std::forward<Args>(args)),...);
#else
_m_fetch_args(arg_strs, std::forward<Args>(args)...); _m_fetch_args(arg_strs, std::forward<Args>(args)...);
#endif
auto msgstr = _m_get(std::move(msgid_utf8)); auto msgstr = _m_get(std::move(msgid_utf8));
_m_replace_args(msgstr, &arg_strs); _m_replace_args(msgstr, &arg_strs);
@ -53,25 +58,28 @@ namespace nana
std::string _m_get(std::string&& msgid) const; std::string _m_get(std::string&& msgid) const;
void _m_replace_args(::std::string& str, std::vector<::std::string> * arg_strs) const; void _m_replace_args(::std::string& str, std::vector<::std::string> * arg_strs) const;
void _m_fetch_args(std::vector<std::string>&) const; //Termination of _m_fetch_args #ifndef __cpp_fold_expressions
static void _m_fetch_args(std::vector<std::string>&); //Termination of _m_fetch_args
#endif
void _m_fetch_args(std::vector<std::string>& v, const char* arg) const; static void _m_fetch_args(std::vector<std::string>& v, const char* arg);
void _m_fetch_args(std::vector<std::string>& v, const std::string& arg) const; static void _m_fetch_args(std::vector<std::string>& v, const std::string& arg);
void _m_fetch_args(std::vector<std::string>& v, std::string& arg) const; static void _m_fetch_args(std::vector<std::string>& v, std::string& arg);
void _m_fetch_args(std::vector<std::string>& v, std::string&& arg) const; static void _m_fetch_args(std::vector<std::string>& v, std::string&& arg);
void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg) const; static void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg);
void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg) const; static void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg);
void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg) const; static void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg);
void _m_fetch_args(std::vector<std::string>& v, std::wstring&& arg) const; static void _m_fetch_args(std::vector<std::string>& v, std::wstring&& arg);
template<typename Arg> template<typename Arg>
void _m_fetch_args(std::vector<std::string>& v, Arg&& arg) const static void _m_fetch_args(std::vector<std::string>& v, Arg&& arg)
{ {
std::stringstream ss; std::stringstream ss;
ss << arg; ss << arg;
v.emplace_back(ss.str()); v.emplace_back(ss.str());
} }
#ifndef __cpp_fold_expressions
template<typename ...Args> template<typename ...Args>
void _m_fetch_args(std::vector<std::string>& v, const char* arg, Args&&... args) const void _m_fetch_args(std::vector<std::string>& v, const char* arg, Args&&... args) const
{ {
@ -136,6 +144,7 @@ namespace nana
v.emplace_back(ss.str()); v.emplace_back(ss.str());
_m_fetch_args(v, std::forward<Args>(args)...); _m_fetch_args(v, std::forward<Args>(args)...);
} }
#endif
};//end class internationalization };//end class internationalization
class i18n_eval class i18n_eval
@ -180,7 +189,11 @@ namespace nana
i18n_eval(std::string msgid_utf8, Args&&... args) i18n_eval(std::string msgid_utf8, Args&&... args)
: msgid_(std::move(msgid_utf8)) : msgid_(std::move(msgid_utf8))
{ {
#ifdef __cpp_fold_expressions
(_m_fetch_args(std::forward<Args>(args)), ...);
#else
_m_fetch_args(std::forward<Args>(args)...); _m_fetch_args(std::forward<Args>(args)...);
#endif
} }
i18n_eval(const i18n_eval&); i18n_eval(const i18n_eval&);
@ -193,6 +206,7 @@ namespace nana
std::string operator()() const; std::string operator()() const;
private: private:
#ifndef __cpp_fold_expressions
void _m_fetch_args(){} //Termination of _m_fetch_args void _m_fetch_args(){} //Termination of _m_fetch_args
template<typename Arg, typename ...Args> template<typename Arg, typename ...Args>
@ -201,6 +215,7 @@ namespace nana
_m_add_args(std::forward<Arg>(arg)); _m_add_args(std::forward<Arg>(arg));
_m_fetch_args(std::forward<Args>(args)...); _m_fetch_args(std::forward<Args>(args)...);
} }
#endif
template<typename Arg> template<typename Arg>
void _m_add_args(Arg&& arg) void _m_add_args(Arg&& arg)

View File

@ -15,8 +15,13 @@
#ifndef NANA_STD_OPTIONAL_HEADER_INCLUDED #ifndef NANA_STD_OPTIONAL_HEADER_INCLUDED
#define NANA_STD_OPTIONAL_HEADER_INCLUDED #define NANA_STD_OPTIONAL_HEADER_INCLUDED
#include <stdexcept>
#include <nana/c++defines.hpp> #include <nana/c++defines.hpp>
#ifndef _nana_std_optional
#include <optional>
#else
#include <stdexcept>
namespace nana namespace nana
{ {
namespace detail namespace detail
@ -361,4 +366,10 @@ namespace nana
}; };
} }
namespace std
{
using nana::optional;
}
#endif //_nana_std_optional
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
* Platform Implementation * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (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) //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); 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); 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); void draw_string(drawable_type, const nana::point&, const wchar_t *, std::size_t len);
}//end namespace detail }//end namespace detail
}//end namespace paint }//end namespace paint

View File

@ -1,7 +1,7 @@
/* /*
* Paint Graphics Implementation * Paint Graphics Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -21,6 +21,10 @@
#include "detail/ptdefs.hpp" #include "detail/ptdefs.hpp"
#ifdef _nana_std_has_string_view
#include <string_view>
#endif
namespace nana namespace nana
{ {
namespace paint namespace paint
@ -108,17 +112,40 @@ namespace nana
void resize(const ::nana::size&); void resize(const ::nana::size&);
void typeface(const font&); ///< Selects a specified font type into the graphics object. void typeface(const font&); ///< Selects a specified font type into the graphics object.
font typeface() const; 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;
///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;
/// 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<unsigned[]> 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 ::std::string&) const;
::nana::size text_extent_size(const char*, std::size_t len) 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 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 ::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 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. ::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.
::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 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; ::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; bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const;
::nana::size bidi_extent_size(const std::wstring&) const; ::nana::size bidi_extent_size(const std::wstring&) const;
::nana::size bidi_extent_size(const std::string&) const; ::nana::size bidi_extent_size(const std::string&) const;
#endif
bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const; bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const;
@ -156,17 +183,27 @@ namespace nana
/// Saves images as a windows bitmap file /// Saves images as a windows bitmap file
/// @param file_utf8 A UTF-8 string to a filename /// @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; ::nana::color palette(bool for_text) const;
graphics& palette(bool for_text, const ::nana::color&); 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, const ::nana::color&);
void set_pixel(int x, int y); 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);
void string(const point&, const std::string& text_utf8, const color&); void string(const point&, const std::string& text_utf8, const color&);
@ -174,6 +211,7 @@ namespace nana
void string(const point&, const wchar_t*); void string(const point&, const wchar_t*);
void string(const point&, const ::std::wstring&); void string(const point&, const ::std::wstring&);
void string(const point&, const ::std::wstring&, const color&); void string(const point&, const ::std::wstring&, const color&);
#endif
void line(const point&, const point&); void line(const point&, const point&);
void line(const point&, const point&, const color&); void line(const point&, const point&, const color&);

View File

@ -86,7 +86,7 @@ namespace std
} }
#endif #endif
#ifdef _enable_std_make_unique #ifdef _nana_std_make_unique
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm
#include <cstddef> #include <cstddef>
@ -124,9 +124,9 @@ namespace std {
typename _Unique_if<T>::_Known_bound typename _Unique_if<T>::_Known_bound
make_unique(Args&&...) = delete; make_unique(Args&&...) = delete;
} }
#endif //_enable_std_make_unique #endif //_nana_std_make_unique
#ifdef _enable_std_put_time #ifdef _nana_std_put_time
#include <ctime> #include <ctime>
#include <string> #include <string>
namespace std namespace std
@ -144,9 +144,9 @@ namespace std
//template<> //template<>
//std::wstring put_time<wchar_t, std::wstring>(const std::tm* tmb, const wchar_t* fmt); //std::wstring put_time<wchar_t, std::wstring>(const std::tm* tmb, const wchar_t* fmt);
} }
#endif // _enable_std_put_time #endif // _nana_std_put_time
#if defined(_enable_std_clamp) #if defined(_nana_std_clamp)
namespace std namespace std
{ {
//<algorithm> since C++17 //<algorithm> since C++17

View File

@ -80,7 +80,7 @@
#pragma message ( SHOW_VALUE(USE_github_com_meganz_mingw_std_threads) ) #pragma message ( SHOW_VALUE(USE_github_com_meganz_mingw_std_threads) )
#pragma message ( SHOW_VALUE(NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) ) #pragma message ( SHOW_VALUE(NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) )
#pragma message ( SHOW_VALUE(STD_THREAD_NOT_SUPPORTED) ) #pragma message ( SHOW_VALUE(STD_THREAD_NOT_SUPPORTED) )
#pragma message ( SHOW_VALUE(_enable_std_put_time) ) #pragma message ( SHOW_VALUE(_nana_std_put_time) )
#pragma message ( SHOW_VALUE(STD_MAKE_UNIQUE_NOT_SUPPORTED) ) #pragma message ( SHOW_VALUE(STD_MAKE_UNIQUE_NOT_SUPPORTED) )
#pragma message ( SHOW_VALUE(STD_FILESYSTEM_NOT_SUPPORTED) ) #pragma message ( SHOW_VALUE(STD_FILESYSTEM_NOT_SUPPORTED) )

View File

@ -65,7 +65,7 @@ namespace nana{namespace audio
bool audio_device::empty() const bool audio_device::empty() const
{ {
#if defined(NANA_POSIX) && not defined(NANA_LINUX) #if defined(NANA_POSIX) && !defined(NANA_LINUX)
return (-1 == handle_); return (-1 == handle_);
#else #else
return (nullptr == handle_); return (nullptr == handle_);
@ -305,7 +305,7 @@ namespace nana{namespace audio
}//end namespace audio }//end namespace audio
}//end namespace nana }//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. // parse input securely, no-overruns or overflows.
static bool match(char *&cursor, const char *pattern, const char *tail) static bool match(char *&cursor, const char *pattern, const char *tail)
{ {

View File

@ -28,6 +28,42 @@
namespace nana namespace nana
{ {
#ifdef _nana_std_has_string_view
bool is_utf8(std::string_view str)
{
auto ustr = reinterpret_cast<const unsigned char*>(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) bool is_utf8(const char* str, std::size_t len)
{ {
auto ustr = reinterpret_cast<const unsigned char*>(str); auto ustr = reinterpret_cast<const unsigned char*>(str);
@ -57,6 +93,23 @@ namespace nana
return true; 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 //class utf8_Error
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -79,22 +132,6 @@ namespace nana
bool utf8_Error::use_throw{ false }; bool utf8_Error::use_throw{ false };
//end class utf8_Error //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) std::string recode_to_utf8(std::string no_utf8)
{ {
return nana::charset(std::move(no_utf8)).to_bytes(nana::unicode::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 ?? /// this text needed change, it needed review ??
bool review_utf8(const std::string& text) 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())) if (!is_utf8(text.c_str(), text.length()))
#endif
{ {
utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit(); utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit();
return true; /// it needed change, it needed review !! return true; /// it needed change, it needed review !!
@ -115,7 +156,11 @@ namespace nana
/// this text needed change, it needed review ?? /// this text needed change, it needed review ??
bool review_utf8(std::string& text) 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())) if (!is_utf8(text.c_str(), text.length()))
#endif
{ {
utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit();
text=recode_to_utf8(text); text=recode_to_utf8(text);
@ -135,10 +180,21 @@ namespace nana
return ::nana::charset(text).to_bytes(::nana::unicode::utf8); 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) std::wstring to_wstring(const std::string& utf8_str)
{ {
return ::nana::charset(utf8_str, ::nana::unicode::utf8); return ::nana::charset(utf8_str, ::nana::unicode::utf8);
} }
#endif
const std::wstring& to_wstring(const std::wstring& wstr) const std::wstring& to_wstring(const std::wstring& wstr)
{ {

View File

@ -16,7 +16,7 @@
#include <sstream> #include <sstream>
#include <nana/config.hpp> #include <nana/config.hpp>
#ifdef _enable_std_put_time #ifdef _nana_std_put_time
#include <nana/stdc++.hpp> #include <nana/stdc++.hpp>
#else #else
#include <iomanip> #include <iomanip>

View File

@ -911,11 +911,18 @@ namespace detail
case Expose: case Expose:
if(msgwnd->visible && (msgwnd->root_graph->empty() == false)) if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
{ {
nana::detail::platform_scope_guard psg; nana::detail::platform_scope_guard lock;
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. if(msgwnd->is_draw_through())
::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); {
if (!update_area.empty()) msgwnd->other.attribute.root->draw_through();
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area); }
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<window>(msgwnd), true, &update_area);
}
} }
break; break;
case KeyPress: case KeyPress:
@ -1142,28 +1149,29 @@ namespace detail
{ {
msgwnd->set_action(mouse_action::normal); msgwnd->set_action(mouse_action::normal);
arg_click click_arg; auto retain = msgwnd->annex.events_ptr;
click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->annex.events_ptr; arg_click click_arg;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) click_arg.mouse_args = nullptr;
{ click_arg.window_handle = reinterpret_cast<window>(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<window>(msgwnd);
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); arg_mouse arg;
wd_manager.do_lazy_refresh(msgwnd, false); arg.alt = false;
} arg.button = ::nana::mouse::left_button;
pressed_wd_space = nullptr; 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<window>(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 else
{ {

View File

@ -408,16 +408,7 @@ namespace detail
if (msg.message == WM_QUIT) break; if (msg.message == WM_QUIT) break;
if ((WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST) || !::IsDialogMessage(native_handle, &msg)) if ((WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST) || !::IsDialogMessage(native_handle, &msg))
{ {
#if 0
auto menu_wd = get_menu(reinterpret_cast<native_window_type>(msg.hwnd), true);
if (menu_wd) interior_helper_for_menu(msg, menu_wd);
::TranslateMessage(&msg); //deprecated
::DispatchMessage(&msg);
#else
process_msg(this, msg); process_msg(this, msg);
#endif
wd_manager().remove_trash_handle(tid); wd_manager().remove_trash_handle(tid);
} }
} }
@ -429,15 +420,7 @@ namespace detail
{ {
if (-1 != ::GetMessage(&msg, 0, 0, 0)) if (-1 != ::GetMessage(&msg, 0, 0, 0))
{ {
#if 0
auto menu_wd = get_menu(reinterpret_cast<native_window_type>(msg.hwnd), true);
if (menu_wd) interior_helper_for_menu(msg, menu_wd);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
#else
process_msg(this, msg); process_msg(this, msg);
#endif
} }
wd_manager().call_safe_place(tid); wd_manager().call_safe_place(tid);
@ -452,17 +435,7 @@ namespace detail
while(context->window_count) while(context->window_count)
{ {
if(-1 != ::GetMessage(&msg, 0, 0, 0)) if(-1 != ::GetMessage(&msg, 0, 0, 0))
{
#if 0
auto menu_wd = get_menu(reinterpret_cast<native_window_type>(msg.hwnd), true);
if(menu_wd) interior_helper_for_menu(msg, menu_wd);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
#else
process_msg(this, msg); process_msg(this, msg);
#endif
}
wd_manager().call_safe_place(tid); wd_manager().call_safe_place(tid);
wd_manager().remove_trash_handle(tid); wd_manager().remove_trash_handle(tid);
@ -1522,38 +1495,40 @@ namespace detail
{ {
msgwnd->set_action(mouse_action::normal); msgwnd->set_action(mouse_action::normal);
auto retain = msgwnd->annex.events_ptr;
arg_click click_arg; arg_click click_arg;
click_arg.mouse_args = nullptr; click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd); click_arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->annex.events_ptr; arg_mouse arg;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) arg.alt = false;
{ arg.button = ::nana::mouse::left_button;
arg_mouse arg; arg.ctrl = false;
arg.alt = false; arg.evt_code = event_code::mouse_up;
arg.button = ::nana::mouse::left_button; arg.left_button = true;
arg.ctrl = false; arg.mid_button = false;
arg.evt_code = event_code::mouse_up; arg.pos.x = 0;
arg.left_button = true; arg.pos.y = 0;
arg.mid_button = false; arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.pos.x = 0;
arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(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); wd_manager.do_lazy_refresh(msgwnd, false);
}
pressed_wd_space = nullptr; pressed_wd_space = nullptr;
} }
else else
{ {
arg_keyboard arg; arg_keyboard keyboard_arg;
arg.evt_code = event_code::key_release; keyboard_arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd); keyboard_arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.key = translate_virtual_key(wParam); keyboard_arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg); brock.get_key_state(keyboard_arg);
arg.ignore = false; keyboard_arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
brock.emit(event_code::key_release, msgwnd, keyboard_arg, true, &context);
} }
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Filebox * Filebox
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -15,18 +15,19 @@
#include <nana/filesystem/filesystem_ext.hpp> #include <nana/filesystem/filesystem_ext.hpp>
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
#include <windows.h> # include <windows.h>
# include <Shobjidl.h>
#elif defined(NANA_POSIX) #elif defined(NANA_POSIX)
#include <nana/gui/widgets/label.hpp> # include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp> # include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/listbox.hpp> # include <nana/gui/widgets/listbox.hpp>
#include <nana/gui/widgets/categorize.hpp> # include <nana/gui/widgets/categorize.hpp>
#include <nana/gui/widgets/textbox.hpp> # include <nana/gui/widgets/textbox.hpp>
#include <nana/gui/widgets/treebox.hpp> # include <nana/gui/widgets/treebox.hpp>
#include <nana/gui/widgets/combox.hpp> # include <nana/gui/widgets/combox.hpp>
#include <nana/gui/place.hpp> # include <nana/gui/place.hpp>
#include <stdexcept> # include <stdexcept>
#include <algorithm> # include <algorithm>
#endif #endif
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
@ -130,6 +131,13 @@ namespace nana
} }
}; };
public: 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 struct kind
{ {
enum t{none, filesystem}; enum t{none, filesystem};
@ -138,8 +146,10 @@ namespace nana
typedef treebox::item_proxy item_proxy; typedef treebox::item_proxy item_proxy;
public: public:
filebox_implement(window owner, bool io_read, const std::string& title) filebox_implement(window owner, mode dialog_mode, const std::string& title, bool pick_directory = false):
: form(owner, API::make_center(owner, 630, 440)), io_read_(io_read) form(owner, API::make_center(owner, 630, 440)),
pick_directory_(pick_directory),
mode_(dialog_mode)
{ {
internationalization i18n; internationalization i18n;
path_.create(*this); path_.create(*this);
@ -159,6 +169,7 @@ namespace nana
_m_load_cat_path(path); _m_load_cat_path(path);
}); });
filter_.create(*this); filter_.create(*this);
filter_.multi_lines(false); filter_.multi_lines(false);
filter_.tip_string(i18n("NANA_FILEBOX_FILTER")); filter_.tip_string(i18n("NANA_FILEBOX_FILTER"));
@ -203,7 +214,7 @@ namespace nana
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70); ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70);
auto fn_sel_file = [this](const arg_mouse& arg){ 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().dbl_click.connect_unignorable(fn_sel_file);
ls_file_.events().mouse_down.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_.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_.create(*this);
tb_file_.multi_lines(false); tb_file_.multi_lines(false);
@ -289,9 +304,13 @@ namespace nana
_m_ok(); _m_ok();
}); });
cb_types_.create(*this); //Don't create the combox for choose a file extension if the dialog is used for picking a directory.
cb_types_.editable(false); if(!pick_directory)
cb_types_.events().selected.connect_unignorable([this](const arg_combox&){ _m_list_fs(); }); {
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_.create(*this);
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY")); btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY"));
@ -313,10 +332,25 @@ namespace nana
_m_layout(); _m_layout();
_m_init_tree(); _m_init_tree();
if(0 == title.size()) if(title.empty())
this->i18n(i18n_eval(io_read ? "NANA_FILEBOX_OPEN" : "NANA_FILEBOX_SAVE_AS")); {
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 else
caption(title); caption(title);
} }
void def_extension(const std::string& ext) void def_extension(const std::string& ext)
@ -412,16 +446,21 @@ namespace nana
"<weight=34 margin=5 path arrange=[variable,200] gap=5>" "<weight=34 margin=5 path arrange=[variable,200] gap=5>"
"<weight=30 margin=[0,0,5,10] new_folder arrange=[100]>" "<weight=30 margin=[0,0,5,10] new_folder arrange=[100]>"
"<content arrange=[180] gap=[5]><weight=8>" "<content arrange=[180] gap=[5]><weight=8>"
"<weight=26<weight=100><vert weight=60 label margin=[0,0,0,5]>" "<weight=26<weight=100><vert weight=80 label margin=[0,5,0,0]>"
"<file margin=[0,18,0,5] arrange=[variable,variable,190] gap=[10]>>" "<file margin=[0,18,0,5] arrange=[variable,variable,190] gap=[10]>>"
"<weight=48 margin=[8,0,14]<>" "<weight=48 margin=[8,0,14]<>"
"<buttons weight=208 margin=[0,18,0] gap=[14]>>"); "<buttons weight=208 margin=[0,18,0] gap=[14]>>");
place_.field("path")<<path_<<filter_; place_.field("path")<<path_<<filter_;
place_.field("new_folder")<<btn_folder_; place_.field("new_folder")<<btn_folder_;
place_.field("content")<<tree_<<ls_file_; place_.field("content")<<tree_<<ls_file_;
place_.field("label")<<lb_file_; place_.field("label")<<lb_file_;
place_.field("file")<<tb_file_<<cb_types_; place_.field("file")<<tb_file_;
if(!pick_directory_)
place_.field("file")<<cb_types_;
place_.field("buttons")<<btn_ok_<<btn_cancel_; place_.field("buttons")<<btn_ok_<<btn_cancel_;
place_.collocate(); place_.collocate();
} }
@ -630,6 +669,9 @@ namespace nana
if(filter.size() && (name.find(filter) == filter.npos)) if(filter.size() && (name.find(filter) == filter.npos))
return false; return false;
if(pick_directory_)
return is_dir;
if((is_dir || 0 == extension) || (0 == extension->size())) return true; if((is_dir || 0 == extension) || (0 == extension->size())) return true;
for(auto & extstr : *extension) for(auto & extstr : *extension)
@ -744,7 +786,7 @@ namespace nana
return true; return true;
} }
private: private:
void _m_sel_file(const arg_mouse& arg) void _m_select_file(const arg_mouse& arg)
{ {
auto sel = ls_file_.selected(); auto sel = ls_file_.selected();
if(sel.empty()) if(sel.empty())
@ -763,7 +805,7 @@ namespace nana
} }
else else
{ {
if(false == m.directory) if((mode::open_directory == mode_) || (false == m.directory))
{ {
selection_.target = addr_.filesystem + m.name; selection_.target = addr_.filesystem + m.name;
tb_file_.caption(m.name); tb_file_.caption(m.name);
@ -816,13 +858,16 @@ namespace nana
return; return;
} }
if(io_read_) if(mode::write_file != mode_)
{ {
if(fs::file_type::not_found == ftype) if(fs::file_type::not_found == ftype)
{ {
msgbox mb(*this, caption()); msgbox mb(*this, caption());
mb.icon(msgbox::icon_information); 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(); mb();
return; return;
@ -892,7 +937,8 @@ namespace nana
} }
} }
private: private:
bool io_read_; bool const pick_directory_;
mode mode_;
std::string def_ext_; std::string def_ext_;
place place_; place place_;
@ -933,224 +979,298 @@ namespace nana
#endif #endif
//class filebox //class filebox
struct filebox::implement struct filebox::implement
{
struct filter
{ {
struct filter std::string des;
{ std::string type;
std::string des;
std::string type;
};
window owner;
bool open_or_save;
std::string file;
std::string title;
std::string path;
std::vector<filter> filters;
}; };
filebox::filebox(bool is_openmode) window owner;
: filebox(nullptr, is_openmode) bool open_or_save;
{
}
filebox::filebox(window owner, bool open) std::string file;
: impl_(new implement) std::string title;
{ std::string path;
impl_->owner = owner; std::vector<filter> filters;
impl_->open_or_save = open; };
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) #if defined(NANA_WINDOWS)
auto len = ::GetCurrentDirectory(0, nullptr); auto len = ::GetCurrentDirectory(0, nullptr);
if(len) if(len)
{ {
std::wstring path; std::wstring path;
path.resize(len + 1); path.resize(len + 1);
::GetCurrentDirectory(len, &(path[0])); ::GetCurrentDirectory(len, &(path[0]));
path.resize(len); path.resize(len);
impl_->path = to_utf8(path); impl_->path = to_utf8(path);
} }
#endif #endif
} }
filebox::filebox(const filebox& other) filebox::filebox(const filebox& other)
: impl_(new implement(*other.impl_)) : 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();
} }
else
filebox& filebox::operator=(const filebox& other)
{ {
if (this != &other) if (fs::is_directory(ipstr))
*impl_ = *other.impl_; impl_->path = ipstr;
return *this;
} }
return *this;
}
void filebox::owner(window wd) filebox& filebox::init_file(const std::string& ifstr)
{ {
impl_->owner = wd; impl_->file = ifstr;
} return *this;
}
std::string filebox::title(std::string s) filebox& filebox::add_filter(const std::string& description, const std::string& filetype)
{ {
impl_->title.swap(s); implement::filter flt = {description, filetype};
return s; impl_->filters.push_back(flt);
} return *this;
}
filebox& filebox::init_path(const std::string& ipstr) std::string filebox::path() const
{ {
if(ipstr.empty()) return impl_->path;
{ }
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::file() const std::string filebox::file() const
{ {
return impl_->file; return impl_->file;
} }
bool filebox::show() const bool filebox::show() const
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
auto winitfile = to_wstring(impl_->file); auto winitfile = to_wstring(impl_->file);
std::wstring wfile(winitfile); std::wstring wfile(winitfile);
wfile.resize(520); wfile.resize(520);
OPENFILENAME ofn; OPENFILENAME ofn;
memset(&ofn, 0, sizeof ofn); memset(&ofn, 0, sizeof ofn);
internal_scope_guard lock; internal_scope_guard lock;
ofn.lStructSize = sizeof(ofn); ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = reinterpret_cast<HWND>(API::root(impl_->owner)); ofn.hwndOwner = reinterpret_cast<HWND>(API::root(impl_->owner));
ofn.lpstrFile = &(wfile[0]); ofn.lpstrFile = &(wfile[0]);
ofn.nMaxFile = static_cast<DWORD>(wfile.size() - 1); ofn.nMaxFile = static_cast<DWORD>(wfile.size() - 1);
const wchar_t * filter; const wchar_t * filter;
std::wstring filter_holder; std::wstring filter_holder;
std::wstring default_extension; std::wstring default_extension;
if(impl_->filters.size()) if(impl_->filters.size())
{
for(auto & f : impl_->filters)
{ {
for(auto & f : impl_->filters) filter_holder += to_wstring(f.des);
filter_holder += static_cast<std::wstring::value_type>('\0');
std::wstring fs = to_wstring(f.type);
std::size_t pos = 0;
while(true)
{ {
filter_holder += to_wstring(f.des); pos = fs.find(L" ", pos);
filter_holder += static_cast<std::wstring::value_type>('\0'); if(pos == fs.npos)
std::wstring fs = to_wstring(f.type); break;
std::size_t pos = 0; fs.erase(pos);
while(true) }
{ filter_holder += fs;
pos = fs.find(L" ", pos); filter_holder += static_cast<std::wstring::value_type>('\0');
if(pos == fs.npos)
break;
fs.erase(pos);
}
filter_holder += fs;
filter_holder += static_cast<std::wstring::value_type>('\0');
//Get the default file extentsion //Get the default file extentsion
if (default_extension.empty()) if (default_extension.empty())
{
pos = fs.find_last_of('.');
if (pos != fs.npos)
{ {
pos = fs.find_last_of('.'); fs = fs.substr(pos + 1);
if (pos != fs.npos) if (fs != L"*")
{ {
fs = fs.substr(pos + 1); default_extension = fs;
if (fs != L"*") ofn.lpstrDefExt = default_extension.data();
{
default_extension = fs;
ofn.lpstrDefExt = default_extension.data();
}
} }
} }
} }
filter = filter_holder.data();
} }
else filter = filter_holder.data();
filter = L"All Files\0*.*\0"; }
else
filter = L"All Files\0*.*\0";
auto wtitle = to_wstring(impl_->title); auto wtitle = to_wstring(impl_->title);
auto wpath = to_wstring(impl_->path); auto wpath = to_wstring(impl_->path);
ofn.lpstrFilter = filter; ofn.lpstrFilter = filter;
ofn.lpstrTitle = (wtitle.empty() ? nullptr : wtitle.c_str()); ofn.lpstrTitle = (wtitle.empty() ? nullptr : wtitle.c_str());
ofn.nFilterIndex = 0; ofn.nFilterIndex = 0;
ofn.lpstrFileTitle = nullptr; ofn.lpstrFileTitle = nullptr;
ofn.nMaxFileTitle = 0; ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = (wpath.empty() ? nullptr : wpath.c_str()); ofn.lpstrInitialDir = (wpath.empty() ? nullptr : wpath.c_str());
if (!impl_->open_or_save) if (!impl_->open_or_save)
ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode
ofn.Flags |= OFN_NOCHANGEDIR; ofn.Flags |= OFN_NOCHANGEDIR;
{ {
internal_revert_guard revert; internal_revert_guard revert;
if (FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn))) 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))
return false; 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; wfile.resize(std::wcslen(wfile.data()));
}//end class filebox 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::path_type> 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<HWND>(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 }//end namespace nana

View File

@ -1294,8 +1294,10 @@ namespace nana
min_width_entry_field_pixels_ = pixels; min_width_entry_field_pixels_ = pixels;
} }
#ifndef _nana_cxx_folding_expression
void inputbox::_m_fetch_args(std::vector<abstract_content*>&) void inputbox::_m_fetch_args(std::vector<abstract_content*>&)
{} {}
#endif
bool inputbox::_m_open(std::vector<abstract_content*>& contents, bool modal) bool inputbox::_m_open(std::vector<abstract_content*>& contents, bool modal)
{ {

View File

@ -64,8 +64,8 @@ namespace nana
eof, error eof, error
}; };
tokenizer(const char* p) noexcept tokenizer(const char* div_text) noexcept
: divstr_(p), sp_(p) : divstr_(div_text), sp_(div_text)
{} {}
const std::string& idstr() const noexcept const std::string& idstr() const noexcept
@ -2583,9 +2583,8 @@ namespace nana
: public division : public division
{ {
public: public:
div_switchable(std::string && name, implement* /*impl*/) noexcept: div_switchable(std::string && name, implement*) noexcept:
division(kind::switchable, std::move(name))//, division(kind::switchable, std::move(name))
//impl_(impl) //deprecated
{} {}
private: private:
void collocate(window wd) override void collocate(window wd) override
@ -2613,8 +2612,6 @@ namespace nana
} }
} }
} }
private:
//implement * const impl_; //deprecated
}; };
place::implement::~implement() place::implement::~implement()
@ -3183,9 +3180,9 @@ namespace nana
sp->set_renderer(impl_->split_renderer, true); 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(); impl_->disconnect();
auto div = impl_->scan_div(tknizer); auto div = impl_->scan_div(tknizer);
try try
@ -3193,7 +3190,7 @@ namespace nana
impl_->connect(div.get()); //throws if there is a redefined name of field. impl_->connect(div.get()); //throws if there is a redefined name of field.
impl_->root_division.reset(); //clear atachments div-fields impl_->root_division.reset(); //clear atachments div-fields
impl_->root_division.swap(div); impl_->root_division.swap(div);
impl_->div_text.assign(s); impl_->div_text.swap(div_text);
} }
catch (...) catch (...)
{ {
@ -3210,7 +3207,7 @@ namespace nana
//Contributed by dankan1890(PR#156) //Contributed by dankan1890(PR#156)
enum class update_operation { erase = 0, insert, replace }; 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) void place::modify(const char* name, const char* div_text)
{ {
@ -3324,7 +3321,7 @@ namespace nana
return *p; 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); const auto fieldname_pos = find_idstr(div, field);
if (div.npos == fieldname_pos) if (div.npos == fieldname_pos)

View File

@ -21,6 +21,9 @@
#include <nana/gui/detail/events_operation.hpp> #include <nana/gui/detail/events_operation.hpp>
#include "../../source/detail/platform_abstraction.hpp" #include "../../source/detail/platform_abstraction.hpp"
#ifdef NANA_X11
# include "../../source/detail/posix/platform_spec.hpp"
#endif
namespace nana namespace nana
{ {
@ -52,6 +55,19 @@ namespace nana
} }
namespace API 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 basic_window = ::nana::detail::basic_window;
using interface_type = ::nana::detail::native_interface; using interface_type = ::nana::detail::native_interface;
@ -244,7 +260,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<basic_window*>(wd); auto const iwd = reinterpret_cast<basic_window*>(wd);
internal_scope_guard isg; internal_scope_guard isg;
@ -377,8 +393,13 @@ namespace API
{ {
if (shortkey) 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<int>(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 off_x = (shortkey_position ? graph.text_extent_size(text.c_str(), shortkey_position).width : 0);
auto key_px = static_cast<int>(graph.text_extent_size(&shortkey, 1).width); auto key_px = static_cast<int>(graph.text_extent_size(&shortkey, 1).width);
#endif
unsigned ascent, descent, inleading; unsigned ascent, descent, inleading;
graph.text_metrics(ascent, descent, inleading); graph.text_metrics(ascent, descent, inleading);
@ -392,7 +413,6 @@ namespace API
} }
}//end namespace dev }//end namespace dev
widget* get_widget(window wd) widget* get_widget(window wd)
{ {
internal_scope_guard lock; internal_scope_guard lock;
@ -823,7 +843,7 @@ namespace API
} }
} }
nana::optional<rectangle> window_rectangle(window wd) std::optional<rectangle> window_rectangle(window wd)
{ {
auto iwd = reinterpret_cast<basic_window*>(wd); auto iwd = reinterpret_cast<basic_window*>(wd);
internal_scope_guard lock; internal_scope_guard lock;
@ -1461,7 +1481,7 @@ namespace API
restrict::wd_manager().set_safe_place(reinterpret_cast<basic_window*>(wd), std::move(fn)); restrict::wd_manager().set_safe_place(reinterpret_cast<basic_window*>(wd), std::move(fn));
} }
optional<std::pair<size, size>> content_extent(window wd, unsigned limited_px, bool limit_width) std::optional<std::pair<size, size>> content_extent(window wd, unsigned limited_px, bool limit_width)
{ {
auto iwd = reinterpret_cast<basic_window*>(wd); auto iwd = reinterpret_cast<basic_window*>(wd);
internal_scope_guard lock; internal_scope_guard lock;

View File

@ -1,7 +1,7 @@
/* /*
* A Button Implementation * A Button Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -27,7 +27,7 @@ namespace nana{ namespace drawerbase
: trigger_{ t } : trigger_{ t }
{} {}
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override std::optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override
{ {
//Button doesn't provide a support of vfit and hfit //Button doesn't provide a support of vfit and hfit
if (limit_pixels) if (limit_pixels)
@ -262,7 +262,11 @@ namespace nana{ namespace drawerbase
if (attr_.omitted) if (attr_.omitted)
tr.render(pos, txtptr, txtlen, omitted_pixels, true); tr.render(pos, txtptr, txtlen, omitted_pixels, true);
else else
#ifdef _nana_std_has_string_view
graph.bidi_string(pos, { txtptr, txtlen });
#else
graph.bidi_string(pos, txtptr, txtlen); graph.bidi_string(pos, txtptr, txtlen);
#endif
API::dev::draw_shortkey_underline(graph, mbstr, shortkey, shortkey_pos, pos, text_color); API::dev::draw_shortkey_underline(graph, mbstr, shortkey, shortkey_pos, pos, text_color);
} }
@ -277,9 +281,15 @@ namespace nana{ namespace drawerbase
} }
else 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.bidi_string(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen);
graph.palette(true, color{ colors::gray }); graph.palette(true, color{ colors::gray });
graph.bidi_string(pos, txtptr, txtlen); graph.bidi_string(pos, txtptr, txtlen);
#endif
} }
} }
} }

View File

@ -78,7 +78,11 @@ namespace nana{ namespace drawerbase
} }
//draw crook //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; 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)); impl_->crook.draw(graph, wdg->bgcolor(), wdg->fgcolor(), rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg));
} }
@ -163,12 +167,12 @@ namespace nana{ namespace drawerbase
return (get_drawer_trigger().impl()->crook.checked() != drawerbase::checkbox::crook_state::unchecked); 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; 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()); API::refresh_window(handle());
arg_checkbox arg(this); arg_checkbox arg(this);

View File

@ -90,7 +90,7 @@ namespace nana
: drw_{ drwimpl } : drw_{ drwimpl }
{} {}
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override std::optional<size> measure(graph_reference graph, unsigned limit_pixels, bool /*limit_width*/) const override
{ {
//Combox doesn't provide a support of vfit and hfit //Combox doesn't provide a support of vfit and hfit
if (limit_pixels) if (limit_pixels)
@ -1037,7 +1037,7 @@ namespace nana
API::refresh_window(*this); 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; internal_scope_guard lock;
auto editor = _m_impl().editor(); auto editor = _m_impl().editor();

View File

@ -35,6 +35,7 @@ namespace nana{
struct group::implement struct group::implement
{ {
label caption; label caption;
align caption_align{ align::left };
place place_content; place place_content;
unsigned gap{2}; unsigned gap{2};
std::string usr_div_str; std::string usr_div_str;
@ -65,11 +66,27 @@ namespace nana{
void update_div() void update_div()
{ {
const std::size_t padding = 10;
caption_dimension = caption.measure(1000); 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) + "]"; std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
div += "<weight=" + std::to_string(caption_dimension.height) + " <weight=5><" + field_title + " weight=" + std::to_string(caption_dimension.width + 1) + ">>";
div += "<<vert margin=5 " + std::string(field_options) + ">"; div += "<weight=" + std::to_string(caption_dimension.height) + " ";
if (align::left == caption_align)
div += "<weight=" + std::to_string(padding) + ">";
else
div += "<>"; //right or center
div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">";
if (align::right == caption_align)
div += "<weight=" + std::to_string(padding) + ">";
else if (align::center == caption_align)
div += "<>";
div += "><<vert margin=5 " + std::string(field_options) + ">";
if (!usr_div_str.empty()) if (!usr_div_str.empty())
div += "<" + usr_div_str + ">>"; div += "<" + usr_div_str + ">>";
@ -97,10 +114,15 @@ namespace nana{
create(parent, r, vsb); create(parent, r, vsb);
} }
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb) group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
: panel(parent, r, vsb), : group(parent, r, vsb)
impl_(new implement(*this, std::move(titel), vsb, gap))
{ {
this->bgcolor(API::bgcolor(parent));
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
impl_->caption.format(formatted); impl_->caption.format(formatted);
_m_init(); _m_init();
} }
@ -128,6 +150,17 @@ namespace nana{
return *impl_->options.back(); 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) group& group::radio_mode(bool enable)
{ {
_THROW_IF_EMPTY() _THROW_IF_EMPTY()
@ -243,7 +276,7 @@ namespace nana{
graph.round_rectangle(rectangle(point(gap_px, top_round_line), graph.round_rectangle(rectangle(point(gap_px, top_round_line),
nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px) 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); auto opt_r = API::window_rectangle(impl_->caption);
if (opt_r) if (opt_r)
@ -263,15 +296,12 @@ namespace nana{
void group::_m_complete_creation() void group::_m_complete_creation()
{ {
panel::_m_complete_creation(); widget::_m_complete_creation();
impl_->create(handle()); impl_->create(handle());
_m_init(); _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(); return impl_->caption.caption_native();
} }

View File

@ -1,7 +1,7 @@
/* /*
* A Label Control Implementation * A Label Control Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -83,7 +83,11 @@ namespace nana
auto pre_font = graph.typeface(); //used for restoring the font 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; const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height;
#endif
font_ = pre_font; font_ = pre_font;
fblock_ = nullptr; fblock_ = nullptr;
@ -170,7 +174,11 @@ namespace nana
auto ft = graph.typeface(); //used for restoring the font 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; const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height;
#endif
font_ = ft; font_ = ft;
fblock_ = nullptr; fblock_ = nullptr;
@ -556,6 +564,16 @@ namespace nana
_m_change_font(graph, fblock_ptr); _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()) if (text_range.second == data_ptr->text().length())
{ {
graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr)); graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr));
@ -567,6 +585,7 @@ namespace nana
graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr)); graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
} }
#endif
_m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr); _m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr);
@ -653,7 +672,7 @@ namespace nana
: impl_{ impl } : impl_{ impl }
{} {}
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override std::optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
{ {
//Label now doesn't support to measure content with a specified height. //Label now doesn't support to measure content with a specified height.
if (graph && ((0 == limit_pixels) || limit_width)) if (graph && ((0 == limit_pixels) || limit_width))
@ -825,7 +844,7 @@ namespace nana
return *this; return *this;
} }
bool label::transparent() const throw() bool label::transparent() const noexcept
{ {
return API::is_transparent_background(*this); return API::is_transparent_background(*this);
} }
@ -849,7 +868,7 @@ namespace nana
return *this; 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; get_drawer_trigger().impl()->for_associated_wd = associated_window;
return *this; return *this;

View File

@ -2470,10 +2470,10 @@ namespace nana
x += col.width_px; x += col.width_px;
if (x > 0) if (x > 0)
{ {
seqs.push_back(col.index);
if (x >= static_cast<int>(lister_w)) if (x >= static_cast<int>(lister_w))
break; break;
seqs.push_back(col.index);
} }
} }
return seqs; return seqs;
@ -2757,6 +2757,17 @@ namespace nana
unsigned es_lister::column_content_pixels(size_type pos) const unsigned es_lister::column_content_pixels(size_type pos) const
{ {
unsigned max_px = 0; unsigned max_px = 0;
std::unique_ptr<paint::graphics> 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 (auto & cat : categories_)
{ {
for (std::size_t i = 0; i < cat.items.size(); ++i) for (std::size_t i = 0; i < cat.items.size(); ++i)
@ -2768,14 +2779,14 @@ namespace nana
if (pos >= model_cells.size()) if (pos >= model_cells.size())
continue; 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 else
{ {
if (pos >= cat.items[i].cells->size()) if (pos >= cat.items[i].cells->size())
continue; 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) if (content_px > max_px)

View File

@ -74,7 +74,7 @@ namespace nana
: impl_{impl} : impl_{impl}
{} {}
optional<size> measure(graph_reference /*graph*/, unsigned limit_pixels, bool /*limit_width*/) const override std::optional<size> measure(graph_reference /*graph*/, unsigned limit_pixels, bool /*limit_width*/) const override
{ {
//Picture doesn't provide a support of vfit and hfit //Picture doesn't provide a support of vfit and hfit
if (!limit_pixels) if (!limit_pixels)

View File

@ -68,12 +68,6 @@ namespace nana {
bool drag_started{ false }; bool drag_started{ false };
point origin; point origin;
/*
scrolls enabled_scrolls{scrolls::both}; //deprecated
nana::scroll<false> horz;
nana::scroll<true> vert;
*/
std::shared_ptr<cv_scroll_rep> cv_scroll; std::shared_ptr<cv_scroll_rep> cv_scroll;
timer tmr; timer tmr;
@ -91,27 +85,10 @@ namespace nana {
cv_scroll(std::make_shared<cv_scroll_rep>()) cv_scroll(std::make_shared<cv_scroll_rep>())
{ {
API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) { 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 = &vert;
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()); auto align_px = (scroll->value() % scroll->step());
if (align_px) if (align_px)

View File

@ -834,8 +834,12 @@ namespace nana{ namespace widgets
if (str_w > pixels) //Indicates the splitting of ts string if (str_w > pixels) //Indicates the splitting of ts string
{ {
std::size_t len = ts.end - ts.begin; 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<unsigned[]> pxbuf(new unsigned[len]); std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
editor_.graph_.glyph_pixels(ts.begin, len, pxbuf.get()); editor_.graph_.glyph_pixels(ts.begin, len, pxbuf.get());
#endif
auto pxptr = pxbuf.get(); auto pxptr = pxbuf.get();
auto pxend = pxptr + len; auto pxend = pxptr + len;
@ -3147,7 +3151,11 @@ namespace nana{ namespace widgets
maskstr.append(n, mask_char_); maskstr.append(n, mask_char_);
return graph_.text_extent_size(maskstr); return graph_.text_extent_size(maskstr);
} }
#ifdef _nana_std_has_string_view
return graph_.text_extent_size(std::basic_string_view<char_type>(str, n));
#else
return graph_.text_extent_size(str, static_cast<unsigned>(n)); return graph_.text_extent_size(str, static_cast<unsigned>(n));
#endif
} }
bool text_editor::_m_adjust_view() bool text_editor::_m_adjust_view()
@ -3301,13 +3309,21 @@ 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 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_.palette(true, fgcolor);
graph_.string(pos, str, len); graph_.string(pos, str, len);
#endif
if (parser.entities().empty()) if (parser.entities().empty())
return; return;
#ifdef _nana_std_has_string_view
auto glyph_px = graph_.glyph_pixels({ str, len });
#else
std::unique_ptr<unsigned[]> glyph_px(new unsigned[len]); std::unique_ptr<unsigned[]> glyph_px(new unsigned[len]);
graph_.glyph_pixels(str, len, glyph_px.get()); graph_.glyph_pixels(str, len, glyph_px.get());
#endif
auto glyphs = glyph_px.get(); auto glyphs = glyph_px.get();
auto px_h = line_height(); auto px_h = line_height();
@ -3347,7 +3363,20 @@ namespace nana{ namespace widgets
ent_pos.x = pos.x + ent_off; 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<std::wstring_view::size_type>(ent_end - ent_begin) };
ent_off = 0;
}
canvas.string({}, ent_sv);
#else
if (rtl) if (rtl)
{ {
//draw the whole text if it is a RTL text, because Arbic language is transformable. //draw the whole text if it is a RTL text, because Arbic language is transformable.
@ -3358,6 +3387,7 @@ namespace nana{ namespace widgets
canvas.string({}, ent_begin, ent_end - ent_begin); canvas.string({}, ent_begin, ent_end - ent_begin);
ent_off = 0; ent_off = 0;
} }
#endif
graph_.bitblt(rectangle{ ent_pos, size{ ent_pixels, canvas.height() } }, canvas, point{ ent_off, 0 }); graph_.bitblt(rectangle{ ent_pos, size{ ent_pixels, canvas.height() } }, canvas, point{ ent_off, 0 });
} }
} }
@ -3383,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) 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_.palette(true, selection_color(true, has_focused));
graph_.rectangle(::nana::rectangle{ text_pos, { text_px, line_px_ } }, true, graph_.rectangle(::nana::rectangle{ text_pos, { text_px, line_px_ } }, true,
selection_color(false, has_focused)); selection_color(false, has_focused));
graph_.string(text_pos, text, len); 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) 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)
@ -3402,9 +3439,12 @@ namespace nana{ namespace widgets
int sel_xpos = static_cast<int>(str_px - (glyph_front + glyph_selected)); int sel_xpos = static_cast<int>(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.palette(true, selection_color(true, has_focused));
graph.string({ -sel_xpos, 0 }, str, len); graph.string({ -sel_xpos, 0 }, str, len);
#endif
graph_.bitblt(nana::rectangle(strpos.x + sel_xpos, strpos.y, glyph_selected, line_px_), graph); graph_.bitblt(nana::rectangle(strpos.x + sel_xpos, strpos.y, glyph_selected, line_px_), graph);
}; };
private: private:
@ -3500,7 +3540,12 @@ namespace nana{ namespace widgets
for (auto & ent : reordered) for (auto & ent : reordered)
{ {
std::size_t len = ent.end - ent.begin; 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; unsigned str_w = graph_.text_extent_size(ent.begin, len).width;
#endif
if ((text_draw_pos.x + static_cast<int>(str_w) > text_area_.area.x) && (text_draw_pos.x < text_right)) if ((text_draw_pos.x + static_cast<int>(str_w) > text_area_.area.x) && (text_draw_pos.x < text_right))
{ {
@ -3519,7 +3564,11 @@ namespace nana{ namespace widgets
for (auto & ent : reordered) for (auto & ent : reordered)
{ {
const auto len = ent.end - ent.begin; 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; auto ent_px = graph_.text_extent_size(ent.begin, len).width;
#endif
extra_space = false; extra_space = false;
@ -3548,8 +3597,12 @@ namespace nana{ namespace widgets
unsigned select_pos = static_cast<unsigned>(ent_sbegin != ent.begin ? ent_sbegin - ent.begin : 0); unsigned select_pos = static_cast<unsigned>(ent_sbegin != ent.begin ? ent_sbegin - ent.begin : 0);
unsigned select_len = static_cast<unsigned>(ent_send - ent_sbegin); unsigned select_len = static_cast<unsigned>(ent_send - ent_sbegin);
#ifdef _nana_std_has_string_view
auto pxbuf = graph_.glyph_pixels({ ent.begin, static_cast<std::size_t>(len) });
#else
std::unique_ptr<unsigned[]> pxbuf{ new unsigned[len] }; std::unique_ptr<unsigned[]> pxbuf{ new unsigned[len] };
graph_.glyph_pixels(ent.begin, len, pxbuf.get()); graph_.glyph_pixels(ent.begin, len, pxbuf.get());
#endif
auto head_px = std::accumulate(pxbuf.get(), pxbuf.get() + select_pos, unsigned{}); 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{}); auto select_px = std::accumulate(pxbuf.get() + select_pos, pxbuf.get() + select_pos + select_len, unsigned{});
@ -3589,7 +3642,11 @@ namespace nana{ namespace widgets
auto pos = text_coord.x + text_len; auto pos = text_coord.x + text_len;
if (b.x != pos || text_coord.y != b.y) 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; auto whitespace_w = graph_.text_extent_size(L" ", 1).width;
#endif
graph_.rectangle(::nana::rectangle{ text_draw_pos, { whitespace_w, line_h_pixels } }, true); graph_.rectangle(::nana::rectangle{ text_draw_pos, { whitespace_w, line_h_pixels } }, true);
} }
} }
@ -3617,9 +3674,13 @@ namespace nana{ namespace widgets
unsigned text_editor::_m_char_by_pixels(const unicode_bidi::entity& ent, unsigned pos) const unsigned text_editor::_m_char_by_pixels(const unicode_bidi::entity& ent, unsigned pos) const
{ {
auto len = static_cast<std::size_t>(ent.end - ent.begin); auto len = static_cast<std::size_t>(ent.end - ent.begin);
#ifdef _nana_std_has_string_view
auto pxbuf = graph_.glyph_pixels({ ent.begin, len });
if (pxbuf)
#else
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]); std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
if (graph_.glyph_pixels(ent.begin, len, pxbuf.get())) if (graph_.glyph_pixels(ent.begin, len, pxbuf.get()))
#endif
{ {
const auto px_end = pxbuf.get() + len; const auto px_end = pxbuf.get() + len;
@ -3677,8 +3738,12 @@ namespace nana{ namespace widgets
{ {
//Characters of some bidi languages may transform in a word. //Characters of some bidi languages may transform in a word.
//RTL //RTL
#ifdef _nana_std_has_string_view
auto pxbuf = graph_.glyph_pixels({ent.begin, len});
#else
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]); std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
graph_.glyph_pixels(ent.begin, len, pxbuf.get()); graph_.glyph_pixels(ent.begin, len, pxbuf.get());
#endif
return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w); return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w);
} }
//LTR //LTR

View File

@ -82,10 +82,39 @@ namespace nana
bool check_value(const std::string& str) const override bool check_value(const std::string& str) const override
{ {
#ifdef __cpp_if_constexpr
auto i = str.c_str();
if ('+' == *i || '-' == *i)
++i;
if constexpr(std::is_same<T, int>::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()) if (str.empty())
return true; return true;
auto size = str.size(); auto const size = str.size();
std::size_t pos = 0; std::size_t pos = 0;
if (str[0] == '+' || str[0] == '-') if (str[0] == '+' || str[0] == '-')
pos = 1; pos = 1;
@ -115,6 +144,7 @@ namespace nana
return false; return false;
} }
} }
#endif
return true; return true;
} }
@ -744,7 +774,7 @@ namespace nana
modifier(to_utf8(prefix), to_utf8(suffix)); 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; internal_scope_guard lock;
auto editor = get_drawer_trigger().impl()->editor(); auto editor = get_drawer_trigger().impl()->editor();

View File

@ -1,6 +1,6 @@
/* /*
* A Tabbar Implementation * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -1489,7 +1489,12 @@ namespace nana
} }
graph.rectangle(r, true); 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()); graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size());
#endif
++pos; ++pos;
} }
@ -1533,7 +1538,7 @@ namespace nana
delete model_; delete model_;
} }
model* driver::get_model() const throw() model* driver::get_model() const noexcept
{ {
return model_; return model_;
} }

View File

@ -785,7 +785,7 @@ namespace drawerbase {
} }
//Override _m_caption for caption() //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; internal_scope_guard lock;
auto editor = get_drawer_trigger().editor(); auto editor = get_drawer_trigger().editor();

View File

@ -1163,7 +1163,11 @@ namespace nana
virtual unsigned item_height(graph_reference graph) const override 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; 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 virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override

View File

@ -54,12 +54,12 @@ namespace nana
widget& wdg_; widget& wdg_;
}; };
std::string widget::caption() const throw() std::string widget::caption() const noexcept
{ {
return to_utf8(_m_caption()); return to_utf8(_m_caption());
} }
std::wstring widget::caption_wstring() const throw() std::wstring widget::caption_wstring() const noexcept
{ {
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
return _m_caption(); return _m_caption();
@ -68,7 +68,7 @@ namespace nana
#endif #endif
} }
auto widget::caption_native() const throw() -> native_string_type auto widget::caption_native() const noexcept -> native_string_type
{ {
return _m_caption(); return _m_caption();
} }
@ -287,7 +287,7 @@ namespace nana
void widget::_m_complete_creation() 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()); return API::dev::window_caption(handle());
} }

View File

@ -1,7 +1,7 @@
/* /*
* An Implementation of i18n * An Implementation of i18n
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (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_SAVE_AS"] = "Save As";
table["NANA_FILEBOX_OPEN"] = "Open"; 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"] = "File";
table["NANA_FILEBOX_FILE_COLON"] = "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_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_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_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_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_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?"; table["NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING"] = "The input file is existing, do you want to overwrite it?";
} }
}; };
@ -414,45 +417,47 @@ namespace nana
} }
} }
void internationalization::_m_fetch_args(std::vector<std::string>&) const #ifndef _nana_cxx_folding_expression
void internationalization::_m_fetch_args(std::vector<std::string>&)
{} {}
#endif
void internationalization::_m_fetch_args(std::vector<std::string>& v, const char* arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, const char* arg)
{ {
v.emplace_back(arg); v.emplace_back(arg);
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, const std::string& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, const std::string& arg)
{ {
v.emplace_back(arg); v.emplace_back(arg);
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, std::string& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, std::string& arg)
{ {
v.emplace_back(arg); v.emplace_back(arg);
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, std::string&& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, std::string&& arg)
{ {
v.emplace_back(std::move(arg)); v.emplace_back(std::move(arg));
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, const wchar_t* arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, const wchar_t* arg)
{ {
v.emplace_back(to_utf8(arg)); v.emplace_back(to_utf8(arg));
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, const std::wstring& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, const std::wstring& arg)
{ {
v.emplace_back(to_utf8(arg)); v.emplace_back(to_utf8(arg));
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, std::wstring& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, std::wstring& arg)
{ {
v.emplace_back(to_utf8(arg)); v.emplace_back(to_utf8(arg));
} }
void internationalization::_m_fetch_args(std::vector<std::string>& v, std::wstring&& arg) const void internationalization::_m_fetch_args(std::vector<std::string>& v, std::wstring&& arg)
{ {
v.emplace_back(to_utf8(arg)); v.emplace_back(to_utf8(arg));
} }

View File

@ -1,7 +1,7 @@
/* /*
* Platform Implementation * Platform Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -134,29 +134,84 @@ namespace detail
pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y}); 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) #if defined(NANA_WINDOWS)
::SIZE size; ::SIZE size;
if(::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size)) if (::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size))
return nana::size(size.cx, size.cy); return nana::size(size.cx, size.cy);
#elif defined(NANA_X11) #elif defined(NANA_X11)
#if defined(NANA_USE_XFT) std::string utf8text = to_utf8(std::wstring(text, len));
std::string utf8str = to_utf8(std::wstring(text, len)); #if defined(NANA_USE_XFT)
XGlyphInfo ext; XGlyphInfo ext;
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle()); XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8str.c_str())), utf8str.size(), &ext); reinterpret_cast<XftChar8*>(const_cast<char*>(utf8text.data())), utf8text.size(), &ext);
return nana::size(ext.xOff, fs->ascent + fs->descent); return nana::size(ext.xOff, fs->ascent + fs->descent);
#else #else
XRectangle ink; XRectangle ink;
XRectangle logic; XRectangle logic;
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), text, len, &ink, &logic); ::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic);
return nana::size(logic.width, logic.height); return nana::size(logic.width, logic.height);
#endif
#endif #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)
#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<int>(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<XftFont*>(dw->font->native_handle());
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
reinterpret_cast<XftChar8*>(const_cast<char*>(text)), len, &ext);
return nana::size(ext.xOff, fs->ascent + fs->descent);
#else
XRectangle ink;
XRectangle logic;
::XmbTextExtents(reinterpret_cast<XFontSet>(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<int>(extents.width) - tabs * static_cast<int>(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) nana::size text_extent_size(drawable_type dw, const wchar_t * text, std::size_t len)
@ -164,7 +219,7 @@ namespace detail
if (nullptr == dw || nullptr == text || 0 == len) if (nullptr == dw || nullptr == text || 0 == len)
return{}; 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; const wchar_t* const end = text + len;
int tabs = 0; int tabs = 0;

View File

@ -411,8 +411,8 @@ namespace paint
impl_->handle = dw.get(); impl_->handle = dw.get();
impl_->size = sz; impl_->size = sz;
impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; impl_->handle->string.tab_pixels = detail::real_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.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width;
} }
} }
@ -438,8 +438,9 @@ namespace paint
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
::SelectObject(impl_->handle->context, reinterpret_cast<HFONT>(f.impl_->real_font->native_handle())); ::SelectObject(impl_->handle->context, reinterpret_cast<HFONT>(f.impl_->real_font->native_handle()));
#endif #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) if (impl_->changed == false)
impl_->changed = true; impl_->changed = true;
@ -453,6 +454,114 @@ namespace paint
return (impl_->handle ? font(impl_->handle) : impl_->font_shadow); 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());
}
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<std::size_t>(0), static_cast<std::size_t>(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<int>(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;
}
std::unique_ptr<unsigned[]> graphics::glyph_pixels(std::wstring_view text) const
{
if (nullptr == impl_->handle || nullptr == impl_->handle->context) return {};
if (text.empty()) return std::unique_ptr<unsigned[]>{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<int>(text.size()), 0, 0, dx, &extents);
auto pxbuf = std::unique_ptr<unsigned[]>{ 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<XftFont*>(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;
}
::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 ::nana::size graphics::text_extent_size(const ::std::string& text) const
{ {
throw_not_utf8(text); throw_not_utf8(text);
@ -486,7 +595,7 @@ namespace paint
nana::size graphics::glyph_extent_size(const wchar_t * str, std::size_t len, std::size_t begin, std::size_t end) const 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{}; if (nullptr == impl_->handle || nullptr == str || 0 == len || begin >= end) return{};
nana::size sz; nana::size sz;
@ -497,13 +606,13 @@ namespace paint
sz.width = dx[end - 1] - (begin ? dx[begin - 1] : 0); sz.width = dx[end - 1] - (begin ? dx[begin - 1] : 0);
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
const wchar_t * pend = str + end; 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.width += tab_pixels;
} }
sz.height = extents.cy; sz.height = extents.cy;
delete [] dx; delete[] dx;
#elif defined(NANA_X11) #elif defined(NANA_X11)
sz = text_extent_size(str + begin, end - begin); sz = text_extent_size(str + begin, end - begin);
#endif #endif
@ -517,8 +626,8 @@ namespace paint
bool graphics::glyph_pixels(const wchar_t * str, std::size_t len, unsigned* pxbuf) const 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 (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == str || nullptr == pxbuf) return false;
if(len == 0) return true; if (len == 0) return true;
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels; unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
@ -526,22 +635,22 @@ namespace paint
SIZE extents; SIZE extents;
::GetTextExtentExPoint(impl_->handle->context, str, static_cast<int>(len), 0, 0, dx, &extents); ::GetTextExtentExPoint(impl_->handle->context, str, static_cast<int>(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]); pxbuf[i] = (str[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]);
} }
delete [] dx; delete[] dx;
#elif defined(NANA_X11) && defined(NANA_USE_XFT) #elif defined(NANA_X11) && defined(NANA_USE_XFT)
auto disp = nana::detail::platform_spec::instance().open_display(); auto disp = nana::detail::platform_spec::instance().open_display();
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle()); auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
XGlyphInfo extents; 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]); FT_UInt glyphs = ::XftCharIndex(disp, xft, str[i]);
::XftGlyphExtents(disp, xft, &glyphs, 1, &extents); ::XftGlyphExtents(disp, xft, &glyphs, 1, &extents);
@ -557,14 +666,18 @@ namespace paint
nana::size graphics::bidi_extent_size(const std::wstring& str) const nana::size graphics::bidi_extent_size(const std::wstring& str) const
{ {
nana::size sz; 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()); 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));
#else
nana::size t = text_extent_size(i.begin, i.end - i.begin); nana::size t = text_extent_size(i.begin, i.end - i.begin);
#endif
sz.width += t.width; sz.width += t.width;
if(sz.height < t.height) if (sz.height < t.height)
sz.height = t.height; sz.height = t.height;
} }
} }
@ -575,6 +688,7 @@ namespace paint
{ {
return bidi_extent_size(static_cast<std::wstring>(::nana::charset(str, ::nana::unicode::utf8))); return bidi_extent_size(static_cast<std::wstring>(::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 bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const
{ {
@ -937,7 +1051,7 @@ namespace paint
impl_->size.width = impl_->size.height = 0; 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) if(impl_->handle)
{ {
@ -1003,25 +1117,6 @@ namespace paint
return *this; 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);
moved_pos.x += static_cast<int>(text_extent_size(i.begin, i.end - i.begin).width);
}
return static_cast<unsigned>(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) void graphics::set_pixel(int x, int y, const ::nana::color& clr)
{ {
if (impl_->handle) if (impl_->handle)
@ -1046,6 +1141,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<std::wstring_view::size_type>(i.end - i.begin) });
moved_pos.x += static_cast<int>(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<int>(text_extent_size(i.begin, i.end - i.begin).width);
#endif
}
return static_cast<unsigned>(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<int>(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<int>(text_extent_size(std::wstring_view(i.begin, i.end - i.begin)).width);
#else
moved_pos.x += static_cast<int>(text_extent_size(i.begin, i.end - i.begin).width);
#endif
}
return static_cast<unsigned>(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) void graphics::string(const point& pos, const std::string& text_utf8)
{ {
string(pos, to_wstring(text_utf8)); string(pos, to_wstring(text_utf8));
@ -1076,7 +1281,7 @@ namespace paint
{ {
//Render a part that does not contains a tab //Render a part that does not contains a tab
detail::draw_string(impl_->handle, pos, str, len); 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; str = i;
@ -1114,6 +1319,7 @@ namespace paint
palette(true, clr); palette(true, clr);
string(pos, text.data(), text.size()); string(pos, text.data(), text.size());
} }
#endif //_nana_std_has_string_view
void graphics::line(const nana::point& pos1, const nana::point& pos2) void graphics::line(const nana::point& pos1, const nana::point& pos2)
{ {

View File

@ -52,6 +52,7 @@ namespace nana
{ {
std::size_t len = ent.end - ent.begin; std::size_t len = ent.end - ent.begin;
nana::size ts = detail::text_extent_size(dw, ent.begin, len); nana::size ts = detail::text_extent_size(dw, ent.begin, len);
if(ts.height > pixels) pixels = ts.height; if(ts.height > pixels) pixels = ts.height;
if(pos.x + static_cast<int>(ts.width) > 0) if(pos.x + static_cast<int>(ts.width) > 0)
@ -128,7 +129,11 @@ namespace nana
draw_string_omitted(graphics& graph, int x, int endpos, bool omitted) draw_string_omitted(graphics& graph, int x, int endpos, bool omitted)
: graph(graph), x(x), endpos(endpos) : 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); omitted_pixels = (omitted ? graph.text_extent_size("...", 3).width : 0);
#endif
if (endpos - x > static_cast<int>(omitted_pixels)) if (endpos - x > static_cast<int>(omitted_pixels))
this->endpos -= omitted_pixels; this->endpos -= omitted_pixels;
else else
@ -164,8 +169,12 @@ namespace nana
dum_graph.bitblt(r, graph, pos); 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.palette(true, graph.palette(true));
dum_graph.string({}, i.begin, len); dum_graph.string({}, i.begin, len);
#endif
r.x = pos.x; r.x = pos.x;
r.y = top; r.y = top;
@ -228,10 +237,14 @@ namespace nana
const std::size_t len = i.end - i.begin; const std::size_t len = i.end - i.begin;
if(len > 1) if(len > 1)
{ {
std::unique_ptr<unsigned[]> pixel_buf(new unsigned[len]);
//Find the char that should be splitted //Find the char that should be splitted
#ifdef _nana_std_has_string_view
auto pixel_buf = graph.glyph_pixels({ i.begin, len });
#else
std::unique_ptr<unsigned[]> pixel_buf(new unsigned[len]);
graph.glyph_pixels(i.begin, len, pixel_buf.get()); graph.glyph_pixels(i.begin, len, pixel_buf.get());
#endif
std::size_t idx_head = 0, idx_splitted; std::size_t idx_head = 0, idx_splitted;
do do
@ -448,10 +461,16 @@ namespace nana
std::size_t len = i.end - i.begin; std::size_t len = i.end - i.begin;
if(len > 1) if(len > 1)
{ {
//Find the char that should be splitted
#ifdef _nana_std_has_string_view
auto scope_res = graph.glyph_pixels({ i.begin, len });
auto pxbuf = scope_res.get();
#else
std::unique_ptr<unsigned[]> scope_res(new unsigned[len]); std::unique_ptr<unsigned[]> scope_res(new unsigned[len]);
auto pxbuf = scope_res.get(); auto pxbuf = scope_res.get();
//Find the char that should be splitted
graph.glyph_pixels(i.begin, len, pxbuf); graph.glyph_pixels(i.begin, len, pxbuf);
#endif
std::size_t idx_head = 0, idx_splitted; std::size_t idx_head = 0, idx_splitted;
do do
@ -625,14 +644,23 @@ namespace nana
break; break;
} }
#ifdef _nana_std_has_string_view
graph_.bidi_string(pos, text);
#else
graph_.bidi_string(pos, text.c_str(), text.size()); graph_.bidi_string(pos, text.c_str(), text.size());
#endif
return; return;
} }
#ifdef _nana_std_has_string_view
const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width;
auto pixels = graph_.glyph_pixels({ text.c_str(), text.size() });
#else
const auto ellipsis = graph_.text_extent_size("...", 3).width; const auto ellipsis = graph_.text_extent_size("...", 3).width;
std::unique_ptr<unsigned[]> pixels(new unsigned[text.size()]); std::unique_ptr<unsigned[]> pixels(new unsigned[text.size()]);
graph_.glyph_pixels(text.c_str(), text.size(), pixels.get()); graph_.glyph_pixels(text.c_str(), text.size(), pixels.get());
#endif
std::size_t substr_len = 0; std::size_t substr_len = 0;
unsigned substr_px = 0; unsigned substr_px = 0;
@ -653,7 +681,11 @@ namespace nana
} while (p != end); } while (p != end);
pos.x += static_cast<int>(width - ellipsis - substr_px) + ellipsis; pos.x += static_cast<int>(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); graph_.bidi_string(pos, text.c_str() + substr_len, text.size() - substr_len);
#endif
pos.x -= ellipsis; pos.x -= ellipsis;
} }
else else
@ -670,8 +702,11 @@ namespace nana
if (align::center == text_align_ex_) if (align::center == text_align_ex_)
pos.x += (width - substr_px - ellipsis) / 2; 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); graph_.bidi_string(pos, text.c_str(), substr_len);
#endif
pos.x += substr_px; pos.x += substr_px;
} }

View File

@ -426,7 +426,7 @@ namespace std
} }
#endif #endif
#ifdef _enable_std_put_time #ifdef _nana_std_put_time
#include <cwchar> #include <cwchar>
namespace std namespace std
{ {