aboutsummaryrefslogblamecommitdiffstats
path: root/lib/widgets/gedit-overlay-child.c
blob: deb94253308054ebd2ffa4090bd9e9bf15d65679 (plain) (tree)





























                                                                             






                      
                   






















                                                                        

























                                                                                   






























































































































































                                                                                                







































































































                                                                                                   
                       
/*
 * gedit-overlay-child.c
 * This file is part of gedit
 *
 * Copyright (C) 2011 - Ignacio Casal Quinteiro
 *
 * gedit is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * gedit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gedit-overlay-child.h"
#include "gedit-enum-types.h"

struct _GeditOverlayChildPrivate
{
    GtkWidget                *widget;
    GtkAllocation             widget_alloc;
    GeditOverlayChildPosition position;
    guint                     offset;
};

enum
{
    PROP_0,
    PROP_WIDGET,
    PROP_POSITION,
    PROP_OFFSET
};

G_DEFINE_TYPE (GeditOverlayChild, gedit_overlay_child, GTK_TYPE_BIN)

static void
gedit_overlay_child_get_property (GObject    *object,
                                  guint       prop_id,
                                  GValue     *value,
                                  GParamSpec *pspec)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (object);

    switch (prop_id)
    {
        case PROP_WIDGET:
            g_value_set_object (value, child->priv->widget);
            break;
        case PROP_POSITION:
            g_value_set_enum (value, child->priv->position);
            break;
        case PROP_OFFSET:
            g_value_set_uint (value, child->priv->offset);
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void
gedit_overlay_child_set_property (GObject      *object,
                                  guint         prop_id,
                                  const GValue *value,
                                  GParamSpec   *pspec)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (object);

    switch (prop_id)
    {
        case PROP_WIDGET:
            gtk_container_add (GTK_CONTAINER (child),
                               g_value_get_object (value));
            break;
        case PROP_POSITION:
            child->priv->position = g_value_get_enum (value);
            break;
        case PROP_OFFSET:
            child->priv->offset = g_value_get_uint (value);
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void
gedit_overlay_child_realize (GtkWidget *widget)
{
    GdkWindowAttr attributes;
    GdkWindow *parent_window;
    GdkWindow *window;
    GtkStyleContext *context;

    gtk_widget_set_realized (widget, TRUE);

    parent_window = gtk_widget_get_parent_window (widget);
    context = gtk_widget_get_style_context (widget);

    attributes.window_type = GDK_WINDOW_CHILD;
    attributes.wclass = GDK_INPUT_OUTPUT;
    attributes.event_mask = GDK_EXPOSURE_MASK;

    window = gdk_window_new (parent_window, &attributes, 0);
    gdk_window_set_user_data (window, widget);
    gtk_widget_set_window (widget, window);
    gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
    gtk_style_context_set_background (context, window);
}

static void
gedit_overlay_child_get_preferred_width (GtkWidget *widget,
                                         gint      *minimum,
                                         gint      *natural)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (widget);
    gint width;

    if (child->priv->widget != NULL)
    {
        gint child_min, child_nat;

        gtk_widget_get_preferred_width (child->priv->widget,
                                        &child_min, &child_nat);
        child->priv->widget_alloc.width = child_min;
    }

    width = child->priv->widget_alloc.width;
    *minimum = *natural = width;
}

static void
gedit_overlay_child_get_preferred_height (GtkWidget *widget,
                                          gint      *minimum,
                                          gint      *natural)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (widget);
    gint height;

    if (child->priv->widget != NULL)
    {
        gint child_min, child_nat;

        gtk_widget_get_preferred_height (child->priv->widget,
                                         &child_min, &child_nat);
        child->priv->widget_alloc.height = child_min;
    }

    height = child->priv->widget_alloc.height;
    *minimum = *natural = height;
}

static void
gedit_overlay_child_size_allocate (GtkWidget     *widget,
                                   GtkAllocation *allocation)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (widget);

    GTK_WIDGET_CLASS (gedit_overlay_child_parent_class)->size_allocate (widget, allocation);

    if (child->priv->widget != NULL &&
        child->priv->widget_alloc.height &&
        child->priv->widget_alloc.width)
    {
        gtk_widget_size_allocate (child->priv->widget,
                                  &child->priv->widget_alloc);
    }
}

static void
gedit_overlay_child_add (GtkContainer *container,
                         GtkWidget    *widget)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (container);

    child->priv->widget = widget;

    GTK_CONTAINER_CLASS (gedit_overlay_child_parent_class)->add (container, widget);
}

static void
gedit_overlay_child_remove (GtkContainer *container,
                            GtkWidget    *widget)
{
    GeditOverlayChild *child = GEDIT_OVERLAY_CHILD (container);

    child->priv->widget = NULL;

    GTK_CONTAINER_CLASS (gedit_overlay_child_parent_class)->remove (container, widget);
}

static void
gedit_overlay_child_class_init (GeditOverlayChildClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
    GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
    
    object_class->get_property = gedit_overlay_child_get_property;
    object_class->set_property = gedit_overlay_child_set_property;

    widget_class->realize = gedit_overlay_child_realize;
    widget_class->get_preferred_width = gedit_overlay_child_get_preferred_width;
    widget_class->get_preferred_height = gedit_overlay_child_get_preferred_height;
    widget_class->size_allocate = gedit_overlay_child_size_allocate;

    container_class->add = gedit_overlay_child_add;
    container_class->remove = gedit_overlay_child_remove;

    g_object_class_install_property (object_class, PROP_WIDGET,
                                     g_param_spec_object ("widget",
                                                          "Widget",
                                                          "The Widget",
                                                          GTK_TYPE_WIDGET,
                                                          G_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT_ONLY |
                                                          G_PARAM_STATIC_STRINGS));

    g_object_class_install_property (object_class, PROP_POSITION,
                                     g_param_spec_enum ("position",
                                                        "Position",
                                                        "The Widget Position",
                                                        GEDIT_TYPE_OVERLAY_CHILD_POSITION,
                                                        GEDIT_OVERLAY_CHILD_POSITION_STATIC,
                                                        G_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT |
                                                        G_PARAM_STATIC_STRINGS));

    g_object_class_install_property (object_class, PROP_OFFSET,
                                     g_param_spec_uint ("offset",
                                                        "Offset",
                                                        "The Widget Offset",
                                                        0,
                                                        G_MAXUINT,
                                                        0,
                                                        G_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT |
                                                        G_PARAM_STATIC_STRINGS));

    g_type_class_add_private (object_class, sizeof (GeditOverlayChildPrivate));
}

static void
gedit_overlay_child_init (GeditOverlayChild *child)
{
    child->priv = G_TYPE_INSTANCE_GET_PRIVATE (child,
                                               GEDIT_TYPE_OVERLAY_CHILD,
                                               GeditOverlayChildPrivate);

    gtk_widget_set_has_window (GTK_WIDGET (child), TRUE);
}

/**
 * gedit_overlay_child_new:
 * @widget: a #GtkWidget
 *
 * Creates a new #GeditOverlayChild object
 *
 * Returns: a new #GeditOverlayChild object
 */
