From 42dd27b68f8fc5a5f367ca184ce49c245af16191 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 14 Aug 2015 01:38:23 +0800 Subject: [PATCH 1/7] add a new tabbar_lite widget --- include/nana/gui/widgets/tabbar.hpp | 47 +++++ include/nana/paint/graphics.hpp | 4 +- source/gui/widgets/tabbar.cpp | 293 ++++++++++++++++++++++++++++ source/paint/graphics.cpp | 13 +- 4 files changed, 355 insertions(+), 2 deletions(-) diff --git a/include/nana/gui/widgets/tabbar.hpp b/include/nana/gui/widgets/tabbar.hpp index 94cf2407..1160c724 100644 --- a/include/nana/gui/widgets/tabbar.hpp +++ b/include/nana/gui/widgets/tabbar.hpp @@ -334,4 +334,51 @@ namespace nana std::unique_ptr > evt_agent_; }; }//end namespace nana + + +namespace nana +{ + namespace ng + { + namespace drawerbase + { + namespace tabbar_lite + { + class model; + + class driver + : public drawer_trigger + { + public: + driver(); + ~driver(); + + model* get_model(); + private: + //Overrides drawer_trigger's method + void attached(widget_reference, graph_reference) override; + void refresh(graph_reference) override; + void mouse_move(graph_reference, const arg_mouse&) override; + void mouse_leave(graph_reference, const arg_mouse&) override; + void mouse_down(graph_reference, const arg_mouse&) override; + private: + model* const model_; + }; + } + }//end namespace drawerbase + + class tabbar_lite + : public widget_object + { + public: + tabbar_lite() = default; + tabbar_lite(window, bool visible = true, const::nana::rectangle& = {}); + + + void push_back(std::string text, ::nana::any par = {}); + void push_front(std::string text, ::nana::any par = {}); + }; + } +} + #endif diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index e790fc89..17a31491 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -96,7 +96,8 @@ namespace nana ::nana::size glyph_extent_size(const char_t*, std::size_t length, std::size_t begin, std::size_t end) const; ::nana::size glyph_extent_size(const string&, std::size_t length, std::size_t begin, std::size_t end) const; bool glyph_pixels(const char_t *, std::size_t length, unsigned* pxbuf) const; - ::nana::size bidi_extent_size(const string&) const; + ::nana::size bidi_extent_size(const std::wstring&) const; + ::nana::size bidi_extent_size(const std::string&) const; bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const; @@ -136,6 +137,7 @@ namespace nana void set_text_color(const ::nana::color&); unsigned bidi_string(const nana::point&, const char_t *, std::size_t len); + unsigned bidi_string(const point& pos, const char*, std::size_t len); void blend(const ::nana::rectangle& r, const ::nana::color&, double fade_rate); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 7a4aaf02..6532bf6e 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1270,3 +1270,296 @@ namespace nana }//end namespace tabbar }//end namespace drawerbase }//end namespace nana + +#include +namespace nana +{ + namespace ng + { + namespace drawerbase + { + namespace tabbar_lite + { + struct item + { + ::std::string text; + ::nana::any value; + ::std::pair pos_ends; + + item(std::string t, ::nana::any v) + : text(std::move(t)), value(std::move(v)) + {} + }; + + void calc_px(std::vector& values, unsigned limit) + { + unsigned base = 0; + auto count = values.size(); + + while (count) + { + unsigned minv = static_cast(-1); + + unsigned minv_count = 0; + for (auto u : values) + { + if (u >= base && u < minv) + { + minv_count = 1; + minv = u; + } + else if (minv == u) + minv_count++; + } + + count -= minv_count; + if (minv * count >= limit) + { + auto piece = limit / double(count); + double deviation = 0; + for (auto & u : values) + { + if (minv >= u) + { + auto px = piece + deviation; + u = static_cast(px); + deviation = px - u; + } + } + return; + } + + base = minv; + limit -= minv_count * minv; + } + } + + class model + { + struct indexes + { + std::size_t hovered_pos{ npos }; + std::size_t active_pos{ 0 }; + }; + public: + using graph_reference = ::nana::paint::graphics&; + static const std::size_t npos = static_cast(-1); + + void set_widget(widget& wdg) + { + widget_ = &wdg; + } + + ::nana::dev::widget_traits::scheme_type & scheme() + { + return API::scheme(*widget_); + } + + std::forward_list& items() + { + return items_; + } + + bool track_pointer(const point& pos) + { + std::size_t item_pos = 0; + bool matched = false; + for (auto & m : items_) + { + if (m.pos_ends.first <= pos.x && pos.x < m.pos_ends.second) + { + matched = true; + break; + } + + ++item_pos; + } + + if (!matched) + item_pos = npos; + + if (indexes_.hovered_pos == item_pos) + return false; + + indexes_.hovered_pos = item_pos; + return true; + } + + indexes& get_indexes() + { + return indexes_; + } + private: + widget * widget_{ nullptr }; + std::forward_list items_; + indexes indexes_; + }; + + class renderer + { + public: + using graph_reference = ::nana::paint::graphics&; + + void render(graph_reference graph, model& model) + { + _m_calc_metrics(graph, model.items()); + + auto & scheme = model.scheme(); + + //draw background + graph.rectangle(true, scheme.background); + + auto & indexes = model.get_indexes(); + std::size_t pos = 0; + for (auto & m : model.items()) + { + rectangle r{ m.pos_ends.first, 0, static_cast(m.pos_ends.second - m.pos_ends.first), graph.height() }; + if (indexes.active_pos == pos) + { + graph.set_color(colors::white); + graph.set_text_color(colors::black); + } + else + { + ::nana::color bgcolor(colors::coral); + + if (pos == indexes.hovered_pos) + bgcolor = bgcolor.blend(colors::white, 0.5); + + graph.set_color(bgcolor); + graph.set_text_color(colors::white); + } + + graph.rectangle(r, true); + graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size()); + + ++pos; + } + + } + private: + void _m_calc_metrics(graph_reference graph, std::forward_list& items) + { + const auto height_px = graph.height(); + std::vector pxs; + + unsigned pixels = 0; + for (auto & m : items) + { + auto ts = graph.bidi_extent_size(m.text); + pxs.push_back(ts.width + 12); + pixels += ts.width + 12; + } + + if (pixels > graph.width()) + calc_px(pxs, graph.width()); + + auto i = pxs.cbegin(); + int pos = 0; + for (auto & m : items) + { + m.pos_ends.first = pos; + m.pos_ends.second = (pos += static_cast(*i++)); + } + } + }; + + + //class driver + driver::driver() + : model_(new model) + { + } + + driver::~driver() + { + delete model_; + } + + model* driver::get_model() + { + return model_; + } + + void driver::attached(widget_reference wdg, graph_reference) + { + model_->set_widget(wdg); + } + + //Overrides drawer_trigger's method + void driver::refresh(graph_reference graph) + { + renderer rd; + rd.render(graph, *model_); + } + + void driver::mouse_move(graph_reference graph, const arg_mouse& arg) + { + if (!model_->track_pointer(arg.pos)) + return; + + refresh(graph); + API::lazy_refresh(); + } + + void driver::mouse_leave(graph_reference graph, const arg_mouse&) + { + if (model_->get_indexes().hovered_pos == model_->npos) + return; + + refresh(graph); + API::lazy_refresh(); + } + + void driver::mouse_down(graph_reference graph, const arg_mouse&) + { + auto & indexes = model_->get_indexes(); + if (indexes.hovered_pos == model_->npos) + return; + + indexes.active_pos = indexes.hovered_pos; + refresh(graph); + API::lazy_refresh(); + } + //end class driver + } + } + + //class tabbar + + tabbar_lite::tabbar_lite(window parent_wd, bool visible, const ::nana::rectangle& r) + { + this->create(parent_wd, r, visible); + } + + void tabbar_lite::push_back(std::string text, ::nana::any any) + { + auto & items = get_drawer_trigger().get_model()->items(); + internal_scope_guard lock; + + auto i = items.cbefore_begin(); + while (true) + { + auto next = i++; + if (i == items.cend()) + { + items.emplace_after(next, std::move(text), std::move(any)); + break; + } + + } + + API::refresh_window(handle()); + } + + void tabbar_lite::push_front(std::string text, ::nana::any any) + { + auto & items = get_drawer_trigger().get_model()->items(); + internal_scope_guard lock; + + items.emplace_front(std::move(text), std::move(any)); + API::refresh_window(handle()); + } + //end class tabbar + } +}//end namespace nana diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 70bba1ef..2a997679 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -451,7 +451,7 @@ namespace paint return true; } - nana::size graphics::bidi_extent_size(const nana::string& str) const + nana::size graphics::bidi_extent_size(const std::wstring& str) const { nana::size sz; #if defined NANA_UNICODE @@ -472,6 +472,11 @@ namespace paint return sz; } + ::nana::size graphics::bidi_extent_size(const std::string& str) const + { + return bidi_extent_size(std::wstring{ ::nana::charset(str, ::nana::unicode::utf8) }); + } + bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const { if(handle_) @@ -880,6 +885,12 @@ namespace paint return static_cast(moved_pos.x - pos.x); } + unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len) + { + std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8); + return bidi_string(pos, wstr.data(), wstr.size()); + } + void graphics::blend(const nana::rectangle& r, const ::nana::color& clr, double fade_rate) { if (handle_) From b0c99fa7805e5fb8ef5ece471affb36944ef482d Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 20 Aug 2015 22:34:48 +0800 Subject: [PATCH 2/7] fix an PNG palette color type issue --- source/paint/detail/image_png.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/paint/detail/image_png.hpp b/source/paint/detail/image_png.hpp index eda096e7..039c7908 100644 --- a/source/paint/detail/image_png.hpp +++ b/source/paint/detail/image_png.hpp @@ -55,6 +55,21 @@ namespace nana const int png_width = ::png_get_image_width(png_ptr, info_ptr); const int png_height = ::png_get_image_height(png_ptr, info_ptr); png_byte color_type = ::png_get_color_type(png_ptr, info_ptr); + const auto bit_depth = ::png_get_bit_depth(png_ptr, info_ptr); + + //do some extra work for palette/gray color type + if (PNG_COLOR_TYPE_PALETTE == color_type) + ::png_set_palette_to_rgb(png_ptr); + else if ((PNG_COLOR_TYPE_GRAY == color_type) && (bit_depth < 8)) + ::png_set_gray_to_rgb(png_ptr); + + bool is_alpha_enabled = (::png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0); + if (is_alpha_enabled) + ::png_set_tRNS_to_alpha(png_ptr); + + //make sure 8-bit per channel + if (16 == bit_depth) + ::png_set_strip_16(png_ptr); ::png_set_interlace_handling(png_ptr); ::png_read_update_info(png_ptr, info_ptr); @@ -65,7 +80,7 @@ namespace nana pixbuf_.open(png_width, png_height); - const bool is_alpha_enabled = ((PNG_COLOR_MASK_ALPHA & color_type) != 0); + is_alpha_enabled |= ((PNG_COLOR_MASK_ALPHA & color_type) != 0); pixbuf_.alpha_channel(is_alpha_enabled); if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t))) From 16c93537c927f7a1b00bfe3139aabbe95bc01182 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 23 Aug 2015 03:42:11 +0800 Subject: [PATCH 3/7] code review --- include/nana/gui/detail/drawer.hpp | 2 +- include/nana/gui/widgets/listbox.hpp | 8 +-- source/gui/widgets/listbox.cpp | 94 +++++++++++++++++++++++----- 3 files changed, 82 insertions(+), 22 deletions(-) diff --git a/include/nana/gui/detail/drawer.hpp b/include/nana/gui/detail/drawer.hpp index dfd98e88..ddd770e3 100644 --- a/include/nana/gui/detail/drawer.hpp +++ b/include/nana/gui/detail/drawer.hpp @@ -16,7 +16,7 @@ #include #include "general_events.hpp" #include -#include +//#include //deprecated #include namespace nana diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 3661b8a3..140d6dd2 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -185,7 +185,7 @@ namespace nana public: trigger(); ~trigger(); - essence_t& essence(); + //essence_t& essence(); //deprecated essence_t& essence() const; void draw(); private: @@ -618,7 +618,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down { typedef typename nana::detail::type_escape::type key_t; nana::key > key(kv); - _m_ease_key(&key); + _m_erase_key(&key); } template @@ -626,7 +626,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down { typedef typename nana::detail::type_escape::type key_t; nana::key > key(std::move(kv)); - _m_ease_key(&key); + _m_erase_key(&key); } bool sortable() const; @@ -661,7 +661,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down drawerbase::listbox::essence_t & _m_ess() const; nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const; drawerbase::listbox::category_t* _m_at_key(std::shared_ptr); - void _m_ease_key(nana::detail::key_interface*); + void _m_erase_key(nana::detail::key_interface*); }; namespace dev diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 8487bb59..c9402b8c 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include //for inline widget #include #include @@ -438,11 +438,13 @@ namespace nana return pixels; } + /* /// return the original order or index previous to any list reorganization of the current column "n". - size_type index(size_type n) const + size_type index(size_type n) const //deprecated { return (n < cont_.size() ? cont_[n].index : npos); } + */ const container& cont() const { @@ -539,23 +541,43 @@ namespace nana return npos; } /// move the col originaly at index to the position currently in front (or after) the col originaly at index "to" invalidating some current index - void move(size_type index, size_type to, bool front) + void move(size_type index, size_type to, bool front) throw() { if(index == to) return; if(index >= cont_.size()) return; if(to >= cont_.size()) return; - auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){return (index == m.index);}); + for (auto i = cont_.begin(); i != cont_.end(); ++i) + { + if (index == i->index) + { + column_t from = std::move(*i); + cont_.erase(i); + + for (auto u = cont_.begin(); u != cont_.end(); ++u) + { + if (to == u->index) + { + cont_.insert(front ? u : ++u, from); + return; + } + } + return; + } + } + /* + auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){return (index == m.index);}); //deprecated if (i == cont_.end()) return; - auto from = *i; // a temp copy + column_t from = std::move(*i); //move cont_.erase(i); i = std::find_if(cont_.begin(), cont_.end(), [to](const container::value_type& m)->bool{ return (to == m.index); } ); if(i != cont_.end()) cont_.insert((front ? i : ++i), from); + */ } private: bool visible_{true}; @@ -842,8 +864,9 @@ namespace nana bool active_sort(bool resort) { - std::swap(resort, resort_); - return resort; + bool prstatus = resort; + resort_ = resort; + return prstatus; } bool sort_reverse() const @@ -2015,12 +2038,14 @@ namespace nana trace_item_abs(lister.last_selected_abs); } - void trace_first_selected_item() + /* + void trace_first_selected_item() //deprecated { auto fs=lister.find_first_selected(); if( ! fs.empty() ) trace_item_abs( fs ); } + */ void update() { @@ -2597,11 +2622,11 @@ namespace nana { const auto& item = essence_->header.column(item_spliter_); //Resize the item specified by item_spliter_. - int new_w = orig_item_width_ - (ref_xpos_ - pos.x); + auto new_w = orig_item_width_ - (ref_xpos_ - pos.x); if(static_cast(item.pixels) != new_w) { essence_->header.item_width(item_spliter_, (new_w < static_cast(essence_->suspension_width + 20) ? essence_->suspension_width + 20 : new_w)); - auto new_w = essence_->header.pixels(); + new_w = essence_->header.pixels(); if(new_w < (rect.width + essence_->scroll.offset_x)) essence_->scroll.offset_x = (new_w > rect.width ? new_w - rect.width : 0); @@ -2614,7 +2639,41 @@ namespace nana void draw(const nana::rectangle& r) { - _m_draw(essence_->header.cont(), r); + //_m_draw(essence_->header.cont(), r); //deprecated + + graph_reference graph = *(essence_->graph); + + int text_top = (r.height - essence_->text_height) / 2 + r.y; + auto text_color = essence_->lister.wd_ptr()->fgcolor(); + + auto state = item_state::normal; + //check whether grabing an item, if item_spliter_ != npos, that indicates the grab item is a spliter. + if (essence_->pointer_where.first == parts::header && (item_spliter_ == npos)) + state = essence_->ptr_state; + + const unsigned height = r.height - 1; + const int bottom_y = r.bottom() - 2; + int x = r.x - essence_->scroll.offset_x; + + for (auto & i : essence_->header.cont()) + { + if (i.visible) + { + int next_x = x + static_cast(i.pixels); + if (next_x > r.x) + { + _m_draw_header_item(graph, x, r.y, height, text_top, text_color, i, (i.index == essence_->pointer_where.second ? state : item_state::normal)); + graph.line({ next_x - 1, r.y }, { next_x - 1, bottom_y }, _m_border_color()); + } + + x = next_x; + if (x > r.right()) + break; + } + } + + if (x < r.right()) + graph.rectangle({ x, r.y, static_cast(r.right() - x), height }, true, essence_->scheme_ptr->header_bgcolor); const int y = r.y + r.height - 1; essence_->graph->line({ r.x, y }, { r.x + static_cast(r.width), y }, _m_border_color()); @@ -2657,9 +2716,9 @@ namespace nana } return npos; } - + /* template - void _m_draw(const Container& cont, const nana::rectangle& rect) + void _m_draw(const Container& cont, const nana::rectangle& rect) //deprecated { graph_reference graph = *(essence_->graph); @@ -2694,6 +2753,7 @@ namespace nana if (x < rect.right()) graph.rectangle({ x, rect.y, static_cast(rect.right() - x), height }, true, essence_->scheme_ptr->header_bgcolor); } + */ template void _m_draw_header_item(graph_reference graph, int x, int y, unsigned height, int txtop, const ::nana::color& fgcolor, const Item& item, item_state state) @@ -3166,10 +3226,12 @@ namespace nana delete essence_; } - essence_t& trigger::essence() + /* + essence_t& trigger::essence() //deprecated { return *essence_; } + */ essence_t& trigger::essence() const { @@ -3513,10 +3575,8 @@ namespace nana case keyboard::os_arrow_up: up = true; case keyboard::os_arrow_down: - // move_select(bool upwards=true, bool unselect_previous=true, bool trace_selected=false) essence_->lister.move_select(up, !arg.shift, true); break; - case STR(' ') : { selection s; @@ -4501,7 +4561,7 @@ namespace nana return cat; } - void listbox::_m_ease_key(nana::detail::key_interface* p) + void listbox::_m_erase_key(nana::detail::key_interface* p) { auto & cont = _m_ess().lister.cat_container(); From 03faa0a7eefa72e5616b0280ca64718524fcc2a6 Mon Sep 17 00:00:00 2001 From: dareg Date: Sat, 22 Aug 2015 23:20:32 +0200 Subject: [PATCH 4/7] Fix missing array declaration in unique_ptr Which was causing a wrong deletion of the array --- source/paint/detail/native_paint_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 153ac5f0..476fc5c4 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -187,7 +187,7 @@ namespace detail reinterpret_cast(const_cast(utf8str.c_str())), utf8str.size()); */ auto fs = reinterpret_cast(dw->font->handle); - std::unique_ptr glyphs_ptr(new FT_UInt[len]); + std::unique_ptr glyphs_ptr(new FT_UInt[len]); auto glyphs = glyphs_ptr.get(); const auto endstr = str + len; for(auto chr = str; chr != endstr; ++chr) From 29ab6be21bf37ba8ba12231606883b0c60e37f64 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 23 Aug 2015 17:51:52 +0800 Subject: [PATCH 5/7] add contribution information --- source/paint/detail/native_paint_interface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 476fc5c4..0222269f 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -8,6 +8,7 @@ * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/paint/detail/native_paint_interface.cpp + * @contributors: dareg */ #include @@ -187,6 +188,8 @@ namespace detail reinterpret_cast(const_cast(utf8str.c_str())), utf8str.size()); */ auto fs = reinterpret_cast(dw->font->handle); + + //Fixed missing array declaration by dareg std::unique_ptr glyphs_ptr(new FT_UInt[len]); auto glyphs = glyphs_ptr.get(); const auto endstr = str + len; From 9384baace4a980aae0f139629a2ec48797cbf90a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 27 Aug 2015 01:40:18 +0800 Subject: [PATCH 6/7] fix a crash caused by calling inner_widget_notifier's destroy twice --- include/nana/gui/widgets/widget.hpp | 2 +- source/gui/detail/window_manager.cpp | 19 ++++++++++++------- source/gui/widgets/tabbar.cpp | 1 - source/gui/widgets/widget.cpp | 8 ++++---- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 18163f61..0288388e 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -31,7 +31,7 @@ namespace nana : nana::noncopyable, nana::nonmovable { friend class detail::widget_notifier_interface; - class notifier; + class inner_widget_notifier; typedef void(*dummy_bool_type)(widget* (*)(const widget&)); public: virtual ~widget() = default; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 4ba1c3a2..e9581fd1 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -326,6 +326,9 @@ namespace detail std::lock_guard lock(mutex_); if (impl_->wd_register.available(wd) == false) return; + if (wd->flags.destroying) + return; + if(wd->other.category == category::root_tag::value) { auto &brock = bedrock::instance(); @@ -340,13 +343,15 @@ namespace detail if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active) native_interface::activate_owner(wd->root); - //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 - //non-existing drawer_trigger which is destroyed by destruction of widget. Crash! - wd->drawer.detached(); - - wd->widget_notifier->destroy(); + if (!wd->flags.destroying) + { + //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 + //non-existing drawer_trigger which is destroyed by destruction of widget. Crash! + wd->drawer.detached(); + wd->widget_notifier->destroy(); + } native_interface::close_window(wd->root); } diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 6532bf6e..8b82c6d0 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1440,7 +1440,6 @@ namespace nana private: void _m_calc_metrics(graph_reference graph, std::forward_list& items) { - const auto height_px = graph.height(); std::vector pxs; unsigned pixels = 0; diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index af853b38..39a2ac57 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -22,10 +22,10 @@ namespace nana //class widget //@brief:The definition of class widget - class widget::notifier: public detail::widget_notifier_interface + class widget::inner_widget_notifier : public detail::widget_notifier_interface { public: - notifier(widget& wdg) + inner_widget_notifier(widget& wdg) : wdg_(wdg) {} @@ -246,7 +246,7 @@ namespace nana std::unique_ptr<::nana::detail::widget_notifier_interface> widget::_m_wdg_notifier() { - return std::unique_ptr<::nana::detail::widget_notifier_interface>(new notifier(*this)); + return std::unique_ptr<::nana::detail::widget_notifier_interface>(new inner_widget_notifier(*this)); } void widget::_m_complete_creation() @@ -348,7 +348,7 @@ namespace nana { std::unique_ptr widget_notifier_interface::get_notifier(widget* wdg) { - return std::unique_ptr(new widget::notifier(*wdg)); + return std::unique_ptr(new widget::inner_widget_notifier(*wdg)); } } }//end namespace nana From 549acf5aefed06db8b68fe6f487bc453f3d25c5d Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 27 Aug 2015 23:06:03 +0800 Subject: [PATCH 7/7] fix a bug that missed refresh in event handling --- source/gui/detail/bedrock_pi.cpp | 53 +++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 0e6c3cf8..8f2cff1c 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -189,8 +189,6 @@ namespace nana auto retain = wd->together.events_ptr; auto evts_ptr = retain.get(); - //enable refreshing flag, this is a RAII class for exception-safe - flag_guard fguard(this, wd); switch (evt_code) { @@ -199,8 +197,11 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (nullptr == arg) return; - - wd->drawer.click(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.click(*arg); + } if (!draw_only) evts_ptr->click.emit(*arg); } @@ -249,7 +250,11 @@ namespace nana throw std::runtime_error("Invalid mouse event code"); } - (wd->drawer.*drawer_event_fn)(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + (wd->drawer.*drawer_event_fn)(*arg); + } if (!draw_only) evt_addr->emit(*arg); @@ -260,7 +265,12 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (arg) { - wd->drawer.mouse_wheel(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.mouse_wheel(*arg); + } + if (!draw_only) evts_ptr->mouse_wheel.emit(*arg); } @@ -299,7 +309,12 @@ namespace nana default: throw std::runtime_error("Invalid keyboard event code"); } - (wd->drawer.*drawer_event_fn)(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + (wd->drawer.*drawer_event_fn)(*arg); + } + if (!draw_only) evt_addr->emit(*arg); break; @@ -317,7 +332,11 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (arg) { - wd->drawer.focus(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.focus(*arg); + } if (!draw_only) evts_ptr->focus.emit(*arg); } @@ -328,7 +347,11 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (arg) { - wd->drawer.move(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.move(*arg); + } if (!draw_only) evts_ptr->move.emit(*arg); } @@ -339,7 +362,11 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (arg) { - wd->drawer.resizing(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.resizing(*arg); + } if (!draw_only) evts_ptr->resizing.emit(*arg); } @@ -350,7 +377,11 @@ namespace nana auto arg = dynamic_cast(&event_arg); if (arg) { - wd->drawer.resized(*arg); + { + //enable refreshing flag, this is a RAII class for exception-safe + flag_guard fguard(this, wd); + wd->drawer.resized(*arg); + } if (!draw_only) evts_ptr->resized.emit(*arg); }