toolbar : added toggle button

Following functions/methods have been add both to toolbar and item_proxy:
bool istoggle() const; ///< Returns true if the tool style is toggle.
				bool toggle() const; ///< Gets the tool toggle state (only if tool style is toggle).
				item_proxy& toggle(bool toggle_state); ///< Sets the tool toggle state (only if tool style is toggle).
				std::string toggle_group() const;	///< Returns the toggle group associated with the tool (only if tool style is toggle).
				item_proxy& toggle_group(const ::std::string& group);	///< Adds the tool to a toggle group (only if tool style is toggle).
This commit is contained in:
besh81 2019-05-08 18:11:21 +02:00
parent 36556b44f5
commit 5422c43002
2 changed files with 231 additions and 33 deletions

View File

@ -33,12 +33,49 @@ namespace nana
{
namespace toolbar
{
struct item_proxy
enum class tool_type
{
nana::toolbar& widget;
std::size_t button;
button,
toggle
};
void enable(bool enable_state);
class item_proxy
{
public:
item_proxy(::nana::toolbar*, std::size_t pos);
bool enable() const;
item_proxy& enable(bool enable_state);
item_proxy& tooltype(tool_type type); ///< Sets the tool style.
bool istoggle() const; ///< Returns true if the tool style is toggle.
bool toggle() const; ///< Gets the tool toggle state (only if tool style is toggle).
item_proxy& toggle(bool toggle_state); ///< Sets the tool toggle state (only if tool style is toggle).
std::string toggle_group() const; ///< Returns the toggle group associated with the tool (only if tool style is toggle).
item_proxy& toggle_group(const ::std::string& group); ///< Adds the tool to a toggle group (only if tool style is toggle).
private:
nana::toolbar* const tb_;
std::size_t const pos_;
};
struct item_type
{
std::string text;
nana::paint::image image;
unsigned pixels{ 0 };
unsigned position{ 0 }; // last item position.
nana::size textsize;
bool enable{ true };
tool_type type{ tool_type::button };
bool toggle{ false };
std::string group;
item_type(const std::string& text, const nana::paint::image& img, tool_type type)
:text(text), image(img), type(type)
{}
};
struct toolbar_events
@ -49,7 +86,6 @@ namespace nana
basic_event<arg_toolbar> leave; ///< The mouse leaves a control button.
};
struct item_type;
class item_container;
class drawer
@ -90,6 +126,7 @@ namespace nana
{
public:
using size_type = std::size_t; ///< A type to count the number of elements.
using tool_type = drawerbase::toolbar::tool_type;
toolbar() = default;
toolbar(window, bool visible, bool detached=false);
@ -102,6 +139,15 @@ namespace nana
bool enable(size_type index) const;
void enable(size_type index, bool enable_state);
void tooltype(size_type index, tool_type type); ///< Sets the tool style.
bool istoggle(size_type index) const; ///< Returns true if the tool style is toggle.
bool toggle(size_type index) const; ///< Gets the tool toggle state (only if tool style is toggle).
void toggle(size_type index, bool toggle_state); ///< Sets the tool toggle state (only if tool style is toggle).
std::string toggle_group(size_type index) const; ///< Returns the toggle group associated with the tool (only if tool style is toggle).
void toggle_group(size_type index, const ::std::string& group); ///< Adds the tool to a toggle group (only if tool style is toggle).
void scale(unsigned s); ///< Sets the scale of control button.
/// Enable to place buttons at right part. After calling it, every new button is right aligned.

View File

@ -27,26 +27,6 @@ namespace nana
{
namespace toolbar
{
struct item_type
{
enum kind{ button, container};
typedef std::size_t size_type;
std::string text;
nana::paint::image image;
unsigned pixels{0};
unsigned position{ 0 }; // last item position.
nana::size textsize;
bool enable{true};
kind type;
item_type(const std::string& text, const nana::paint::image& img, kind type)
:text(text), image(img), type(type)
{}
};
class item_container
{
public:
@ -58,7 +38,7 @@ namespace nana
clear();
}
void insert(size_type pos, std::string text, const nana::paint::image& img, item_type::kind type)
void insert(size_type pos, std::string text, const nana::paint::image& img, tool_type type)
{
item_type* m = new item_type(std::move(text), img, type);
@ -70,12 +50,12 @@ namespace nana
void push_back(const std::string& text, const nana::paint::image& img)
{
insert(cont_.size(), text, img, item_type::kind::button);
insert(cont_.size(), text, img, tool_type::button);
}
void push_back(const std::string& text)
{
insert(cont_.size(), text, nana::paint::image(), item_type::kind::button);
insert(cont_.size(), text, nana::paint::image(), tool_type::button);
}
//Contributed by kmribti(pr#105)
@ -126,6 +106,45 @@ namespace nana
cont_.clear();
}
void update_toggle_group(item_type* item, bool toggle_state, bool clicked = true)
{
if(!item)
return;
if(item->group.empty())
{
item->toggle = toggle_state;
return;
}
// group rules:
// 1. inside a group only one item at the time is selected
// 2. inside a group one item must always be selected
// 3. a group with only one item IS NOT a group
bool is_group = false;
// look for other items inside the group
for(auto i : cont_)
{
if(i == item)
continue;
if(i && i->group == item->group)
{
if(toggle_state == false && clicked == false) // needs to avoid to break rule no. 2
return;
is_group = true;
i->toggle = false;
}
}
item->toggle = is_group ? true : toggle_state;
}
private:
container_type cont_;
size_t right_{ npos };
@ -152,6 +171,13 @@ namespace nana
if (state_t::highlighted == state || state_t::selected == state)
graph.gradual_rectangle(background_r.pare_off(1), bgcolor, static_cast<color_rgb>(state_t::selected == state ? 0x99CCFF : 0xC0DDFC), true);
}
else if (item.type == tool_type::toggle && item.toggle)
{
nana::rectangle background_r(x, y, width, height);
graph.rectangle(background_r, false, static_cast<color_rgb>(item.enable ? 0x3399FF : 0x999999));
graph.gradual_rectangle(background_r.pare_off(1), bgcolor, static_cast<color_rgb>(item.enable ? 0xC0DDFC : 0x969696), true);
}
if(!item.image.empty())
{
@ -378,6 +404,10 @@ namespace nana
size_type which = _m_which(arg.pos, false);
if(impl_->which == which)
{
// update toggle state
auto m = impl_->items.at(impl_->which);
impl_->items.update_toggle_group(m, !m->toggle);
::nana::arg_toolbar arg{ *widget_, which };
widget_->events().selected.emit(arg, widget_->handle());
@ -429,9 +459,52 @@ namespace nana
//class drawer
// Item Proxy
void item_proxy::enable(bool enable_state)
item_proxy::item_proxy(::nana::toolbar* t, std::size_t pos)
: tb_{ t }, pos_{ pos }
{}
bool item_proxy::enable() const
{
widget.enable(button, enable_state);
return tb_->enable(pos_);
}
item_proxy& item_proxy::enable(bool enable_state)
{
tb_->enable(pos_, enable_state);
return *this;
}
item_proxy& item_proxy::tooltype(tool_type type)
{
tb_->tooltype(pos_, type);
return *this;
}
bool item_proxy::istoggle() const
{
return tb_->istoggle(pos_);
}
bool item_proxy::toggle() const
{
return tb_->toggle(pos_);
}
item_proxy& item_proxy::toggle(bool toggle_state)
{
tb_->toggle(pos_, toggle_state);
return *this;
}
std::string item_proxy::toggle_group() const
{
return tb_->toggle_group(pos_);
}
item_proxy& item_proxy::toggle_group(const ::std::string& group)
{
tb_->toggle_group(pos_, group);
return *this;
}
}//end namespace toolbar
}//end namespace drawerbase
@ -465,14 +538,14 @@ namespace nana
{
get_drawer_trigger().items().push_back(text, img);
API::refresh_window(handle());
return {*this, get_drawer_trigger().items().size() - 1u};
return {this, get_drawer_trigger().items().size() - 1u};
}
drawerbase::toolbar::item_proxy toolbar::append(const std::string& text)
{
get_drawer_trigger().items().push_back(text, {});
API::refresh_window(this->handle());
return {*this, get_drawer_trigger().items().size() - 1u};
return {this, get_drawer_trigger().items().size() - 1u};
}
void toolbar::clear()
@ -507,6 +580,85 @@ namespace nana
}
}
void toolbar::tooltype(size_type index, tool_type type)
{
auto & items = get_drawer_trigger().items();
if(items.size() > index)
{
auto m = items.at(index);
if(m && m->type != type)
{
m->type = type;
API::refresh_window(this->handle());
}
}
}
bool toolbar::istoggle(size_type index) const
{
auto & items = get_drawer_trigger().items();
if(items.size() <= index)
return false;
auto m = items.at(index);
return (m && m->type == tool_type::toggle);
}
bool toolbar::toggle(size_type index) const
{
auto & items = get_drawer_trigger().items();
if(items.size() <= index)
return false;
auto m = items.at(index);
return (m && m->toggle);
}
void toolbar::toggle(size_type index, bool toggle_state)
{
auto & items = get_drawer_trigger().items();
if(items.size() > index)
{
auto m = items.at(index);
if(m)
{
items.update_toggle_group(m, toggle_state, false);
API::refresh_window(this->handle());
}
}
}
std::string toolbar::toggle_group(size_type index) const
{
auto & items = get_drawer_trigger().items();
if(items.size() <= index)
return "";
auto m = items.at(index);
return m ? m->group : "";
}
void toolbar::toggle_group(size_type index, const ::std::string& group)
{
auto & items = get_drawer_trigger().items();
if(items.size() > index)
{
auto m = items.at(index);
if(m && (m->group != group))
{
m->group = group;
API::refresh_window(this->handle()); //XXX
}
}
}
void toolbar::scale(unsigned s)
{
get_drawer_trigger().scale(s);