diff --git a/include/nana/gui/widgets/checkbox.hpp b/include/nana/gui/widgets/checkbox.hpp index 57239d20..1a75c91a 100644 --- a/include/nana/gui/widgets/checkbox.hpp +++ b/include/nana/gui/widgets/checkbox.hpp @@ -104,6 +104,7 @@ namespace drawerbase struct element_tag { checkbox * uiobj; + event_handle eh_clicked; event_handle eh_checked; event_handle eh_destroy; event_handle eh_keyboard; diff --git a/include/nana/gui/widgets/group.hpp b/include/nana/gui/widgets/group.hpp index c453c168..24c7676a 100644 --- a/include/nana/gui/widgets/group.hpp +++ b/include/nana/gui/widgets/group.hpp @@ -42,6 +42,13 @@ namespace nana{ using field_reference = place::field_reference; constexpr static const std::size_t npos = static_cast(-1); + enum class background_mode + { + none, + transparent, + blending + }; + /// The default construction group(); @@ -66,7 +73,8 @@ namespace nana{ checkbox& add_option(::std::string); /// Modifies the alignment of the title - void caption_align(align position); + group& caption_align(align position); + group& caption_background_mode(background_mode mode); /// Enables/disables the radio mode which is single selection group& radio_mode(bool); diff --git a/source/gui/element.cpp b/source/gui/element.cpp index a67a7341..ea3b94a2 100644 --- a/source/gui/element.cpp +++ b/source/gui/element.cpp @@ -163,7 +163,8 @@ namespace nana bld_fgcolor = fgcolor.blend(highlighted, 0.6); break; case element_state::disabled: - bld_bgcolor = bld_fgcolor = static_cast(0xb2b7bc); + bld_bgcolor = static_cast(0xE0E0E0); + bld_fgcolor = static_cast(0x999A9E); break; default: //Leave things as they are diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index c458a4ac..3148ee88 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -85,9 +85,13 @@ namespace nana{ namespace drawerbase graph.text_metrics(txt_px, descent, ileading); txt_px += (descent + 2); + auto e_state = API::element_state(*wdg); + if(!wdg->enabled()) + e_state = element_state::disabled; + impl_->crook.draw(graph, impl_->scheme_ptr->square_bgcolor.get(wdg->bgcolor()), impl_->scheme_ptr->square_border_color.get(wdg->fgcolor()), - rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg)); + rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), e_state); } void drawer::mouse_down(graph_reference graph, const arg_mouse&) @@ -212,6 +216,7 @@ namespace nana{ namespace drawerbase { e.uiobj->radio(false); e.uiobj->react(true); + API::umake_event(e.eh_clicked); API::umake_event(e.eh_checked); API::umake_event(e.eh_destroy); API::umake_event(e.eh_keyboard); @@ -228,7 +233,7 @@ namespace nana{ namespace drawerbase el.uiobj = &uiobj; - uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg) + el.eh_checked = uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg) { if (arg.widget->checked()) { @@ -240,7 +245,7 @@ namespace nana{ namespace drawerbase } }, true); - el.eh_checked = uiobj.events().click.connect_unignorable([this](const arg_click& arg) + el.eh_clicked = uiobj.events().click.connect_unignorable([this](const arg_click& arg) { for (auto & i : ui_container_) i.uiobj->check(arg.window_handle == i.uiobj->handle()); diff --git a/source/gui/widgets/group.cpp b/source/gui/widgets/group.cpp index 1f3d24dd..f1ca7821 100644 --- a/source/gui/widgets/group.cpp +++ b/source/gui/widgets/group.cpp @@ -33,13 +33,14 @@ namespace nana static const char* field_title = "__nana_group_title__"; static const char* field_options = "__nana_group_options__"; -struct group::implement -{ - label caption; - align caption_align{ align::left }; - place place_content; - unsigned gap{2}; - std::string usr_div_str; + struct group::implement + { + label caption; + align caption_align{ align::left }; + background_mode caption_mode{ background_mode::blending }; + place place_content; + unsigned gap{2}; + std::string usr_div_str; nana::size caption_dimension; @@ -143,200 +144,216 @@ checkbox& group::add_option(std::string text) impl_->options.emplace_back(new checkbox(handle())); auto & opt = impl_->options.back(); #endif - 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(); - if (impl_->radio_logic) - impl_->radio_logic->add(*opt); + 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(); - return *impl_->options.back(); -} + if (impl_->radio_logic) + impl_->radio_logic->add(*opt); -void group::caption_align(align position) -{ - if (position != impl_->caption_align) - { - impl_->caption_align = position; - impl_->update_div(); - impl_->place_content.collocate(); - API::refresh_window(*this); - } -} + return *impl_->options.back(); + } -group& group::radio_mode(bool enable) -{ - _THROW_IF_EMPTY() + group& group::caption_align(align position) + { + if (position != impl_->caption_align) + { + impl_->caption_align = position; + impl_->update_div(); + impl_->place_content.collocate(); + API::refresh_window(*this); + } + return *this; + } - if (enable) - { - //Create radio_group if it is null - if (!impl_->radio_logic) - impl_->radio_logic = new ::nana::radio_group; + group& group::caption_background_mode(background_mode mode) + { + if (mode != impl_->caption_mode) + { + impl_->caption_mode = mode; + switch (mode) + { + case background_mode::none: + impl_->caption.bgcolor(this->bgcolor()); + impl_->caption.transparent(false); + break; + case background_mode::blending: + impl_->caption.transparent(true); + impl_->caption.bgcolor(API::bgcolor(this->parent()).blend(colors::black, 0.025)); + break; + case background_mode::transparent: + impl_->caption.transparent(true); + impl_->caption.bgcolor(API::bgcolor(this->parent()).blend(colors::black, 0.025)); + break; + } + API::refresh_window(*this); + } + return *this; + } - //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; - } - return *this; -} + group& group::radio_mode(bool enable) + { + _THROW_IF_EMPTY() -std::size_t group::option() const -{ - _THROW_IF_EMPTY(); + if (enable) + { + //Create radio_group if it is null + if (!impl_->radio_logic) + impl_->radio_logic = new ::nana::radio_group; - if (impl_->radio_logic) - return impl_->radio_logic->checked(); + //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; + } + return *this; + } - throw std::logic_error("the radio_mode of the group is disabled"); -} + std::size_t group::option() const + { + _THROW_IF_EMPTY(); -bool group::option_checked(std::size_t pos) const -{ - _THROW_IF_EMPTY(); - return impl_->options.at(pos)->checked(); -} + if (impl_->radio_logic) + return impl_->radio_logic->checked(); -void group::typeface( const nana::paint::font& font ) -{ - // change typeface of caption label - impl_->caption.typeface( font ); + throw std::logic_error("the radio_mode of the group is disabled"); + } - /* change size of caption label + bool group::option_checked(std::size_t pos) const + { + _THROW_IF_EMPTY(); + return impl_->options.at(pos)->checked(); + } - The caption may be changed AFTER this call - so the neccessary label size is unknown - set it to 80% of the current widget width and 50 pixels - */ - impl_->caption.move( rectangle(0,0,size().width * 0.8,50)); -} + group& group::enable_format_caption(bool format) + { + impl_->caption.format(format); + return *this; + } -group& group::enable_format_caption(bool format) -{ - impl_->caption.format(format); - return *this; -} + group& group::collocate() noexcept + { + impl_->place_content.collocate(); + return *this; + } -group& group::collocate() noexcept -{ - impl_->place_content.collocate(); - return *this; -} + group& group::div(const char* div_str) noexcept + { + if (div_str) + impl_->usr_div_str = div_str; + else + impl_->usr_div_str.clear(); -group& group::div(const char* div_str) noexcept -{ - if (div_str) - impl_->usr_div_str = div_str; - else - impl_->usr_div_str.clear(); + impl_->update_div(); + return *this; + } - impl_->update_div(); - return *this; -} + group::field_reference group::operator[](const char* field) + { + return impl_->place_content.field(field); + } -group::field_reference group::operator[](const char* field) -{ - return impl_->place_content.field(field); -} + void group::field_display(const char* field_name, bool display) + { + impl_->place_content.field_display(field_name, display); + } -void group::field_display(const char* field_name, bool display) -{ - impl_->place_content.field_display(field_name, display); -} + bool group::field_display(const char* field_name) const + { + return impl_->place_content.field_display(field_name); + } -bool group::field_display(const char* field_name) const -{ - return impl_->place_content.field_display(field_name); -} + void group::erase(window handle) + { + impl_->place_content.erase(handle); + } -void group::erase(window handle) -{ - impl_->place_content.erase(handle); -} + void group::_m_add_child(const char* field, widget* wdg) + { + impl_->place_content[field] << wdg->handle(); + } -void group::_m_add_child(const char* field, widget* wdg) -{ - impl_->place_content[field] << wdg->handle(); -} + void group::_m_init() + { + this->div(nullptr); -void group::_m_init() -{ - this->div(nullptr); + auto & outter = impl_->place_content; - auto & outter = impl_->place_content; + outter[field_title] << impl_->caption; + outter.collocate(); - outter[field_title] << impl_->caption; - outter.collocate(); + impl_->caption.transparent(true); + color pbg = API::bgcolor(this->parent()); + impl_->caption.bgcolor(pbg.blend(colors::black, 0.025)); - impl_->caption.transparent(true); - color pbg = API::bgcolor(this->parent()); - impl_->caption.bgcolor(pbg.blend(colors::black, 0.025)); + this->bgcolor(pbg.blend(colors::black, 0.05)); - this->bgcolor(pbg.blend(colors::black, 0.05)); + drawing dw(*this); - drawing dw(*this); + //When the group is resized, the drawing is called before moving the caption, but + //the drawing of group requires the lastest position of caption for gradual rectangle. + //For the requirement, a move event handler is required for listning the change of caption's position. + impl_->caption.events().move([this](const arg_move&){ + if (align::left != impl_->caption_align) + API::refresh_window(*this); + }); - //When the group is resized, the drawing is called before moving the caption, but - //the drawing of group requires the lastest position of caption for gradual rectangle. - //For the requirement, a move event handler is required for listning the change of caption's position. - impl_->caption.events().move([this](const arg_move&) - { - if (align::left != impl_->caption_align) - API::refresh_window(*this); - }); + // This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !! + dw.draw([this](paint::graphics& graph) + { + auto gap_px = impl_->gap - 1; - // This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !! - dw.draw([this](paint::graphics& graph) - { - auto gap_px = impl_->gap - 1; + auto const top_round_line = static_cast(impl_->caption_dimension.height) / 2; - auto const top_round_line = static_cast(impl_->caption_dimension.height) / 2; + graph.rectangle(true, API::bgcolor(this->parent())); + graph.round_rectangle(rectangle(point(gap_px, top_round_line), + nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px) + ), + 3, 3, this->scheme().border, true, this->bgcolor()); - graph.rectangle(true, API::bgcolor(this->parent())); - graph.round_rectangle(rectangle(point(gap_px, top_round_line), - nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px) - ), - 3, 3, this->scheme().border, true, this->bgcolor()); + if (background_mode::blending == impl_->caption_mode) + { + auto opt_r = API::window_rectangle(impl_->caption); + if (opt_r) + { + rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width + 4, static_cast(top_round_line - opt_r->y) } }; - auto opt_r = API::window_rectangle(impl_->caption); - if (opt_r) - { - rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width + 4, static_cast(top_round_line - opt_r->y) } }; + grad_r.y += top_round_line * 2 / 3; + grad_r.x -= 2; - grad_r.y += top_round_line*2 / 3; - grad_r.x -= 2; + graph.gradual_rectangle(grad_r, + API::bgcolor(this->parent()), this->bgcolor(), true + ); + } + } + }); + } - graph.gradual_rectangle(grad_r, - API::bgcolor(this->parent()), this->bgcolor(), true - ); - } - }); -} + void group::_m_complete_creation() + { + widget::_m_complete_creation(); + impl_->create(handle()); + _m_init(); + } -void group::_m_complete_creation() -{ - widget::_m_complete_creation(); - impl_->create(handle()); - _m_init(); -} + auto group::_m_caption() const noexcept -> native_string_type + { + return impl_->caption.caption_native(); + } -auto group::_m_caption() const noexcept -> native_string_type -{ - return impl_->caption.caption_native(); -} + void group::_m_caption(native_string_type&& str) + { + impl_->caption.caption(std::move(str)); + impl_->update_div(); + impl_->place_content.collocate(); + } -void group::_m_caption(native_string_type&& str) -{ - impl_->caption.caption(std::move(str)); - impl_->update_div(); - impl_->place_content.collocate(); -} }//end namespace nana diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 304ed929..f53a5837 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1,7 +1,7 @@ /* * A text editor implementation * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -1728,7 +1728,7 @@ namespace nana { str = impl_->textbase.getline(0); for (std::size_t i = 1; i < lines; ++i) { - str += L"\n\r"; + str += L"\r\n"; str += impl_->textbase.getline(i); } } @@ -2002,7 +2002,7 @@ namespace nana { auto fgcolor = scheme_->foreground.get_color(); if (!API::window_enabled(window_)) - fgcolor.blend(bgcolor, 0.5); + fgcolor = fgcolor.blend(bgcolor, 0.5); //Thank to besh81 for getting the fgcolor to be changed if (API::widget_borderless(window_)) graph_.rectangle(false, bgcolor); diff --git a/source/paint/detail/image_process_provider.cpp b/source/paint/detail/image_process_provider.cpp index 414d68dc..89324e04 100644 --- a/source/paint/detail/image_process_provider.cpp +++ b/source/paint/detail/image_process_provider.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include "image_processor.hpp" namespace nana { diff --git a/include/nana/paint/detail/image_processor.hpp b/source/paint/detail/image_processor.hpp similarity index 98% rename from include/nana/paint/detail/image_processor.hpp rename to source/paint/detail/image_processor.hpp index 1a412a2e..5e7e3548 100644 --- a/include/nana/paint/detail/image_processor.hpp +++ b/source/paint/detail/image_processor.hpp @@ -1,7 +1,7 @@ /* * Image Processor Algorithm Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -15,8 +15,8 @@ #ifndef NANA_PAINT_DETAIL_IMAGE_PROCESSOR_HPP #define NANA_PAINT_DETAIL_IMAGE_PROCESSOR_HPP -#include "../image_process_interface.hpp" #include +#include #include #include @@ -421,15 +421,19 @@ namespace detail { virtual void process(paint::pixel_buffer & pixbuf, const nana::point& pos_beg, const nana::point& pos_end, const ::nana::color& clr, double fade_rate) const { + //Return if it is completely transparent + if (fade_rate <= 0) + return; + auto rgb_color = clr.px_color().value; const std::size_t bytes_pl = pixbuf.bytes_per_line(); unsigned char * fade_table = nullptr; std::unique_ptr autoptr; nana::pixel_argb_t rgb_imd = {}; - if(fade_rate != 0.0) + if(fade_rate < 1) { - autoptr = detail::alloc_fade_table(1 - fade_rate); + autoptr = detail::alloc_fade_table(1.0 - fade_rate); fade_table = autoptr.get(); rgb_imd.value = rgb_color; rgb_imd = detail::fade_color_intermedia(rgb_imd, fade_table);