/*------------------------------------------------------------------------------
 src/lib/djWidget/djLayout.h

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

#ifndef DJ_LAYOUT_H
#define DJ_LAYOUT_H
#include <djBox.h>
#include <djWidgetBase.h>

namespace dj {

// Layout sizes.
//
int layoutSpacing();
int layoutMargin();
int layoutWidgetMargin();
int layoutButtonSize();
int layoutThumbnailSize();
static const int layoutIconSize = 21;
static const int layoutToolIconSize = 11;

// Layout item.
//
class LayoutItem {
public:

  enum TYPE { WIDGET, LAYOUT, SPACER };

  LayoutItem(TYPE);
  virtual ~LayoutItem() = 0;
  
  TYPE type() const { return _type; }
  
  // Size.
  //
  virtual void resize(int, int, int, int);
  virtual const Box2i geom() const { return _geom; }
  virtual const Vec2i sizeHint() const { return Vec2i(); }
  
  // Size policies.
  //
  enum SIZE_POLICY { FIXED, STRETCH };
  enum ALIGN_POLICY { LEFT, CENTER, RIGHT };
  void sizePolicy(SIZE_POLICY, SIZE_POLICY);
  void alignPolicy(ALIGN_POLICY, ALIGN_POLICY);
  const SIZE_POLICY * sizePolicy() const { return _sizePolicy; }
  const ALIGN_POLICY * alignPolicy() const { return _alignPolicy; }
  
  // Visibility.
  //
  virtual int visible() const { return true; }

  // Parent.
  //
  virtual void parent(LayoutItem *);
  LayoutItem * parent() const { return _parent; }
  
protected:

  virtual void layoutUpdate();

private:

  TYPE _type;
  Box2i _geom;
  SIZE_POLICY _sizePolicy [2];
  ALIGN_POLICY _alignPolicy [2];
  LayoutItem * _parent;
};

// Layout spacer.
//
class LayoutSpacer : public LayoutItem {
public:
  LayoutSpacer() : LayoutItem(SPACER) {}
};

// Layout base.
//
class Layout : public LayoutItem {
public:

  Layout(LayoutItem * parent = 0);
  virtual ~Layout() = 0;
  
  // Items.
  //
  virtual void add(LayoutItem *);
  virtual void insert(LayoutItem *, int);
  virtual LayoutItem * remove(int);
  virtual LayoutItem * remove(LayoutItem *);
  virtual void del(int);
  virtual void del(LayoutItem *);
  virtual void del();
  const List<LayoutItem *> & itemList() const { return _itemList; }

  // Spacing.
  //
  void spacing(int);
  void margin(int);
  int spacing() const { return _spacing; }
  int margin() const { return _margin; }
  
  // Visibility.
  //
  virtual int visible() const;

private:

  List<LayoutItem *> _itemList;
  int _spacing, _margin;
};

// Stack layout.
//
class StackLayout : public Layout {
public:

  StackLayout(LayoutItem * parent = 0);
  
  const Vec2i sizeHint() const;
  void resize(int, int, int, int);
};

// Row layout base.
//
class RowLayout : public Layout {
public:

  RowLayout(LayoutItem * parent = 0);

  // Items.
  //
  void spacerAdd(const Vec2i &);
  void stretchAdd(bool stretchItem = true);
  
  // Stretch item.
  //
  void stretch(int);
  void stretch(const LayoutItem *);
  int stretch() const { return _stretch; }

protected:

  enum TYPE { HORIZONTAL, VERTICAL };
  static const List<Box2i> layout(
    const List<LayoutItem *> &,
    const Vec2i & size, TYPE, int spacing, int stretch
  );

private:

  int _stretch;
};

// Horizontal row layout.
//
class HLayout : public RowLayout {
public:

  HLayout(LayoutItem * parent = 0);
  
  void spacerAdd(int = layoutSpacing());

  const Vec2i sizeHint() const;
  void resize(int, int, int, int);
};

// Vertical row layout.
//
class VLayout : public RowLayout {
public:

  VLayout(LayoutItem * parent = 0);
  
  void spacerAdd(int = layoutSpacing());

  const Vec2i sizeHint() const;
  void resize(int, int, int, int);
};

}

#endif
