bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / unx / gtk3 / customcellrenderer.cxx
blobc7c6661ed9123797c817d4eee12afda62ca90291
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <vcl/svapp.hxx>
11 #include "customcellrenderer.hxx"
12 #if !GTK_CHECK_VERSION(4, 0, 0)
13 #include <gtk/gtk-a11y.h>
14 #endif
16 namespace
18 struct _CustomCellRendererClass : public GtkCellRendererTextClass
22 enum
24 PROP_ID = 10000,
25 PROP_INSTANCE_TREE_VIEW = 10001
29 G_DEFINE_TYPE(CustomCellRenderer, custom_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
31 static void custom_cell_renderer_init(CustomCellRenderer* self)
34 SolarMutexGuard aGuard;
35 new (&self->device) VclPtr<VirtualDevice>;
38 // prevent loplugin:unreffun firing on macro generated function
39 (void)custom_cell_renderer_get_instance_private(self);
42 static void custom_cell_renderer_get_property(GObject* object, guint param_id, GValue* value,
43 GParamSpec* pspec)
45 CustomCellRenderer* cellsurface = CUSTOM_CELL_RENDERER(object);
47 switch (param_id)
49 case PROP_ID:
50 g_value_set_string(value, cellsurface->id);
51 break;
52 case PROP_INSTANCE_TREE_VIEW:
53 g_value_set_pointer(value, cellsurface->instance);
54 break;
55 default:
56 G_OBJECT_CLASS(custom_cell_renderer_parent_class)
57 ->get_property(object, param_id, value, pspec);
58 break;
62 static void custom_cell_renderer_set_property(GObject* object, guint param_id, const GValue* value,
63 GParamSpec* pspec)
65 CustomCellRenderer* cellsurface = CUSTOM_CELL_RENDERER(object);
67 switch (param_id)
69 case PROP_ID:
70 g_free(cellsurface->id);
71 cellsurface->id = g_value_dup_string(value);
72 break;
73 case PROP_INSTANCE_TREE_VIEW:
74 cellsurface->instance = g_value_get_pointer(value);
75 break;
76 default:
77 G_OBJECT_CLASS(custom_cell_renderer_parent_class)
78 ->set_property(object, param_id, value, pspec);
79 break;
83 static bool custom_cell_renderer_get_preferred_size(GtkCellRenderer* cell,
84 GtkOrientation orientation, gint* minimum_size,
85 gint* natural_size);
87 #if GTK_CHECK_VERSION(4, 0, 0)
88 static void custom_cell_renderer_snapshot(GtkCellRenderer* cell, GtkSnapshot* snapshot,
89 GtkWidget* widget, const GdkRectangle* background_area,
90 const GdkRectangle* cell_area,
91 GtkCellRendererState flags);
92 #endif
94 static void custom_cell_renderer_render(GtkCellRenderer* cell, cairo_t* cr, GtkWidget* widget,
95 const GdkRectangle* background_area,
96 const GdkRectangle* cell_area, GtkCellRendererState flags);
98 static void custom_cell_renderer_finalize(GObject* object)
100 CustomCellRenderer* cellsurface = CUSTOM_CELL_RENDERER(object);
102 g_free(cellsurface->id);
105 SolarMutexGuard aGuard;
106 cellsurface->device.disposeAndClear();
107 cellsurface->device.~VclPtr<VirtualDevice>();
110 G_OBJECT_CLASS(custom_cell_renderer_parent_class)->finalize(object);
113 static void custom_cell_renderer_get_preferred_width(GtkCellRenderer* cell, GtkWidget* widget,
114 gint* minimum_size, gint* natural_size)
116 if (!custom_cell_renderer_get_preferred_size(cell, GTK_ORIENTATION_HORIZONTAL, minimum_size,
117 natural_size))
119 // fallback to parent if we're empty
120 GTK_CELL_RENDERER_CLASS(custom_cell_renderer_parent_class)
121 ->get_preferred_width(cell, widget, minimum_size, natural_size);
125 static void custom_cell_renderer_get_preferred_height(GtkCellRenderer* cell, GtkWidget* widget,
126 gint* minimum_size, gint* natural_size)
128 if (!custom_cell_renderer_get_preferred_size(cell, GTK_ORIENTATION_VERTICAL, minimum_size,
129 natural_size))
131 // fallback to parent if we're empty
132 GTK_CELL_RENDERER_CLASS(custom_cell_renderer_parent_class)
133 ->get_preferred_height(cell, widget, minimum_size, natural_size);
137 static void custom_cell_renderer_get_preferred_height_for_width(GtkCellRenderer* cell,
138 GtkWidget* widget, gint /*width*/,
139 gint* minimum_height,
140 gint* natural_height)
142 gtk_cell_renderer_get_preferred_height(cell, widget, minimum_height, natural_height);
145 static void custom_cell_renderer_get_preferred_width_for_height(GtkCellRenderer* cell,
146 GtkWidget* widget, gint /*height*/,
147 gint* minimum_width,
148 gint* natural_width)
150 gtk_cell_renderer_get_preferred_width(cell, widget, minimum_width, natural_width);
153 void custom_cell_renderer_class_init(CustomCellRendererClass* klass)
155 GtkCellRendererClass* cell_class = GTK_CELL_RENDERER_CLASS(klass);
156 GObjectClass* object_class = G_OBJECT_CLASS(klass);
158 /* Hook up functions to set and get our custom cell renderer properties */
159 object_class->get_property = custom_cell_renderer_get_property;
160 object_class->set_property = custom_cell_renderer_set_property;
162 custom_cell_renderer_parent_class = g_type_class_peek_parent(klass);
163 object_class->finalize = custom_cell_renderer_finalize;
165 cell_class->get_preferred_width = custom_cell_renderer_get_preferred_width;
166 cell_class->get_preferred_height = custom_cell_renderer_get_preferred_height;
167 cell_class->get_preferred_width_for_height
168 = custom_cell_renderer_get_preferred_width_for_height;
169 cell_class->get_preferred_height_for_width
170 = custom_cell_renderer_get_preferred_height_for_width;
172 #if GTK_CHECK_VERSION(4, 0, 0)
173 cell_class->snapshot = custom_cell_renderer_snapshot;
174 #else
175 cell_class->render = custom_cell_renderer_render;
176 #endif
178 g_object_class_install_property(
179 object_class, PROP_ID,
180 g_param_spec_string("id", "ID", "The ID of the custom data", nullptr, G_PARAM_READWRITE));
182 g_object_class_install_property(
183 object_class, PROP_INSTANCE_TREE_VIEW,
184 g_param_spec_pointer("instance", "Instance", "The GtkInstanceTreeView", G_PARAM_READWRITE));
186 #if !GTK_CHECK_VERSION(4, 0, 0)
187 gtk_cell_renderer_class_set_accessible_type(cell_class, GTK_TYPE_TEXT_CELL_ACCESSIBLE);
188 #endif
191 GtkCellRenderer* custom_cell_renderer_new()
193 return GTK_CELL_RENDERER(g_object_new(CUSTOM_TYPE_CELL_RENDERER, nullptr));
196 bool custom_cell_renderer_get_preferred_size(GtkCellRenderer* cell, GtkOrientation orientation,
197 gint* minimum_size, gint* natural_size)
199 GValue value = G_VALUE_INIT;
200 g_value_init(&value, G_TYPE_STRING);
201 g_object_get_property(G_OBJECT(cell), "id", &value);
203 const char* pStr = g_value_get_string(&value);
205 OUString sId(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
207 value = G_VALUE_INIT;
208 g_value_init(&value, G_TYPE_POINTER);
209 g_object_get_property(G_OBJECT(cell), "instance", &value);
211 CustomCellRenderer* cellsurface = CUSTOM_CELL_RENDERER(cell);
213 Size aSize;
215 gpointer pWidget = g_value_get_pointer(&value);
216 if (pWidget)
218 SolarMutexGuard aGuard;
219 custom_cell_renderer_ensure_device(cellsurface, pWidget);
220 aSize = custom_cell_renderer_get_size(*cellsurface->device, sId, pWidget);
223 if (orientation == GTK_ORIENTATION_HORIZONTAL)
225 if (minimum_size)
226 *minimum_size = aSize.Width();
228 if (natural_size)
229 *natural_size = aSize.Width();
231 else
233 if (minimum_size)
234 *minimum_size = aSize.Height();
236 if (natural_size)
237 *natural_size = aSize.Height();
240 return true;
243 void custom_cell_renderer_render(GtkCellRenderer* cell, cairo_t* cr, GtkWidget* /*widget*/,
244 const GdkRectangle* /*background_area*/,
245 const GdkRectangle* cell_area, GtkCellRendererState flags)
247 GValue value = G_VALUE_INIT;
248 g_value_init(&value, G_TYPE_STRING);
249 g_object_get_property(G_OBJECT(cell), "id", &value);
251 const char* pStr = g_value_get_string(&value);
252 OUString sId(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
254 value = G_VALUE_INIT;
255 g_value_init(&value, G_TYPE_POINTER);
256 g_object_get_property(G_OBJECT(cell), "instance", &value);
258 CustomCellRenderer* cellsurface = CUSTOM_CELL_RENDERER(cell);
260 gpointer pWidget = g_value_get_pointer(&value);
261 if (!pWidget)
262 return;
264 SolarMutexGuard aGuard;
266 custom_cell_renderer_ensure_device(cellsurface, pWidget);
268 Size aSize(cell_area->width, cell_area->height);
269 // false to not bother setting the bg on resize as we'll do that
270 // ourself via cairo
271 cellsurface->device->SetOutputSizePixel(aSize, false);
273 cairo_surface_t* pSurface = get_underlying_cairo_surface(*cellsurface->device);
275 // fill surface as transparent so it can be blended with the potentially
276 // selected background
277 cairo_t* tempcr = cairo_create(pSurface);
278 cairo_set_source_rgba(tempcr, 0, 0, 0, 0);
279 cairo_set_operator(tempcr, CAIRO_OPERATOR_SOURCE);
280 cairo_paint(tempcr);
281 cairo_destroy(tempcr);
282 cairo_surface_flush(pSurface);
284 custom_cell_renderer_render(*cellsurface->device, tools::Rectangle(Point(0, 0), aSize),
285 static_cast<bool>(flags & GTK_CELL_RENDERER_SELECTED), sId,
286 pWidget);
288 cairo_surface_mark_dirty(pSurface);
290 cairo_set_source_surface(cr, pSurface, cell_area->x, cell_area->y);
291 cairo_paint(cr);
294 #if GTK_CHECK_VERSION(4, 0, 0)
295 static void custom_cell_renderer_snapshot(GtkCellRenderer* cell, GtkSnapshot* snapshot,
296 GtkWidget* widget, const GdkRectangle* background_area,
297 const GdkRectangle* cell_area, GtkCellRendererState flags)
299 graphene_rect_t rect = GRAPHENE_RECT_INIT(
300 static_cast<float>(cell_area->x), static_cast<float>(cell_area->y),
301 static_cast<float>(cell_area->width), static_cast<float>(cell_area->height));
302 cairo_t* cr = gtk_snapshot_append_cairo(GTK_SNAPSHOT(snapshot), &rect);
303 custom_cell_renderer_render(cell, cr, widget, background_area, cell_area, flags);
304 cairo_destroy(cr);
307 #endif
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */