/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * Copyright (C) 2013 Red Hat, Inc.
 *
 * This program 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.";
 */

#include "polari-fixed-size-frame.h"

typedef struct _PolariFixedSizeFramePrivate PolariFixedSizeFramePrivate;

struct _PolariFixedSizeFrame {
  GtkFrame parent_instance;

  PolariFixedSizeFramePrivate *priv;
};

struct _PolariFixedSizeFramePrivate {
  int width;
  int height;
};

enum
{
  PROP_0,

  PROP_WIDTH,
  PROP_HEIGHT,

  LAST_PROP
};

static GParamSpec *props[LAST_PROP];

static void
polari_fixed_size_frame_buildable_init (GtkBuildableIface *iface);

G_DEFINE_TYPE_WITH_CODE (PolariFixedSizeFrame, polari_fixed_size_frame,
                         GTK_TYPE_FRAME,
                         G_ADD_PRIVATE (PolariFixedSizeFrame)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                polari_fixed_size_frame_buildable_init))

static void
polari_fixed_size_frame_buildable_init (GtkBuildableIface *iface)
{
}

static void
queue_redraw (PolariFixedSizeFrame *self)
{
  GtkWidget *child = gtk_bin_get_child (GTK_BIN (self));

  if (child)
    gtk_widget_queue_resize (child);

  gtk_widget_queue_draw (GTK_WIDGET (self));
}

static void
polari_fixed_size_frame_set_width (PolariFixedSizeFrame *self,
                                       int                       width)
{
  if (self->priv->width != width)
    {
      self->priv->width = width;
      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_WIDTH]);

      queue_redraw (self);
    }
}

static void
polari_fixed_size_frame_set_height (PolariFixedSizeFrame *self,
                                        int                       height)
{
  if (self->priv->height != height)
    {
      self->priv->height = height;
      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HEIGHT]);

      queue_redraw (self);
    }
}

static void
polari_fixed_size_frame_set_property (GObject      *object,
                                          guint         prop_id,
                                          const GValue *value,
                                          GParamSpec   *pspec)
{
  PolariFixedSizeFrame *self = POLARI_FIXED_SIZE_FRAME (object);

  switch (prop_id)
    {
    case PROP_WIDTH:
      polari_fixed_size_frame_set_width(self, g_value_get_int (value));
      break;
    case PROP_HEIGHT:
      polari_fixed_size_frame_set_height(self, g_value_get_int (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
polari_fixed_size_frame_get_property (GObject    *object,
                                          guint       prop_id,
                                          GValue     *value,
                                          GParamSpec *pspec)
{
  PolariFixedSizeFrame *self = POLARI_FIXED_SIZE_FRAME (object);

  switch (prop_id)
    {
    case PROP_WIDTH:
        g_value_set_int (value, self->priv->width);
      break;
    case PROP_HEIGHT:
        g_value_set_int (value, self->priv->height);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
polari_fixed_size_frame_get_preferred_width (GtkWidget *widget,
                                                 int       *minimum_size,
                                                 int       *natural_size)
{
  PolariFixedSizeFrame *self = POLARI_FIXED_SIZE_FRAME (widget);

  if (self->priv->width == -1)
    {
      GTK_WIDGET_CLASS (polari_fixed_size_frame_parent_class)->get_preferred_width (widget, minimum_size, natural_size);
    }
  else
    {
      *minimum_size = *natural_size = self->priv->width;
    }
}

static void
polari_fixed_size_frame_get_preferred_height (GtkWidget *widget,
                                                  int       *minimum_size,
                                                  int       *natural_size)
{
  PolariFixedSizeFrame *self = POLARI_FIXED_SIZE_FRAME (widget);

  if (self->priv->height == -1)
    {
      GTK_WIDGET_CLASS (polari_fixed_size_frame_parent_class)->get_preferred_height (widget, minimum_size, natural_size);
    }
  else
    {
      *minimum_size = *natural_size = self->priv->height;
    }
}

static void
polari_fixed_size_frame_class_init (PolariFixedSizeFrameClass *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 = polari_fixed_size_frame_get_property;
  object_class->set_property = polari_fixed_size_frame_set_property;
  widget_class->get_preferred_width =
    polari_fixed_size_frame_get_preferred_width;
  widget_class->get_preferred_height =
    polari_fixed_size_frame_get_preferred_height;
  gtk_container_class_handle_border_width (container_class);

  props[PROP_WIDTH] =
    g_param_spec_int ("width",
                      "Width",
                      "Fixed width of the widget, or -1 to use the child's "
                      "width",
                      -1,
                      G_MAXINT,
                      -1,
                      G_PARAM_READWRITE);

  props[PROP_HEIGHT] =
    g_param_spec_int ("height",
                      "Height",
                      "Fixed height of the widget, or -1 to use the child's "
                      "height",
                      -1,
                      G_MAXINT,
                      -1,
                      G_PARAM_READWRITE);

  g_object_class_install_properties (object_class, LAST_PROP, props);
}

static void
polari_fixed_size_frame_init (PolariFixedSizeFrame *self)
{
  self->priv = polari_fixed_size_frame_get_instance_private (self),
  self->priv->width = -1;
  self->priv->height = -1;
}
