diff --git a/include/nana/basic_types.hpp b/include/nana/basic_types.hpp index a48d9ece..475f652e 100644 --- a/include/nana/basic_types.hpp +++ b/include/nana/basic_types.hpp @@ -406,10 +406,10 @@ namespace nana struct rectangle { - rectangle(); ///< a zero-size rectangle at (0, 0). + rectangle(); ///< a zero-size rectangle at (0, 0). rectangle(int x, int y, unsigned width, unsigned height); - rectangle(const size &); ///< a rectangle with specified size at coordinate (0, 0). - rectangle(const point&, const size& = size()); + explicit rectangle(const size &); ///< a rectangle with specified size at coordinate (0, 0). + explicit rectangle(const point&, const size& = size()); bool operator==(const rectangle& rhs) const; bool operator!=(const rectangle& rhs) const; diff --git a/include/nana/gui/widgets/detail/inline_widget.hpp b/include/nana/gui/widgets/detail/inline_widget.hpp index 124b6a7a..24c1671f 100644 --- a/include/nana/gui/widgets/detail/inline_widget.hpp +++ b/include/nana/gui/widgets/detail/inline_widget.hpp @@ -23,29 +23,56 @@ namespace nana class inline_widget_indicator { public: + /// A type to index a item using index_type = Index; + + /// A type to the value of the item using value_type = Value; + + /// The destructor virtual ~inline_widget_indicator() = default; - private: - virtual void modify(index_type, const value_type&) const = 0; + + /// Modifies the value of a item specified by pos + virtual void modify(index_type pos, const value_type&) const = 0; + + /// Sends a signal that a specified item is selected + virtual void selected(index_type) = 0; + + /// Sends a signal that a specified item is hovered + virtual void hovered(index_type) = 0; }; template - class inline_widget_interface + class inline_widget_notifier_interface { public: + /// A type to index a item using index_type = Index; + + /// A type to the value of the item using value_type = Value; + + /// A typedef name of a inline widget indicator using inline_indicator = inline_widget_indicator; - using factory_interface = inline_widget_interface; - virtual ~inline_widget_interface() = default; + /// A type to the notifier interface that will be refered by the abstract factory pattern + using factory_interface = inline_widget_notifier_interface; + /// The destructor + virtual ~inline_widget_notifier_interface() = default; + + /// A message to create the inline widget virtual void create(window) = 0; + + /// A message to activate the inline widget to attach a specified item virtual void activate(inline_indicator&, index_type) = 0; + + /// A message to resize the inline widget virtual void resize(const size&) = 0; + + /// A message to set the value from a item virtual void set(const value_type&) = 0; - }; + }; //end class inline_widget_notifier_interface } } diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index adb3cdb7..eac5ec29 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -81,7 +81,7 @@ namespace nana using selection = std::vector; - using inline_interface = detail::inline_widget_interface; + using inline_notifier_interface = detail::inline_widget_notifier_interface; struct cell { @@ -347,7 +347,7 @@ namespace nana : public std::iterator < std::input_iterator_tag, cat_proxy > { public: - using inline_interface = drawerbase::listbox::inline_interface; + using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface; cat_proxy() = default; cat_proxy(essence_t*, size_type pos); @@ -429,7 +429,7 @@ namespace nana /// Behavior of Iterator bool operator!=(const cat_proxy&) const; - void inline_factory(size_type column, pat::cloneable> factory); + void inline_factory(size_type column, pat::cloneable> factory); private: void _m_append(std::vector && cells); void _m_cat_by_pos(); @@ -506,7 +506,7 @@ By \a clicking on a header the list get \a reordered, first up, and then down al using cell = drawerbase::listbox::cell; using export_options= drawerbase::listbox::export_options; using columns_indexs= drawerbase::listbox::size_type; - using inline_interface = drawerbase::listbox::inline_interface; + using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface; public: listbox() = default; listbox(window, bool visible); diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 98e87cc3..9f7cac45 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -76,6 +76,7 @@ namespace nana point pos() const; void move(int x, int y); + //void move(const point&); void move(const rectangle&); void fgcolor(const nana::color&); diff --git a/source/gui/animation.cpp b/source/gui/animation.cpp index 9ed5a7ea..16b21dae 100644 --- a/source/gui/animation.cpp +++ b/source/gui/animation.cpp @@ -208,7 +208,7 @@ namespace nana good_frame_by_frmbuilder = frmobj.u.frbuilder->frbuilder(pos_in_this_frame, framegraph, framegraph_dimension); if(good_frame_by_frmbuilder) { - nana::rectangle r = framegraph_dimension; + nana::rectangle r(framegraph_dimension); _m_render(outs, [&r, &framegraph](paint::graphics& tar, const nana::point& pos) mutable { r.x = pos.x; diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index a0f025a0..46670951 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -24,7 +24,6 @@ namespace nana //class window_layout void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed) { - if (wd->flags.refreshing) return; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index fdfc4e30..f6053bce 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -689,16 +689,18 @@ namespace detail { if(forced || (false == wd->belong_to_lazy())) { - wndlayout_type::paint(wd, redraw, false); - this->map(wd, forced); - } - else - { - if(redraw) - wndlayout_type::paint(wd, true, false); - if(wd->other.upd_state == core_window_t::update_state::lazy) - wd->other.upd_state = core_window_t::update_state::refresh; + if (!wd->flags.refreshing) + { + wndlayout_type::paint(wd, redraw, false); + this->map(wd, forced); + return true; + } } + else if(redraw) + wndlayout_type::paint(wd, true, false); + + if (wd->other.upd_state == core_window_t::update_state::lazy) + wd->other.upd_state = core_window_t::update_state::refresh; } return true; } diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index e4391f11..e32908e0 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -659,7 +659,7 @@ namespace nana //A cat may have a key object to identify the category std::shared_ptr key_ptr; - std::deque>> factories; + std::deque>> factories; category_t() = default; @@ -1907,6 +1907,23 @@ namespace nana { ess_->lister.at(pos).cells; } + + void selected(index_type pos) override + { + if (ess_->lister.at(pos).flags.selected) + return; + ess_->lister.select_for_all(false); + cat_proxy(ess_, pos.cat).at(pos.item).select(true); + } + + void hovered(index_type pos) override + { + auto offset = ess_->lister.distance(ess_->scroll.offset_y_dpl, pos); + ess_->pointer_where.first = parts::lister; + ess_->pointer_where.second = offset; + + ess_->update(); + } private: essence_t * const ess_; }; @@ -1920,7 +1937,10 @@ namespace nana unsigned item_size{24}; unsigned text_height{0}; unsigned suspension_width{0}; - ::nana::listbox::export_options def_exp_options ; + + inline_indicator indicator{ this }; + + ::nana::listbox::export_options def_exp_options; ::nana::listbox::export_options& def_export_options() { @@ -1952,7 +1972,7 @@ namespace nana { ::nana::panel pane_bottom; //pane for pane_widget ::nana::panel pane_widget; //pane for placing user-define widget - std::unique_ptr inline_ptr; + std::unique_ptr inline_ptr; }; std::map>> inline_table, inline_buffered_table; @@ -2360,7 +2380,7 @@ namespace nana } } - inline_pane * open_inline(pat::abstract_factory* factory) + inline_pane * open_inline(pat::abstract_factory* factory) { std::unique_ptr pane_ptr; auto i = inline_buffered_table.find(factory); @@ -2634,7 +2654,6 @@ namespace nana void _m_draw(const Container& cont, const nana::rectangle& rect) { graph_reference graph = *(essence_->graph); - int txtop = (rect.height - essence_->text_height) / 2 + rect.y; auto txtcolor = essence_->lister.wd_ptr()->fgcolor(); @@ -2654,7 +2673,7 @@ namespace nana int next_x = x + static_cast(i.pixels); if(next_x > rect.x) { - _m_draw_item(graph, x, rect.y, height, txtop, txtcolor, i, (i.index == essence_->pointer_where.second ? state : item_state::normal)); + _m_draw_header_item(graph, x, rect.y, height, txtop, txtcolor, i, (i.index == essence_->pointer_where.second ? state : item_state::normal)); graph.line({ next_x - 1, rect.y }, { next_x - 1, bottom_y }, _m_border_color()); } @@ -2669,7 +2688,7 @@ namespace nana } template - void _m_draw_item(graph_reference graph, int x, int y, unsigned height, int txtop, const ::nana::color& fgcolor, const Item& item, item_state state) + 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) { essence_->scheme_ptr->header_bgcolor.get_color(); ::nana::color bgcolor; @@ -2701,10 +2720,10 @@ namespace nana ext_graph.typeface(essence_->graph->typeface()); int txtop = (essence_->header_size - essence_->text_height) / 2; - _m_draw_item(ext_graph, 0, 0, essence_->header_size, txtop, colors::white, item, item_state::floated); + _m_draw_header_item(ext_graph, 0, 0, essence_->header_size, txtop, colors::white, item, item_state::floated); int xpos = essence_->header.item_pos(item.index, nullptr) + pos.x - ref_xpos_; - ext_graph.blend(ext_graph.size(), *(essence_->graph), nana::point(xpos - essence_->scroll.offset_x + rect.x, rect.y), 0.5); + ext_graph.blend(rectangle{ ext_graph.size() }, *(essence_->graph), nana::point(xpos - essence_->scroll.offset_x + rect.x, rect.y), 0.5); } private: @@ -2749,7 +2768,7 @@ namespace nana es_lister & lister = essence_->lister; //The Tracker indicates the item where mouse placed. index_pair tracker(npos, npos); - auto & ptr_where = essence_->pointer_where; + auto & ptr_where = essence_->pointer_where; //if where == lister || where == checker, 'second' indicates the offset to the relative display-order pos of the scroll offset_y which stands for the first item to be displayed in lister. if((ptr_where.first == parts::lister || ptr_where.first == parts::checker) && ptr_where.second != npos) @@ -2784,12 +2803,16 @@ namespace nana } std::size_t size = i_categ->items.size(); + index_pair item_index{ idx.cat, 0 }; for(std::size_t offs = essence_->scroll.offset_y_dpl.item; offs < size; ++offs, ++idx.item) { if(n-- == 0) break; state = (tracker == idx ? item_state::highlighted : item_state::normal); - _m_draw_item(*i_categ, i_categ->items[lister.absolute(index_pair(idx.cat, offs)) ], x, y, txtoff, header_w, rect, subitems, bgcolor,fgcolor, state); + item_index.item = offs; + item_index = lister.absolute_pair(item_index); + + _m_draw_item(*i_categ, item_index, x, y, txtoff, header_w, rect, subitems, bgcolor,fgcolor, state); y += essence_->item_size; } @@ -2811,12 +2834,16 @@ namespace nana continue; auto size = i_categ->items.size(); + index_pair item_pos{ idx.cat, 0 }; for(decltype(size) pos = 0; pos < size; ++pos) { if(n-- == 0) break; state = (idx == tracker ? item_state::highlighted : item_state::normal); - _m_draw_item(*i_categ, i_categ->items[ lister.absolute(index_pair(idx.cat, pos))], x, y, txtoff, header_w, rect, subitems, bgcolor, fgcolor, state); + item_pos.item = pos; + item_pos.item = lister.absolute(item_pos); + + _m_draw_item(*i_categ, item_pos, x, y, txtoff, header_w, rect, subitems, bgcolor, fgcolor, state); y += essence_->item_size; ++idx.item; } @@ -2874,8 +2901,10 @@ namespace nana //Draws an item //@param content_r the rectangle of list content - void _m_draw_item(const category_t& cat, const item_t& item, const int x, const int y, const int txtoff, unsigned width, const nana::rectangle& content_r, const std::vector& seqs, nana::color bgcolor, nana::color fgcolor, item_state state) const + void _m_draw_item(const category_t& cat, const index_pair& item_pos, const int x, const int y, const int txtoff, unsigned width, const nana::rectangle& content_r, const std::vector& seqs, nana::color bgcolor, nana::color fgcolor, item_state state) const { + auto & item = cat.items[item_pos.item]; + if (item.flags.selected) // fetch the "def" colors bgcolor = essence_->scheme_ptr->item_selected; else if (!item.bgcolor.invisible()) @@ -2961,7 +2990,7 @@ namespace nana nana::rectangle img_r(item.img_show_size); img_r.x = static_cast(ext_w)+item_xpos + static_cast(16 - item.img_show_size.width) / 2; img_r.y = y + static_cast(essence_->item_size - item.img_show_size.height) / 2; - item.img.stretch(item.img.size(), *graph, img_r); + item.img.stretch(rectangle{ item.img.size() }, *graph, img_r); } ext_w += 18; } @@ -2994,6 +3023,7 @@ namespace nana auto inline_wdg = _m_get_pane(cat, index); if (inline_wdg) { + //Make sure the user-define inline widgets in right visible rectangle. rectangle pane_r; if (::nana::overlap(content_r, { item_xpos, y, header.pixels, essence_->item_size }, pane_r)) { @@ -3004,7 +3034,7 @@ namespace nana if (y < content_r.y) pane_pos.y = y - content_r.y; - inline_wdg->pane_widget.move(pane_pos); + inline_wdg->pane_widget.move(pane_pos.x, pane_pos.y); inline_wdg->pane_bottom.move(pane_r); } else @@ -3012,7 +3042,7 @@ namespace nana inline_wdg->pane_widget.size({ header.pixels, essence_->item_size }); inline_wdg->inline_ptr->resize({ header.pixels, essence_->item_size }); - //inline_wdg->inline_ptr->activate() + inline_wdg->inline_ptr->activate(essence_->indicator, item_pos); } item_xpos += static_cast(header.pixels); @@ -3199,7 +3229,16 @@ namespace nana } } - switch(update) + if (update) + { + if (2 == update) + draw(); + + API::lazy_refresh(); + } + + /* + switch(update) //deprecated { case 1: API::update_window(essence_->lister.wd_ptr()->handle()); @@ -3209,6 +3248,7 @@ namespace nana API::lazy_refresh(); break; } + */ } void trigger::mouse_leave(graph_reference graph, const arg_mouse&) @@ -3261,7 +3301,7 @@ namespace nana else if (arg.ctrl) sel = !item_proxy(essence_, index_pair (item_pos.cat, lister.absolute(item_pos))).selected(); else - lister.select_for_all(false); + lister.select_for_all(false); //cancel all selections } else sel = !item_proxy(essence_, index_pair (item_pos.cat, lister.absolute(item_pos))).selected(); @@ -3560,6 +3600,8 @@ namespace nana } else if (ess_->lister.last_selected_abs == pos_) ess_->lister.last_selected_abs.set_both(npos); + + ess_->update(); return *this; } @@ -3953,7 +3995,7 @@ namespace nana return ! this->operator==(r); } - void cat_proxy::inline_factory(size_type column, pat::cloneable> factory) + void cat_proxy::inline_factory(size_type column, pat::cloneable> factory) { if (column >= ess_->header.cont().size()) throw std::out_of_range("listbox.cat_proxy.inline_factory: invalid column index"); diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index cd504eac..f5075c52 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -173,6 +173,13 @@ namespace nana _m_move(x, y); } + /* + void widget::move(const point& pos) //deprecated + { + _m_move(pos); + } + */ + void widget::move(const rectangle& r) { _m_move(r);