From 8d0e48bd1e6c05a95604c0e4125f151ad705817a Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 24 Apr 2015 16:47:03 +0200 Subject: [PATCH 01/18] FIX: Listbox doesn't handle Home, End. OK in windows --- include/nana/gui/basis.hpp | 3 ++- source/gui/widgets/listbox.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index 4eb95c88..c0ef0aa5 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -96,7 +96,8 @@ namespace nana //System Code for OS os_pageup = 0x21, os_pagedown, os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down, - os_insert = 0x2D, os_del + os_insert = 0x2D, os_del , + os_end = 0x23 , os_home //Pos 1 }; }; diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index e47706d2..75968f93 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3294,7 +3294,16 @@ namespace nana break; } - // case keyboard:: + case keyboard::os_home: + essence_->lister.select_for_all(false); + item_proxy::from_display(essence_, {0,0}).select(true); + essence_->trace_last_selected_item (); + break; + case keyboard::os_end: + essence_->lister.select_for_all(false); + item_proxy::from_display(essence_, essence_->lister.last()).select(true); + essence_->trace_last_selected_item (); + break; default: return; From 0d736db47984ab653fb2448b831bf7946d9a9486 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 24 Apr 2015 17:25:27 +0200 Subject: [PATCH 02/18] FIX: PageDown select last item in page not first --- source/gui/widgets/listbox.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 75968f93..daf9bc2f 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3256,7 +3256,6 @@ namespace nana void trigger::key_press(graph_reference graph, const arg_keyboard& arg) { bool up = false; - switch(arg.key) { case keyboard::os_arrow_up: @@ -3290,8 +3289,14 @@ namespace nana if (! scrl.make_page_scroll(!up)) return; essence_->lister.select_for_all(false); - item_proxy {essence_, essence_->scroll_y_abs() } .select(true); - + if (up) + item_proxy {essence_, essence_->scroll_y_abs()}.select(true); + else + { + index_pair idx{essence_->scroll_y_dpl()}; + essence_->lister.forward(idx, scrl.range()-1, idx); + item_proxy::from_display(essence_,idx).select(true); + } break; } case keyboard::os_home: From 063968a803ec5daf71311aaab87da85495b6c02b Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 10:16:51 +0200 Subject: [PATCH 03/18] working on listbox export to string CSV: listbox, header, dummy list --- source/gui/widgets/listbox.cpp | 58 ++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index daf9bc2f..506c7f38 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -333,6 +333,24 @@ namespace nana typedef std::vector container; + nana::string to_string() const + { + nana::string sep{STR(";")}, endl{STR("\n")}, head_str; + bool first{true}; + for(auto & i: cont()) + { + if(i.visible) + { + if(first) + first=false; + else + head_str += sep; + head_str += i.text; + } + } + return head_str; + } + bool visible() const { return visible_; @@ -651,6 +669,39 @@ namespace nana } return nullptr; } + nana::string to_string() const + { + nana::string sep{STR(";")}, endl{STR("\n")}, list_str{STR("Empieza list: ")}; + bool first{true}; + for(auto & cat: cat_container()) + { + list_str += STR("categorias: ") ; + if(first) + first=false; + else + { + //if(cat.selected()) + list_str += (cat.text + STR("categorias 2 ") + endl); + } + list_str += STR("categorias: ") ; + bool first_it{true}; + for (auto i : cat.sorted) + { + auto& it= cat.items[i] ; + if(it.flags.selected) + { + list_str += (it.cells[0].text + endl); + if(first_it) + first_it=false; + else + { + } + } + + } + } + return list_str + STR("Termina: "); + } /// each sort() ivalidate any existing reference from display position to absolute item, that is after sort() display offset point to different items void sort() @@ -1838,6 +1889,13 @@ namespace nana lister.fetch_ordering_comparer = std::bind(&es_header::fetch_comp, &header, std::placeholders::_1); } + nana::string to_string() const + { + nana::string sep{STR(";")}, endl{STR("\n")}; + lister.to_string(); + return header.to_string() + endl + lister.to_string() ; + } + const index_pair& scroll_y_abs() const { return scroll.offset_y_abs; From 1fb363fb72bbcf26f7ef7794daf64237fedc6422 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 10:22:34 +0200 Subject: [PATCH 04/18] listbox override key_char to manage copy: Ctrl-C. --- include/nana/gui/widgets/listbox.hpp | 1 + source/gui/widgets/listbox.cpp | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 1827a585..5e3fc92e 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -194,6 +194,7 @@ namespace nana void dbl_click(graph_reference, const arg_mouse&) override; void resized(graph_reference, const arg_resized&) override; void key_press(graph_reference, const arg_keyboard&) override; + void key_char(graph_reference, const arg_keyboard&) override; private: essence_t * essence_; drawer_header_impl *drawer_header_; diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 506c7f38..4a1cd532 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -702,7 +702,7 @@ namespace nana } return list_str + STR("Termina: "); } - + /// each sort() ivalidate any existing reference from display position to absolute item, that is after sort() display offset point to different items void sort() { @@ -1896,7 +1896,7 @@ namespace nana return header.to_string() + endl + lister.to_string() ; } - const index_pair& scroll_y_abs() const + const index_pair& scroll_y_abs() const { return scroll.offset_y_abs; } @@ -3332,13 +3332,6 @@ namespace nana } break; - case keyboard::copy: - { - nana::string str{STR("to_csv()")}; - //nana::system::dataexch().set(str); - return; - } - case keyboard::os_pageup : up = true; case keyboard::os_pagedown: @@ -3374,6 +3367,19 @@ namespace nana draw(); API::lazy_refresh(); } + + void trigger::key_char(graph_reference graph, const arg_keyboard& arg) + { + switch(arg.key) + { + case keyboard::copy: + nana::system::dataexch().set(essence_->to_string()); + return; + default: + return; + } + } + //end class trigger //class item_proxy From 26bca2cc0843f0e18f7570ae0aa28f05188c32fb Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 17:29:32 +0200 Subject: [PATCH 05/18] listbox: introducing struct export options --- include/nana/gui/widgets/listbox.hpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 5e3fc92e..e38fdbbe 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -429,7 +429,19 @@ namespace nana category_t* cat_{nullptr}; size_type pos_{0}; ///< Absolute position, not relative to display, and dont change during sort() }; - } + + struct export_options + { + nana::string sep = nana::string {STR(";" )}, + endl= nana::string {STR("\n")} ; + bool only_selected_items{true}, + only_checked_items {false}, + only_visible_columns{true}; + + using columns_indexs = std::vector; + columns_indexs columns_order; + }; + } }//end namespace drawerbase struct arg_listbox @@ -482,7 +494,9 @@ By \a clicking on a header the list get \a reordered, first up, and then down al using selection = drawerbase::listbox::selection; /// Date: Sat, 25 Apr 2015 17:44:31 +0200 Subject: [PATCH 06/18] columns_indexs all_headers( only_visibles) --- source/gui/widgets/listbox.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 4a1cd532..524b64f4 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -331,7 +331,18 @@ namespace nana {} }; - typedef std::vector container; + using container = std::vector ; + + export_options::columns_indexs all_headers(bool only_visibles) const + { + export_options::columns_indexs idx; + for(auto hd : cont()) + { + if(!only_visibles || hd.visible) + idx.push_back(hd.index); + } + return idx; + } nana::string to_string() const { From 8fdbb0bf44f71dfba73ae60884fc92bbd5d2dbdb Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 17:45:16 +0200 Subject: [PATCH 07/18] item to string in column order --- source/gui/widgets/listbox.cpp | 71 ++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 524b64f4..a14fe980 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -607,6 +607,21 @@ namespace nana return *this; } + nana::string to_string(const export_options::columns_indexs& col_order) const + { + nana::string sep{STR(";")}, endl{STR("\n")}, item_str; + bool first{true}; + for( size_type idx{}; idxheader.all_headers(true); + bool first{true}; + for(auto & cat: cat_container()) + { + if(first) + first=false; + else + list_str += (cat.text + endl); + + bool first_item{true}; + for (auto i : cat.sorted) + { + auto& it= cat.items[i] ; + if(it.flags.selected) + list_str += (it.to_string(col_order) + endl); + } + } + return list_str ; + } class drawer_header_impl From 2767fa75ca2382110e1e8e4ecfb3956f244ca43f Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 20:53:13 +0200 Subject: [PATCH 08/18] listbox have def_export_options(); --- include/nana/gui/widgets/listbox.hpp | 3 ++- source/gui/widgets/listbox.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index e38fdbbe..9599a484 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -432,7 +432,7 @@ namespace nana struct export_options { - nana::string sep = nana::string {STR(";" )}, + nana::string sep = nana::string {STR("\t" )}, endl= nana::string {STR("\n")} ; bool only_selected_items{true}, only_checked_items {false}, @@ -591,6 +591,7 @@ By \a clicking on a header the list get \a reordered, first up, and then down al void enable_single(bool for_selection, bool category_limited); void disable_single(bool for_selection); + export_options& def_export_options(); private: drawerbase::listbox::essence_t & _m_ess() const; nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const; diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index a14fe980..aa78abee 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -1856,6 +1856,13 @@ namespace nana unsigned item_size{24}; unsigned text_height{0}; unsigned suspension_width{0}; + ::nana::listbox::export_options def_exp_options ; + + ::nana::listbox::export_options& def_export_options() + { + return def_exp_options; + } + es_header header; es_lister lister; // we have at least one emty cat. the #0 @@ -4191,6 +4198,11 @@ namespace nana _m_ess().lister.disable_single(for_selection); } + listbox::export_options& listbox::def_export_options() + { + return _m_ess().def_export_options(); + } + drawerbase::listbox::essence_t & listbox::_m_ess() const { return get_drawer_trigger().essence(); From 7fcd38816bc7204714f3bda648a0d9badbdb2ac9 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 20:59:28 +0200 Subject: [PATCH 09/18] to string take (uses) export options --- source/gui/widgets/listbox.cpp | 89 +++++++++------------------------- 1 file changed, 23 insertions(+), 66 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index aa78abee..5888ef81 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace nana { @@ -344,20 +345,21 @@ namespace nana return idx; } - nana::string to_string() const + nana::string to_string(const export_options& exp_opt) const { - nana::string sep{STR(";")}, endl{STR("\n")}, head_str; + nana::string head_str; bool first{true}; - for(auto & i: cont()) - { - if(i.visible) + for( size_type idx{}; idxhandle()); } -#if ( 0 ) - void update_selection_range(index_pair to, const arg_mouse& arg) - { - using item_state = essence_t::item_state; - using parts = essence_t::parts; - bool update = false; - index_pair item_pos; - bool sel = true; - if (!lister.single_selection()) - { - if (arg.shift) - lister.select_display_range(lister.last_selected, item_pos, sel); - else if (arg.ctrl) - sel = !item_proxy(essence_, index_pair (item_pos.cat, lister.absolute(item_pos))).selected(); - else - lister.select_for_all(false); - } - else - sel = !item_proxy(essence_, index_pair (item_pos.cat, lister.absolute(item_pos))).selected(); - - item_ptr->flags.selected = sel; - index_pair last_selected(item_pos.cat, lister.absolute(item_pos)); - - arg_listbox arg{item_proxy{essence_, last_selected}, sel}; - lister.wd_ptr()->events().selected.emit(arg); - - if (item_ptr->flags.selected) - { - lister.cancel_others_if_single_enabled(true, last_selected); - essence_->lister.last_selected = last_selected; - - } - else if (essence_->lister.last_selected == last_selected) - essence_->lister.last_selected.set_both(npos); - } - else if(!lister.single_selection()) - lister.categ_selected(item_pos.cat, true); - update = true; - - } -#endif - }; void es_lister::scroll_refresh() @@ -2450,24 +2408,23 @@ namespace nana else break; } } - nana::string es_lister::to_string() const + nana::string es_lister::to_string(const export_options& exp_opt) const { - nana::string sep{STR(";")}, endl{STR("\n")}, list_str; - auto col_order = ess_->header.all_headers(true); + nana::string list_str; bool first{true}; for(auto & cat: cat_container()) { if(first) first=false; else - list_str += (cat.text + endl); + list_str += (cat.text + exp_opt.endl); bool first_item{true}; for (auto i : cat.sorted) { auto& it= cat.items[i] ; - if(it.flags.selected) - list_str += (it.to_string(col_order) + endl); + if(it.flags.selected || !exp_opt.only_selected_items) + list_str += (it.to_string(exp_opt) + exp_opt.endl); } } return list_str ; From 49378469ab5ee6805e48b68436b415c643a55f2b Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 20:59:54 +0200 Subject: [PATCH 10/18] copy base on def export options --- source/gui/widgets/listbox.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 5888ef81..482e8e9c 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3353,8 +3353,13 @@ namespace nana switch(arg.key) { case keyboard::copy: - nana::system::dataexch().set(essence_->to_string()); + { + export_options exp_opt {essence_->def_export_options()}; + exp_opt.columns_order = essence_->header.all_headers(true); + exp_opt.only_selected_items = true; + nana::system::dataexch().set(essence_->to_string(exp_opt)); return; + } default: return; } From db0591a5db53dcb7158df6e6649a06fbf90f595f Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 21:39:09 +0200 Subject: [PATCH 11/18] allow programmatically export an arbitrary set of columns --- source/gui/widgets/listbox.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 482e8e9c..1310c1f8 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -350,16 +350,20 @@ namespace nana nana::string head_str; bool first{true}; for( size_type idx{}; idxvisible || ! exp_opt.only_visible_columns); + + if(first) + first=false; + else head_str += exp_opt.sep; - head_str += cont()[idx].text; + head_str += col->text; } return head_str; } @@ -3358,7 +3362,7 @@ namespace nana exp_opt.columns_order = essence_->header.all_headers(true); exp_opt.only_selected_items = true; nana::system::dataexch().set(essence_->to_string(exp_opt)); - return; + return; } default: return; From 83fa73d11faa3dac8b14ee0835ca94ec941f2ccb Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 25 Apr 2015 22:56:53 +0200 Subject: [PATCH 12/18] listbox select all Now the programs user can "export" the whole list just by pressing ctrl+A-C and pasting into another application, like LibreOffice Calc, Excel, an editor, etc --- source/gui/widgets/listbox.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 1310c1f8..b2fdde1c 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3364,6 +3364,12 @@ namespace nana nana::system::dataexch().set(essence_->to_string(exp_opt)); return; } + case keyboard::select_all : + essence_->lister.select_for_all(true); + draw(); + API::lazy_refresh(); + break; + default: return; } From 585732a497dbbfbea0f1e30bbc571c2ad8ecb974 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 26 Apr 2015 02:32:22 +0200 Subject: [PATCH 13/18] simpler code --- source/gui/widgets/listbox.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index b2fdde1c..88f04699 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -351,19 +351,23 @@ namespace nana bool first{true}; for( size_type idx{}; idxvisible || ! exp_opt.only_visible_columns); - if(first) first=false; else head_str += exp_opt.sep; - head_str += col->text; + size_type index{exp_opt.columns_order[idx]}; + bool bad{true}; + for (auto&col:cont()) + if(col.index == index) + { + bad=false; + head_str += col.text; + break; + } + + if(bad) + throw std::out_of_range("Trying to export from a lisboxt an inexisting column"); } return head_str; } From 4b4843bb7f7fdf8bfac0643226373fde16316fb5 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Mon, 27 Apr 2015 01:00:26 +0200 Subject: [PATCH 14/18] fix necessary copy, add comments and code review --- include/nana/gui/widgets/listbox.hpp | 5 +- source/gui/widgets/listbox.cpp | 90 ++++++++++++++-------------- 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 8d630ea5..d4775fc3 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -17,6 +17,7 @@ #include "widget.hpp" #include #include +//#include #include #include @@ -28,7 +29,7 @@ namespace nana { namespace listbox { - typedef std::size_t size_type; + using size_type = std::size_t ; struct cell { @@ -36,7 +37,7 @@ namespace nana { ::nana::color bgcolor; ::nana::color fgcolor; - + /// ::nana::paint::font font; \todo format() = default; format(const ::nana::color& bgcolor, const ::nana::color& fgcolor); }; diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 88f04699..9cc63577 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -313,14 +313,14 @@ namespace nana } //end class iresolver/oresolver - class es_header /// Essence of the columns Header + /// Essence of the columns Header + class es_header { public: - typedef std::size_t size_type; struct column_t { - nana::string text; //< "text" header of the column number "index" with weigth "pixels" + nana::string text; ///< "text" header of the column number "index" with weigth "pixels" unsigned pixels; bool visible{true}; size_type index; @@ -337,10 +337,10 @@ namespace nana export_options::columns_indexs all_headers(bool only_visibles) const { export_options::columns_indexs idx; - for(auto hd : cont()) + for(const auto &header : cont()) { - if(!only_visibles || hd.visible) - idx.push_back(hd.index); + if(header.visible || !only_visibles) + idx.push_back(header.index); } return idx; } @@ -356,18 +356,7 @@ namespace nana else head_str += exp_opt.sep; - size_type index{exp_opt.columns_order[idx]}; - bool bad{true}; - for (auto&col:cont()) - if(col.index == index) - { - bad=false; - head_str += col.text; - break; - } - - if(bad) - throw std::out_of_range("Trying to export from a lisboxt an inexisting column"); + head_str += column_ref(exp_opt.columns_order[idx]).text; } return head_str; } @@ -438,6 +427,7 @@ 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 { return (n < cont_.size() ? cont_[n].index : npos); @@ -448,6 +438,7 @@ namespace nana return cont_; } + /// find and return a ref to the column that originaly was at position "pos" previous to any list reorganization. column_t& column(size_type pos) { for(auto & m : cont_) @@ -457,18 +448,29 @@ namespace nana } throw std::out_of_range("Nana.GUI.Listbox: invalid header index."); } + const column_t& column_ref(size_type pos) const + { + for(const auto & m : cont_) + { + if(m.index == pos) + return m; + } + throw std::out_of_range("Nana.GUI.Listbox: invalid header index."); + } + /// return the original index of the current column at x . size_type item_by_x(int x) const { - for(auto & m : cont_) + for(const auto & col : cont_) // in current order { - if(x < static_cast(m.pixels)) - return m.index; - x -= m.pixels; + if(x < static_cast(col.pixels)) + return col.index; + x -= col.pixels; } return npos; } + /// return the left position of the column originaly at index "pos" . int item_pos(size_type pos, unsigned * pixels) const { int left = 0; @@ -486,11 +488,11 @@ namespace nana } return left; } - + /// return the original index of the visible col currently before(in front of) or after the col originaly at index "index" size_type neighbor(size_type index, bool front) const { size_type n = npos; - for(auto i = cont_.cbegin(); i != cont_.cend(); ++i) + for(auto i = cont_.cbegin(); i != cont_.cend(); ++i) // in current order { if(i->index == index) { @@ -506,16 +508,17 @@ namespace nana } return npos; } - + /// return the original index of the currently first visible col size_type begin() const { - for(auto & m : cont_) + for(const auto & m : cont_) { if(m.visible) return m.index; } return npos; } + /// return the original index of the currently last visible col size_type last() const { for(auto i = cont_.rbegin(); i != cont_.rend(); ++i) @@ -524,25 +527,24 @@ 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) { - if((index != to) && (index < cont_.size()) && (to < cont_.size())) - { - auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){ - return (index == m.index); - }); + if(index == to) return; + if(index >= cont_.size()) return; + if(to >= cont_.size()) return; - if (i == cont_.end()) - return; + auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){return (index == m.index);}); - auto from = *i; - cont_.erase(i); + if (i == cont_.end()) + return; - 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); - } + auto from = *i; // a temp copy + 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}; @@ -553,7 +555,7 @@ namespace nana struct item_t { - typedef std::vector container; + using container = std::vector; container cells; nana::color bgcolor; @@ -2463,13 +2465,13 @@ namespace nana if(essence_->ptr_state == item_state::highlighted) { x -= (r.x - essence_->scroll.offset_x); - for(auto & hd : essence_->header.cont()) + for(auto & hd : essence_->header.cont()) // in current order { if(hd.visible) { if((static_cast(hd.pixels) - 2 < x) && (x < static_cast(hd.pixels) + 3)) { - item_spliter_ = hd.index; + item_spliter_ = hd.index; // original index return true; } x -= hd.pixels; @@ -3058,7 +3060,7 @@ namespace nana } } - if(essence_->ptr_state == item_state::grabbed) + if(essence_->ptr_state == item_state::grabbed) { nana::point pos = arg.pos; essence_->widget_to_header(pos); From 611d295fc854199badaa008560fb8e3c5d784ff6 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Mon, 27 Apr 2015 13:26:44 +0200 Subject: [PATCH 15/18] comment key use --- include/nana/gui/widgets/listbox.hpp | 3 +++ include/nana/key_type.hpp | 4 ++-- source/gui/widgets/listbox.cpp | 9 +++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index d4775fc3..eacc6857 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -514,8 +514,11 @@ By \a clicking on a header the list get \a reordered, first up, and then down al void append(std::initializer_list); /// cat_proxy operator[](const Key & ck) { diff --git a/include/nana/key_type.hpp b/include/nana/key_type.hpp index 9550f8df..dcfa4f79 100644 --- a/include/nana/key_type.hpp +++ b/include/nana/key_type.hpp @@ -22,10 +22,10 @@ namespace nana virtual ~key_interface(){} virtual bool same_type(const key_interface*) const = 0; - virtual bool compare(const key_interface*) const = 0; + virtual bool compare(const key_interface*) const = 0; ///< is this key less than right key? [call it less(rk), less_than(rk) or compare_less(rk)?: if (lk.less_than(rk )) ] }; //end class key_interface - //Use less compare for equal compare + //Use less compare for equal compare [call it equal_by_less()?] inline bool pred_equal_by_less(const key_interface * left, const key_interface* right) { return (left->compare(right) == false) && (right->compare(left) == false); diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 9cc63577..95c216a9 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -834,20 +834,21 @@ namespace nana return sorted_reverse_; } - ///Append a new category with a specified name. + ///Append a new category with a specified name and return a pointer to it. category_t* create_cat(nana::string&& text) { list_.emplace_back(std::move(text)); return &list_.back(); } - + /// just append a list of new cat. void create_cat(const std::initializer_list& args) { for (auto & arg : args) list_.emplace_back(arg); } - category_t* create_cat(std::shared_ptr ptr) + /// will use the key to insert new cat before the first cat with compare less than the key, or at the end of the list of cat and return a ref to that new cat. ? + category_t* create_cat(std::shared_ptr ptr) { for (auto i = list_.begin(); i != list_.end(); ++i) { @@ -863,7 +864,7 @@ namespace nana list_.back().key_ptr = ptr; return &list_.back(); } - + /// add a new cat created at "pos" and return a ref to it category_t* create_cat(std::size_t pos, nana::string&& text) { #if defined(NANA_LINUX) || defined(NANA_MINGW) From 4fcd2edd54d3f8e346d619c893bdb72a89bdf836 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Wed, 29 Apr 2015 12:44:52 +0200 Subject: [PATCH 16/18] FIX: crash when clear an ordered listbox --- source/gui/widgets/listbox.cpp | 50 ++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 95c216a9..f1ebd7d6 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -943,7 +943,7 @@ namespace nana catobj.items.clear(); catobj.sorted.clear(); } - + /// clear all items in all cat, but not the container of cat self. void clear() { for(auto & m : list_) @@ -1677,7 +1677,18 @@ namespace nana ///Translate relative position (position in display) into absolute position (original data order) size_type absolute(const index_pair& display_pos) const { - return (sorted_index_ == npos ? display_pos.item : _m_at(display_pos.cat)->sorted[display_pos.item]); + if(sorted_index_ == npos) + return display_pos.item ; + + auto & catobj = *_m_at(display_pos.cat); + + if(catobj.items.size()==0) + if (display_pos == index_pair{0,0} ) + return 0; + else + return npos; + + return catobj.sorted[display_pos.item] ; } index_pair absolute_pair(const index_pair& display_pos) const { @@ -1687,7 +1698,8 @@ namespace nana ///Translate absolute position (original data order) into relative position (position in display) size_type relative(const index_pair& pos) const { - if (sorted_index_ == npos) return pos.item ; + if (sorted_index_ == npos) + return pos.item ; auto & catobj = *_m_at(pos.cat); @@ -1695,6 +1707,10 @@ namespace nana if (pos.item == catobj.sorted[i]) return i; + if (pos == index_pair{0,0} ) + if(catobj.items.size()==0) + return 0; + return npos ; } index_pair relative_pair(const index_pair& pos) const @@ -1934,7 +1950,12 @@ namespace nana else if(number) scroll.offset_y_abs.item = number - 1; else + { scroll.offset_y_abs.item = (pos_abs.cat > 0 ? npos : 0); + scroll.offset_y_dpl = scroll.offset_y_abs ; + return ; + } + scroll_y_dpl_refresh() ; } void scroll_y_rel(const index_pair& pos_rel) { @@ -4025,12 +4046,13 @@ namespace nana { auto & ess = _m_ess(); ess.lister.clear(cat); - auto pos = ess.scroll_y_dpl(); - if(pos.cat == cat) - { - pos.item = (pos.cat > 0 ? npos : 0); - ess.set_scroll_y_dpl(pos); - } + //unsort(); // ?? + + // from current display position + // move to the cat self if not in first cat + // move to first item ?? if in first cat + ess.scroll_y_abs(ess.scroll_y_abs()); + ess.update(); } @@ -4038,9 +4060,13 @@ namespace nana { auto & ess = _m_ess(); ess.lister.clear(); - auto pos = ess.scroll_y_dpl(); - pos.item = (pos.cat > 0 ? npos : 0); - ess.set_scroll_y_dpl(pos); + unsort(); // apperar to be espected + + // from current display position + // move to the cat self if not in first cat + // move to first item ?? if in first cat + ess.scroll_y_abs(ess.scroll_y_abs()); + ess.update(); } From 97db67b2a445c5d748ff4518348e6cd1079bbfc6 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Wed, 29 Apr 2015 12:45:37 +0200 Subject: [PATCH 17/18] FIX: a crash when clear an empty listbox --- source/gui/widgets/listbox.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index f1ebd7d6..488903e8 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -1711,7 +1711,7 @@ namespace nana if(catobj.items.size()==0) return 0; - return npos ; + return npos ; } index_pair relative_pair(const index_pair& pos) const { @@ -1951,7 +1951,7 @@ namespace nana scroll.offset_y_abs.item = number - 1; else { - scroll.offset_y_abs.item = (pos_abs.cat > 0 ? npos : 0); + scroll.offset_y_abs.item = (pos_abs.cat > 0 ? npos : 0); scroll.offset_y_dpl = scroll.offset_y_abs ; return ; } @@ -3326,6 +3326,10 @@ namespace nana void trigger::key_press(graph_reference graph, const arg_keyboard& arg) { bool up = false; + + if (essence_->lister.size_categ()==1 && essence_->lister.size_item(0)==0) + return ; + switch(arg.key) { case keyboard::os_arrow_up: From c6df0c4293dee26e1b494e111f4fe62ee26699c4 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Wed, 29 Apr 2015 23:05:14 +0200 Subject: [PATCH 18/18] FIX: a draw problem with item in listbox --- source/gui/widgets/listbox.cpp | 57 ++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 488903e8..fef9660b 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -2297,7 +2297,7 @@ namespace nana void header_seq(std::vector &seqs, unsigned lister_w)const { int x = - (scroll.offset_x); - for(auto hd : header.cont()) + for(const auto& hd : header.cont()) { if(false == hd.visible) continue; x += hd.pixels; @@ -2711,7 +2711,9 @@ namespace nana unsigned header_w = essence_->header.pixels(); essence_->graph->set_color(bgcolor); if(header_w - essence_->scroll.offset_x < rect.width) - essence_->graph->rectangle(rectangle{ rect.x + static_cast(header_w)-essence_->scroll.offset_x, rect.y, rect.width - (header_w - essence_->scroll.offset_x), rect.height }, true); + essence_->graph->rectangle(rectangle{ point(rect.x + static_cast(header_w)-essence_->scroll.offset_x, rect.y), + size(static_cast(rect.width) + essence_->scroll.offset_x - static_cast(header_w), rect.height) }, + true); es_lister & lister = essence_->lister; //The Tracker indicates the item where mouse placed. @@ -2739,12 +2741,12 @@ namespace nana auto state = item_state::normal; - //Here draws a root categ or a first drawing is not a categ. + //Here we draw the root categ (0) or a first item if the first drawing is not a categ.(item!=npos)) if(idx.cat == 0 || !idx.is_category()) { - if (idx.cat == 0 && idx.is_category()) + if (idx.cat == 0 && idx.is_category()) // the 0 cat { - essence_->scroll.offset_y_dpl.item = 0; + essence_->scroll.offset_y_dpl.item = 0; // no, we draw the first item of cat 0, not the 0 cat itself idx.item = 0; } @@ -2837,7 +2839,7 @@ namespace nana void _m_draw_item(const item_t& item, int x, int y, int txtoff, unsigned width, const nana::rectangle& r, const std::vector& seqs, nana::color bgcolor, nana::color fgcolor, item_state state) const { - if (item.flags.selected) + if (item.flags.selected) // fetch the "def" colors bgcolor = essence_->scheme_ptr->item_selected; else if (!item.bgcolor.invisible()) bgcolor = item.bgcolor; @@ -2846,10 +2848,10 @@ namespace nana fgcolor = item.fgcolor; auto graph = essence_->graph; - if (item_state::highlighted == state) + if (item_state::highlighted == state) // and blend it if "highlighted" { if (item.flags.selected) - bgcolor = bgcolor.blend(colors::black, 0.98); + bgcolor = bgcolor.blend(colors::black, 0.98); // or "selected" else bgcolor = bgcolor.blend(essence_->scheme_ptr->item_selected, 0.7); } @@ -2865,20 +2867,22 @@ namespace nana unsigned extreme_text = x; bool first = true; - for(auto index : seqs) + + for(size_type display_order{0}; display_order < seqs.size(); ++display_order) // get the cell (column) index in the order headers are displayed { - const auto & header = essence_->header.column(index); + auto index = seqs[display_order]; + const auto & header = essence_->header.column(index); // deduce the corresponding header which is in a kind of dislay order auto it_bgcolor = bgcolor; - if ((item.cells.size() > index) && (header.pixels > 5)) + if ((item.cells.size() > index) && (header.pixels > 5)) // process only if the cell is visible { auto cell_txtcolor = fgcolor; auto & m_cell = item.cells[index]; - nana::size ts = graph->text_extent_size(m_cell.text); + nana::size ts = graph->text_extent_size(m_cell.text); // precalcule text geometry - if (m_cell.custom_format && (!m_cell.custom_format->bgcolor.invisible())) + if (m_cell.custom_format && (!m_cell.custom_format->bgcolor.invisible())) // adapt to costum format if need { - it_bgcolor = m_cell.custom_format->bgcolor; + it_bgcolor = m_cell.custom_format->bgcolor; if (item.flags.selected) it_bgcolor = it_bgcolor.blend( bgcolor , 0.5) ; if (item_state::highlighted == state) @@ -2891,7 +2895,7 @@ namespace nana } int ext_w = 5; - if(first && essence_->checkable) + if(first && essence_->checkable) // draw the checkbox if need, only before the first column (display_order=0 ?) { ext_w += 18; @@ -2913,7 +2917,7 @@ namespace nana crook_renderer_.draw(*graph, bgcolor, fgcolor, essence_->checkarea(item_xpos, y), estate); } - if ((0 == index) && essence_->if_image) + if ((0 == index) && essence_->if_image) // draw the image if need, ??only before the first column?? (display_order=0 ?) { if (item.img) { @@ -2926,23 +2930,24 @@ namespace nana } graph->set_text_color(cell_txtcolor); - graph->string(point{ item_xpos + ext_w, y + txtoff }, m_cell.text); + graph->string(point{ item_xpos + ext_w, y + txtoff }, m_cell.text); // draw full text of the cell index (column) - if (ts.width + ext_w > header.pixels) + if (ts.width + ext_w > header.pixels) // it was an excess { - //The text is painted over the next subitem - int xpos = item_xpos + header.pixels - essence_->suspension_width; + //The text is painted over the next subitem // here beging the ... + int xpos = item_xpos + static_cast(header.pixels) - static_cast(essence_->suspension_width); - graph->set_color(it_bgcolor); - graph->rectangle(rectangle{ xpos, y + 2, essence_->suspension_width, essence_->item_size - 4 }, true); + graph->set_color(it_bgcolor); // litter rect with the item bg end ... + graph->rectangle(rectangle{ xpos, y + 2, essence_->suspension_width, essence_->item_size - 4 }, true); graph->set_text_color(cell_txtcolor); graph->string(point{ xpos, y + 2 }, STR("...")); //Erase the part that over the next subitem. - if (index + 1 < seqs.size()) + if ( display_order + 1 < seqs.size() ) // this is not the last column { - graph->set_color(bgcolor); - graph->rectangle(rectangle{item_xpos + static_cast(header.pixels), y + 2, ts.width + ext_w - header.pixels, essence_->item_size - 4}, true); + graph->set_color(bgcolor); // we need to erase the excess, because some cell may not draw text over + graph->rectangle(rectangle{item_xpos + static_cast(header.pixels), y + 2, + ts.width + ext_w - header.pixels, essence_->item_size - 4}, true); } extreme_text = std::max (extreme_text, item_xpos + ext_w + ts.width); } @@ -2951,7 +2956,7 @@ namespace nana graph->line({ item_xpos - 1, y }, { item_xpos - 1, y + static_cast(essence_->item_size) - 1 }, { 0xEB, 0xF4, 0xF9 }); item_xpos += header.pixels; - if (index + 1 >= seqs.size() && static_cast(extreme_text) > item_xpos) + if (display_order + 1 >= seqs.size() && static_cast(extreme_text) > item_xpos) { graph->set_color(item.bgcolor); graph->rectangle(rectangle{item_xpos , y + 2, extreme_text - item_xpos, essence_->item_size - 4}, true);