Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1312)

Unified Diff: chrome/browser/gtk/gtk_floating_container.cc

Issue 115835: Implement GtkFloatingContainer (Closed)
Patch Set: Cleanups Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/gtk/gtk_floating_container.h ('k') | chrome/browser/gtk/status_bubble_gtk.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/gtk/gtk_floating_container.cc
diff --git a/chrome/browser/gtk/gtk_floating_container.cc b/chrome/browser/gtk/gtk_floating_container.cc
new file mode 100644
index 0000000000000000000000000000000000000000..51f5e14ffff43e966145f4c54232746e07e89a7d
--- /dev/null
+++ b/chrome/browser/gtk/gtk_floating_container.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/gtk/gtk_floating_container.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
+#include <gtk/gtkmarshal.h>
+
+#include <algorithm>
+
+namespace {
+
+enum {
+ SET_FLOATING_POSITION,
+ LAST_SIGNAL
+};
+
+enum {
+ CHILD_PROP_0,
+ CHILD_PROP_X,
+ CHILD_PROP_Y
+};
+
+// Returns the GtkFloatingContainerChild associated with |widget| (or NULL if
+// |widget| not found).
+GtkFloatingContainerChild* GetChild(GtkFloatingContainer* container,
+ GtkWidget* widget) {
+ for (GList* floating_children = container->floating_children;
+ floating_children; floating_children = g_list_next(floating_children)) {
+ GtkFloatingContainerChild* child =
+ reinterpret_cast<GtkFloatingContainerChild*>(floating_children->data);
+
+ if (child->widget == widget)
+ return child;
+ }
+
+ return NULL;
+}
+
+} // namespace
+
+G_BEGIN_DECLS
+
+static void gtk_floating_container_remove(GtkContainer* container,
+ GtkWidget* widget);
+static void gtk_floating_container_forall(GtkContainer* container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_floating_container_size_request(GtkWidget* widget,
+ GtkRequisition* requisition);
+static void gtk_floating_container_size_allocate(GtkWidget* widget,
+ GtkAllocation* allocation);
+static void gtk_floating_container_set_child_property(GtkContainer* container,
+ GtkWidget* child,
+ guint property_id,
+ const GValue* value,
+ GParamSpec* pspec);
+static void gtk_floating_container_get_child_property(GtkContainer* container,
+ GtkWidget* child,
+ guint property_id,
+ GValue* value,
+ GParamSpec* pspec);
+
+static guint floating_container_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE(GtkFloatingContainer, gtk_floating_container, GTK_TYPE_BIN)
+
+static void gtk_floating_container_class_init(
+ GtkFloatingContainerClass *klass) {
+ GtkObjectClass* object_class =
+ reinterpret_cast<GtkObjectClass*>(klass);
+
+ GtkWidgetClass* widget_class =
+ reinterpret_cast<GtkWidgetClass*>(klass);
+ widget_class->size_request = gtk_floating_container_size_request;
+ widget_class->size_allocate = gtk_floating_container_size_allocate;
+
+ GtkContainerClass* container_class =
+ reinterpret_cast<GtkContainerClass*>(klass);
+ container_class->remove = gtk_floating_container_remove;
+ container_class->forall = gtk_floating_container_forall;
+
+ container_class->set_child_property =
+ gtk_floating_container_set_child_property;
+ container_class->get_child_property =
+ gtk_floating_container_get_child_property;
+
+ gtk_container_class_install_child_property(
+ container_class,
+ CHILD_PROP_X,
+ g_param_spec_int("x",
+ "X position",
+ "X position of child widget",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
+
+ gtk_container_class_install_child_property(
+ container_class,
+ CHILD_PROP_Y,
+ g_param_spec_int("y",
+ "Y position",
+ "Y position of child widget",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ static_cast<GParamFlags>(GTK_PARAM_READWRITE)));
+
+ floating_container_signals[SET_FLOATING_POSITION] =
+ g_signal_new("set-floating-position",
+ G_OBJECT_CLASS_TYPE(object_class),
+ static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST |
+ G_SIGNAL_ACTION),
+ NULL,
+ NULL, NULL,
+ gtk_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+static void gtk_floating_container_init(GtkFloatingContainer* container) {
+ GTK_WIDGET_SET_FLAGS(container, GTK_NO_WINDOW);
+
+ container->floating_children = NULL;
+}
+
+static void gtk_floating_container_remove(GtkContainer* container,
+ GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_WIDGET(widget));
+
+ GtkBin* bin = GTK_BIN(container);
+ if (bin->child == widget) {
+ ((GTK_CONTAINER_CLASS(gtk_floating_container_parent_class))->remove)
+ (container, widget);
+ } else {
+ // Handle the other case where it's in our |floating_children| list.
+ GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
+ GList* children = floating->floating_children;
+ gboolean removed_child = false;
+ while (children) {
+ GtkFloatingContainerChild* child =
+ reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+
+ if (child->widget == widget) {
+ removed_child = true;
+ gboolean was_visible = GTK_WIDGET_VISIBLE(widget);
+
+ gtk_widget_unparent(widget);
+
+ floating->floating_children =
+ g_list_remove_link(floating->floating_children, children);
+ g_list_free(children);
+ g_free(child);
+
+ if (was_visible && GTK_WIDGET_VISIBLE(container))
+ gtk_widget_queue_resize(GTK_WIDGET(container));
+
+ break;
+ }
+ children = children->next;
+ }
+
+ g_return_if_fail(removed_child);
+ }
+}
+
+static void gtk_floating_container_forall(GtkContainer* container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data) {
+ GtkBin *bin = GTK_BIN(container);
+
+ g_return_if_fail(callback != NULL);
+
+ if (bin->child)
+ (*callback)(bin->child, callback_data);
+
+ GtkFloatingContainer* floating = GTK_FLOATING_CONTAINER(container);
+ GList* children = floating->floating_children;
+ while (children) {
+ GtkFloatingContainerChild* child =
+ reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+ children = children->next;
+
+ (*callback)(child->widget, callback_data);
+ }
+}
+
+static void gtk_floating_container_size_request(GtkWidget* widget,
+ GtkRequisition* requisition) {
+ GtkBin *bin = GTK_BIN(widget);
+ if (bin && bin->child) {
+ gtk_widget_size_request(bin->child, requisition);
+ } else {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+}
+
+static void gtk_floating_container_size_allocate(GtkWidget* widget,
+ GtkAllocation* allocation) {
+ widget->allocation = *allocation;
+
+ if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) {
+ gdk_window_move_resize(widget->window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+ }
+
+ // Give the same allocation to our GtkBin component.
+ GtkBin* bin = GTK_BIN(widget);
+ if (bin->child) {
+ gtk_widget_size_allocate(bin->child, allocation);
+ }
+
+ // We need to give whoever is pulling our strings a chance to set the "x" and
+ // "y" properties on all of our children.
+ g_signal_emit(widget, floating_container_signals[SET_FLOATING_POSITION], 0,
+ allocation);
+
+ // Our allocation has been set. We've asked our controller to place the other
+ // widgets. Pass out allocations to all our children based on where they want
+ // to be.
+ GtkFloatingContainer* container = GTK_FLOATING_CONTAINER(widget);
+ GList* children = container->floating_children;
+ GtkAllocation child_allocation;
+ GtkRequisition child_requisition;
+ while (children) {
+ GtkFloatingContainerChild* child =
+ reinterpret_cast<GtkFloatingContainerChild*>(children->data);
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE(child->widget)) {
+ gtk_widget_size_request(child->widget, &child_requisition);
+ child_allocation.x = child->x;
+ child_allocation.y = child->y;
+ child_allocation.width = std::max(1, std::min(child_requisition.width,
+ allocation->width));
+ child_allocation.height = std::max(1, std::min(child_requisition.height,
+ allocation->height));
+ gtk_widget_size_allocate(child->widget, &child_allocation);
+ }
+ }
+}
+
+static void gtk_floating_container_set_child_property(GtkContainer* container,
+ GtkWidget* child,
+ guint property_id,
+ const GValue* value,
+ GParamSpec* pspec) {
+ GtkFloatingContainerChild* floating_child =
+ GetChild(GTK_FLOATING_CONTAINER(container), child);
+ g_return_if_fail(floating_child);
+
+ switch (property_id) {
+ case CHILD_PROP_X:
+ floating_child->x = g_value_get_int(value);
+ gtk_widget_child_notify(child, "x");
+ break;
+ case CHILD_PROP_Y:
+ floating_child->y = g_value_get_int(value);
+ gtk_widget_child_notify(child, "y");
+ break;
+ default:
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
+ container, property_id, pspec);
+ break;
+ };
+}
+
+static void gtk_floating_container_get_child_property(GtkContainer* container,
+ GtkWidget* child,
+ guint property_id,
+ GValue* value,
+ GParamSpec* pspec) {
+ GtkFloatingContainerChild* floating_child =
+ GetChild(GTK_FLOATING_CONTAINER(container), child);
+ g_return_if_fail(floating_child);
+
+ switch (property_id) {
+ case CHILD_PROP_X:
+ g_value_set_int(value, floating_child->x);
+ break;
+ case CHILD_PROP_Y:
+ g_value_set_int(value, floating_child->y);
+ break;
+ default:
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID(
+ container, property_id, pspec);
+ break;
+ };
+}
+
+GtkWidget* gtk_floating_container_new() {
+ return GTK_WIDGET(g_object_new(GTK_TYPE_FLOATING_CONTAINER, NULL));
+}
+
+void gtk_floating_container_add_floating(GtkFloatingContainer* container,
+ GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_FLOATING_CONTAINER(container));
+ g_return_if_fail(GTK_IS_WIDGET(widget));
+
+ GtkFloatingContainerChild* child_info = g_new(GtkFloatingContainerChild, 1);
+ child_info->widget = widget;
+ child_info->x = 0;
+ child_info->y = 0;
+
+ gtk_widget_set_parent(widget, GTK_WIDGET(container));
+
+ container->floating_children =
+ g_list_append(container->floating_children, child_info);
+}
+
+G_END_DECLS
« no previous file with comments | « chrome/browser/gtk/gtk_floating_container.h ('k') | chrome/browser/gtk/status_bubble_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698