Fawkes API  Fawkes Development Version
twolines_cellrenderer.cpp
1 
2 /***************************************************************************
3  * twolines_cellrenderer.cpp - Gtk rell renderer for two lines of text
4  *
5  * Created: Sat Nov 29 16:36:41 2008
6  * Copyright 2008-2011 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <gui_utils/twolines_cellrenderer.h>
25 
26 #include <gtkmm.h>
27 #include <glib-object.h>
28 
29 #include <algorithm>
30 #include <cstring>
31 #include <cstdio>
32 
33 namespace fawkes {
34 #if 0 /* just to make Emacs auto-indent happy */
35 }
36 #endif
37 
38 /** @class TwoLinesCellRenderer <gui_utils/twolines_cellrenderer.h>
39  * Gtk cell renderer for two lines of text in a cell.
40  * This cell renderer allows you to have two lines of text in a single
41  * cell. It works by getting the text via two properties. The first line is
42  * the primary line and printed "normally". The second line is the secondary
43  * line and printed with a slightly smaller font.
44  * @author Tim Niemueller
45  */
46 
47 /** Constructor. */
49  : Glib::ObjectBase(typeid(TwoLinesCellRenderer)),
50  Gtk::CellRenderer()
51 #ifdef GLIBMM_PROPERTIES_ENABLED
52  , __property_line1(*this, "line1", "")
53  , __property_line2(*this, "line2", "")
54  , __property_line2_enabled(*this, "line2_enabled", true)
55 #endif
56 {
57 }
58 
59 /** Destructor. */
61 {
62 }
63 
64 
65 #ifdef GLIBMM_PROPERTIES_ENABLED
66 /** Get property proxy for first line.
67  * @return property proxy for first line
68  */
69 Glib::PropertyProxy<Glib::ustring>
70 TwoLinesCellRenderer::property_line1()
71 {
72  return __property_line1.get_proxy();
73 }
74 
75 
76 /** Get property proxy for second line.
77  * @return property proxy for second line
78  */
79 Glib::PropertyProxy<Glib::ustring>
80 TwoLinesCellRenderer::property_line2()
81 {
82  return __property_line2.get_proxy();
83 }
84 
85 
86 /** Get property proxy that indicates whether the second line is enabled.
87  * @return property proxy that indicates whether the second line is enabled
88  */
89 Glib::PropertyProxy<bool>
90 TwoLinesCellRenderer::property_line2_enabled()
91 {
92  return __property_line2_enabled.get_proxy();
93 }
94 #endif
95 
96 
97 #if GTK_VERSION_GE(3,0)
98 /** Get required size for widget.
99  * @param widget widget to create Pango layouts from
100  * @param width upon return contains the required width
101  * @param height upon return contains the required height
102  */
103 void
104 TwoLinesCellRenderer::get_size(Gtk::Widget &widget,
105  int *width, int *height) const
106 #else
107 /** Get required size for cell.
108  * @param widget widget
109  * @param cell_area area of the cell
110  * @param x_offset ignored
111  * @param y_offset ignored
112  * @param width upon return contains the required width of the cell
113  * @param height upon return contains the required height of the cell
114  */
115 void
117  const Gdk::Rectangle *cell_area,
118  int *x_offset, int *y_offset,
119  int *width, int *height) const
120 #endif
121 {
122 #ifdef GLIBMM_PROPERTIES_ENABLED
123  // Compute text width
124  Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(__property_line1);
125  Pango::Rectangle rect = layout_ptr->get_pixel_logical_extents();
126 
127  int line1_width = property_xpad() * 2 + rect.get_width();
128  int line1_height = property_ypad() * 2 + rect.get_height();
129  int line2_height;
130 
131  if (__property_line2_enabled.get_value()) {
132  Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(__property_line2);
133 #if GTK_VERSION_GE(3,0)
134  Pango::FontDescription font2("sans 10");
135 #else
136  Glib::RefPtr<Gtk::Style> style = widget.get_style();
137  Pango::FontDescription font2 = style->get_font();
138 #endif
139 
140  font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
141  layout2->set_font_description(font2);
142  Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
143  layout2->set_ellipsize(Pango::ELLIPSIZE_END);
144 
145  line2_height = property_ypad() * 2 + rect2.get_height();
146  } else {
147  line2_height = 0;
148  }
149 
150  if (width) *width = line1_width;
151  if (height) *height = line1_height + 4 + line2_height;
152 #endif
153 }
154 
155 #if GTK_VERSION_GE(3,0)
156 /** Get required size for cell.
157  * @param widget widget
158  * @param minimum_width upon return contains the required width of the cell
159  * @param natural_width upon return contains the required width of the cell
160  */
161 void
162 TwoLinesCellRenderer::get_preferred_width_vfunc(Gtk::Widget &widget,
163  int &minimum_width,
164  int &natural_width) const
165 {
166  int width = 0;
167  get_size(widget, &width, NULL);
168  minimum_width = natural_width = width;
169 }
170 
171 /** Get required size for cell.
172  * @param widget widget
173  * @param minimum_height upon return contains the required height of the cell
174  * @param natural_height upon return contains the required height of the cell
175  */
176 void
177 TwoLinesCellRenderer::get_preferred_height_vfunc(Gtk::Widget &widget,
178  int &minimum_height,
179  int &natural_height) const
180 {
181  int height = 0;
182  get_size(widget, NULL, &height);
183  minimum_height = natural_height = height;
184 }
185 #endif
186 
187 #if GTK_VERSION_GE(3,0)
188 /** Render the cell.
189  * This is called to render the cell.
190  * @param cr graphic context to use for drawing
191  * @param widget widget
192  * @param background_area dimensions of the background area
193  * @param cell_area dimensions of the cell area
194  * @param flags render flags
195  */
196 void
197 TwoLinesCellRenderer::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
198  Gtk::Widget &widget,
199  const Gdk::Rectangle &background_area,
200  const Gdk::Rectangle &cell_area,
201  Gtk::CellRendererState flags)
202 #else
203 /** Render the cell.
204  * This is called to render the cell.
205  * @param window window
206  * @param widget widget
207  * @param background_area dimensions of the background area
208  * @param cell_area dimensions of the cell area
209  * @param expose_area dimensions of the exposed area
210  * @param flags render flags
211  */
212 void
213 TwoLinesCellRenderer::render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window,
214  Gtk::Widget &widget,
215  const Gdk::Rectangle &background_area,
216  const Gdk::Rectangle &cell_area,
217  const Gdk::Rectangle &expose_area,
218  Gtk::CellRendererState flags)
219 #endif
220 {
221 #ifdef GLIBMM_PROPERTIES_ENABLED
222  // Get cell size
223  int x_offset = 0, y_offset = 0;
224 #if GTK_VERSION_LT(3,0)
225  int width = 0, height = 0;
226  get_size(widget, cell_area, x_offset, y_offset, width, height);
227 
228  // Get cell state
229  //Gtk::StateType state;
230  Gtk::StateType text_state;
231  if ((flags & Gtk::CELL_RENDERER_SELECTED) != 0) {
232  //state = Gtk::STATE_SELECTED;
233  text_state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
234  } else {
235  //state = Gtk::STATE_NORMAL;
236  text_state = (widget.is_sensitive()) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
237  }
238 
239  // Draw color text
240  Glib::RefPtr<Gdk::Window> win =
241  Glib::RefPtr<Gdk::Window>::cast_dynamic(window);
242 #endif
243  Glib::RefPtr<Pango::Layout> layout_ptr =
244  widget.create_pango_layout(__property_line1);
245  Pango::Rectangle rect1 = layout_ptr->get_pixel_logical_extents();
246 #if GTK_VERSION_GE(3,0)
247  Glib::RefPtr<Gtk::StyleContext> stylecontext = widget.get_style_context();
248  Gdk::RGBA c = stylecontext->get_color(Gtk::STATE_FLAG_NORMAL);
249 
250  cr->set_source_rgba(c.get_red(), c.get_green(), c.get_blue(), c.get_alpha());
251  cr->move_to(cell_area.get_x() + x_offset + 2 * property_xpad(),
252  cell_area.get_y() + y_offset + 2 * property_ypad());
253  layout_ptr->show_in_cairo_context(cr);
254 #else
255  widget.get_style()->paint_layout(win, text_state, true, cell_area,
256  widget, "cellrenderertext",
257  cell_area.get_x() + x_offset + 2 * property_xpad(),
258  cell_area.get_y() + y_offset + 2 * property_ypad(),
259  layout_ptr);
260 #endif
261 
262  if (__property_line2_enabled.get_value()) {
263  Glib::RefPtr<Pango::Layout> layout2 =
264  widget.create_pango_layout(__property_line2);
265 #if GTK_VERSION_GE(3,0)
266  Pango::FontDescription font2("sans 10");
267 #else
268  Glib::RefPtr<Gtk::Style> style = widget.get_style();
269  Pango::FontDescription font2 = style->get_font();
270 #endif
271  font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
272  layout2->set_font_description(font2);
273  //Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
274  layout2->set_ellipsize(Pango::ELLIPSIZE_END);
275  layout2->set_width((cell_area.get_width() - property_xpad()) * Pango::SCALE);
276 
277 #if GTK_VERSION_GE(3,0)
278  cr->move_to(cell_area.get_x() + x_offset + property_xpad(),
279  cell_area.get_y() + y_offset + property_ypad() +
280  rect1.get_height() + 4);
281  layout2->show_in_cairo_context(cr);
282 #else
283  widget.get_style()->paint_layout (win, text_state, true, cell_area,
284  widget, "cellrenderertext",
285  cell_area.get_x() + x_offset + property_xpad(),
286  cell_area.get_y() + y_offset + property_ypad() + rect1.get_height() + 4,
287  layout2);
288 #endif
289  }
290 #endif
291 }
292 
293 
294 } // end namespace fawkes
Gtk cell renderer for two lines of text in a cell.
Fawkes library namespace.
virtual void render_vfunc(const Glib::RefPtr< Gdk::Drawable > &window, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, const Gdk::Rectangle &expose_area, Gtk::CellRendererState flags)
Render the cell.
virtual ~TwoLinesCellRenderer()
Destructor.
virtual void get_size_vfunc(Gtk::Widget &widget, const Gdk::Rectangle *cell_area, int *x_offset, int *y_offset, int *width, int *height) const
Get required size for cell.