/* This is -*- C -*- */
/* vim: set sw=2: */
/* $Id: guppi-compass-box-view.c,v 1.2 2001/11/26 20:00:11 trow Exp $ */

/*
 * guppi-compass-box-view.c
 *
 * Copyright (C) 2001 The Free Software Foundation
 *
 * Developed by Jon Trowbridge <trow@gnu.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <config.h>
#include "guppi-compass-box-view.h"

#include <guppi-memory.h>
#include <guppi-group-view-layout.h>


static GtkObjectClass *parent_class = NULL;

static void
position_floating (GuppiCompassBoxView *view)
{
  GuppiGroupView *grp = GUPPI_GROUP_VIEW (view);
  GuppiGeometry *geom_fixed, *geom_floating;
  GuppiLayoutEngine *engine;
  guppi_compass_t pos;
  double mleft, mright, mtop, mbottom, minner;

  guppi_element_state_get (guppi_element_view_state ((GuppiElementView *) view),
			   "position", &pos,
			   "margin_left",    &mleft,
			   "margin_right",   &mright,
			   "margin_top",     &mtop,
			   "margin_bottom",  &mbottom,
			   "margin_inner",   &minner,
			   NULL);

  if (pos == view->current_pos) {
    return;
  }

  if (view->fixed == NULL || view->floating == NULL)
    return;

  geom_fixed    = guppi_element_view_geometry (view->fixed);
  geom_floating = guppi_element_view_geometry (view->floating);

  /* Tear down existing layout */
  engine = guppi_group_view_layout (grp);

  guppi_layout_engine_remove_geometry_rules (engine, geom_fixed);
  guppi_layout_engine_remove_geometry_rules (engine, geom_floating);

  /* Build up new layout based on the current position */

  switch (pos) {

  case GUPPI_COMPASS_INVALID:

    guppi_group_view_layout_fill (grp, view->fixed, mleft, mright, mtop, mbottom);
    break;

  case GUPPI_NORTH:
  case GUPPI_SOUTH: {

    GuppiElementView *view_top;
    GuppiElementView *view_bot;

    view_top = pos == GUPPI_NORTH ? view->floating : view->fixed;
    view_bot = pos == GUPPI_NORTH ? view->fixed    : view->floating;
    
    guppi_group_view_layout_flush_top (grp, view_top, mtop);
    guppi_group_view_layout_vertically_adjacent (grp, view_top, view_bot, minner);
    guppi_group_view_layout_flush_bottom (grp, view_bot, mbottom);

    if (guppi_geometry_has_natural_width (geom_fixed))
      guppi_group_view_layout_center_horizontally (grp, view->fixed);
    else
      guppi_group_view_layout_fill_horizontally (grp, view->fixed, mleft, mright);

    if (guppi_geometry_has_natural_width (geom_floating))
      guppi_group_view_layout_center_horizontally (grp, view->floating);
    else
      guppi_group_view_layout_fill_horizontally (grp, view->floating, mleft, mright);

    break;
  }

  case GUPPI_EAST:
  case GUPPI_WEST: {

    GuppiElementView *view_left;
    GuppiElementView *view_right;

    view_left  = pos == GUPPI_WEST ? view->floating : view->fixed;
    view_right = pos == GUPPI_WEST ? view->fixed    : view->floating;

    guppi_group_view_layout_flush_left (grp, view_left, mleft);
    guppi_group_view_layout_horizontally_adjacent (grp, view_left, view_right, minner);
    guppi_group_view_layout_flush_right (grp, view_right, mright);

    if (guppi_geometry_has_natural_height (geom_fixed))
      guppi_group_view_layout_center_vertically (grp, view->fixed);
    else
      guppi_group_view_layout_fill_vertically (grp, view->fixed, mtop, mbottom);

    if (guppi_geometry_has_natural_height (geom_floating))
      guppi_group_view_layout_center_vertically (grp, view->floating);
    else
      guppi_group_view_layout_fill_vertically (grp, view->floating, mtop, mbottom);

    break;
  }

  default:
    g_assert_not_reached ();
  }

  view->current_pos = pos;
}

static void
add_hook (GuppiGroupView *grp, GuppiElementView *view)
{
  GuppiCompassBoxView *box_view = GUPPI_COMPASS_BOX_VIEW (grp);

  if (box_view->floating == NULL) {
    box_view->floating = view;
  } else if (box_view->fixed == NULL) {
    box_view->fixed = view;
  } else {
    g_warning ("Can't add more than two views to GuppiCompassBoxView.");
    return;
  }

  guppi_ref (view);

  if (box_view->fixed && box_view->floating) {
    position_floating (box_view);
  }
    

  if (GUPPI_GROUP_VIEW_CLASS (parent_class)->add_hook)
    GUPPI_GROUP_VIEW_CLASS (parent_class)->add_hook (grp, view);
}

static void
changed_state (GuppiElementView *view)
{
  position_floating (GUPPI_COMPASS_BOX_VIEW (view));

  if (GUPPI_ELEMENT_VIEW_CLASS (parent_class)->changed_state)
    GUPPI_ELEMENT_VIEW_CLASS (parent_class)->changed_state (view);
}

/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */

static void
guppi_compass_box_view_finalize (GtkObject *obj)
{
  GuppiCompassBoxView *x = GUPPI_COMPASS_BOX_VIEW(obj);

  guppi_unref (x->floating);
  guppi_unref (x->fixed);

  guppi_finalized (obj);

  if (parent_class->finalize)
    parent_class->finalize (obj);
}

static void
guppi_compass_box_view_class_init (GuppiCompassBoxViewClass *klass)
{
  GtkObjectClass *object_class = (GtkObjectClass *)klass;
  GuppiGroupViewClass *group_view_class = GUPPI_GROUP_VIEW_CLASS (klass);
  GuppiElementViewClass *element_view_class = GUPPI_ELEMENT_VIEW_CLASS (klass);
  
  parent_class = gtk_type_class (GUPPI_TYPE_GROUP_VIEW);

  object_class->finalize = guppi_compass_box_view_finalize;

  group_view_class->add_hook = add_hook;
  element_view_class->changed_state = changed_state;
}

static void
guppi_compass_box_view_init (GuppiCompassBoxView *obj)
{
  obj->current_pos = -1;
}

GtkType
guppi_compass_box_view_get_type (void)
{
  static GtkType guppi_compass_box_view_type = 0;
  if (!guppi_compass_box_view_type) {
    static const GtkTypeInfo guppi_compass_box_view_info = {
      "GuppiCompassBoxView",
      sizeof (GuppiCompassBoxView),
      sizeof (GuppiCompassBoxViewClass),
      (GtkClassInitFunc)guppi_compass_box_view_class_init,
      (GtkObjectInitFunc)guppi_compass_box_view_init,
      NULL, NULL, (GtkClassInitFunc)NULL
    };
    guppi_compass_box_view_type = gtk_type_unique (GUPPI_TYPE_GROUP_VIEW, &guppi_compass_box_view_info);
  }
  return guppi_compass_box_view_type;
}



syntax highlighted by Code2HTML, v. 0.9.1