Logo Search packages:      
Sourcecode: gambas version File versions  Download package

CContainer.cpp

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

  CContainer.cpp

  The Container class

  (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net>

  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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.

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

#define __CCONTAINER_CPP



#include <qnamespace.h>
#include <qapplication.h>
#include <qmainwindow.h>
#include <qlayout.h>
#include <qevent.h>

#include "gambas.h"

#include "CWidget.h"
#include "CWindow.h"
#include "CConst.h"

#include "CContainer.h"

/*#define DEBUG*/

static QWidget *get_widget(QObjectList *list)
{
  for(;;)
  {
    QObject *ob = list->current();
    if (!ob)
      return NULL;
    list->next();
    if (ob->isWidgetType())
    {
      if (((QWidget *)ob)->isVisible())
        return (QWidget *)ob;
    }
  }
}

void CCONTAINER_arrange(QFrame *cont)
{
  QWidget *wid;
  int x, y, w, h, i;
  int xc, yc, wc, hc;
  int sexp, nexp;
  bool swap, autoresize;
  CCONTAINER_ARRANGEMENT *arr;
  void *ob;
  bool redo;
  bool first;

  //if (lock)
  //  return;

  ob = CWidget::get(cont);
  if (CWIDGET_test_flag(ob, WF_DESIGN))
    return;

  arr = (CCONTAINER_ARRANGEMENT *)ob;

  if (arr->locked)
    return;

  if (arr->mode == ARRANGE_NONE)
    return;

  QObjectList *list = (QObjectList *)cont->children();

  if (!list || list->count() == 0)
    return;

  arr->locked = true;

  swap = (arr->mode & 1) == 0;
  autoresize = arr->autoresize && !CWIDGET_test_flag(ob, WF_EXPAND);

  for (i = 0; i < 3; i++)
  {
    redo = false;

    xc = cont->contentsRect().x() + arr->padding;
    yc = cont->contentsRect().y() + arr->padding;
    wc = cont->contentsRect().width() - arr->padding * 2;
    hc = cont->contentsRect().height() - arr->padding * 2;

    if (wc <= 0 || hc <= 0)
      break;

    x = xc;
    y = yc;
    w = h = 0;
    wid = 0;
    list->first();

    switch (arr->mode)
    {
      case ARRANGE_HORIZONTAL:
      case ARRANGE_VERTICAL:

        sexp = 0;
        nexp = 0;

        for(;;)
        {
          wid = get_widget(list);
          if (!wid)
            break;

          ob = CWidget::get(wid);

          if (ob && CWIDGET_test_flag(ob, WF_EXPAND))
            nexp++;
          else
            sexp += (swap ? wid->height() : wid->width());

          sexp += arr->spacing;
        }

        sexp -= arr->spacing;
        sexp = (swap ? hc : wc) - sexp;

        list->first();
        wid = 0;

        for(;;)
        {
          first = wid == 0;

          wid = get_widget(list);
          if (!wid)
            break;

          if (!first)
          {
            if (swap)
              y += arr->spacing;
            else
              x += arr->spacing;
          }

          ob = CWidget::get(wid);

          if (swap)
          {
            if (CWIDGET_test_flag(ob, WF_EXPAND))
            {
              h = sexp / nexp;
              sexp -= h;
              nexp--;
            }
            else
              h = wid->height();

            if (h > 0)
            {
              if (wc != wid->width() || h != wid->height())
                redo = true;

              wid->setGeometry(x, y, wc, h);
              y += h;
            }
          }
          else
          {
            if (CWIDGET_test_flag(ob, WF_EXPAND))
            {
              w = sexp / nexp;
              sexp -= w;
              nexp--;
            }
            else
              w = wid->width();

            if (w > 0)
            {
              if (w != wid->width() || hc != wid->height())
                redo = true;

              wid->setGeometry(x, y, w, hc);
              x += w;
            }
          }
        }
        break;

      case ARRANGE_LEFT_RIGHT:
      case ARRANGE_TOP_BOTTOM:

        for(;;)
        {
          wid = get_widget(list);
          if (!wid)
            break;

          if (swap)
          {
            if ((y > yc) && ((y + wid->height()) > hc))
            {
              y = yc;
              x += w + arr->spacing;
              w = 0;
            }

            wid->move(x, y);
            y += wid->height() + arr->spacing;

            if (wid->width() > w)
              w = wid->width();
          }
          else
          {
            if ((x > xc) && ((x + wid->width()) > wc))
            {
              x = xc;
              y += h + arr->spacing;
              h = 0;
            }

            wid->move(x, y);
            x += wid->width() + arr->spacing;

            if (wid->height() > h)
              h = wid->height();
          }
        }
        break;

      case ARRANGE_FILL:

        for(;;)
        {
          wid = get_widget(list);
          if (!wid)
            break;

          wid->setGeometry(xc, yc, wc, hc);
        }

        break;
    }

    if (autoresize)
    {
      switch(arr->mode)
      {
        case ARRANGE_HORIZONTAL:
          cont->resize(x + cont->width() - wc - xc, cont->height());
          break;

        case ARRANGE_TOP_BOTTOM:
          cont->resize(x + w + cont->width() - wc - xc, cont->height());
          break;

        case ARRANGE_VERTICAL:
          //qDebug("h = %d  cont->height() = %d  hc = %d  --> %d", h, cont->height(), hc, h + cont->height() - hc);
          cont->resize(cont->width(), y + cont->height() - hc - yc);
          break;

        case ARRANGE_LEFT_RIGHT:
          cont->resize(cont->width(), y + h + cont->height() - hc - yc);
          break;
      }
    }

    if (!redo)
      break;
  }

  arr->locked = false;
}



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

  class MyContainer

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

MyContainer::MyContainer(QWidget *parent)
: QFrame(parent)
{
}


void MyContainer::frameChanged(void)
{
  QFrame::frameChanged();
  CCONTAINER_arrange(this);
}

void MyContainer::resizeEvent(QResizeEvent *e)
{
  QFrame::resizeEvent(e);
  CCONTAINER_arrange(this);
}

void MyContainer::childEvent(QChildEvent *e)
{
  QFrame::childEvent(e);

  if (!e->child()->isWidgetType())
    return;

  if (e->inserted())
  {
    e->child()->installEventFilter(this);
    //qDebug("inserted");
  }
  else if (e->removed())
  {
    e->child()->removeEventFilter(this);
    //qDebug("removed");
  }

  CCONTAINER_arrange(this);
}

bool MyContainer::eventFilter(QObject *o, QEvent *e)
{
  int type = e->type();

  if (type == QEvent::Move || type == QEvent::Resize || type == QEvent::Show || type == QEvent::Hide || type == EVENT_EXPAND)
    CCONTAINER_arrange(this);

  return QObject::eventFilter(o, e);
}


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

  CContainer

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

BEGIN_METHOD_VOID(CCONTAINER_next)

  #ifdef DEBUG
  if (!THIS_CONTAINER)
    qDebug("Null container");
  #endif

  QObjectList *list = (QObjectList *)THIS_CONTAINER->children();
  unsigned int index;
  CWIDGET *widget;

  for(;;)
  {
    index = ENUM(int);

    if (list == NULL || index >= list->count())
    {
      GB.StopEnum();
      return;
    }

    ENUM(int) = index + 1;

    widget = CWidget::getReal(list->at(index));
    if (widget)
    {
      GB.ReturnObject(widget);
      return;
    }
  }

END_METHOD


BEGIN_PROPERTY(CCONTAINER_count)

  QWidget *wid = THIS_CONTAINER;
  QObjectList *list;
  QObject *ob;
  int n = 0;

  if (!wid)
      goto __DONE;

      list = (QObjectList *)wid->children();
      if (!list || !list->count())
            goto __DONE;

      list->first();
  for(;;)
  {
    ob = list->current();
    if (!ob)
      break;
    list->next();
    if (ob->isWidgetType() && CWidget::getReal(ob))
      n++;
  }

__DONE:
  GB.ReturnInteger(n);

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_x)

  #ifdef DEBUG
  if (!THIS_CONTAINER)
    qDebug("Null container");
  #endif

  QPoint p(0, 0);
  /*if (WIDGET->layout())
    WIDGET->layout()->activate();*/
  GB.ReturnInteger(THIS_CONTAINER->mapTo(WIDGET, p).x());

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_y)

  #ifdef DEBUG
  if (!THIS_CONTAINER)
    qDebug("Null container");
  #endif

  QPoint p(0, 0);

  /*if (WIDGET->layout())
    WIDGET->layout()->activate();*/
  GB.ReturnInteger(THIS_CONTAINER->mapTo(WIDGET, p).y());

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_width)

  #ifdef DEBUG
  if (!THIS_CONTAINER)
    qDebug("Null container");
  #endif

  GB.ReturnInteger(THIS_CONTAINER->width());

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_height)

  #ifdef DEBUG
  if (!THIS_CONTAINER)
    qDebug("Null container");
  #endif

  GB.ReturnInteger(THIS_CONTAINER->height());

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_arrangement)

  int arr;

  if (READ_PROPERTY)
    GB.ReturnInteger(THIS_ARRANGEMENT->mode);
  else
  {
    arr = VPROP(GB_INTEGER);
    if (arr < 0 || arr > 8)
      return;
    THIS_ARRANGEMENT->mode = arr;
    CCONTAINER_arrange((QFrame *)THIS_CONTAINER);
  }

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_auto_resize)

  if (READ_PROPERTY)
    GB.ReturnBoolean(THIS_ARRANGEMENT->autoresize);
  else
  {
    THIS_ARRANGEMENT->autoresize = VPROP(GB_BOOLEAN);
    CCONTAINER_arrange((QFrame *)THIS_CONTAINER);
  }

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_padding)

  if (READ_PROPERTY)
    GB.ReturnInteger(THIS_ARRANGEMENT->padding);
  else
  {
    int val = VPROP(GB_INTEGER);

    if (val >= 0 && val < 32768)
    {
      THIS_ARRANGEMENT->padding = val;
      CCONTAINER_arrange((QFrame *)THIS_CONTAINER);
    }
  }

