Fawkes API  Fawkes Development Version
twolines_cellrenderer.cpp
00001 
00002 /***************************************************************************
00003  *  twolines_cellrenderer.cpp - Gtk rell renderer for two lines of text
00004  *
00005  *  Created: Sat Nov 29 16:36:41 2008
00006  *  Copyright  2008-2011  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <gui_utils/twolines_cellrenderer.h>
00025 
00026 #include <gtkmm.h>
00027 #include <glib-object.h>
00028 
00029 #include <algorithm>
00030 #include <cstring>
00031 #include <cstdio>
00032 
00033 namespace fawkes {
00034 #if 0 /* just to make Emacs auto-indent happy */
00035 }
00036 #endif
00037 
00038 /** @class TwoLinesCellRenderer <gui_utils/twolines_cellrenderer.h>
00039  * Gtk cell renderer for two lines of text in a cell.
00040  * This cell renderer allows you to have two lines of text in a single
00041  * cell. It works by getting the text via two properties. The first line is
00042  * the primary line and printed "normally". The second line is the secondary
00043  * line and printed with a slightly smaller font.
00044  * @author Tim Niemueller
00045  */
00046 
00047 /** Constructor. */
00048 TwoLinesCellRenderer::TwoLinesCellRenderer()
00049   : Glib::ObjectBase(typeid(TwoLinesCellRenderer)),
00050     Gtk::CellRenderer()
00051 #ifdef GLIBMM_PROPERTIES_ENABLED
00052     , __property_line1(*this, "line1", "")
00053     , __property_line2(*this, "line2", "")
00054     , __property_line2_enabled(*this, "line2_enabled", true)
00055 #endif
00056 {
00057 }
00058 
00059 /** Destructor. */
00060 TwoLinesCellRenderer::~TwoLinesCellRenderer()
00061 {
00062 }
00063 
00064 
00065 #ifdef GLIBMM_PROPERTIES_ENABLED
00066 /** Get property proxy for first line.
00067  * @return property proxy for first line
00068  */
00069 Glib::PropertyProxy<Glib::ustring>
00070 TwoLinesCellRenderer::property_line1()
00071 {
00072   return __property_line1.get_proxy();
00073 }
00074 
00075 
00076 /** Get property proxy for second line.
00077  * @return property proxy for second line
00078  */
00079 Glib::PropertyProxy<Glib::ustring>
00080 TwoLinesCellRenderer::property_line2()
00081 {
00082   return __property_line2.get_proxy();
00083 }
00084 
00085 
00086 /** Get property proxy that indicates whether the second line is enabled.
00087  * @return property proxy that indicates whether the second line is enabled
00088  */
00089 Glib::PropertyProxy<bool>
00090 TwoLinesCellRenderer::property_line2_enabled()
00091 {
00092   return __property_line2_enabled.get_proxy();
00093 }
00094 #endif
00095 
00096 
00097 #if GTK_VERSION_GE(3,0)
00098 /** Get required size for widget.
00099  * @param widget widget to create Pango layouts from
00100  * @param width upon return contains the required width
00101  * @param height upon return contains the required height
00102  */
00103 void
00104 TwoLinesCellRenderer::get_size(Gtk::Widget &widget,
00105                                int *width, int *height) const
00106 #else
00107 /** Get required size for cell.
00108  * @param widget widget
00109  * @param cell_area area of the cell
00110  * @param x_offset ignored
00111  * @param y_offset ignored
00112  * @param width upon return contains the required width of the cell
00113  * @param height upon return contains the required height of the cell
00114  */
00115 void
00116 TwoLinesCellRenderer::get_size_vfunc(Gtk::Widget &widget,
00117                                      const Gdk::Rectangle *cell_area,
00118                                      int *x_offset, int *y_offset,
00119                                      int *width, int *height) const
00120 #endif
00121 {
00122 #ifdef GLIBMM_PROPERTIES_ENABLED
00123   // Compute text width
00124   Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(__property_line1);
00125   Pango::Rectangle rect = layout_ptr->get_pixel_logical_extents();
00126         
00127   int line1_width  = property_xpad() * 2 + rect.get_width();
00128   int line1_height = property_ypad() * 2 + rect.get_height();
00129   int line2_height;
00130 
00131   if (__property_line2_enabled.get_value()) {
00132     Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(__property_line2);
00133 #if GTK_VERSION_GE(3,0)
00134     Pango::FontDescription font2("sans 10");
00135 #else
00136     Glib::RefPtr<Gtk::Style> style = widget.get_style();
00137     Pango::FontDescription font2 = style->get_font();
00138 #endif
00139 
00140     font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
00141     layout2->set_font_description(font2);
00142     Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
00143     layout2->set_ellipsize(Pango::ELLIPSIZE_END);
00144 
00145     line2_height = property_ypad() * 2 + rect2.get_height();
00146   } else {
00147     line2_height = 0;
00148   }
00149 
00150   if (width)  *width  = line1_width;
00151   if (height) *height = line1_height + 4 + line2_height;
00152 #endif
00153 }
00154 
00155 #if GTK_VERSION_GE(3,0)
00156 /** Get required size for cell.
00157  * @param widget widget
00158  * @param minimum_width upon return contains the required width of the cell
00159  * @param natural_width upon return contains the required width of the cell
00160  */
00161 void
00162 TwoLinesCellRenderer::get_preferred_width_vfunc(Gtk::Widget &widget,
00163                                                 int &minimum_width,
00164                                                 int &natural_width) const
00165 {
00166   int width = 0;
00167   get_size(widget, &width, NULL);
00168   minimum_width = natural_width = width;
00169 }
00170 
00171 /** Get required size for cell.
00172  * @param widget widget
00173  * @param minimum_height upon return contains the required height of the cell
00174  * @param natural_height upon return contains the required height of the cell
00175  */
00176 void
00177 TwoLinesCellRenderer::get_preferred_height_vfunc(Gtk::Widget &widget,
00178                                                 int &minimum_height,
00179                                                 int &natural_height) const
00180 {
00181   int height = 0;
00182   get_size(widget, NULL, &height);
00183   minimum_height = natural_height = height;
00184 }
00185 #endif
00186 
00187 #if GTK_VERSION_GE(3,0)
00188 /** Render the cell.
00189  * This is called to render the cell.
00190  * @param cr graphic context to use for drawing
00191  * @param widget widget
00192  * @param background_area dimensions of the background area
00193  * @param cell_area dimensions of the cell area
00194  * @param flags render flags
00195  */
00196 void
00197 TwoLinesCellRenderer::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
00198                                    Gtk::Widget &widget,
00199                                    const Gdk::Rectangle &background_area,
00200                                    const Gdk::Rectangle &cell_area,
00201                                    Gtk::CellRendererState flags)
00202 #else
00203 /** Render the cell.
00204  * This is called to render the cell.
00205  * @param window window
00206  * @param widget widget
00207  * @param background_area dimensions of the background area
00208  * @param cell_area dimensions of the cell area
00209  * @param expose_area dimensions of the exposed area
00210  * @param flags render flags
00211  */
00212 void
00213 TwoLinesCellRenderer::render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window,
00214                                    Gtk::Widget &widget,
00215                                    const Gdk::Rectangle &background_area,
00216                                    const Gdk::Rectangle &cell_area,
00217                                    const Gdk::Rectangle &expose_area,
00218                                    Gtk::CellRendererState flags)
00219 #endif
00220 {
00221 #ifdef GLIBMM_PROPERTIES_ENABLED
00222   // Get cell size
00223   int x_offset = 0, y_offset = 0;
00224 #if GTK_VERSION_LT(3,0)
00225   int width = 0, height = 0;
00226   get_size(widget, cell_area, x_offset, y_offset, width, height);
00227 
00228   // Get cell state
00229   //Gtk::StateType state;
00230   Gtk::StateType text_state;
00231   if ((flags & Gtk::CELL_RENDERER_SELECTED) != 0) {
00232     //state = Gtk::STATE_SELECTED;
00233     text_state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
00234   } else {
00235     //state = Gtk::STATE_NORMAL;
00236     text_state = (widget.is_sensitive()) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
00237   }
00238         
00239   // Draw color text
00240   Glib::RefPtr<Gdk::Window> win =
00241     Glib::RefPtr<Gdk::Window>::cast_dynamic(window);
00242 #endif
00243   Glib::RefPtr<Pango::Layout> layout_ptr =
00244     widget.create_pango_layout(__property_line1);
00245   Pango::Rectangle rect1 = layout_ptr->get_pixel_logical_extents();
00246 #if GTK_VERSION_GE(3,0)
00247   cr->move_to(cell_area.get_x() + x_offset + 2 * property_xpad(),
00248               cell_area.get_y() + y_offset + 2 * property_ypad());
00249   layout_ptr->show_in_cairo_context(cr);
00250 #else
00251   widget.get_style()->paint_layout(win, text_state, true, cell_area,
00252                                    widget, "cellrenderertext",
00253                                    cell_area.get_x() + x_offset + 2 * property_xpad(),
00254                                    cell_area.get_y() + y_offset + 2 * property_ypad(),
00255                                    layout_ptr);
00256 #endif
00257 
00258   if (__property_line2_enabled.get_value()) {
00259     Glib::RefPtr<Pango::Layout> layout2 =
00260       widget.create_pango_layout(__property_line2);
00261 #if GTK_VERSION_GE(3,0)
00262     Pango::FontDescription font2("sans 10");
00263 #else
00264     Glib::RefPtr<Gtk::Style> style = widget.get_style();
00265     Pango::FontDescription font2 = style->get_font();
00266 #endif
00267     font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
00268     layout2->set_font_description(font2);
00269     //Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
00270     layout2->set_ellipsize(Pango::ELLIPSIZE_END);
00271     layout2->set_width((cell_area.get_width() - property_xpad()) * Pango::SCALE);
00272 
00273 #if GTK_VERSION_GE(3,0)
00274   cr->move_to(cell_area.get_x() + x_offset + property_xpad(),
00275               cell_area.get_y() + y_offset + property_ypad() +
00276              rect1.get_height() + 4);
00277   layout2->show_in_cairo_context(cr);
00278 #else
00279     widget.get_style()->paint_layout (win, text_state, true, cell_area,
00280                                       widget, "cellrenderertext",
00281                                       cell_area.get_x() + x_offset + property_xpad(),
00282                                       cell_area.get_y() + y_offset + property_ypad() + rect1.get_height() + 4,
00283                                       layout2);
00284 #endif
00285   }
00286 #endif
00287 }
00288 
00289 
00290 } // end namespace fawkes