Back to index

lightning-sunbird  0.9+nobinonly
mozcontainer.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is mozilla.org code.
00018  *
00019  * The Initial Developer of the Original Code is Christopher Blizzard
00020  * <blizzard@mozilla.org>.  Portions created by the Initial Developer
00021  * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "mozcontainer.h"
00040 #include <gtk/gtkprivate.h>
00041 #include <stdio.h>
00042 
00043 /* init methods */
00044 static void moz_container_class_init          (MozContainerClass *klass);
00045 static void moz_container_init                (MozContainer      *container);
00046 
00047 /* widget class methods */
00048 static void moz_container_map                 (GtkWidget         *widget);
00049 static void moz_container_unmap               (GtkWidget         *widget);
00050 static void moz_container_realize             (GtkWidget         *widget);
00051 static void moz_container_size_allocate       (GtkWidget         *widget,
00052                                                GtkAllocation     *allocation);
00053 
00054 /* container class methods */
00055 static void moz_container_remove      (GtkContainer      *container,
00056                                        GtkWidget         *child_widget);
00057 static void moz_container_forall      (GtkContainer      *container,
00058                                        gboolean           include_internals,
00059                                        GtkCallback        callback,
00060                                        gpointer           callback_data);
00061 static void moz_container_add         (GtkContainer      *container,
00062                                         GtkWidget        *widget);
00063 
00064 typedef struct _MozContainerChild MozContainerChild;
00065 
00066 struct _MozContainerChild {
00067     GtkWidget *widget;
00068     gint x;
00069     gint y;
00070 };
00071 
00072 static void moz_container_allocate_child (MozContainer      *container,
00073                                           MozContainerChild *child);
00074 static MozContainerChild *
00075 moz_container_get_child (MozContainer *container, GtkWidget *child);
00076 
00077 static GtkContainerClass *parent_class = NULL;
00078 
00079 /* public methods */
00080 
00081 GtkType
00082 moz_container_get_type(void)
00083 {
00084     static GtkType moz_container_type = 0;
00085 
00086     if (!moz_container_type) {
00087         static GTypeInfo moz_container_info = {
00088             sizeof(MozContainerClass), /* class_size */
00089             NULL, /* base_init */
00090             NULL, /* base_finalize */
00091             (GClassInitFunc) moz_container_class_init, /* class_init */
00092             NULL, /* class_destroy */
00093             NULL, /* class_data */
00094             sizeof(MozContainer), /* instance_size */
00095             0, /* n_preallocs */
00096             (GInstanceInitFunc) moz_container_init, /* instance_init */
00097             NULL, /* value_table */
00098         };
00099 
00100         moz_container_type = g_type_register_static (GTK_TYPE_CONTAINER,
00101                                                      "MozContainer",
00102                                                      &moz_container_info, 0);
00103     }
00104 
00105     return moz_container_type;
00106 }
00107 
00108 GtkWidget *
00109 moz_container_new (void)
00110 {
00111     MozContainer *container;
00112 
00113     container = gtk_type_new (MOZ_CONTAINER_TYPE);
00114 
00115     return GTK_WIDGET(container);
00116 }
00117 
00118 void
00119 moz_container_put (MozContainer *container, GtkWidget *child_widget,
00120                    gint x, gint y)
00121 {
00122     MozContainerChild *child;
00123 
00124     child = g_new (MozContainerChild, 1);
00125 
00126     child->widget = child_widget;
00127     child->x = x;
00128     child->y = y;
00129 
00130     /*  printf("moz_container_put %p %p %d %d\n", (void *)container,
00131         (void *)child_widget, x, y); */
00132 
00133     container->children = g_list_append (container->children, child);
00134 
00135     /* we assume that the caller of this function will have already set
00136        the parent GdkWindow because we can have many anonymous children. */
00137     gtk_widget_set_parent(child_widget, GTK_WIDGET(container));
00138 }
00139 
00140 void
00141 moz_container_move (MozContainer *container, GtkWidget *child_widget,
00142                     gint x, gint y, gint width, gint height)
00143 {
00144     MozContainerChild *child;
00145     GtkAllocation new_allocation;
00146 
00147     child = moz_container_get_child (container, child_widget);
00148 
00149     child->x = x;
00150     child->y = y;
00151 
00152     new_allocation.x = x;
00153     new_allocation.y = y;
00154     new_allocation.width = width;
00155     new_allocation.height = height;
00156 
00157     /* printf("moz_container_move %p %p will allocate to %d %d %d %d\n",
00158        (void *)container, (void *)child_widget,
00159        new_allocation.x, new_allocation.y,
00160        new_allocation.width, new_allocation.height); */
00161 
00162     gtk_widget_size_allocate(child_widget, &new_allocation);
00163 }
00164 
00165 /* This function updates the allocation on a child widget without
00166 causing a size_allocate event to be generated on that widget.  This
00167 should only be used for scrolling since it's assumed that the expose
00168 event created by the scroll will update any widgets that come into view. */
00169 
00170 void
00171 moz_container_scroll_update (MozContainer *container, GtkWidget *child_widget,
00172                              gint x, gint y)
00173 {
00174     MozContainerChild *child;
00175     GtkAllocation new_allocation;
00176 
00177     child = moz_container_get_child (container, child_widget);
00178 
00179     child->x = x;
00180     child->y = y;
00181 
00182     new_allocation.x = x;
00183     new_allocation.y = y;
00184     new_allocation.width = child_widget->allocation.width;
00185     new_allocation.height = child_widget->allocation.height;
00186 
00187     /* printf("moz_container_update %p %p will allocate to %d %d %d %d\n",
00188        (void *)container, (void *)child_widget,
00189        new_allocation.x, new_allocation.y,
00190        new_allocation.width, new_allocation.height); */
00191 
00192     gtk_widget_size_allocate(child_widget, &new_allocation);
00193 }
00194 
00195 /* static methods */
00196 
00197 void
00198 moz_container_class_init (MozContainerClass *klass)
00199 {
00200     /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
00201       GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
00202     GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
00203     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
00204 
00205     parent_class = g_type_class_peek_parent (klass);
00206 
00207     widget_class->map = moz_container_map;
00208     widget_class->unmap = moz_container_unmap;
00209     widget_class->realize = moz_container_realize;
00210     widget_class->size_allocate = moz_container_size_allocate;
00211 
00212     container_class->remove = moz_container_remove;
00213     container_class->forall = moz_container_forall;
00214     container_class->add = moz_container_add;
00215 }
00216 
00217 void
00218 moz_container_init (MozContainer *container)
00219 {
00220     GTK_WIDGET_SET_FLAGS(container, GTK_CAN_FOCUS);
00221     container->container.resize_mode = GTK_RESIZE_IMMEDIATE;
00222     gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container),
00223                                       FALSE);
00224 
00225     /* Mozilla uses the the gdbrgb colormap and visual throughout the
00226        backend so for widgets we just use that colormap instead of the
00227        default one. */
00228     gtk_widget_set_colormap(GTK_WIDGET(container), gdk_rgb_get_colormap());
00229 }
00230 
00231 void
00232 moz_container_map (GtkWidget *widget)
00233 {
00234     MozContainer *container;
00235     GList *tmp_list;
00236     GtkWidget *tmp_child;
00237 
00238     g_return_if_fail (IS_MOZ_CONTAINER(widget));
00239     container = MOZ_CONTAINER (widget);
00240 
00241     GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
00242 
00243     tmp_list = container->children;
00244     while (tmp_list) {
00245         tmp_child = ((MozContainerChild *)tmp_list->data)->widget;
00246     
00247         if (GTK_WIDGET_VISIBLE(tmp_child)) {
00248             if (!GTK_WIDGET_MAPPED(tmp_child))
00249                 gtk_widget_map(tmp_child);
00250         }
00251         tmp_list = tmp_list->next;
00252     }
00253 
00254     gdk_window_show (widget->window);
00255 }
00256 
00257 void
00258 moz_container_unmap (GtkWidget *widget)
00259 {
00260     MozContainer *container;
00261 
00262     g_return_if_fail (IS_MOZ_CONTAINER (widget));
00263     container = MOZ_CONTAINER (widget);
00264   
00265     GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
00266 
00267     gdk_window_hide (widget->window);
00268 }
00269 
00270 void
00271 moz_container_realize (GtkWidget *widget)
00272 {
00273     GdkWindowAttr attributes;
00274     gint attributes_mask = 0;
00275     MozContainer *container;
00276 
00277     g_return_if_fail(IS_MOZ_CONTAINER(widget));
00278 
00279     container = MOZ_CONTAINER(widget);
00280 
00281     GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
00282 
00283     /* create the shell window */
00284 
00285     attributes.event_mask = gtk_widget_get_events (widget);
00286     attributes.event_mask |=  (GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK);
00287     attributes.x = widget->allocation.x;
00288     attributes.y = widget->allocation.y;
00289     attributes.width = widget->allocation.width;
00290     attributes.height = widget->allocation.height;
00291     attributes.wclass = GDK_INPUT_OUTPUT;
00292     attributes.visual = gtk_widget_get_visual (widget);
00293     attributes.colormap = gtk_widget_get_colormap (widget);
00294     attributes.window_type = GDK_WINDOW_CHILD;
00295 
00296     attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP |
00297         GDK_WA_X | GDK_WA_Y;
00298 
00299     widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
00300                                      &attributes, attributes_mask);
00301     /*  printf("widget->window is %p\n", (void *)widget->window); */
00302     gdk_window_set_user_data (widget->window, container);
00303 
00304     widget->style = gtk_style_attach (widget->style, widget->window);
00305 
00306     /* set the back pixmap to None so that you don't end up with the gtk
00307        default which is BlackPixel */
00308     gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
00309 }
00310 
00311 void
00312 moz_container_size_allocate (GtkWidget     *widget,
00313                              GtkAllocation *allocation)
00314 {
00315     MozContainer   *container;
00316     GList          *tmp_list;
00317     GtkAllocation   tmp_allocation;
00318     GtkRequisition  tmp_requisition;
00319     GtkWidget      *tmp_child;
00320 
00321     g_return_if_fail (IS_MOZ_CONTAINER (widget));
00322 
00323     /*  printf("moz_container_size_allocate %p %d %d %d %d\n",
00324         (void *)widget,
00325         allocation->x,
00326         allocation->y,
00327         allocation->width,
00328         allocation->height); */
00329 
00330     /* short circuit if you can */
00331     container = MOZ_CONTAINER (widget);
00332     if (!container->children &&
00333         widget->allocation.x == allocation->x &&
00334         widget->allocation.y == allocation->y &&
00335         widget->allocation.width == allocation->width &&
00336         widget->allocation.height == allocation->height) {
00337         return;
00338     }
00339 
00340     widget->allocation = *allocation;
00341 
00342     tmp_list = container->children;
00343 
00344     while (tmp_list) {
00345         MozContainerChild *child = tmp_list->data;
00346 
00347         moz_container_allocate_child (container, child);
00348 
00349         tmp_list = tmp_list->next;
00350     }
00351 
00352     if (GTK_WIDGET_REALIZED (widget)) {
00353         gdk_window_move_resize(widget->window,
00354                                widget->allocation.x,
00355                                widget->allocation.y,
00356                                widget->allocation.width,
00357                                widget->allocation.height);
00358     }
00359 }
00360 
00361 void
00362 moz_container_remove (GtkContainer *container, GtkWidget *child_widget)
00363 {
00364     MozContainerChild *child;
00365     MozContainer *moz_container;
00366     GList *tmp_list;
00367 
00368     g_return_if_fail (IS_MOZ_CONTAINER(container));
00369     g_return_if_fail (GTK_IS_WIDGET(child_widget));
00370 
00371     moz_container = MOZ_CONTAINER(container);
00372 
00373     child = moz_container_get_child (moz_container, child_widget);
00374     g_return_if_fail (child);
00375 
00376     if(child->widget == child_widget) {
00377         gtk_widget_unparent(child_widget);
00378     }
00379 
00380     moz_container->children = g_list_remove(moz_container->children, child);
00381     g_free(child);
00382 }
00383 
00384 void
00385 moz_container_forall (GtkContainer *container, gboolean include_internals,
00386                       GtkCallback  callback, gpointer callback_data)
00387 {
00388     MozContainer *moz_container;
00389     GList *tmp_list;
00390   
00391     g_return_if_fail (IS_MOZ_CONTAINER(container));
00392     g_return_if_fail (callback != NULL);
00393 
00394     moz_container = MOZ_CONTAINER(container);
00395 
00396     tmp_list = moz_container->children;
00397     while (tmp_list) {
00398         MozContainerChild *child;
00399         child = tmp_list->data;
00400         tmp_list = tmp_list->next;
00401         (* callback) (child->widget, callback_data);
00402     }
00403 }
00404 
00405 static void
00406 moz_container_allocate_child (MozContainer *container,
00407                               MozContainerChild *child)
00408 {
00409     GtkAllocation  allocation;
00410     GtkRequisition requisition;
00411 
00412     allocation.x = child->x;
00413     allocation.y = child->y;
00414     /* gtk_widget_get_child_requisition (child->widget, &requisition); */
00415     /* gtk_widget_size_request (child->widget, &requisition); */
00416     allocation.width = child->widget->allocation.width;
00417     allocation.height = child->widget->allocation.height;
00418 
00419     gtk_widget_size_allocate (child->widget, &allocation);
00420 }
00421 
00422 MozContainerChild *
00423 moz_container_get_child (MozContainer *container, GtkWidget *child_widget)
00424 {
00425     GList *tmp_list;
00426 
00427     tmp_list = container->children;
00428     while (tmp_list) {
00429         MozContainerChild *child;
00430     
00431         child = tmp_list->data;
00432         tmp_list = tmp_list->next;
00433 
00434         if (child->widget == child_widget)
00435             return child;
00436     }
00437 
00438     return NULL;
00439 }
00440 
00441 static void 
00442 moz_container_add(GtkContainer *container, GtkWidget *widget)
00443 {
00444     moz_container_put(MOZ_CONTAINER(container), widget, 0, 0);
00445 }
00446