END_PROPERTY


BEGIN_PROPERTY(CCONTAINER_spacing)

  if (READ_PROPERTY)
    GB.ReturnInteger(THIS_ARRANGEMENT->spacing);
  else
  {
    int val = VPROP(GB_INTEGER);

    if (val >= 0 && val < 32768)
    {
      THIS_ARRANGEMENT->spacing = val;
      CCONTAINER_arrange((QFrame *)THIS_CONTAINER);
    }
  }

END_PROPERTY


GB_DESC CChildrenDesc[] =
{
  GB_DECLARE(".ContainerChildren", sizeof(CCONTAINER)), GB_VIRTUAL_CLASS(),

  GB_METHOD("_next", "Control", CCONTAINER_next, NULL),
  GB_PROPERTY_READ("Count", "i", CCONTAINER_count),

  GB_END_DECLARE
};


GB_DESC CContainerDesc[] =
{
  GB_DECLARE("Container", sizeof(CCONTAINER)), GB_INHERITS("Control"),

  GB_NOT_CREATABLE(),

  GB_PROPERTY_SELF("Children", ".ContainerChildren"),

  GB_PROPERTY_READ("ClientX", "i", CCONTAINER_x),
  GB_PROPERTY_READ("ClientY", "i", CCONTAINER_y),
  GB_PROPERTY_READ("ClientW", "i", CCONTAINER_width),
  GB_PROPERTY_READ("ClientWidth", "i", CCONTAINER_width),
  GB_PROPERTY_READ("ClientH", "i", CCONTAINER_height),
  GB_PROPERTY_READ("ClientHeight", "i", CCONTAINER_height),

  GB_END_DECLARE
};




Generated by  Doxygen 1.6.0   Back to index