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  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 <gtk/gtkcellrenderer.h>
00028 #include <glib-object.h>
00029 
00030 #include <algorithm>
00031 #include <cstring>
00032 #include <cstdio>
00033 
00034 namespace fawkes {
00035 #if 0 /* just to make Emacs auto-indent happy */
00036 }
00037 #endif
00038 
00039 /** @class TwoLinesCellRenderer <gui_utils/twolines_cellrenderer.h>
00040  * Gtk cell renderer for two lines of text in a cell.
00041  * This cell renderer allows you to have two lines of text in a single
00042  * cell. It works by getting the text via two properties. The first line is
00043  * the primary line and printed "normally". The second line is the secondary
00044  * line and printed with a slightly smaller font.
00045  * @author Tim Niemueller
00046  */
00047 
00048 /** Constructor. */
00049 TwoLinesCellRenderer::TwoLinesCellRenderer()
00050   : Glib::ObjectBase(typeid(TwoLinesCellRenderer)),
00051     Gtk::CellRenderer()
00052 #ifdef GLIBMM_PROPERTIES_ENABLED
00053     , __property_line1(*this, "line1", "")
00054     , __property_line2(*this, "line2", "")
00055     , __property_line2_enabled(*this, "line2_enabled", true)
00056 #endif
00057 {
00058 }
00059 
00060 /** Destructor. */
00061 TwoLinesCellRenderer::~TwoLinesCellRenderer()
00062 {
00063 }
00064 
00065 
00066 #ifdef GLIBMM_PROPERTIES_ENABLED
00067 /** Get property proxy for first line.
00068  * @return property proxy for first line
00069  */
00070 Glib::PropertyProxy<Glib::ustring>
00071 TwoLinesCellRenderer::property_line1()
00072 {
00073   return __property_line1.get_proxy();
00074 }
00075 
00076 
00077 /** Get property proxy for second line.
00078  * @return property proxy for second line
00079  */
00080 Glib::PropertyProxy<Glib::ustring>
00081 TwoLinesCellRenderer::property_line2()
00082 {
00083   return __property_line2.get_proxy();
00084 }
00085 
00086 
00087 /** Get property proxy that indicates whether the second line is enabled.
00088  * @return property proxy that indicates whether the second line is enabled
00089  */
00090 Glib::PropertyProxy<bool>
00091 TwoLinesCellRenderer::property_line2_enabled()
00092 {
00093   return __property_line2_enabled.get_proxy();
00094 }
00095 #endif
00096 
00097 
00098 /** Get required size for cell.
00099  * @param widget widget
00100  * @param cell_area area of the cell
00101  * @param x_offset ignored
00102  * @param y_offset ignored
00103  * @param width upon return contains the required width of the cell
00104  * @param height upon return contains the required height of the cell
00105  */
00106 void
00107 TwoLinesCellRenderer::get_size_vfunc(Gtk::Widget &widget,
00108                                      const Gdk::Rectangle *cell_area,
00109                                      int *x_offset, int *y_offset,
00110                                      int *width, int *height) const
00111 {
00112 #ifdef GLIBMM_PROPERTIES_ENABLED
00113   // Compute text width
00114   Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(__property_line1);
00115   Pango::Rectangle rect = layout_ptr->get_pixel_logical_extents();
00116         
00117   int line1_width  = property_xpad() * 2 + rect.get_width();
00118   int line1_height = property_ypad() * 2 + rect.get_height();
00119   int line2_height;
00120 
00121   if (__property_line2_enabled.get_value()) {
00122     Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(__property_line2);
00123     Glib::RefPtr<Gtk::Style> style = widget.get_style();
00124     Pango::FontDescription font2 = style->get_font();
00125     font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
00126     layout2->set_font_description(font2);
00127     Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
00128     layout2->set_ellipsize(Pango::ELLIPSIZE_END);
00129 
00130     line2_height = property_ypad() * 2 + rect2.get_height();
00131   } else {
00132     line2_height = 0;
00133   }
00134 
00135   if ( width )  *width  = line1_width;
00136   if ( height ) *height = line1_height + 4 + line2_height;    
00137 #endif
00138 }
00139 
00140 
00141 /** Render the cell.
00142  * This is called to render the cell.
00143  * @param window window
00144  * @param widget widget
00145  * @param background_area dimensions of the background area
00146  * @param cell_area dimensions of the cell area
00147  * @param expose_area dimensions of the exposed area
00148  * @param flags render flags
00149  */
00150 void
00151 TwoLinesCellRenderer::render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window,
00152                                    Gtk::Widget &widget,
00153                                    const Gdk::Rectangle &background_area,
00154                                    const Gdk::Rectangle &cell_area,
00155                                    const Gdk::Rectangle &expose_area,
00156                                    Gtk::CellRendererState flags)
00157 {
00158 #ifdef GLIBMM_PROPERTIES_ENABLED
00159   // Get cell size
00160   int x_offset = 0, y_offset = 0, width = 0, height = 0;
00161   get_size(widget, cell_area, x_offset, y_offset, width, height);
00162     
00163   // Create the graphic context
00164   Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create(window);
00165     
00166   // Get cell state
00167   //Gtk::StateType state;
00168   Gtk::StateType text_state;
00169   if ((flags & Gtk::CELL_RENDERER_SELECTED) != 0) {
00170     //state = Gtk::STATE_SELECTED;
00171     text_state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
00172   } else {
00173     //state = Gtk::STATE_NORMAL;
00174     text_state = (widget.is_sensitive()) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
00175   }
00176         
00177   // Draw color text
00178   Glib::RefPtr<Gdk::Window> win = Glib::RefPtr<Gdk::Window>::cast_dynamic(window);    
00179   Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(__property_line1);
00180   Pango::Rectangle rect1 = layout_ptr->get_pixel_logical_extents();
00181   widget.get_style()->paint_layout (win, text_state, true, cell_area,
00182                                     widget, "cellrenderertext",
00183                                     cell_area.get_x() + x_offset + 2 * property_xpad(),
00184                                     cell_area.get_y() + y_offset + 2 * property_ypad(),
00185                                     layout_ptr);
00186 
00187   if (__property_line2_enabled.get_value()) {
00188     Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(__property_line2);
00189     Glib::RefPtr<Gtk::Style> style = widget.get_style();
00190     Pango::FontDescription font2 = style->get_font();
00191     font2.set_size((int)roundf(Pango::SCALE_SMALL * std::max(font2.get_size(), 8)));
00192     layout2->set_font_description(font2);
00193     //Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
00194     layout2->set_ellipsize(Pango::ELLIPSIZE_END);
00195     layout2->set_width((cell_area.get_width() - property_xpad()) * Pango::SCALE);
00196     widget.get_style()->paint_layout (win, text_state, true, cell_area,
00197                                       widget, "cellrenderertext",
00198                                       cell_area.get_x() + x_offset + property_xpad(),
00199                                       cell_area.get_y() + y_offset + property_ypad() + rect1.get_height() + 4,
00200                                       layout2);
00201   }
00202 #endif
00203 }
00204 
00205 
00206 } // end namespace fawkes