From 2abae1dd68d73bd3cc3dd4a6e821213ace9c84a4 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 8 Mar 2019 06:11:21 +0800 Subject: [PATCH] refactoring --- include/nana/gui/detail/general_events.hpp | 32 ++---- include/nana/gui/detail/window_manager.hpp | 6 +- include/nana/gui/programming_interface.hpp | 3 +- .../gui/widgets/skeletons/text_editor.hpp | 11 +- source/gui/detail/inner_fwd_implement.hpp | 2 +- source/gui/detail/native_window_interface.cpp | 2 + source/gui/detail/window_manager.cpp | 101 +++++------------- source/gui/dragger.cpp | 10 +- source/gui/programming_interface.cpp | 44 ++++++-- source/gui/widgets/skeletons/text_editor.cpp | 80 ++++---------- source/gui/widgets/textbox.cpp | 4 +- 11 files changed, 106 insertions(+), 189 deletions(-) diff --git a/include/nana/gui/detail/general_events.hpp b/include/nana/gui/detail/general_events.hpp index e912d7b5..c2595fe5 100644 --- a/include/nana/gui/detail/general_events.hpp +++ b/include/nana/gui/detail/general_events.hpp @@ -298,34 +298,16 @@ namespace nana }; } - static std::function build_second(fn_type&& fn, void(fn_type::*)(arg_reference)) + template + static std::function build_second(Tfn&& fn, Ret(fn_type::*)(arg_reference)) { - return std::move(fn); + return std::forward(fn); } - static std::function build_second(fn_type&& fn, void(fn_type::*)(arg_reference) const) + template + static std::function build_second(Tfn&& fn, Ret(fn_type::*)(arg_reference)const) { - return std::move(fn); - } - - static std::function build_second(fn_type& fn, void(fn_type::*)(arg_reference)) - { - return fn; - } - - static std::function build_second(fn_type& fn, void(fn_type::*)(arg_reference) const) - { - return fn; - } - - static std::function build_second(const fn_type& fn, void(fn_type::*)(arg_reference)) - { - return fn; - } - - static std::function build_second(const fn_type& fn, void(fn_type::*)(arg_reference) const) - { - return fn; + return std::forward(fn); } template @@ -421,7 +403,7 @@ namespace nana typedef typename std::remove_reference::type arg_type; static_assert(std::is_convertible::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function."); - static std::function build(Ret(*fn)(Arg)) + static std::function build(Ret(*fn)(Arg2)) { return[fn](arg_reference arg){ fn(arg); diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index 474cd2ea..82e3c57c 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -118,10 +118,6 @@ namespace detail void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false); void map_requester(core_window_t*); - bool get_graphics(core_window_t*, nana::paint::graphics&); - bool get_visual_rectangle(core_window_t*, nana::rectangle&); - - std::vector get_children(core_window_t*) const; 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); @@ -144,7 +140,6 @@ namespace detail bool register_shortkey(core_window_t*, unsigned long key); void unregister_shortkey(core_window_t*, bool with_children); - std::vector> shortkeys(core_window_t*, bool with_children); core_window_t* find_shortkey(native_window_type, unsigned long key); @@ -154,6 +149,7 @@ namespace detail void _m_disengage(core_window_t*, core_window_t* for_new); void _m_destroy(core_window_t*); void _m_move_core(core_window_t*, const point& delta); + void _m_shortkeys(core_window_t*, bool with_chlidren, std::vector>& keys) const; core_window_t* _m_find(core_window_t*, const point&); static bool _m_effective(core_window_t*, const point& root_pos); private: diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 2fdd3c14..48a773ce 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -230,7 +230,6 @@ namespace API window root(native_window_type); ///< Retrieves the native window of a Nana.GUI window. void fullscreen(window, bool); - bool enabled_double_click(window, bool); void close_window(window); void show_window(window, bool show); ///< Sets a window visible state. @@ -239,6 +238,7 @@ namespace API bool visible(window); window get_parent_window(window); window get_owner_window(window); + bool set_parent_window(window, window new_parent); template @@ -435,6 +435,7 @@ namespace API /// 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. void take_active(window, bool has_active, window take_if_has_active_false); + /// Copies the graphics of a specified to a new graphics object. bool window_graphics(window, nana::paint::graphics&); bool root_graphics(window, nana::paint::graphics&); bool get_visual_rectangle(window, nana::rectangle&); diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index 89b3651b..5f691543 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -136,13 +136,11 @@ namespace nana{ namespace widgets void enable_background(bool); void enable_background_counterpart(bool); - void undo_enabled(bool); - bool undo_enabled() const; + void undo_clear(); void undo_max_steps(std::size_t); std::size_t undo_max_steps() const; renderers& customized_renderers(); - void clear_undo(); ///< same with undo_max_steps(0) unsigned line_height() const; unsigned screen_lines(bool completed_line = false) const; @@ -203,12 +201,11 @@ namespace nana{ namespace widgets void del(); void backspace(bool record_undo, bool perform_event); void undo(bool reverse); - void set_undo_queue_length(std::size_t len); void move_ns(bool to_north); //Moves up and down void move_left(); void move_right(); const upoint& mouse_caret(const point& screen_pos, bool stay_in_view); - const upoint& caret() const; + const upoint& caret() const noexcept; point caret_screen_pos() const; bool scroll(bool upwards, bool vertical); @@ -218,8 +215,8 @@ namespace nana{ namespace widgets void mouse_pressed(const arg_mouse& arg); bool select_word(const arg_mouse& arg); - skeletons::textbase& textbase(); - const skeletons::textbase& textbase() const; + skeletons::textbase& textbase() noexcept; + const skeletons::textbase& textbase() const noexcept; bool try_refresh(); diff --git a/source/gui/detail/inner_fwd_implement.hpp b/source/gui/detail/inner_fwd_implement.hpp index ed8ef73d..5c66323c 100644 --- a/source/gui/detail/inner_fwd_implement.hpp +++ b/source/gui/detail/inner_fwd_implement.hpp @@ -46,7 +46,7 @@ namespace nana{ void umake(window wd); - std::vector keys(window wd) const; + const std::vector* keys(window wd) const; window find(unsigned long key) const; private: diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index a9753bc7..2d2d0e58 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -1444,6 +1444,8 @@ namespace nana{ { if(owner) return owner; + + return x11_parent_window(wd); } else if(window_relationship::owner == rsp) return owner; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 78ea0927..6349685d 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -111,17 +111,17 @@ namespace nana } } - std::vector shortkey_container::keys(window wd) const + const std::vector* shortkey_container::keys(window wd) const { if (wd) { for (auto & m : impl_->base) { if (m.handle == wd) - return m.keys; + return &m.keys; } } - return{}; + return nullptr; } window shortkey_container::find(unsigned long key) const @@ -1111,41 +1111,6 @@ namespace detail wd->other.mapping_requester.clear(); } - //get_graphics - //@brief: Get a copy of the graphics object of a window. - // the copy of the graphics object has a same buf handle with the graphics object's, they are count-refered - // here returns a reference that because the framework does not guarantee the wnd's - // graphics object available after a get_graphics call. - bool window_manager::get_graphics(core_window_t* wd, nana::paint::graphics& result) - { - //Thread-Safe Required! - std::lock_guard lock(mutex_); - if (!impl_->wd_register.available(wd)) - return false; - - result.make(wd->drawer.graphics.size()); - result.bitblt(0, 0, wd->drawer.graphics); - window_layer::paste_children_to_graphics(wd, result); - return true; - } - - bool window_manager::get_visual_rectangle(core_window_t* wd, nana::rectangle& r) - { - //Thread-Safe Required! - std::lock_guard lock(mutex_); - return (impl_->wd_register.available(wd) ? - window_layer::read_visual_rectangle(wd, r) : - false); - } - - std::vector window_manager::get_children(core_window_t* wd) const - { - std::lock_guard lock(mutex_); - if (impl_->wd_register.available(wd)) - return wd->children; - return{}; - } - bool window_manager::set_parent(core_window_t* wd, core_window_t* newpa) { //Thread-Safe Required! @@ -1351,7 +1316,6 @@ namespace detail } } - // preconditions of get_tabstop: tabstop is not empty and at least one window is visible window_manager::core_window_t* get_tabstop(window_manager::core_window_t* wd, bool forward) { @@ -1464,9 +1428,8 @@ namespace detail std::lock_guard lock(mutex_); if (impl_->wd_register.available(wd)) { - auto object = root_runtime(wd->root); - if(object) - return object->shortkeys.make(reinterpret_cast(wd), key); + //the root runtime must exist, because the wd is valid. Otherse, it's bug of library + return root_runtime(wd->root)->shortkeys.make(reinterpret_cast(wd), key); } return false; } @@ -1489,35 +1452,6 @@ namespace detail } } - auto window_manager::shortkeys(core_window_t* wd, bool with_children) -> std::vector> - { - std::vector> result; - - //Thread-Safe Required! - std::lock_guard lock(mutex_); - if (impl_->wd_register.available(wd)) - { - auto root_rt = root_runtime(wd->root); - if (root_rt) - { - auto keys = root_rt->shortkeys.keys(reinterpret_cast(wd)); - for (auto key : keys) - result.emplace_back(wd, key); - - if (with_children) - { - for (auto child : wd->children) - { - auto child_keys = shortkeys(child, true); - std::copy(child_keys.begin(), child_keys.end(), std::back_inserter(result)); - } - } - } - } - - return result; - } - window_manager::core_window_t* window_manager::find_shortkey(native_window_type native_window, unsigned long key) { if(native_window) @@ -1577,7 +1511,6 @@ namespace detail { auto * const wdpa = wd->parent; - bool established = (for_new && (wdpa != for_new)); decltype(for_new->root_widget->other.attribute.root) pa_root_attr = nullptr; @@ -1603,7 +1536,7 @@ namespace detail if (root_attr->menubar && check_tree(wd, root_attr->menubar)) root_attr->menubar = nullptr; - sk_holder = shortkeys(wd, true); + _m_shortkeys(wd, true, sk_holder); } else { @@ -1815,6 +1748,28 @@ namespace detail } } + void window_manager::_m_shortkeys(core_window_t* wd, bool with_children, std::vector>& keys) const + { + if (impl_->wd_register.available(wd)) + { + //The root_rt must exist, because wd is valid. Otherwise, it's a bug of the library. + auto root_rt = root_runtime(wd->root); + + auto pkeys = root_rt->shortkeys.keys(reinterpret_cast(wd)); + if (pkeys) + { + for (auto key : *pkeys) + keys.emplace_back(wd, key); + } + + if (with_children) + { + for (auto child : wd->children) + _m_shortkeys(child, true, keys); + } + } + } + //_m_find //@brief: find a window on root window through a given root coordinate. // the given root coordinate must be in the rectangle of wnd. diff --git a/source/gui/dragger.cpp b/source/gui/dragger.cpp index 44ea2254..946273c7 100644 --- a/source/gui/dragger.cpp +++ b/source/gui/dragger.cpp @@ -1,7 +1,7 @@ /* * A Dragger Implementation * 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 @@ -93,9 +93,7 @@ namespace nana for (auto & t : targets_) { t.origin = API::window_position(t.wd); - window owner = API::get_owner_window(t.wd); - if (owner) - API::calc_screen_point(owner, t.origin); + API::calc_screen_point(API::get_owner_window(t.wd), t.origin); } break; case event_code::mouse_move: @@ -108,10 +106,8 @@ namespace nana { if (API::is_window_zoomed(t.wd, true) == false) { - auto owner = API::get_owner_window(t.wd); auto wdps = t.origin; - if (owner) - API::calc_window_point(owner, wdps); + API::calc_window_point(API::get_owner_window(t.wd), wdps); switch (t.move_direction) { diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 3218069d..148667ff 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -90,16 +91,21 @@ namespace API void enum_widgets_function_base::enum_widgets(window wd, bool recursive) { - using basic_window = ::nana::detail::basic_window; + auto iwd = reinterpret_cast(wd); internal_scope_guard lock; - - auto children = restrict::wd_manager().get_children(reinterpret_cast(wd)); - for (auto child : children) + if (restrict::wd_manager().available(iwd)) { - auto widget_ptr = API::get_widget(reinterpret_cast(child)); - if (widget_ptr) + //Use a copy, because enum function may close a child window and the original children container would be changed, + //in the situation, the walking thorugh directly to the iwd->children would cause error. + auto children = iwd->children; + + for (auto child : children) { + auto widget_ptr = API::get_widget(reinterpret_cast(child)); + if (!widget_ptr) + continue; + _m_enum_fn(widget_ptr); if (recursive) enum_widgets(reinterpret_cast(child), recursive); @@ -643,7 +649,15 @@ namespace API auto iwd = reinterpret_cast(wd); internal_scope_guard lock; if (restrict::wd_manager().available(iwd)) + { + if (category::flags::root == iwd->other.category) + { + return reinterpret_cast(restrict::wd_manager().root( + interface_type::get_window(iwd->root, window_relationship::parent) + )); + } return reinterpret_cast(iwd->parent); + } return nullptr; } @@ -1308,7 +1322,16 @@ namespace API bool window_graphics(window wd, nana::paint::graphics& graph) { - return restrict::wd_manager().get_graphics(reinterpret_cast(wd), graph); + auto iwd = reinterpret_cast(wd); + + internal_scope_guard lock; + if (!restrict::wd_manager().available(iwd)) + return false; + + graph.make(iwd->drawer.graphics.size()); + graph.bitblt(0, 0, iwd->drawer.graphics); + nana::detail::window_layout::paste_children_to_graphics(iwd, graph); + return true; } bool root_graphics(window wd, nana::paint::graphics& graph) @@ -1325,7 +1348,12 @@ namespace API bool get_visual_rectangle(window wd, nana::rectangle& r) { - return restrict::wd_manager().get_visual_rectangle(reinterpret_cast(wd), r); + auto iwd = reinterpret_cast(wd); + internal_scope_guard lock; + if (restrict::wd_manager().available(iwd)) + return nana::detail::window_layout::read_visual_rectangle(iwd, r); + + return false; } void typeface(window wd, const nana::paint::font& font) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index f5af56a6..d3878e75 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -49,7 +49,7 @@ namespace nana { using command = EnumCommand; using container = std::deque>>; - void clear() + void clear() noexcept { commands_.clear(); pos_ = 0; @@ -67,21 +67,9 @@ namespace nana { return max_steps_; } - void enable(bool enb) - { - enabled_ = enb; - if (!enb) - clear(); - } - - bool enabled() const - { - return enabled_; - } - void push(std::unique_ptr> && ptr) { - if (!ptr || !enabled_) + if (!ptr) return; if (pos_ < commands_.size()) @@ -100,7 +88,7 @@ namespace nana { ++pos_; } - std::size_t count(bool is_undo) const + std::size_t count(bool is_undo) const noexcept { return (is_undo ? pos_ : commands_.size() - pos_); } @@ -108,10 +96,7 @@ namespace nana { void undo() { if (pos_ > 0) - { - --pos_; - commands_[pos_].get()->execute(false); - } + commands_[--pos_].get()->execute(false); } void redo() @@ -122,7 +107,6 @@ namespace nana { private: container commands_; - bool enabled_{ true }; std::size_t max_steps_{ 30 }; std::size_t pos_{ 0 }; }; @@ -763,9 +747,7 @@ namespace nana { if (second < linemtr_.size()) linemtr_.erase(linemtr_.begin() + first + 1, linemtr_.begin() + second + 1); - auto const width_px = editor_.width_pixels(); - - pre_calc_line(first, width_px); + pre_calc_line(first, editor_.width_pixels()); } void add_lines(std::size_t pos, std::size_t lines) override @@ -1074,8 +1056,8 @@ namespace nana { //class text_editor - text_editor::text_editor(window wd, graph_reference graph, const text_editor_scheme* schm) - : impl_(new implementation), + text_editor::text_editor(window wd, graph_reference graph, const text_editor_scheme* schm): + impl_(new implementation), window_(wd), graph_(graph), scheme_(schm) @@ -1400,14 +1382,11 @@ namespace nana { impl_->counterpart.buffer.release(); } - void text_editor::undo_enabled(bool enb) + void text_editor::undo_clear() { - impl_->undo.enable(enb); - } - - bool text_editor::undo_enabled() const - { - return impl_->undo.enabled(); + auto size = this->undo_max_steps(); + impl_->undo.max_steps(0); + impl_->undo.max_steps(size); } void text_editor::undo_max_steps(std::size_t maxs) @@ -1420,13 +1399,6 @@ namespace nana { return impl_->undo.max_steps(); } - void text_editor::clear_undo() - { - auto size = impl_->undo.max_steps(); - impl_->undo.max_steps(0); - impl_->undo.max_steps(size); - } - auto text_editor::customized_renderers() -> renderers& { return impl_->customized_renderers; @@ -1435,12 +1407,11 @@ namespace nana { unsigned text_editor::line_height() const { unsigned ascent, descent, internal_leading; - unsigned px = 0; - if (graph_.text_metrics(ascent, descent, internal_leading)) - px = ascent + descent; + if (!graph_.text_metrics(ascent, descent, internal_leading)) + return 0; - impl_->cview->step(px, false); - return px; + impl_->cview->step(ascent + descent, false); + return ascent + descent; } unsigned text_editor::screen_lines(bool completed_line) const @@ -1449,13 +1420,7 @@ namespace nana { if (line_px) { auto h = impl_->cview->view_area().height; - if (graph_ && h) - { - if (completed_line) - return (h / line_px); - - return (h / line_px + (h % line_px ? 1 : 0)); - } + return (h / line_px) + ((completed_line || !(h % line_px)) ? 0 : 1); } return 0; } @@ -1652,12 +1617,12 @@ namespace nana { return true; } - textbase & text_editor::textbase() + textbase & text_editor::textbase() noexcept { return impl_->textbase; } - const textbase & text_editor::textbase() const + const textbase & text_editor::textbase() const noexcept { return impl_->textbase; } @@ -2327,11 +2292,6 @@ namespace nana { impl_->try_refresh = sync_graph::refresh; } - void text_editor::set_undo_queue_length(std::size_t len) - { - impl_->undo.max_steps(len); - } - void text_editor::move_ns(bool to_north) { const bool redraw_required = _m_cancel_select(0); @@ -2566,7 +2526,7 @@ namespace nana { return points_.caret; } - const upoint& text_editor::caret() const + const upoint& text_editor::caret() const noexcept { return points_.caret; } @@ -3344,7 +3304,7 @@ namespace nana { int text_editor::_m_text_topline() const { auto px = static_cast(line_height()); - return (px ? (impl_->cview->origin().y / px) : px); + return (px ? (impl_->cview->origin().y / px) : 0); } int text_editor::_m_text_x(const text_section& sct) const diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index 6e0a0ecc..6ea644e2 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -671,7 +671,7 @@ namespace drawerbase { void textbox::clear_undo() { - get_drawer_trigger().editor()->clear_undo(); + get_drawer_trigger().editor()->undo_clear(); } void textbox::set_highlight(const std::string& name, const ::nana::color& fgcolor, const ::nana::color& bgcolor) @@ -792,7 +792,7 @@ namespace drawerbase { internal_scope_guard lock; auto editor = get_drawer_trigger().editor(); if (editor) - editor->set_undo_queue_length(len); + editor->undo_max_steps(len); } std::size_t textbox::display_line_count() const noexcept