GeditOverlayChild *
gedit_overlay_child_new (GtkWidget *widget)
{
    return g_object_new (GEDIT_TYPE_OVERLAY_CHILD,
                         "widget", widget,
                         NULL);
}

/**
 * gedit_overlay_child_get_position:
 * @child: a #GeditOverlayChild
 *
 * Gets the position of the widget
 *
 * Returns: wether the child should be placed in a #GeditOverlay
 */
GeditOverlayChildPosition
gedit_overlay_child_get_position (GeditOverlayChild *child)
{
    g_return_val_if_fail (GEDIT_IS_OVERLAY_CHILD (child), GEDIT_OVERLAY_CHILD_POSITION_STATIC);

    return child->priv->position;
}

/**
 * gedit_overlay_child_set_position:
 * @child: a #GeditOverlayChild
 * @position: a #GeditOverlayChildPosition
 *
 * Sets the new position for @child
 */
void
gedit_overlay_child_set_position (GeditOverlayChild        *child,
                                  GeditOverlayChildPosition position)
{
    g_return_if_fail (GEDIT_IS_OVERLAY_CHILD (child));

    if (child->priv->position != position)
    {
        child->priv->position = position;

        g_object_notify (G_OBJECT (child), "position");
    }
}

/**
 * gedit_overlay_child_get_offset:
 * @child: a #GeditOverlayChild
 *
 * Gets the offset for @child. The offset is usually used by #GeditOverlay
 * to not place the widget directly in the border of the container
 *
 * Returns: the offset for @child
 */
guint
gedit_overlay_child_get_offset (GeditOverlayChild *child)
{
    g_return_val_if_fail (GEDIT_IS_OVERLAY_CHILD (child), 0);

    return child->priv->offset;
}

/**
 * gedit_overlay_child_set_offset:
 * @child: a #GeditOverlayChild
 * @offset: the offset for @child
 *
 * Sets the new offset for @child
 */
void
gedit_overlay_child_set_offset (GeditOverlayChild *child,
                                guint              offset)
{
    g_return_if_fail (GEDIT_IS_OVERLAY_CHILD (child));

    if (child->priv->offset != offset)
    {
        child->priv->offset = offset;

        g_object_notify (G_OBJECT (child), "offset");
    }
}

/* ex:set ts=8 noet: */