751 lines
25 KiB
C++
751 lines
25 KiB
C++
/**
|
|
* A List Box Implementation
|
|
* Nana C++ Library(http://www.nanapro.org)
|
|
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
|
*
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*
|
|
* @file: nana/gui/widgets/listbox.hpp
|
|
* @contributors:
|
|
* Hiroshi Seki
|
|
* Ariel Vina-Rodriguez
|
|
* leobackes
|
|
* Benjamin Navarro
|
|
*/
|
|
|
|
#ifndef NANA_GUI_WIDGETS_LISTBOX_HPP
|
|
#define NANA_GUI_WIDGETS_LISTBOX_HPP
|
|
#include "widget.hpp"
|
|
#include "detail/inline_widget.hpp"
|
|
#include <nana/pat/abstract_factory.hpp>
|
|
#include <nana/concepts.hpp>
|
|
#include <nana/key_type.hpp>
|
|
#include <functional>
|
|
#include <initializer_list>
|
|
|
|
namespace nana
|
|
{
|
|
class listbox;
|
|
|
|
namespace drawerbase
|
|
{
|
|
namespace listbox
|
|
{
|
|
using size_type = std::size_t;
|
|
using native_string_type = ::nana::detail::native_string_type;
|
|
|
|
/// usefull for both absolute and display (sorted) positions
|
|
struct index_pair
|
|
{
|
|
size_type cat; //The pos of category
|
|
size_type item; //the pos of item in a category.
|
|
|
|
index_pair(size_type cat_pos = 0, size_type item_pos = 0)
|
|
: cat(cat_pos),
|
|
item(item_pos)
|
|
{}
|
|
|
|
bool empty() const
|
|
{
|
|
return (npos == cat);
|
|
}
|
|
|
|
void set_both(size_type n)
|
|
{
|
|
cat = item = n;
|
|
}
|
|
|
|
bool is_category() const
|
|
{
|
|
return (npos != cat && npos == item);
|
|
}
|
|
|
|
bool is_item() const
|
|
{
|
|
return (npos != cat && npos != item);
|
|
}
|
|
|
|
bool operator==(const index_pair& r) const
|
|
{
|
|
return (r.cat == cat && r.item == item);
|
|
}
|
|
|
|
bool operator!=(const index_pair& r) const
|
|
{
|
|
return !this->operator==(r);
|
|
}
|
|
|
|
bool operator>(const index_pair& r) const
|
|
{
|
|
return (cat > r.cat) || (cat == r.cat && item > r.item);
|
|
}
|
|
};
|
|
|
|
using selection = std::vector<index_pair>;
|
|
|
|
using inline_notifier_interface = detail::inline_widget_notifier_interface<index_pair, std::string>;
|
|
|
|
struct cell
|
|
{
|
|
struct format
|
|
{
|
|
::nana::color bgcolor;
|
|
::nana::color fgcolor;
|
|
/// ::nana::paint::font font; \todo
|
|
format() = default;
|
|
format(const ::nana::color& bgcolor, const ::nana::color& fgcolor);
|
|
};
|
|
|
|
using format_ptr = ::std::unique_ptr<format>;
|
|
|
|
::std::string text;
|
|
format_ptr custom_format;
|
|
|
|
cell() = default;
|
|
cell(const cell&);
|
|
cell(cell&&);
|
|
cell(::std::string);
|
|
cell(::std::string, const format&);
|
|
cell(::std::string, const ::nana::color& bgcolor, const ::nana::color& fgcolor);
|
|
|
|
cell& operator=(const cell&);
|
|
cell& operator=(cell&&);
|
|
};
|
|
|
|
class oresolver
|
|
{
|
|
public:
|
|
oresolver& operator<<(bool);
|
|
oresolver& operator<<(short);
|
|
oresolver& operator<<(unsigned short);
|
|
oresolver& operator<<(int);
|
|
oresolver& operator<<(unsigned int);
|
|
oresolver& operator<<(long);
|
|
oresolver& operator<<(unsigned long);
|
|
oresolver& operator<<(long long);
|
|
oresolver& operator<<(unsigned long long);
|
|
oresolver& operator<<(float);
|
|
oresolver& operator<<(double);
|
|
oresolver& operator<<(long double);
|
|
|
|
oresolver& operator<<(const char* text_utf8);
|
|
oresolver& operator<<(const wchar_t*);
|
|
oresolver& operator<<(const std::string& text_utf8);
|
|
oresolver& operator<<(const std::wstring&);
|
|
oresolver& operator<<(std::wstring&&);
|
|
oresolver& operator<<(cell);
|
|
oresolver& operator<<(std::nullptr_t);
|
|
|
|
std::vector<cell> && move_cells();
|
|
private:
|
|
std::vector<cell> cells_;
|
|
};
|
|
|
|
class iresolver
|
|
{
|
|
public:
|
|
iresolver(const std::vector<cell>&);
|
|
|
|
iresolver& operator>>(bool&);
|
|
iresolver& operator>>(short&);
|
|
iresolver& operator>>(unsigned short&);
|
|
iresolver& operator>>(int&);
|
|
iresolver& operator>>(unsigned int&);
|
|
iresolver& operator>>(long&);
|
|
iresolver& operator>>(unsigned long&);
|
|
iresolver& operator>>(long long&);
|
|
iresolver& operator>>(unsigned long long&);
|
|
iresolver& operator>>(float&);
|
|
iresolver& operator>>(double&);
|
|
iresolver& operator>>(long double&);
|
|
|
|
iresolver& operator>>(std::string& text_utf8);
|
|
iresolver& operator>>(std::wstring&);
|
|
iresolver& operator>>(cell&);
|
|
iresolver& operator>>(std::nullptr_t);
|
|
private:
|
|
const std::vector<cell>& cells_;
|
|
std::size_t pos_{0};
|
|
};
|
|
|
|
using selection = std::vector<index_pair>;
|
|
|
|
/// struct essence_t
|
|
///@brief: this struct gives many data for listbox,
|
|
/// the state of the struct does not effect on member funcions, therefore all data members are public.
|
|
struct essence_t;
|
|
|
|
struct category_t;
|
|
class drawer_header_impl;
|
|
class drawer_lister_impl;
|
|
|
|
/// mostly works on display positions
|
|
class trigger: public drawer_trigger
|
|
{
|
|
public:
|
|
trigger();
|
|
~trigger();
|
|
essence_t& essence() const;
|
|
private:
|
|
void _m_draw_border();
|
|
private:
|
|
void attached(widget_reference, graph_reference) override;
|
|
void detached() override;
|
|
void typeface_changed(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;
|
|
void mouse_up(graph_reference, const arg_mouse&) override;
|
|
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
|
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_;
|
|
drawer_lister_impl *drawer_lister_;
|
|
};//end class trigger
|
|
|
|
/// operate with absolute positions and contain only the position but montain pointers to parts of the real items
|
|
/// item_proxy self, it references and iterators are not invalidated by sort()
|
|
class item_proxy
|
|
: public std::iterator<std::input_iterator_tag, item_proxy>
|
|
{
|
|
public:
|
|
item_proxy(essence_t*);
|
|
item_proxy(essence_t*, const index_pair&);
|
|
|
|
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
|
static item_proxy from_display(essence_t *ess, const index_pair &relative) ;
|
|
item_proxy from_display(const index_pair &relative) const;
|
|
|
|
/// posible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort()
|
|
index_pair to_display() const;
|
|
|
|
bool empty() const;
|
|
|
|
item_proxy & check(bool ck);
|
|
bool checked() const;
|
|
|
|
item_proxy & select(bool);
|
|
bool selected() const;
|
|
|
|
item_proxy & bgcolor(const nana::color&);
|
|
nana::color bgcolor() const;
|
|
|
|
item_proxy& fgcolor(const nana::color&);
|
|
nana::color fgcolor() const;
|
|
|
|
index_pair pos() const;
|
|
|
|
size_type columns() const;
|
|
|
|
item_proxy& text(size_type col, cell);
|
|
item_proxy& text(size_type col, std::string);
|
|
item_proxy& text(size_type col, std::wstring);
|
|
std::string text(size_type col) const;
|
|
|
|
void icon(const nana::paint::image&);
|
|
|
|
template<typename T>
|
|
item_proxy & resolve_from(const T& t)
|
|
{
|
|
oresolver ores;
|
|
ores << t;
|
|
auto && cells = ores.move_cells();
|
|
auto cols = columns();
|
|
cells.resize(cols);
|
|
for (auto pos = 0u; pos < cols; ++pos)
|
|
{
|
|
auto & el = cells[pos];
|
|
if (el.text.size() == 1 && el.text[0] == '\0')
|
|
continue;
|
|
text(pos, std::move(el));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
void resolve_to(T& t) const
|
|
{
|
|
iresolver ires(_m_cells());
|
|
ires >> t;
|
|
}
|
|
|
|
template<typename T>
|
|
T* value_ptr() const
|
|
{
|
|
return any_cast<T>(_m_value());
|
|
}
|
|
|
|
template<typename T>
|
|
T & value() const
|
|
{
|
|
auto * pany = _m_value();
|
|
if(nullptr == pany)
|
|
throw std::runtime_error("listbox::item_proxy.value<T>() is empty");
|
|
|
|
T * p = any_cast<T>(_m_value());
|
|
if(nullptr == p)
|
|
throw std::runtime_error("listbox::item_proxy.value<T>() invalid type of value");
|
|
return *p;
|
|
}
|
|
template<typename T>
|
|
T & value()
|
|
{
|
|
auto * pany = _m_value();
|
|
if (nullptr == pany)
|
|
throw std::runtime_error("listbox::item_proxy.value<T>() is empty");
|
|
|
|
T * p = any_cast<T>(_m_value(false));
|
|
if (nullptr == p)
|
|
throw std::runtime_error("listbox::item_proxy.value<T>() invalid type of value");
|
|
return *p;
|
|
}
|
|
template<typename T>
|
|
item_proxy & value(T&& t)
|
|
{
|
|
*_m_value(true) = std::forward<T>(t);
|
|
return *this;
|
|
}
|
|
|
|
/// Behavior of Iterator's value_type
|
|
bool operator==(const char * s) const;
|
|
bool operator==(const wchar_t * s) const;
|
|
bool operator==(const ::std::string& s) const;
|
|
bool operator==(const ::std::wstring& s) const;
|
|
|
|
/// Behavior of Iterator
|
|
item_proxy & operator=(const item_proxy&);
|
|
|
|
/// Behavior of Iterator
|
|
item_proxy & operator++();
|
|
|
|
/// Behavior of Iterator
|
|
item_proxy operator++(int);
|
|
|
|
/// Behavior of Iterator
|
|
item_proxy& operator*();
|
|
|
|
/// Behavior of Iterator
|
|
const item_proxy& operator*() const;
|
|
|
|
/// Behavior of Iterator
|
|
item_proxy* operator->();
|
|
|
|
/// Behavior of Iterator
|
|
const item_proxy* operator->() const;
|
|
|
|
/// Behavior of Iterator
|
|
bool operator==(const item_proxy&) const;
|
|
|
|
/// Behavior of Iterator
|
|
bool operator!=(const item_proxy&) const;
|
|
|
|
//Undocumented method
|
|
essence_t * _m_ess() const;
|
|
private:
|
|
std::vector<cell> & _m_cells() const;
|
|
nana::any * _m_value(bool alloc_if_empty);
|
|
const nana::any * _m_value() const;
|
|
private:
|
|
essence_t * ess_;
|
|
category_t* cat_{nullptr};
|
|
index_pair pos_;
|
|
};
|
|
|
|
class cat_proxy
|
|
: public std::iterator < std::input_iterator_tag, cat_proxy >
|
|
{
|
|
public:
|
|
using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface;
|
|
|
|
cat_proxy() = default;
|
|
cat_proxy(essence_t*, size_type pos);
|
|
cat_proxy(essence_t*, category_t*);
|
|
|
|
/// Append an item at abs end of the category, set_value determines whether assign T object to the value of item.
|
|
template<typename T>
|
|
item_proxy append(T&& t, bool set_value = false)
|
|
{
|
|
oresolver ores;
|
|
if (set_value)
|
|
ores << t; //copy it if it is rvalue and set_value is true.
|
|
else
|
|
ores << std::forward<T>(t);
|
|
|
|
_m_append(ores.move_cells());
|
|
|
|
item_proxy iter{ ess_, index_pair(pos_, size() - 1) };
|
|
if (set_value)
|
|
iter.value(std::forward<T>(t));
|
|
|
|
_m_update();
|
|
|
|
return iter;
|
|
}
|
|
|
|
/// Appends one item at the end of this category with the specifies text in the column fields
|
|
void append(std::initializer_list<std::string> texts_utf8);
|
|
void append(std::initializer_list<std::wstring> texts);
|
|
|
|
size_type columns() const;
|
|
|
|
cat_proxy& text(std::string);
|
|
cat_proxy& text(std::wstring);
|
|
std::string text() const;
|
|
|
|
cat_proxy & select(bool);
|
|
bool selected() const;
|
|
|
|
/// Behavior of a container
|
|
void push_back(std::string text_utf8);
|
|
|
|
item_proxy begin() const;
|
|
item_proxy end() const;
|
|
item_proxy cbegin() const;
|
|
item_proxy cend() const;
|
|
|
|
item_proxy at(size_type pos_abs) const;
|
|
item_proxy back() const;
|
|
|
|
/// Returns the absolute index of a item by its display pos, the index of the item isn't changed after sorting.
|
|
/// convert from display order to absolute (find the real item in that display pos) but without check from current active sorting, in fact using just the last sorting !!!
|
|
size_type index_by_display_order(size_type disp_order) const;
|
|
|
|
/// find display order for the real item but without check from current active sorting, in fact using just the last sorting !!!
|
|
size_type display_order(size_type pos) const;
|
|
|
|
/// this cat position
|
|
size_type position() const;
|
|
|
|
/// Returns the number of items
|
|
size_type size() const;
|
|
|
|
/// Behavior of Iterator
|
|
cat_proxy& operator=(const cat_proxy&);
|
|
|
|
/// Behavior of Iterator
|
|
cat_proxy & operator++();
|
|
|
|
/// Behavior of Iterator
|
|
cat_proxy operator++(int);
|
|
|
|
/// Behavior of Iterator
|
|
cat_proxy& operator*();
|
|
|
|
/// Behavior of Iterator
|
|
const cat_proxy& operator*() const;
|
|
|
|
/// Behavior of Iterator
|
|
cat_proxy* operator->();
|
|
|
|
/// Behavior of Iterator
|
|
const cat_proxy* operator->() const;
|
|
|
|
/// Behavior of Iterator
|
|
bool operator==(const cat_proxy&) const;
|
|
|
|
/// Behavior of Iterator
|
|
bool operator!=(const cat_proxy&) const;
|
|
|
|
void inline_factory(size_type column, pat::cloneable<pat::abstract_factory<inline_notifier_interface>> factory);
|
|
private:
|
|
void _m_append(std::vector<cell> && cells);
|
|
void _m_cat_by_pos();
|
|
void _m_update();
|
|
private:
|
|
essence_t* ess_{nullptr};
|
|
category_t* cat_{nullptr};
|
|
size_type pos_{0}; ///< Absolute position, not relative to display, and dont change during sort()
|
|
};
|
|
|
|
struct export_options
|
|
{
|
|
std::string sep = ::std::string {"\t"},
|
|
endl= ::std::string {"\n"};
|
|
bool only_selected_items{true},
|
|
only_checked_items {false},
|
|
only_visible_columns{true};
|
|
|
|
using columns_indexs = std::vector<size_type>;
|
|
columns_indexs columns_order;
|
|
};
|
|
}
|
|
}//end namespace drawerbase
|
|
|
|
struct arg_listbox
|
|
: public event_arg
|
|
{
|
|
mutable drawerbase::listbox::item_proxy item;
|
|
bool selected;
|
|
|
|
arg_listbox(const drawerbase::listbox::item_proxy&, bool selected) noexcept;
|
|
};
|
|
|
|
/// The event argument type for listbox's category_dbl_click
|
|
struct arg_category
|
|
: public event_arg
|
|
{
|
|
drawerbase::listbox::cat_proxy category;
|
|
|
|
/// Block expension/shrink of category
|
|
void block_category_change() const noexcept;
|
|
|
|
/// Determines whether expension/shrink of category is blocked
|
|
bool category_change_blocked() const noexcept;
|
|
|
|
arg_category(const drawerbase::listbox::cat_proxy&) noexcept;
|
|
private:
|
|
mutable bool block_change_;
|
|
};
|
|
|
|
namespace drawerbase
|
|
{
|
|
namespace listbox
|
|
{
|
|
struct listbox_events
|
|
: public general_events
|
|
{
|
|
basic_event<arg_listbox> checked;
|
|
basic_event<arg_listbox> selected;
|
|
|
|
/// An event that occurs when a listbox category is double clicking.
|
|
basic_event<arg_category> category_dbl_click;
|
|
};
|
|
|
|
struct scheme
|
|
: public widget_colors
|
|
{
|
|
color_proxy header_bgcolor{static_cast<color_rgb>(0xf1f2f4)};
|
|
color_proxy header_grabbed{ static_cast<color_rgb>(0x8BD6F6)};
|
|
color_proxy header_floated{ static_cast<color_rgb>(0xBABBBC)};
|
|
color_proxy item_selected{ static_cast<color_rgb>(0xD5EFFC) };
|
|
|
|
/// \todo how to implement some geometrical parameters ??
|
|
unsigned max_header_width{ 3000 }; ///< during auto width don't alow more than this
|
|
unsigned min_header_width{ 20 }; ///< non counting suspension_width
|
|
unsigned suspension_width{ 8 }; ///< def= . the trigger will set this to the width if ("...")
|
|
unsigned ext_w { 5 }; ///< def= . ??
|
|
unsigned header_height { 20 }; ///< def= . header height header_size
|
|
unsigned text_height { 14 }; ///< the trigger will set this to the height of the text font
|
|
unsigned item_height_ex { 2 }; ///< Set !=0 !!!! def=6. item_height = text_height + item_height_ex
|
|
unsigned item_height { 16 }; ///< the trigger will set this TO item_height = text_height + item_height_ex
|
|
unsigned header_mouse_spliter_area_before{ 4 }; ///< def=2
|
|
unsigned header_mouse_spliter_area_after { 4 }; ///< def=3
|
|
|
|
void debug_print(const std::string &msg);
|
|
|
|
};
|
|
}
|
|
}//end namespace drawerbase
|
|
|
|
/*! \class listbox
|
|
\brief A rectangle containing a list of strings from which the user can select.
|
|
This widget contain a list of \a categories, with in turn contain a list of \a items.
|
|
A \a category is a text with can be \a selected, \a checked and \a expanded to show the \a items.
|
|
An \a item is formed by \a column-fields, each corresponding to one of the \a headers.
|
|
An \a item can be \a selected and \a checked.
|
|
The user can \a drag the header to \a resize it or to \a reorganize it.
|
|
By \a clicking on one header the list get \a reordered, first up, and then down alternatively.
|
|
|
|
1. The resolver is used to resolute an object of the specified type into (or back from) a listbox item.
|
|
3. nana::listbox creates the category 0 by default.
|
|
This is an special category, becouse it is invisible, while the associated items are visible.
|
|
The optional, user-created categories begin at index 1 and are visibles.
|
|
The member functions without the categ parameter operate the items that belong to category 0.
|
|
4. A sort compare is used for sorting the items. It is a strict weak ordering comparer that must meet the requirement:
|
|
Irreflexivity (comp(x, x) returns false)
|
|
and
|
|
Antisymmetry(comp(a, b) != comp(b, a) returns true)
|
|
A simple example.
|
|
bool sort_compare( const std::string& s1, nana::any*,
|
|
const std::string& s2, nana::any*, bool reverse)
|
|
{
|
|
return (reverse ? s1 > s2 : s1 < s2);
|
|
}
|
|
listbox.set_sort_compare(0, sort_compare);
|
|
The listbox supports attaching a customer's object for each item, therefore the items can be
|
|
sorted by comparing these customer's object.
|
|
bool sort_compare( const std::string&, nana::any* o1,
|
|
const std::string&, nana::any* o2, bool reverse)
|
|
{
|
|
if(o1 && o2) //some items may not attach a customer object.
|
|
{
|
|
int * i1 = any_cast<int>(*o1);
|
|
int * i2 = any_cast<int>(*o2);
|
|
return (i1 && i2 && (reverse ? *i1 > *i2 : *i1 < *i2));
|
|
// ^ some types may not be int.
|
|
}
|
|
return false;
|
|
}
|
|
listbox.anyobj(0, 0, 10); //the type of customer's object is int.
|
|
listbox.anyobj(0, 0, 20);
|
|
5. listbox is a widget_object, with template parameters drawerbase::listbox::trigger and drawerbase::listbox::scheme
|
|
amon others.
|
|
That means that listbox have a member trigger_ constructed first and accecible with get_drawer_trigger() and
|
|
a member (unique pointer to) scheme_ accesible with scheme_type& scheme() created in the constructor
|
|
with API::dev::make_scheme<Scheme>() which call API::detail::make_scheme(::nana::detail::scheme_factory<Scheme>())
|
|
which call restrict::bedrock.make_scheme(static_cast<::nana::detail::scheme_factory_base&&>(factory));
|
|
which call pi_data_->scheme.create(std::move(factory));
|
|
which call factory.create(scheme_template(std::move(factory)));
|
|
which call (new Scheme(static_cast<Scheme&>(other)));
|
|
and which in create is setted with: API::dev::set_scheme(handle_, scheme_.get()); which save the scheme pointer in
|
|
the nana::detail::basic_window member pointer scheme
|
|
\todo doc: actualize this example listbox.at(0)...
|
|
\see nana::drawerbase::listbox::cat_proxy
|
|
\see nana::drawerbase::listbox::item_proxy
|
|
\example listbox_Resolver.cpp
|
|
*/
|
|
class listbox
|
|
: public widget_object<category::widget_tag, drawerbase::listbox::trigger, drawerbase::listbox::listbox_events, drawerbase::listbox::scheme>,
|
|
public concepts::any_objective<drawerbase::listbox::size_type, 2>
|
|
{
|
|
public:
|
|
using size_type = drawerbase::listbox::size_type;
|
|
using index_pair = drawerbase::listbox::index_pair;
|
|
using cat_proxy = drawerbase::listbox::cat_proxy;
|
|
using item_proxy = drawerbase::listbox::item_proxy;
|
|
using selection = drawerbase::listbox::selection; ///<A container type for items.
|
|
using iresolver = drawerbase::listbox::iresolver;
|
|
using oresolver = drawerbase::listbox::oresolver;
|
|
using cell = drawerbase::listbox::cell;
|
|
using export_options= drawerbase::listbox::export_options;
|
|
using columns_indexs= drawerbase::listbox::size_type;
|
|
using inline_notifier_interface = drawerbase::listbox::inline_notifier_interface;
|
|
public:
|
|
listbox() = default;
|
|
listbox(window, bool visible);
|
|
listbox(window, const rectangle& = {}, bool visible = true);
|
|
|
|
void auto_draw(bool); ///< Set state: Redraw automatically after an operation
|
|
|
|
/// Scrolls the view to the first or last item of a specified category
|
|
void scroll(bool to_bottom, size_type cat_pos = ::nana::npos);
|
|
void scroll(bool to_bottom, const index_pair& pos);
|
|
|
|
/// Appends a new column with a header text and the specified width at the end, and return it position
|
|
size_type append_header(std::string text_utf8, unsigned width = 120);
|
|
size_type append_header(std::wstring text, unsigned width = 120);
|
|
listbox& header_width(size_type position, unsigned pixels);
|
|
unsigned header_width(size_type position) const;
|
|
unsigned auto_width(size_type position, unsigned max=3000);
|
|
|
|
|
|
cat_proxy append(std::string); ///< Appends a new category to the end
|
|
cat_proxy append(std::wstring); ///< Appends a new category to the end
|
|
void append(std::initializer_list<std::string>); ///< Appends categories to the end
|
|
void append(std::initializer_list<std::wstring>); ///< Appends categories to the end
|
|
|
|
cat_proxy insert(cat_proxy, ::std::string);
|
|
cat_proxy insert(cat_proxy, ::std::wstring);
|
|
cat_proxy at(size_type pos) const;
|
|
|
|
/// add categories in order when use a key?
|
|
listbox& ordered_categories(bool);
|
|
|
|
/// return a proxy to tha cat with the key or create a new one in the right order
|
|
template<typename Key>
|
|
cat_proxy operator[](const Key & ck)
|
|
{
|
|
using catkey = typename ::nana::detail::type_escape<Key>::type;
|
|
std::shared_ptr<nana::detail::key_interface> p(new nana::key<catkey, std::less<catkey>>(ck), [](nana::detail::key_interface* p)
|
|
{
|
|
delete p;
|
|
});
|
|
|
|
return cat_proxy(&_m_ess(), _m_at_key(p));
|
|
}
|
|
|
|
template<typename Key>
|
|
cat_proxy operator[](Key && ck)
|
|
{
|
|
using catkey = typename ::nana::detail::type_escape<Key>::type;
|
|
std::shared_ptr<nana::detail::key_interface> p(new nana::key<catkey, std::less<catkey>>(std::move(ck)), [](nana::detail::key_interface* p)
|
|
{
|
|
delete p;
|
|
});
|
|
|
|
return cat_proxy(&_m_ess(), _m_at_key(p));
|
|
}
|
|
|
|
/// Returns an item by the specified absolute position
|
|
item_proxy at(const index_pair &abs_pos) const;
|
|
|
|
/// Returns an index of item which contains the specified point.
|
|
index_pair at(const point & pos) const;
|
|
|
|
/// Returns the column which contains the specified point.
|
|
columns_indexs column_from_pos(const point & pos);
|
|
|
|
|
|
void insert(const index_pair&, ::std::string); ///<Insert a new item with a text in the first column.
|
|
void insert(const index_pair&, ::std::wstring); ///<Insert a new item with a text in the first column.
|
|
|
|
void checkable(bool);
|
|
selection checked() const; ///<Returns the items which are checked.
|
|
|
|
void clear(size_type cat); ///<Removes all the items from the specified category
|
|
void clear(); ///<Removes all the items from all categories
|
|
void erase(size_type cat); ///<Erases a category
|
|
void erase(); ///<Erases all categories.
|
|
item_proxy erase(item_proxy);
|
|
|
|
template<typename Key>
|
|
void erase_key(const Key& kv)
|
|
{
|
|
typedef typename nana::detail::type_escape<Key>::type key_t;
|
|
nana::key<key_t, std::less<key_t> > key(kv);
|
|
_m_erase_key(&key);
|
|
}
|
|
|
|
template<typename Key>
|
|
void erase_key(Key&& kv)
|
|
{
|
|
typedef typename nana::detail::type_escape<Key>::type key_t;
|
|
nana::key<key_t, std::less<key_t> > key(std::move(kv));
|
|
_m_erase_key(&key);
|
|
}
|
|
|
|
bool sortable() const;
|
|
void sortable(bool enable);
|
|
|
|
///Sets a strict weak ordering comparer for a column
|
|
void set_sort_compare(size_type col, std::function<bool(const std::string&, nana::any*,
|
|
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
|
|
|
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
|
void sort_col(size_type col, bool reverse = false);
|
|
size_type sort_col() const;
|
|
|
|
/// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
|
void unsort();
|
|
bool freeze_sort(bool freeze);
|
|
|
|
selection selected() const; ///<Get the absolute indexs of all the selected items
|
|
|
|
void show_header(bool);
|
|
bool visible_header() const;
|
|
void move_select(bool upwards); ///<Selects an item besides the current selected item in the display.
|
|
|
|
size_type size_categ() const; ///<Get the number of categories
|
|
size_type size_item() const; ///<The number of items in the default category
|
|
size_type size_item(size_type cat) const; ///<The number of items in category "cat"
|
|
|
|
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;
|
|
drawerbase::listbox::category_t* _m_at_key(std::shared_ptr<nana::detail::key_interface>);
|
|
void _m_erase_key(nana::detail::key_interface*);
|
|
};
|
|
}//end namespace nana
|
|
#endif
|