diff --git a/src/cairo_widget.hh b/src/cairo_widget.hh index 429f63a..4ed89c7 100644 --- a/src/cairo_widget.hh +++ b/src/cairo_widget.hh @@ -30,9 +30,62 @@ namespace sgpem { + /** + * \brief Base abstract class to derive widgets that use cairo graphic output. + * + * This class is the starting point to derive graphics widgets using cairo. + * It provides explicit in memory double buffering, and scaling. + * In order to build a new widget that uses cairo output the developer should + * use this as base class. + * + * The implementer: + * - must + * - implement draw_widget() to draw in the widget client area \see draw_widget() + * - should + * - define calc_drawing_size() to provide correct size calculation + * - call resize_redraw() to calc size and redraw + * - can + * - define calc_widget_size() to get predefined widget dimensions + * - set the desired scaling mode \see set_scaling_mode() + * - call redraw() to only redraw the widget + * + */ class CairoWidget : public Gtk::Widget { public: + /** + * \brief Defines cairo widget scaling modes. + * + * Scaling is the geometric operation that maps draw_widget()'s output + * into client area. + * There are some ways to scale the output to fit in client area. + * The developer does'n need to know how to build the scaling but + * only how it works. + * The defined modes are: + * - scaling_none without any scaling + * - scaling_to_w uses width to calculate scale factor + * - scaling_to_h uses height to calculate scale factor + * - scaling_min uses minimum scale factor from width, height + * - scaling_max uses maximum scale factor from width, height + * - scaling_all scale to stretch into client area + * + * Each mode has advantages and disvantages. + * - scaling_none doesn't do any scaling at all. + * The graphics are rendered as they are drawn. + * - scaling_to_w calc both x and y scaling to fit the client width. + * Probably the draw will exceed the client area height. + * - scaling_to_h calc both x and y scaling to fit the client height. + * Probably the draw will exceed the client area width. + * - scaling_min calc both x and y scaling to enter in the client area. + * The draw will always fit in the window. + * - scaling_max calc both x and y scaling to not enter in the client area. + * The draw will rarely fit in the window. + * - scaling_all calc x and y scaling to fit exactly in the client area. + * The draw will always fit the entire client area. + * NOTE: This scaling mode stretch the drawing and not respect the + * ratio between width and height. + * + */ enum scaling_mode { scaling_none = 0, // without any scaling @@ -43,69 +96,195 @@ namespace sgpem scaling_all = 1 << 4 // scale to stretch into client area }; + /** + * \brief Unique constructor, initialize data members. + */ CairoWidget(); + + /** + * \brief Widget's destructor. + */ virtual ~CairoWidget(); // scaling related functions + /** + * \brief Assign the desired scaling mode and returns the old one. + * + * Change scaling mode; default is scaling_none. + * The programmer must call resize_redraw() becous it take effect. + * + * \param scaling_mode The new desired scaling mode. + * \return Previous scaling mode. + */ scaling_mode set_scaling_mode(scaling_mode scaling_mode); - scaling_mode get_scaling_mode(); + + /** + * \brief Retrieve current scaling mode. + * + * \return Previous scaling mode. + */ + scaling_mode get_scaling_mode() const; - // need for redrawing the widget (double buffering related) + /** + * \brief Force the widgets readrawing without calc new size. + * + * Useful for redrawing the widget (double buffering related). + */ void redraw(); - // need for auto resizing and redrawing the widget (double buffering related) + /** + * \brief Force the widgets readrawing without calc new size. + * + * Need for auto resizing and redrawing the widget (double buffering related). + */ void resize_redraw(); - - // TODO - temporary: will be removed soon - // void change_scaling_mode(); protected: + /** + * \brief Widgets size type. + */ typedef unsigned int size_t; - // implements fundamental widget's method + // implementation of fundamental widget's method + /** + * \brief Implements standard widget's on_realize() mehtod. + * + * The on_realize() function is called by the Gtk windowing system + * before it creates a new widget. + * See gtkmm documentation for more informations. + */ virtual void on_realize(); + + /** + * \brief Implements standard widget's on_size_allocate() mehtod. + * + * The on_size_allocate() function is called by the Gtk windowing system + * after creation of a new widget asking the desired widget dimensions. + * See gtkmm documentation for more informations. + */ virtual void on_size_allocate(const Gtk::Allocation& allocation); + + /** + * \brief Implements standard widget's on_size_request() mehtod. + * + * The on_size_request() function is called by the Gtk windowing system + * when need to change the widget dimensions. + * See gtkmm documentation for more informations. + */ virtual void on_size_request(Gtk::Requisition* request); + + /** + * \brief Implements standard widget's on_expose_event() mehtod. + * + * The on_expose_event() function is called by the Gtk windowing system + * when the widgets' redrawing is requested after creation or to update. + * See gtkmm documentation for more informations. + */ virtual bool on_expose_event(GdkEventExpose* event); + /* + to delete asap virtual bool on_button_press_event(GdkEventButton* event); + */ - // in this method the implemented widget must "do the things" + /** + * \brief Client area drawing method. + * + * In this method the implemented widget must "do the things" + * and (obviously) its implementation is a need. + * The programmer then use the passed cairo context, ctx, to + * draw in the widgets client area. + * See cairo documentation for more informations. + */ virtual void draw_widget(cairo_t* ctx) = 0; - // with this method CairoWidget tells the needed drawing dimensions + /** + * \brief Method to calculate widget dimensions. + * + * The user should implement this method to allow scaling factors calculation. + * Is necessary if scaling is needed/used. + */ virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height); - // with this method CairoWidget tells the needed widgwt dimensions + // with this method CairoWidget tells the needed widget dimensions + /** + * \brief Method to define default widget dimensions. + * + * The user can implement this method to give default dimensions. + * It isn't necessary because scaling (and resizing) take care of calc_drawing_size() results. + */ virtual void calc_widget_size(size_t& width, size_t& height); + /** + * \brief Calculate scaling factors to apply during widget's redrawing. + * + * This method is used internally to recomute scaling factors. + * Implementors of derived calsses doesn't worry about it. + */ void calc_scale_factors(); + /* + I don't know the meaning of these definition! + Paolo typedef Gdk::Rectangle area_t; typedef sigc::mem_functor0 method0_t; typedef std::pair area_callback_t; typedef std::vector areas_vect_t; + */ + /** + * \brief Calculated width of drawing. + *; mutable size_t _draw_w; + + /** + * \brief Calculated height of drawing. + *; mutable size_t _draw_h; - + private: - // The width and height the widget will assume, must be determined - // before starting drawing by calc_size() - // drawing dimensions required - // window client area + /** + * \brief Client area width of widget. + */ mutable size_t _client_w; + + /** + * \brief Client area height of widget. + */ mutable size_t _client_h; - // pixmap client area + + /** + * \brief Client area width of pixmap. + */ mutable size_t _pixmap_w; + + /** + * \brief Client area width of pixmap. + */ mutable size_t _pixmap_h; - // cairo scale factors + + /** + * \brief Cairo x scale factor. + */ mutable double _scale_x; + + /** + * \brief Cairo y scale factor. + */ mutable double _scale_y; + /** + * \brief Flag to signal require redrawing. + */ mutable bool _need_redraw; + + /** + * \brief Actual scaling mode. + */ scaling_mode _scaling_mode; - // The offscreen pixmap we use for double-buffering + /** + * \brief Offscreen pixmap used for double-buffering. + */ Glib::RefPtr _buf; };