geom_drawing_area.cpp

00001 
00002 /***************************************************************************
00003  *  geom_drawing_area.cpp - A Gtk::DrawingArea for objects of the Fawkes
00004  *  geometry library
00005  *
00006  *  Created: Wed Oct 08 18:52:10 2008
00007  *  Copyright  2008  Daniel Beck
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <geometry/gtk/geom_drawing_area.h>
00026 #include <geometry/hom_point.h>
00027 #include <geometry/gtk/hom_point_drawer.h>
00028 #include <geometry/hom_vector.h>
00029 #include <geometry/gtk/hom_vector_drawer.h>
00030 #include <geometry/line_segment.h>
00031 #include <geometry/gtk/line_segment_drawer.h>
00032 #include <geometry/bezier.h>
00033 #include <geometry/gtk/spline_drawer.h>
00034 #include <geometry/spline.h>
00035 #include <geometry/gtk/bezier_drawer.h>
00036 #include <geometry/gtk/drawing_manipulator.h>
00037 #include <cmath>
00038 
00039 using namespace std;
00040 
00041 namespace fawkes{
00042 
00043 /** @class fawkes::GeomDrawingArea <geometry/gtk/geom_drawing_area.h>
00044  * A Gtk::DrawingArea that allows to easily display drawable objects
00045  * of the geometry library.
00046  * @author Daniel Beck
00047  */
00048 
00049 /** @var fawkes::GeomDrawingArea::m_drawers
00050  * A list of drawers for objects that have been requested to be drawn.
00051  */
00052 
00053 /** @var fawkes::GeomDrawingArea::m_max_x
00054  * Right boundary of the drawing area.
00055  */
00056 
00057 /** @var fawkes::GeomDrawingArea::m_max_y
00058  * Top boundary of the drawing area.
00059  */
00060 
00061 /** @var fawkes::GeomDrawingArea::m_min_x
00062  * Left boundary of the drawing area.
00063  */
00064 
00065 /** @var fawkes::GeomDrawingArea::m_min_y
00066  * Bottom boundary of the drawing area.
00067  */
00068 
00069 /** Constructor.
00070  * @param max_x top right corner
00071  * @param max_y top right corner
00072  * @param min_x bottom left corner
00073  * @param min_y bottom left corner
00074  */
00075 GeomDrawingArea::GeomDrawingArea( float max_x, 
00076                                   float max_y,
00077                                   float min_x,
00078                                   float min_y )
00079   : m_max_x(max_x),
00080     m_max_y(max_y),
00081     m_min_x(min_x),
00082     m_min_y(min_y)
00083 {
00084   m_cur_drawing_manipulator = NULL;
00085 }
00086 
00087 #ifdef HAVE_GLADEMM
00088 /** Constructor.
00089  * @param cobject pointer to the base object
00090  * @param ref_xml Glade XML file
00091  */
00092 GeomDrawingArea::GeomDrawingArea( BaseObjectType* cobject,
00093                                   const Glib::RefPtr<Gnome::Glade::Xml>& ref_xml )
00094   : Gtk::DrawingArea(cobject)
00095 {
00096   m_max_x =  5.0;
00097   m_max_y =  5.0;
00098   m_min_x = -5.0;
00099   m_min_y = -5.0;
00100 
00101   m_cur_drawing_manipulator = NULL;
00102 }
00103 #endif
00104 
00105 /** Destructor. */
00106 GeomDrawingArea::~GeomDrawingArea()
00107 {
00108   clear();
00109 }
00110 
00111 /** Clear the drawing area. */
00112 void
00113 GeomDrawingArea::clear()
00114 {
00115   for ( vector<GeomDrawer*>::iterator iter = m_drawers.begin();
00116         iter != m_drawers.end();
00117         ++iter )
00118     {
00119       delete *iter;
00120     }
00121 
00122   m_drawers.clear();
00123 
00124   m_cur_drawing_manipulator = NULL;
00125 }
00126 
00127 /** <<-operator for HomPoint objects
00128  * @param p a HomPoint object
00129  * @return a reference to the drawing area
00130  */
00131 GeomDrawingArea&
00132 GeomDrawingArea::operator<<(fawkes::HomPoint& p)
00133 {
00134   HomPointDrawer* d = new HomPointDrawer(p);
00135 
00136   if (m_cur_drawing_manipulator)
00137     { d->set_point_size( m_cur_drawing_manipulator->get_point_size() ); }
00138 
00139   m_drawers.push_back(d);
00140 
00141   return *this;
00142 }
00143 
00144 /** <<-operator for HomPoint objects
00145  * @param p a HomPoint object
00146  * @return a reference to the drawing area
00147  */
00148 GeomDrawingArea&
00149 GeomDrawingArea::operator<<(const fawkes::HomPoint& p)
00150 {
00151   HomPointDrawer* d = new HomPointDrawer(p);
00152 
00153   if (m_cur_drawing_manipulator)
00154     { d->set_point_size( m_cur_drawing_manipulator->get_point_size() ); }
00155 
00156   m_drawers.push_back(d);
00157 
00158   return *this;
00159 }
00160 
00161 /** <<-operator for HomVector objects
00162  * @param vp a pair constisting of the vector and the offset
00163  * @return a reference to the drawing area
00164  */
00165 GeomDrawingArea&
00166 GeomDrawingArea::operator<<(std::pair<HomVector, HomPoint> vp)
00167 {
00168   const HomVector& v = vp.first;
00169   const HomPoint& offset = vp.second;
00170   HomVectorDrawer* d = new HomVectorDrawer(v, offset);
00171   m_drawers.push_back(d);
00172 
00173   return *this;
00174 }
00175 
00176 /** <<-operator for LineSegments objects
00177  * @param l a LineSegment object
00178  * @return a reference to the drawing area
00179  */
00180 GeomDrawingArea&
00181 GeomDrawingArea::operator<<(fawkes::LineSegment& l)
00182 {
00183   LineSegmentDrawer* d = new LineSegmentDrawer(l);
00184   m_drawers.push_back(d);
00185 
00186   return *this;
00187 }
00188 
00189 /** <<-operator for Bezier objects.
00190  * @param b a Bezier object
00191  * @return a reference to the drawing area
00192  */
00193 GeomDrawingArea&
00194 GeomDrawingArea::operator<<(fawkes::Bezier& b)
00195 {
00196   BezierDrawer* d = new BezierDrawer(b);
00197   m_drawers.push_back(d);
00198 
00199   return *this;
00200 }
00201 
00202 /** <<-operator for Spline objects.
00203  * @param s a Spline object
00204  * @return a reference to the drawing area
00205  */
00206 GeomDrawingArea&
00207 GeomDrawingArea::operator<<(fawkes::Spline& s)
00208 {
00209   SplineDrawer* d = new SplineDrawer(s);
00210   m_drawers.push_back(d);
00211 
00212   return *this;
00213 }
00214 
00215 /** <<-operator for Spline objects.
00216  * @param s a Spline object
00217  * @return a reference to the drawing area
00218  */
00219 GeomDrawingArea&
00220 GeomDrawingArea::operator<<(const fawkes::Spline& s)
00221 {
00222   SplineDrawer* d = new SplineDrawer(s);
00223   m_drawers.push_back(d);
00224 
00225   return *this;
00226 }
00227 
00228 /** <<-operator for DrawingManipulator objects.
00229  * Note: the drawing area takes over the ownwership of the manipulator.
00230  * @param m a DrawingManipulator object
00231  * @return a reference to the drawing area
00232  */
00233 GeomDrawingArea&
00234 GeomDrawingArea::operator<<(fawkes::DrawingManipulator* m)
00235 {
00236   if (m_cur_drawing_manipulator)
00237     { m->integrate(m_cur_drawing_manipulator); }
00238 
00239   m_cur_drawing_manipulator = m;
00240   m_drawers.push_back(m);
00241 
00242   return *this;
00243 }
00244 
00245 /** Signal handler for the expose event.
00246  * @param event the event
00247  * @return true if event has been handled
00248  */
00249 bool
00250 GeomDrawingArea::on_expose_event(GdkEventExpose* event)
00251 {
00252   Glib::RefPtr<Gdk::Window> window = get_window();
00253   if (window)
00254     {
00255       Gtk::Allocation allocation = get_allocation();
00256       m_window_width = allocation.get_width();
00257       m_window_height = allocation.get_height();
00258       
00259       Cairo::RefPtr<Cairo::Context> context = window->create_cairo_context();
00260       
00261       if (event)
00262         {
00263           context->rectangle( event->area.x, event->area.y,
00264                               event->area.width, event->area.height );
00265           context->clip();
00266         }
00267       
00268       float unit_width  = fabs(m_max_x) + fabs(m_min_x);
00269       float unit_height = fabs(m_max_y) + fabs(m_min_y);
00270       if ( (m_window_width / unit_width) <= (m_window_height / unit_height) )
00271         { m_unit = m_window_width / unit_width; }
00272       else
00273         { m_unit = m_window_height / unit_height; }
00274       
00275       pre_draw(context);
00276       
00277       for ( vector<GeomDrawer*>::iterator iter = m_drawers.begin();
00278             iter != m_drawers.end();
00279             ++iter )
00280         {
00281           GeomDrawer* d = *iter;
00282           d->draw(context);
00283         }
00284 
00285       post_draw(context);
00286 
00287       context->stroke();
00288     }
00289 
00290   return true;
00291 }
00292 
00293 /** Convert the given window coordinates into the frame of the drawing area.
00294  * @param window_x the window coordinate
00295  * @param window_y the window coordinate
00296  * @param drawing_x the drawing coordinate
00297  * @param drawing_y the drawing coordinate
00298  */
00299 void
00300 GeomDrawingArea::to_drawing_coords( int window_x, int window_y,
00301                                     float& drawing_x, float& drawing_y )
00302 {
00303   float unit_width  = fabs(m_max_x) + fabs(m_min_x);
00304   
00305   float pixel_per_unit = m_window_width / unit_width;
00306 
00307   drawing_x =   window_x / pixel_per_unit + m_min_x;
00308   drawing_y = -(window_y / pixel_per_unit + m_min_y);
00309 }
00310 
00311 /** This method is called by the expose signal handler before the draw
00312  * routines of the registered drawers are called.
00313  * Derived classes might want to change this to add static drawing
00314  * elements or to change the viewing matrix.
00315  * @param context the drawing context
00316  */
00317 void
00318 GeomDrawingArea::pre_draw(Cairo::RefPtr<Cairo::Context>& context)
00319 {
00320   context->translate( m_window_width / 2.0, m_window_height / 2.0 );
00321   context->scale(m_unit, -m_unit);
00322 }
00323 
00324 /** This method is called by the expose signal handler after the
00325  * draw routines of the registered drawers are called.
00326  * Derived classes might want to change this to add static drawing
00327  * elements.
00328  * @param context the drawing context
00329  */
00330 void
00331 GeomDrawingArea::post_draw(Cairo::RefPtr<Cairo::Context>& context)
00332 {
00333 }
00334 
00335 } // end namespace fawkes

Generated on Tue Feb 22 13:32:27 2011 for Fawkes API by  doxygen 1.4.7