Add the arrow element

This commit is contained in:
cnjinhao 2015-01-19 02:12:29 +08:00
parent 5b025ccd20
commit a9d063ab17
3 changed files with 314 additions and 16 deletions

View File

@ -464,6 +464,16 @@ namespace nana
{ {
top, center, bottom top, center, bottom
}; };
///The definition of the four corners of the world
enum class direction
{
north,
south,
east,
west,
southeast
};
}//end namespace nana }//end namespace nana
#endif #endif

View File

@ -61,6 +61,14 @@ namespace nana
virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, unsigned weight) = 0; virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, unsigned weight) = 0;
}; };
class arrow_interface
{
public:
using graph_reference = paint::graphics&;
virtual ~arrow_interface() = default;
virtual bool draw(graph_reference, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle&, element_state, direction) = 0;
};
class provider class provider
{ {
public: public:
@ -95,6 +103,9 @@ namespace nana
void add_border(const std::string&, const pat::cloneable<factory_interface<border_interface>>&); void add_border(const std::string&, const pat::cloneable<factory_interface<border_interface>>&);
border_interface* const * keeper_border(const std::string&); border_interface* const * keeper_border(const std::string&);
void add_arrow(const std::string&, const pat::cloneable<factory_interface<arrow_interface>>&);
arrow_interface* const * keeper_arrow(const std::string&);
}; };
class crook; class crook;
@ -106,13 +117,20 @@ namespace nana
} }
class border; class border;
template<typename BorderElement> template<typename BorderElement>
void add_border(const std::string& name) void add_border(const std::string& name)
{ {
using factory_t = provider::factory<BorderElement, border_interface>; using factory_t = provider::factory<BorderElement, border_interface>;
provider().add_border(name, pat::cloneable<typename factory_t::interface_type>(factory_t())); provider().add_border(name, pat::cloneable<typename factory_t::interface_type>(factory_t()));
} }
class arrow;
template<typename ArrowElement>
void add_arrow(const std::string& name)
{
using factory_t = provider::factory<ArrowElement, arrow_interface>;
provider().add_arrow(name, pat::cloneable<typename factory_t::interface_type>(factory_t()));
}
}//end namespace element }//end namespace element
template<typename Element> class facade; template<typename Element> class facade;
@ -125,8 +143,7 @@ namespace nana
using graph_reference = ::nana::paint::graphics &; using graph_reference = ::nana::paint::graphics &;
using state = element::crook_interface::state; using state = element::crook_interface::state;
facade(); facade(const char* name = nullptr);
facade(const char* name);
facade & reverse(); facade & reverse();
facade & check(state); facade & check(state);
@ -150,8 +167,7 @@ namespace nana
{ {
using graph_reference = ::nana::paint::graphics &; using graph_reference = ::nana::paint::graphics &;
public: public:
facade(); facade(const char* name = nullptr);
facade(const char* name);
void switch_to(const char*); void switch_to(const char*);
public: public:
@ -161,6 +177,30 @@ namespace nana
element::border_interface* const * keeper_; element::border_interface* const * keeper_;
};//end class facade<element::border> };//end class facade<element::border>
template<>
class facade<element::arrow>
: public element::element_interface
{
using graph_reference = ::nana::paint::graphics &;
public:
enum class style
{
solid
};
facade(const char* name = nullptr);
void switch_to(const char*);
void direction(::nana::direction);
public:
//Implement element_interface
bool draw(graph_reference, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle&, element_state) override;
private:
element::arrow_interface* const * keeper_;
::nana::direction dir_{::nana::direction::north};
};//end class facade<element::arrow>
namespace element namespace element
{ {
void set_bground(const char* name, const pat::cloneable<element_interface>&); void set_bground(const char* name, const pat::cloneable<element_interface>&);

View File

@ -268,6 +268,215 @@ namespace nana
return true; return true;
} }
}; };
class arrow_solid_triangle
: public arrow_interface
{
bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, direction dir) override
{
::nana::point pos{ r.x + 3, r.y + 3 };
switch (dir)
{
case ::nana::direction::east:
pos.x += 3;
pos.y += 1;
for (int i = 0; i < 5; ++i)
graph.line(point{ pos.x + i, pos.y + i }, point{ pos.x + i, pos.y + 8 - i });
break;
case ::nana::direction::south:
pos.y += 3;
for (int i = 0; i < 5; ++i)
graph.line(point{ pos.x + i, pos.y + i }, point{ pos.x + 8 - i, pos.y + i });
break;
case ::nana::direction::west:
pos.x += 5;
pos.y += 1;
for (int i = 0; i < 5; ++i)
graph.line(point{ pos.x - i, pos.y + i }, point{ pos.x - i, pos.y + 8 - i });
break;
case ::nana::direction::north:
pos.y += 7;
for (int i = 0; i < 5; ++i)
graph.line(point{ pos.x + i, pos.y - i }, point{ pos.x + 8 - i, pos.y - i });
break;
case direction::southeast:
pos.x += 2;
pos.y += 7;
for (int i = 0; i < 6; ++i)
graph.line(point{ pos.x + i, pos.y - i }, point{ pos.x + 5, pos.y - i });
break;
}
return true;
}
};//end class arrow_solid_triangle
class arrow_hollow_triangle
: public arrow_interface
{
bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, ::nana::direction dir) override
{
int x = r.x + 3;
int y = r.x + 3;
switch (dir)
{
case ::nana::direction::east:
x += 3;
graph.line(point{ x, y + 1 }, point{ x, y + 9 });
graph.line(point{ x + 1, y + 2 }, point{ x + 4, y + 5 });
graph.line(point{ x + 3, y + 6 }, point{ x + 1, y + 8 });
break;
case direction::southeast:
x += 7;
y += 6;
graph.line(point{ x - 5 , y + 1 }, point{ x, y + 1 });
graph.line(point{ x, y - 4 }, point{ x, y });
graph.line(point{ x - 4, y }, point{ x - 1, y - 3 });
break;
case direction::south:
y += 3;
graph.line(point{ x, y }, point{ x + 8, y });
graph.line(point{ x + 1, y + 1 }, point{ x + 4, y + 4 });
graph.line(point{ x + 7, y + 1 }, point{ x + 5, y + 3 });
break;
case direction::west:
x += 5;
y += 1;
graph.line(point{ x, y }, point{ x, y + 8 });
graph.line(point{ x - 4, y + 4 }, point{ x - 1, y + 1 });
graph.line(point{ x - 3, y + 5 }, point{ x - 1, y + 7 });
break;
case direction::north:
y += 7;
graph.line(point{ x, y }, point{ x + 8, y });
graph.line(point{ x + 1, y - 1 }, point{ x + 4, y - 4 });
graph.line(point{ x + 5, y - 3 }, point{ x + 7, y - 1 });
break;
}
return true;
}
};//end class arrow_hollow_triangle
class arrowhead
: public arrow_interface
{
bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, ::nana::direction dir) override
{
int x = r.x;
int y = r.y + 5;
switch (dir)
{
case direction::north:
{
x += 3;
int pixels = 1;
for (int l = 0; l < 4; ++l)
{
for (int i = 0; i < pixels; ++i)
{
if (l == 3 && i == 3)
continue;
graph.set_pixel(x + i, y);
}
x--;
y++;
pixels += 2;
}
graph.set_pixel(x + 1, y);
graph.set_pixel(x + 2, y);
graph.set_pixel(x + 6, y);
graph.set_pixel(x + 7, y);
}
break;
case direction::south:
{
graph.set_pixel(x, y);
graph.set_pixel(x + 1, y);
graph.set_pixel(x + 5, y);
graph.set_pixel(x + 6, y);
++y;
int pixels = 7;
for (int l = 0; l < 4; ++l)
{
for (int i = 0; i < pixels; ++i)
{
if (l != 0 || i != 3)
graph.set_pixel(x + i, y);
}
x++;
y++;
pixels -= 2;
}
}
break;
}
return true;
}
};//end class arrowhead
class arrow_double
: public arrow_interface
{
bool draw(graph_reference graph, const ::nana::color& bgcolor, const ::nana::color& fgcolor, const ::nana::rectangle& r, element_state estate, ::nana::direction dir) override
{
int x = r.x;
int y = r.y;
switch (dir)
{
case direction::east:
_m_line(graph, x + 4, y + 6, true);
_m_line(graph, x + 5, y + 7, true);
_m_line(graph, x + 6, y + 8, true);
_m_line(graph, x + 5, y + 9, true);
_m_line(graph, x + 4, y + 10, true);
break;
case direction::west:
_m_line(graph, x + 5, y + 6, true);
_m_line(graph, x + 4, y + 7, true);
_m_line(graph, x + 3, y + 8, true);
_m_line(graph, x + 4, y + 9, true);
_m_line(graph, x + 5, y + 10, true);
break;
case direction::south:
_m_line(graph, x + 5, y + 4, false);
_m_line(graph, x + 6, y + 5, false);
_m_line(graph, x + 7, y + 6, false);
_m_line(graph, x + 8, y + 5, false);
_m_line(graph, x + 9, y + 4, false);
break;
case direction::north:
_m_line(graph, x + 5, y + 6, false);
_m_line(graph, x + 6, y + 5, false);
_m_line(graph, x + 7, y + 4, false);
_m_line(graph, x + 8, y + 5, false);
_m_line(graph, x + 9, y + 6, false);
break;
default:
break;
}
return true;
}
static void _m_line(nana::paint::graphics & graph, int x, int y, bool horizontal)
{
graph.set_pixel(x, y);
if (horizontal)
{
graph.set_pixel(x + 1, y);
graph.set_pixel(x + 4, y);
graph.set_pixel(x + 5, y);
}
else
{
graph.set_pixel(x, y + 1);
graph.set_pixel(x, y + 4);
graph.set_pixel(x, y + 5);
}
}
};
}//end namespace element }//end namespace element
template<typename ElementInterface> template<typename ElementInterface>
@ -348,6 +557,11 @@ namespace nana
element::add_crook<element::menu_crook>("menu_crook"); element::add_crook<element::menu_crook>("menu_crook");
element::add_border<element::border_depressed>(""); element::add_border<element::border_depressed>("");
element::add_arrow<element::arrowhead>("");
element::add_arrow<element::arrow_double>("double");
element::add_arrow<element::arrow_solid_triangle>("solid_triangle");
element::add_arrow<element::arrow_hollow_triangle>("hollow_triangle");
} }
return obj; return obj;
} }
@ -371,6 +585,16 @@ namespace nana
{ {
return _m_get(name, border_).keeper(); return _m_get(name, border_).keeper();
} }
void arrow(const std::string& name, const pat::cloneable<element::provider::factory_interface<element::arrow_interface>>& factory)
{
_m_add((name.empty() ? "arrowhead" : name), arrow_, factory);
}
element::arrow_interface * const * arrow(const std::string& name) const
{
return _m_get((name.empty() ? "arrowhead" : name), arrow_).keeper();
}
private: private:
using lock_guard = std::lock_guard<std::recursive_mutex>; using lock_guard = std::lock_guard<std::recursive_mutex>;
@ -405,6 +629,7 @@ namespace nana
mutable std::recursive_mutex mutex_; mutable std::recursive_mutex mutex_;
item<element::crook_interface> crook_; item<element::crook_interface> crook_;
item<element::border_interface> border_; item<element::border_interface> border_;
item<element::arrow_interface> arrow_;
}; };
namespace element namespace element
@ -429,17 +654,20 @@ namespace nana
{ {
return element_manager::instance().border(name); return element_manager::instance().border(name);
} }
void provider::add_arrow(const std::string& name, const pat::cloneable<factory_interface<arrow_interface>>& factory)
{
element_manager::instance().arrow(name, factory);
}
arrow_interface* const * provider::keeper_arrow(const std::string& name)
{
return element_manager::instance().arrow(name);
}
}//end namespace element }//end namespace element
//facades //facades
//template<> class facade<element::crook> //template<> class facade<element::crook>
facade<element::crook>::facade()
: keeper_(element::provider().keeper_crook(""))
{
data_.check_state = state::unchecked;
data_.radio = false;
}
facade<element::crook>::facade(const char* name) facade<element::crook>::facade(const char* name)
: keeper_(element::provider().keeper_crook(name ? name : "")) : keeper_(element::provider().keeper_crook(name ? name : ""))
{ {
@ -487,10 +715,6 @@ namespace nana
//end class facade<element::crook> //end class facade<element::crook>
//class facade<element::border> //class facade<element::border>
facade<element::border>::facade()
: facade(nullptr)
{}
facade<element::border>::facade(const char* name) facade<element::border>::facade(const char* name)
: keeper_(element::provider().keeper_border(name ? name : "")) : keeper_(element::provider().keeper_border(name ? name : ""))
{} {}
@ -506,6 +730,30 @@ namespace nana
} }
//end class facade<element::border> //end class facade<element::border>
//class facade<element::arrow>
facade<element::arrow>::facade(const char* name)
: keeper_(element::provider().keeper_arrow(name ? name : ""))
{
}
void facade<element::arrow>::switch_to(const char* name)
{
keeper_ = element::provider().keeper_arrow(name ? name : "");
}
void facade<element::arrow>::direction(::nana::direction dir)
{
dir_ = dir;
}
//Implement element_interface
bool facade<element::arrow>::draw(graph_reference graph, const nana::color& bgcolor, const nana::color& fgcolor, const nana::rectangle& r, element_state estate)
{
graph.set_color(fgcolor);
return (*keeper_)->draw(graph, bgcolor, fgcolor, r, estate, dir_);
}
//end class facade<element::arrow>
namespace element namespace element
{ {
void set_bground(const char* name, const pat::cloneable<element_interface>& obj) void set_bground(const char* name, const pat::cloneable<element_interface>& obj)