From 5393daedd5dc269ce90aea5ea21e9b4092d4610f Mon Sep 17 00:00:00 2001 From: Ning Shi Date: Tue, 1 Jan 2008 23:06:08 +0800 Subject: [PATCH] Edges are clickable now. Added abstract base class template Drawable. --- gtk/src/Makefile.am | 3 +- gtk/src/Makefile.in | 3 +- gtk/src/drawable.hpp | 38 +++++++++++++++++++++++ gtk/src/edge.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++--- gtk/src/edge.hpp | 16 +++++++--- gtk/src/tree_model.cpp | 35 ++++++++++++---------- gtk/src/tree_model.hpp | 2 ++ gtk/src/vertex.cpp | 29 ++++++++---------- gtk/src/vertex.hpp | 23 +++++--------- 9 files changed, 172 insertions(+), 58 deletions(-) create mode 100644 gtk/src/drawable.hpp diff --git a/gtk/src/Makefile.am b/gtk/src/Makefile.am index 00eafb1..8f86ada 100644 --- a/gtk/src/Makefile.am +++ b/gtk/src/Makefile.am @@ -2,7 +2,8 @@ SUBDIRS = core bin_PROGRAMS = avt -source_hpp = edge.hpp \ +source_hpp = drawable.hpp \ + edge.hpp \ list_view.hpp \ main_window.hpp \ tree_model.hpp \ diff --git a/gtk/src/Makefile.in b/gtk/src/Makefile.in index ed7389a..bad42b9 100644 --- a/gtk/src/Makefile.in +++ b/gtk/src/Makefile.in @@ -170,7 +170,8 @@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = core -source_hpp = edge.hpp \ +source_hpp = drawable.hpp \ + edge.hpp \ list_view.hpp \ main_window.hpp \ tree_model.hpp \ diff --git a/gtk/src/drawable.hpp b/gtk/src/drawable.hpp new file mode 100644 index 0000000..718095c --- /dev/null +++ b/gtk/src/drawable.hpp @@ -0,0 +1,38 @@ +#ifndef __DRAWABLE_HPP__ +#define __DRAWABLE_HPP__ + +#include +#include +#include + +template +class Drawable +{ +public: + typedef sigc::signal changed_signal_t; + + Drawable(void) { } + virtual ~Drawable(void) { } + virtual changed_signal_t get_changed_signal(void) const; + virtual void draw(Cairo::RefPtr cr) = 0; + virtual bool select(Cairo::RefPtr cr, gdouble x, gdouble y) = 0; + virtual void deselect(void) = 0; +protected: + virtual void _set_changed(void); +private: + changed_signal_t _changed_signal; +}; + +template +inline typename Drawable::changed_signal_t Drawable::get_changed_signal(void) const +{ + return _changed_signal; +} + +template +inline void Drawable::_set_changed(void) +{ + _changed_signal.emit((T)this); +} + +#endif diff --git a/gtk/src/edge.cpp b/gtk/src/edge.cpp index efdb617..cb34218 100644 --- a/gtk/src/edge.cpp +++ b/gtk/src/edge.cpp @@ -1,8 +1,11 @@ +#include + #include "edge.hpp" Edge::Edge(Vertex &source, Vertex &target) : - _source(source), - _target(target) + Drawable(), + _source(&source), + _target(&target) { } @@ -18,8 +21,8 @@ void Edge::draw(Cairo::RefPtr cr) gdouble end_x, end_y; if (cr) { - _source.get_bottom_anchor(start_x, start_y); - _target.get_top_anchor(end_x, end_y); + _source->get_bottom_anchor(start_x, start_y); + _target->get_top_anchor(end_x, end_y); cr->save(); cr->begin_new_path(); @@ -31,3 +34,73 @@ void Edge::draw(Cairo::RefPtr cr) cr->restore(); } } + +bool Edge::select(Cairo::RefPtr cr, gdouble x, gdouble y) +{ + if (!_is_in_region(cr, x, y)) { + return false; + } + + // If y-coordinate is positive, it means that it is closer to the target + // sentence + if (y > 0) { + change_target_follow_mouse(); + } else { + change_source_follow_mouse(); + } + + return true; +} + +void Edge::deselect(void) +{ + +} + +void Edge::change_source(Vertex &source) +{ + +} + +void Edge::change_target(Vertex &target) +{ + +} + +void Edge::change_source_follow_mouse(void) +{ + +} + +void Edge::change_target_follow_mouse(void) +{ + +} + +bool +Edge::_is_in_region(Cairo::RefPtr cr, gdouble x, gdouble y) const +{ + gdouble start_x, start_y; + gdouble end_x, end_y; + gdouble a, b, distance; + + _source->get_bottom_anchor(start_x, start_y); + _target->get_top_anchor(end_x, end_y); + + // Discards the point if its higher than the source anchor or lower than + // the target anchor + if (y < start_y || y > end_y) { + return false; + } + + // The point has to be within 5 units away from the line segment + a = start_x - end_x; + b = start_y - end_y; + distance = (fabs(a * (end_y - y) - (end_x - x) * b) / + sqrt(pow(a, 2) + pow(b, 2))); + if (distance < 5.0) { + return true; + } + + return false; +} diff --git a/gtk/src/edge.hpp b/gtk/src/edge.hpp index 3f907f8..89e41c0 100644 --- a/gtk/src/edge.hpp +++ b/gtk/src/edge.hpp @@ -3,17 +3,25 @@ #include +#include "drawable.hpp" #include "vertex.hpp" -class Edge +class Edge : public Drawable { public: Edge(Vertex &source, Vertex &target); virtual ~Edge(void); - void draw(Cairo::RefPtr cr); + virtual void draw(Cairo::RefPtr cr); + virtual bool select(Cairo::RefPtr cr, gdouble x, gdouble y); + virtual void deselect(void); + void change_source(Vertex &source); + void change_target(Vertex &target); + void change_source_follow_mouse(void); + void change_target_follow_mouse(void); private: - Vertex &_source; - Vertex &_target; + bool _is_in_region(Cairo::RefPtr cr, gdouble x, gdouble y) const; + Vertex *_source; + Vertex *_target; }; #endif diff --git a/gtk/src/tree_model.cpp b/gtk/src/tree_model.cpp index 55fe8a3..b713df8 100644 --- a/gtk/src/tree_model.cpp +++ b/gtk/src/tree_model.cpp @@ -113,24 +113,13 @@ bool TreeModel::on_expose_event(GdkEventExpose *event) bool TreeModel::on_button_press_event(GdkEventButton *event) { - std::vector::iterator viter; - std::vector::iterator eiter; gdouble x = _d2c_x(event->x); gdouble y = _d2c_y(event->y); - for (viter = _source.begin(); viter != _source.end(); viter++) { - if ((*viter)->is_in_region(_cr, x, y)) { - (*viter)->select(); - - return true; - } - } - for (viter = _target.begin(); viter != _target.end(); viter++) { - if ((*viter)->is_in_region(_cr, x, y)) { - (*viter)->select(); - - return true; - } + if (_button_press_event_cb(_source, x, y) || + _button_press_event_cb(_target, x, y) || + _button_press_event_cb(_edges, x, y)) { + return true; } return true; @@ -160,7 +149,7 @@ void TreeModel::_add_word(const Word &word, bool source) { Vertex *v = new Vertex(*this, word); - v->get_vertex_changed().connect(sigc::mem_fun(*this, &TreeModel::_invalidate_vertex)); + v->get_changed_signal().connect(sigc::mem_fun(*this, &TreeModel::_invalidate_vertex)); if (source) { _source.push_back(v); @@ -235,3 +224,17 @@ void TreeModel::_invalidate_rect(gint x, gint y, gint width, gint height) window->invalidate_rect(invalid, false); } } + +template +bool TreeModel::_button_press_event_cb(std::vector &obj, gdouble x, gdouble y) +{ + typename std::vector::iterator iter; + + for (iter = obj.begin(); iter != obj.end(); iter++) { + if ((*iter)->select(_cr, x, y)) { + return true; + } + } + + return false; +} diff --git a/gtk/src/tree_model.hpp b/gtk/src/tree_model.hpp index 8e008de..69d4692 100644 --- a/gtk/src/tree_model.hpp +++ b/gtk/src/tree_model.hpp @@ -28,6 +28,8 @@ private: void _invalidate_window(void); void _invalidate_vertex(Vertex *v); void _invalidate_rect(gint x, gint y, gint width, gint height); + template + bool _button_press_event_cb(std::vector &obj, gdouble x, gdouble y); gint _c2d_x(gdouble x) const; gint _c2d_y(gdouble y) const; gdouble _d2c_x(gint x) const; diff --git a/gtk/src/vertex.cpp b/gtk/src/vertex.cpp index b11a60a..c675f43 100644 --- a/gtk/src/vertex.cpp +++ b/gtk/src/vertex.cpp @@ -1,13 +1,14 @@ #include "vertex.hpp" Vertex::Vertex(Gtk::Widget &parent, const Word &word) : + Drawable(), _PADDING(2), _x(0), _y(0), _is_highlight(false), _path(NULL), - _layout(parent.create_pango_layout("j")), - _word(word) + _word(word), + _layout(parent.create_pango_layout(_word.get_word())) { Glib::RefPtr line; Pango::Rectangle ink_extents; @@ -16,18 +17,13 @@ Vertex::Vertex(Gtk::Widget &parent, const Word &word) : // Set Font set_font("Sans 12"); - // Get the descent of the font for layout calculation - line = _layout->get_line(0); - if (line) { - _descent = line->get_ink_extents().get_descent() / Pango::SCALE; - } - // Set text and get layout information _layout->set_text(_word.get_word()); line = _layout->get_line(0); if (line) { line->get_extents(ink_extents, extents); + _descent = extents.get_descent() / Pango::SCALE; _width = extents.get_width() / Pango::SCALE + _PADDING * 2; _height = extents.get_height() / Pango::SCALE + @@ -112,12 +108,18 @@ bool Vertex::is_friend(const Vertex &v) const return false; } -void Vertex::select(void) +bool Vertex::select(Cairo::RefPtr cr, gdouble x, gdouble y) { + if (!_is_in_region(cr, x, y)) { + return false; + } + if (!_is_highlight) { _is_highlight = true; _set_changed(); } + + return true; } void Vertex::deselect(void) @@ -128,8 +130,8 @@ void Vertex::deselect(void) } } -bool Vertex::is_in_region(Cairo::RefPtr cr, - gdouble x, gdouble y) const +bool Vertex::_is_in_region(Cairo::RefPtr cr, + gdouble x, gdouble y) const { bool result; @@ -141,8 +143,3 @@ bool Vertex::is_in_region(Cairo::RefPtr cr, return result; } - -void Vertex::_set_changed(void) -{ - _vertex_changed.emit(this); -} diff --git a/gtk/src/vertex.hpp b/gtk/src/vertex.hpp index 010587a..3856f2f 100644 --- a/gtk/src/vertex.hpp +++ b/gtk/src/vertex.hpp @@ -6,13 +6,12 @@ #include #include +#include "drawable.hpp" #include "core/word.hpp" -class Vertex +class Vertex : public Drawable { public: - typedef sigc::signal vertex_changed_signal_t; - Vertex(Gtk::Widget &parent, const Word &word); virtual ~Vertex(void); void set_font(const Glib::ustring &font); @@ -23,16 +22,14 @@ public: gdouble get_height(void) const; void get_top_anchor(gdouble &x, gdouble &y) const; void get_bottom_anchor(gdouble &x, gdouble &y) const; - vertex_changed_signal_t get_vertex_changed(void) const; - void draw(Cairo::RefPtr cr); + virtual void draw(Cairo::RefPtr cr); void add_friend(const Vertex &v); void delete_friend(const Vertex &v); bool is_friend(const Vertex &v) const; - void select(void); - void deselect(void); - bool is_in_region(Cairo::RefPtr cr, gdouble x, gdouble y) const; + virtual bool select(Cairo::RefPtr cr, gdouble x, gdouble y); + virtual void deselect(void); private: - void _set_changed(void); + bool _is_in_region(Cairo::RefPtr cr, gdouble x, gdouble y) const; const gint _PADDING; gdouble _x; @@ -42,10 +39,9 @@ private: gdouble _descent; bool _is_highlight; Cairo::Path *_path; - Glib::RefPtr _layout; - vertex_changed_signal_t _vertex_changed; const Word &_word; + Glib::RefPtr _layout; std::vector _friends; }; @@ -87,9 +83,4 @@ inline void Vertex::get_bottom_anchor(gdouble &x, gdouble &y) const y = _y + _height; } -inline Vertex::vertex_changed_signal_t Vertex::get_vertex_changed(void) const -{ - return _vertex_changed; -} - #endif -- 2.11.4.GIT