Merge branch 'develop'
This commit is contained in:
commit
719bceb616
@ -36,9 +36,14 @@
|
||||
* - STD_TO_STRING_NOT_SUPPORTED (MinGW with GCC < 4.8)
|
||||
* - STD_FILESYSTEM_NOT_SUPPORTED (GCC < 5.3) ....
|
||||
* - CXX_NO_INLINE_NAMESPACE (Visual C++ < 2015)
|
||||
* - _enable_std_make_unique (__cpluscplus < 201402)
|
||||
* - _enable_std_put_time (GCC < 5)
|
||||
* - _enable_std_clamp (Visual C++ < 2017)
|
||||
*
|
||||
* There are two kinds of flags:
|
||||
* * _nana_std_xxx indicates that nana provides a standard-like class for workaround of lack of C++ support.
|
||||
* * _nana_std_has_xxx indicates that nana detects whether a C++ feature is supported. Nana doesn't provide a standard-like class for this missing feature.
|
||||
*
|
||||
* - _nana_std_make_unique (__cpluscplus < 201402)
|
||||
* - _nana_std_put_time (GCC < 5)
|
||||
* - _nana_std_clamp (Visual C++ < 2017)
|
||||
*/
|
||||
|
||||
#ifndef NANA_CXX_DEFINES_INCLUDED
|
||||
@ -145,7 +150,7 @@
|
||||
|
||||
|
||||
# if ((__GNUC__ < 5) )
|
||||
# define _enable_std_put_time
|
||||
# define _nana_std_put_time
|
||||
# endif
|
||||
|
||||
# if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
|
||||
@ -189,20 +194,38 @@
|
||||
|
||||
//Detects the feature std::make_unique
|
||||
//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 )))) \
|
||||
|| ((!defined(__clang__)) && defined(__GNUC__) && __cplusplus < 201300L)
|
||||
# define _enable_std_make_unique
|
||||
# define _nana_std_make_unique
|
||||
#endif
|
||||
|
||||
|
||||
//Detects the feature 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)) \
|
||||
|| (defined(__clang__) && (__cplusplus < 201406L)) \
|
||||
|| (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
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The Deploy Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -23,6 +23,10 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
{
|
||||
/// move to *.h ??
|
||||
@ -44,10 +48,15 @@ namespace nana
|
||||
|
||||
|
||||
/// Checks whether a specified text is utf8 encoding
|
||||
#ifdef _nana_std_has_string_view
|
||||
bool is_utf8(std::string_view str);
|
||||
void throw_not_utf8(std::string_view str);
|
||||
#else
|
||||
bool is_utf8(const char* str, std::size_t len);
|
||||
void throw_not_utf8(const std::string& text);
|
||||
void throw_not_utf8(const char*, std::size_t len);
|
||||
void throw_not_utf8(const char*);
|
||||
#endif
|
||||
|
||||
/// this text needed change, it needed review ??
|
||||
bool review_utf8(const std::string& text);
|
||||
@ -58,7 +67,12 @@ namespace nana
|
||||
const std::string& to_utf8(const std::string&);
|
||||
std::string to_utf8(const std::wstring&);
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
std::wstring to_wstring(std::string_view utf8_str);
|
||||
#else
|
||||
std::wstring to_wstring(const std::string& utf8_str);
|
||||
#endif
|
||||
|
||||
const std::wstring& to_wstring(const std::wstring& wstr);
|
||||
std::wstring&& to_wstring(std::wstring&& wstr);
|
||||
|
||||
|
||||
@ -35,14 +35,14 @@ namespace filesystem_ext
|
||||
|
||||
std::experimental::filesystem::path path_user(); ///< extention ?
|
||||
|
||||
/// workaround Boost not having path.generic_u8string() - a good point for http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0251r0.pdf
|
||||
/// workaround Boost not having path.generic_u8string() - a good point for http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0251r0.pdf
|
||||
inline std::string generic_u8string(const std::experimental::filesystem::path& p)
|
||||
{
|
||||
#if NANA_USING_BOOST_FILESYSTEM
|
||||
#if NANA_USING_BOOST_FILESYSTEM
|
||||
return nana::to_utf8(p.generic_wstring());
|
||||
#else
|
||||
#else
|
||||
return p.generic_u8string();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept
|
||||
|
||||
@ -134,10 +134,24 @@ namespace nana
|
||||
template<typename Function>
|
||||
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;
|
||||
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.
|
||||
event_handle connect(void (*fn)(arg_reference))
|
||||
{
|
||||
@ -145,13 +159,27 @@ namespace nana
|
||||
fn(arg);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
/// It will not get called if stop_propagation() was called, because it is set at the end of the chain..
|
||||
template<typename Function>
|
||||
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;
|
||||
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.
|
||||
@ -165,9 +193,21 @@ namespace nana
|
||||
template<typename Function>
|
||||
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;
|
||||
|
||||
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)
|
||||
@ -210,6 +250,8 @@ namespace nana
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
#ifndef __cpp_if_constexpr
|
||||
template<typename Fn, bool IsBind>
|
||||
struct factory
|
||||
{
|
||||
@ -385,6 +427,7 @@ namespace nana
|
||||
};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
struct arg_mouse
|
||||
|
||||
@ -35,7 +35,7 @@ namespace nana
|
||||
* @param limit_width True if limits the width, false if limits the height.
|
||||
* @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
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Filebox
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -15,6 +15,7 @@
|
||||
#ifndef NANA_GUI_FILEBOX_HPP
|
||||
#define NANA_GUI_FILEBOX_HPP
|
||||
#include <nana/gui/basis.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
@ -80,5 +81,29 @@ namespace nana
|
||||
private:
|
||||
implement * impl_;
|
||||
};
|
||||
|
||||
class folderbox
|
||||
{
|
||||
struct implement;
|
||||
|
||||
folderbox(const folderbox&) = delete;
|
||||
folderbox& operator=(const folderbox&) = delete;
|
||||
folderbox(folderbox&&) = delete;
|
||||
folderbox& operator=(folderbox&&) = delete;
|
||||
public:
|
||||
using path_type = std::experimental::filesystem::path;
|
||||
|
||||
folderbox(window owner = nullptr, const path_type& init_path = {});
|
||||
~folderbox();
|
||||
|
||||
std::optional<path_type> show() const;
|
||||
|
||||
std::optional<path_type> operator()() const
|
||||
{
|
||||
return show();
|
||||
}
|
||||
private:
|
||||
implement* impl_;
|
||||
};
|
||||
}//end namespace nana
|
||||
#endif
|
||||
|
||||
@ -240,7 +240,11 @@ namespace nana
|
||||
bool show(Args&& ... args)
|
||||
{
|
||||
std::vector<abstract_content*> contents;
|
||||
#ifdef __cpp_fold_expressions
|
||||
(contents.emplace_back(&args), ...);
|
||||
#else
|
||||
_m_fetch_args(contents, std::forward<Args>(args)...);
|
||||
#endif
|
||||
if (contents.empty())
|
||||
return false;
|
||||
|
||||
@ -270,6 +274,7 @@ namespace nana
|
||||
void min_width_entry_field( unsigned pixels );
|
||||
|
||||
private:
|
||||
#ifndef __cpp_fold_expressions
|
||||
void _m_fetch_args(std::vector<abstract_content*>&);
|
||||
|
||||
template<typename ...Args>
|
||||
@ -278,6 +283,7 @@ namespace nana
|
||||
contents.push_back(&content);
|
||||
_m_fetch_args(contents, std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool _m_open(std::vector<abstract_content*>&, bool modal);
|
||||
private:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An Implementation of Place for Layout
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -119,7 +119,7 @@ namespace nana
|
||||
|
||||
void splitter_renderer(std::function<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.
|
||||
void modify(const char* field_name, const char* div_text); ///< Modifies a specified field.
|
||||
|
||||
|
||||
@ -45,6 +45,15 @@ namespace nana
|
||||
|
||||
namespace API
|
||||
{
|
||||
#ifdef NANA_X11
|
||||
//Some platform specific functions for X11
|
||||
namespace x11
|
||||
{
|
||||
/// Returns the connection to the X server
|
||||
const void* get_display();
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
::nana::widget_geometrics* make_scheme(::nana::detail::scheme_factory_interface&&);
|
||||
@ -80,7 +89,7 @@ namespace API
|
||||
void set_measurer(window, ::nana::dev::widget_content_measurer_interface*);
|
||||
|
||||
void attach_drawer(widget&, drawer_trigger&);
|
||||
::nana::detail::native_string_type window_caption(window) throw();
|
||||
::nana::detail::native_string_type window_caption(window) noexcept;
|
||||
void window_caption(window, ::nana::detail::native_string_type);
|
||||
|
||||
window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached);
|
||||
@ -110,6 +119,7 @@ namespace API
|
||||
void draw_shortkey_underline(paint::graphics&, const std::string& text, wchar_t shortkey, std::size_t shortkey_position, const point& text_pos, const color&);
|
||||
}//end namespace dev
|
||||
|
||||
|
||||
/// Returns the widget pointer of the specified window.
|
||||
/*
|
||||
* @param window_handle A handle to a window owning the widget.
|
||||
@ -245,6 +255,19 @@ namespace API
|
||||
if (nullptr == general_evt)
|
||||
throw std::invalid_argument("API::events(): bad parameter window handle, no events object or invalid window handle.");
|
||||
|
||||
#ifdef __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)
|
||||
return *static_cast<event_type*>(general_evt);
|
||||
|
||||
@ -252,6 +275,7 @@ namespace API
|
||||
if (nullptr == widget_evt)
|
||||
throw std::invalid_argument("API::events(): bad template parameter Widget, the widget type and window handle do not match.");
|
||||
return *widget_evt;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<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)
|
||||
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)
|
||||
return *static_cast<scheme_type*>(wdg_colors);
|
||||
|
||||
@ -285,6 +322,7 @@ namespace API
|
||||
if (nullptr == comp_wdg_colors)
|
||||
throw std::invalid_argument("API::scheme(): bad template parameter Widget, the widget type and window handle do not match.");
|
||||
return *comp_wdg_colors;
|
||||
#endif
|
||||
}
|
||||
|
||||
point window_position(window);
|
||||
@ -302,7 +340,7 @@ namespace API
|
||||
size window_outline_size(window);
|
||||
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 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);
|
||||
@ -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); ///< 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
|
||||
/**
|
||||
@ -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
|
||||
* 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);
|
||||
}//end namespace API
|
||||
|
||||
@ -79,7 +79,9 @@ namespace drawerbase
|
||||
void element_set(const char* name);
|
||||
void react(bool want); ///< Enables the reverse check while clicking on the checkbox.
|
||||
bool checked() const;
|
||||
void check(bool chk);
|
||||
|
||||
/// Checks/unchecks the checkbox
|
||||
void check(bool state);
|
||||
|
||||
/// \brief With the radio mode, users make a choice among a set of mutually exclusive,
|
||||
/// related options. Users can choose one and only one option.
|
||||
|
||||
@ -223,7 +223,7 @@ namespace nana
|
||||
const drawerbase::combox::drawer_impl& _m_impl() const;
|
||||
private:
|
||||
//Overrides widget's virtual functions
|
||||
native_string_type _m_caption() const throw() override;
|
||||
native_string_type _m_caption() const noexcept override;
|
||||
void _m_caption(native_string_type&&) override;
|
||||
nana::any * _m_anyobj(std::size_t pos, bool alloc_if_empty) const override;
|
||||
};
|
||||
|
||||
36
include/nana/gui/widgets/detail/widget_iterator.hpp
Normal file
36
include/nana/gui/widgets/detail/widget_iterator.hpp
Normal 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
|
||||
@ -22,8 +22,20 @@
|
||||
#include <nana/gui/widgets/checkbox.hpp>
|
||||
|
||||
namespace nana{
|
||||
|
||||
namespace drawerbase
|
||||
{
|
||||
namespace group
|
||||
{
|
||||
struct scheme : public nana::widget_geometrics
|
||||
{
|
||||
color_proxy border{ colors::gray_border };
|
||||
};
|
||||
}// end namespace panel
|
||||
}//end namespace drawerbase
|
||||
|
||||
class group
|
||||
: public panel<true>
|
||||
: public widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>
|
||||
{
|
||||
struct implement;
|
||||
public:
|
||||
@ -53,6 +65,9 @@ namespace nana{
|
||||
/// Adds an option for user selection
|
||||
checkbox& add_option(::std::string);
|
||||
|
||||
/// Modifies the alignment of the title
|
||||
void caption_align(align position);
|
||||
|
||||
/// Enables/disables the radio mode which is single selection
|
||||
group& radio_mode(bool);
|
||||
|
||||
@ -83,7 +98,7 @@ namespace nana{
|
||||
void _m_add_child(const char* field, widget*);
|
||||
void _m_init();
|
||||
void _m_complete_creation() override;
|
||||
native_string_type _m_caption() const throw() override;
|
||||
native_string_type _m_caption() const noexcept override;
|
||||
void _m_caption(native_string_type&&) override;
|
||||
private:
|
||||
std::unique_ptr<implement> impl_;
|
||||
|
||||
@ -62,12 +62,12 @@ namespace nana
|
||||
label(window parent, const char* text, bool visible = true) :label(parent, std::string(text),visible) {};
|
||||
label(window, const rectangle& = {}, bool visible = true);
|
||||
label& transparent(bool); ///< Switchs the label widget to the transparent background mode.
|
||||
bool transparent() const throw();
|
||||
bool transparent() const noexcept;
|
||||
label& format(bool); ///< Switches the format mode of the widget.
|
||||
label& add_format_listener(std::function<void(command, const std::string&)>);
|
||||
|
||||
/// as same as the HTML "for" attribute of a label
|
||||
label& click_for(window associated_window) throw();
|
||||
label& click_for(window associated_window) noexcept;
|
||||
|
||||
/// Returns the size of the text. If *allowed_width_in_pixel* is not zero, returns a
|
||||
/// "corrected" size that changes lines to fit the text into the specified width
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
#include "widget.hpp"
|
||||
#include "detail/inline_widget.hpp"
|
||||
#include "detail/widget_iterator.hpp"
|
||||
#include <nana/pat/abstract_factory.hpp>
|
||||
#include <nana/concepts.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
|
||||
/// item_proxy self, it references and iterators are not invalidated by sort()
|
||||
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:
|
||||
item_proxy(essence*, const index_pair& = index_pair{npos, npos});
|
||||
@ -982,7 +984,8 @@ namespace nana
|
||||
};
|
||||
|
||||
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:
|
||||
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 text_margin{ 5 }; ///< def= 5. Additional or extended with added (before) to the text width to determine the cell width. cell_w = text_w + ext_w +1
|
||||
|
||||
//deprecated
|
||||
//unsigned header_height { 25 }; ///< def=25 . header height header_size
|
||||
|
||||
unsigned item_height_ex{ 6 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
|
||||
unsigned header_splitter_area_before{ 2 }; ///< def=2. But 4 is better... IMO
|
||||
unsigned header_splitter_area_after{ 3 }; ///< def=3. But 4 is better...
|
||||
|
||||
@ -116,7 +116,7 @@ namespace nana
|
||||
void modifier(std::string prefix_utf8, std::string suffix_utf8);
|
||||
void modifier(const std::wstring & prefix, const std::wstring& suffix);
|
||||
private:
|
||||
native_string_type _m_caption() const throw();
|
||||
native_string_type _m_caption() const noexcept;
|
||||
void _m_caption(native_string_type&&);
|
||||
}; //end class spinbox
|
||||
}//end namespace nana
|
||||
|
||||
@ -383,7 +383,7 @@ namespace nana
|
||||
driver();
|
||||
~driver();
|
||||
|
||||
model* get_model() const throw();
|
||||
model* get_model() const noexcept;
|
||||
private:
|
||||
//Overrides drawer_trigger's method
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
|
||||
@ -276,7 +276,7 @@ namespace nana
|
||||
std::size_t text_line_count() const noexcept;
|
||||
protected:
|
||||
//Overrides widget's virtual functions
|
||||
native_string_type _m_caption() const throw() override;
|
||||
native_string_type _m_caption() const noexcept override;
|
||||
void _m_caption(native_string_type&&) override;
|
||||
void _m_typeface(const paint::font&) override;
|
||||
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
||||
|
||||
@ -54,9 +54,9 @@ namespace nana
|
||||
|
||||
window parent() const;
|
||||
|
||||
::std::string caption() const throw();
|
||||
::std::wstring caption_wstring() const throw();
|
||||
native_string_type caption_native() const throw();
|
||||
::std::string caption() const noexcept;
|
||||
::std::wstring caption_wstring() const noexcept;
|
||||
native_string_type caption_native() const noexcept;
|
||||
|
||||
widget& caption(std::string utf8);
|
||||
widget& caption(std::wstring);
|
||||
@ -132,7 +132,7 @@ namespace nana
|
||||
virtual void _m_complete_creation();
|
||||
|
||||
virtual general_events& _m_get_general_events() const = 0;
|
||||
virtual native_string_type _m_caption() const throw();
|
||||
virtual native_string_type _m_caption() const noexcept;
|
||||
virtual void _m_caption(native_string_type&&);
|
||||
virtual nana::cursor _m_cursor() const;
|
||||
virtual void _m_cursor(nana::cursor);
|
||||
|
||||
@ -34,7 +34,12 @@ namespace nana
|
||||
::std::string get(std::string msgid_utf8, Args&&... args) const
|
||||
{
|
||||
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)...);
|
||||
#endif
|
||||
|
||||
auto msgstr = _m_get(std::move(msgid_utf8));
|
||||
_m_replace_args(msgstr, &arg_strs);
|
||||
@ -53,25 +58,28 @@ namespace nana
|
||||
std::string _m_get(std::string&& msgid) const;
|
||||
void _m_replace_args(::std::string& str, std::vector<::std::string> * arg_strs) const;
|
||||
|
||||
void _m_fetch_args(std::vector<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;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const std::string& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::string& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::string&& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg) const;
|
||||
void _m_fetch_args(std::vector<std::string>& v, std::wstring&& arg) const;
|
||||
static void _m_fetch_args(std::vector<std::string>& v, const char* arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, const std::string& arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, std::string& arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, std::string&& arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, const wchar_t* arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, const std::wstring& arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, std::wstring& arg);
|
||||
static void _m_fetch_args(std::vector<std::string>& v, std::wstring&& 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;
|
||||
ss << arg;
|
||||
v.emplace_back(ss.str());
|
||||
}
|
||||
|
||||
#ifndef __cpp_fold_expressions
|
||||
template<typename ...Args>
|
||||
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());
|
||||
_m_fetch_args(v, std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
};//end class internationalization
|
||||
|
||||
class i18n_eval
|
||||
@ -180,7 +189,11 @@ namespace nana
|
||||
i18n_eval(std::string msgid_utf8, Args&&... args)
|
||||
: msgid_(std::move(msgid_utf8))
|
||||
{
|
||||
#ifdef __cpp_fold_expressions
|
||||
(_m_fetch_args(std::forward<Args>(args)), ...);
|
||||
#else
|
||||
_m_fetch_args(std::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
i18n_eval(const i18n_eval&);
|
||||
@ -193,6 +206,7 @@ namespace nana
|
||||
|
||||
std::string operator()() const;
|
||||
private:
|
||||
#ifndef __cpp_fold_expressions
|
||||
void _m_fetch_args(){} //Termination of _m_fetch_args
|
||||
|
||||
template<typename Arg, typename ...Args>
|
||||
@ -201,6 +215,7 @@ namespace nana
|
||||
_m_add_args(std::forward<Arg>(arg));
|
||||
_m_fetch_args(std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Arg>
|
||||
void _m_add_args(Arg&& arg)
|
||||
|
||||
@ -15,8 +15,13 @@
|
||||
#ifndef NANA_STD_OPTIONAL_HEADER_INCLUDED
|
||||
#define NANA_STD_OPTIONAL_HEADER_INCLUDED
|
||||
|
||||
#include <stdexcept>
|
||||
#include <nana/c++defines.hpp>
|
||||
|
||||
#ifndef _nana_std_optional
|
||||
#include <optional>
|
||||
#else
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
@ -361,4 +366,10 @@ namespace nana
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
using nana::optional;
|
||||
}
|
||||
|
||||
#endif //_nana_std_optional
|
||||
#endif
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Platform Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -32,8 +32,11 @@ namespace detail
|
||||
//dw color = dw color * fade_rate + bdcolor * (1 - fade_rate)
|
||||
void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t bdcolor, double fade_rate);
|
||||
|
||||
nana::size raw_text_extent_size(drawable_type, const wchar_t*, std::size_t len);
|
||||
nana::size real_text_extent_size(drawable_type, const char*, std::size_t len);
|
||||
nana::size real_text_extent_size(drawable_type, const wchar_t*, std::size_t len);
|
||||
nana::size text_extent_size(drawable_type, const char*, std::size_t len);
|
||||
nana::size text_extent_size(drawable_type, const wchar_t*, std::size_t len);
|
||||
|
||||
void draw_string(drawable_type, const nana::point&, const wchar_t *, std::size_t len);
|
||||
}//end namespace detail
|
||||
}//end namespace paint
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Paint Graphics Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -21,6 +21,10 @@
|
||||
|
||||
#include "detail/ptdefs.hpp"
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace paint
|
||||
@ -108,17 +112,40 @@ namespace nana
|
||||
void resize(const ::nana::size&);
|
||||
void typeface(const font&); ///< Selects a specified font type into the graphics object.
|
||||
font typeface() const;
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
::nana::size text_extent_size(std::string_view text) const;
|
||||
::nana::size text_extent_size(std::wstring_view text) const;
|
||||
|
||||
///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 char*, std::size_t len) const;
|
||||
|
||||
::nana::size text_extent_size(const wchar_t*) const; ///< Computes the width and height of the specified string of text.
|
||||
::nana::size text_extent_size(const ::std::wstring&) const; ///< Computes the width and height of the specified string of text.
|
||||
::nana::size text_extent_size(const wchar_t*, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length.
|
||||
::nana::size text_extent_size(const ::std::wstring&, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length.
|
||||
|
||||
::nana::size glyph_extent_size(const wchar_t*, std::size_t length, std::size_t begin, std::size_t end) const;
|
||||
::nana::size glyph_extent_size(const ::std::wstring&, std::size_t length, std::size_t begin, std::size_t end) const;
|
||||
|
||||
bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const;
|
||||
|
||||
::nana::size bidi_extent_size(const std::wstring&) const;
|
||||
::nana::size bidi_extent_size(const std::string&) const;
|
||||
#endif
|
||||
|
||||
bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const;
|
||||
|
||||
@ -156,17 +183,27 @@ namespace nana
|
||||
|
||||
/// Saves images as a windows bitmap file
|
||||
/// @param file_utf8 A UTF-8 string to a filename
|
||||
void save_as_file(const char* file_utf8) const throw();
|
||||
void save_as_file(const char* file_utf8) const noexcept;
|
||||
|
||||
::nana::color palette(bool for_text) const;
|
||||
graphics& palette(bool for_text, const ::nana::color&);
|
||||
|
||||
unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len);
|
||||
unsigned bidi_string(const point& pos, const char*, std::size_t len);
|
||||
|
||||
void set_pixel(int x, int y, const ::nana::color&);
|
||||
void set_pixel(int x, int y);
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
unsigned bidi_string(const point&, std::string_view utf8str);
|
||||
unsigned bidi_string(const point& pos, std::wstring_view str);
|
||||
|
||||
void string(const point&, std::string_view utf8str);
|
||||
void string(const point&, std::string_view utf8str, const nana::color&);
|
||||
|
||||
void string(const point&, std::wstring_view str);
|
||||
void string(const point&, std::wstring_view str, const nana::color&);
|
||||
#else
|
||||
unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len);
|
||||
unsigned bidi_string(const point& pos, const char*, std::size_t len);
|
||||
|
||||
void string(const point&, const std::string& text_utf8);
|
||||
void string(const point&, const std::string& text_utf8, const color&);
|
||||
|
||||
@ -174,6 +211,7 @@ namespace nana
|
||||
void string(const point&, const wchar_t*);
|
||||
void string(const point&, const ::std::wstring&);
|
||||
void string(const point&, const ::std::wstring&, const color&);
|
||||
#endif
|
||||
|
||||
void line(const point&, const point&);
|
||||
void line(const point&, const point&, const color&);
|
||||
|
||||
@ -86,7 +86,7 @@ namespace std
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _enable_std_make_unique
|
||||
#ifdef _nana_std_make_unique
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm
|
||||
|
||||
#include <cstddef>
|
||||
@ -124,9 +124,9 @@ namespace std {
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
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 <string>
|
||||
namespace std
|
||||
@ -144,9 +144,9 @@ namespace std
|
||||
//template<>
|
||||
//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
|
||||
{
|
||||
//<algorithm> since C++17
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
#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(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_FILESYSTEM_NOT_SUPPORTED) )
|
||||
|
||||
@ -65,7 +65,7 @@ namespace nana{namespace audio
|
||||
|
||||
bool audio_device::empty() const
|
||||
{
|
||||
#if defined(NANA_POSIX) && not defined(NANA_LINUX)
|
||||
#if defined(NANA_POSIX) && !defined(NANA_LINUX)
|
||||
return (-1 == handle_);
|
||||
#else
|
||||
return (nullptr == handle_);
|
||||
@ -305,7 +305,7 @@ namespace nana{namespace audio
|
||||
}//end namespace audio
|
||||
}//end namespace nana
|
||||
|
||||
#if defined(NANA_POSIX) && not defined(NANA_LINUX)
|
||||
#if defined(NANA_POSIX) && !defined(NANA_LINUX)
|
||||
// parse input securely, no-overruns or overflows.
|
||||
static bool match(char *&cursor, const char *pattern, const char *tail)
|
||||
{
|
||||
|
||||
@ -28,6 +28,42 @@
|
||||
|
||||
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)
|
||||
{
|
||||
auto ustr = reinterpret_cast<const unsigned char*>(str);
|
||||
@ -57,6 +93,23 @@ namespace nana
|
||||
return true;
|
||||
}
|
||||
|
||||
void throw_not_utf8(const std::string& text)
|
||||
{
|
||||
throw_not_utf8(text.c_str(), text.size());
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text)
|
||||
{
|
||||
throw_not_utf8(text, std::strlen(text));
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text, std::size_t len)
|
||||
{
|
||||
if (!is_utf8(text, len))
|
||||
return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len)).emit();
|
||||
}
|
||||
#endif
|
||||
|
||||
//class utf8_Error
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
@ -79,22 +132,6 @@ namespace nana
|
||||
bool utf8_Error::use_throw{ false };
|
||||
//end class utf8_Error
|
||||
|
||||
void throw_not_utf8(const std::string& text)
|
||||
{
|
||||
throw_not_utf8(text.c_str(), text.size());
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text)
|
||||
{
|
||||
throw_not_utf8(text, std::strlen(text));
|
||||
}
|
||||
|
||||
void throw_not_utf8(const char* text, std::size_t len)
|
||||
{
|
||||
if (!is_utf8(text, len))
|
||||
return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len) ).emit();
|
||||
}
|
||||
|
||||
std::string recode_to_utf8(std::string no_utf8)
|
||||
{
|
||||
return nana::charset(std::move(no_utf8)).to_bytes(nana::unicode::utf8);
|
||||
@ -103,7 +140,11 @@ namespace nana
|
||||
/// this text needed change, it needed review ??
|
||||
bool review_utf8(const std::string& text)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
if (!is_utf8(text))
|
||||
#else
|
||||
if (!is_utf8(text.c_str(), text.length()))
|
||||
#endif
|
||||
{
|
||||
utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit();
|
||||
return true; /// it needed change, it needed review !!
|
||||
@ -115,7 +156,11 @@ namespace nana
|
||||
/// this text needed change, it needed review ??
|
||||
bool review_utf8(std::string& text)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
if(!is_utf8(text))
|
||||
#else
|
||||
if (!is_utf8(text.c_str(), text.length()))
|
||||
#endif
|
||||
{
|
||||
utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit();
|
||||
text=recode_to_utf8(text);
|
||||
@ -135,10 +180,21 @@ namespace nana
|
||||
return ::nana::charset(text).to_bytes(::nana::unicode::utf8);
|
||||
}
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
std::wstring to_wstring(std::string_view utf8_str)
|
||||
{
|
||||
if (utf8_str.empty())
|
||||
return{};
|
||||
|
||||
return ::nana::charset(std::string{ utf8_str.data(), utf8_str.size() }, unicode::utf8);
|
||||
}
|
||||
#else
|
||||
std::wstring to_wstring(const std::string& utf8_str)
|
||||
{
|
||||
return ::nana::charset(utf8_str, ::nana::unicode::utf8);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const std::wstring& to_wstring(const std::wstring& wstr)
|
||||
{
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include <nana/config.hpp>
|
||||
#ifdef _enable_std_put_time
|
||||
#ifdef _nana_std_put_time
|
||||
#include <nana/stdc++.hpp>
|
||||
#else
|
||||
#include <iomanip>
|
||||
|
||||
@ -911,12 +911,19 @@ namespace detail
|
||||
case Expose:
|
||||
if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
|
||||
{
|
||||
nana::detail::platform_scope_guard psg;
|
||||
nana::detail::platform_scope_guard lock;
|
||||
if(msgwnd->is_draw_through())
|
||||
{
|
||||
msgwnd->other.attribute.root->draw_through();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed.
|
||||
::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height);
|
||||
if (!update_area.empty())
|
||||
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
nana::detail::platform_spec::instance().write_keystate(xevent.xkey);
|
||||
@ -1142,13 +1149,12 @@ namespace detail
|
||||
{
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
|
||||
arg_click click_arg;
|
||||
click_arg.mouse_args = nullptr;
|
||||
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
|
||||
{
|
||||
arg_mouse arg;
|
||||
arg.alt = false;
|
||||
arg.button = ::nana::mouse::left_button;
|
||||
@ -1161,8 +1167,10 @@ namespace detail
|
||||
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
|
||||
|
||||
@ -408,16 +408,7 @@ namespace detail
|
||||
if (msg.message == WM_QUIT) break;
|
||||
if ((WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST) || !::IsDialogMessage(native_handle, &msg))
|
||||
{
|
||||
#if 0
|
||||
auto menu_wd = get_menu(reinterpret_cast<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);
|
||||
#endif
|
||||
|
||||
wd_manager().remove_trash_handle(tid);
|
||||
}
|
||||
}
|
||||
@ -429,15 +420,7 @@ namespace detail
|
||||
{
|
||||
if (-1 != ::GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
#if 0
|
||||
auto menu_wd = get_menu(reinterpret_cast<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);
|
||||
#endif
|
||||
}
|
||||
|
||||
wd_manager().call_safe_place(tid);
|
||||
@ -452,17 +435,7 @@ namespace detail
|
||||
while(context->window_count)
|
||||
{
|
||||
if(-1 != ::GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
#if 0
|
||||
auto menu_wd = get_menu(reinterpret_cast<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);
|
||||
#endif
|
||||
}
|
||||
|
||||
wd_manager().call_safe_place(tid);
|
||||
wd_manager().remove_trash_handle(tid);
|
||||
@ -1522,13 +1495,12 @@ namespace detail
|
||||
{
|
||||
msgwnd->set_action(mouse_action::normal);
|
||||
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
|
||||
arg_click click_arg;
|
||||
click_arg.mouse_args = nullptr;
|
||||
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
|
||||
auto retain = msgwnd->annex.events_ptr;
|
||||
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
|
||||
{
|
||||
arg_mouse arg;
|
||||
arg.alt = false;
|
||||
arg.button = ::nana::mouse::left_button;
|
||||
@ -1541,19 +1513,22 @@ namespace detail
|
||||
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
|
||||
{
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_release;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.key = translate_virtual_key(wParam);
|
||||
brock.get_key_state(arg);
|
||||
arg.ignore = false;
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
arg_keyboard keyboard_arg;
|
||||
keyboard_arg.evt_code = event_code::key_release;
|
||||
keyboard_arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
keyboard_arg.key = translate_virtual_key(wParam);
|
||||
brock.get_key_state(keyboard_arg);
|
||||
keyboard_arg.ignore = false;
|
||||
|
||||
brock.emit(event_code::key_release, msgwnd, keyboard_arg, true, &context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Filebox
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -15,18 +15,19 @@
|
||||
#include <nana/filesystem/filesystem_ext.hpp>
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
# include <Shobjidl.h>
|
||||
#elif defined(NANA_POSIX)
|
||||
#include <nana/gui/widgets/label.hpp>
|
||||
#include <nana/gui/widgets/button.hpp>
|
||||
#include <nana/gui/widgets/listbox.hpp>
|
||||
#include <nana/gui/widgets/categorize.hpp>
|
||||
#include <nana/gui/widgets/textbox.hpp>
|
||||
#include <nana/gui/widgets/treebox.hpp>
|
||||
#include <nana/gui/widgets/combox.hpp>
|
||||
#include <nana/gui/place.hpp>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
# include <nana/gui/widgets/label.hpp>
|
||||
# include <nana/gui/widgets/button.hpp>
|
||||
# include <nana/gui/widgets/listbox.hpp>
|
||||
# include <nana/gui/widgets/categorize.hpp>
|
||||
# include <nana/gui/widgets/textbox.hpp>
|
||||
# include <nana/gui/widgets/treebox.hpp>
|
||||
# include <nana/gui/widgets/combox.hpp>
|
||||
# include <nana/gui/place.hpp>
|
||||
# include <stdexcept>
|
||||
# include <algorithm>
|
||||
#endif
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
@ -130,6 +131,13 @@ namespace nana
|
||||
}
|
||||
};
|
||||
public:
|
||||
enum class mode
|
||||
{
|
||||
open_file, //choose an existing file.
|
||||
write_file, //choose a filename, it can be specified a new filename which doesn't exist.
|
||||
open_directory, //choose an existing directory.
|
||||
};
|
||||
|
||||
struct kind
|
||||
{
|
||||
enum t{none, filesystem};
|
||||
@ -138,8 +146,10 @@ namespace nana
|
||||
typedef treebox::item_proxy item_proxy;
|
||||
public:
|
||||
|
||||
filebox_implement(window owner, bool io_read, const std::string& title)
|
||||
: form(owner, API::make_center(owner, 630, 440)), io_read_(io_read)
|
||||
filebox_implement(window owner, mode dialog_mode, const std::string& title, bool pick_directory = false):
|
||||
form(owner, API::make_center(owner, 630, 440)),
|
||||
pick_directory_(pick_directory),
|
||||
mode_(dialog_mode)
|
||||
{
|
||||
internationalization i18n;
|
||||
path_.create(*this);
|
||||
@ -159,6 +169,7 @@ namespace nana
|
||||
_m_load_cat_path(path);
|
||||
});
|
||||
|
||||
|
||||
filter_.create(*this);
|
||||
filter_.multi_lines(false);
|
||||
filter_.tip_string(i18n("NANA_FILEBOX_FILTER"));
|
||||
@ -203,7 +214,7 @@ namespace nana
|
||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70);
|
||||
|
||||
auto fn_sel_file = [this](const arg_mouse& arg){
|
||||
_m_sel_file(arg);
|
||||
_m_select_file(arg);
|
||||
};
|
||||
ls_file_.events().dbl_click.connect_unignorable(fn_sel_file);
|
||||
ls_file_.events().mouse_down.connect_unignorable(fn_sel_file);
|
||||
@ -278,7 +289,11 @@ namespace nana
|
||||
});
|
||||
|
||||
lb_file_.create(*this);
|
||||
lb_file_.i18n(i18n_eval("NANA_FILEBOX_FILE_COLON"));
|
||||
|
||||
const char* idstr = (mode::open_directory == dialog_mode? "NANA_FILEBOX_DIRECTORY_COLON" : "NANA_FILEBOX_FILE_COLON");
|
||||
lb_file_.i18n(i18n_eval(idstr));
|
||||
lb_file_.text_align(align::right, align_v::center);
|
||||
|
||||
|
||||
tb_file_.create(*this);
|
||||
tb_file_.multi_lines(false);
|
||||
@ -289,9 +304,13 @@ namespace nana
|
||||
_m_ok();
|
||||
});
|
||||
|
||||
//Don't create the combox for choose a file extension if the dialog is used for picking a directory.
|
||||
if(!pick_directory)
|
||||
{
|
||||
cb_types_.create(*this);
|
||||
cb_types_.editable(false);
|
||||
cb_types_.events().selected.connect_unignorable([this](const arg_combox&){ _m_list_fs(); });
|
||||
}
|
||||
|
||||
btn_ok_.create(*this);
|
||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY"));
|
||||
@ -313,8 +332,23 @@ namespace nana
|
||||
_m_layout();
|
||||
_m_init_tree();
|
||||
|
||||
if(0 == title.size())
|
||||
this->i18n(i18n_eval(io_read ? "NANA_FILEBOX_OPEN" : "NANA_FILEBOX_SAVE_AS"));
|
||||
if(title.empty())
|
||||
{
|
||||
const char* idstr{ nullptr };
|
||||
switch(dialog_mode)
|
||||
{
|
||||
case mode::open_file:
|
||||
idstr = "NANA_FILEBOX_OPEN";
|
||||
break;
|
||||
case mode::write_file:
|
||||
idstr = "NANA_FILEBOX_SAVE_AS";
|
||||
break;
|
||||
case mode::open_directory:
|
||||
idstr = "NANA_FILEBOX_OPEN_DIRECTORY";
|
||||
break;
|
||||
}
|
||||
this->i18n(i18n_eval(idstr));
|
||||
}
|
||||
else
|
||||
caption(title);
|
||||
}
|
||||
@ -412,16 +446,21 @@ namespace nana
|
||||
"<weight=34 margin=5 path arrange=[variable,200] gap=5>"
|
||||
"<weight=30 margin=[0,0,5,10] new_folder arrange=[100]>"
|
||||
"<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]>>"
|
||||
"<weight=48 margin=[8,0,14]<>"
|
||||
"<buttons weight=208 margin=[0,18,0] gap=[14]>>");
|
||||
|
||||
place_.field("path")<<path_<<filter_;
|
||||
|
||||
place_.field("new_folder")<<btn_folder_;
|
||||
place_.field("content")<<tree_<<ls_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_.collocate();
|
||||
}
|
||||
@ -630,6 +669,9 @@ namespace nana
|
||||
if(filter.size() && (name.find(filter) == filter.npos))
|
||||
return false;
|
||||
|
||||
if(pick_directory_)
|
||||
return is_dir;
|
||||
|
||||
if((is_dir || 0 == extension) || (0 == extension->size())) return true;
|
||||
|
||||
for(auto & extstr : *extension)
|
||||
@ -744,7 +786,7 @@ namespace nana
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
void _m_sel_file(const arg_mouse& arg)
|
||||
void _m_select_file(const arg_mouse& arg)
|
||||
{
|
||||
auto sel = ls_file_.selected();
|
||||
if(sel.empty())
|
||||
@ -763,7 +805,7 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
if(false == m.directory)
|
||||
if((mode::open_directory == mode_) || (false == m.directory))
|
||||
{
|
||||
selection_.target = addr_.filesystem + m.name;
|
||||
tb_file_.caption(m.name);
|
||||
@ -816,13 +858,16 @@ namespace nana
|
||||
return;
|
||||
}
|
||||
|
||||
if(io_read_)
|
||||
if(mode::write_file != mode_)
|
||||
{
|
||||
if(fs::file_type::not_found == ftype)
|
||||
{
|
||||
msgbox mb(*this, caption());
|
||||
mb.icon(msgbox::icon_information);
|
||||
if(mode::open_file != mode_)
|
||||
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
||||
else
|
||||
mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar);
|
||||
mb();
|
||||
|
||||
return;
|
||||
@ -892,7 +937,8 @@ namespace nana
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool io_read_;
|
||||
bool const pick_directory_;
|
||||
mode mode_;
|
||||
std::string def_ext_;
|
||||
|
||||
place place_;
|
||||
@ -1118,7 +1164,8 @@ namespace nana
|
||||
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);
|
||||
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())
|
||||
{
|
||||
@ -1153,4 +1200,77 @@ namespace nana
|
||||
|
||||
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
|
||||
|
||||
@ -1294,8 +1294,10 @@ namespace nana
|
||||
min_width_entry_field_pixels_ = pixels;
|
||||
}
|
||||
|
||||
#ifndef _nana_cxx_folding_expression
|
||||
void inputbox::_m_fetch_args(std::vector<abstract_content*>&)
|
||||
{}
|
||||
#endif
|
||||
|
||||
bool inputbox::_m_open(std::vector<abstract_content*>& contents, bool modal)
|
||||
{
|
||||
|
||||
@ -64,8 +64,8 @@ namespace nana
|
||||
eof, error
|
||||
};
|
||||
|
||||
tokenizer(const char* p) noexcept
|
||||
: divstr_(p), sp_(p)
|
||||
tokenizer(const char* div_text) noexcept
|
||||
: divstr_(div_text), sp_(div_text)
|
||||
{}
|
||||
|
||||
const std::string& idstr() const noexcept
|
||||
@ -2583,9 +2583,8 @@ namespace nana
|
||||
: public division
|
||||
{
|
||||
public:
|
||||
div_switchable(std::string && name, implement* /*impl*/) noexcept:
|
||||
division(kind::switchable, std::move(name))//,
|
||||
//impl_(impl) //deprecated
|
||||
div_switchable(std::string && name, implement*) noexcept:
|
||||
division(kind::switchable, std::move(name))
|
||||
{}
|
||||
private:
|
||||
void collocate(window wd) override
|
||||
@ -2613,8 +2612,6 @@ namespace nana
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
//implement * const impl_; //deprecated
|
||||
};
|
||||
|
||||
place::implement::~implement()
|
||||
@ -3183,9 +3180,9 @@ namespace nana
|
||||
sp->set_renderer(impl_->split_renderer, true);
|
||||
}
|
||||
|
||||
void place::div(const char* s)
|
||||
void place::div(std::string div_text)
|
||||
{
|
||||
place_parts::tokenizer tknizer(s);
|
||||
place_parts::tokenizer tknizer(div_text.c_str());
|
||||
impl_->disconnect();
|
||||
auto div = impl_->scan_div(tknizer);
|
||||
try
|
||||
@ -3193,7 +3190,7 @@ namespace nana
|
||||
impl_->connect(div.get()); //throws if there is a redefined name of field.
|
||||
impl_->root_division.reset(); //clear atachments div-fields
|
||||
impl_->root_division.swap(div);
|
||||
impl_->div_text.assign(s);
|
||||
impl_->div_text.swap(div_text);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -3210,7 +3207,7 @@ namespace nana
|
||||
//Contributed by dankan1890(PR#156)
|
||||
enum class update_operation { erase = 0, insert, replace };
|
||||
|
||||
void update_div(std::string& div, const char* field, const char* attr, update_operation operation);
|
||||
static void update_div(std::string& div, const char* field, const char* attr, update_operation operation);
|
||||
|
||||
void place::modify(const char* name, const char* div_text)
|
||||
{
|
||||
@ -3324,7 +3321,7 @@ namespace nana
|
||||
return *p;
|
||||
}
|
||||
|
||||
void update_div(std::string& div, const char* field, const char* attr, update_operation operation)
|
||||
static void update_div(std::string& div, const char* field, const char* attr, update_operation operation)
|
||||
{
|
||||
const auto fieldname_pos = find_idstr(div, field);
|
||||
if (div.npos == fieldname_pos)
|
||||
|
||||
@ -21,6 +21,9 @@
|
||||
#include <nana/gui/detail/events_operation.hpp>
|
||||
|
||||
#include "../../source/detail/platform_abstraction.hpp"
|
||||
#ifdef NANA_X11
|
||||
# include "../../source/detail/posix/platform_spec.hpp"
|
||||
#endif
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -52,6 +55,19 @@ namespace nana
|
||||
}
|
||||
namespace API
|
||||
{
|
||||
#ifdef NANA_X11
|
||||
//Some platform specific functions for X11
|
||||
namespace x11
|
||||
{
|
||||
/// Returns the connection to the X server
|
||||
const void* get_display()
|
||||
{
|
||||
auto & spec = nana::detail::platform_spec::instance();
|
||||
return spec.open_display();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
using basic_window = ::nana::detail::basic_window;
|
||||
using interface_type = ::nana::detail::native_interface;
|
||||
|
||||
@ -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);
|
||||
internal_scope_guard isg;
|
||||
@ -377,8 +393,13 @@ namespace API
|
||||
{
|
||||
if (shortkey)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto off_x = (shortkey_position ? graph.text_extent_size(std::string_view{ text.c_str(), shortkey_position }).width : 0);
|
||||
auto key_px = static_cast<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 key_px = static_cast<int>(graph.text_extent_size(&shortkey, 1).width);
|
||||
#endif
|
||||
|
||||
unsigned ascent, descent, inleading;
|
||||
graph.text_metrics(ascent, descent, inleading);
|
||||
@ -392,7 +413,6 @@ namespace API
|
||||
}
|
||||
}//end namespace dev
|
||||
|
||||
|
||||
widget* get_widget(window wd)
|
||||
{
|
||||
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);
|
||||
internal_scope_guard lock;
|
||||
@ -1461,7 +1481,7 @@ namespace API
|
||||
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);
|
||||
internal_scope_guard lock;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Button Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -27,7 +27,7 @@ namespace nana{ namespace drawerbase
|
||||
: 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
|
||||
if (limit_pixels)
|
||||
@ -262,7 +262,11 @@ namespace nana{ namespace drawerbase
|
||||
if (attr_.omitted)
|
||||
tr.render(pos, txtptr, txtlen, omitted_pixels, true);
|
||||
else
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph.bidi_string(pos, { txtptr, txtlen });
|
||||
#else
|
||||
graph.bidi_string(pos, txtptr, txtlen);
|
||||
#endif
|
||||
|
||||
API::dev::draw_shortkey_underline(graph, mbstr, shortkey, shortkey_pos, pos, text_color);
|
||||
}
|
||||
@ -277,9 +281,15 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, { txtptr, txtlen });
|
||||
graph.palette(true, color{ colors::gray });
|
||||
graph.bidi_string(pos, { txtptr, txtlen });
|
||||
#else
|
||||
graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen);
|
||||
graph.palette(true, color{ colors::gray });
|
||||
graph.bidi_string(pos, txtptr, txtlen);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +78,11 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
|
||||
//draw crook
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto txt_px = graph.text_extent_size(std::wstring_view( L"jN", 2 )).height + 2;
|
||||
#else
|
||||
auto txt_px = graph.text_extent_size(L"jN", 2).height + 2;
|
||||
#endif
|
||||
impl_->crook.draw(graph, wdg->bgcolor(), wdg->fgcolor(), rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg));
|
||||
}
|
||||
|
||||
@ -163,12 +167,12 @@ namespace nana{ namespace drawerbase
|
||||
return (get_drawer_trigger().impl()->crook.checked() != drawerbase::checkbox::crook_state::unchecked);
|
||||
}
|
||||
|
||||
void checkbox::check(bool chk)
|
||||
void checkbox::check(bool state)
|
||||
{
|
||||
using crook_state = drawerbase::checkbox::crook_state;
|
||||
if (checked() != chk)
|
||||
if (checked() != state)
|
||||
{
|
||||
get_drawer_trigger().impl()->crook.check(chk ? crook_state::checked : crook_state::unchecked);
|
||||
get_drawer_trigger().impl()->crook.check(state ? crook_state::checked : crook_state::unchecked);
|
||||
API::refresh_window(handle());
|
||||
|
||||
arg_checkbox arg(this);
|
||||
|
||||
@ -90,7 +90,7 @@ namespace nana
|
||||
: 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
|
||||
if (limit_pixels)
|
||||
@ -1037,7 +1037,7 @@ namespace nana
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
|
||||
auto combox::_m_caption() const throw() -> native_string_type
|
||||
auto combox::_m_caption() const noexcept -> native_string_type
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
auto editor = _m_impl().editor();
|
||||
|
||||
@ -35,6 +35,7 @@ namespace nana{
|
||||
struct group::implement
|
||||
{
|
||||
label caption;
|
||||
align caption_align{ align::left };
|
||||
place place_content;
|
||||
unsigned gap{2};
|
||||
std::string usr_div_str;
|
||||
@ -65,11 +66,27 @@ namespace nana{
|
||||
|
||||
void update_div()
|
||||
{
|
||||
const std::size_t padding = 10;
|
||||
caption_dimension = caption.measure(1000);
|
||||
caption_dimension.width += 1;
|
||||
|
||||
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
||||
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())
|
||||
div += "<" + usr_div_str + ">>";
|
||||
@ -97,10 +114,15 @@ namespace nana{
|
||||
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)
|
||||
: panel(parent, r, vsb),
|
||||
impl_(new implement(*this, std::move(titel), vsb, gap))
|
||||
: group(parent, r, vsb)
|
||||
{
|
||||
this->bgcolor(API::bgcolor(parent));
|
||||
|
||||
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
||||
|
||||
impl_->caption.format(formatted);
|
||||
_m_init();
|
||||
}
|
||||
@ -128,6 +150,17 @@ namespace nana{
|
||||
return *impl_->options.back();
|
||||
}
|
||||
|
||||
void group::caption_align(align position)
|
||||
{
|
||||
if (position != impl_->caption_align)
|
||||
{
|
||||
impl_->caption_align = position;
|
||||
impl_->update_div();
|
||||
impl_->place_content.collocate();
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
}
|
||||
|
||||
group& group::radio_mode(bool enable)
|
||||
{
|
||||
_THROW_IF_EMPTY()
|
||||
@ -243,7 +276,7 @@ namespace nana{
|
||||
graph.round_rectangle(rectangle(point(gap_px, top_round_line),
|
||||
nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px)
|
||||
),
|
||||
3, 3, colors::gray_border, true, this->bgcolor());
|
||||
3, 3, this->scheme().border, true, this->bgcolor());
|
||||
|
||||
auto opt_r = API::window_rectangle(impl_->caption);
|
||||
if (opt_r)
|
||||
@ -263,15 +296,12 @@ namespace nana{
|
||||
|
||||
void group::_m_complete_creation()
|
||||
{
|
||||
panel::_m_complete_creation();
|
||||
|
||||
widget::_m_complete_creation();
|
||||
impl_->create(handle());
|
||||
|
||||
|
||||
_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();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Label Control Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (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
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view{ L" ", 1 }).height;
|
||||
#else
|
||||
const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height;
|
||||
#endif
|
||||
|
||||
font_ = pre_font;
|
||||
fblock_ = nullptr;
|
||||
@ -170,7 +174,11 @@ namespace nana
|
||||
|
||||
auto ft = graph.typeface(); //used for restoring the font
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view(L" ", 1)).height;
|
||||
#else
|
||||
const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height;
|
||||
#endif
|
||||
|
||||
font_ = ft;
|
||||
fblock_ = nullptr;
|
||||
@ -556,6 +564,16 @@ namespace nana
|
||||
|
||||
_m_change_font(graph, fblock_ptr);
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
std::wstring_view text_sv{ data_ptr->text() };
|
||||
if (text_range.second != text_sv.size())
|
||||
{
|
||||
text_sv = text_sv.substr(text_range.first, text_range.second);
|
||||
sz = graph.text_extent_size(text_sv);
|
||||
}
|
||||
|
||||
graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr));
|
||||
#else
|
||||
if (text_range.second == data_ptr->text().length())
|
||||
{
|
||||
graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr));
|
||||
@ -567,6 +585,7 @@ namespace nana
|
||||
|
||||
graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
_m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr);
|
||||
@ -653,7 +672,7 @@ namespace nana
|
||||
: 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.
|
||||
if (graph && ((0 == limit_pixels) || limit_width))
|
||||
@ -825,7 +844,7 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool label::transparent() const throw()
|
||||
bool label::transparent() const noexcept
|
||||
{
|
||||
return API::is_transparent_background(*this);
|
||||
}
|
||||
@ -849,7 +868,7 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
label& label::click_for(window associated_window) throw()
|
||||
label& label::click_for(window associated_window) noexcept
|
||||
{
|
||||
get_drawer_trigger().impl()->for_associated_wd = associated_window;
|
||||
return *this;
|
||||
|
||||
@ -2470,10 +2470,10 @@ namespace nana
|
||||
x += col.width_px;
|
||||
if (x > 0)
|
||||
{
|
||||
seqs.push_back(col.index);
|
||||
|
||||
if (x >= static_cast<int>(lister_w))
|
||||
break;
|
||||
|
||||
seqs.push_back(col.index);
|
||||
}
|
||||
}
|
||||
return seqs;
|
||||
@ -2757,6 +2757,17 @@ namespace nana
|
||||
unsigned es_lister::column_content_pixels(size_type pos) const
|
||||
{
|
||||
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 (std::size_t i = 0; i < cat.items.size(); ++i)
|
||||
@ -2768,14 +2779,14 @@ namespace nana
|
||||
if (pos >= model_cells.size())
|
||||
continue;
|
||||
|
||||
content_px = ess_->graph->text_extent_size(model_cells[pos].text).width;
|
||||
content_px = graph->text_extent_size(model_cells[pos].text).width;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos >= cat.items[i].cells->size())
|
||||
continue;
|
||||
|
||||
content_px = ess_->graph->text_extent_size((*cat.items[i].cells)[pos].text).width;
|
||||
content_px = graph->text_extent_size((*cat.items[i].cells)[pos].text).width;
|
||||
}
|
||||
|
||||
if (content_px > max_px)
|
||||
|
||||
@ -74,7 +74,7 @@ namespace nana
|
||||
: 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
|
||||
if (!limit_pixels)
|
||||
|
||||
@ -68,12 +68,6 @@ namespace nana {
|
||||
bool drag_started{ false };
|
||||
point origin;
|
||||
|
||||
/*
|
||||
scrolls enabled_scrolls{scrolls::both}; //deprecated
|
||||
nana::scroll<false> horz;
|
||||
nana::scroll<true> vert;
|
||||
*/
|
||||
|
||||
std::shared_ptr<cv_scroll_rep> cv_scroll;
|
||||
|
||||
timer tmr;
|
||||
@ -91,27 +85,10 @@ namespace nana {
|
||||
cv_scroll(std::make_shared<cv_scroll_rep>())
|
||||
{
|
||||
API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) {
|
||||
#if 0
|
||||
scroll_interface * scroll = nullptr;
|
||||
switch (arg.which)
|
||||
{
|
||||
case arg_wheel::wheel::vertical:
|
||||
scroll = |
|
||||
break;
|
||||
case arg_wheel::wheel::horizontal:
|
||||
scroll = &horz;
|
||||
break;
|
||||
default:
|
||||
//Other button is not unsupported.
|
||||
return;
|
||||
}
|
||||
#else
|
||||
auto const scroll = cv_scroll->scroll(arg.which);
|
||||
if (nullptr == scroll)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!API::empty_window(arg.window_handle))
|
||||
auto const scroll = cv_scroll->scroll(arg.which);
|
||||
|
||||
if (scroll && (!API::empty_window(arg.window_handle)))
|
||||
{
|
||||
auto align_px = (scroll->value() % scroll->step());
|
||||
if (align_px)
|
||||
|
||||
@ -834,8 +834,12 @@ namespace nana{ namespace widgets
|
||||
if (str_w > pixels) //Indicates the splitting of ts string
|
||||
{
|
||||
std::size_t len = ts.end - ts.begin;
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto pxbuf = editor_.graph_.glyph_pixels({ts.begin, len});
|
||||
#else
|
||||
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
|
||||
editor_.graph_.glyph_pixels(ts.begin, len, pxbuf.get());
|
||||
#endif
|
||||
|
||||
auto pxptr = pxbuf.get();
|
||||
auto pxend = pxptr + len;
|
||||
@ -3147,7 +3151,11 @@ namespace nana{ namespace widgets
|
||||
maskstr.append(n, mask_char_);
|
||||
return graph_.text_extent_size(maskstr);
|
||||
}
|
||||
#ifdef _nana_std_has_string_view
|
||||
return graph_.text_extent_size(std::basic_string_view<char_type>(str, n));
|
||||
#else
|
||||
return graph_.text_extent_size(str, static_cast<unsigned>(n));
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph_.string(pos, { str, len }, fgcolor);
|
||||
#else
|
||||
graph_.palette(true, fgcolor);
|
||||
graph_.string(pos, str, len);
|
||||
#endif
|
||||
if (parser.entities().empty())
|
||||
return;
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto glyph_px = graph_.glyph_pixels({ str, len });
|
||||
#else
|
||||
std::unique_ptr<unsigned[]> glyph_px(new unsigned[len]);
|
||||
graph_.glyph_pixels(str, len, glyph_px.get());
|
||||
#endif
|
||||
auto glyphs = glyph_px.get();
|
||||
|
||||
auto px_h = line_height();
|
||||
@ -3347,7 +3363,20 @@ namespace nana{ namespace widgets
|
||||
|
||||
ent_pos.x = pos.x + ent_off;
|
||||
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
std::wstring_view ent_sv;
|
||||
if (rtl)
|
||||
{
|
||||
//draw the whole text if it is a RTL text, because Arbic language is transformable.
|
||||
ent_sv = { str, len };
|
||||
}
|
||||
else
|
||||
{
|
||||
ent_sv = { ent_begin, static_cast<std::wstring_view::size_type>(ent_end - ent_begin) };
|
||||
ent_off = 0;
|
||||
}
|
||||
canvas.string({}, ent_sv);
|
||||
#else
|
||||
if (rtl)
|
||||
{
|
||||
//draw the whole text if it is a RTL text, because Arbic language is transformable.
|
||||
@ -3358,6 +3387,7 @@ namespace nana{ namespace widgets
|
||||
canvas.string({}, ent_begin, ent_end - ent_begin);
|
||||
ent_off = 0;
|
||||
}
|
||||
#endif
|
||||
graph_.bitblt(rectangle{ ent_pos, size{ ent_pixels, canvas.height() } }, canvas, point{ ent_off, 0 });
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph_.rectangle(::nana::rectangle{ text_pos,{ text_px, line_px_ } }, true,
|
||||
selection_color(false, has_focused));
|
||||
|
||||
graph_.string(text_pos, { text, len }, selection_color(true, has_focused));
|
||||
#else
|
||||
graph_.palette(true, selection_color(true, has_focused));
|
||||
|
||||
graph_.rectangle(::nana::rectangle{ text_pos, { text_px, line_px_ } }, true,
|
||||
selection_color(false, has_focused));
|
||||
|
||||
graph_.string(text_pos, text, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rtl_string(point strpos, const wchar_t* str, std::size_t len, std::size_t str_px, unsigned glyph_front, unsigned glyph_selected, bool has_focused)
|
||||
@ -3402,9 +3439,12 @@ namespace nana{ namespace widgets
|
||||
|
||||
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.string({ -sel_xpos, 0 }, str, len);
|
||||
#endif
|
||||
graph_.bitblt(nana::rectangle(strpos.x + sel_xpos, strpos.y, glyph_selected, line_px_), graph);
|
||||
};
|
||||
private:
|
||||
@ -3500,7 +3540,12 @@ namespace nana{ namespace widgets
|
||||
for (auto & ent : reordered)
|
||||
{
|
||||
std::size_t len = ent.end - ent.begin;
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
unsigned str_w = graph_.text_extent_size(std::wstring_view{ ent.begin, len }).width;
|
||||
#else
|
||||
unsigned str_w = graph_.text_extent_size(ent.begin, len).width;
|
||||
#endif
|
||||
|
||||
if ((text_draw_pos.x + static_cast<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)
|
||||
{
|
||||
const auto len = ent.end - ent.begin;
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto ent_px = graph_.text_extent_size(std::wstring_view(ent.begin, len)).width;
|
||||
#else
|
||||
auto ent_px = graph_.text_extent_size(ent.begin, len).width;
|
||||
#endif
|
||||
|
||||
extra_space = false;
|
||||
|
||||
@ -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_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] };
|
||||
graph_.glyph_pixels(ent.begin, len, pxbuf.get());
|
||||
#endif
|
||||
|
||||
auto head_px = std::accumulate(pxbuf.get(), pxbuf.get() + select_pos, unsigned{});
|
||||
auto select_px = std::accumulate(pxbuf.get() + select_pos, pxbuf.get() + select_pos + select_len, unsigned{});
|
||||
@ -3589,7 +3642,11 @@ namespace nana{ namespace widgets
|
||||
auto pos = text_coord.x + text_len;
|
||||
if (b.x != pos || text_coord.y != b.y)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto whitespace_w = graph_.text_extent_size(std::wstring_view{ L" ", 1 }).width;
|
||||
#else
|
||||
auto whitespace_w = graph_.text_extent_size(L" ", 1).width;
|
||||
#endif
|
||||
graph_.rectangle(::nana::rectangle{ text_draw_pos, { whitespace_w, line_h_pixels } }, true);
|
||||
}
|
||||
}
|
||||
@ -3617,9 +3674,13 @@ namespace nana{ namespace widgets
|
||||
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);
|
||||
|
||||
#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]);
|
||||
if (graph_.glyph_pixels(ent.begin, len, pxbuf.get()))
|
||||
#endif
|
||||
{
|
||||
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.
|
||||
//RTL
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto pxbuf = graph_.glyph_pixels({ent.begin, len});
|
||||
#else
|
||||
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
|
||||
graph_.glyph_pixels(ent.begin, len, pxbuf.get());
|
||||
#endif
|
||||
return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w);
|
||||
}
|
||||
//LTR
|
||||
|
||||
@ -82,10 +82,39 @@ namespace nana
|
||||
|
||||
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())
|
||||
return true;
|
||||
|
||||
auto size = str.size();
|
||||
auto const size = str.size();
|
||||
std::size_t pos = 0;
|
||||
if (str[0] == '+' || str[0] == '-')
|
||||
pos = 1;
|
||||
@ -115,6 +144,7 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -744,7 +774,7 @@ namespace nana
|
||||
modifier(to_utf8(prefix), to_utf8(suffix));
|
||||
}
|
||||
|
||||
auto spinbox::_m_caption() const throw() -> native_string_type
|
||||
auto spinbox::_m_caption() const noexcept -> native_string_type
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().impl()->editor();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Tabbar Implementation
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -1489,7 +1489,12 @@ namespace nana
|
||||
}
|
||||
|
||||
graph.rectangle(r, true);
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text);
|
||||
|
||||
#else
|
||||
graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size());
|
||||
#endif
|
||||
|
||||
++pos;
|
||||
}
|
||||
@ -1533,7 +1538,7 @@ namespace nana
|
||||
delete model_;
|
||||
}
|
||||
|
||||
model* driver::get_model() const throw()
|
||||
model* driver::get_model() const noexcept
|
||||
{
|
||||
return model_;
|
||||
}
|
||||
|
||||
@ -785,7 +785,7 @@ namespace drawerbase {
|
||||
}
|
||||
|
||||
//Override _m_caption for caption()
|
||||
auto textbox::_m_caption() const throw() -> native_string_type
|
||||
auto textbox::_m_caption() const noexcept -> native_string_type
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().editor();
|
||||
|
||||
@ -1163,7 +1163,11 @@ namespace nana
|
||||
|
||||
virtual unsigned item_height(graph_reference graph) const override
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
return graph.text_extent_size(std::wstring_view{ L"jH{", 3 }).height + 8;
|
||||
#else
|
||||
return graph.text_extent_size(L"jH{", 3).height + 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override
|
||||
|
||||
@ -54,12 +54,12 @@ namespace nana
|
||||
widget& wdg_;
|
||||
};
|
||||
|
||||
std::string widget::caption() const throw()
|
||||
std::string widget::caption() const noexcept
|
||||
{
|
||||
return to_utf8(_m_caption());
|
||||
}
|
||||
|
||||
std::wstring widget::caption_wstring() const throw()
|
||||
std::wstring widget::caption_wstring() const noexcept
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
return _m_caption();
|
||||
@ -68,7 +68,7 @@ namespace nana
|
||||
#endif
|
||||
}
|
||||
|
||||
auto widget::caption_native() const throw() -> native_string_type
|
||||
auto widget::caption_native() const noexcept -> native_string_type
|
||||
{
|
||||
return _m_caption();
|
||||
}
|
||||
@ -287,7 +287,7 @@ namespace nana
|
||||
void widget::_m_complete_creation()
|
||||
{}
|
||||
|
||||
auto widget::_m_caption() const throw() -> native_string_type
|
||||
auto widget::_m_caption() const noexcept -> native_string_type
|
||||
{
|
||||
return API::dev::window_caption(handle());
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An Implementation of i18n
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -185,14 +185,17 @@ namespace nana
|
||||
|
||||
table["NANA_FILEBOX_SAVE_AS"] = "Save As";
|
||||
table["NANA_FILEBOX_OPEN"] = "Open";
|
||||
table["NANA_FILEBOX_DIRECTORY"] = "Directory";
|
||||
table["NANA_FILEBOX_OPEN_DIRECTORY"] = "Select A Directory";
|
||||
table["NANA_FILEBOX_FILE"] = "File";
|
||||
table["NANA_FILEBOX_FILE_COLON"] = "File:";
|
||||
table["NANA_FILEBOX_DIRECTORY"] = "Directory";
|
||||
table["NANA_FILEBOX_DIRECTORY_COLON"] = "Directory:";
|
||||
table["NANA_FILEBOX_ERROR_INVALID_FOLDER_NAME"] = "Please input a valid name for the new folder.";
|
||||
table["NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_EXISTING"] = "The folder is existing, please rename it.";
|
||||
table["NANA_FILEBOX_ERROR_RENAME_FOLDER_BECAUSE_OF_FAILED_CREATION"] = "Failed to create the folder, please rename it.";
|
||||
table["NANA_FILEBOX_ERROR_INVALID_FILENAME"] = "The filename is invalid.";
|
||||
table["NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY"] = "The file \"%arg0\"\n is not existing. Please check and retry.";
|
||||
table["NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY"] = "The directory \"%arg0\"\n is not existing. Please check and retry.";
|
||||
table["NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING"] = "The input file is existing, do you want to overwrite it?";
|
||||
}
|
||||
};
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -134,29 +134,84 @@ namespace detail
|
||||
pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y});
|
||||
}
|
||||
|
||||
nana::size raw_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len)
|
||||
nana::size real_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len)
|
||||
{
|
||||
if(nullptr == dw || nullptr == text || 0 == len) return nana::size();
|
||||
if (dw && text && len)
|
||||
{
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
::SIZE size;
|
||||
if(::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size))
|
||||
if (::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size))
|
||||
return nana::size(size.cx, size.cy);
|
||||
#elif defined(NANA_X11)
|
||||
#if defined(NANA_USE_XFT)
|
||||
std::string utf8str = to_utf8(std::wstring(text, len));
|
||||
std::string utf8text = to_utf8(std::wstring(text, len));
|
||||
#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*>(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);
|
||||
#else
|
||||
#else
|
||||
XRectangle ink;
|
||||
XRectangle logic;
|
||||
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic);
|
||||
return nana::size(logic.width, logic.height);
|
||||
#endif
|
||||
#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();
|
||||
#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)
|
||||
@ -164,7 +219,7 @@ namespace detail
|
||||
if (nullptr == dw || nullptr == text || 0 == len)
|
||||
return{};
|
||||
|
||||
nana::size extents = raw_text_extent_size(dw, text, len);
|
||||
nana::size extents = real_text_extent_size(dw, text, len);
|
||||
|
||||
const wchar_t* const end = text + len;
|
||||
int tabs = 0;
|
||||
|
||||
@ -411,8 +411,8 @@ namespace paint
|
||||
impl_->handle = dw.get();
|
||||
impl_->size = sz;
|
||||
|
||||
impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width;
|
||||
impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width;
|
||||
impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width;
|
||||
impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width;
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,8 +438,9 @@ namespace paint
|
||||
#if defined(NANA_WINDOWS)
|
||||
::SelectObject(impl_->handle->context, reinterpret_cast<HFONT>(f.impl_->real_font->native_handle()));
|
||||
#endif
|
||||
impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width;
|
||||
impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width;
|
||||
|
||||
impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width;
|
||||
impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width;
|
||||
|
||||
if (impl_->changed == false)
|
||||
impl_->changed = true;
|
||||
@ -453,6 +454,114 @@ namespace paint
|
||||
return (impl_->handle ? font(impl_->handle) : impl_->font_shadow);
|
||||
}
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
size graphics::text_extent_size(std::string_view text) const
|
||||
{
|
||||
throw_not_utf8(text);
|
||||
return detail::text_extent_size(impl_->handle, text.data(), text.length());
|
||||
}
|
||||
|
||||
size graphics::text_extent_size(std::wstring_view text) const
|
||||
{
|
||||
return detail::text_extent_size(impl_->handle, text.data(), text.length());
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
if(len < end) end = len;
|
||||
if (len < end) end = len;
|
||||
if (nullptr == impl_->handle || nullptr == str || 0 == len || begin >= end) return{};
|
||||
|
||||
nana::size sz;
|
||||
@ -497,13 +606,13 @@ namespace paint
|
||||
sz.width = dx[end - 1] - (begin ? dx[begin - 1] : 0);
|
||||
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
|
||||
const wchar_t * pend = str + end;
|
||||
for(const wchar_t * p = str + begin; p != pend; ++p)
|
||||
for (const wchar_t * p = str + begin; p != pend; ++p)
|
||||
{
|
||||
if(*p == '\t')
|
||||
if (*p == '\t')
|
||||
sz.width += tab_pixels;
|
||||
}
|
||||
sz.height = extents.cy;
|
||||
delete [] dx;
|
||||
delete[] dx;
|
||||
#elif defined(NANA_X11)
|
||||
sz = text_extent_size(str + begin, end - begin);
|
||||
#endif
|
||||
@ -517,8 +626,8 @@ namespace paint
|
||||
|
||||
bool graphics::glyph_pixels(const wchar_t * str, std::size_t len, unsigned* pxbuf) const
|
||||
{
|
||||
if(nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == str || nullptr == pxbuf) return false;
|
||||
if(len == 0) return true;
|
||||
if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == str || nullptr == pxbuf) return false;
|
||||
if (len == 0) return true;
|
||||
|
||||
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
|
||||
#if defined(NANA_WINDOWS)
|
||||
@ -528,20 +637,20 @@ namespace paint
|
||||
|
||||
pxbuf[0] = (str[0] == '\t' ? tab_pixels : dx[0]);
|
||||
|
||||
for(std::size_t i = 1; i < len; ++i)
|
||||
for (std::size_t i = 1; i < len; ++i)
|
||||
{
|
||||
pxbuf[i] = (str[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]);
|
||||
}
|
||||
delete [] dx;
|
||||
delete[] dx;
|
||||
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
||||
|
||||
auto disp = nana::detail::platform_spec::instance().open_display();
|
||||
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
|
||||
|
||||
XGlyphInfo extents;
|
||||
for(std::size_t i = 0; i < len; ++i)
|
||||
for (std::size_t i = 0; i < len; ++i)
|
||||
{
|
||||
if(str[i] != '\t')
|
||||
if (str[i] != '\t')
|
||||
{
|
||||
FT_UInt glyphs = ::XftCharIndex(disp, xft, str[i]);
|
||||
::XftGlyphExtents(disp, xft, &glyphs, 1, &extents);
|
||||
@ -557,14 +666,18 @@ namespace paint
|
||||
nana::size graphics::bidi_extent_size(const std::wstring& str) const
|
||||
{
|
||||
nana::size sz;
|
||||
if(impl_->handle && impl_->handle->context && str.size())
|
||||
if (impl_->handle && impl_->handle->context && str.size())
|
||||
{
|
||||
auto const reordered = unicode_reorder(str.c_str(), str.size());
|
||||
for(auto & i: reordered)
|
||||
for (auto & i : reordered)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
nana::size t = text_extent_size(std::wstring_view(i.begin, i.end - i.begin));
|
||||
#else
|
||||
nana::size t = text_extent_size(i.begin, i.end - i.begin);
|
||||
#endif
|
||||
sz.width += t.width;
|
||||
if(sz.height < t.height)
|
||||
if (sz.height < t.height)
|
||||
sz.height = t.height;
|
||||
}
|
||||
}
|
||||
@ -575,6 +688,7 @@ namespace paint
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -937,7 +1051,7 @@ namespace paint
|
||||
impl_->size.width = impl_->size.height = 0;
|
||||
}
|
||||
|
||||
void graphics::save_as_file(const char* file_utf8) const throw()
|
||||
void graphics::save_as_file(const char* file_utf8) const noexcept
|
||||
{
|
||||
if(impl_->handle)
|
||||
{
|
||||
@ -1003,25 +1117,6 @@ namespace paint
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned graphics::bidi_string(const nana::point& pos, const wchar_t * str, std::size_t len)
|
||||
{
|
||||
auto moved_pos = pos;
|
||||
|
||||
auto const reordered = unicode_reorder(str, len);
|
||||
for (auto & i : reordered)
|
||||
{
|
||||
string(moved_pos, i.begin, i.end - i.begin);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
string(pos, to_wstring(text_utf8));
|
||||
@ -1076,7 +1281,7 @@ namespace paint
|
||||
{
|
||||
//Render a part that does not contains a tab
|
||||
detail::draw_string(impl_->handle, pos, str, len);
|
||||
pos.x += detail::raw_text_extent_size(impl_->handle, str, len).width;
|
||||
pos.x += detail::real_text_extent_size(impl_->handle, str, len).width;
|
||||
}
|
||||
|
||||
str = i;
|
||||
@ -1114,6 +1319,7 @@ namespace paint
|
||||
palette(true, clr);
|
||||
string(pos, text.data(), text.size());
|
||||
}
|
||||
#endif //_nana_std_has_string_view
|
||||
|
||||
void graphics::line(const nana::point& pos1, const nana::point& pos2)
|
||||
{
|
||||
|
||||
@ -52,6 +52,7 @@ namespace nana
|
||||
{
|
||||
std::size_t len = ent.end - ent.begin;
|
||||
nana::size ts = detail::text_extent_size(dw, ent.begin, len);
|
||||
|
||||
if(ts.height > pixels) pixels = ts.height;
|
||||
|
||||
if(pos.x + static_cast<int>(ts.width) > 0)
|
||||
@ -128,7 +129,11 @@ namespace nana
|
||||
draw_string_omitted(graphics& graph, int x, int endpos, bool omitted)
|
||||
: graph(graph), x(x), endpos(endpos)
|
||||
{
|
||||
#ifdef _nana_std_has_string_view
|
||||
omitted_pixels = (omitted ? graph.text_extent_size(std::string_view{ "...", 3 }).width : 0);
|
||||
#else
|
||||
omitted_pixels = (omitted ? graph.text_extent_size("...", 3).width : 0);
|
||||
#endif
|
||||
if (endpos - x > static_cast<int>(omitted_pixels))
|
||||
this->endpos -= omitted_pixels;
|
||||
else
|
||||
@ -164,8 +169,12 @@ namespace nana
|
||||
|
||||
dum_graph.bitblt(r, graph, pos);
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
dum_graph.string({}, { i.begin, len }, graph.palette(true));
|
||||
#else
|
||||
dum_graph.palette(true, graph.palette(true));
|
||||
dum_graph.string({}, i.begin, len);
|
||||
#endif
|
||||
|
||||
r.x = pos.x;
|
||||
r.y = top;
|
||||
@ -228,10 +237,14 @@ namespace nana
|
||||
const std::size_t len = i.end - i.begin;
|
||||
if(len > 1)
|
||||
{
|
||||
std::unique_ptr<unsigned[]> pixel_buf(new unsigned[len]);
|
||||
|
||||
//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());
|
||||
#endif
|
||||
|
||||
std::size_t idx_head = 0, idx_splitted;
|
||||
|
||||
do
|
||||
@ -448,10 +461,16 @@ namespace nana
|
||||
std::size_t len = i.end - i.begin;
|
||||
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]);
|
||||
auto pxbuf = scope_res.get();
|
||||
//Find the char that should be splitted
|
||||
graph.glyph_pixels(i.begin, len, pxbuf);
|
||||
#endif
|
||||
|
||||
std::size_t idx_head = 0, idx_splitted;
|
||||
|
||||
do
|
||||
@ -625,14 +644,23 @@ namespace nana
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph_.bidi_string(pos, text);
|
||||
#else
|
||||
graph_.bidi_string(pos, text.c_str(), text.size());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width;
|
||||
auto pixels = graph_.glyph_pixels({ text.c_str(), text.size() });
|
||||
#else
|
||||
const auto ellipsis = graph_.text_extent_size("...", 3).width;
|
||||
|
||||
std::unique_ptr<unsigned[]> pixels(new unsigned[text.size()]);
|
||||
graph_.glyph_pixels(text.c_str(), text.size(), pixels.get());
|
||||
#endif
|
||||
|
||||
std::size_t substr_len = 0;
|
||||
unsigned substr_px = 0;
|
||||
@ -653,7 +681,11 @@ namespace nana
|
||||
} while (p != end);
|
||||
|
||||
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);
|
||||
#endif
|
||||
pos.x -= ellipsis;
|
||||
}
|
||||
else
|
||||
@ -670,8 +702,11 @@ namespace nana
|
||||
|
||||
if (align::center == text_align_ex_)
|
||||
pos.x += (width - substr_px - ellipsis) / 2;
|
||||
|
||||
#ifdef _nana_std_has_string_view
|
||||
graph_.bidi_string(pos, { text.c_str(), substr_len });
|
||||
#else
|
||||
graph_.bidi_string(pos, text.c_str(), substr_len);
|
||||
#endif
|
||||
|
||||
pos.x += substr_px;
|
||||
}
|
||||
|
||||
@ -426,7 +426,7 @@ namespace std
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _enable_std_put_time
|
||||
#ifdef _nana_std_put_time
|
||||
#include <cwchar>
|
||||
namespace std
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user