OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/views/widget/gtk_views_fixed.h" | |
6 | |
7 #include "base/logging.h" | |
8 | |
9 // We store whether we use the widget's allocated size as a property. Ideally | |
10 // we would stash this in GtkFixedChild, but GtkFixed doesn't allow subclassing | |
11 // gtk_fixed_put. Alternatively we could subclass GtkContainer and use our own | |
12 // API (effectively duplicating GtkFixed), but that means folks could no longer | |
13 // use the GtkFixed API else where in Chrome. For now I'm going with this route. | |
14 static const char* kUseAllocatedSize = "__VIEWS_USE_ALLOCATED_SIZE__"; | |
15 static const char* kRequisitionWidth = "__VIEWS_REQUISITION_WIDTH__"; | |
16 static const char* kRequisitionHeight = "__VIEWS_REQUISITION_HEIGHT__"; | |
17 | |
18 G_BEGIN_DECLS | |
19 | |
20 G_DEFINE_TYPE(GtkViewsFixed, gtk_views_fixed, GTK_TYPE_FIXED) | |
21 | |
22 static void gtk_views_fixed_size_allocate(GtkWidget* widget, | |
23 GtkAllocation* allocation) { | |
24 widget->allocation = *allocation; | |
25 if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) { | |
26 gdk_window_move_resize(widget->window, allocation->x, allocation->y, | |
27 allocation->width, allocation->height); | |
28 } | |
29 | |
30 int border_width = GTK_CONTAINER(widget)->border_width; | |
31 GList* children = GTK_FIXED(widget)->children; | |
32 while (children) { | |
33 GtkFixedChild* child = reinterpret_cast<GtkFixedChild*>(children->data); | |
34 children = children->next; | |
35 | |
36 if (GTK_WIDGET_VISIBLE(child->widget)) { | |
37 GtkAllocation child_allocation; | |
38 | |
39 int width, height; | |
40 bool use_allocated_size = | |
41 gtk_views_fixed_get_widget_size(child->widget, &width, &height); | |
42 if (use_allocated_size) { | |
43 // NOTE: even though the size isn't changing, we have to call | |
44 // size_allocate, otherwise things like buttons won't repaint. | |
45 child_allocation.width = width; | |
46 child_allocation.height = height; | |
47 } else { | |
48 GtkRequisition child_requisition; | |
49 gtk_widget_get_child_requisition(child->widget, &child_requisition); | |
50 child_allocation.width = child_requisition.width; | |
51 child_allocation.height = child_requisition.height; | |
52 } | |
53 child_allocation.x = child->x + border_width; | |
54 child_allocation.y = child->y + border_width; | |
55 | |
56 if (GTK_WIDGET_NO_WINDOW(widget)) { | |
57 child_allocation.x += widget->allocation.x; | |
58 child_allocation.y += widget->allocation.y; | |
59 } | |
60 | |
61 gtk_widget_size_allocate(child->widget, &child_allocation); | |
62 } | |
63 } | |
64 } | |
65 | |
66 static void gtk_views_fixed_class_init(GtkViewsFixedClass* views_fixed_class) { | |
67 GtkWidgetClass* widget_class = | |
68 reinterpret_cast<GtkWidgetClass*>(views_fixed_class); | |
69 widget_class->size_allocate = gtk_views_fixed_size_allocate; | |
70 } | |
71 | |
72 static void gtk_views_fixed_init(GtkViewsFixed* fixed) { | |
73 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(fixed), GTK_CAN_FOCUS); | |
74 } | |
75 | |
76 GtkWidget* gtk_views_fixed_new(void) { | |
77 return GTK_WIDGET(g_object_new(GTK_TYPE_VIEWS_FIXED, NULL)); | |
78 } | |
79 | |
80 void gtk_views_fixed_set_widget_size(GtkWidget* widget, | |
81 int width, int height) { | |
82 // Remember the allocation request, and set this widget up to use it. | |
83 bool use_requested_size = (width != 0 && height != 0); | |
84 g_object_set_data(G_OBJECT(widget), kUseAllocatedSize, | |
85 reinterpret_cast<gpointer>(use_requested_size ? 1 : 0)); | |
86 g_object_set_data(G_OBJECT(widget), kRequisitionWidth, | |
87 reinterpret_cast<gpointer>(width)); | |
88 g_object_set_data(G_OBJECT(widget), kRequisitionHeight, | |
89 reinterpret_cast<gpointer>(height)); | |
90 | |
91 gtk_widget_queue_resize(widget); | |
92 } | |
93 | |
94 bool gtk_views_fixed_get_widget_size(GtkWidget* widget, | |
95 int* width, int* height) { | |
96 DCHECK(width); | |
97 DCHECK(height); | |
98 *width = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget), | |
99 kRequisitionWidth)); | |
100 *height = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget), | |
101 kRequisitionHeight)); | |
102 return (g_object_get_data(G_OBJECT(widget), kUseAllocatedSize) != 0); | |
103 } | |
104 | |
105 G_END_DECLS | |
OLD | NEW |