improve nana::picture

This commit is contained in:
Jinhao 2015-02-23 01:43:23 +08:00
parent baa8f4a9e9
commit 723dea218d
4 changed files with 111 additions and 262 deletions

View File

@ -17,59 +17,39 @@
namespace nana namespace nana
{ {
namespace xpicture namespace drawerbase
{ {
class picture_drawer: public drawer_trigger namespace picture
{ {
public: struct implement;
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 class drawer : public drawer_trigger
{ {
::nana::color gradual_from; public:
::nana::color gradual_to; drawer();
bool horizontal; ~drawer();
}bground_; 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 /// Rectangle area for displaying a bitmap file
class picture class picture
: public widget_object<category::widget_tag, xpicture::picture_drawer> : public widget_object<category::widget_tag, drawerbase::picture::drawer>
{ {
public: public:
picture(); picture();
picture(window, bool visible); 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 stretchable(unsigned left, unsigned top, unsigned right, unsigned bottom);
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.
);
/// 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. /// 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); void set_gradual_background(const ::nana::color& clr_from, const ::nana::color& clr_to, bool horizontal);

View File

@ -128,6 +128,7 @@ namespace nana
unsigned height() const; ///< Returns the height of the off-screen buffer. unsigned height() const; ///< Returns the height of the off-screen buffer.
::nana::size size() const; ::nana::size size() const;
void setsta(); ///< Clears the status if the graphics object had been changed void setsta(); ///< Clears the status if the graphics object had been changed
void set_changed();
void release(); void release();
void save_as_file(const char*); void save_as_file(const char*);

View File

@ -1,6 +1,7 @@
/* /*
* A Picture Implementation * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -13,244 +14,83 @@
#include <nana/gui/widgets/picture.hpp> #include <nana/gui/widgets/picture.hpp>
#include <nana/paint/image.hpp> #include <nana/paint/image.hpp>
#include <nana/gui/element.hpp>
namespace nana namespace nana
{ {
namespace xpicture namespace drawerbase
{ {
namespace picture
//class picture_drawer {
picture_drawer::picture_drawer():graph_(nullptr) struct implement
{ {
bground_.horizontal = true; widget* wdg_ptr{nullptr};
backimg_.arg = nana::arrange::unknown; paint::graphics* graph_ptr{nullptr};
backimg_.beg = backimg_.end = 0;
}
void picture_drawer::attached(widget_reference& widget, graph_reference graph)
{
widget_ = &widget;
graph_ = &graph;
}
void picture_drawer::load(const nana::char_t* file) struct gradual_bground_tag
{
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)
{ {
backimg_.is_stretch = is_stretch; ::nana::color gradual_from;
backimg_.arg = arg; ::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<element::bground> bground;
}backimg;
};
if(beg < 0) beg = 0; //class drawer
if(end < beg) end = beg; drawer::drawer() :impl_(new implement)
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<unsigned>(beg) >= scale)
beg = static_cast<int>(scale) - 1;
if(end < beg)
end = beg;
else if(static_cast<unsigned>(end) >= scale)
end = static_cast<int>(scale) - 1;
backimg_.beg = beg;
backimg_.end = end;
return true;
}
backimg_.arg = nana::arrange::unknown;
return false;
} }
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(); _m_draw_background();
if(backimg_.image.empty() == false) impl_->backimg.image.paste(graph, 0, 0);
{
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<int>(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<int>(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<int>(gsize.width))
{
backimg_.image.paste(graph, x, 0);
x += static_cast<int>(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<unsigned>(backimg_.beg)), graph, nana::point());
if(block_tail)
backimg_.image.paste(nana::rectangle(0, static_cast<int>(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<int>(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<int>(gsize.height))
{
backimg_.image.paste(graph, 0, y);
y += static_cast<int>(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<int>(gsize.height))
{
int x = 0;
while(x < static_cast<int>(gsize.width))
{
backimg_.image.paste(graph, x, y);
x += static_cast<int>(imgsize.width);
}
y += static_cast<int>(imgsize.height);
}
}
else
backimg_.image.stretch(imgsize, graph, gsize);
break;
}
}
} }
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()) auto & bground = impl_->gradual_bground;
graph_->rectangle(true, widget_->bgcolor()); if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
else if(bground_.gradual_from == bground_.gradual_to) graph->rectangle(true, impl_->wdg_ptr->bgcolor());
graph_->rectangle(true, bground_.gradual_from); else if (bground.gradual_from == bground.gradual_to)
graph->rectangle(true, bground.gradual_from);
else 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 class drawer
}//end namespace xpicture }//end namespace picture
}//end namespace drawerbase
//class picture //class picture
picture::picture(){} picture::picture(){}
@ -265,21 +105,44 @@ namespace nana
create(wd, r, visible); 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); 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)) if (!handle())
API::refresh_window(*this); 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) 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) void picture::transparent(bool enabled)

View File

@ -800,6 +800,11 @@ namespace paint
changed_ = false; changed_ = false;
} }
void graphics::set_changed()
{
changed_ = true;
}
void graphics::release() void graphics::release()
{ {
dwptr_.reset(); dwptr_.reset();