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 <algorithm>
27 #include <cstdio>
28 #include <cstring>
29 #include <glib-object.h>
30 #include <gtkmm.h>
31 
32 namespace fawkes {
33 
34 /** @class TwoLinesCellRenderer <gui_utils/twolines_cellrenderer.h>
35  * Gtk cell renderer for two lines of text in a cell.
36  * This cell renderer allows you to have two lines of text in a single
37  * cell. It works by getting the text via two properties. The first line is
38  * the primary line and printed "normally". The second line is the secondary
39  * line and printed with a slightly smaller font.
40  * @author Tim Niemueller
41  */
42 
43 /** Constructor. */
45 : Glib::ObjectBase(typeid(TwoLinesCellRenderer)),
46  Gtk::CellRenderer()
47 #ifdef GLIBMM_PROPERTIES_ENABLED
48  ,
49  property_line1_(*this, "line1", ""),
50  property_line2_(*this, "line2", ""),
51  property_line2_enabled_(*this, "line2_enabled", true)
52 #endif
53 {
54 }
55 
56 /** Destructor. */
58 {
59 }
60 
61 #ifdef GLIBMM_PROPERTIES_ENABLED
62 /** Get property proxy for first line.
63  * @return property proxy for first line
64  */
65 Glib::PropertyProxy<Glib::ustring>
66 TwoLinesCellRenderer::property_line1()
67 {
68  return property_line1_.get_proxy();
69 }
70 
71 /** Get property proxy for second line.
72  * @return property proxy for second line
73  */
74 Glib::PropertyProxy<Glib::ustring>
75 TwoLinesCellRenderer::property_line2()
76 {
77  return property_line2_.get_proxy();
78 }
79 
80 /** Get property proxy that indicates whether the second line is enabled.
81  * @return property proxy that indicates whether the second line is enabled
82  */
83 Glib::PropertyProxy<bool>
84 TwoLinesCellRenderer::property_line2_enabled()
85 {
86  return property_line2_enabled_.get_proxy();
87 }
88 #endif
89 
90 #if GTK_VERSION_GE(3, 0)
91 /** Get required size for widget.
92  * @param widget widget to create Pango layouts from
93  * @param width upon return contains the required width
94  * @param height upon return contains the required height
95  */
96 void
97 TwoLinesCellRenderer::get_size(Gtk::Widget &widget, int *width, int *height) const
98 #else
99 /** Get required size for cell.
100  * @param widget widget
101  * @param cell_area area of the cell
102  * @param x_offset ignored
103  * @param y_offset ignored
104  * @param width upon return contains the required width of the cell
105  * @param height upon return contains the required height of the cell
106  */
107 void
109  const Gdk::Rectangle *cell_area,
110  int * x_offset,
111  int * y_offset,
112  int * width,
113  int * height) const
114 #endif
115 {
116 #ifdef GLIBMM_PROPERTIES_ENABLED
117  // Compute text width
118  Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(property_line1_);
119  Pango::Rectangle rect = layout_ptr->get_pixel_logical_extents();
120 
121  int line1_width = property_xpad() * 2 + rect.get_width();
122  int line1_height = property_ypad() * 2 + rect.get_height();
123  int line2_height;
124 
125  if (property_line2_enabled_.get_value()) {
126  Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(property_line2_);
127 # if GTK_VERSION_GE(3, 0)
128  Pango::FontDescription font2("sans 10");
129 # else
130  Glib::RefPtr<Gtk::Style> style = widget.get_style();
131  Pango::FontDescription font2 = style->get_font();
132 # endif
133 
134  font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
135  layout2->set_font_description(font2);
136  Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
137  layout2->set_ellipsize(Pango::ELLIPSIZE_END);
138 
139  line2_height = property_ypad() * 2 + rect2.get_height();
140  } else {
141  line2_height = 0;
142  }
143 
144  if (width)
145  *width = line1_width;
146  if (height)
147  *height = line1_height + 4 + line2_height;
148 #endif
149 }
150 
151 #if GTK_VERSION_GE(3, 0)
152 /** Get required size for cell.
153  * @param widget widget
154  * @param minimum_width upon return contains the required width of the cell
155  * @param natural_width upon return contains the required width of the cell
156  */
157 void
158 TwoLinesCellRenderer::get_preferred_width_vfunc(Gtk::Widget &widget,
159  int & minimum_width,
160  int & natural_width) const
161 {
162  int width = 0;
163  get_size(widget, &width, NULL);
164  minimum_width = natural_width = width;
165 }
166 
167 /** Get required size for cell.
168  * @param widget widget
169  * @param minimum_height upon return contains the required height of the cell
170  * @param natural_height upon return contains the required height of the cell
171  */
172 void
173 TwoLinesCellRenderer::get_preferred_height_vfunc(Gtk::Widget &widget,
174  int & minimum_height,
175  int & natural_height) const
176 {
177  int height = 0;
178  get_size(widget, NULL, &height);
179  minimum_height = natural_height = height;
180 }
181 #endif
182 
183 #if GTK_VERSION_GE(3, 0)
184 /** Render the cell.
185  * This is called to render the cell.
186  * @param cr graphic context to use for drawing
187  * @param widget widget
188  * @param background_area dimensions of the background area
189  * @param cell_area dimensions of the cell area
190  * @param flags render flags
191  */
192 void
193 TwoLinesCellRenderer::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
194  Gtk::Widget & widget,
195  const Gdk::Rectangle & background_area,
196  const Gdk::Rectangle & cell_area,
197  Gtk::CellRendererState flags)
198 #else
199 /** Render the cell.
200  * This is called to render the cell.
201  * @param window window
202  * @param widget widget
203  * @param background_area dimensions of the background area
204  * @param cell_area dimensions of the cell area
205  * @param expose_area dimensions of the exposed area
206  * @param flags render flags
207  */
208 void
209 TwoLinesCellRenderer::render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window,
210  Gtk::Widget & widget,
211  const Gdk::Rectangle & background_area,
212  const Gdk::Rectangle & cell_area,
213  const Gdk::Rectangle & expose_area,
214  Gtk::CellRendererState flags)
215 #endif
216 {
217 #ifdef GLIBMM_PROPERTIES_ENABLED
218  // Get cell size
219  int x_offset = 0, y_offset = 0;
220 # if GTK_VERSION_LT(3, 0)
221  int width = 0, height = 0;
222  get_size(widget, cell_area, x_offset, y_offset, width, height);
223 
224  // Get cell state
225  //Gtk::StateType state;
226  Gtk::StateType text_state;
227  if ((flags & Gtk::CELL_RENDERER_SELECTED) != 0) {
228  //state = Gtk::STATE_SELECTED;
229  text_state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
230  } else {
231  //state = Gtk::STATE_NORMAL;
232  text_state = (widget.is_sensitive()) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
233  }
234 
235  // Draw color text
236  Glib::RefPtr<Gdk::Window> win = Glib::RefPtr<Gdk::Window>::cast_dynamic(window);
237 # endif
238  Glib::RefPtr<Pango::Layout> layout_ptr = widget.create_pango_layout(property_line1_);
239  Pango::Rectangle rect1 = layout_ptr->get_pixel_logical_extents();
240 # if GTK_VERSION_GE(3, 0)
241  Glib::RefPtr<Gtk::StyleContext> stylecontext = widget.get_style_context();
242  Gdk::RGBA c = stylecontext->get_color(Gtk::STATE_FLAG_NORMAL);
243 
244  cr->set_source_rgba(c.get_red(), c.get_green(), c.get_blue(), c.get_alpha());
245  cr->move_to(cell_area.get_x() + x_offset + 2 * property_xpad(),
246  cell_area.get_y() + y_offset + 2 * property_ypad());
247  layout_ptr->show_in_cairo_context(cr);
248 # else
249  widget.get_style()->paint_layout(win,
250  text_state,
251  true,
252  cell_area,
253  widget,
254  "cellrenderertext",
255  cell_area.get_x() + x_offset + 2 * property_xpad(),
256  cell_area.get_y() + y_offset + 2 * property_ypad(),
257  layout_ptr);
258 # endif
259 
260  if (property_line2_enabled_.get_value()) {
261  Glib::RefPtr<Pango::Layout> layout2 = widget.create_pango_layout(property_line2_);
262 # if GTK_VERSION_GE(3, 0)
263  Pango::FontDescription font2("sans 10");
264 # else
265  Glib::RefPtr<Gtk::Style> style = widget.get_style();
266  Pango::FontDescription font2 = style->get_font();
267 # endif
268  font2.set_size((int)roundf(Pango::SCALE_SMALL * font2.get_size()));
269  layout2->set_font_description(font2);
270  //Pango::Rectangle rect2 = layout2->get_pixel_logical_extents();
271  layout2->set_ellipsize(Pango::ELLIPSIZE_END);
272  layout2->set_width((cell_area.get_width() - property_xpad()) * Pango::SCALE);
273 
274 # if GTK_VERSION_GE(3, 0)
275  cr->move_to(cell_area.get_x() + x_offset + property_xpad(),
276  cell_area.get_y() + y_offset + property_ypad() + rect1.get_height() + 4);
277  layout2->show_in_cairo_context(cr);
278 # else
279  widget.get_style()->paint_layout(win,
280  text_state,
281  true,
282  cell_area,
283  widget,
284  "cellrenderertext",
285  cell_area.get_x() + x_offset + property_xpad(),
286  cell_area.get_y() + y_offset + property_ypad()
287  + rect1.get_height() + 4,
288  layout2);
289 # endif
290  }
291 #endif
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.