Merge branch 'develop'
This commit is contained in:
commit
4df1689b46
@ -8,11 +8,11 @@ cache:
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: CXX=g++-5 CC=gcc-5
|
||||
- env: CXX=g++-8
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
- g++-8
|
||||
- libjpeg8-dev
|
||||
- libpng-dev
|
||||
- libasound2-dev
|
||||
@ -21,7 +21,7 @@ matrix:
|
||||
- libx11-dev
|
||||
- libxft-dev
|
||||
- libxcursor-dev
|
||||
sources:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
allow_failures:
|
||||
@ -44,7 +44,7 @@ matrix:
|
||||
|
||||
before_install:
|
||||
- cd ..
|
||||
- git clone --depth=1 --branch=cmake-dev https://github.com/qPCR4vir/nana-demo.git nana-demo
|
||||
- git clone --depth=1 --branch=hotfix https://github.com/qPCR4vir/nana-demo.git nana-demo
|
||||
- export PATH="$HOME/bin:$PATH"
|
||||
|
||||
#- mkdir ~/bin #it seemd that a bin already exists from 20170901
|
||||
|
||||
@ -61,7 +61,7 @@ namespace nana
|
||||
return new holder(value);
|
||||
}
|
||||
public:
|
||||
Value value; //representation accessable for friend of any
|
||||
Value value; //representation accessible for friend of any
|
||||
};
|
||||
public:
|
||||
//constructors and destructor
|
||||
|
||||
@ -74,7 +74,7 @@ namespace nana
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct drawable_impl_type; //declearation, defined in platform_spec.hpp
|
||||
struct drawable_impl_type; //declaration, defined in platform_spec.hpp
|
||||
}
|
||||
|
||||
namespace paint
|
||||
@ -275,7 +275,7 @@ namespace nana
|
||||
yellow = 0xFFFF00,
|
||||
yellow_green = 0x9acd32,
|
||||
|
||||
//temporary defintions, these will be replaced by color schema
|
||||
//temporary definitions, these will be replaced by color schema
|
||||
button_face_shadow_start = 0xF5F4F2,
|
||||
button_face_shadow_end = 0xD5D2CA,
|
||||
button_face = 0xD4D0C8 , //,light_cyan
|
||||
@ -425,7 +425,7 @@ namespace nana
|
||||
size(value_type width, value_type height);
|
||||
|
||||
bool empty() const; ///< true if width * height == 0
|
||||
bool is_hit(const point&) const; ///< Assume it is a rectangle at (0,0), and check whether a specified position is in the rectange.
|
||||
bool is_hit(const point&) const; ///< Assume it is a rectangle at (0,0), and check whether a specified position is in the rectangle.
|
||||
size& shift();
|
||||
|
||||
bool operator==(const size& rhs) const;
|
||||
|
||||
@ -164,7 +164,7 @@
|
||||
|
||||
#if defined(NANA_MINGW)
|
||||
#ifndef __MINGW64_VERSION_MAJOR
|
||||
//It's a knonwn issue under MinGW(except MinGW-W64)
|
||||
//It's a known issue under MinGW(except MinGW-W64)
|
||||
#define STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -18,7 +18,7 @@ namespace nana
|
||||
{
|
||||
namespace utf
|
||||
{
|
||||
/// Attempt to get a pointer to a character of UTF-8 string by a specifed character index.
|
||||
/// Attempt to get a pointer to a character of UTF-8 string by a specified character index.
|
||||
/// @param text_utf8 A string encoded as UTF-8.
|
||||
/// @param pos The unicode character index.
|
||||
/// @returns A pointer to the unicode character. It returns a null if pos is out of range.
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
//
|
||||
//#define BOOST_FILESYSTEM_AVAILABLE // "Is Boost filesystem available?"
|
||||
//#define BOOST_FILESYSTEM_FORCE // "Force use of Boost filesystem if available (over ISO and nana)
|
||||
//#define STD_FILESYSTEM_FORCE // "Use of STD filesystem?(a compilation error will ocurre if not available)" OFF)
|
||||
//#define STD_FILESYSTEM_FORCE // "Use of STD filesystem?(a compilation error will occur if not available)" OFF)
|
||||
//#define NANA_FILESYSTEM_FORCE // "Force nana filesystem over ISO and boost?" OFF)
|
||||
//
|
||||
// Make sure you (cmake?) provide the following where correspond (please find the correct values):
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @file: nana/deploy.hpp
|
||||
*
|
||||
* What follow are dependented on what defined in nana/config.hpp
|
||||
* What follows is dependent on what defined in nana/config.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_DEPLOY_HPP
|
||||
|
||||
@ -108,11 +108,16 @@ namespace std {
|
||||
{
|
||||
using namespace experimental::filesystem;
|
||||
}
|
||||
|
||||
#ifndef __cpp_lib_experimental_filesystem
|
||||
# define __cpp_lib_experimental_filesystem 201406
|
||||
#endif
|
||||
} // std
|
||||
|
||||
#else
|
||||
# undef NANA_USING_STD_FILESYSTEM
|
||||
# define NANA_USING_STD_FILESYSTEM 1
|
||||
//Detects whether the compiler supports std::filesystem under current options
|
||||
# if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) || \
|
||||
((__cplusplus >= 201703L) && \
|
||||
(defined(__clang__) && (__clang_major__ >= 7) || \
|
||||
@ -125,14 +130,11 @@ namespace std {
|
||||
using namespace std::experimental::filesystem;
|
||||
}
|
||||
}
|
||||
# undef NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||
# define NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __cpp_lib_experimental_filesystem
|
||||
# define __cpp_lib_experimental_filesystem 201406
|
||||
#endif
|
||||
|
||||
#if NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
#include <string>
|
||||
@ -254,7 +256,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
path relative_path() const;
|
||||
path parent_path() const;
|
||||
path filename() const;
|
||||
//path stem() const;
|
||||
path stem() const;
|
||||
path extension() const;
|
||||
|
||||
// query
|
||||
@ -290,6 +292,8 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
// std::u16string generic_u16string() const;
|
||||
// std::u32string generic_u32string() const;
|
||||
|
||||
path lexically_normal() const;
|
||||
|
||||
//appends
|
||||
path& operator/=(const path& other);
|
||||
|
||||
@ -544,6 +548,9 @@ namespace std {
|
||||
|
||||
path canonical(const path& p);
|
||||
path canonical(const path& p, std::error_code& err);
|
||||
|
||||
path weakly_canonical(const path& p);
|
||||
path weakly_canonical(const path& p, std::error_code& err);
|
||||
#endif
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
||||
@ -553,7 +560,23 @@ namespace std {
|
||||
#endif
|
||||
}
|
||||
} // std
|
||||
#else
|
||||
|
||||
//Implements the missing functions for various version of experimental/filesystem
|
||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
//Visual Studio 2017
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801))
|
||||
path weakly_canonical(const path& p);
|
||||
path weakly_canonical(const path& p, std::error_code& err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif //NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ namespace nana
|
||||
public:
|
||||
frameset();
|
||||
void push_back(paint::image); ///< Inserts frames at the end.
|
||||
void push_back(framebuilder fb, std::size_t length); ///< Insters a framebuilder and the number of frames that it generates.
|
||||
void push_back(framebuilder fb, std::size_t length); ///< Inserts a framebuilder and the number of frames that it generates.
|
||||
private:
|
||||
std::shared_ptr<impl> impl_;
|
||||
};
|
||||
|
||||
@ -183,7 +183,7 @@ namespace nana
|
||||
|
||||
A window has an appearance. This appearance can be specified when a window is being created.
|
||||
To determine the appearance of a window there is a structure named nana::appearance with
|
||||
a bool member for each feature with can be included or excluded in the "apereance" of the windows form.
|
||||
a bool member for each feature with can be included or excluded in the "appearance" of the windows form.
|
||||
But in practical development is hard to describe the style of the appearance using the struct nana::appearance.
|
||||
If a form would to be defined without min/max button and sizable border, then
|
||||
|
||||
@ -282,7 +282,7 @@ that return a corresponding nana::appearance with predefined values.
|
||||
set_type::template count<sizable>::value);
|
||||
}
|
||||
};
|
||||
};//end namespace apper
|
||||
};//end namespace appear
|
||||
|
||||
/// Interface for caret operations
|
||||
class caret_interface
|
||||
|
||||
@ -127,6 +127,9 @@ namespace detail
|
||||
basic_window * seek_non_lite_widget_ancestor() const;
|
||||
|
||||
void set_action(mouse_action);
|
||||
|
||||
/// Only refresh when the root of window is in lazy-updating mode
|
||||
bool try_lazy_update(bool try_refresh);
|
||||
public:
|
||||
/// Override event_holder
|
||||
bool set_events(const std::shared_ptr<general_events>&) override;
|
||||
@ -176,8 +179,7 @@ namespace detail
|
||||
bool ignore_mouse_focus : 1; ///< A flag indicates whether the widget accepts focus when clicking on it
|
||||
bool space_click_enabled : 1; ///< A flag indicates whether enable mouse_down/click/mouse_up when pressing and releasing whitespace key.
|
||||
bool draggable : 1;
|
||||
bool ignore_child_mapping : 1;
|
||||
unsigned Reserved :16;
|
||||
unsigned Reserved : 17;
|
||||
unsigned char tab; ///< indicate a window that can receive the keyboard TAB
|
||||
mouse_action action;
|
||||
mouse_action action_before;
|
||||
@ -205,11 +207,14 @@ namespace detail
|
||||
{
|
||||
struct attr_root_tag
|
||||
{
|
||||
bool ime_enabled{ false };
|
||||
bool lazy_update{ false }; ///< Indicates whether the window is in lazy-updating mode.
|
||||
|
||||
container update_requesters; ///< Container for lazy-updating requesting windows.
|
||||
container tabstop;
|
||||
std::vector<edge_nimbus_action> effects_edge_nimbus;
|
||||
basic_window* focus{nullptr};
|
||||
basic_window* menubar{nullptr};
|
||||
bool ime_enabled{false};
|
||||
cursor state_cursor{nana::cursor::arrow};
|
||||
basic_window* state_cursor_window{ nullptr };
|
||||
|
||||
@ -223,8 +228,6 @@ namespace detail
|
||||
update_state upd_state;
|
||||
dragdrop_status dnd_state{ dragdrop_status::not_ready };
|
||||
|
||||
container mapping_requester; ///< Children which are ignored to mapping
|
||||
|
||||
union
|
||||
{
|
||||
attr_root_tag * root;
|
||||
|
||||
@ -98,10 +98,10 @@ namespace nana
|
||||
void clear_filter();
|
||||
|
||||
private:
|
||||
void _m_reset_overrided();
|
||||
bool _m_overrided(event_code) const;
|
||||
void _m_reset_overridden();
|
||||
bool _m_overridden(event_code) const;
|
||||
private:
|
||||
unsigned overrided_{ 0xFFFFFFFF };
|
||||
unsigned overridden_{ 0xFFFFFFFF };
|
||||
unsigned evt_disabled_{ 0 }; // bit set if event is filtered
|
||||
};
|
||||
|
||||
@ -117,8 +117,8 @@ namespace nana
|
||||
enum class method_state
|
||||
{
|
||||
pending,
|
||||
overrided,
|
||||
not_overrided
|
||||
overridden,
|
||||
not_overridden
|
||||
};
|
||||
public:
|
||||
drawer();
|
||||
@ -165,7 +165,7 @@ namespace nana
|
||||
auto realizer = this->realizer();
|
||||
auto & mth_state = _m_mth_state(pos);
|
||||
|
||||
if (realizer && (method_state::not_overrided != mth_state))
|
||||
if (realizer && (method_state::not_overridden != mth_state))
|
||||
{
|
||||
const bool bFiltered = !bForce__EmitInternal && realizer->filter_event(evt_code);
|
||||
if (method_state::pending == mth_state)
|
||||
@ -176,7 +176,7 @@ namespace nana
|
||||
//Check realizer, when the window is closed in that event handler, the drawer will be
|
||||
//detached and realizer will be a nullptr
|
||||
if (realizer)
|
||||
mth_state = (realizer->_m_overrided(evt_code) ? method_state::overrided : method_state::not_overrided);
|
||||
mth_state = (realizer->_m_overridden(evt_code) ? method_state::overridden : method_state::not_overridden);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -28,7 +28,7 @@ namespace nana
|
||||
mouse_wheel, ///< A mouse scrolls the wheel on a widget.
|
||||
mouse_drop, ///< A mouse release over a window that is registered as recipient of drag and drop.
|
||||
expose, ///<
|
||||
resizing, ///< A widget's size is sizing. In this event, A widget's size can be overrided with a new size.
|
||||
resizing, ///< A widget's size is sizing. In this event, A widget's size can be overridden with a new size.
|
||||
resized, ///< A widget's size is changing.
|
||||
move, ///<
|
||||
unload, ///< A form is closed by clicking the X button, only works for root widget.
|
||||
|
||||
@ -99,7 +99,11 @@ namespace detail
|
||||
|
||||
bool show(core_window_t* wd, bool visible);
|
||||
|
||||
core_window_t* find_window(native_window_type root, const point& pos);
|
||||
//find a widget window at specified position
|
||||
//@param root A root window
|
||||
//@param pos Position
|
||||
//@param ignore_captured A flag indicates whether to ignore redirecting the result to its captured window. If this paramter is true, it returns the window at the position, if the parameter is false, it returns the captured window if the captured window don't ignore children.
|
||||
core_window_t* find_window(native_window_type root, const point& pos, bool ignore_captured = false);
|
||||
|
||||
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
|
||||
bool move(core_window_t*, int x, int y, bool passive);
|
||||
@ -116,7 +120,6 @@ namespace detail
|
||||
void refresh_tree(core_window_t*);
|
||||
|
||||
void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false);
|
||||
void map_requester(core_window_t*);
|
||||
|
||||
bool set_parent(core_window_t* wd, core_window_t* new_parent);
|
||||
core_window_t* set_focus(core_window_t*, bool root_has_been_focused, arg_focus::reason);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
#include "../traits.hpp"
|
||||
namespace nana
|
||||
{
|
||||
/// \brief Draw pictures on a widget by specifying a drawing method that will be employed everytime the widget refreshes.
|
||||
/// \brief Draw pictures on a widget by specifying a drawing method that will be employed every time the widget refreshes.
|
||||
/// By the end of drawing, the picture may not be displayed immediately.
|
||||
/// If a picture need to be displayed immediately call nana::gui::API::refresh_window() .
|
||||
class drawing
|
||||
|
||||
@ -17,10 +17,10 @@
|
||||
|
||||
namespace nana
|
||||
{
|
||||
//overlap test if overlaped between r1 and r2
|
||||
//overlap test if overlapped between r1 and r2
|
||||
bool overlapped(const rectangle& r1, const rectangle& r2);
|
||||
|
||||
// overlap, compute the overlap area between r1 and r2. the r is for root
|
||||
// overlap, compute the overlapping area between r1 and r2. the r is for root
|
||||
bool overlap(const rectangle& r1, const rectangle& r2, rectangle& r);
|
||||
|
||||
bool overlap(const rectangle& ir, const size& valid_input_area, const rectangle & dr, const size& valid_dst_area, rectangle& output_src_r, rectangle& output_dst_r);
|
||||
@ -37,7 +37,7 @@ namespace nana
|
||||
|
||||
//covered
|
||||
//@brief: Tests a rectangle whether it is wholly covered by another.
|
||||
bool covered(const rectangle& underlying, //Rectangle 1 is must under rectangle 2
|
||||
bool covered(const rectangle& underlying, // 1st rectangle must be placed under 2nd rectangle
|
||||
const rectangle& cover);
|
||||
}//end namespace nana
|
||||
#endif
|
||||
|
||||
@ -21,7 +21,7 @@ namespace nana
|
||||
//Forward declaration of filebox for msgbox
|
||||
class filebox;
|
||||
|
||||
/// Prefabricated modal dialog box (with text, icon and actions buttons) that inform and instruct the user.
|
||||
/// Prefabricated modal dialog box (with text, icon and actions buttons) that informs and instructs the user.
|
||||
class msgbox
|
||||
{
|
||||
public:
|
||||
@ -34,19 +34,19 @@ namespace nana
|
||||
/// Identifiers of buttons that a user clicked.
|
||||
enum pick_t{pick_ok, pick_yes, pick_no, pick_cancel};
|
||||
|
||||
/// Default construct that creates a message box with default title and default button, the default button is OK.
|
||||
/// Default constructor that creates a message box with default title and default button, the default button is OK.
|
||||
msgbox();
|
||||
|
||||
/// Copy construct from an existing msgbox object.
|
||||
/// Copy constructor from an existing msgbox object.
|
||||
msgbox(const msgbox&);
|
||||
|
||||
/// Assign from an existing msgbox object.
|
||||
msgbox& operator=(const msgbox&);
|
||||
|
||||
/// Construct that creates a message box with a specified title and default button.
|
||||
/// Constructor that creates a message box with a specified title and default button.
|
||||
msgbox(const ::std::string&);
|
||||
|
||||
/// Construct that creates a message box with an owner windoow, a specified title and buttons.
|
||||
/// Constructor that creates a message box with an owner window, a specified title and buttons.
|
||||
msgbox(window, const ::std::string&, button_t = ok);
|
||||
|
||||
/// Sets an icon for informing user.
|
||||
@ -73,7 +73,7 @@ namespace nana
|
||||
// Calls a manipulator to the stream.
|
||||
msgbox & operator<<(std::ostream& (*)(std::ostream&));
|
||||
|
||||
/// Write a streamizable object to the buffer.
|
||||
/// Write a streamable object to the buffer.
|
||||
template<typename T>
|
||||
msgbox & operator<<(const T& t)
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Definition of Notifier
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -59,7 +59,11 @@ namespace nana
|
||||
void text(const ::std::string&);
|
||||
void icon(const ::std::string& icon_file);
|
||||
void insert_icon(const ::std::string& icon_file);
|
||||
#if 0 //deprecated
|
||||
void period(unsigned millisecond);
|
||||
#else
|
||||
void period(std::chrono::milliseconds time);
|
||||
#endif
|
||||
detail::notifier_events& events();
|
||||
window handle() const;
|
||||
private:
|
||||
|
||||
@ -73,7 +73,7 @@ namespace nana
|
||||
std::function<void(Widget&)> init_;
|
||||
};
|
||||
|
||||
/// Layout managment - an object of class place is attached to a widget, and it automatically positions and resizes the children widgets.
|
||||
/// Layout management - an object of class place is attached to a widget, and it automatically positions and resizes the children widgets.
|
||||
class place
|
||||
: ::nana::noncopyable
|
||||
{
|
||||
|
||||
@ -108,7 +108,7 @@ namespace API
|
||||
bool copy_transparent_background(window, paint::graphics&);
|
||||
bool copy_transparent_background(window, const rectangle& src_r, paint::graphics&, const point& dst_pt);
|
||||
|
||||
/// Refreshs a widget surface
|
||||
/// Refreshes a widget surface
|
||||
/*
|
||||
* This function will copy the drawer surface into system window after the event process finished.
|
||||
*/
|
||||
@ -186,13 +186,13 @@ namespace API
|
||||
void exit(); ///< close all windows in current thread
|
||||
void exit_all(); ///< close all windows
|
||||
|
||||
/// @brief Searchs whether the text contains a '&' and removes the character for transforming.
|
||||
/// If the text contains more than one '&' charachers, the others are ignored. e.g
|
||||
/// @brief Searches whether the text contains a '&' and removes the character for transforming.
|
||||
/// If the text contains more than one '&' characters, the others are ignored. e.g
|
||||
/// text = "&&a&bcd&ef", the result should be "&abcdef", shortkey = 'b', and pos = 2.
|
||||
std::string transform_shortkey_text
|
||||
( std::string text, ///< the text is transformed
|
||||
wchar_t &shortkey, ///< the character which indicates a short key.
|
||||
std::string::size_type *skpos ///< retrives the shortkey position if it is not a null_ptr;
|
||||
std::string::size_type *skpos ///< retrieves the shortkey position if it is not a null_ptr;
|
||||
);
|
||||
bool register_shortkey(window, unsigned long);
|
||||
void unregister_shortkey(window);
|
||||
@ -344,11 +344,11 @@ namespace API
|
||||
|
||||
/// Refresh the window and display it immediately calling the refresh function of its drawer_trigger.
|
||||
/*
|
||||
* The drawer::refresh() will be called. If the currently state is lazy_refrsh, the window is delayed to update the graphics until an event is finished.
|
||||
* The drawer::refresh() will be called. If the current state is lazy_refrsh, the window is delayed to update the graphics until an event is finished.
|
||||
* @param window_handle A handle to the window to be refreshed.
|
||||
*/
|
||||
void refresh_window(window window_handle);
|
||||
void refresh_window_tree(window); ///< Refreshes the specified window and all its children windows, then display it immediately
|
||||
void refresh_window_tree(window); ///< Refreshes the specified window and all its children windows, then displays it immediately
|
||||
void update_window(window); ///< Copies the off-screen buffer to the screen for immediate display.
|
||||
|
||||
void window_caption(window, const std::string& title_utf8);
|
||||
@ -418,8 +418,8 @@ namespace API
|
||||
/// Enables or disables a window to receive a key_char event for pressing TAB key.
|
||||
/*
|
||||
* @param window_handle A handle to the window to catch TAB key through key_char event.
|
||||
* @param enable Indicates whether to enable or disable catch of TAB key. If this parameter is *true*, the window is
|
||||
* received a key_char when pressing TAB key, and the input focus is not changed. If this parameter is *false*, the
|
||||
* @param enable Indicates whether to enable or disable catch of TAB key. If this parameter is *true*, the window
|
||||
* receives a key_char event when pressing TAB key, and the input focus is not changed. If this parameter is *false*, the
|
||||
* input focus is changed to the next tabstop window.
|
||||
*/
|
||||
void eat_tabstop(window window_handle, bool enable);
|
||||
@ -432,7 +432,7 @@ namespace API
|
||||
*/
|
||||
window move_tabstop(window window_handle, bool forward);
|
||||
|
||||
/// Sets the window active state. If a window active state is false, the window will not obtain the focus when a mouse clicks on it wich will be obteined by take_if_has_active_false.
|
||||
/// Sets the window active state. If a window active state is false, the window will not obtain the focus when a mouse clicks on it which will be obtained by take_if_has_active_false.
|
||||
void take_active(window, bool has_active, window take_if_has_active_false);
|
||||
|
||||
/// Copies the graphics of a specified to a new graphics object.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Timer Implementation
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -9,8 +9,10 @@
|
||||
* @file: nana/gui/timer.hpp
|
||||
* @description:
|
||||
* A timer can repeatedly call a piece of code. The duration between
|
||||
* calls is specified in milliseconds. Timer is defferent from other graphics
|
||||
* calls is specified in milliseconds. Timer is different from other graphics
|
||||
* controls, it has no graphics interface.
|
||||
*
|
||||
* @contributors: rbrugo(#417)
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_TIMER_HPP
|
||||
@ -38,7 +40,16 @@ namespace nana
|
||||
timer& operator=(timer&&) = delete;
|
||||
public:
|
||||
timer();
|
||||
#if 0 //deprecated
|
||||
[[deprecated("prefer a std::chrono::duration (like std::chrono::milliseconds) over "
|
||||
"raw integers for durations")]]
|
||||
timer(unsigned int ms) : timer{} { interval_(ms); } /// Accepts an initial interval in ms
|
||||
|
||||
template <typename Rep, typename Period> /// Accepts an initial interval in any chrono unit
|
||||
explicit timer(std::chrono::duration<Rep, Period> const & time) : timer{} { interval(time); }
|
||||
#else
|
||||
explicit timer(std::chrono::milliseconds ms);
|
||||
#endif
|
||||
~timer();
|
||||
|
||||
template<typename Function>
|
||||
@ -52,8 +63,30 @@ namespace nana
|
||||
bool started() const;
|
||||
void stop();
|
||||
|
||||
void interval(unsigned milliseconds); ///< Set the duration between calls (millisec ??)
|
||||
#if 0 //deprecated
|
||||
[[deprecated("prefer a std::chrono::duration (like std::chrono::milliseconds) over "
|
||||
"raw integers for durations")]]
|
||||
inline void interval(unsigned milliseconds) { interval_(milliseconds); }
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
inline void interval(std::chrono::duration<Rep, Period> const & time_interval) ///< Set the duration between calls, accepts std::chrono
|
||||
{
|
||||
_m_interval(static_cast<unsigned>(std::chrono::duration_cast<std::chrono::milliseconds>(time_interval).count()));
|
||||
}
|
||||
#else
|
||||
void interval(std::chrono::milliseconds ms);
|
||||
#endif
|
||||
|
||||
#if 0 //deprecated
|
||||
unsigned interval() const;
|
||||
#endif
|
||||
template <typename Duration = std::chrono::milliseconds>
|
||||
inline Duration interval() const
|
||||
{
|
||||
return std::chrono::duration_cast<Duration>(std::chrono::milliseconds{ _m_interval() });
|
||||
}
|
||||
private:
|
||||
unsigned _m_interval() const;
|
||||
private:
|
||||
nana::basic_event<arg_elapse> elapse_;
|
||||
implement * const impl_;
|
||||
|
||||
@ -115,7 +115,7 @@ namespace nana
|
||||
bool clear();
|
||||
|
||||
//splitstr
|
||||
//@brief: Sets the splitstr. If the parameter will be ingored if it is an empty string.
|
||||
//@brief: Sets the splitstr. If the parameter will be ignored if it is an empty string.
|
||||
void splitstr(const ::std::string&);
|
||||
const ::std::string& splitstr() const;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A CheckBox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -98,6 +98,7 @@ namespace drawerbase
|
||||
void transparent(bool value);
|
||||
bool transparent() const;
|
||||
};//end class checkbox
|
||||
|
||||
/// for managing checkboxs in radio mode
|
||||
class radio_group
|
||||
{
|
||||
@ -113,8 +114,28 @@ namespace drawerbase
|
||||
constexpr static const std::size_t npos = static_cast<std::size_t>(-1);
|
||||
~radio_group();
|
||||
void add(checkbox&);
|
||||
std::size_t checked() const; ///< Retrieves the index of the checkbox which is checked.
|
||||
|
||||
///< Retrieves the index of checked option. It returns radio_group::npos if no checkbox is checked.
|
||||
std::size_t checked() const;
|
||||
std::size_t size() const;
|
||||
|
||||
template<typename Function>
|
||||
void on_clicked(Function&& click_fn)
|
||||
{
|
||||
for (auto & e : ui_container_)
|
||||
{
|
||||
e.uiobj->events().click(std::move(click_fn));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
void on_checked(Function&& check_fn)
|
||||
{
|
||||
for (auto & e : ui_container_)
|
||||
{
|
||||
e.uiobj->events().checked(std::move(check_fn));
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<element_tag> ui_container_;
|
||||
};
|
||||
|
||||
@ -76,7 +76,7 @@ namespace nana
|
||||
|
||||
bool chose() const;
|
||||
nana::date read() const;
|
||||
void weekstr(unsigned index, ::std::string);///<Set the week strings which will be displayed for day, index is in range of [0, 6]
|
||||
void weekstr(unsigned index, ::std::string);///<Set the week strings which will be displayed for day, index is in the range of [0, 6]
|
||||
};
|
||||
}//end namespace nana
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Tree Container class implementation
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -193,6 +193,11 @@ namespace detail
|
||||
node_type* insert(const std::string& key, const element_type& elem)
|
||||
{
|
||||
auto node = _m_locate<true>(key);
|
||||
|
||||
//Doesn't return the root node
|
||||
if (node == &root_)
|
||||
return nullptr;
|
||||
|
||||
if(node)
|
||||
node->value.second = elem;
|
||||
return node;
|
||||
@ -206,12 +211,14 @@ namespace detail
|
||||
|
||||
node_type* find(const std::string& path) const
|
||||
{
|
||||
return _m_locate(path);
|
||||
auto p = _m_locate(path);
|
||||
return (&root_ == p ? nullptr : p);
|
||||
}
|
||||
|
||||
node_type* ref(const std::string& path)
|
||||
{
|
||||
return _m_locate<true>(path);
|
||||
auto p = _m_locate<true>(path);
|
||||
return (&root_ == p ? nullptr : p);
|
||||
}
|
||||
|
||||
unsigned indent_size(const node_type* node) const
|
||||
@ -479,42 +486,42 @@ namespace detail
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// foreach elements of key.
|
||||
// the root name "/" and "\\" are treated as a node. This is a feature that can easily support the UNIX-like path.
|
||||
template<typename Function>
|
||||
void _m_for_each(const ::std::string& key, Function function) const
|
||||
{
|
||||
if(key.size())
|
||||
//Ignores separaters at the begin of key.
|
||||
::std::string::size_type beg = key.find_first_not_of("\\/");
|
||||
if (key.npos == beg)
|
||||
return;
|
||||
|
||||
auto end = key.find_first_of("\\/", beg);
|
||||
|
||||
|
||||
while(end != ::std::string::npos)
|
||||
{
|
||||
::std::string::size_type beg = 0;
|
||||
auto end = key.find_first_of("\\/");
|
||||
|
||||
while(end != ::std::string::npos)
|
||||
if(beg != end)
|
||||
{
|
||||
if(beg != end)
|
||||
{
|
||||
if(!function(key.substr(beg, end - beg)))
|
||||
return;
|
||||
}
|
||||
|
||||
auto next = key.find_first_not_of("\\/", end);
|
||||
|
||||
if ((next == ::std::string::npos) && end)
|
||||
if(!function(key.substr(beg, end - beg)))
|
||||
return;
|
||||
|
||||
if (0 == end)
|
||||
{
|
||||
if ((!function(key.substr(0, 1))) || (next == ::std::string::npos))
|
||||
return;
|
||||
}
|
||||
|
||||
beg = next;
|
||||
end = key.find_first_of("\\/", beg);
|
||||
|
||||
}
|
||||
|
||||
function(key.substr(beg, key.size() - beg));
|
||||
auto next = key.find_first_not_of("\\/", end);
|
||||
|
||||
if ((next == ::std::string::npos) && end)
|
||||
return;
|
||||
|
||||
if (0 == end)
|
||||
{
|
||||
if ((!function(key.substr(0, 1))) || (next == ::std::string::npos))
|
||||
return;
|
||||
}
|
||||
|
||||
beg = next;
|
||||
end = key.find_first_of("\\/", beg);
|
||||
|
||||
}
|
||||
|
||||
function(key.substr(beg, key.size() - beg));
|
||||
}
|
||||
|
||||
template<bool CreateIfNotExists>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A float_listbox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -46,8 +46,10 @@ namespace nana
|
||||
class item_renderer
|
||||
{
|
||||
public:
|
||||
typedef widget& widget_reference;
|
||||
typedef paint::graphics& graph_reference;
|
||||
using widget_reference = widget&;
|
||||
using graph_reference = paint::graphics&;
|
||||
using item_interface = float_listbox::item_interface;
|
||||
|
||||
enum state_t{StateNone, StateHighlighted};
|
||||
|
||||
virtual ~item_renderer() = default;
|
||||
@ -91,7 +93,7 @@ namespace nana
|
||||
* @param window A handle to a window which is a owner of float_listbox
|
||||
* @param rectangle A position and a size of float_listbox
|
||||
* @param is_ignore_first_mouse_up The flost_listbox will be closed when a mouse_up is emitted, this parameter is specified for ignoring the first mouse_up emitting.
|
||||
* @remark The float_listbox can be popupped in a mouse_down event, the next mouse_up may be ignored, otherwise the float_listbox will be closed when user releases the button.
|
||||
* @remark The float_listbox can be pop-upped in a mouse_down event, the next mouse_up may be ignored, otherwise the float_listbox will be closed when user releases the button.
|
||||
*/
|
||||
float_listbox(window, const rectangle&, bool is_ignore_first_mouse_up);
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ namespace nana
|
||||
}//end namespace form
|
||||
}//end namespace drawerbase
|
||||
|
||||
/// \brief Pop-up window. Is different from other window widgets: its default constructor create the window.
|
||||
/// \brief Pop-up window. Is different from other window widgets: its default constructor creates the window.
|
||||
/// \see nana::appearance
|
||||
class form
|
||||
: public drawerbase::form::form_base
|
||||
|
||||
@ -55,12 +55,12 @@ namespace nana{
|
||||
/// The construction that creates the widget
|
||||
group(window parent, const rectangle& = {}, bool visible = true);
|
||||
|
||||
/// The construction that creates the widget and set the titel or caption
|
||||
/// The construction that creates the widget and set the title or caption
|
||||
|
||||
group(window parent, ///< a handle to the parent
|
||||
::std::string titel, ///< caption of the group
|
||||
::std::string title, ///< caption of the group
|
||||
bool formatted = false, ///< Enable/disable the formatted text for the title
|
||||
unsigned gap = 2, ///< betwen the content and the external limit
|
||||
unsigned gap = 2, ///< between the content and the external limit
|
||||
const rectangle& r = {} ,
|
||||
bool visible = true
|
||||
);
|
||||
|
||||
@ -651,7 +651,7 @@ namespace nana
|
||||
};
|
||||
|
||||
|
||||
/// usefull for both absolute and display (sorted) positions
|
||||
/// useful for both absolute and display (sorted) positions
|
||||
struct index_pair
|
||||
{
|
||||
constexpr static const size_type npos = ::nana::npos;
|
||||
@ -712,7 +712,7 @@ namespace nana
|
||||
|
||||
// struct essence
|
||||
//@brief: this struct gives many data for listbox,
|
||||
// the state of the struct does not effect on member funcions, therefore all data members are public.
|
||||
// the state of the struct does not effect on member functions, therefore all data members are public.
|
||||
struct essence;
|
||||
|
||||
class oresolver
|
||||
@ -806,7 +806,7 @@ namespace nana
|
||||
drawer_lister_impl *drawer_lister_;
|
||||
};//end class trigger
|
||||
|
||||
/// operate with absolute positions and contain only the position but montain pointers to parts of the real items
|
||||
/// operate with absolute positions and contain only the position but maintain pointers to parts of the real items
|
||||
/// item_proxy self, it references and iterators are not invalidated by sort()
|
||||
class item_proxy
|
||||
: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, item_proxy>
|
||||
@ -814,11 +814,11 @@ namespace nana
|
||||
public:
|
||||
item_proxy(essence*, const index_pair& = index_pair{npos, npos});
|
||||
|
||||
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
||||
/// the main purpose of this it to make obvious that item_proxy operate with absolute positions, and don't get moved during sort()
|
||||
static item_proxy from_display(essence *, const index_pair &relative) ;
|
||||
item_proxy from_display(const index_pair &relative) const;
|
||||
|
||||
/// posible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
||||
/// possible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
||||
index_pair to_display() const;
|
||||
|
||||
/// Determines whether the item is displayed on the screen
|
||||
@ -837,9 +837,9 @@ namespace nana
|
||||
/// Determines whether the item is checked
|
||||
bool checked() const;
|
||||
|
||||
/// Selects/unselects the item
|
||||
/// Selects/deselects the item
|
||||
/**
|
||||
* @param sel Indicates whether to select or unselect the item
|
||||
* @param sel Indicates whether to select or deselect the item
|
||||
* @param scroll_view Indicates whether to scroll the view to the item. It is ignored if the item is displayed.
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
@ -1176,7 +1176,7 @@ namespace nana
|
||||
{
|
||||
drawerbase::listbox::cat_proxy category;
|
||||
|
||||
/// A flag that indicates whether or not to block expension/shrink of category when it is double clicking.
|
||||
/// A flag that indicates whether or not to block expansion/shrink of category when it is double clicked.
|
||||
mutable bool block_operation{ false };
|
||||
|
||||
arg_listbox_category(const drawerbase::listbox::cat_proxy&) noexcept;
|
||||
@ -1189,7 +1189,7 @@ namespace nana
|
||||
struct listbox_events
|
||||
: public general_events
|
||||
{
|
||||
/// An envent occurs when the toggle of a listbox item is checked.
|
||||
/// An event occurs when the toggle of a listbox item is checked.
|
||||
basic_event<arg_listbox> checked;
|
||||
|
||||
/// An event occurs when a listbox item is clicked.
|
||||
@ -1244,8 +1244,8 @@ By \a clicking on one header the list get \a reordered, first up, and then down
|
||||
|
||||
1. The resolver is used to resolute an object of the specified type into (or back from) a listbox item.
|
||||
3. nana::listbox creates the category 0 by default.
|
||||
This is an special category, becouse it is invisible, while the associated items are visible.
|
||||
The optional, user-created categories begin at index 1 and are visibles.
|
||||
This is an special category, because it is invisible, while the associated items are visible.
|
||||
The optional, user-created categories begin at index 1 and are visible.
|
||||
The member functions without the categ parameter operate the items that belong to category 0.
|
||||
4. A sort compare is used for sorting the items. It is a strict weak ordering comparer that must meet the requirement:
|
||||
Irreflexivity (comp(x, x) returns false)
|
||||
@ -1276,15 +1276,15 @@ By \a clicking on one header the list get \a reordered, first up, and then down
|
||||
cat.at(0).value(10); //10 is custom data.
|
||||
cat.at(1).value(20); //20 is custom data.
|
||||
5. listbox is a widget_object, with template parameters drawerbase::listbox::trigger and drawerbase::listbox::scheme
|
||||
amon others.
|
||||
That means that listbox have a member trigger_ constructed first and accecible with get_drawer_trigger() and
|
||||
a member (unique pointer to) scheme_ accesible with scheme_type& scheme() created in the constructor
|
||||
among others.
|
||||
That means that listbox have a member trigger_ constructed first and accessible with get_drawer_trigger() and
|
||||
a member (unique pointer to) scheme_ accessible with scheme_type& scheme() created in the constructor
|
||||
with API::dev::make_scheme<Scheme>() which call API::detail::make_scheme(::nana::detail::scheme_factory<Scheme>())
|
||||
which call restrict::bedrock.make_scheme(static_cast<::nana::detail::scheme_factory_base&&>(factory));
|
||||
which call pi_data_->scheme.create(std::move(factory));
|
||||
which call factory.create(scheme_template(std::move(factory)));
|
||||
which call (new Scheme(static_cast<Scheme&>(other)));
|
||||
and which in create is setted with: API::dev::set_scheme(handle_, scheme_.get()); which save the scheme pointer in
|
||||
and which in create is set with: API::dev::set_scheme(handle_, scheme_.get()); which save the scheme pointer in
|
||||
the nana::detail::basic_window member pointer scheme
|
||||
\todo doc: actualize this example listbox.at(0)...
|
||||
\see nana::drawerbase::listbox::cat_proxy
|
||||
@ -1426,7 +1426,7 @@ the nana::detail::basic_window member pointer scheme
|
||||
/// Scrolls the view to the first or last item of a specified category
|
||||
void scroll(bool to_bottom, size_type cat_pos = ::nana::npos);
|
||||
|
||||
/// Scrolls the view to show an item sepcified by absolute position at top/bottom of the listbox.
|
||||
/// Scrolls the view to show an item specified by absolute position at top/bottom of the listbox.
|
||||
void scroll(bool to_bottom, const index_pair& abs_pos);
|
||||
|
||||
/// Appends a new column with a header text and the specified width at the end, and return it position
|
||||
@ -1532,11 +1532,11 @@ the nana::detail::basic_window member pointer scheme
|
||||
std::function<bool(const std::string&, nana::any*,
|
||||
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||
|
||||
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
/// sort() and invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void sort_col(size_type col, bool reverse = false);
|
||||
size_type sort_col() const;
|
||||
|
||||
/// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
/// potentially invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void unsort();
|
||||
bool freeze_sort(bool freeze);
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ namespace nana
|
||||
}//end namespace menubar
|
||||
}//end namespace drawerbase
|
||||
|
||||
/// \brief A toolbar at the top of window for popuping menus.
|
||||
/// \brief A toolbar at the top of window for pop-upping menus.
|
||||
///
|
||||
/// The widget sets as shortkey the character behind the first of & in the text, for the item. e.g. "File(&F)" or "&File".
|
||||
class menubar
|
||||
@ -79,7 +79,7 @@ namespace nana
|
||||
|
||||
/// Deselects the menu
|
||||
/**
|
||||
* If a menu is popped up, the menu deselects the item and close the popuped menu.
|
||||
* If a menu is popped up, the menu deselects the item and close the pop-upped menu.
|
||||
* @return true if an item is deselected, false otherwise.
|
||||
*/
|
||||
bool cancel();
|
||||
|
||||
@ -34,7 +34,7 @@ namespace nana
|
||||
};
|
||||
}// end namespace panel
|
||||
}//end namespace drawerbase
|
||||
/// For placing other widgets, where the bool template parameter determinte if it is widget or lite_widget, wich in actual use make no difference.
|
||||
/// For placing other widgets, where the bool template parameter determines if it is widget or lite_widget, which in actual use makes no difference.
|
||||
template<bool HasBackground>
|
||||
class panel
|
||||
: public widget_object<typename std::conditional<HasBackground, category::widget_tag, category::lite_widget_tag>::type,
|
||||
|
||||
@ -59,10 +59,10 @@ namespace nana
|
||||
/// Enables the image to be stretched to the widget size.
|
||||
void stretchable(unsigned left, unsigned top, unsigned right, unsigned bottom);
|
||||
|
||||
/// Enables/disable the image to be stretched without changing aspect ratio.
|
||||
/// Enables/disables the image to be stretched without changing aspect ratio.
|
||||
void stretchable(bool);
|
||||
|
||||
/// Fills a gradual-change color in background. If One of colors is invisible or clr_from is equal to clr_to, it draws background in bgcolor.
|
||||
/// Fills a gradual-change color in background. If one of colors is invisible or clr_from is equal to clr_to, it draws background in bgcolor.
|
||||
void set_gradual_background(const color& clr_from, const color& clr_to, bool horizontal);
|
||||
void transparent(bool);
|
||||
bool transparent() const;
|
||||
|
||||
@ -47,8 +47,8 @@ namespace nana
|
||||
};
|
||||
}
|
||||
}//end namespace drawerbase
|
||||
/// \brief A progressbar widget with two styles: know, and unknow amount value (goal).
|
||||
/// In unknow style the amount is ignored and the bar is scrolled when value change.
|
||||
/// \brief A progressbar widget with two styles: know, and unknown amount value (goal).
|
||||
/// In unknown style the amount is ignored and the bar is scrolled when value change.
|
||||
class progress
|
||||
: public widget_object<category::widget_tag, drawerbase::progress::trigger, ::nana::general_events, drawerbase::progress::scheme>
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Scroll Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -51,14 +51,14 @@ namespace nana
|
||||
using size_type = std::size_t;
|
||||
|
||||
size_type peak; ///< the whole total
|
||||
size_type range; ///< how many is shonw on a page, that is, How many to scroll after click on first or second
|
||||
size_type range; ///< how many is shown on a page, that is, How many to scroll after click on first or second
|
||||
size_type step; ///< how many to scroll by click in forward or backward
|
||||
size_type value; ///< current offset calculated from the very beginnig
|
||||
size_type value; ///< current offset calculated from the very beginning
|
||||
|
||||
buttons what;
|
||||
bool pressed;
|
||||
size_type scroll_length; ///< the lenght in pixels of the central button show how many of the total (peak) is shonw (range)
|
||||
int scroll_pos; ///< in pixels, and correspond to the offsset from the very beginning (value)
|
||||
size_type scroll_length; ///< the length in pixels of the central button show how many of the total (peak) is shown (range)
|
||||
int scroll_pos; ///< in pixels, and correspond to the offset from the very beginning (value)
|
||||
int scroll_mouse_offset;
|
||||
|
||||
metrics_type();
|
||||
@ -258,7 +258,7 @@ namespace nana
|
||||
case buttons::first:
|
||||
case buttons::second:
|
||||
make_step(drawer_.metrics.what == buttons::second, 1);
|
||||
timer_.interval(1000);
|
||||
timer_.interval(std::chrono::seconds{1});
|
||||
timer_.start();
|
||||
break;
|
||||
case buttons::scroll:
|
||||
@ -321,7 +321,7 @@ namespace nana
|
||||
{
|
||||
make_step(drawer_.metrics.what == buttons::second, 1);
|
||||
API::refresh_window(widget_->handle());
|
||||
timer_.interval(100);
|
||||
timer_.interval(std::chrono::milliseconds{ 100 });
|
||||
}
|
||||
private:
|
||||
::nana::scroll<Vertical> * widget_;
|
||||
@ -348,13 +348,13 @@ namespace nana
|
||||
|
||||
virtual void amount(size_type peak) = 0;
|
||||
|
||||
/// Get the range of the widget (how many is shonw on a page, that is, How many to scroll after click on first or second)
|
||||
/// Get the range of the widget (how many is shown on a page, that is, How many to scroll after click on first or second)
|
||||
virtual size_type range() const = 0;
|
||||
|
||||
/// Set the range of the widget.
|
||||
virtual void range(size_type r) = 0;
|
||||
|
||||
/// \brief Get the value (current offset calculated from the very beginnig)
|
||||
/// \brief Get the value (current offset calculated from the very beginning)
|
||||
/// @return the value.
|
||||
virtual size_type value() const = 0;
|
||||
|
||||
@ -371,7 +371,7 @@ namespace nana
|
||||
/// @param s a value for step.
|
||||
virtual void step(size_type s) = 0;
|
||||
|
||||
/// \brief Increase/decrease values by a step (alternativelly by some number of steps).
|
||||
/// \brief Increase/decrease values by a step (alternatively by some number of steps).
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the value is changed.
|
||||
virtual bool make_step(bool forward, unsigned steps = 1) = 0;
|
||||
@ -426,7 +426,7 @@ namespace nana
|
||||
return this->get_drawer_trigger().peak(peak);
|
||||
}
|
||||
|
||||
/// Get the range of the widget (how many is shonw on a page, that is, How many to scroll after click on first or second)
|
||||
/// Get the range of the widget (how many is shown on a page, that is, How many to scroll after click on first or second)
|
||||
size_type range() const override
|
||||
{
|
||||
return this->get_drawer_trigger().metrics().range;
|
||||
@ -438,7 +438,7 @@ namespace nana
|
||||
return this->get_drawer_trigger().range(r);
|
||||
}
|
||||
|
||||
/// \brief Get the value (current offset calculated from the very beginnig)
|
||||
/// \brief Get the value (current offset calculated from the very beginning)
|
||||
/// @return the value.
|
||||
size_type value() const override
|
||||
{
|
||||
@ -466,7 +466,7 @@ namespace nana
|
||||
return this->get_drawer_trigger().step(s);
|
||||
}
|
||||
|
||||
/// \brief Increase/decrease values by a step (alternativelly by some number of steps).
|
||||
/// \brief Increase/decrease values by a step (alternatively by some number of steps).
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the value is changed.
|
||||
bool make_step(bool forward, unsigned steps = 1) override
|
||||
@ -486,7 +486,7 @@ namespace nana
|
||||
|
||||
/// \brief Increase/decrease values by steps as if it is scrolled through mouse wheel.
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the vlaue is changed.
|
||||
/// @return true if the value is changed.
|
||||
bool make_scroll(bool forward)
|
||||
{
|
||||
return this->make_step(forward, 3); // set this 3 in the metrics of the widget scheme ?
|
||||
@ -494,7 +494,7 @@ namespace nana
|
||||
|
||||
/// \brief Increase/decrease values by a page as if it is scrolled page up.
|
||||
/// @param forward it determines whether increase or decrease.
|
||||
/// @return true if the vlaue is changed.
|
||||
/// @return true if the value is changed.
|
||||
bool make_page_scroll(bool forward)
|
||||
{
|
||||
auto const count = range() / step();
|
||||
|
||||
@ -134,7 +134,7 @@ namespace nana
|
||||
}//end namespace drawerbase
|
||||
|
||||
|
||||
/// A slider widget wich the user can drag for tracking
|
||||
/// A slider widget which the user can drag for tracking
|
||||
class slider
|
||||
: public widget_object<category::widget_tag, drawerbase::slider::trigger, drawerbase::slider::slider_events, drawerbase::slider::scheme_impl>
|
||||
{
|
||||
|
||||
@ -86,7 +86,7 @@ namespace nana
|
||||
spinbox(window, const nana::rectangle& = {}, bool visible = true);
|
||||
|
||||
/// Sets the widget whether it accepts user keyboard input.
|
||||
/// @param accept Set to indicate whether it accepts uesr keyboard input.
|
||||
/// @param accept Set to indicate whether it accepts user keyboard input.
|
||||
void editable(bool accept);
|
||||
|
||||
/// Determines whether the widget accepts user keyboard input.
|
||||
@ -103,10 +103,10 @@ namespace nana
|
||||
std::pair<int, int> range_int() const;
|
||||
std::pair<double, double> range_double() const;
|
||||
|
||||
/// Selects/unselects the text
|
||||
/// Selects/Deselects the text
|
||||
void select(bool);
|
||||
|
||||
/// Gets the spined value
|
||||
/// Gets the spun value
|
||||
::std::string value() const;
|
||||
void value(const ::std::string&);
|
||||
int to_int() const;
|
||||
|
||||
@ -328,7 +328,7 @@ namespace nana
|
||||
tabbar& append(std::wstring text, window attach_wd, value_type value = {})
|
||||
{
|
||||
if (attach_wd && API::empty_window(attach_wd))
|
||||
throw std::invalid_argument("Appening a tab to a tabbar - error: tabbar.attach: invalid window handle");
|
||||
throw std::invalid_argument("Appending a tab to a tabbar - error: tabbar.attach: invalid window handle");
|
||||
|
||||
this->get_drawer_trigger().insert(::nana::npos, to_nstring(std::move(text)), std::move(value));
|
||||
if (attach_wd)
|
||||
@ -409,7 +409,7 @@ namespace nana
|
||||
this->get_drawer_trigger().text(pos, to_nstring(str));
|
||||
}
|
||||
|
||||
std::string text(std::size_t pos) const /// Returns a title of a specified item, If pos is invalid, the method trhows a std::out_of_range object.
|
||||
std::string text(std::size_t pos) const /// Returns a title of a specified item, If pos is invalid, the method throws a std::out_of_range object.
|
||||
{
|
||||
return to_utf8(this->get_drawer_trigger().text(pos));
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ namespace nana
|
||||
bool selected() const;
|
||||
bool get_selected_points(nana::upoint &a, nana::upoint &b) const;
|
||||
|
||||
/// Selects/unselects all text.
|
||||
/// Selects/Deselects all text.
|
||||
void select(bool);
|
||||
|
||||
void select_points(nana::upoint arg_a, nana::upoint arg_b);
|
||||
|
||||
@ -194,7 +194,7 @@ namespace nana
|
||||
bool empty() const;
|
||||
|
||||
/// \brief Return the distance between the ROOT node and this node.
|
||||
/// @return only available when emtpy() is false.
|
||||
/// @return only available when empty() is false.
|
||||
std::size_t level() const;
|
||||
|
||||
/// Return the check state
|
||||
@ -309,7 +309,7 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Undocumentated methods for internal use
|
||||
// Undocumented methods for internal use
|
||||
trigger::node_type * _m_node() const;
|
||||
private:
|
||||
nana::any& _m_value();
|
||||
@ -397,7 +397,7 @@ namespace nana
|
||||
|
||||
const nana::pat::cloneable<compset_placer_interface> & placer() const;
|
||||
|
||||
/// \brief Eanble the widget to be draws automatically when it is operated.
|
||||
/// \brief Enable the widget to be draws automatically when it is operated.
|
||||
///
|
||||
/// The treebox automatically redraws after certain operations, but,
|
||||
/// under some circumstances, it is good to disable the automatic drawing mode,
|
||||
@ -441,7 +441,7 @@ namespace nana
|
||||
/// If 'hovered' or 'expanded' are not set, it uses 'normal' state image for these 2 states.
|
||||
/// See also in [documentation](http://nanapro.org/en-us/help/widgets/treebox.htm)
|
||||
/// @param id The name of an icon scheme. If the name is not existing, it creates a new scheme for the name.
|
||||
/// @return The reference of node image scheme correspending with the specified id.
|
||||
/// @return The reference of node image scheme corresponding with the specified id.
|
||||
node_image_type& icon(const ::std::string& id);
|
||||
|
||||
void icon_erase(const ::std::string& id);
|
||||
@ -480,6 +480,8 @@ namespace nana
|
||||
*/
|
||||
void scroll_into_view(item_proxy item);
|
||||
|
||||
/// Gets the current hovered node.
|
||||
item_proxy hovered(bool exclude_expander) const;
|
||||
private:
|
||||
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ namespace nana
|
||||
|
||||
#ifdef NANA_AUTOMATIC_GUI_TESTING
|
||||
|
||||
/// @brief Take control of the GUI and optionaly automaticaly tests it.
|
||||
/// @brief Take control of the GUI and optionally automatically tests it.
|
||||
///
|
||||
/// @detail It transfers to nana the program flow control, which begin pumping messages
|
||||
/// from the underlying OS, interpreting and sending it with suitable arguments
|
||||
@ -71,10 +71,10 @@ namespace nana
|
||||
void exec(
|
||||
unsigned wait = 1, ///< for the GUI to be constructed, in seconds
|
||||
unsigned wait_end = 1, ///< for the GUI to be destructed, in seconds
|
||||
std::function<void()> = {} ///< emit events to mimics user actions and may asert results
|
||||
std::function<void()> = {} ///< emit events to mimics user actions and may assert results
|
||||
);
|
||||
|
||||
/// send a click message to this widget - useffull in GUI testing
|
||||
/// send a click message to this widget - useful in GUI testing
|
||||
void click(widget& w);
|
||||
|
||||
/// in seconds
|
||||
|
||||
@ -99,7 +99,7 @@ namespace nana
|
||||
|
||||
//add
|
||||
//@brief: The add operation is successful if the name does not exist.
|
||||
// it does not replace the existing object by new object, becuase this
|
||||
// it does not replace the existing object by new object, because this
|
||||
// feature is thread safe and efficiency.
|
||||
template<typename ImageProcessor, typename Tag>
|
||||
void add(Tag & tag, const std::string& name)
|
||||
|
||||
@ -21,35 +21,35 @@
|
||||
#if defined(STD_NUMERIC_CONVERSIONS_NOT_SUPPORTED)
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::stoi in MinGW.
|
||||
//Workaround for no implementation of std::stoi in MinGW.
|
||||
int stoi(const std::string&, std::size_t * pos = nullptr, int base = 10);
|
||||
int stoi(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stof in MinGW.
|
||||
//Workaround for no implementation of std::stof in MinGW.
|
||||
float stof(const std::string&, std::size_t * pos = nullptr);
|
||||
float stof(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stod in MinGW.
|
||||
//Workaround for no implementation of std::stod in MinGW.
|
||||
double stod(const std::string&, std::size_t * pos = nullptr);
|
||||
double stod(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stold in MinGW.
|
||||
//Workaround for no implementation of std::stold in MinGW.
|
||||
long double stold(const std::string&, std::size_t * pos = nullptr);
|
||||
long double stold(const std::wstring&, std::size_t* pos = nullptr);
|
||||
|
||||
//Workaround for no implemenation of std::stol in MinGW.
|
||||
//Workaround for no implementation of std::stol in MinGW.
|
||||
long stol(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long stol(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoll in MinGW.
|
||||
//Workaround for no implementation of std::stoll in MinGW.
|
||||
long long stoll(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
long long stoll(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoul in MinGW.
|
||||
//Workaround for no implementation of std::stoul in MinGW.
|
||||
unsigned long stoul(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long stoul(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
|
||||
//Workaround for no implemenation of std::stoull in MinGW.
|
||||
//Workaround for no implementation of std::stoull in MinGW.
|
||||
unsigned long long stoull(const std::string&, std::size_t* pos = nullptr, int base = 10);
|
||||
unsigned long long stoull(const std::wstring&, std::size_t* pos = nullptr, int base = 10);
|
||||
}
|
||||
@ -58,7 +58,7 @@ namespace std
|
||||
#ifdef STD_TO_STRING_NOT_SUPPORTED
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::to_string/std::to_wstring in MinGW.
|
||||
//Workaround for no implementation of std::to_string/std::to_wstring in MinGW.
|
||||
std::string to_string(long double);
|
||||
std::string to_string(double);
|
||||
std::string to_string(unsigned);
|
||||
@ -131,7 +131,7 @@ namespace std {
|
||||
#include <string>
|
||||
namespace std
|
||||
{
|
||||
//Workaround for no implemenation of std::put_time in gcc < 5.
|
||||
//Workaround for no implementation of std::put_time in gcc < 5.
|
||||
/* std unspecified return type */
|
||||
//template< class CharT, class RTSTR >// let fail for CharT != char / wchar_t
|
||||
//RTSTR put_time(const std::tm* tmb, const CharT* fmt);
|
||||
|
||||
@ -100,7 +100,7 @@ namespace nana
|
||||
//Initializes the color with a CSS-like string
|
||||
//contributor: BigDave(mortis2007 at hotmail co uk)
|
||||
//date: February 3, 2015
|
||||
//maintainor: Jinhao, extended the support of CSS-spec
|
||||
//maintainer: Jinhao, extended the support of CSS-spec
|
||||
|
||||
color::color(std::string css_color)
|
||||
: a_(1.0)
|
||||
|
||||
@ -349,7 +349,7 @@ namespace nana
|
||||
virtual std::wstring&& wstr_move() = 0;
|
||||
};
|
||||
|
||||
/// playing with the idea - we need a mechanisme to set a user selected police - Testing an abtract interphase
|
||||
/// playing with the idea - we need a mechanism to set a user selected police - Testing an abstract interface
|
||||
struct encoding_error_police
|
||||
{
|
||||
virtual unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) = 0;
|
||||
@ -689,14 +689,14 @@ namespace nana
|
||||
}
|
||||
unsigned ch = *p;
|
||||
unsigned long code;
|
||||
if(ch < 0xC0) // error? - move to end. Posible ANSI or ISO code-page
|
||||
if(ch < 0xC0) // error? - move to end. Possible ANSI or ISO code-page
|
||||
{
|
||||
//return *(p++); // temp: assume equal
|
||||
//p = end;
|
||||
//return 0;
|
||||
return def_encoding_error_police->next_code_point(p, end);
|
||||
}
|
||||
else if(ch < 0xE0 && (p + 1 <= end)) // two byte chararcter
|
||||
else if(ch < 0xE0 && (p + 1 <= end)) // two byte character
|
||||
{
|
||||
code = ((ch & 0x1F) << 6) | (p[1] & 0x3F);
|
||||
p += 2;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @file: nana/depoly.cpp
|
||||
*
|
||||
* What follow are dependented on what defined in nana/config.hpp
|
||||
* What follows is dependent on what defined in nana/config.hpp
|
||||
*/
|
||||
|
||||
#include <nana/deploy.hpp>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
*
|
||||
* @file: nana/filesystem/filesystem.cpp
|
||||
* @description:
|
||||
* provide some interface for file managment
|
||||
* provide some interface for file management
|
||||
*/
|
||||
|
||||
#include <nana/filesystem/filesystem_ext.hpp>
|
||||
@ -225,8 +225,12 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
//Because of No wide character version of POSIX
|
||||
#if defined(NANA_POSIX)
|
||||
const char* separators = "/";
|
||||
const char separator = '/';
|
||||
const char* punt = ".";
|
||||
#else
|
||||
const wchar_t* separators = L"/\\";
|
||||
const char separator = '\\';
|
||||
const wchar_t* punt = L".";
|
||||
#endif
|
||||
|
||||
//class file_status
|
||||
@ -283,7 +287,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
path path::extension() const
|
||||
{
|
||||
// todo: make more globlal
|
||||
// todo: make more global
|
||||
#if defined(NANA_WINDOWS)
|
||||
auto SLorP=L"\\/.";
|
||||
auto P=L'.';
|
||||
@ -453,6 +457,22 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return{ pathstr_ };
|
||||
}
|
||||
|
||||
path path::stem() const
|
||||
{
|
||||
auto pos = pathstr_.find_last_of(separators);
|
||||
auto ext = pathstr_.find_last_of(punt);
|
||||
|
||||
if (pos == pathstr_.npos)
|
||||
pos = 0;
|
||||
else
|
||||
pos++;
|
||||
|
||||
if (ext == pathstr_.npos || ext < pos)
|
||||
return path(pathstr_.substr(pos));
|
||||
else
|
||||
return path(pathstr_.substr(pos, ext-pos));
|
||||
}
|
||||
|
||||
void path::clear() noexcept
|
||||
{
|
||||
pathstr_.clear();
|
||||
@ -550,6 +570,71 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
std::replace(str.begin(), str.end(), '\\', '/'); // uppss ... revise this !!!!!
|
||||
return to_utf8(str);
|
||||
}
|
||||
|
||||
path path::lexically_normal() const
|
||||
{
|
||||
if (pathstr_.empty())
|
||||
return *this;
|
||||
|
||||
std::vector<path> elements;
|
||||
path temp{ pathstr_ };
|
||||
while (!temp.empty())
|
||||
{
|
||||
elements.emplace_back(temp.filename());
|
||||
temp.remove_filename();
|
||||
}
|
||||
|
||||
auto start = elements.begin();
|
||||
auto last = elements.end();
|
||||
auto stop = last--;
|
||||
for (auto itr(start); itr != stop; ++itr)
|
||||
{
|
||||
// ignore "." except at start and last
|
||||
if (itr->native().size() == 1
|
||||
&& (itr->native())[0] == '.'
|
||||
&& itr != start
|
||||
&& itr != last) continue;
|
||||
|
||||
// ignore a name and following ".."
|
||||
if (!temp.empty()
|
||||
&& itr->native().size() == 2
|
||||
&& (itr->native())[0] == '.'
|
||||
&& (itr->native())[1] == '.') // dot dot
|
||||
{
|
||||
string_type lf(temp.filename().native());
|
||||
if (lf.size() > 0
|
||||
&& (lf.size() != 1
|
||||
|| (lf[0] != '.'
|
||||
&& (lf[0] != '/' && lf[0] != '\\')))
|
||||
&& (lf.size() != 2
|
||||
|| (lf[0] != '.'
|
||||
&& lf[1] != '.'
|
||||
# ifdef NANA_WINDOWS
|
||||
&& lf[1] != ':'
|
||||
# endif
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
temp.remove_filename();
|
||||
auto next = itr;
|
||||
if (temp.empty() && ++next != stop
|
||||
&& next == last && last->string() == ".")
|
||||
{
|
||||
temp /= ".";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
temp /= *itr;
|
||||
};
|
||||
|
||||
if (temp.empty())
|
||||
temp = ".";
|
||||
return temp;
|
||||
}
|
||||
|
||||
path & path::operator/=(const path& p)
|
||||
{
|
||||
if (p.empty())
|
||||
@ -1045,7 +1130,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
::fclose(stream);
|
||||
return bytes;
|
||||
}
|
||||
ec.assign(static_cast<int>(::errno), std::generic_category());
|
||||
ec.assign(static_cast<int>(errno), std::generic_category());
|
||||
#endif
|
||||
return static_cast<std::uintmax_t>(-1);
|
||||
}
|
||||
@ -1180,7 +1265,7 @@ namespace std
|
||||
return p; // p.is_absolute() is true
|
||||
}
|
||||
|
||||
path absolute(const path& p, std::error_code& err)
|
||||
path absolute(const path& p, std::error_code& /*err*/)
|
||||
{
|
||||
return absolute(p);
|
||||
}
|
||||
@ -1254,6 +1339,81 @@ namespace std
|
||||
{
|
||||
return canonical(p, &err);
|
||||
}
|
||||
|
||||
bool try_throw(int err_val, const path& p, std::error_code* ec, const char* message)
|
||||
{
|
||||
if (0 == err_val)
|
||||
{
|
||||
if (ec) ec->clear();
|
||||
}
|
||||
else
|
||||
{ //error
|
||||
if (nullptr == ec)
|
||||
throw (filesystem_error(
|
||||
message, p,
|
||||
error_code(err_val, generic_category())));
|
||||
else
|
||||
ec->assign(err_val, system_category());
|
||||
}
|
||||
return err_val != 0;
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p, std::error_code* err)
|
||||
{
|
||||
path head{ p };
|
||||
|
||||
std::error_code tmp_err;
|
||||
std::vector<path> elements;
|
||||
while (!head.empty())
|
||||
{
|
||||
auto head_status = status(head, tmp_err);
|
||||
|
||||
if (head_status.type() == file_type::unknown)
|
||||
{
|
||||
if (try_throw(static_cast<int>(errc::invalid_argument), head, err, "nana::filesystem::weakly_canonical"))
|
||||
return path{};
|
||||
}
|
||||
if (head_status.type() != file_type::not_found)
|
||||
break;
|
||||
|
||||
elements.emplace_back(head.filename());
|
||||
head.remove_filename();
|
||||
}
|
||||
|
||||
bool tail_has_dots = false;
|
||||
path tail;
|
||||
|
||||
for (auto & e : elements)
|
||||
{
|
||||
tail /= e;
|
||||
// for a later optimization, track if any dot or dot-dot elements are present
|
||||
if (e.native().size() <= 2
|
||||
&& e.native()[0] == '.'
|
||||
&& (e.native().size() == 1 || e.native()[1] == '.'))
|
||||
tail_has_dots = true;
|
||||
}
|
||||
|
||||
if (head.empty())
|
||||
return p.lexically_normal();
|
||||
head = canonical(head, tmp_err);
|
||||
if (try_throw(tmp_err.value(), head, err, "nana::filesystem::weakly_canonical"))
|
||||
return path();
|
||||
return tail.empty()
|
||||
? head
|
||||
: (tail_has_dots // optimization: only normalize if tail had dot or dot-dot element
|
||||
? (head / tail).lexically_normal()
|
||||
: head / tail);
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p)
|
||||
{
|
||||
return weakly_canonical(p, nullptr);
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p, std::error_code& err)
|
||||
{
|
||||
return weakly_canonical(p, &err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
||||
@ -1275,5 +1435,162 @@ namespace std
|
||||
}//end namespace filesystem
|
||||
}//end namespace std
|
||||
|
||||
#endif
|
||||
#else //NANA_USING_NANA_FILESYSTEM
|
||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
||||
|
||||
//Defines the functions that are not provided by experimental/filesystem
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801))
|
||||
|
||||
namespace detail
|
||||
{
|
||||
bool try_throw(int err_val, const path& p, std::error_code* ec, const char* message)
|
||||
{
|
||||
if (0 == err_val)
|
||||
{
|
||||
if (ec) ec->clear();
|
||||
}
|
||||
else
|
||||
{ //error
|
||||
if (nullptr == ec)
|
||||
throw (filesystem_error(
|
||||
message, p,
|
||||
error_code(err_val, generic_category())));
|
||||
else
|
||||
ec->assign(err_val, system_category());
|
||||
}
|
||||
return err_val != 0;
|
||||
}
|
||||
|
||||
path lexically_normal(path p)
|
||||
{
|
||||
if (p.empty())
|
||||
return p;
|
||||
|
||||
std::vector<path> elements;
|
||||
|
||||
while (!p.empty())
|
||||
{
|
||||
elements.emplace_back(p.filename());
|
||||
p.remove_filename();
|
||||
}
|
||||
|
||||
auto start = elements.begin();
|
||||
auto last = elements.end();
|
||||
auto stop = last--;
|
||||
for (auto itr(start); itr != stop; ++itr)
|
||||
{
|
||||
// ignore "." except at start and last
|
||||
if (itr->native().size() == 1
|
||||
&& (itr->native())[0] == '.'
|
||||
&& itr != start
|
||||
&& itr != last) continue;
|
||||
|
||||
// ignore a name and following ".."
|
||||
if (!p.empty()
|
||||
&& itr->native().size() == 2
|
||||
&& (itr->native())[0] == '.'
|
||||
&& (itr->native())[1] == '.') // dot dot
|
||||
{
|
||||
auto lf(p.filename().native());
|
||||
if (lf.size() > 0
|
||||
&& (lf.size() != 1
|
||||
|| (lf[0] != '.'
|
||||
&& (lf[0] != '/' && lf[0] != '\\')))
|
||||
&& (lf.size() != 2
|
||||
|| (lf[0] != '.'
|
||||
&& lf[1] != '.'
|
||||
# ifdef NANA_WINDOWS
|
||||
&& lf[1] != ':'
|
||||
# endif
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
p.remove_filename();
|
||||
auto next = itr;
|
||||
if (p.empty() && ++next != stop
|
||||
&& next == last && last->string() == ".")
|
||||
{
|
||||
p /= ".";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
p /= *itr;
|
||||
};
|
||||
|
||||
if (p.empty())
|
||||
p = ".";
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p, std::error_code* err)
|
||||
{
|
||||
path head{ p };
|
||||
|
||||
std::error_code tmp_err;
|
||||
std::vector<path> elements;
|
||||
while (!head.empty())
|
||||
{
|
||||
auto head_status = status(head, tmp_err);
|
||||
|
||||
if (head_status.type() == file_type::unknown)
|
||||
{
|
||||
if (detail::try_throw(static_cast<int>(errc::invalid_argument), head, err, "nana::filesystem::weakly_canonical"))
|
||||
return path{};
|
||||
}
|
||||
if (head_status.type() != file_type::not_found)
|
||||
break;
|
||||
|
||||
elements.emplace_back(head.filename());
|
||||
head.remove_filename();
|
||||
}
|
||||
|
||||
bool tail_has_dots = false;
|
||||
path tail;
|
||||
|
||||
for (auto & e : elements)
|
||||
{
|
||||
tail /= e;
|
||||
// for a later optimization, track if any dot or dot-dot elements are present
|
||||
if (e.native().size() <= 2
|
||||
&& e.native()[0] == '.'
|
||||
&& (e.native().size() == 1 || e.native()[1] == '.'))
|
||||
tail_has_dots = true;
|
||||
}
|
||||
|
||||
if (head.empty())
|
||||
return detail::lexically_normal(p);
|
||||
head = canonical(head, tmp_err);
|
||||
if (detail::try_throw(tmp_err.value(), head, err, "nana::filesystem::weakly_canonical"))
|
||||
return path();
|
||||
return tail.empty()
|
||||
? head
|
||||
: (tail_has_dots // optimization: only normalize if tail had dot or dot-dot element
|
||||
? detail::lexically_normal(head / tail)
|
||||
: head / tail);
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p)
|
||||
{
|
||||
return weakly_canonical(p, nullptr);
|
||||
}
|
||||
|
||||
path weakly_canonical(const path& p, std::error_code& err)
|
||||
{
|
||||
return weakly_canonical(p, &err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif //NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ namespace nana
|
||||
//struct frameset::impl
|
||||
struct frameset::impl
|
||||
{
|
||||
//Only list whos iterator would not invalided after a insertion.
|
||||
//Only list whose iterator would not be invalidated after an insertion.
|
||||
std::list<frame> frames;
|
||||
std::list<frame>::iterator this_frame;
|
||||
std::size_t pos_in_this_frame{ 0 };
|
||||
|
||||
@ -336,6 +336,43 @@ namespace nana
|
||||
flags.action = act;
|
||||
}
|
||||
|
||||
|
||||
bool basic_window::try_lazy_update(bool try_refresh)
|
||||
{
|
||||
if (drawer.graphics.empty())
|
||||
return true;
|
||||
|
||||
if (!this->root_widget->other.attribute.root->lazy_update)
|
||||
return false;
|
||||
|
||||
if (nullptr == effect.bground)
|
||||
{
|
||||
if (try_refresh)
|
||||
{
|
||||
flags.refreshing = true;
|
||||
drawer.refresh();
|
||||
flags.refreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = this->root_widget->other.attribute.root->update_requesters.cbegin(); i != this->root_widget->other.attribute.root->update_requesters.cend();)
|
||||
{
|
||||
auto req = *i;
|
||||
//Avoid redundancy, don't insert the window if it or its ancestor window already exist in the container.
|
||||
if ((req == this) || req->is_ancestor_of(this))
|
||||
return true;
|
||||
|
||||
//If there is a window which is a child or child's child of the window, remove it.
|
||||
if (this->is_ancestor_of(req))
|
||||
i = this->root_widget->other.attribute.root->update_requesters.erase(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
this->root_widget->other.attribute.root->update_requesters.push_back(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void basic_window::_m_init_pos_and_size(basic_window* parent, const rectangle& r)
|
||||
{
|
||||
pos_owner = pos_root = r.position();
|
||||
@ -390,7 +427,6 @@ namespace nana
|
||||
flags.ignore_menubar_focus = false;
|
||||
flags.ignore_mouse_focus = false;
|
||||
flags.space_click_enabled = false;
|
||||
flags.ignore_child_mapping = false;
|
||||
|
||||
visible = false;
|
||||
|
||||
@ -401,7 +437,7 @@ namespace nana
|
||||
extra_width = extra_height = 0;
|
||||
|
||||
//The window must keep its thread_id same as its parent if it is a child.
|
||||
//Otherwise, its root buffer would be mapped repeatly if it is in its parent thread.
|
||||
//Otherwise, its root buffer would be mapped repeatedly if it is in its parent thread.
|
||||
thread_id = nana::system::this_thread_id();
|
||||
if(agrparent && (thread_id != agrparent->thread_id))
|
||||
thread_id = agrparent->thread_id;
|
||||
|
||||
@ -641,13 +641,8 @@ namespace nana
|
||||
if (update_state::none == wd->other.upd_state)
|
||||
wd->other.upd_state = update_state::lazy;
|
||||
|
||||
auto ignore_mapping_value = wd->flags.ignore_child_mapping;
|
||||
wd->flags.ignore_child_mapping = true;
|
||||
|
||||
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
|
||||
|
||||
wd->flags.ignore_child_mapping = ignore_mapping_value;
|
||||
|
||||
bool good_wd = false;
|
||||
if(wd_manager().available(wd))
|
||||
{
|
||||
@ -658,10 +653,7 @@ namespace nana
|
||||
wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code));
|
||||
}
|
||||
else
|
||||
{
|
||||
wd_manager().map_requester(wd);
|
||||
wd->other.upd_state = update_state::none;
|
||||
}
|
||||
|
||||
good_wd = true;
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/gui/detail/window_layout.hpp>
|
||||
#include <nana/gui/detail/element_store.hpp>
|
||||
#include "inner_fwd_implement.hpp"
|
||||
#include <errno.h>
|
||||
@ -555,6 +556,27 @@ namespace detail
|
||||
context.is_alt_pressed = false;
|
||||
}
|
||||
|
||||
class window_proc_guard
|
||||
{
|
||||
public:
|
||||
window_proc_guard(detail::basic_window* wd) :
|
||||
root_wd_(wd)
|
||||
{
|
||||
root_wd_->other.attribute.root->lazy_update = true;
|
||||
}
|
||||
|
||||
~window_proc_guard()
|
||||
{
|
||||
if (!bedrock::instance().wd_manager().available(root_wd_))
|
||||
return;
|
||||
|
||||
root_wd_->other.attribute.root->lazy_update = false;
|
||||
root_wd_->other.attribute.root->update_requesters.clear();
|
||||
}
|
||||
private:
|
||||
detail::basic_window* const root_wd_;
|
||||
};
|
||||
|
||||
void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
|
||||
{
|
||||
typedef detail::bedrock::core_window_t core_window_t;
|
||||
@ -569,10 +591,13 @@ namespace detail
|
||||
|
||||
if(root_runtime)
|
||||
{
|
||||
auto msgwnd = root_runtime->window;
|
||||
auto const root_wd = root_runtime->window;
|
||||
auto msgwnd = root_wd;
|
||||
window_proc_guard wp_guard{ root_wd };
|
||||
|
||||
auto& context = *brock.get_thread_context(msgwnd->thread_id);
|
||||
|
||||
auto pre_event_window = context.event_window;
|
||||
auto const pre_event_window = context.event_window;
|
||||
auto pressed_wd = root_runtime->condition.pressed;
|
||||
auto pressed_wd_space = root_runtime->condition.pressed_by_space;
|
||||
auto hovered_wd = root_runtime->condition.hovered;
|
||||
@ -1190,6 +1215,15 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
if (wd_manager.available(root_wd) && root_wd->other.attribute.root->update_requesters.size())
|
||||
{
|
||||
for (auto wd : root_wd->other.attribute.root->update_requesters)
|
||||
{
|
||||
window_layout::paint(wd, window_layout::paint_operation::have_refreshed, false);
|
||||
wd_manager.map(wd, true);
|
||||
}
|
||||
}
|
||||
|
||||
root_runtime = wd_manager.root_runtime(native_window);
|
||||
if(root_runtime)
|
||||
{
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <nana/gui.hpp>
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/gui/detail/window_layout.hpp>
|
||||
#include <nana/gui/detail/element_store.hpp>
|
||||
#include <nana/gui/detail/color_schemes.hpp>
|
||||
#include "inner_fwd_implement.hpp"
|
||||
@ -37,6 +38,7 @@
|
||||
|
||||
#include "bedrock_types.hpp"
|
||||
|
||||
|
||||
typedef void (CALLBACK *win_event_proc_t)(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
|
||||
|
||||
namespace nana
|
||||
@ -214,7 +216,7 @@ namespace detail
|
||||
if(wd_manager().number_of_core_window())
|
||||
{
|
||||
std::string msg = "Nana.GUI detects a memory leaks in window_manager, " + std::to_string(wd_manager().number_of_core_window()) + " window(s) are not uninstalled.";
|
||||
std::cerr << msg; /// \todo add list of cations of open windows and if aut testin GUI do auto Ok after 2 sec.
|
||||
std::cerr << msg; /// \todo add list of cations of opening windows and if auto testing GUI do auto OK after 2 seconds.
|
||||
::MessageBoxA(0, msg.c_str(), ("Nana C++ Library"), MB_OK);
|
||||
}
|
||||
|
||||
@ -223,7 +225,7 @@ namespace detail
|
||||
}
|
||||
|
||||
|
||||
/// @brief increament the number of windows in the thread id
|
||||
/// @brief increment the number of windows in the thread id
|
||||
int bedrock::inc_window(thread_t tid)
|
||||
{
|
||||
//impl refers to the object of private_impl, the object is created when bedrock is creating.
|
||||
@ -592,7 +594,7 @@ namespace detail
|
||||
delete [] reinterpret_cast<wchar_t*>(wParam);
|
||||
return true;
|
||||
case nana::detail::messages::remote_thread_destroy_window:
|
||||
detail::native_interface::close_window(reinterpret_cast<native_window_type>(wd)); //The owner would be actived before the message has posted in current thread.
|
||||
detail::native_interface::close_window(reinterpret_cast<native_window_type>(wd)); //The owner would be activated before the message has posted in current thread.
|
||||
{
|
||||
internal_scope_guard sg;
|
||||
auto * thrd = bedrock.get_thread_context();
|
||||
@ -738,6 +740,27 @@ namespace detail
|
||||
return static_cast<wchar_t>(vkey);
|
||||
}
|
||||
|
||||
class window_proc_guard
|
||||
{
|
||||
public:
|
||||
window_proc_guard(detail::basic_window* wd) :
|
||||
root_wd_(wd)
|
||||
{
|
||||
root_wd_->other.attribute.root->lazy_update = true;
|
||||
}
|
||||
|
||||
~window_proc_guard()
|
||||
{
|
||||
if (!bedrock::instance().wd_manager().available(root_wd_))
|
||||
return;
|
||||
|
||||
root_wd_->other.attribute.root->lazy_update = false;
|
||||
root_wd_->other.attribute.root->update_requesters.clear();
|
||||
}
|
||||
private:
|
||||
detail::basic_window* const root_wd_;
|
||||
};
|
||||
|
||||
LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT window_proc_value = 0;
|
||||
@ -757,6 +780,7 @@ namespace detail
|
||||
bool def_window_proc = false;
|
||||
auto& context = *brock.get_thread_context();
|
||||
|
||||
auto const pre_event_window = context.event_window;
|
||||
auto pressed_wd = root_runtime->condition.pressed;
|
||||
auto pressed_wd_space = root_runtime->condition.pressed_by_space;
|
||||
auto hovered_wd = root_runtime->condition.hovered;
|
||||
@ -766,7 +790,10 @@ namespace detail
|
||||
pmdec.raw_param.wparam = wParam;
|
||||
|
||||
internal_scope_guard lock;
|
||||
auto msgwnd = root_runtime->window;
|
||||
auto const root_wd = root_runtime->window;
|
||||
auto msgwnd = root_wd;
|
||||
|
||||
window_proc_guard wp_guard{ root_wd };
|
||||
|
||||
switch (message)
|
||||
{
|
||||
@ -775,10 +802,7 @@ namespace detail
|
||||
{
|
||||
auto i = root_runtime->wpassoc->accel_commands.find(LOWORD(wParam));
|
||||
if (i != root_runtime->wpassoc->accel_commands.end())
|
||||
{
|
||||
auto fn = i->second;
|
||||
fn();
|
||||
}
|
||||
i->second();
|
||||
}
|
||||
break;
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
@ -896,8 +920,8 @@ namespace detail
|
||||
|
||||
//Don't take care about whether msgwnd is equal to the pressed_wd.
|
||||
//
|
||||
//pressed_wd will remains when opens a no-actived window in an mouse_down event(like combox popups the drop-list).
|
||||
//After the no-actived window is closed, the window doesn't respond to the mouse click other than pressed_wd.
|
||||
//pressed_wd will remain when opens a non-activated window in an mouse_down event(like combox popups the drop-list).
|
||||
//After the non-activated window is closed, the window doesn't respond to the mouse click other than pressed_wd.
|
||||
pressed_wd = nullptr;
|
||||
if (nullptr == msgwnd)
|
||||
break;
|
||||
@ -1092,7 +1116,9 @@ namespace detail
|
||||
//The focus window receives the message in Windows system, it should be redirected to the hovered window
|
||||
::POINT scr_pos{ pmdec.mouse.x, pmdec.mouse.y}; //Screen position
|
||||
auto pointer_wd = ::WindowFromPoint(scr_pos);
|
||||
if (pointer_wd == root_window)
|
||||
|
||||
//Ignore the message if the window is disabled.
|
||||
if ((pointer_wd == root_window) && ::IsWindowEnabled(root_window))
|
||||
{
|
||||
::ScreenToClient(pointer_wd, &scr_pos);
|
||||
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), { scr_pos.x, scr_pos.y });
|
||||
@ -1124,7 +1150,7 @@ namespace detail
|
||||
wd_manager.do_lazy_refresh(scrolled_wd, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (pointer_wd != root_window)
|
||||
{
|
||||
DWORD pid = 0;
|
||||
::GetWindowThreadProcessId(pointer_wd, &pid);
|
||||
@ -1330,7 +1356,7 @@ namespace detail
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if(msgwnd)
|
||||
{
|
||||
//Don't call default window proc to avoid popuping system menu.
|
||||
//Don't call default window proc to avoid pop-upping system menu.
|
||||
def_window_proc = false;
|
||||
|
||||
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
|
||||
@ -1416,8 +1442,8 @@ namespace detail
|
||||
if (msgwnd->root_widget->other.attribute.root->menubar == msgwnd)
|
||||
{
|
||||
//In order to keep the focus on the menubar, cancel the delay_restore
|
||||
//when pressing ESC to close the menu which is popuped by the menubar.
|
||||
//If no menu popuped by the menubar, it should enable delay restore to
|
||||
//when pressing ESC to close the menu which is pop-upped by the menubar.
|
||||
//If no menu pop-upped by the menubar, it should enable delay restore to
|
||||
//restore the focus for taken window.
|
||||
|
||||
int cmd = (menu_wd && (keyboard::escape == static_cast<wchar_t>(wParam)) ? 1 : 0);
|
||||
@ -1450,7 +1476,7 @@ namespace detail
|
||||
wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case WM_KEYUP:
|
||||
if(wParam != VK_MENU) //MUST NOT BE AN ALT
|
||||
{
|
||||
@ -1522,7 +1548,7 @@ namespace detail
|
||||
if (!arg.cancel)
|
||||
{
|
||||
def_window_proc = true;
|
||||
//Activate is owner, refer to the window_manager::close for the explaination
|
||||
//Activates its owner, refer to the window_manager::close for the explanation
|
||||
if (msgwnd->flags.modal || (msgwnd->owner == 0) || msgwnd->owner->flags.take_active)
|
||||
native_interface::activate_owner(msgwnd->root);
|
||||
}
|
||||
@ -1532,7 +1558,7 @@ namespace detail
|
||||
if (msgwnd->root == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore not decleared
|
||||
brock.delay_restore(3); //Restores if delay_restore not declared
|
||||
}
|
||||
wd_manager.destroy(msgwnd);
|
||||
nana::detail::platform_spec::instance().release_window_icon(msgwnd->root);
|
||||
@ -1551,13 +1577,28 @@ namespace detail
|
||||
def_window_proc = true;
|
||||
}
|
||||
|
||||
if (wd_manager.available(root_wd) && root_wd->other.attribute.root->update_requesters.size())
|
||||
{
|
||||
for (auto wd : root_wd->other.attribute.root->update_requesters)
|
||||
{
|
||||
window_layout::paint(wd, window_layout::paint_operation::have_refreshed, false);
|
||||
wd_manager.map(wd, true);
|
||||
}
|
||||
}
|
||||
|
||||
root_runtime = wd_manager.root_runtime(native_window);
|
||||
if(root_runtime)
|
||||
{
|
||||
context.event_window = pre_event_window;
|
||||
root_runtime->condition.pressed = pressed_wd;
|
||||
root_runtime->condition.hovered = hovered_wd;
|
||||
root_runtime->condition.pressed_by_space = pressed_wd_space;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto context = brock.get_thread_context();
|
||||
if(context) context->event_window = pre_event_window;
|
||||
}
|
||||
|
||||
if (!def_window_proc)
|
||||
return 0;
|
||||
@ -1578,7 +1619,7 @@ namespace detail
|
||||
delete passoc;
|
||||
}
|
||||
|
||||
//Generates an identitifer for an accel key.
|
||||
//Generates an identifier for an accel key.
|
||||
std::pair<int, WORD> id_accel_key(const accel_key& key)
|
||||
{
|
||||
std::pair<int, WORD> ret;
|
||||
|
||||
@ -33,99 +33,99 @@ namespace nana
|
||||
|
||||
void drawer_trigger::resizing(graph_reference, const arg_resizing&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::resizing));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::resizing));
|
||||
}
|
||||
|
||||
void drawer_trigger::resized(graph_reference graph, const arg_resized&)
|
||||
{
|
||||
overrided_ |= (1 << static_cast<int>(event_code::resized));
|
||||
overridden_ |= (1 << static_cast<int>(event_code::resized));
|
||||
this->refresh(graph);
|
||||
detail::bedrock::instance().thread_context_lazy_refresh();
|
||||
}
|
||||
|
||||
void drawer_trigger::move(graph_reference, const arg_move&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::move));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::move));
|
||||
}
|
||||
|
||||
void drawer_trigger::click(graph_reference, const arg_click&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::click));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::click));
|
||||
}
|
||||
|
||||
void drawer_trigger::dbl_click(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::dbl_click));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::dbl_click));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_enter));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_enter));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_move(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_move));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_move));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_leave));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_leave));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_down(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_down));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_down));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_up(graph_reference, const arg_mouse&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_up));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_up));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_wheel));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_wheel));
|
||||
}
|
||||
|
||||
void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_drop));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::mouse_drop));
|
||||
}
|
||||
|
||||
void drawer_trigger::focus(graph_reference, const arg_focus&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::focus));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::focus));
|
||||
}
|
||||
|
||||
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::key_press));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::key_press));
|
||||
}
|
||||
|
||||
void drawer_trigger::key_char(graph_reference, const arg_keyboard&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::key_char));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::key_char));
|
||||
}
|
||||
|
||||
void drawer_trigger::key_release(graph_reference, const arg_keyboard&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::key_release));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::key_release));
|
||||
}
|
||||
|
||||
void drawer_trigger::shortkey(graph_reference, const arg_keyboard&)
|
||||
{
|
||||
overrided_ &= ~(1 << static_cast<int>(event_code::shortkey));
|
||||
overridden_ &= ~(1 << static_cast<int>(event_code::shortkey));
|
||||
}
|
||||
|
||||
void drawer_trigger::_m_reset_overrided()
|
||||
void drawer_trigger::_m_reset_overridden()
|
||||
{
|
||||
overrided_ = 0xFFFFFFFF;
|
||||
overridden_ = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
bool drawer_trigger::_m_overrided(event_code evt_code) const
|
||||
bool drawer_trigger::_m_overridden(event_code evt_code) const
|
||||
{
|
||||
return 0 != (overrided_ & (1 << static_cast<int>(evt_code)));
|
||||
return 0 != (overridden_ & (1 << static_cast<int>(evt_code)));
|
||||
}
|
||||
|
||||
void drawer_trigger::filter_event(const event_code evt_code, const bool bDisabled)
|
||||
@ -396,7 +396,7 @@ namespace nana
|
||||
*i = method_state::pending;
|
||||
|
||||
data_impl_->realizer = &realizer;
|
||||
realizer._m_reset_overrided();
|
||||
realizer._m_reset_overridden();
|
||||
realizer.attached(wd, graphics);
|
||||
realizer.typeface_changed(graphics);
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ namespace nana{
|
||||
|
||||
|
||||
//The XMoveWindow and XMoveResizeWindow don't take effect if the specified window is
|
||||
//unmapped, and the members x and y of XSetSizeHints is obsoluted. So the position that
|
||||
//unmapped, and the members x and y of XSetSizeHints is obsoleted. So the position that
|
||||
//set to a unmapped windows should be kept and use the position when the window is mapped.
|
||||
std::map<Window, ::nana::point> exposed_positions; //locked by platform_scope_guard
|
||||
|
||||
@ -498,7 +498,7 @@ namespace nana{
|
||||
{
|
||||
if(nullptr == parent) return nullptr;
|
||||
#if defined(NANA_WINDOWS)
|
||||
HWND handle = ::CreateWindowEx(WS_EX_CONTROLPARENT, // Extended possibilites for variation
|
||||
HWND handle = ::CreateWindowEx(WS_EX_CONTROLPARENT, // Extended possibilities for variation
|
||||
L"NanaWindowInternal",
|
||||
L"Nana Child Window", // Title Text
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||
@ -703,7 +703,7 @@ namespace nana{
|
||||
::PostMessage(reinterpret_cast<HWND>(wd), nana::detail::messages::remote_thread_destroy_window, 0, 0);
|
||||
}
|
||||
#elif defined(NANA_X11)
|
||||
//Under X, XDestroyWindow destroys the specified window and generats a DestroyNotify
|
||||
//Under X, XDestroyWindow destroys the specified window and generates a DestroyNotify
|
||||
//event, when the client receives the event, the specified window has been already
|
||||
//destroyed. This is a feature which is different from Windows. So the following
|
||||
//works should be handled before calling XDestroyWindow.
|
||||
@ -711,7 +711,7 @@ namespace nana{
|
||||
if(wd == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore is not decleard
|
||||
brock.delay_restore(3); //Restores if delay_restore is not declared
|
||||
}
|
||||
|
||||
Display* disp = restrict::spec.open_display();
|
||||
|
||||
@ -88,7 +88,7 @@ namespace nana
|
||||
//read_visual_rectangle
|
||||
///@brief Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget,
|
||||
/// the visual rectangle is a rectangular block that a window should be displayed on screen.
|
||||
/// The result is a rectangle that is a visible area for its ancesters.
|
||||
/// The result is a rectangle that is a visible area for its ancestors.
|
||||
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual)
|
||||
{
|
||||
if (! wd->displayed()) return false;
|
||||
|
||||
@ -511,7 +511,7 @@ namespace detail
|
||||
if (impl_->wd_register.available(owner))
|
||||
{
|
||||
if (owner->flags.destroying)
|
||||
throw std::runtime_error("the specified owner is destoryed");
|
||||
throw std::runtime_error("the specified owner is destroyed");
|
||||
|
||||
native = owner->root_widget->root;
|
||||
r.x += owner->pos_root.x;
|
||||
@ -592,7 +592,7 @@ namespace detail
|
||||
brock.emit(event_code::unload, wd, arg, true, brock.get_thread_context());
|
||||
if (false == arg.cancel)
|
||||
{
|
||||
//Before close the window, its owner window should be actived, otherwise other window will be
|
||||
//Before close the window, its owner window should be activated, otherwise other window will be
|
||||
//activated due to the owner window is not enabled.
|
||||
if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active)
|
||||
native_interface::activate_owner(wd->root);
|
||||
@ -601,7 +601,7 @@ namespace detail
|
||||
{
|
||||
//Close should detach the drawer and send destroy signal to widget object.
|
||||
//Otherwise, when a widget object is been deleting in other thread by delete operator, the object will be destroyed
|
||||
//before the window_manager destroyes the window, and then, window_manager detaches the
|
||||
//before the window_manager destroys the window, and then, window_manager detaches the
|
||||
//non-existing drawer_trigger which is destroyed by destruction of widget. Crash!
|
||||
wd->drawer.detached();
|
||||
wd->widget_notifier->destroy();
|
||||
@ -701,19 +701,40 @@ namespace detail
|
||||
return true;
|
||||
}
|
||||
|
||||
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos)
|
||||
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos, bool ignore_captured)
|
||||
{
|
||||
if (nullptr == root)
|
||||
return nullptr;
|
||||
|
||||
if((false == attr_.capture.ignore_children) || (nullptr == attr_.capture.window) || (attr_.capture.window->root != root))
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
if (ignore_captured || (nullptr == attr_.capture.window))
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
auto rrt = root_runtime(root);
|
||||
if (rrt && _m_effective(rrt->window, pos))
|
||||
return _m_find(rrt->window, pos);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (attr_.capture.ignore_children)
|
||||
return attr_.capture.window;
|
||||
|
||||
auto rrt = root_runtime(root);
|
||||
if (rrt && _m_effective(rrt->window, pos))
|
||||
{
|
||||
auto target = _m_find(rrt->window, pos);
|
||||
|
||||
auto p = target;
|
||||
while (p)
|
||||
{
|
||||
if (p == attr_.capture.window)
|
||||
return target;
|
||||
p = p->parent;
|
||||
}
|
||||
}
|
||||
|
||||
return attr_.capture.window;
|
||||
}
|
||||
|
||||
@ -894,7 +915,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
//Before resiz the window, creates the new graphics
|
||||
//Before resizing the window, creates the new graphics
|
||||
paint::graphics graph;
|
||||
paint::graphics root_graph;
|
||||
if (category::flags::lite_widget != wd->other.category)
|
||||
@ -980,28 +1001,7 @@ namespace detail
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) && !wd->is_draw_through())
|
||||
{
|
||||
auto parent = wd->parent;
|
||||
while (parent)
|
||||
{
|
||||
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
|
||||
{
|
||||
auto top = parent;
|
||||
while(parent->parent)
|
||||
{
|
||||
parent = parent->parent;
|
||||
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
|
||||
top = parent;
|
||||
}
|
||||
|
||||
top->other.mapping_requester.push_back(wd);
|
||||
return;
|
||||
}
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
bedrock::instance().flush_surface(wd, forced, update_area);
|
||||
}
|
||||
}
|
||||
|
||||
//update
|
||||
@ -1028,8 +1028,11 @@ namespace detail
|
||||
{
|
||||
if (!wd->flags.refreshing)
|
||||
{
|
||||
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
|
||||
this->map(wd, forced, update_area);
|
||||
if (!wd->try_lazy_update(redraw))
|
||||
{
|
||||
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
|
||||
this->map(wd, forced, update_area);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (forced)
|
||||
@ -1076,39 +1079,28 @@ namespace detail
|
||||
{
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refreshed) || (wd->other.upd_state == core_window_t::update_state::request_refresh) || force_copy_to_screen)
|
||||
{
|
||||
window_layer::paint(wd, (wd->other.upd_state == core_window_t::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree);
|
||||
this->map(wd, force_copy_to_screen);
|
||||
if (!wd->try_lazy_update(wd->other.upd_state == core_window_t::update_state::request_refresh))
|
||||
{
|
||||
window_layer::paint(wd, (wd->other.upd_state == core_window_t::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree);
|
||||
this->map(wd, force_copy_to_screen);
|
||||
}
|
||||
}
|
||||
else if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
{
|
||||
//The window is still mapped because of edge nimbus effect.
|
||||
//Avoid duplicate copy if action state is not changed and the window is not focused.
|
||||
if (wd->flags.action != wd->flags.action_before)
|
||||
this->map(wd, true);
|
||||
{
|
||||
if (!wd->try_lazy_update(false))
|
||||
this->map(wd, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
window_layer::paint(wd, paint_operation::try_refresh, refresh_tree); //only refreshing if it has an invisible parent
|
||||
}
|
||||
|
||||
wd->other.upd_state = core_window_t::update_state::none;
|
||||
wd->other.mapping_requester.clear();
|
||||
}
|
||||
|
||||
void window_manager::map_requester(core_window_t* wd)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
if (false == impl_->wd_register.available(wd))
|
||||
return;
|
||||
|
||||
if (wd->visible_parents())
|
||||
{
|
||||
for(auto requestor : wd->other.mapping_requester)
|
||||
this->map(requestor, true);
|
||||
}
|
||||
|
||||
wd->other.mapping_requester.clear();
|
||||
}
|
||||
|
||||
bool window_manager::set_parent(core_window_t* wd, core_window_t* newpa)
|
||||
@ -1191,7 +1183,7 @@ namespace detail
|
||||
//A fix by Katsuhisa Yuasa
|
||||
//The menubar token window will be redirected to the prev focus window when the new
|
||||
//focus window is a menubar.
|
||||
//The focus window will be restored to the prev focus which losts the focus becuase of
|
||||
//The focus window will be restored to the prev focus which losts the focus because of
|
||||
//memberbar.
|
||||
if (prev_focus && (wd == wd->root_widget->other.attribute.root->menubar))
|
||||
wd = prev_focus;
|
||||
@ -1302,7 +1294,7 @@ namespace detail
|
||||
|
||||
//enable_tabstop
|
||||
//@brief: when users press a TAB, the focus should move to the next widget.
|
||||
// this method insert a window which catchs an user TAB into a TAB window container
|
||||
// this method insert a window which catches an user TAB into a TAB window container
|
||||
// the TAB window container is held by a wd's root widget. Not every widget has a TAB window container,
|
||||
// the container is created while a first Tab Window is setting
|
||||
void window_manager::enable_tabstop(core_window_t* wd)
|
||||
@ -1728,7 +1720,7 @@ namespace detail
|
||||
|
||||
void window_manager::_m_move_core(core_window_t* wd, const point& delta)
|
||||
{
|
||||
if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its childs are not to be changed
|
||||
if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its children are not to be changed
|
||||
{
|
||||
wd->pos_root += delta;
|
||||
|
||||
|
||||
@ -1239,7 +1239,7 @@ namespace nana
|
||||
if(!child.empty())
|
||||
{
|
||||
child->icon("icon-folder");
|
||||
//The try-catch can be eleminated by using
|
||||
//The try-catch can be eliminated by using
|
||||
//directory_iterator( const std::filesystem::path& p, std::error_code& ec ) noexcept;
|
||||
//in C++17
|
||||
try
|
||||
@ -1359,7 +1359,7 @@ namespace nana
|
||||
path.resize(len);
|
||||
|
||||
impl_->path = to_utf8(path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1589,7 +1589,7 @@ namespace nana
|
||||
};
|
||||
|
||||
folderbox::folderbox(window owner, const path_type& init_path, std::string title)
|
||||
: impl_(new implement{ owner, fs::canonical(init_path).make_preferred(), title, false})
|
||||
: impl_(new implement{ owner, fs::weakly_canonical(init_path).make_preferred(), title, false})
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
namespace nana
|
||||
{
|
||||
//overlap test if overlaped between r1 and r2
|
||||
//overlap test if overlapped between r1 and r2
|
||||
bool overlapped(const rectangle& r1, const rectangle& r2)
|
||||
{
|
||||
if (r1.y + (long long)(r1.height) <= r2.y) return false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Message Box Class
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -453,7 +453,20 @@ namespace nana
|
||||
default: break;
|
||||
}
|
||||
|
||||
auto bt = ::MessageBoxW(reinterpret_cast<HWND>(API::root(wd_)), to_wstring(sstream_.str()).c_str(), to_wstring(title_).c_str(), type);
|
||||
//Disables the owner window to prevent the owner window processing mouse wheel event
|
||||
//when the message box is showing and scroll the wheel on the owner window.
|
||||
auto native = reinterpret_cast<HWND>(API::root(wd_));
|
||||
BOOL enabled = FALSE;
|
||||
if (native)
|
||||
{
|
||||
enabled = ::IsWindowEnabled(native);
|
||||
if (enabled)
|
||||
::EnableWindow(native, FALSE);
|
||||
}
|
||||
auto bt = ::MessageBoxW(native, to_wstring(sstream_.str()).c_str(), to_wstring(title_).c_str(), type);
|
||||
|
||||
if (native && enabled)
|
||||
::EnableWindow(native, TRUE);
|
||||
|
||||
switch(bt)
|
||||
{
|
||||
@ -745,7 +758,7 @@ namespace nana
|
||||
impl->label_text = std::move(label);
|
||||
}
|
||||
|
||||
//Instance for impl_ because implmenet is incomplete type at the point of declaration
|
||||
//Instance for impl_ because implement is incomplete type at the point of declaration
|
||||
inputbox::integer::~integer(){}
|
||||
|
||||
int inputbox::integer::value() const
|
||||
@ -828,7 +841,7 @@ namespace nana
|
||||
impl->label_text = std::move(label);
|
||||
}
|
||||
|
||||
//Instance for impl_ because implmenet is incomplete type at the point of declaration
|
||||
//Instance for impl_ because implement is incomplete type at the point of declaration
|
||||
inputbox::real::~real(){}
|
||||
|
||||
double inputbox::real::value() const
|
||||
@ -920,7 +933,7 @@ namespace nana
|
||||
impl_->label_text.swap(label);
|
||||
}
|
||||
|
||||
//Instance for impl_ because implmenet is incomplete type at the point of declaration
|
||||
//Instance for impl_ because implement is incomplete type at the point of declaration
|
||||
inputbox::text::~text(){}
|
||||
|
||||
void inputbox::text::tip_string(std::wstring tip)
|
||||
@ -1041,7 +1054,7 @@ namespace nana
|
||||
impl_->label_text.swap(label);
|
||||
}
|
||||
|
||||
//Instance for impl_ because implmenet is incomplete type at the point of declaration
|
||||
//Instance for impl_ because implement is incomplete type at the point of declaration
|
||||
inputbox::date::~date(){}
|
||||
|
||||
::std::string inputbox::date::value() const
|
||||
@ -1192,7 +1205,7 @@ namespace nana
|
||||
{
|
||||
}
|
||||
|
||||
//Instance for impl_ because implmenet is incomplete type at the point of declaration
|
||||
//Instance for impl_ because implement is incomplete type at the point of declaration
|
||||
inputbox::path::~path(){}
|
||||
|
||||
::std::string inputbox::path::value() const
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Implementation of Notifier
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -351,13 +351,14 @@ namespace nana
|
||||
#endif
|
||||
}
|
||||
|
||||
void notifier::period(unsigned ms)
|
||||
void notifier::period(std::chrono::milliseconds ms)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
if (ms && impl_->icons.size())
|
||||
if (ms.count() && impl_->icons.size())
|
||||
{
|
||||
ms /= static_cast<unsigned>(impl_->icons.size());
|
||||
impl_->ani_timer.interval(ms < 16 ? 16 : ms);
|
||||
auto frame_ms = (std::max)(ms.count() / static_cast<long long>(impl_->icons.size()), static_cast<long long>(16));
|
||||
|
||||
impl_->ani_timer.interval(std::chrono::milliseconds{frame_ms});
|
||||
impl_->ani_timer.start();
|
||||
}
|
||||
else
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An Implementation of Place for Layout
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -630,7 +630,8 @@ namespace nana
|
||||
void collocate();
|
||||
|
||||
static division * search_div_name(division* start, const std::string&) noexcept;
|
||||
std::unique_ptr<division> scan_div(place_parts::tokenizer&);
|
||||
|
||||
std::unique_ptr<division> scan_div(place_parts::tokenizer&, bool implicitly_started, const std::string& ignore_duplicate = {});
|
||||
void check_unique(const division*) const;
|
||||
|
||||
//connect the field/dock with div object
|
||||
@ -1987,7 +1988,7 @@ namespace nana
|
||||
|
||||
std::string::size_type tag_pos{ left ? div.find('<', bound.second + 2) : div.rfind('>', bound.first - 2) };
|
||||
if (div.npos == tag_pos)
|
||||
throw std::runtime_error("place report an issue if it throws");
|
||||
throw std::invalid_argument("please report an issue if it throws");
|
||||
|
||||
auto other_bound = get_field_boundary(div, tag_pos);
|
||||
|
||||
@ -2666,7 +2667,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
//Collocate doesn't sync the visiblity of fastened windows.
|
||||
//Collocate doesn't sync the visibility of fastened windows.
|
||||
//This is a feature that allows tabbar panels to be fastened to a same field, the collocate()
|
||||
//shouldn't break the visibility of panels that are maintained by tabbar.
|
||||
field.second->visible(is_show, false);
|
||||
@ -2706,7 +2707,9 @@ namespace nana
|
||||
throw std::invalid_argument("nana.place: the type of the " + std::string{pos_strs[pos]} +"th parameter for collapse should be integer.");
|
||||
}
|
||||
|
||||
auto place::implement::scan_div(place_parts::tokenizer& tknizer) -> std::unique_ptr<division>
|
||||
//implicitly_started indicates whether the field in div-text starts without < mark.
|
||||
//ignore_duplicate A field is allowed to have same name if its has an ancestor which name is same with ignore_duplicate.
|
||||
auto place::implement::scan_div(place_parts::tokenizer& tknizer, bool implicitly_started, const std::string& ignore_duplicate) -> std::unique_ptr<division>
|
||||
{
|
||||
using token = place_parts::tokenizer::token ;
|
||||
|
||||
@ -2728,7 +2731,8 @@ namespace nana
|
||||
bool undisplayed = false;
|
||||
bool invisible = false;
|
||||
|
||||
for (token tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
|
||||
token tk = token::eof;
|
||||
for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
|
||||
{
|
||||
switch (tk)
|
||||
{
|
||||
@ -2752,14 +2756,25 @@ namespace nana
|
||||
{
|
||||
auto splitter = new div_splitter(tknizer.number(), this);
|
||||
children.back()->div_next = splitter;
|
||||
|
||||
//Hides the splitter if its left leaf is undisplayed.
|
||||
if (!children.back()->display)
|
||||
splitter->display = false;
|
||||
|
||||
children.emplace_back(std::unique_ptr<division>{ splitter });
|
||||
}
|
||||
break;
|
||||
case token::div_start:
|
||||
{
|
||||
auto div = scan_div(tknizer);
|
||||
auto div = scan_div(tknizer, false, ignore_duplicate);
|
||||
if (!children.empty())
|
||||
{
|
||||
//Hides the splitter if its right leaf is undisplayed.
|
||||
if ((children.back()->kind_of_division == division::kind::splitter) && !div->display)
|
||||
children.back()->display = false;
|
||||
|
||||
children.back()->div_next = div.get();
|
||||
}
|
||||
|
||||
children.emplace_back(std::move(div));
|
||||
}
|
||||
@ -2887,6 +2902,9 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
if (implicitly_started && (tk == token::div_end))
|
||||
throw std::invalid_argument("nana.place: the div-text ends prematurely at " + std::to_string(tknizer.pos()));
|
||||
|
||||
field_gather * attached_field = nullptr;
|
||||
|
||||
//find the field with specified name.
|
||||
@ -2897,20 +2915,43 @@ namespace nana
|
||||
attached_field = i->second;
|
||||
//the field is attached to a division, it means there is another division with same name.
|
||||
if (attached_field->attached)
|
||||
throw std::runtime_error("place, the name '" + name + "' is redefined.");
|
||||
{
|
||||
//The fields are allowed to have a same name. E.g.
|
||||
//place.div("A <B><C>");
|
||||
//place.modify("A", "<B>"); Here the same name B must be allowed, otherwise it throws runtime error.
|
||||
|
||||
bool allow_same_name = false;
|
||||
if (!ignore_duplicate.empty())
|
||||
{
|
||||
auto f = attached_field->attached->div_owner;
|
||||
while (f)
|
||||
{
|
||||
if (f->name == ignore_duplicate)
|
||||
{
|
||||
allow_same_name = true;
|
||||
break;
|
||||
}
|
||||
|
||||
f = f->div_owner;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow_same_name)
|
||||
throw std::runtime_error("place, the name '" + name + "' is redefined.");
|
||||
}
|
||||
}
|
||||
|
||||
token unmatch = token::width;
|
||||
switch (div_type)
|
||||
{
|
||||
case token::eof: // "horitontal" div
|
||||
case token::eof: // "horizontal" div
|
||||
case token::vert: // "vertical" div
|
||||
if(token::eof == div_type)
|
||||
unmatch = token::height;
|
||||
|
||||
for (auto& ch : children)
|
||||
if (ch->weigth_type == unmatch)
|
||||
throw std::invalid_argument("nana.place: unmatch vertical-heigth/horizontal-width betwen division '"
|
||||
throw std::invalid_argument("nana.place: unmatch vertical-height/horizontal-width between division '"
|
||||
+name+"' and children division '" + ch->name);
|
||||
|
||||
div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange)));
|
||||
@ -2977,7 +3018,16 @@ namespace nana
|
||||
//attach the field to the division
|
||||
div->field = attached_field;
|
||||
if (attached_field)
|
||||
{
|
||||
//Replaces the previous div with the new div which is allowed to have a same name.
|
||||
|
||||
//Detaches the field from the previous div.
|
||||
if (attached_field->attached)
|
||||
attached_field->attached->field = nullptr;
|
||||
|
||||
//Attaches new div
|
||||
attached_field->attached = div.get();
|
||||
}
|
||||
|
||||
if (children.size())
|
||||
{
|
||||
@ -3033,7 +3083,7 @@ namespace nana
|
||||
void place::implement::check_unique(const division* div) const
|
||||
{
|
||||
//The second field_impl is useless. Reuse the map type in order to
|
||||
//reduce the size of the generated code, becuase std::set<std::string>
|
||||
//reduce the size of the generated code, because std::set<std::string>
|
||||
//will create a new template class.
|
||||
std::map<std::string, field_gather*> unique;
|
||||
field_gather tmp(nullptr);
|
||||
@ -3194,11 +3244,11 @@ namespace nana
|
||||
{
|
||||
place_parts::tokenizer tknizer(div_text.c_str());
|
||||
impl_->disconnect();
|
||||
auto div = impl_->scan_div(tknizer);
|
||||
auto div = impl_->scan_div(tknizer, true);
|
||||
try
|
||||
{
|
||||
impl_->connect(div.get()); //throws if there is a redefined name of field.
|
||||
impl_->root_division.reset(); //clear atachments div-fields
|
||||
impl_->root_division.reset(); //clear attachments div-fields
|
||||
impl_->root_division.swap(div);
|
||||
impl_->div_text.swap(div_text);
|
||||
}
|
||||
@ -3263,7 +3313,7 @@ namespace nana
|
||||
try
|
||||
{
|
||||
place_parts::tokenizer tknizer(div_text);
|
||||
auto modified = impl_->scan_div(tknizer);
|
||||
auto modified = impl_->scan_div(tknizer, true, name);
|
||||
auto modified_ptr = modified.get();
|
||||
modified_ptr->name = name;
|
||||
|
||||
@ -3322,7 +3372,7 @@ namespace nana
|
||||
if (div)
|
||||
{
|
||||
if (div->field && (div->field != p))
|
||||
throw std::runtime_error("nana.place: unexpected error, the division attachs a unexpected field.");
|
||||
throw std::runtime_error("nana.place: unexpected error, the division attaches an unexpected field.");
|
||||
|
||||
div->field = p;
|
||||
p->attached = div;
|
||||
|
||||
@ -262,7 +262,7 @@ namespace API
|
||||
iwd->drawer.graphics.make(iwd->dimension);
|
||||
iwd->drawer.graphics.rectangle(true, iwd->annex.scheme->background.get_color());
|
||||
iwd->drawer.attached(wd, dr);
|
||||
iwd->drawer.refresh(); //Always redrawe no matter it is visible or invisible. This can make the graphics data correctly.
|
||||
iwd->drawer.refresh(); //Always redraw no matter it is visible or invisible. This can make the graphics data correctly.
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,12 +456,12 @@ namespace API
|
||||
}
|
||||
|
||||
//transform_shortkey_text
|
||||
//@brief: This function searchs whether the text contains a '&' and removes the character for transforming.
|
||||
// If the text contains more than one '&' charachers, the others are ignored. e.g
|
||||
//@brief: This function searches whether the text contains a '&' and removes the character for transforming.
|
||||
// If the text contains more than one '&' character, the others are ignored. e.g
|
||||
// text = "&&a&bcd&ef", the result should be "&abcdef", shortkey = 'b', and pos = 2.
|
||||
//@param, text: the text is transformed.
|
||||
//@param, shortkey: the character which indicates a short key.
|
||||
//@param, skpos: retrives the shortkey position if it is not a null_ptr;
|
||||
//@param, skpos: retrieves the shortkey position if it is not a null_ptr;
|
||||
std::string transform_shortkey_text(std::string text, wchar_t &shortkey, std::string::size_type *skpos)
|
||||
{
|
||||
shortkey = 0;
|
||||
@ -1057,7 +1057,7 @@ namespace API
|
||||
else
|
||||
return;
|
||||
|
||||
//modal has to guarantee that does not lock the mutex of window_manager before invokeing the pump_event,
|
||||
//modal has to guarantee that does not lock the mutex of window_manager before invoking the pump_event,
|
||||
//otherwise, the modal will prevent the other thread access the window.
|
||||
restrict::bedrock.pump_event(wd, true);
|
||||
}
|
||||
@ -1403,7 +1403,7 @@ namespace API
|
||||
::nana::point clipos{pos};
|
||||
interface_type::calc_window_point(wd, clipos);
|
||||
return reinterpret_cast<window>(
|
||||
restrict::wd_manager().find_window(wd, clipos));
|
||||
restrict::wd_manager().find_window(wd, clipos, true));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Timer Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -10,7 +10,7 @@
|
||||
* @file: nana/gui/timer.hpp
|
||||
* @description:
|
||||
* A timer can repeatedly call a piece of code. The duration between
|
||||
* calls is specified in milliseconds. Timer is defferent from other graphics
|
||||
* calls is specified in milliseconds. Timer is different from other graphics
|
||||
* controls, it has no graphics interface.
|
||||
* @contributors: Benjamin Navarro(pr#81)
|
||||
*/
|
||||
@ -174,6 +174,12 @@ namespace nana
|
||||
: impl_(new implement)
|
||||
{
|
||||
}
|
||||
|
||||
timer::timer(std::chrono::milliseconds ms):
|
||||
timer()
|
||||
{
|
||||
this->interval(ms);
|
||||
}
|
||||
|
||||
timer::~timer()
|
||||
{
|
||||
@ -220,17 +226,17 @@ namespace nana
|
||||
timer_driver::instance().destroy(tmid);
|
||||
}
|
||||
|
||||
void timer::interval(unsigned ms)
|
||||
void timer::interval(std::chrono::milliseconds ms)
|
||||
{
|
||||
if (ms != impl_->interval)
|
||||
if (ms.count() != static_cast<long long>(impl_->interval))
|
||||
{
|
||||
impl_->interval = ms;
|
||||
impl_->interval = static_cast<unsigned>(ms.count());
|
||||
if (impl_->tm_core)
|
||||
impl_->tm_core->interval(ms);
|
||||
impl_->tm_core->interval(impl_->interval);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned timer::interval() const
|
||||
unsigned timer::_m_interval() const
|
||||
{
|
||||
return impl_->interval;
|
||||
}
|
||||
|
||||
@ -86,12 +86,12 @@ namespace nana
|
||||
timer_.reset();
|
||||
if (duration_)
|
||||
{
|
||||
timer_.interval(static_cast<unsigned>(duration_));
|
||||
timer_.interval(std::chrono::milliseconds{ duration_ });
|
||||
timer_.elapse(std::bind(&tip_form::_m_tick_duration, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
timer_.interval(500);
|
||||
timer_.interval(std::chrono::milliseconds{ 500 });
|
||||
timer_.elapse(std::bind(&tip_form::_m_tick, this));
|
||||
}
|
||||
timer_.start();
|
||||
|
||||
@ -446,7 +446,7 @@ namespace nana
|
||||
{
|
||||
r.width = i->value.second.pixels;
|
||||
//If the item is over the right border of widget, the item would be painted at
|
||||
//the begining of the next line.
|
||||
//the beginning of the next line.
|
||||
if(r.right() > xend)
|
||||
{
|
||||
r.x = xbase;
|
||||
@ -573,7 +573,7 @@ namespace nana
|
||||
|
||||
style_.listbox->events().destroy.connect_unignorable([this](const arg_destroy&)
|
||||
{
|
||||
//Close list when listbox is destoryed
|
||||
//Close list when listbox is destroyed
|
||||
style_.mode = mode::normal;
|
||||
style_.state = mouse_action::normal;
|
||||
|
||||
@ -646,7 +646,7 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
//Too many items, so some of items cann't be displayed
|
||||
//Too many items, so some of items can't be displayed
|
||||
r.x += 16;
|
||||
r.width -= 16;
|
||||
return r;
|
||||
@ -918,5 +918,5 @@ namespace nana
|
||||
}
|
||||
//end class trigger
|
||||
}//end namespace categorize
|
||||
}//end namespace draerbase
|
||||
}//end namespace drawerbase
|
||||
}//end namespace nana
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -293,7 +293,7 @@ namespace nana
|
||||
|
||||
//The lister window closes by itself. I just take care about the destroy event.
|
||||
//The event should be destroy rather than unload. Because the unload event is invoked while
|
||||
//the lister is not closed, if popuping a message box, the lister will cover the message box.
|
||||
//the lister is not closed, if pop-upping a message box, the lister will cover the message box.
|
||||
state_.lister->events().destroy.connect_unignorable([this](const arg_destroy&)
|
||||
{
|
||||
state_.lister = nullptr; //The lister closes by itself.
|
||||
@ -676,7 +676,10 @@ namespace nana
|
||||
{
|
||||
auto * editor = drawer_->editor();
|
||||
editor->mouse_pressed(arg);
|
||||
drawer_->open_lister_if_push_button_positioned();
|
||||
|
||||
//Pops up the droplist only if left button is clicked
|
||||
if(arg.is_left_button())
|
||||
drawer_->open_lister_if_push_button_positioned();
|
||||
|
||||
drawer_->draw();
|
||||
if(editor->attr().editable)
|
||||
|
||||
@ -532,7 +532,7 @@ namespace nana
|
||||
perf_transform_helper(window_handle, transf, graph, dirtybuf, gbuf, refpos);
|
||||
}
|
||||
private:
|
||||
//renderring functions
|
||||
//rendering functions
|
||||
|
||||
void _m_calc_basis(graph_reference graph, const nana::point& refpos)
|
||||
{
|
||||
|
||||
@ -49,8 +49,8 @@ static const char* field_options = "__nana_group_options__";
|
||||
|
||||
implement() = default;
|
||||
|
||||
implement(window grp_panel, ::std::string titel, bool vsb, unsigned gap=2)
|
||||
: caption (grp_panel, std::move(titel), vsb),
|
||||
implement(window grp_panel, ::std::string title, bool vsb, unsigned gap=2)
|
||||
: caption (grp_panel, std::move(title), vsb),
|
||||
place_content{grp_panel},
|
||||
gap{gap}
|
||||
{
|
||||
@ -118,12 +118,12 @@ group::group(window parent, const rectangle& r, bool vsb)
|
||||
|
||||
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
|
||||
|
||||
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
||||
group::group(window parent, ::std::string title, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
||||
: group(parent, r, vsb)
|
||||
{
|
||||
this->bgcolor(API::bgcolor(parent));
|
||||
|
||||
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
||||
impl_.reset(new implement(*this, std::move(title), vsb, gap));
|
||||
|
||||
impl_->caption.format(formatted);
|
||||
_m_init();
|
||||
@ -312,14 +312,14 @@ checkbox& group::add_option(std::string text)
|
||||
drawing dw(*this);
|
||||
|
||||
//When the group is resized, the drawing is called before moving the caption, but
|
||||
//the drawing of group requires the lastest position of caption for gradual rectangle.
|
||||
//For the requirement, a move event handler is required for listning the change of caption's position.
|
||||
//the drawing of group requires the latest position of caption for gradual rectangle.
|
||||
//For the requirement, a move event handler is required for listening the change of caption's position.
|
||||
impl_->caption.events().move([this](const arg_move&){
|
||||
if (align::left != impl_->caption_align)
|
||||
API::refresh_window(*this);
|
||||
});
|
||||
|
||||
// This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !!
|
||||
// This drawing function is owner by the owner of dw (the outer panel of the group widget), not by dw !!
|
||||
dw.draw([this](paint::graphics& graph)
|
||||
{
|
||||
auto gap_px = impl_->gap - 1;
|
||||
|
||||
@ -376,7 +376,7 @@ namespace nana
|
||||
{
|
||||
text_pos += static_cast<int>(extent_size.width);
|
||||
|
||||
//Adjust height of extent_size for special text alignement.
|
||||
//Adjust height of extent_size for special text alignment.
|
||||
if (fblock::aligns::baseline == fblock->text_align)
|
||||
{
|
||||
ascent = static_cast<unsigned>(data->ascent());
|
||||
@ -420,7 +420,7 @@ namespace nana
|
||||
|
||||
text_pos = 0;
|
||||
max_content_height = max_ascent = max_descent = 0;
|
||||
//Adjust height of extent_size for special text alignement.
|
||||
//Adjust height of extent_size for special text alignment.
|
||||
if (fblock::aligns::baseline == fblock->text_align)
|
||||
{
|
||||
ascent = static_cast<unsigned>(data->ascent());
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
* Benjamin Navarro(pr#81)
|
||||
* besh81(pr#130)
|
||||
* dankan1890(pr#158)
|
||||
* ErrorFlynn(pr#418)
|
||||
*
|
||||
*/
|
||||
#include <algorithm>
|
||||
@ -675,7 +676,7 @@ namespace nana
|
||||
else
|
||||
item_str += exp_opt.sep;
|
||||
|
||||
//Use the model cells instead if model cells is avaiable
|
||||
//Use the model cells instead if model cells is available
|
||||
item_str += (model_cells ? model_cells : cells.get())->operator[](col).text;
|
||||
}
|
||||
|
||||
@ -842,7 +843,7 @@ namespace nana
|
||||
return sort_attrs_;
|
||||
}
|
||||
|
||||
/// each sort() ivalidate any existing reference from display position to absolute item, that is after sort() display offset point to different items
|
||||
/// each sort() invalidates any existing reference from display position to absolute item, that is after sort() display offset point to different items
|
||||
void sort()
|
||||
{
|
||||
if((npos == sort_attrs_.column) || (!sort_attrs_.resort))
|
||||
@ -1554,7 +1555,7 @@ namespace nana
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Finds a good item or category if an item specified by pos is invaild
|
||||
/// Finds a good item or category if an item specified by pos is invalid
|
||||
index_pair find_next_good(index_pair pos, bool ignore_category) const noexcept
|
||||
{
|
||||
//Return the pos if it is good
|
||||
@ -1691,7 +1692,7 @@ namespace nana
|
||||
/**
|
||||
* @param for_selection Indicates whether the selected items or checked items to be returned.
|
||||
* @param find_first Indicates whether or not to return the first item which
|
||||
* @param items_status a pointer refers to a bool object to receive the status whethe the picked items are all selected or all checked, in contrast to for_selection
|
||||
* @param items_status a pointer refers to a bool object to receive the status whether the picked items are all selected or all checked, in contrast to for_selection
|
||||
*/
|
||||
index_pairs pick_items(bool for_selection, bool find_first = false, bool * items_status = nullptr) const
|
||||
{
|
||||
@ -1989,7 +1990,7 @@ namespace nana
|
||||
msup_deselect
|
||||
};
|
||||
|
||||
/// created and live by the trigger, holds data for listbox: the state of the struct does not effect on member funcions, therefore all data members are public.
|
||||
/// created and live by the trigger, holds data for listbox: the state of the struct does not effect on member functions, therefore all data members are public.
|
||||
struct essence
|
||||
{
|
||||
enum class item_state{normal, highlighted, pressed, grabbed, floated};
|
||||
@ -2006,7 +2007,7 @@ namespace nana
|
||||
::nana::listbox::export_options def_exp_options;
|
||||
|
||||
es_header header;
|
||||
es_lister lister; // we have at least one emty cat. the #0
|
||||
es_lister lister; // we have at least one empty cat. the #0
|
||||
|
||||
item_state ptr_state{ item_state::normal };
|
||||
std::pair<parts, std::size_t> pointer_where; //The 'first' stands for which object, such as header and lister, 'second' stands for item
|
||||
@ -3114,7 +3115,7 @@ namespace nana
|
||||
{
|
||||
auto next_selected_dpl = index_cast_noexcept(latest_selected_abs, false); //convert absolute position to display position
|
||||
|
||||
if (next_selected_dpl.empty()) // has no cat ? (cat == npos) => beging from first cat
|
||||
if (next_selected_dpl.empty()) // has no cat ? (cat == npos) => begins from first cat
|
||||
{
|
||||
bool good = false;
|
||||
for (size_type i = 0, size = categories_.size(); i < size; ++i) // run all cat
|
||||
@ -3377,7 +3378,7 @@ namespace nana
|
||||
auto text_color = essence_->scheme_ptr->header_fgcolor.get_color();
|
||||
|
||||
auto state = item_state::normal;
|
||||
//check whether grabing an item, if item_spliter_ != npos, that indicates the grab item is a spliter.
|
||||
//check whether grabbing an item, if item_spliter_ != npos, that indicates the grabbed item is a splitter.
|
||||
if ((parts::header == essence_->pointer_where.first) && (npos == grabs_.splitter))
|
||||
state = essence_->ptr_state;
|
||||
|
||||
@ -3651,7 +3652,7 @@ namespace nana
|
||||
// The first display is empty when the listbox is empty.
|
||||
if (!first_disp.empty())
|
||||
{
|
||||
index_pair hoverred_pos(npos, npos); //the hoverred item.
|
||||
index_pair hoverred_pos(npos, npos); //the hovered item.
|
||||
|
||||
//if where == lister || where == checker, 'second' indicates the offset to the relative display-order pos of the scroll offset_y which stands for the first item to be displayed in lister.
|
||||
if ((ptr_where.first == parts::list || ptr_where.first == parts::checker) && ptr_where.second != npos)
|
||||
@ -3879,7 +3880,7 @@ namespace nana
|
||||
for (size_type display_order{ 0 }; display_order < seqs.size(); ++display_order) // get the cell (column) index in the order headers are displayed
|
||||
{
|
||||
const auto column_pos = seqs[display_order];
|
||||
const auto & col = essence_->header.at(column_pos); // deduce the corresponding header which is in a kind of dislay order
|
||||
const auto & col = essence_->header.at(column_pos); // deduce the corresponding header which is in a kind of display order
|
||||
|
||||
if (col.width_px > essence_->scheme_ptr->text_margin)
|
||||
{
|
||||
@ -4724,7 +4725,7 @@ namespace nana
|
||||
cat_ = &(*ess->lister.get(pos.cat));
|
||||
}
|
||||
|
||||
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
||||
/// the main purpose of this it to make obvious that item_proxy operate with absolute positions, and don't get moved during sort()
|
||||
item_proxy item_proxy::from_display(essence *ess, const index_pair &relative)
|
||||
{
|
||||
return item_proxy{ ess, ess->lister.index_cast(relative, true) };
|
||||
@ -4735,7 +4736,7 @@ namespace nana
|
||||
return item_proxy{ess_, ess_->lister.index_cast(relative, true)};
|
||||
}
|
||||
|
||||
/// posible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
||||
/// possible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
||||
index_pair item_proxy::to_display() const
|
||||
{
|
||||
return ess_->lister.index_cast(pos_, false); //convert absolute position to display position
|
||||
@ -5455,9 +5456,12 @@ namespace nana
|
||||
internal_scope_guard lock;
|
||||
|
||||
if (_m_ess().lister.enable_ordered(enable))
|
||||
{
|
||||
_m_ess().update();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void listbox::auto_draw(bool enabled) noexcept
|
||||
@ -5811,7 +5815,7 @@ namespace nana
|
||||
auto & ess = _m_ess();
|
||||
|
||||
ess.lister.clear();
|
||||
unsort(); // apperar to be espected
|
||||
unsort(); // appear to be expected
|
||||
|
||||
ess.calc_content_size(false);
|
||||
ess.content_view->change_position(0, false, false);
|
||||
@ -5946,7 +5950,7 @@ namespace nana
|
||||
_m_ess().header.at(col).weak_ordering = std::move(strick_ordering);
|
||||
}
|
||||
|
||||
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
/// sort() and invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void listbox::sort_col(size_type col, bool reverse)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
@ -5959,7 +5963,7 @@ namespace nana
|
||||
return _m_ess().lister.sort_attrs().column;
|
||||
}
|
||||
|
||||
/// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
/// potentially invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void listbox::unsort()
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menu implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -84,7 +84,7 @@ namespace nana
|
||||
crook_.check(facade<element::crook>::state::checked);
|
||||
}
|
||||
private:
|
||||
//Impelement renderer_interface
|
||||
//Implements renderer_interface
|
||||
void background(graph_reference graph, window)
|
||||
{
|
||||
nana::size sz = graph.size();
|
||||
@ -133,7 +133,7 @@ namespace nana
|
||||
return;
|
||||
}
|
||||
|
||||
//Stretchs menu icon only when it doesn't fit, center it otherwise.
|
||||
//Stretches menu icon only when it doesn't fit, center it otherwise.
|
||||
//Contributed by kmribti(pr#102)
|
||||
img.paste(graph, {
|
||||
pos.x + static_cast<int>(image_px - img.size().width) / 2,
|
||||
@ -740,7 +740,7 @@ namespace nana
|
||||
|
||||
struct widget_detail
|
||||
{
|
||||
nana::point monitor_pos; //It is used for determinating the monitor.
|
||||
nana::point monitor_pos; //It is used for determining the monitor.
|
||||
nana::upoint border;
|
||||
}detail_;
|
||||
};//end class menu_drawer
|
||||
@ -819,7 +819,7 @@ namespace nana
|
||||
events.mouse_down.connect_unignorable(fn);
|
||||
events.mouse_up.connect_unignorable(fn);
|
||||
|
||||
timer_.interval(100);
|
||||
timer_.interval(std::chrono::milliseconds{ 100 });
|
||||
timer_.elapse([this]{
|
||||
this->_m_open_sub(500); //Try to open submenu
|
||||
});
|
||||
@ -927,7 +927,7 @@ namespace nana
|
||||
this->_m_close_all(); //means deleting this;
|
||||
//The deleting operation has moved here, because item.event_handler.operator()(ip)
|
||||
//may create a window, which make a killing focus for menu window, if so the close_all
|
||||
//operation preformences after item.event_handler.operator()(ip), that would be deleting this object twice!
|
||||
//operation performs after item.event_handler.operator()(ip), that would be deleting this object twice!
|
||||
|
||||
if (item.event_handler)
|
||||
{
|
||||
|
||||
@ -36,7 +36,7 @@ namespace nana
|
||||
shortkey_pos(shortkey_pos)
|
||||
{}
|
||||
|
||||
std::string text; ///< Transformed text, the shortkey charactor has been proccessed.
|
||||
std::string text; ///< Transformed text, the shortkey character has been processed.
|
||||
wchar_t shortkey;
|
||||
std::size_t shortkey_pos;
|
||||
::nana::menu menu_obj;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Content View Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2017-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2017-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -132,7 +132,7 @@ namespace nana {
|
||||
}
|
||||
else if (this->drag_view_move && this->drive(arg.pos))
|
||||
{
|
||||
tmr.interval(16);
|
||||
tmr.interval(std::chrono::milliseconds{ 16 });
|
||||
tmr.start();
|
||||
}
|
||||
}
|
||||
@ -277,7 +277,7 @@ namespace nana {
|
||||
else
|
||||
{
|
||||
cv_scroll->horz.close();
|
||||
//If horz is allowed, it indicates the horzontal origin is not moved
|
||||
//If horz is allowed, it indicates the horizontal origin is not moved
|
||||
//Make sure the x origin is zero
|
||||
if (horz_allowed)
|
||||
origin.x = 0;
|
||||
|
||||
@ -1018,7 +1018,7 @@ namespace nana {
|
||||
for (++i; i != entities.end(); )
|
||||
{
|
||||
if (bound > i->begin)
|
||||
i = entities.erase(i); // erase overlaping. Left only the first.
|
||||
i = entities.erase(i); // erase overlapping. Left only the first.
|
||||
else
|
||||
++i;
|
||||
}
|
||||
@ -2363,7 +2363,7 @@ namespace nana {
|
||||
//The number of text lines
|
||||
auto const line_count = textbase().lines();
|
||||
|
||||
//The number of charecters in the line of caret
|
||||
//The number of characters in the line of caret
|
||||
auto const text_length = textbase().getline(points_.caret.y).size();
|
||||
|
||||
switch (key) {
|
||||
@ -2403,10 +2403,10 @@ namespace nana {
|
||||
coord.y += static_cast<int>(line_px);
|
||||
break;
|
||||
case keyboard::os_home:
|
||||
//move the caret to the begining of the line
|
||||
//move the caret to the beginning of the line
|
||||
pos.x = 0;
|
||||
|
||||
//move the caret to the begining of the text if Ctrl is pressed
|
||||
//move the caret to the beginning of the text if Ctrl is pressed
|
||||
if (arg.ctrl)
|
||||
pos.y = 0;
|
||||
break;
|
||||
@ -2415,7 +2415,7 @@ namespace nana {
|
||||
//move the caret to the end of the text if Ctrl is pressed
|
||||
if (arg.ctrl) {
|
||||
coord.y = static_cast<unsigned>((line_count - 1) * line_px);
|
||||
//The number of charecters of the bottom line
|
||||
//The number of characters of the bottom line
|
||||
auto const text_length = textbase().getline(std::max<size_t>(0, line_count - 1)).size();
|
||||
//move the caret to the end of the line
|
||||
pos.x = static_cast<decltype(pos.x)>(text_length);
|
||||
@ -3385,7 +3385,7 @@ namespace nana {
|
||||
std::wstring_view ent_sv;
|
||||
if (rtl)
|
||||
{
|
||||
//draw the whole text if it is a RTL text, because Arbic language is transformable.
|
||||
//draw the whole text if it is a RTL text, because Arabic language is transformable.
|
||||
ent_sv = { str, len };
|
||||
}
|
||||
else
|
||||
@ -3397,7 +3397,7 @@ namespace nana {
|
||||
#else
|
||||
if (rtl)
|
||||
{
|
||||
//draw the whole text if it is a RTL text, because Arbic language is transformable.
|
||||
//draw the whole text if it is a RTL text, because Arabic language is transformable.
|
||||
canvas.string({}, str, len);
|
||||
}
|
||||
else
|
||||
|
||||
@ -275,11 +275,11 @@ namespace nana
|
||||
API::update_window(editor_->window_handle());
|
||||
|
||||
auto intv = timer_.interval();
|
||||
if (intv > 50)
|
||||
if (intv.count() > 50)
|
||||
timer_.interval(intv / 2);
|
||||
});
|
||||
|
||||
timer_.interval(600);
|
||||
timer_.interval(std::chrono::milliseconds{ 600 });
|
||||
}
|
||||
|
||||
void attach(::nana::widget& wdg, ::nana::paint::graphics& graph)
|
||||
@ -396,7 +396,7 @@ namespace nana
|
||||
API::release_capture(editor_->window_handle());
|
||||
|
||||
timer_.stop();
|
||||
timer_.interval(600);
|
||||
timer_.interval(std::chrono::milliseconds{ 600 });
|
||||
}
|
||||
|
||||
if (buttons::none != spin_stated_)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Tabbar Implementation
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -748,7 +748,7 @@ namespace nana
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private: //Fundation
|
||||
private: //Foundation
|
||||
bool _m_nextable() const
|
||||
{
|
||||
return (basis_.scroll_pixels + _m_itembar_right() < basis_.item_pixels * list_.size());
|
||||
@ -1291,7 +1291,8 @@ namespace nana
|
||||
|
||||
void trigger::mouse_down(graph_reference, const arg_mouse& arg)
|
||||
{
|
||||
if(layouter_->press())
|
||||
//Activates the tab only if left button is clicked.
|
||||
if(arg.is_left_button() && layouter_->press())
|
||||
{
|
||||
if(false == layouter_->active_by_trace(arg))
|
||||
layouter_->toolbox_answer(arg);
|
||||
@ -1593,10 +1594,10 @@ namespace nana
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void driver::mouse_down(graph_reference graph, const arg_mouse&)
|
||||
void driver::mouse_down(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
auto & indexes = model_->get_indexes();
|
||||
if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos))
|
||||
if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos) || !arg.is_left_button())
|
||||
return;
|
||||
|
||||
if (indexes.active_pos != indexes.hovered_pos)
|
||||
|
||||
@ -46,7 +46,7 @@ namespace drawerbase {
|
||||
}
|
||||
//end class event_agent
|
||||
|
||||
//class draweer
|
||||
//class drawer
|
||||
drawer::drawer()
|
||||
: widget_(nullptr), editor_(nullptr)
|
||||
{
|
||||
@ -278,8 +278,8 @@ namespace drawerbase {
|
||||
return{};
|
||||
}
|
||||
|
||||
/// Enables/disables the textbox to indent a line. Idents a new line when it is created by pressing enter.
|
||||
/// @param generator generates text for identing a line. If it is empty, textbox indents the line according to last line.
|
||||
/// Enables/disables the textbox to indent a line. Indents a new line when it is created by pressing enter.
|
||||
/// @param generator generates text for indenting a line. If it is empty, textbox indents the line according to last line.
|
||||
textbox& textbox::indention(bool enb, std::function<std::string()> generator)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
@ -474,7 +474,7 @@ namespace drawerbase {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/// Determine wheter the text is auto-line changed.
|
||||
/// Determine whether the text is auto-line changed.
|
||||
bool textbox::line_wrapped() const
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
|
||||
@ -342,7 +342,7 @@ namespace nana
|
||||
|
||||
struct adjust_tag
|
||||
{
|
||||
int offset_x_adjust; //It is a new value of offset_x, and offset_x will be djusted to the new value
|
||||
int offset_x_adjust; //It is a new value of offset_x, and offset_x will be adjusted to the new value
|
||||
tree_cont_type::node_type * node;
|
||||
std::size_t scroll_timestamp;
|
||||
nana::timer timer;
|
||||
@ -963,6 +963,11 @@ namespace nana
|
||||
if(text_r.right() > visible_w_pixels())
|
||||
{
|
||||
node_state.tooltip = new tooltip_window(data.widget_ptr->handle(), text_r);
|
||||
|
||||
//PR#406 Error Flynn's contribution
|
||||
//fix: tooltip window doesn't have tree scheme & typeface
|
||||
API::dev::set_scheme(node_state.tooltip->handle(), API::dev::get_scheme(data.widget_ptr->handle()));
|
||||
node_state.tooltip->typeface(data.widget_ptr->typeface());
|
||||
|
||||
node_attribute node_attr;
|
||||
assign_node_attr(node_attr, node_state.pointed);
|
||||
@ -1062,7 +1067,7 @@ namespace nana
|
||||
item_proxy::item_proxy(trigger* trg, trigger::node_type* node)
|
||||
: trigger_(trg), node_(node)
|
||||
{
|
||||
//Make it an end itertor if one of them is a nullptr
|
||||
//Make it an end iterator if one of them is a nullptr
|
||||
if(nullptr == trg || nullptr == node)
|
||||
{
|
||||
trigger_ = nullptr;
|
||||
@ -1320,7 +1325,7 @@ namespace nana
|
||||
return node_->value.second.value;
|
||||
}
|
||||
|
||||
//Undocumentated methods for internal use.
|
||||
//Undocumented methods for internal use.
|
||||
trigger::node_type * item_proxy::_m_node() const
|
||||
{
|
||||
return node_;
|
||||
@ -1735,7 +1740,7 @@ namespace nana
|
||||
}
|
||||
});
|
||||
|
||||
impl_->adjust.timer.interval(16);
|
||||
impl_->adjust.timer.interval(std::chrono::milliseconds{ 16 });
|
||||
impl_->adjust.timer.start();
|
||||
}
|
||||
|
||||
@ -1927,7 +1932,7 @@ namespace nana
|
||||
|
||||
void trigger::detached()
|
||||
{
|
||||
//Reset the comp_placer, because after deteching, the scheme refered by comp_placer will be released
|
||||
//Reset the comp_placer, because after detaching, the scheme referred by comp_placer will be released
|
||||
impl_->data.comp_placer.reset();
|
||||
impl_->data.graph = nullptr;
|
||||
}
|
||||
@ -2366,6 +2371,19 @@ namespace nana
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
|
||||
treebox::item_proxy treebox::hovered(bool exclude_expander) const
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
auto dw = &get_drawer_trigger();
|
||||
if (dw->impl()->node_state.pointed)
|
||||
{
|
||||
//Returns empty item_proxy if the mouse is on expander and exclude_expander is required.
|
||||
if (exclude_expander && (dw->impl()->node_state.comp_pointed == drawerbase::treebox::component::expander))
|
||||
return item_proxy{};
|
||||
}
|
||||
return item_proxy(const_cast<drawer_trigger_t*>(dw), dw->impl()->node_state.pointed);
|
||||
}
|
||||
|
||||
std::shared_ptr<scroll_operation_interface> treebox::_m_scroll_operation()
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
|
||||
@ -65,7 +65,7 @@ namespace nana
|
||||
void exec(
|
||||
unsigned wait, // = 1, ///< for the GUI to be constructed, in seconds
|
||||
unsigned wait_end, // = 1, ///< for the GUI to be destructed, in seconds
|
||||
std::function<void()>f // = {} ///< emit events to mimics user actions and may asert results
|
||||
std::function<void()>f // = {} ///< emit events to mimics user actions and may assert results
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
@ -520,7 +520,7 @@ namespace nana
|
||||
args_.emplace_back(arg->clone());
|
||||
}
|
||||
|
||||
//Workaround for VC2013, becuase it can't specified a default explicit move-constructor
|
||||
//Workaround for VC2013, because it can't specify a default explicit move-constructor
|
||||
i18n_eval::i18n_eval(i18n_eval&& other)
|
||||
: msgid_(std::move(other.msgid_)), args_(std::move(other.args_))
|
||||
{
|
||||
|
||||
@ -18,8 +18,8 @@ namespace paint
|
||||
|
||||
image_process_provider::image_process_provider()
|
||||
{
|
||||
add<paint::detail::algorithms::bilinear_interoplation>(stretch_, "bilinear interoplation");
|
||||
add<paint::detail::algorithms::proximal_interoplation>(stretch_, "proximal interoplation");
|
||||
add<paint::detail::algorithms::bilinear_interoplation>(stretch_, "bilinear interpolation");
|
||||
add<paint::detail::algorithms::proximal_interoplation>(stretch_, "proximal interpolation");
|
||||
add<paint::detail::algorithms::alpha_blend>(alpha_blend_, "alpha_blend");
|
||||
add<paint::detail::algorithms::blend>(blend_, "blend");
|
||||
add<paint::detail::algorithms::bresenham_line>(line_, "bresenham_line");
|
||||
|
||||
@ -285,7 +285,7 @@ namespace paint
|
||||
const void* graphics::pixmap() const
|
||||
{
|
||||
//The reinterpret_cast is used for same platform. Under Windows, the type
|
||||
//of pixmap can be conversed into void* directly, but under X11, the type is not a pointer.
|
||||
//of pixmap can be converted into void* directly, but under X11, the type is not a pointer.
|
||||
return (impl_->handle ? reinterpret_cast<void*>(impl_->handle->pixmap) : nullptr);
|
||||
}
|
||||
|
||||
@ -310,7 +310,7 @@ namespace paint
|
||||
return;
|
||||
}
|
||||
|
||||
//The object will be delete while dwptr_ is performing a release.
|
||||
//The object will be deleted while dwptr_ is performing a release.
|
||||
std::shared_ptr<nana::detail::drawable_impl_type> dw{ new nana::detail::drawable_impl_type, detail::drawable_deleter{} };
|
||||
|
||||
//Reuse the old font
|
||||
@ -856,7 +856,7 @@ namespace paint
|
||||
{
|
||||
if(impl_->handle)
|
||||
{
|
||||
//Create the color table for perfermance
|
||||
//Create the color table for performance
|
||||
float* tablebuf = new float[0x100 * 3];
|
||||
float* table_red = tablebuf;
|
||||
float* table_green = tablebuf + 0x100;
|
||||
|
||||
@ -305,7 +305,7 @@ namespace nana{ namespace paint
|
||||
}
|
||||
|
||||
#if defined(NANA_X11)
|
||||
//The implementation of attach in X11 is same with non-attach's, because the image buffer of drawable can't be refered indirectly
|
||||
//The implementation of attach in X11 is same with non-attach's, because the image buffer of drawable can't be referred indirectly
|
||||
//so the pixel_buffer::open() method may call the attached version of pixel_buffer_storage construction.
|
||||
void detach()
|
||||
{
|
||||
@ -371,7 +371,7 @@ namespace nana{ namespace paint
|
||||
::XPutImage(disp, dw, gc,
|
||||
img, src_x, src_y, x, y, width, height);
|
||||
}
|
||||
img->data = nullptr; //Set null pointer to avoid XDestroyImage destroyes the buffer.
|
||||
img->data = nullptr; //Set null pointer to avoid XDestroyImage destroys the buffer.
|
||||
XDestroyImage(img);
|
||||
}
|
||||
#endif
|
||||
@ -787,7 +787,7 @@ namespace nana{ namespace paint
|
||||
auto sp = storage_.get();
|
||||
if(nullptr == sp) return;
|
||||
|
||||
//Test if the line intersects the rectangle, and retrive the two points that
|
||||
//Test if the line intersects the rectangle, and retrieve the two points that
|
||||
//are always in the area of rectangle, good_pos_beg is left point, good_pos_end is right.
|
||||
nana::point good_pos_beg, good_pos_end;
|
||||
if(intersection(nana::rectangle(sp->pixel_size), pos_beg, pos_end, good_pos_beg, good_pos_end))
|
||||
|
||||
@ -661,7 +661,7 @@ namespace nana
|
||||
//W1. Examine each nonspacing mark, and change the type of the NSM to the type of the previous
|
||||
//character.
|
||||
//W2. Search backward from each instance of a European number until the first strong type(R, L, AL, or sor) is found
|
||||
//If an AL is found, change the type of the European Number to arbic number.
|
||||
//If an AL is found, change the type of the European Number to Arabic number.
|
||||
//W3. Change all ALs to R.
|
||||
|
||||
//The three phases could be combined as one process. Because these phases are standalone.
|
||||
@ -702,7 +702,7 @@ namespace nana
|
||||
}
|
||||
|
||||
|
||||
//W4. A single european separator between two european numbers changes to a european number.
|
||||
//W4. A single European separator between two European numbers changes to a European number.
|
||||
//A single common separator between two numbers of the same type changes to that type.
|
||||
//
|
||||
//W5. A sequence of European terminators adjacent to European numbers changes to all European numbers.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user