/*------------------------------------------------------------------------------
 src/lib/djWidget/layout.cxx

 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "djLayout.h"
#include <djWidget.h>
#include <djApp.h>
#include <FL/Fl.H>
#include <FL/Fl_Group.H>

namespace dj {

int layoutSpacing() { return djApp->layoutSpacing(); }
int layoutMargin() { return djApp->layoutMargin(); }
int layoutWidgetMargin() { return djApp->layoutWidgetMargin(); }
int layoutButtonSize() { return djApp->layoutButtonSize(); }
int layoutThumbnailSize() { return djApp->layoutThumbnailSize(); }

Layout::Layout(LayoutItem * parent) :
  LayoutItem(LAYOUT),
  _spacing(djApp->layoutSpacing()), _margin(djApp->layoutMargin())
{
  //DJ_DBG_FNC("dj::Layout::Layout");
  
  // XXX Parent.
  //
  if (parent) {
    if (WIDGET == parent->type()) {
      static_cast<WidgetBase *>(parent)->layout(this);
    } else if (LAYOUT == parent->type()) {
      static_cast<Layout *>(parent)->add(this);
    }
    this->parent(parent);
  }
}

Layout::~Layout()
{
  //DJ_DBG_FNC("dj::Layout::~Layout");
  //DJ_DBG_PRN("type = " << type());
  
  del();
}

void Layout::add(LayoutItem * in)
{
  if (! in) return;
  
  DJ_DBG_FNC("dj::Layout::add");
  DJ_DBG_PRN("type = " << in->type());
  
  insert(in, _itemList.size());
}

void Layout::insert(LayoutItem * in, int index)
{
  if (! in) return;
  
  DJ_DBG_FNC("dj::Layout::insert");
  DJ_DBG_PRN("index = " << index);
  DJ_DBG_PRN("type = " << in->type());
  
  _itemList.insert(in, index);
  
  // XXX Reparent item.
  //
  if (in->parent()) {
    if (WIDGET == in->parent()->type()) {
      if (LAYOUT == in->type())
        static_cast<WidgetBase *>(in->parent())->layout(0);
    } else if (LAYOUT == in->parent()->type()) {
      static_cast<Layout *>(in->parent())->remove(in);
    }
  }
  if (Fl_Widget * w = dynamic_cast<Fl_Widget *>(in)) {
    if (w->parent()) {
      w->parent()->remove(w);
      w->parent(0);
    }
    LayoutItem * parent = this;
    while (WIDGET != parent->type()) {
      parent = parent->parent();
      if (! parent) break;
    }
    if (Fl_Group * w2 = dynamic_cast<Fl_Group *>(parent)) {
      DJ_DBG_PRN("fltk add");
      w2->add(w);
    }
  }
  in->parent(this);

# ifdef DJ_DBG
  for (ListIt<LayoutItem *> it = _itemList; it.isValid(); ++it)
    DJ_DBG_PRN("item = " << it()->type());
# endif
  
  layoutUpdate();
}

LayoutItem * Layout::remove(int in)
{
  DJ_DBG_FNC("dj::Layout::remove");
  DJ_DBG_PRN("in = " << in);
  
  LayoutItem * item = _itemList.del(in);
  DJ_DBG_PRN("type = " << item->type());
  
  // XXX FLTK mangling.
  //
  if (Fl_Widget * w = dynamic_cast<Fl_Widget *>(item))
    if (w->parent()) {
      DJ_DBG_PRN("fltk remove");
      w->parent()->remove(w);
      w->parent(0);
    }
  item->parent(0);
  
  layoutUpdate();
  
  return item;
}

LayoutItem * Layout::remove(LayoutItem * in)
{
  return remove(find(_itemList, in));
}

void Layout::del(int in)
{
  DJ_DBG_FNC("dj::Layout::del");
  DJ_DBG_PRN("in = " << in);
  
  LayoutItem * item = remove(in);
  
  // XXX FLTK mangling.
  //
  if (WIDGET == item->type()) {
    static_cast<WidgetBase *>(item)->die();
    Fl_Widget * w = dynamic_cast<Fl_Widget *>(item);
    DJ_ASSERT(w);
    Fl::delete_widget(w);
  } else {
    delete item;
  }
}

void Layout::del(LayoutItem * in)
{
  del(find(_itemList, in));
}

void Layout::del()
{
  DJ_DBG_FNC("dj::Layout::del");
  
  while (_itemList.size()) del(0);
}

void Layout::spacing(int in)
{
  if (in == _spacing) return;
  
  _spacing = in;
  
  layoutUpdate();
}

void Layout::margin(int in)
{
  if (in == _margin) return;
  
  _margin = in;

  layoutUpdate();
}

int Layout::visible() const
{
  //DJ_DBG_FNC("dj::Layout::visible");
  //DJ_DBG_PRN("items = " << _itemList.size());
  
  int out = 0;
  
  for (ConstListIt<LayoutItem *> it = _itemList; it.isValid(); ++it)
    if (SPACER != it()->type()) {
      //DJ_DBG_PRN("visible = " << it()->visible());
      out |= it()->visible();
    }
  
  //DJ_DBG_PRN("out = " << bool(out));
  return out;
}

}
