From 51f9e879792c71ffeeb2a336fcf34c9e32e48f3b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 25 Jul 2015 20:26:44 +0800 Subject: [PATCH] add checkbox function for group --- include/nana/gui/widgets/group.hpp | 25 +++++-- source/gui/widgets/checkbox.cpp | 10 ++- source/gui/widgets/group.cpp | 113 ++++++++++++++++++++++++----- 3 files changed, 119 insertions(+), 29 deletions(-) diff --git a/include/nana/gui/widgets/group.hpp b/include/nana/gui/widgets/group.hpp index aa2b6a96..b5022253 100644 --- a/include/nana/gui/widgets/group.hpp +++ b/include/nana/gui/widgets/group.hpp @@ -36,18 +36,30 @@ namespace nana{ /// The construction that creates the widget and set the titel or caption - group(window parent, ///< - ::nana::string titel, ///< - bool format = false, ///< Use a formated label? - unsigned gap = 2, ///< betwen the content and the external limit - rectangle r = {} , ///< - bool visible = true + group(window parent, ///< a handle to the parent + ::nana::string titel, ///< caption of the group + bool formatted = false, ///< Enable/disable the formatted text for the title + unsigned gap = 2, ///< betwen the content and the external limit + const rectangle& r = {} , + bool visible = true ); /// The destruction ~group(); + /// Adds an option for user selection + void add_option(::nana::string); + + /// Enables/disables the radio mode which is single selection + void radio_mode(bool); + + /// Returns the index of option in radio_mode, it throws a logic_error if radio_mode is false. + std::size_t option() const; + + /// Determines a specified option is checked, it throws an out_of_range if !(pos < number of options) + bool option_checked(std::size_t pos) const; + group& enable_format_caption(bool format); @@ -56,7 +68,6 @@ namespace nana{ void collocate(); void div(const char* div_str); field_reference operator[](const char* field); - template Widget* create_child(const char* field, Args && ... args) diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index a5f3720b..b0d89b74 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -185,6 +185,7 @@ namespace checkbox void checkbox::radio(bool is_radio) { get_drawer_trigger().impl()->crook.radio(is_radio); + API::refresh_window(handle()); } void checkbox::transparent(bool enabled) @@ -193,6 +194,7 @@ namespace checkbox API::effects_bground(*this, effects::bground_transparent(0), 0.0); else API::effects_bground_remove(*this); + API::refresh_window(handle()); } bool checkbox::transparent() const @@ -204,10 +206,12 @@ namespace checkbox //class radio_group radio_group::~radio_group() { - for(auto & i : ui_container_) + for(auto & e : ui_container_) { - API::umake_event(i.eh_checked); - API::umake_event(i.eh_destroy); + e.uiobj->radio(false); + e.uiobj->react(true); + API::umake_event(e.eh_checked); + API::umake_event(e.eh_destroy); } } diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index a97848d8..1a12b35c 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -18,18 +18,29 @@ #include #include #include +#include + +#define _THROW_IF_EMPTY()\ + if(empty()) \ + throw std::logic_error("the group is invalid"); namespace nana{ + static const char* field_title = "__nana_group_title__"; + static const char* field_options = "__nana_group_options__"; + struct group::implement { label caption; place place_content; - unsigned gap{2}; + std::string usr_div_str; + std::vector> options; + radio_group * radio_logic{nullptr}; implement() = default; + implement(window grp_panel, ::nana::string titel, bool vsb, unsigned gap=2) : caption (grp_panel, std::move(titel), vsb), place_content{grp_panel}, @@ -43,6 +54,26 @@ namespace nana{ caption.caption(STR("")); place_content.bind(pnl); } + + void update_div() + { + ::nana::size sz = caption.measure(1000); + + std::stringstream ss; + ss << "vert margin=[0," << gap << "," << gap + 5 << "," << gap << "]" + << " <" << field_title << " weight=" << sz.width + 1 << "> >" + << "<"; + + if (!usr_div_str.empty()) + ss << "<" << usr_div_str << ">>"; + else + ss << ">"; + + place_content.div(ss.str().c_str()); + + if (options.empty()) + place_content.field_display(field_options, false); + } }; group::group() @@ -56,23 +87,68 @@ namespace nana{ create(parent, r, vsb); } - group::group( window parent, ///< - ::nana::string titel /*={}*/, ///< - bool format /*=false*/, ///< - unsigned gap /*=2*/, ///< - rectangle r /*={} */, ///< - bool vsb /*= true */ ///< - ) + group::group(window parent, ::nana::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb) : panel(parent, r, vsb), impl_(new implement(*this, std::move(titel), vsb, gap)) { - impl_->caption.format(format); + impl_->caption.format(formatted); _m_init(); } - group::~group() { + delete impl_->radio_logic; + } + + void group::add_option(::nana::string text) + { + _THROW_IF_EMPTY() + + impl_->options.emplace_back(new checkbox(handle())); + auto & opt = impl_->options.back(); + opt->transparent(true); + opt->caption(std::move(text)); + impl_->place_content[field_options] << *opt; + impl_->place_content.field_display(field_options, true); + impl_->place_content.collocate(); + + } + + void group::radio_mode(bool enable) + { + _THROW_IF_EMPTY() + + if (enable) + { + //Create radio_group if it is null + if (!impl_->radio_logic) + impl_->radio_logic = new ::nana::radio_group; + + //add all options into the radio_group + for (auto & opt : impl_->options) + impl_->radio_logic->add(*opt); + } + else + { + delete impl_->radio_logic; + impl_->radio_logic = nullptr; + } + } + + std::size_t group::option() const + { + _THROW_IF_EMPTY(); + + if (impl_->radio_logic) + return impl_->radio_logic->checked(); + + throw std::logic_error("the radio_mode of the group is disabled"); + } + + bool group::option_checked(std::size_t pos) const + { + _THROW_IF_EMPTY(); + return impl_->options.at(pos)->checked(); } group& group::enable_format_caption(bool format) @@ -86,7 +162,6 @@ namespace nana{ return impl_->place_content; } - void group::collocate() { impl_->place_content.collocate(); @@ -96,13 +171,12 @@ namespace nana{ { ::nana::size sz = impl_->caption.measure(1000); - std::stringstream ss; - ss << "vert margin=[0," << impl_->gap << "," << impl_->gap << "," << impl_->gap << "]" - << " >" - << " <"<<(div_str ? div_str : "")<<">"; - - impl_->place_content.div(ss.str().c_str()); + if (div_str) + impl_->usr_div_str = div_str; + else + impl_->usr_div_str.clear(); + impl_->update_div(); } group::field_reference group::operator[](const char* field) @@ -121,7 +195,7 @@ namespace nana{ auto & outter = impl_->place_content; - outter["nanaGroupTitle2015"] << impl_->caption; + outter[field_title] << impl_->caption; outter.collocate(); color pbg = API::bgcolor(this->parent()); @@ -164,7 +238,8 @@ namespace nana{ void group::_m_caption(::nana::string&& str) { - return impl_->caption.caption(std::move(str)); + impl_->caption.caption(std::move(str)); + impl_->update_div(); } }//end namespace nana