diff --git a/.travis.yml b/.travis.yml index 08c3d6f0..7b71b9ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/include/nana/any.hpp b/include/nana/any.hpp index ed711146..149be255 100644 --- a/include/nana/any.hpp +++ b/include/nana/any.hpp @@ -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 diff --git a/include/nana/basic_types.hpp b/include/nana/basic_types.hpp index 0821c91b..895f476c 100644 --- a/include/nana/basic_types.hpp +++ b/include/nana/basic_types.hpp @@ -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; diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 9456887f..4f00e5f9 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -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 diff --git a/include/nana/charset.hpp b/include/nana/charset.hpp index 0bbb9c71..b26dbb6a 100644 --- a/include/nana/charset.hpp +++ b/include/nana/charset.hpp @@ -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. diff --git a/include/nana/config.hpp b/include/nana/config.hpp index 1d88b379..791cf0f9 100644 --- a/include/nana/config.hpp +++ b/include/nana/config.hpp @@ -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): diff --git a/include/nana/deploy.hpp b/include/nana/deploy.hpp index 71ad399d..168358c5 100644 --- a/include/nana/deploy.hpp +++ b/include/nana/deploy.hpp @@ -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 diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index f14c043f..86b907a6 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.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 @@ -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 diff --git a/include/nana/gui/animation.hpp b/include/nana/gui/animation.hpp index e8338399..f0267a46 100644 --- a/include/nana/gui/animation.hpp +++ b/include/nana/gui/animation.hpp @@ -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_; }; diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index 1e043621..b868a00a 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -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::value); } }; - };//end namespace apper + };//end namespace appear /// Interface for caret operations class caret_interface diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index b79ec168..bc0a116f 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -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&) 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 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; diff --git a/include/nana/gui/detail/drawer.hpp b/include/nana/gui/detail/drawer.hpp index 7c20db17..46796573 100644 --- a/include/nana/gui/detail/drawer.hpp +++ b/include/nana/gui/detail/drawer.hpp @@ -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 { diff --git a/include/nana/gui/detail/event_code.hpp b/include/nana/gui/detail/event_code.hpp index 2f126db6..2c63cb4c 100644 --- a/include/nana/gui/detail/event_code.hpp +++ b/include/nana/gui/detail/event_code.hpp @@ -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. diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index 82e3c57c..d9c26326 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -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); diff --git a/include/nana/gui/drawing.hpp b/include/nana/gui/drawing.hpp index d7f7c7be..693af743 100644 --- a/include/nana/gui/drawing.hpp +++ b/include/nana/gui/drawing.hpp @@ -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 diff --git a/include/nana/gui/layout_utility.hpp b/include/nana/gui/layout_utility.hpp index 56127aac..fdadf036 100644 --- a/include/nana/gui/layout_utility.hpp +++ b/include/nana/gui/layout_utility.hpp @@ -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 diff --git a/include/nana/gui/msgbox.hpp b/include/nana/gui/msgbox.hpp index a004fd21..c67795f6 100644 --- a/include/nana/gui/msgbox.hpp +++ b/include/nana/gui/msgbox.hpp @@ -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 msgbox & operator<<(const T& t) { diff --git a/include/nana/gui/notifier.hpp b/include/nana/gui/notifier.hpp index 3e136cdb..31cf28f1 100644 --- a/include/nana/gui/notifier.hpp +++ b/include/nana/gui/notifier.hpp @@ -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: diff --git a/include/nana/gui/place.hpp b/include/nana/gui/place.hpp index b0202e4f..a20bd50b 100644 --- a/include/nana/gui/place.hpp +++ b/include/nana/gui/place.hpp @@ -73,7 +73,7 @@ namespace nana std::function 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 { diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 48a773ce..0b5e42ed 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -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. diff --git a/include/nana/gui/timer.hpp b/include/nana/gui/timer.hpp index 9ae26f32..0bd2973f 100644 --- a/include/nana/gui/timer.hpp +++ b/include/nana/gui/timer.hpp @@ -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 /// Accepts an initial interval in any chrono unit + explicit timer(std::chrono::duration const & time) : timer{} { interval(time); } +#else + explicit timer(std::chrono::milliseconds ms); +#endif ~timer(); template @@ -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 + inline void interval(std::chrono::duration const & time_interval) ///< Set the duration between calls, accepts std::chrono + { + _m_interval(static_cast(std::chrono::duration_cast(time_interval).count())); + } +#else + void interval(std::chrono::milliseconds ms); +#endif + +#if 0 //deprecated unsigned interval() const; +#endif + template + inline Duration interval() const + { + return std::chrono::duration_cast(std::chrono::milliseconds{ _m_interval() }); + } + private: + unsigned _m_interval() const; private: nana::basic_event elapse_; implement * const impl_; diff --git a/include/nana/gui/widgets/categorize.hpp b/include/nana/gui/widgets/categorize.hpp index dcbdde12..7cf90000 100644 --- a/include/nana/gui/widgets/categorize.hpp +++ b/include/nana/gui/widgets/categorize.hpp @@ -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; diff --git a/include/nana/gui/widgets/checkbox.hpp b/include/nana/gui/widgets/checkbox.hpp index 1a75c91a..d5b6d252 100644 --- a/include/nana/gui/widgets/checkbox.hpp +++ b/include/nana/gui/widgets/checkbox.hpp @@ -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(-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 + void on_clicked(Function&& click_fn) + { + for (auto & e : ui_container_) + { + e.uiobj->events().click(std::move(click_fn)); + } + } + + template + void on_checked(Function&& check_fn) + { + for (auto & e : ui_container_) + { + e.uiobj->events().checked(std::move(check_fn)); + } + } private: std::vector ui_container_; }; diff --git a/include/nana/gui/widgets/date_chooser.hpp b/include/nana/gui/widgets/date_chooser.hpp index b36d800f..3d138faf 100644 --- a/include/nana/gui/widgets/date_chooser.hpp +++ b/include/nana/gui/widgets/date_chooser.hpp @@ -76,7 +76,7 @@ namespace nana bool chose() const; nana::date read() const; - void weekstr(unsigned index, ::std::string);/// diff --git a/include/nana/gui/widgets/detail/tree_cont.hpp b/include/nana/gui/widgets/detail/tree_cont.hpp index 3aa3b4f9..e2373bb5 100644 --- a/include/nana/gui/widgets/detail/tree_cont.hpp +++ b/include/nana/gui/widgets/detail/tree_cont.hpp @@ -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(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(path); + auto p = _m_locate(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 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 diff --git a/include/nana/gui/widgets/float_listbox.hpp b/include/nana/gui/widgets/float_listbox.hpp index 97670410..ac842845 100644 --- a/include/nana/gui/widgets/float_listbox.hpp +++ b/include/nana/gui/widgets/float_listbox.hpp @@ -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); diff --git a/include/nana/gui/widgets/form.hpp b/include/nana/gui/widgets/form.hpp index 6053a1d7..65f4572e 100644 --- a/include/nana/gui/widgets/form.hpp +++ b/include/nana/gui/widgets/form.hpp @@ -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 diff --git a/include/nana/gui/widgets/group.hpp b/include/nana/gui/widgets/group.hpp index 3ca870d2..6188ccce 100644 --- a/include/nana/gui/widgets/group.hpp +++ b/include/nana/gui/widgets/group.hpp @@ -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 ); diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index b6279630..1d9cdec0 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -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 @@ -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 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() which call API::detail::make_scheme(::nana::detail::scheme_factory()) 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(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 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); diff --git a/include/nana/gui/widgets/menubar.hpp b/include/nana/gui/widgets/menubar.hpp index c6bbd7c9..b159a775 100644 --- a/include/nana/gui/widgets/menubar.hpp +++ b/include/nana/gui/widgets/menubar.hpp @@ -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(); diff --git a/include/nana/gui/widgets/panel.hpp b/include/nana/gui/widgets/panel.hpp index b159fa35..2b6683d6 100644 --- a/include/nana/gui/widgets/panel.hpp +++ b/include/nana/gui/widgets/panel.hpp @@ -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 class panel : public widget_object::type, diff --git a/include/nana/gui/widgets/picture.hpp b/include/nana/gui/widgets/picture.hpp index d4805662..83068b79 100644 --- a/include/nana/gui/widgets/picture.hpp +++ b/include/nana/gui/widgets/picture.hpp @@ -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; diff --git a/include/nana/gui/widgets/progress.hpp b/include/nana/gui/widgets/progress.hpp index f43da854..37a5c890 100644 --- a/include/nana/gui/widgets/progress.hpp +++ b/include/nana/gui/widgets/progress.hpp @@ -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 { diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 62857c6f..9bee580d 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -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 * 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(); diff --git a/include/nana/gui/widgets/slider.hpp b/include/nana/gui/widgets/slider.hpp index 2fc015ce..5cbffa9a 100644 --- a/include/nana/gui/widgets/slider.hpp +++ b/include/nana/gui/widgets/slider.hpp @@ -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 { diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index 9595321f..d1f779e0 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -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 range_int() const; std::pair 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; diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 863b66ec..2ebea403 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -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)); } diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index 8bf34b38..68c408b7 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -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); diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index ba40c4c1..fd48b022 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -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 & 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 _m_scroll_operation() override; diff --git a/include/nana/gui/wvl.hpp b/include/nana/gui/wvl.hpp index ccee91d3..c18be253 100644 --- a/include/nana/gui/wvl.hpp +++ b/include/nana/gui/wvl.hpp @@ -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 = {} ///< emit events to mimics user actions and may asert results + std::function = {} ///< 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 diff --git a/include/nana/paint/detail/image_process_provider.hpp b/include/nana/paint/detail/image_process_provider.hpp index e3d0ca6f..761544a3 100644 --- a/include/nana/paint/detail/image_process_provider.hpp +++ b/include/nana/paint/detail/image_process_provider.hpp @@ -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 void add(Tag & tag, const std::string& name) diff --git a/include/nana/stdc++.hpp b/include/nana/stdc++.hpp index 54d62f73..bcdc4fcb 100644 --- a/include/nana/stdc++.hpp +++ b/include/nana/stdc++.hpp @@ -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 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); diff --git a/source/basic_types.cpp b/source/basic_types.cpp index dafe8574..fa6c5e67 100644 --- a/source/basic_types.cpp +++ b/source/basic_types.cpp @@ -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) diff --git a/source/charset.cpp b/source/charset.cpp index 4ea53570..91d7855f 100644 --- a/source/charset.cpp +++ b/source/charset.cpp @@ -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; diff --git a/source/deploy.cpp b/source/deploy.cpp index 1ae165ef..465988b3 100644 --- a/source/deploy.cpp +++ b/source/deploy.cpp @@ -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 diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index b13e8465..8be0cce9 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -8,7 +8,7 @@ * * @file: nana/filesystem/filesystem.cpp * @description: - * provide some interface for file managment + * provide some interface for file management */ #include @@ -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 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(::errno), std::generic_category()); + ec.assign(static_cast(errno), std::generic_category()); #endif return static_cast(-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 elements; + while (!head.empty()) + { + auto head_status = status(head, tmp_err); + + if (head_status.type() == file_type::unknown) + { + if (try_throw(static_cast(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 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 elements; + while (!head.empty()) + { + auto head_status = status(head, tmp_err); + + if (head_status.type() == file_type::unknown) + { + if (detail::try_throw(static_cast(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 diff --git a/source/gui/animation.cpp b/source/gui/animation.cpp index 16e54729..f897735f 100644 --- a/source/gui/animation.cpp +++ b/source/gui/animation.cpp @@ -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 frames; std::list::iterator this_frame; std::size_t pos_in_this_frame{ 0 }; diff --git a/source/gui/detail/basic_window.cpp b/source/gui/detail/basic_window.cpp index a52b2215..661e3619 100644 --- a/source/gui/detail/basic_window.cpp +++ b/source/gui/detail/basic_window.cpp @@ -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; diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 65d644ec..0cd1e796 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -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; } diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 65e66701..9c96a7cd 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "inner_fwd_implement.hpp" #include @@ -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) { diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index bd02a00d..2747e65f 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #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(wParam); return true; case nana::detail::messages::remote_thread_destroy_window: - detail::native_interface::close_window(reinterpret_cast(wd)); //The owner would be actived before the message has posted in current thread. + detail::native_interface::close_window(reinterpret_cast(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(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(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(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 id_accel_key(const accel_key& key) { std::pair ret; diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index 3f5bc755..da5b0091 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -33,99 +33,99 @@ namespace nana void drawer_trigger::resizing(graph_reference, const arg_resizing&) { - overrided_ &= ~(1 << static_cast(event_code::resizing)); + overridden_ &= ~(1 << static_cast(event_code::resizing)); } void drawer_trigger::resized(graph_reference graph, const arg_resized&) { - overrided_ |= (1 << static_cast(event_code::resized)); + overridden_ |= (1 << static_cast(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(event_code::move)); + overridden_ &= ~(1 << static_cast(event_code::move)); } void drawer_trigger::click(graph_reference, const arg_click&) { - overrided_ &= ~(1 << static_cast(event_code::click)); + overridden_ &= ~(1 << static_cast(event_code::click)); } void drawer_trigger::dbl_click(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::dbl_click)); + overridden_ &= ~(1 << static_cast(event_code::dbl_click)); } void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_enter)); + overridden_ &= ~(1 << static_cast(event_code::mouse_enter)); } void drawer_trigger::mouse_move(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_move)); + overridden_ &= ~(1 << static_cast(event_code::mouse_move)); } void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_leave)); + overridden_ &= ~(1 << static_cast(event_code::mouse_leave)); } void drawer_trigger::mouse_down(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_down)); + overridden_ &= ~(1 << static_cast(event_code::mouse_down)); } void drawer_trigger::mouse_up(graph_reference, const arg_mouse&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_up)); + overridden_ &= ~(1 << static_cast(event_code::mouse_up)); } void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_wheel)); + overridden_ &= ~(1 << static_cast(event_code::mouse_wheel)); } void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&) { - overrided_ &= ~(1 << static_cast(event_code::mouse_drop)); + overridden_ &= ~(1 << static_cast(event_code::mouse_drop)); } void drawer_trigger::focus(graph_reference, const arg_focus&) { - overrided_ &= ~(1 << static_cast(event_code::focus)); + overridden_ &= ~(1 << static_cast(event_code::focus)); } void drawer_trigger::key_press(graph_reference, const arg_keyboard&) { - overrided_ &= ~(1 << static_cast(event_code::key_press)); + overridden_ &= ~(1 << static_cast(event_code::key_press)); } void drawer_trigger::key_char(graph_reference, const arg_keyboard&) { - overrided_ &= ~(1 << static_cast(event_code::key_char)); + overridden_ &= ~(1 << static_cast(event_code::key_char)); } void drawer_trigger::key_release(graph_reference, const arg_keyboard&) { - overrided_ &= ~(1 << static_cast(event_code::key_release)); + overridden_ &= ~(1 << static_cast(event_code::key_release)); } void drawer_trigger::shortkey(graph_reference, const arg_keyboard&) { - overrided_ &= ~(1 << static_cast(event_code::shortkey)); + overridden_ &= ~(1 << static_cast(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(evt_code))); + return 0 != (overridden_ & (1 << static_cast(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); } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index 2d2d0e58..efe49d21 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -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 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(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(); diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 12b5f86f..b0187eec 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -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; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 6349685d..b5842be8 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -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 lock(mutex_); + + if (ignore_captured || (nullptr == attr_.capture.window)) { - //Thread-Safe Required! - std::lock_guard 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 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 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; diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 5b2db9e2..b748b5cf 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -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}) {} diff --git a/source/gui/layout_utility.cpp b/source/gui/layout_utility.cpp index 4daade4a..f790a9ea 100644 --- a/source/gui/layout_utility.cpp +++ b/source/gui/layout_utility.cpp @@ -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; diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index 7263aa84..d11816fa 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -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(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(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 diff --git a/source/gui/notifier.cpp b/source/gui/notifier.cpp index 356d90f8..ddb9b3d6 100644 --- a/source/gui/notifier.cpp +++ b/source/gui/notifier.cpp @@ -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(impl_->icons.size()); - impl_->ani_timer.interval(ms < 16 ? 16 : ms); + auto frame_ms = (std::max)(ms.count() / static_cast(impl_->icons.size()), static_cast(16)); + + impl_->ani_timer.interval(std::chrono::milliseconds{frame_ms}); impl_->ani_timer.start(); } else diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 9b278111..968d8736 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -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 scan_div(place_parts::tokenizer&); + + std::unique_ptr 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 + //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 { 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{ 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 "); + //place.modify("A", ""); 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 + //reduce the size of the generated code, because std::set //will create a new template class. std::map 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; diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 148667ff..a73ec1bf 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -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( - restrict::wd_manager().find_window(wd, clipos)); + restrict::wd_manager().find_window(wd, clipos, true)); } return nullptr; } diff --git a/source/gui/timer.cpp b/source/gui/timer.cpp index b19a3b11..52981a8e 100644 --- a/source/gui/timer.cpp +++ b/source/gui/timer.cpp @@ -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(impl_->interval)) { - impl_->interval = ms; + impl_->interval = static_cast(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; } diff --git a/source/gui/tooltip.cpp b/source/gui/tooltip.cpp index 34692036..429c2cc4 100644 --- a/source/gui/tooltip.cpp +++ b/source/gui/tooltip.cpp @@ -86,12 +86,12 @@ namespace nana timer_.reset(); if (duration_) { - timer_.interval(static_cast(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(); diff --git a/source/gui/widgets/categorize.cpp b/source/gui/widgets/categorize.cpp index b00bdf8c..19d3ab23 100644 --- a/source/gui/widgets/categorize.cpp +++ b/source/gui/widgets/categorize.cpp @@ -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 diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index 619446a2..c5ef5f85 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -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) diff --git a/source/gui/widgets/date_chooser.cpp b/source/gui/widgets/date_chooser.cpp index b2f743e4..739a86ac 100644 --- a/source/gui/widgets/date_chooser.cpp +++ b/source/gui/widgets/date_chooser.cpp @@ -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) { diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index 4c68d5f5..726814e8 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -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; -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; diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 075591cc..77a6d0c0 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -376,7 +376,7 @@ namespace nana { text_pos += static_cast(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(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(data->ascent()); diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 29105225..00e2052a 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -15,6 +15,7 @@ * Benjamin Navarro(pr#81) * besh81(pr#130) * dankan1890(pr#158) + * ErrorFlynn(pr#418) * */ #include @@ -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 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; diff --git a/source/gui/widgets/menu.cpp b/source/gui/widgets/menu.cpp index 26b21812..e3b181e4 100644 --- a/source/gui/widgets/menu.cpp +++ b/source/gui/widgets/menu.cpp @@ -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::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(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) { diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp index aeb0c405..94fc12c6 100644 --- a/source/gui/widgets/menubar.cpp +++ b/source/gui/widgets/menubar.cpp @@ -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; diff --git a/source/gui/widgets/skeletons/content_view.cpp b/source/gui/widgets/skeletons/content_view.cpp index 62c92ce9..2b5c1d50 100644 --- a/source/gui/widgets/skeletons/content_view.cpp +++ b/source/gui/widgets/skeletons/content_view.cpp @@ -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; diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index d3878e75..9049165f 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -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(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((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(0, line_count - 1)).size(); //move the caret to the end of the line pos.x = static_cast(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 diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 4a631c2c..74169085 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -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_) diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index cf58e0f6..4cf17919 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -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) diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index 6ea644e2..100a832d 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -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 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; diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 1d1a6c13..377d0e7a 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -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(dw), dw->impl()->node_state.pointed); + } + std::shared_ptr treebox::_m_scroll_operation() { internal_scope_guard lock; diff --git a/source/gui/wvl.cpp b/source/gui/wvl.cpp index 610484cd..7497d3c4 100644 --- a/source/gui/wvl.cpp +++ b/source/gui/wvl.cpp @@ -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::functionf // = {} ///< emit events to mimics user actions and may asert results + std::functionf // = {} ///< emit events to mimics user actions and may assert results ) { diff --git a/source/internationalization.cpp b/source/internationalization.cpp index ba3ffcd6..ddd53d14 100644 --- a/source/internationalization.cpp +++ b/source/internationalization.cpp @@ -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_)) { diff --git a/source/paint/detail/image_process_provider.cpp b/source/paint/detail/image_process_provider.cpp index 89324e04..246c26ac 100644 --- a/source/paint/detail/image_process_provider.cpp +++ b/source/paint/detail/image_process_provider.cpp @@ -18,8 +18,8 @@ namespace paint image_process_provider::image_process_provider() { - add(stretch_, "bilinear interoplation"); - add(stretch_, "proximal interoplation"); + add(stretch_, "bilinear interpolation"); + add(stretch_, "proximal interpolation"); add(alpha_blend_, "alpha_blend"); add(blend_, "blend"); add(line_, "bresenham_line"); diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 004a34a5..c217dd70 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -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(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 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; diff --git a/source/paint/pixel_buffer.cpp b/source/paint/pixel_buffer.cpp index 4297c476..81316842 100644 --- a/source/paint/pixel_buffer.cpp +++ b/source/paint/pixel_buffer.cpp @@ -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)) diff --git a/source/unicode_bidi.cpp b/source/unicode_bidi.cpp index 32ca0541..26eaf512 100644 --- a/source/unicode_bidi.cpp +++ b/source/unicode_bidi.cpp @@ -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.