From 64899a3d6a1b2776271f666b03a6bd177d430a57 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 28 Aug 2017 21:09:04 +0800 Subject: [PATCH 1/6] add functions to menubar for auto-close when mouse leave --- include/nana/gui/widgets/menu.hpp | 5 ++++ include/nana/gui/widgets/menubar.hpp | 11 ++++++++ source/gui/widgets/menu.cpp | 5 ++++ source/gui/widgets/menubar.cpp | 40 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/include/nana/gui/widgets/menu.hpp b/include/nana/gui/widgets/menu.hpp index f8ec1167..b2315ac0 100644 --- a/include/nana/gui/widgets/menu.hpp +++ b/include/nana/gui/widgets/menu.hpp @@ -181,6 +181,11 @@ namespace nana void renderer(const pat::cloneable&); ///< Sets a user-defined renderer. const pat::cloneable& renderer() const; + /// Returns the handle of menu window + /** + * @return handle of menu window, nullptr if the menu hasn't been popped up. + */ + window handle() const; private: void _m_popup(window, const point& position, bool called_by_menubar); private: diff --git a/include/nana/gui/widgets/menubar.hpp b/include/nana/gui/widgets/menubar.hpp index a76b21bb..c245df4a 100644 --- a/include/nana/gui/widgets/menubar.hpp +++ b/include/nana/gui/widgets/menubar.hpp @@ -64,6 +64,7 @@ namespace nana nana::menu* push_back(const std::string&); nana::menu* at(size_t) const; std::size_t size() const; + bool cancel(); private: void attached(widget_reference, graph_reference) override; void refresh(graph_reference) override; @@ -126,6 +127,16 @@ namespace nana menu& push_back(const std::string&); ///< Appends a new (empty) menu. menu& at(size_t index) const; ///< Gets the menu specified by index. std::size_t length() const; ///< Number of menus. + + /// Deselects the menu + /** + * If a menu is popped up, the menu deselects the item and close the popuped menu. + * @return true if an item is deselected, false otherwise. + */ + bool cancel(); + + /// Determines the mouse is hovered on the menubar or its popped menu. + bool hovered() const; private: ::nana::event_handle evt_resized_{nullptr}; };//end class menubar diff --git a/source/gui/widgets/menu.cpp b/source/gui/widgets/menu.cpp index 36dbb7de..26b21812 100644 --- a/source/gui/widgets/menu.cpp +++ b/source/gui/widgets/menu.cpp @@ -1355,6 +1355,11 @@ namespace nana impl_->mbuilder.renderer(rd); } + window menu::handle() const + { + return (impl_->window_ptr ? impl_->window_ptr->handle() : nullptr); + } + void menu::_m_popup(window wd, const point& pos, bool called_by_menubar) { if (impl_->mbuilder.data().items.size()) diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp index 4ed24c67..ebf8420e 100644 --- a/source/gui/widgets/menubar.cpp +++ b/source/gui/widgets/menubar.cpp @@ -165,6 +165,15 @@ namespace nana return items_->cont().size(); } + bool trigger::cancel() + { + if (nana::npos == state_.active) + return false; + + _m_total_close(); + return true; + } + void trigger::attached(widget_reference widget, graph_reference graph) { graph_ = &graph; @@ -624,5 +633,36 @@ namespace nana { return get_drawer_trigger().size(); } + + bool menubar::cancel() + { + return get_drawer_trigger().cancel(); + } + + bool menubar::hovered() const + { + auto const native_handle = API::root(this->handle()); + if (native_handle) + { + auto wd = API::find_window(API::cursor_position()); + if (wd == this->handle()) + return true; + + while (wd) + { + auto owner = API::get_owner_window(wd); + if (API::root(owner) == native_handle) + { + for (std::size_t i = 0; i < get_drawer_trigger().size(); ++i) + { + if(get_drawer_trigger().at(i)->handle() == wd) + return true; + } + } + wd = owner; + } + } + return false; + } //end class menubar }//end namespace nana From fba40978519c68e8b9d854e47cec2ec518dc0ff5 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 31 Aug 2017 02:57:34 +0800 Subject: [PATCH 2/6] refactor menubar --- include/nana/gui/widgets/menubar.hpp | 42 +-- source/gui/widgets/menubar.cpp | 504 +++++++++++++-------------- 2 files changed, 254 insertions(+), 292 deletions(-) diff --git a/include/nana/gui/widgets/menubar.hpp b/include/nana/gui/widgets/menubar.hpp index c245df4a..2eb39a38 100644 --- a/include/nana/gui/widgets/menubar.hpp +++ b/include/nana/gui/widgets/menubar.hpp @@ -1,7 +1,7 @@ /* * A Menubar implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -58,13 +58,12 @@ namespace nana : public drawer_trigger { class itembase; + + struct essence; public: trigger(); ~trigger(); - nana::menu* push_back(const std::string&); - nana::menu* at(size_t) const; - std::size_t size() const; - bool cancel(); + essence& ess() const; private: void attached(widget_reference, graph_reference) override; void refresh(graph_reference) override; @@ -77,38 +76,9 @@ namespace nana void key_release(graph_reference, const arg_keyboard&) override; void shortkey(graph_reference, const arg_keyboard&) override; private: - void _m_move(bool to_left); - bool _m_popup_menu(); - void _m_total_close(); - bool _m_close_menu(); - std::size_t _m_item_by_pos(const ::nana::point&); - bool _m_track_mouse(const ::nana::point&); + void _m_move(graph_reference, bool to_left); private: - widget *widget_; - paint::graphics *graph_; - - itembase* items_; - - struct state_type - { - enum behavior_t - { - behavior_none, behavior_focus, behavior_menu, - }; - - state_type(); - - std::size_t active; - behavior_t behavior; - - bool menu_active; - bool passive_close; - - bool nullify_mouse; - - nana::menu *menu; - nana::point mouse_pos; - }state_; + essence * const ess_; }; }//end namespace menubar }//end namespace drawerbase diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp index ebf8420e..342bc132 100644 --- a/source/gui/widgets/menubar.cpp +++ b/source/gui/widgets/menubar.cpp @@ -30,7 +30,7 @@ namespace nana { struct item_type { - item_type(const native_string_type text, unsigned long shortkey) + item_type(const native_string_type& text, unsigned long shortkey) : text(text), shortkey(shortkey) {} @@ -83,6 +83,131 @@ namespace nana container cont_; }; + struct trigger::essence + { + widget *widget_ptr{ nullptr }; + //paint::graphics *graph{ nullptr }; + + itembase items; + + enum class behavior + { + none, focus, menu, + }; + + struct state_type + { + std::size_t active{ nana::npos }; + behavior behave{ behavior::none }; + + bool menu_active{ false }; + bool passive_close{ true }; + + bool nullify_mouse{ false }; + + nana::menu *menu{ nullptr }; + nana::point mouse_pos; + }state; + + //functions + nana::menu& push_back(const std::string& text) + { + wchar_t shortkey; + API::transform_shortkey_text(text, shortkey, nullptr); + + if (shortkey) + API::register_shortkey(this->widget_ptr->handle(), shortkey); + + this->items.append(to_nstring(text), shortkey); + API::refresh_window(this->widget_ptr->handle()); + + return this->items.cont()[this->items.cont().size() - 1]->menu_obj; + } + + bool cancel() + { + if (nana::npos == state.active) + return false; + + this->close_menu(); + state.menu_active = false; + state.behave = behavior::none; + + auto pos = API::cursor_position(); + API::calc_window_point(widget_ptr->handle(), pos); + state.active = find(pos); + + return true; + } + + + bool open_menu() + { + auto pos = state.active; + if (pos >= items.cont().size()) + return false; + + auto item_ptr = items.cont()[pos]; + + if (state.menu_active && (state.menu != &(item_ptr->menu_obj))) + { + API::dev::delay_restore(true); + this->close_menu(); + API::dev::delay_restore(false); + state.active = pos; + + state.menu = &(item_ptr->menu_obj); + state.menu->destroy_answer([this] + { + state.menu = nullptr; + if (state.passive_close) + { + cancel(); + API::refresh_window(*widget_ptr); + } + }); + + if (API::focus_window() != this->widget_ptr->handle()) + API::focus_window(widget_ptr->handle()); + menu_accessor::popup(*state.menu, *widget_ptr, item_ptr->pos.x, item_ptr->pos.y + static_cast(item_ptr->size.height)); + return true; + } + return false; + } + + bool close_menu() + { + if (state.menu) + { + state.passive_close = false; + state.menu->close(); + state.passive_close = true; + state.menu = nullptr; + return true; + } + return false; + } + + std::size_t find(const ::nana::point& pos) + { + if ((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25)) + { + int item_x = 2; + std::size_t index = 0; + for (auto i : items.cont()) + { + if (item_x <= pos.x && pos.x < item_x + static_cast(i->size.width)) + return index; + + item_x += i->size.width; + ++index; + } + } + + return npos; + } + }; + //class item_renderer item_renderer::item_renderer(window wd, graph_reference graph) :graph_(graph), scheme_ptr_(static_cast(API::dev::get_scheme(wd))) @@ -91,19 +216,17 @@ namespace nana void item_renderer::background(const nana::point& pos, const nana::size& size, state item_state) { auto bground = scheme_ptr_->text_fgcolor; - ::nana::color border, body, corner; + ::nana::color border, body; switch (item_state) { case state::highlighted: border = scheme_ptr_->border_highlight; body = scheme_ptr_->body_highlight; - corner = body.blend(bground, 0.5); break; case state::selected: border = scheme_ptr_->border_selected; body = scheme_ptr_->body_selected; - corner = body.blend(bground, 0.5); break; default: //Don't process other states. return; @@ -112,7 +235,7 @@ namespace nana nana::rectangle r(pos, size); graph_.rectangle(r, false, border); - graph_.palette(false, corner); + graph_.palette(false, body.blend(bground, 0.5)); paint::draw{ graph_ }.corner(r, 1); graph_.rectangle(r.pare_off(1), true, body); @@ -127,86 +250,52 @@ namespace nana //class trigger trigger::trigger() - : widget_(nullptr) - , graph_(nullptr) - , items_(new itembase) {} + : ess_(new essence) + {} trigger::~trigger() { - delete items_; + delete ess_; } - nana::menu* trigger::push_back(const std::string& text) + auto trigger::ess() const -> essence& { - wchar_t shkey; - API::transform_shortkey_text(text, shkey, nullptr); - - if(shkey) - API::register_shortkey(widget_->handle(), shkey); - - auto pos = items_->cont().size(); - items_->append(to_nstring(text), shkey); - refresh(*graph_); - API::update_window(*widget_); - - return at(pos); - } - - nana::menu* trigger::at(std::size_t pos) const - { - if (pos < items_->cont().size()) - return &(items_->cont()[pos]->menu_obj); - - return nullptr; - } - - std::size_t trigger::size() const - { - return items_->cont().size(); - } - - bool trigger::cancel() - { - if (nana::npos == state_.active) - return false; - - _m_total_close(); - return true; + return *ess_; } void trigger::attached(widget_reference widget, graph_reference graph) { - graph_ = &graph; - widget_ = &widget; + ess_->widget_ptr = &widget; } void trigger::refresh(graph_reference graph) { - auto bgcolor = API::bgcolor(*widget_); - graph_->rectangle(true, bgcolor); + auto bgcolor = API::bgcolor(*ess_->widget_ptr); - item_renderer ird(*widget_, graph); + graph.rectangle(true, bgcolor); + + item_renderer ird{ *ess_->widget_ptr, graph }; nana::point item_pos(2, 2); nana::size item_s(0, 23); unsigned long index = 0; - for (auto i : items_->cont()) + for (auto pm : ess_->items.cont()) { //Transform the text if it contains the hotkey character wchar_t hotkey; ::std::wstring::size_type hotkey_pos; - auto text = API::transform_shortkey_text(to_utf8(i->text), hotkey, &hotkey_pos); + auto text = API::transform_shortkey_text(to_utf8(pm->text), hotkey, &hotkey_pos); nana::size text_s = graph.text_extent_size(text); item_s.width = text_s.width + 16; - i->pos = item_pos; - i->size = item_s; + pm->pos = item_pos; + pm->size = item_s; using state = item_renderer::state; - state item_state = (index != state_.active ? state::normal : (state_.menu_active ? state::selected : state::highlighted)); + state item_state = (index != ess_->state.active ? state::normal : (ess_->state.menu_active ? state::selected : state::highlighted)); ird.background(item_pos, item_s, item_state); if (state::selected == item_state) @@ -223,59 +312,67 @@ namespace nana API::dev::draw_shortkey_underline(graph, text, hotkey, hotkey_pos, { item_pos.x + 8, item_pos.y + text_top_off }, ird.scheme_ptr()->text_fgcolor); - item_pos.x += i->size.width; + item_pos.x += pm->size.width; ++index; } } void trigger::mouse_move(graph_reference graph, const arg_mouse& arg) { - if (arg.pos != state_.mouse_pos) - state_.nullify_mouse = false; + + if (arg.pos != ess_->state.mouse_pos) + ess_->state.nullify_mouse = false; bool popup = false; - if(state_.behavior == state_type::behavior_focus) + if(essence::behavior::focus == ess_->state.behave) { - auto index = _m_item_by_pos(arg.pos); - if(index != npos && state_.active != index) + auto index = ess_->find(arg.pos); + if(index != npos && ess_->state.active != index) { - state_.active = index; + ess_->state.active = index; + popup = true; + } + } + else if (!ess_->state.nullify_mouse) + { + auto which = ess_->find(arg.pos); + if ((which != ess_->state.active) && (which != npos || (false == ess_->state.menu_active))) + { + ess_->state.active = which; popup = true; } } - else - popup = _m_track_mouse(arg.pos); if(popup) { - _m_popup_menu(); + ess_->open_menu(); refresh(graph); API::dev::lazy_refresh(); } - state_.mouse_pos = arg.pos; + ess_->state.mouse_pos = arg.pos; } void trigger::mouse_leave(graph_reference graph, const arg_mouse& arg) { - state_.nullify_mouse = false; + ess_->state.nullify_mouse = false; mouse_move(graph, arg); } void trigger::mouse_down(graph_reference graph, const arg_mouse& arg) { - state_.nullify_mouse = false; - state_.active = _m_item_by_pos(arg.pos); + ess_->state.nullify_mouse = false; + ess_->state.active = ess_->find(arg.pos); - if (npos != state_.active) + if (npos != ess_->state.active) { - if (!state_.menu_active) - state_.menu_active = true; + if (!ess_->state.menu_active) + ess_->state.menu_active = true; - _m_popup_menu(); + ess_->open_menu(); } else - _m_total_close(); + ess_->cancel(); refresh(graph); API::dev::lazy_refresh(); @@ -283,17 +380,17 @@ namespace nana void trigger::mouse_up(graph_reference graph, const arg_mouse&) { - state_.nullify_mouse = false; + ess_->state.nullify_mouse = false; - if(state_.behavior != state_.behavior_menu) + if(ess_->state.behave != essence::behavior::menu) { - if(state_.menu_active) - state_.behavior = state_.behavior_menu; + if(ess_->state.menu_active) + ess_->state.behave = essence::behavior::menu; } else { - state_.behavior = state_.behavior_none; - _m_total_close(); + ess_->state.behave = essence::behavior::none; + ess_->cancel(); refresh(graph); API::dev::lazy_refresh(); } @@ -301,13 +398,13 @@ namespace nana void trigger::focus(graph_reference graph, const arg_focus& arg) { - if((arg.getting == false) && (state_.active != npos)) + if((arg.getting == false) && (ess_->state.active != npos)) { - state_.behavior = state_type::behavior_none; - state_.nullify_mouse = true; - state_.menu_active = false; - _m_close_menu(); - state_.active = npos; + ess_->state.behave = essence::behavior::none; + ess_->state.nullify_mouse = true; + ess_->state.menu_active = false; + ess_->close_menu(); + ess_->state.active = npos; refresh(graph); API::dev::lazy_refresh(); } @@ -315,53 +412,55 @@ namespace nana void trigger::key_press(graph_reference graph, const arg_keyboard& arg) { - state_.nullify_mouse = true; - if(state_.menu) + ess_->state.nullify_mouse = true; + + auto & menu_ptr = ess_->state.menu; + if(ess_->state.menu) { switch(arg.key) { case keyboard::os_arrow_down: case keyboard::backspace: case keyboard::os_arrow_up: - state_.menu->goto_next(keyboard::os_arrow_down == arg.key); + menu_ptr->goto_next(keyboard::os_arrow_down == arg.key); break; case keyboard::os_arrow_right: - if(state_.menu->goto_submen() == false) - _m_move(false); + if(menu_ptr->goto_submen() == false) + _m_move(graph, false); break; case keyboard::os_arrow_left: - if(state_.menu->exit_submenu() == false) - _m_move(true); + if(menu_ptr->exit_submenu() == false) + _m_move(graph, true); break; case keyboard::escape: - if(state_.menu->exit_submenu() == false) + if(menu_ptr->exit_submenu() == false) { - _m_close_menu(); - state_.behavior = state_.behavior_focus; - state_.menu_active = false; + ess_->close_menu(); + ess_->state.behave = essence::behavior::focus; + ess_->state.menu_active = false; } break; case keyboard::enter: - state_.menu->pick(); + menu_ptr->pick(); break; default: //Katsuhisa Yuasa: menubar key_press improvements //send_shortkey has 3 states, 0 = UNKNOWN KEY, 1 = ITEM, 2 = GOTO SUBMENU - int sk_state = state_.menu->send_shortkey(arg.key); + int sk_state = menu_ptr->send_shortkey(arg.key); switch(sk_state) { case 0: //UNKNOWN KEY break; case 1: //ITEM - if (state_.active != npos) + if (ess_->state.active != npos) { - _m_total_close(); + ess_->cancel(); if (arg.key == 18) //ALT - state_.behavior = state_.behavior_focus; + ess_->state.behave = essence::behavior::focus; } break; case 2: //GOTO SUBMENU - state_.menu->goto_submen(); + menu_ptr->goto_submen(); break; default: break; } @@ -375,30 +474,30 @@ namespace nana case keyboard::os_arrow_right: case keyboard::backspace: case keyboard::os_arrow_left: - _m_move(keyboard::os_arrow_right != arg.key); + _m_move(graph, keyboard::os_arrow_right != arg.key); break; case keyboard::os_arrow_up: case keyboard::os_arrow_down: case keyboard::enter: - state_.menu_active = true; - if(_m_popup_menu()) - state_.menu->goto_next(true); + ess_->state.menu_active = true; + if(ess_->open_menu()) + menu_ptr->goto_next(true); break; case keyboard::escape: - if(state_.behavior == state_.behavior_focus) + if(essence::behavior::focus == ess_->state.behave) { - state_.active= npos; - state_.behavior = state_.behavior_none; + ess_->state.active= npos; + ess_->state.behave = essence::behavior::none; } break; default: - auto index = items_->find(arg.key); + auto index = ess_->items.find(arg.key); if(index != npos) { - state_.active = index; - state_.menu_active = true; - if(_m_popup_menu()) - state_.menu->goto_next(true); + ess_->state.active = index; + ess_->state.menu_active = true; + if(ess_->open_menu()) + menu_ptr->goto_next(true); } break; } @@ -412,20 +511,20 @@ namespace nana { if(arg.key == 18) { - if(state_.behavior == state_type::behavior_none) + if(essence::behavior::none == ess_->state.behave) { - state_.behavior = state_type::behavior_focus; - state_.active = 0; + ess_->state.behave = essence::behavior::focus; + ess_->state.active = 0; } else { - state_.behavior = state_type::behavior_none; + ess_->state.behave = essence::behavior::none; auto pos = API::cursor_position(); - API::calc_window_point(widget_->handle(), pos); - state_.active = _m_item_by_pos(pos); + API::calc_window_point(ess_->widget_ptr->handle(), pos); + ess_->state.active = ess_->find(pos); } - state_.menu_active = false; + ess_->state.menu_active = false; refresh(graph); API::dev::lazy_refresh(); } @@ -433,31 +532,31 @@ namespace nana void trigger::shortkey(graph_reference graph, const arg_keyboard& arg) { - API::focus_window(widget_->handle()); + API::focus_window(ess_->widget_ptr->handle()); - auto index = items_->find(arg.key); - if(index != npos && (index != state_.active || nullptr == state_.menu)) + auto index = ess_->items.find(arg.key); + if(index != npos && (index != ess_->state.active || nullptr == ess_->state.menu)) { - _m_close_menu(); - state_.menu_active = true; - state_.nullify_mouse = true; - state_.active = index; + ess_->close_menu(); + ess_->state.menu_active = true; + ess_->state.nullify_mouse = true; + ess_->state.active = index; - if(_m_popup_menu()) - state_.menu->goto_next(true); + if(ess_->open_menu()) + ess_->state.menu->goto_next(true); refresh(graph); API::dev::lazy_refresh(); - state_.behavior = state_.behavior_menu; + ess_->state.behave = essence::behavior::menu; } } - void trigger::_m_move(bool to_left) + void trigger::_m_move(graph_reference graph, bool to_left) { - if(items_->cont().empty()) return; + if(ess_->items.cont().empty()) return; - const std::size_t last_pos = items_->cont().size() - 1; - auto index = state_.active; + const std::size_t last_pos = ess_->items.cont().size() - 1; + auto index = ess_->state.active; if(to_left) { --index; @@ -471,121 +570,16 @@ namespace nana index = 0; } - if(index != state_.active) + if(index != ess_->state.active) { - state_.active = index; - refresh(*graph_); + ess_->state.active = index; + refresh(graph); API::dev::lazy_refresh(); - if(_m_popup_menu()) - state_.menu->goto_next(true); + if(ess_->open_menu()) + ess_->state.menu->goto_next(true); } } - - bool trigger::_m_popup_menu() - { - auto& items = items_->cont(); - - auto pos = state_.active; - if (pos >= items.size()) - return false; - - if(state_.menu_active && (state_.menu != &(items[pos]->menu_obj))) - { - API::dev::delay_restore(true); - _m_close_menu(); - API::dev::delay_restore(false); - state_.active = pos; - - auto & m = items[pos]; - state_.menu = &(m->menu_obj); - state_.menu->destroy_answer([this] - { - state_.menu = nullptr; - if (state_.passive_close) - { - _m_total_close(); - - refresh(*graph_); - API::update_window(widget_->handle()); - } - }); - - if (API::focus_window() != this->widget_->handle()) - API::focus_window(widget_->handle()); - menu_accessor::popup(*state_.menu, *widget_, m->pos.x, m->pos.y + static_cast(m->size.height)); - return true; - } - return false; - } - - void trigger::_m_total_close() - { - _m_close_menu(); - state_.menu_active = false; - state_.behavior = state_.behavior_none; - - auto pos = API::cursor_position(); - API::calc_window_point(widget_->handle(), pos); - state_.active = _m_item_by_pos(pos); - } - - bool trigger::_m_close_menu() - { - if(state_.menu) - { - state_.passive_close = false; - state_.menu->close(); - state_.passive_close = true; - state_.menu = nullptr; - return true; - } - return false; - } - - std::size_t trigger::_m_item_by_pos(const ::nana::point& pos) - { - if((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25)) - { - int item_x = 2; - std::size_t index = 0; - for(auto i : items_->cont()) - { - if(item_x <= pos.x && pos.x < item_x + static_cast(i->size.width)) - return index; - - item_x += i->size.width; - ++index; - } - } - - return npos; - } - - bool trigger::_m_track_mouse(const ::nana::point& pos) - { - if(state_.nullify_mouse == false) - { - auto which = _m_item_by_pos(pos); - if((which != state_.active) && (which != npos || (false == state_.menu_active))) - { - state_.active = which; - return true; - } - } - return false; - } - - //struct state_type - trigger::state_type::state_type() - : active(npos), - behavior(behavior_none), - menu_active(false), - passive_close(true), - nullify_mouse(false), - menu(nullptr) - {} - //end struct state_type //end class trigger }//end namespace menubar }//end namespace drawerbase @@ -608,7 +602,7 @@ namespace nana ::create(wd, rectangle(nana::size(API::window_size(wd).width, 28))); API::dev::set_menubar(handle(), true); - evt_resized_ = API::events(wd).resized.connect([this](const ::nana::arg_resized& arg) + evt_resized_ = API::events(wd).resized.connect_unignorable([this](const ::nana::arg_resized& arg) { auto sz = this->size(); sz.width = arg.width; @@ -618,25 +612,22 @@ namespace nana menu& menubar::push_back(const std::string& text) { - return *(get_drawer_trigger().push_back(text)); + return get_drawer_trigger().ess().push_back(text); } - menu& menubar::at(std::size_t index) const + menu& menubar::at(std::size_t pos) const { - auto p = get_drawer_trigger().at(index); - if(nullptr == p) - throw std::out_of_range("menubar::at, out of range"); - return *p; + return get_drawer_trigger().ess().items.cont().at(pos)->menu_obj; } std::size_t menubar::length() const { - return get_drawer_trigger().size(); + return get_drawer_trigger().ess().items.cont().size(); } bool menubar::cancel() { - return get_drawer_trigger().cancel(); + return get_drawer_trigger().ess().cancel(); } bool menubar::hovered() const @@ -648,14 +639,15 @@ namespace nana if (wd == this->handle()) return true; + auto & items = get_drawer_trigger().ess().items.cont(); while (wd) { auto owner = API::get_owner_window(wd); if (API::root(owner) == native_handle) { - for (std::size_t i = 0; i < get_drawer_trigger().size(); ++i) + for (auto p : items) { - if(get_drawer_trigger().at(i)->handle() == wd) + if (p->menu_obj.handle() == wd) return true; } } From 29fc286ba3fc3ea820ee03ee716db4e5e4aa135c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 31 Aug 2017 04:36:09 +0800 Subject: [PATCH 3/6] fix bug that throws exception in listbox::column_at(#248) --- source/gui/widgets/listbox.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index a6161056..c49841c5 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -433,8 +433,16 @@ namespace nana { check_range(pos, cont_.size()); + //The order of cont_'s elements is the display order. if (!disp_order) - pos = this->cast(pos, false); + { + /// It always match the item with pos, otherwise a bug occurs. + for (auto & m : cont_) + { + if (m.index == pos) + return m; + } + } return cont_[pos]; } From 2cf0adf7773afe76b385b5e3b43eb21a686efcf5 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 31 Aug 2017 04:41:43 +0800 Subject: [PATCH 4/6] small modification --- source/gui/place.cpp | 2 +- source/gui/place_parts.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index f1b4a5ff..257e4656 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -3058,7 +3058,7 @@ namespace nana throw std::runtime_error("place.bind: it has already bound to a window."); impl_->window_handle = wd; - impl_->event_size_handle = API::events(wd).resized.connect([this](const arg_resized& arg) + impl_->event_size_handle = API::events(wd).resized.connect_unignorable([this](const arg_resized& arg) { if (impl_->root_division) { diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 4511dc95..b17be9cd 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -260,7 +260,7 @@ namespace nana notifier_->request_close(); }); - this->events().resized.connect([this](const arg_resized& arg) + this->events().resized.connect_unignorable([this](const arg_resized& arg) { rectangle r{ 0, 0, arg.width, 20 }; caption_.move(r); @@ -360,7 +360,7 @@ namespace nana API::set_parent_window(handle(), container_->handle()); this->move({ 1, 1 }); - container_->events().resized.connect([this](const arg_resized& arg) + container_->events().resized.connect_unignorable([this](const arg_resized& arg) { this->size({arg.width - 2, arg.height - 2}); }); From 2974fe213721459f341201977a0d0b2cc2a086fc Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 1 Sep 2017 22:57:12 +0800 Subject: [PATCH 5/6] add event filter contributed by A2Razor --- include/nana/gui/detail/bedrock.hpp | 5 +- include/nana/gui/detail/drawer.hpp | 75 ++++++++--- include/nana/gui/programming_interface.hpp | 11 ++ include/nana/gui/widgets/widget.hpp | 35 ++++- source/gui/detail/bedrock_pi.cpp | 46 ++++--- source/gui/detail/bedrock_posix.cpp | 8 +- source/gui/detail/bedrock_windows.cpp | 8 +- source/gui/detail/drawer.cpp | 148 ++++++++++++++++----- source/gui/programming_interface.cpp | 7 +- 9 files changed, 254 insertions(+), 89 deletions(-) diff --git a/include/nana/gui/detail/bedrock.hpp b/include/nana/gui/detail/bedrock.hpp index 5462857d..0db691b3 100644 --- a/include/nana/gui/detail/bedrock.hpp +++ b/include/nana/gui/detail/bedrock.hpp @@ -91,9 +91,10 @@ namespace detail void manage_form_loader(core_window_t*, bool insert_or_remove); public: - bool emit(event_code, core_window_t*, const event_arg&, bool ask_update, thread_context*); + // if 'bForce__EmitInternal', then ONLY internal (widget's) events are processed (even through explicit filtering) + bool emit(event_code, core_window_t*, const event_arg&, bool ask_update, thread_context*, const bool bForce__EmitInternal = false); private: - void _m_emit_core(event_code, core_window_t*, bool draw_only, const event_arg&); + void _m_emit_core(event_code, core_window_t*, bool draw_only, const event_arg&, const bool bForce__EmitInternal); void _m_event_filter(event_code, core_window_t*, thread_context*); private: static bedrock bedrock_object; diff --git a/include/nana/gui/detail/drawer.hpp b/include/nana/gui/detail/drawer.hpp index 5a202438..63cea67f 100644 --- a/include/nana/gui/detail/drawer.hpp +++ b/include/nana/gui/detail/drawer.hpp @@ -17,6 +17,7 @@ #include "general_events.hpp" #include #include +#include namespace nana { @@ -27,6 +28,25 @@ namespace nana class drawer; } + class drawer_trigger; + class event_filter_status + { + public: + event_filter_status(); + event_filter_status(const event_filter_status& rOther); + event_filter_status(const unsigned evt_disabled_); + const event_filter_status& operator=(const event_filter_status& rOther); + const event_filter_status& operator=(const unsigned evt_disabled_); + + bool operator[](const nana::event_code evt_code) const; + bool operator==(const event_filter_status& rOther) const; + bool operator!=(const event_filter_status& rOther) const; + + private: + unsigned evt_disabled_; + friend class drawer_trigger; + }; + class drawer_trigger { friend class detail::drawer; @@ -70,11 +90,19 @@ namespace nana virtual void key_release(graph_reference, const arg_keyboard&); virtual void shortkey(graph_reference, const arg_keyboard&); + void filter_event(const event_code evt_code, const bool bDisabled); + void filter_event(const std::vector evt_codes, const bool bDisabled); + void filter_event(const event_filter_status& evt_all_states); + bool filter_event(const event_code evt_code); + event_filter_status filter_event(); + void clear_filter(); + private: void _m_reset_overrided(); bool _m_overrided(event_code) const; private: unsigned overrided_{ 0xFFFFFFFF }; + unsigned evt_disabled_{ 0 }; // bit set if event is filtered }; namespace detail @@ -99,23 +127,23 @@ namespace nana void bind(basic_window*); void typeface_changed(); - void click(const arg_click&); - void dbl_click(const arg_mouse&); - void mouse_enter(const arg_mouse&); - void mouse_move(const arg_mouse&); - void mouse_leave(const arg_mouse&); - void mouse_down(const arg_mouse&); - void mouse_up(const arg_mouse&); - void mouse_wheel(const arg_wheel&); - void mouse_dropfiles(const arg_dropfiles&); - void resizing(const arg_resizing&); - void resized(const arg_resized&); - void move(const arg_move&); - void focus(const arg_focus&); - void key_press(const arg_keyboard&); - void key_char(const arg_keyboard&); - void key_release(const arg_keyboard&); - void shortkey(const arg_keyboard&); + void click(const arg_click&, const bool); + void dbl_click(const arg_mouse&, const bool); + void mouse_enter(const arg_mouse&, const bool); + void mouse_move(const arg_mouse&, const bool); + void mouse_leave(const arg_mouse&, const bool); + void mouse_down(const arg_mouse&, const bool); + void mouse_up(const arg_mouse&, const bool); + void mouse_wheel(const arg_wheel&, const bool); + void mouse_dropfiles(const arg_dropfiles&, const bool); + void resizing(const arg_resizing&, const bool); + void resized(const arg_resized&, const bool); + void move(const arg_move&, const bool); + void focus(const arg_focus&, const bool); + void key_press(const arg_keyboard&, const bool); + void key_char(const arg_keyboard&, const bool); + void key_release(const arg_keyboard&, const bool); + void shortkey(const arg_keyboard&, const bool); void map(window, bool forced, const rectangle* update_area = nullptr); //Copy the root buffer to screen void refresh(); drawer_trigger* realizer() const; @@ -130,7 +158,7 @@ namespace nana method_state& _m_mth_state(int pos); template - void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr) + void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr, const bool bForce__EmitInternal) { const int pos = static_cast(evt_code); @@ -139,17 +167,22 @@ namespace nana if (realizer && (method_state::not_overrided != mth_state)) { + const bool bFiltered = !bForce__EmitInternal && realizer->filter_event(evt_code); if (method_state::pending == mth_state) { - (realizer->*mfptr)(graphics, arg); - + if (!bFiltered) + (realizer->*mfptr)(graphics, arg); + //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); } else - (realizer->*mfptr)(graphics, arg); + { + if (!bFiltered) + (realizer->*mfptr)(graphics, arg); + } _m_effect_bground_subsequent(); } diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 4d1931dc..8c0d85fe 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -120,8 +120,13 @@ namespace API namespace detail { general_events* get_general_events(window); + + // emits both internal and external event (internal event can be filtered) bool emit_event(event_code, window, const ::nana::event_arg&); + // explicitly emits internal event (internal event not to be filtered) + bool emit_internal_event(event_code, window, const ::nana::event_arg&); + class enum_widgets_function_base { public: @@ -255,6 +260,12 @@ namespace API return detail::emit_event(evt_code, wd, arg); } + template::value>::type* = nullptr> + bool emit_internal_event(event_code evt_code, window wd, const EventArg& arg) + { + return detail::emit_internal_event(evt_code, wd, arg); + } + void umake_event(event_handle); template diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 922fbe3b..0ee37703 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -206,7 +206,7 @@ namespace nana API::dev::attach_drawer(*this, trigger_); if(visible) API::show_window(handle_, true); - + this->_m_complete_creation(); } return (this->empty() == false); @@ -227,6 +227,39 @@ namespace nana { return *scheme_; } + + // disables or re-enables internal handling of event within base-widget + void filter_event(const event_code evt_code, const bool bDisabled) + { + trigger_.filter_event(evt_code, bDisabled); + } + + void filter_event(const std::vector evt_codes, const bool bDisabled) + { + trigger_.filter_event(evt_codes, bDisabled); + } + + void filter_event(const event_filter_status& evt_all_states) + { + trigger_.filter_event(evt_all_states); + } + + void clear_filter() + { + trigger_.clear_filter(); + } + + // reads status of if event is filtered + bool filter_event(const event_code evt_code) + { + return trigger_.filter_event(evt_code); + } + + event_filter_status filter_event() + { + return trigger_.filter_event(); + } + protected: DrawerTrigger& get_drawer_trigger() { diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 294c56f9..ec27ac07 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -379,11 +379,13 @@ namespace nana return pi_data_->scheme; } - void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg) + void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg, const bool bForce__EmitInternal) { auto retain = wd->annex.events_ptr; auto evts_ptr = retain.get(); + // if 'bForce__EmitInternal', omit user defined events + const bool bProcess__External_event = !draw_only && !bForce__EmitInternal; switch (evt_code) { case event_code::click: @@ -394,9 +396,9 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.click(*arg); + wd->drawer.click(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->click.emit(*arg, reinterpret_cast(wd)); } } @@ -412,7 +414,7 @@ namespace nana if (nullptr == arg) return; - void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&); + void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&, const bool); ::nana::basic_event* evt_addr; switch (evt_code) @@ -448,10 +450,10 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - (wd->drawer.*drawer_event_fn)(*arg); + (wd->drawer.*drawer_event_fn)(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evt_addr->emit(*arg, reinterpret_cast(wd)); break; } @@ -463,10 +465,10 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.mouse_wheel(*arg); + wd->drawer.mouse_wheel(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->mouse_wheel.emit(*arg, reinterpret_cast(wd)); } break; @@ -480,7 +482,7 @@ namespace nana if (nullptr == arg) return; - void(::nana::detail::drawer::*drawer_event_fn)(const arg_keyboard&); + void(::nana::detail::drawer::*drawer_event_fn)(const arg_keyboard&, const bool); ::nana::basic_event* evt_addr; switch (evt_code) @@ -507,15 +509,15 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - (wd->drawer.*drawer_event_fn)(*arg); + (wd->drawer.*drawer_event_fn)(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evt_addr->emit(*arg, reinterpret_cast(wd)); break; } case event_code::expose: - if (!draw_only) + if (bProcess__External_event) { auto arg = dynamic_cast(&event_arg); if (arg) @@ -530,9 +532,9 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.focus(*arg); + wd->drawer.focus(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->focus.emit(*arg, reinterpret_cast(wd)); } break; @@ -545,9 +547,9 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.move(*arg); + wd->drawer.move(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->move.emit(*arg, reinterpret_cast(wd)); } break; @@ -560,9 +562,9 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.resizing(*arg); + wd->drawer.resizing(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->resizing.emit(*arg, reinterpret_cast(wd)); } break; @@ -575,15 +577,15 @@ namespace nana { //enable refreshing flag, this is a RAII class for exception-safe flag_guard fguard(this, wd); - wd->drawer.resized(*arg); + wd->drawer.resized(*arg, bForce__EmitInternal); } - if (!draw_only) + if (bProcess__External_event) evts_ptr->resized.emit(*arg, reinterpret_cast(wd)); } break; } case event_code::unload: - if (!draw_only) + if (bProcess__External_event) { auto arg = dynamic_cast(&event_arg); if (arg && (wd->other.category == category::flags::root)) @@ -595,7 +597,7 @@ namespace nana } break; case event_code::destroy: - if (!draw_only) + if (bProcess__External_event) { auto arg = dynamic_cast(&event_arg); if (arg) diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 55c39b58..9b0e24e0 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -232,7 +232,7 @@ namespace detail //No implementation for Linux } - bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd) + bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal) { if(wd_manager().available(wd) == false) return false; @@ -248,7 +248,7 @@ namespace detail if(wd->other.upd_state == core_window_t::update_state::none) wd->other.upd_state = core_window_t::update_state::lazy; - _m_emit_core(evt_code, wd, false, arg); + _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); //A child of wd may not be drawn if it was out of wd's range before wd resized, //so refresh all children of wd when a resized occurs. @@ -396,7 +396,7 @@ namespace detail } template - void draw_invoker(void(::nana::detail::drawer::*event_ptr)(const Arg&), basic_window* wd, const Arg& arg, bedrock::thread_context* thrd) + void draw_invoker(void(::nana::detail::drawer::*event_ptr)(const Arg&, const bool), basic_window* wd, const Arg& arg, bedrock::thread_context* thrd) { if(bedrock::instance().wd_manager().available(wd) == false) return; @@ -410,7 +410,7 @@ namespace detail if(wd->other.upd_state == basic_window::update_state::none) wd->other.upd_state = basic_window::update_state::lazy; - (wd->drawer.*event_ptr)(arg); + (wd->drawer.*event_ptr)(arg, false); if(thrd) thrd->event_window = pre_wd; } diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 68d996b3..ebf32705 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -755,7 +755,7 @@ namespace detail } template - void draw_invoker(void (::nana::detail::drawer::*event_ptr)(const Arg&), basic_window* wd, const Arg& arg, bedrock::thread_context* thrd) + void draw_invoker(void (::nana::detail::drawer::*event_ptr)(const Arg&, const bool), basic_window* wd, const Arg& arg, bedrock::thread_context* thrd) { if (bedrock::instance().wd_manager().available(wd) == false) return; @@ -770,7 +770,7 @@ namespace detail if (wd->other.upd_state == basic_window::update_state::none) wd->other.upd_state = basic_window::update_state::lazy; - (wd->drawer.*event_ptr)(arg); + (wd->drawer.*event_ptr)(arg, false); if (thrd) thrd->event_window = prev_event_wd; } @@ -1626,7 +1626,7 @@ namespace detail } } - bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd) + bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal) { if (wd_manager().available(wd) == false) return false; @@ -1642,7 +1642,7 @@ namespace detail if (wd->other.upd_state == core_window_t::update_state::none) wd->other.upd_state = core_window_t::update_state::lazy; - _m_emit_core(evt_code, wd, false, arg); + _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); bool good_wd = false; if (wd_manager().available(wd)) diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index f73cb3ee..e6b9108a 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -128,8 +128,88 @@ namespace nana return 0 != (overrided_ & (1 << static_cast(evt_code))); } + void drawer_trigger::filter_event(const event_code evt_code, const bool bDisabled) + { + if (bDisabled) + evt_disabled_ |= 1 << static_cast(evt_code); // set + else + evt_disabled_ &= ~(1 << static_cast(evt_code)); // clear + } + + void drawer_trigger::filter_event(const std::vector evt_codes, const bool bDisabled) + { + const auto it_end = evt_codes.end(); + for (auto it = evt_codes.begin(); it != it_end; it++) + filter_event(*it, bDisabled); + } + + void drawer_trigger::filter_event(const event_filter_status& evt_all_states) + { + evt_disabled_ = evt_all_states.evt_disabled_; + } + + bool drawer_trigger::filter_event(const event_code evt_code) + { + return static_cast((evt_disabled_ >> static_cast(evt_code)) & 1); + } + + event_filter_status drawer_trigger::filter_event() + { + return event_filter_status(evt_disabled_); + } + + void drawer_trigger::clear_filter() + { + for (int i = 0; i < static_cast(nana::event_code::end); i++) + filter_event(static_cast(i), false); + } + //end class drawer_trigger + //class event_filter_status + event_filter_status::event_filter_status() + { + evt_disabled_ = 0; + } + + event_filter_status::event_filter_status(const event_filter_status& rOther) + { + this->evt_disabled_ = rOther.evt_disabled_; + } + + event_filter_status::event_filter_status(const unsigned evt_disabled_) + { + this->evt_disabled_ = evt_disabled_; + } + + bool event_filter_status::operator[](const nana::event_code evt_code) const + { + return static_cast((evt_disabled_ >> static_cast(evt_code)) & 1); + } + + bool event_filter_status::operator==(const event_filter_status& rOther) const + { + return evt_disabled_ == rOther.evt_disabled_; + } + + bool event_filter_status::operator!=(const event_filter_status& rOther) const + { + return evt_disabled_ != rOther.evt_disabled_; + } + + const event_filter_status& event_filter_status::operator=(const event_filter_status& rOther) + { + evt_disabled_ = rOther.evt_disabled_; + return *this; + } + + const event_filter_status& event_filter_status::operator=(const unsigned evt_disabled_) + { + this->evt_disabled_ = evt_disabled_; + return *this; + } + //end of class event_filter_status + namespace detail { typedef bedrock bedrock_type; @@ -174,89 +254,89 @@ namespace nana data_impl_->realizer->typeface_changed(graphics); } - void drawer::click(const arg_click& arg) + void drawer::click(const arg_click& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::click, arg, &drawer_trigger::click); + _m_emit(event_code::click, arg, &drawer_trigger::click, bForce__EmitInternal); } - void drawer::dbl_click(const arg_mouse& arg) + void drawer::dbl_click(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::dbl_click, arg, &drawer_trigger::dbl_click); + _m_emit(event_code::dbl_click, arg, &drawer_trigger::dbl_click, bForce__EmitInternal); } - void drawer::mouse_enter(const arg_mouse& arg) + void drawer::mouse_enter(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_enter, arg, &drawer_trigger::mouse_enter); + _m_emit(event_code::mouse_enter, arg, &drawer_trigger::mouse_enter, bForce__EmitInternal); } - void drawer::mouse_move(const arg_mouse& arg) + void drawer::mouse_move(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_move, arg, &drawer_trigger::mouse_move); + _m_emit(event_code::mouse_move, arg, &drawer_trigger::mouse_move, bForce__EmitInternal); } - void drawer::mouse_leave(const arg_mouse& arg) + void drawer::mouse_leave(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_leave, arg, &drawer_trigger::mouse_leave); + _m_emit(event_code::mouse_leave, arg, &drawer_trigger::mouse_leave, bForce__EmitInternal); } - void drawer::mouse_down(const arg_mouse& arg) + void drawer::mouse_down(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_down, arg, &drawer_trigger::mouse_down); + _m_emit(event_code::mouse_down, arg, &drawer_trigger::mouse_down, bForce__EmitInternal); } - void drawer::mouse_up(const arg_mouse& arg) + void drawer::mouse_up(const arg_mouse& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_up, arg, &drawer_trigger::mouse_up); + _m_emit(event_code::mouse_up, arg, &drawer_trigger::mouse_up, bForce__EmitInternal); } - void drawer::mouse_wheel(const arg_wheel& arg) + void drawer::mouse_wheel(const arg_wheel& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_wheel, arg, &drawer_trigger::mouse_wheel); + _m_emit(event_code::mouse_wheel, arg, &drawer_trigger::mouse_wheel, bForce__EmitInternal); } - void drawer::mouse_dropfiles(const arg_dropfiles& arg) + void drawer::mouse_dropfiles(const arg_dropfiles& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::mouse_drop, arg, &drawer_trigger::mouse_dropfiles); + _m_emit(event_code::mouse_drop, arg, &drawer_trigger::mouse_dropfiles, bForce__EmitInternal); } - void drawer::resizing(const arg_resizing& arg) + void drawer::resizing(const arg_resizing& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::resizing, arg, &drawer_trigger::resizing); + _m_emit(event_code::resizing, arg, &drawer_trigger::resizing, bForce__EmitInternal); } - void drawer::resized(const arg_resized& arg) + void drawer::resized(const arg_resized& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::resized, arg, &drawer_trigger::resized); + _m_emit(event_code::resized, arg, &drawer_trigger::resized, bForce__EmitInternal); } - void drawer::move(const arg_move& arg) + void drawer::move(const arg_move& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::move, arg, &drawer_trigger::move); + _m_emit(event_code::move, arg, &drawer_trigger::move, bForce__EmitInternal); } - void drawer::focus(const arg_focus& arg) + void drawer::focus(const arg_focus& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::focus, arg, &drawer_trigger::focus); + _m_emit(event_code::focus, arg, &drawer_trigger::focus, bForce__EmitInternal); } - void drawer::key_press(const arg_keyboard& arg) + void drawer::key_press(const arg_keyboard& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::key_press, arg, &drawer_trigger::key_press); + _m_emit(event_code::key_press, arg, &drawer_trigger::key_press, bForce__EmitInternal); } - void drawer::key_char(const arg_keyboard& arg) + void drawer::key_char(const arg_keyboard& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::key_char, arg, &drawer_trigger::key_char); + _m_emit(event_code::key_char, arg, &drawer_trigger::key_char, bForce__EmitInternal); } - void drawer::key_release(const arg_keyboard& arg) + void drawer::key_release(const arg_keyboard& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::key_release, arg, &drawer_trigger::key_release); + _m_emit(event_code::key_release, arg, &drawer_trigger::key_release, bForce__EmitInternal); } - void drawer::shortkey(const arg_keyboard& arg) + void drawer::shortkey(const arg_keyboard& arg, const bool bForce__EmitInternal) { - _m_emit(event_code::shortkey, arg, &drawer_trigger::shortkey); + _m_emit(event_code::shortkey, arg, &drawer_trigger::shortkey, bForce__EmitInternal); } void drawer::map(window wd, bool forced, const rectangle* update_area) //Copy the root buffer to screen diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 6121d95d..1fd7d158 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -62,7 +62,12 @@ namespace API bool emit_event(event_code evt_code, window wd, const ::nana::event_arg& arg) { - return restrict::bedrock.emit(evt_code, reinterpret_cast<::nana::detail::basic_window*>(wd), arg, true, restrict::bedrock.get_thread_context()); + return restrict::bedrock.emit(evt_code, reinterpret_cast<::nana::detail::basic_window*>(wd), arg, true, restrict::bedrock.get_thread_context(), false); + } + + bool emit_internal_event(event_code evt_code, window wd, const ::nana::event_arg& arg) + { + return restrict::bedrock.emit(evt_code, reinterpret_cast<::nana::detail::basic_window*>(wd), arg, true, restrict::bedrock.get_thread_context(), true); } void enum_widgets_function_base::enum_widgets(window wd, bool recursive) From d36a7e684adcfc9f859548527f078a259e6a4fe1 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 2 Sep 2017 21:25:30 +0800 Subject: [PATCH 6/6] fix travis for new update --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 170ef287..4543e6b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ matrix: before_install: - git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git ../nana-demo - export PATH="$HOME/bin:$PATH" - - mkdir ~/bin + #- mkdir ~/bin #it seemd that a bin already exists from 20170901 - wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true - chmod -R +x /tmp/tools