From 723dea218d803e7142abdb1b7a77c8e111f274c3 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 23 Feb 2015 01:43:23 +0800 Subject: [PATCH] improve nana::picture --- include/nana/gui/widgets/picture.hpp | 60 ++---- include/nana/paint/graphics.hpp | 1 + source/gui/widgets/picture.cpp | 307 ++++++++------------------- source/paint/graphics.cpp | 5 + 4 files changed, 111 insertions(+), 262 deletions(-) diff --git a/include/nana/gui/widgets/picture.hpp b/include/nana/gui/widgets/picture.hpp index 5c9b5f97..712bb167 100644 --- a/include/nana/gui/widgets/picture.hpp +++ b/include/nana/gui/widgets/picture.hpp @@ -17,59 +17,39 @@ namespace nana { - namespace xpicture + namespace drawerbase { - class picture_drawer: public drawer_trigger + namespace picture { - public: - picture_drawer(); - void attached(widget_reference, graph_reference) override; - void load(const nana::char_t* file); - void load(const nana::paint::image&); - void set_shadow_background(const ::nana::color& from, const ::nana::color& to, bool horizontal); - bool bgstyle(bool is_stretch, nana::arrange, int beg, int end); - private: - void refresh(graph_reference) override; - void _m_draw_background(); - private: - widget* widget_; - nana::paint::graphics* graph_; + struct implement; - struct + class drawer : public drawer_trigger { - ::nana::color gradual_from; - ::nana::color gradual_to; - bool horizontal; - }bground_; + public: + drawer(); + ~drawer(); + void attached(widget_reference, graph_reference) override; + private: + void refresh(graph_reference) override; + void _m_draw_background(); + public: + implement * const impl_; + }; + }//end namespace picture + }//end namespace drawerbase - struct back_image_tag - { - nana::paint::image image; - bool is_stretch; - nana::arrange arg; - int beg, end; - }backimg_; - - }; - - }//end namespace xpicture /// Rectangle area for displaying a bitmap file class picture - : public widget_object + : public widget_object { public: picture(); picture(window, bool visible); - picture(window, const rectangle& = rectangle(), bool visible = true); + picture(window, const rectangle& ={}, bool visible = true); - void load(const nana::paint::image&); + void load(nana::paint::image); - /// Sets the background image style. - void bgstyle(bool stretchable, ///< if false the other arguments will be ignored - nana::arrange arg, ///< stretching the image horizontally or vertically - int beg, ///< specify the stretchy area of image. - int end ///< specify the stretchy area of image. - ); + void stretchable(unsigned left, unsigned top, unsigned right, unsigned bottom); /// Fills a gradual-change color in background. If One of colors is invisible or clr_from is equal to clr_to, it draws background in bgcolor. void set_gradual_background(const ::nana::color& clr_from, const ::nana::color& clr_to, bool horizontal); diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index b14a4cb7..aac4712a 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -128,6 +128,7 @@ namespace nana unsigned height() const; ///< Returns the height of the off-screen buffer. ::nana::size size() const; void setsta(); ///< Clears the status if the graphics object had been changed + void set_changed(); void release(); void save_as_file(const char*); diff --git a/source/gui/widgets/picture.cpp b/source/gui/widgets/picture.cpp index 7571d709..4446dff1 100644 --- a/source/gui/widgets/picture.cpp +++ b/source/gui/widgets/picture.cpp @@ -1,6 +1,7 @@ /* * A Picture Implementation - * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) + * Nana C++ Library(http://www.nanapro.org) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -13,244 +14,83 @@ #include #include +#include namespace nana { - namespace xpicture + namespace drawerbase { - - //class picture_drawer - picture_drawer::picture_drawer():graph_(nullptr) + namespace picture + { + struct implement { - bground_.horizontal = true; - backimg_.arg = nana::arrange::unknown; - backimg_.beg = backimg_.end = 0; - } + widget* wdg_ptr{nullptr}; + paint::graphics* graph_ptr{nullptr}; - void picture_drawer::attached(widget_reference& widget, graph_reference graph) - { - widget_ = &widget; - graph_ = &graph; - } - void picture_drawer::load(const nana::char_t* file) - { - backimg_.image.open(file); - } - - void picture_drawer::load(const nana::paint::image& img) - { - backimg_.image = img; - } - - void picture_drawer::set_shadow_background(const ::nana::color& from, const ::nana::color& to, bool horizontal) - { - bground_.gradual_from = from; - bground_.gradual_to = to; - bground_.horizontal = horizontal; - - _m_draw_background(); - } - - bool picture_drawer::bgstyle(bool is_stretch, nana::arrange arg, int beg, int end) - { - if(backimg_.image) + struct gradual_bground_tag { - backimg_.is_stretch = is_stretch; - backimg_.arg = arg; + ::nana::color gradual_from; + ::nana::color gradual_to; + bool horizontal{true}; + }gradual_bground; - if(arg == nana::arrange::horizontal_vertical) return false; + struct back_image_tag + { + paint::image image; + std::unique_ptr bground; + }backimg; + }; - if(beg < 0) beg = 0; - if(end < beg) end = beg; - if((backimg_.beg == beg) && (backimg_.end == end)) return false; - - nana::size imgsize = backimg_.image.size(); - unsigned scale = (arg == nana::arrange::horizontal ? imgsize.width : imgsize.height); - - if(beg < 0) - beg = 0; - else if(static_cast(beg) >= scale) - beg = static_cast(scale) - 1; - - if(end < beg) - end = beg; - else if(static_cast(end) >= scale) - end = static_cast(scale) - 1; - - backimg_.beg = beg; - backimg_.end = end; - return true; - } - - backimg_.arg = nana::arrange::unknown; - return false; + //class drawer + drawer::drawer() :impl_(new implement) + { } - void picture_drawer::refresh(graph_reference graph) + drawer::~drawer() { - if(graph.changed()) + delete impl_; + } + + void drawer::attached(widget_reference& wdg, graph_reference graph) + { + impl_->wdg_ptr = &wdg; + impl_->graph_ptr = &graph; + } + + void drawer::refresh(graph_reference graph) + { + if (!graph.changed()) + return; + + if (!impl_->backimg.bground) { _m_draw_background(); - if(backimg_.image.empty() == false) - { - nana::size imgsize = backimg_.image.size(); - nana::size gsize = graph.size(); - - switch(backimg_.arg) - { - case nana::arrange::unknown: - backimg_.image.paste(graph, 0, 0); - break; - case nana::arrange::horizontal: - if(backimg_.beg < backimg_.end) - { - unsigned block_tail = imgsize.width - backimg_.end; - - if(backimg_.beg) - backimg_.image.paste(nana::rectangle(0, 0, backimg_.beg, imgsize.height), graph, nana::point()); - - if(block_tail) - backimg_.image.paste(nana::rectangle(static_cast(imgsize.width - block_tail), 0, block_tail, imgsize.height), graph, nana::point(gsize.width - block_tail, 0)); - - if(backimg_.beg < backimg_.end) - { - unsigned fixed_size = backimg_.beg + block_tail; - if(fixed_size < gsize.width) - { - if(false == backimg_.is_stretch) - { - unsigned imgarea = backimg_.end - backimg_.beg; - fixed_size = gsize.width - fixed_size; - - nana::rectangle r(backimg_.beg, 0, imgarea, imgsize.height); - nana::point p_dst(backimg_.beg, 0); - - while(imgarea < fixed_size) - { - backimg_.image.paste(r, graph, p_dst); - p_dst.x += static_cast(imgarea); - fixed_size -= imgarea; - } - if(fixed_size) - { - r.width = fixed_size; - backimg_.image.paste(r, graph, p_dst); - } - } - else - backimg_.image.stretch(nana::rectangle(backimg_.beg, 0, imgsize.width - fixed_size, imgsize.height), graph, nana::rectangle(backimg_.beg, 0, gsize.width - fixed_size, imgsize.height)); - } - } - } - else - { - if(false == backimg_.is_stretch) - { - int x = 0; - while(x < static_cast(gsize.width)) - { - backimg_.image.paste(graph, x, 0); - x += static_cast(imgsize.width); - } - } - else - backimg_.image.stretch(imgsize, graph, nana::size(gsize.width, imgsize.height)); - } - break; - case nana::arrange::vertical: - if(backimg_.beg < backimg_.end) - { - unsigned block_tail = imgsize.height - backimg_.end; - - if(backimg_.beg) - backimg_.image.paste(nana::rectangle(0, 0, imgsize.width, static_cast(backimg_.beg)), graph, nana::point()); - - if(block_tail) - backimg_.image.paste(nana::rectangle(0, static_cast(imgsize.height - block_tail), imgsize.width, block_tail), graph, nana::point(0, gsize.height - block_tail)); - - if(backimg_.beg < backimg_.end) - { - unsigned fixed_size = backimg_.beg + block_tail; - if(fixed_size < gsize.height) - { - if(false == backimg_.is_stretch) - { - unsigned imgarea = backimg_.end - backimg_.beg; - fixed_size = gsize.height - fixed_size; - - nana::rectangle r(0, backimg_.beg, imgsize.width, imgarea); - nana::point pos(0, backimg_.beg); - - while(imgarea < fixed_size) - { - backimg_.image.paste(r, graph, pos); - pos.y += static_cast(imgarea); - fixed_size -= imgarea; - } - if(fixed_size) - { - r.height = fixed_size; - backimg_.image.paste(r, graph, pos); - } - } - else - backimg_.image.stretch(nana::rectangle(0, backimg_.beg, imgsize.width, imgsize.height - fixed_size), graph, nana::rectangle(0, backimg_.beg, imgsize.width, gsize.height - fixed_size)); - } - } - } - else - { - if(false == backimg_.is_stretch) - { - int y = 0; - while(y < static_cast(gsize.height)) - { - backimg_.image.paste(graph, 0, y); - y += static_cast(imgsize.height); - } - } - else - backimg_.image.stretch(imgsize, graph, nana::rectangle(0, 0, imgsize.width, gsize.height)); - } - break; - case nana::arrange::horizontal_vertical: - if(backimg_.is_stretch == false) - { - int y = 0; - while(y < static_cast(gsize.height)) - { - int x = 0; - while(x < static_cast(gsize.width)) - { - backimg_.image.paste(graph, x, y); - x += static_cast(imgsize.width); - } - y += static_cast(imgsize.height); - } - } - else - backimg_.image.stretch(imgsize, graph, gsize); - break; - } - } + impl_->backimg.image.paste(graph, 0, 0); } + else + impl_->backimg.bground->draw(graph, {}, {}, graph.size(), element_state::normal); + + graph.setsta(); } - void picture_drawer::_m_draw_background() + void drawer::_m_draw_background() { - if(graph_ && (bground_mode::basic != API::effects_bground_mode(*widget_))) + auto graph = impl_->graph_ptr; + if (graph && (bground_mode::basic != API::effects_bground_mode(*impl_->wdg_ptr))) { - if (bground_.gradual_from.invisible() || bground_.gradual_to.invisible()) - graph_->rectangle(true, widget_->bgcolor()); - else if(bground_.gradual_from == bground_.gradual_to) - graph_->rectangle(true, bground_.gradual_from); + auto & bground = impl_->gradual_bground; + if (bground.gradual_from.invisible() || bground.gradual_to.invisible()) + graph->rectangle(true, impl_->wdg_ptr->bgcolor()); + else if (bground.gradual_from == bground.gradual_to) + graph->rectangle(true, bground.gradual_from); else - graph_->gradual_rectangle(graph_->size(), bground_.gradual_from, bground_.gradual_to, !bground_.horizontal); + graph->gradual_rectangle(graph->size(), bground.gradual_from, bground.gradual_to, !bground.horizontal); } } - //end class picture_drawer - }//end namespace xpicture + //end class drawer + }//end namespace picture + }//end namespace drawerbase //class picture picture::picture(){} @@ -265,21 +105,44 @@ namespace nana create(wd, r, visible); } - void picture::load(const nana::paint::image& img) + void picture::load(nana::paint::image img) { - get_drawer_trigger().load(img); + auto& backimg = get_drawer_trigger().impl_->backimg; + backimg.image = std::move(img); + + if (backimg.bground) + backimg.bground->image(backimg.image, true, {}); + + get_drawer_trigger().impl_->graph_ptr->set_changed(); API::refresh_window(*this); } - void picture::bgstyle(bool stretchable, nana::arrange arg, int beg, int end) + void picture::stretchable(unsigned left, unsigned top, unsigned right, unsigned bottom) { - if(get_drawer_trigger().bgstyle(stretchable, arg, beg, end)) - API::refresh_window(*this); + if (!handle()) + return; + + auto & backimg = get_drawer_trigger().impl_->backimg; + if (!backimg.bground) + { + backimg.bground.reset(new element::bground); + backimg.bground->states({ element_state::normal }); + backimg.bground->image(backimg.image, true, {}); + } + + backimg.bground->stretch_parts(left, top, right, bottom); + get_drawer_trigger().impl_->graph_ptr->set_changed(); + API::refresh_window(*this); } void picture::set_gradual_background(const ::nana::color& from, const ::nana::color& to, bool horizontal) { - get_drawer_trigger().set_shadow_background(from, to, horizontal); + auto & bground = get_drawer_trigger().impl_->gradual_bground; + bground.gradual_from = from; + bground.gradual_to = to; + bground.horizontal = horizontal; + get_drawer_trigger().impl_->graph_ptr->set_changed(); + API::refresh_window(*this); } void picture::transparent(bool enabled) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index f8649ca5..8e61e8dd 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -800,6 +800,11 @@ namespace paint changed_ = false; } + void graphics::set_changed() + { + changed_ = true; + } + void graphics::release() { dwptr_.reset();