/* acontainer.h
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2004-2024 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef ACONTAINER_H
#define ACONTAINER_H

#include "aguixdefs.h"
#include <vector>

class AContainer
{
public:
  AContainer( class AWindow *twin, int txelems = 1, int tyelems = 1 );
  AContainer( class AWindow *twin, int txelems, int tyelems, int border_width, int min_space, int max_space );
  virtual ~AContainer();
  AContainer( const AContainer &other );
  AContainer &operator=( const AContainer &other );

  enum { ACONT_NONE = 0,
         ACONT_MAXW = 1 << 0,
         ACONT_MAXH = 1 << 1,
         ACONT_MINW = 1 << 2,
         ACONT_MINH = 1 << 3,
         ACONT_NORESIZE = 1 << 4,
         ACONT_CENTERH = 1 << 5,
         ACONT_CENTERV = 1 << 6,
         ACONT_CENTER = ACONT_CENTERH | ACONT_CENTERV };

  static const int CO_INCW = ACONT_MINH + ACONT_MINW + ACONT_MAXH;
  static const int CO_INCWNR = CO_INCW + ACONT_NORESIZE;
  static const int CO_FIX = ACONT_MINH + ACONT_MINW + ACONT_MAXH + ACONT_MAXW;
  static const int CO_FIXNR = CO_FIX + ACONT_NORESIZE;
  static const int CO_MIN = ACONT_MINH + ACONT_MINW;
  static const int CO_INCH = ACONT_MINH + ACONT_MINW + ACONT_MAXW;

  class Widget *add( class Widget *newelement, int tx = 0, int ty = 0, int tautosizeMode = ACONT_NONE );
  AContainer *add( AContainer *newcont, int tx = 0, int ty = 0 );
  template <class T> T *addWidget( T *newelement, int tx = 0, int ty = 0, int tautosizeMode = ACONT_NONE )
  {
      return static_cast<T*>( add( newelement, tx, ty, tautosizeMode ) );
  }

  void setParent( AContainer *nv );
  int remove( const AContainer *v );
  virtual int remove( const Widget *v );

  enum { ACONT_ONLYH = 1, ACONT_ONLYV };
  int resize( int nw, int nh );
  int move( int nx, int ny );
  virtual int rearrange( int vhmode = 0 );

  void setBorderWidth( int nv );
  int getBorderWidth() const;
  void setMinSpace( int nv );
  int getMinSpace() const;
  void setMaxSpace( int nv );
  int getMaxSpace() const;
  void setMinWidth( int nv, int tx = 0, int ty = 0 );
  int getMinWidth( int tx = 0, int ty = 0 ) const;
  void setMaxWidth( int nv, int tx = 0, int ty = 0 );
  int getMaxWidth( int tx = 0, int ty = 0 ) const;
  void setMinHeight( int nv, int tx = 0, int ty = 0 );
  int getMinHeight( int tx = 0, int ty = 0 ) const;
  void setMaxHeight( int nv, int tx = 0, int ty = 0 );
  int getMaxHeight( int tx = 0, int ty = 0 ) const;
  void setWWeight( int nv, int tx = 0, int ty = 0 );
  int getWWeight( int tx = 0, int ty = 0 ) const;
  void setHWeight( int nv, int tx = 0, int ty = 0 );
  int getHWeight( int tx = 0, int ty = 0 ) const;
  int getX() const;
  int getY() const;

  void readLimits();

  int getWidth() const;
  int getHeight() const;
  int getWidth( int tx, int ty ) const;
  int getHeight( int tx, int ty ) const;

    void setNoResize( bool nv, int tx, int ty );
    bool getNoResize( int tx, int ty ) const;

    virtual void hide();
    virtual void show();
 private:
  class AWindow *win;
  AContainer *parent;
  int xelems, yelems;

  class AContElem {
  public:
    AContElem();
    AContElem( const AContElem &other );
    AContElem &operator=( const AContElem &other );

    class Widget *widelem() const;
    AContainer *cont() const;
    void widelem( class Widget *newelem );
    void cont( AContainer *newcont );
    int width() const;
    void width( int nv );
    int height() const;
    void height( int nv );
    int minWidth() const;
    void minWidth( int nv );
    int maxWidth() const;
    void maxWidth( int nv );
    int minHeight() const;
    void minHeight( int nv );
    int maxHeight() const;
    void maxHeight( int nv );
    int autosizeMode() const;
    void autosizeMode( int nv );
    int wWeight() const;
    void wWeight( int nv );
    int hWeight() const;
    void hWeight( int nv );

    bool noResize() const;
    void noResize( bool nv );

    enum acont_elem_center_mode {
        CENTER_NONE = 0,
        CENTER_VERTICALLY = 1 << 0,
        CENTER_HORIZONTALLY = 1 << 1,
        CENTER_BOTH = CENTER_VERTICALLY | CENTER_HORIZONTALLY
    };

    enum acont_elem_center_mode center() const;
    void center( enum acont_elem_center_mode nv );
  private:
    class Widget *_widelem;
    AContainer *Cont;
    int Width, Height;

    int MinWidth, MaxWidth, MinHeight, MaxHeight;
    int AutosizeMode;
    int WWeight, HWeight;
    bool NoResize;
    enum acont_elem_center_mode m_center = CENTER_NONE;
  };

  struct update_infos {
  update_infos() : active( false ),
          x( 0 ),
          y( 0 ) {}

      bool active;
      int x;
      int y;
  };

  AContElem *elements;
  int *ergWidths, *ergHeights;

  int width, height, x, y;
  int BorderWidth, MinSpace, MaxSpace;

  std::vector< update_infos > m_move_infos;
  std::vector< update_infos > m_resize_infos;
  std::vector< update_infos > m_rearrange_infos;

  int old_rearrange_width, old_rearrange_height;
};

#endif
