/*
    Rosegarden
    A sequencer and musical notation editor.
 
    This program is Copyright 2000-2008
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <bownie@bownie.com>
 
    The moral right of the authors to claim authorship of this work
    has been asserted.
 
    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.  See the file
    COPYING included with this distribution for more information.
*/

#include <tqcanvas.h>
#include "misc/Debug.h"

#include "QCanvasGroupableItem.h"

QCanvasGroupableItem::QCanvasGroupableItem(TQCanvasItem *i,
        TQCanvasItemGroup *g,
        bool withRelativeCoords)
        : m_group(g),
        m_item(i)
{
    //     RG_DEBUG << "QCanvasGroupableItem() - this : " << this
    //                          << " - group : " << g
    //                          << " - item : " << i << endl;

    if (withRelativeCoords)
        group()->addItemWithRelativeCoords(item());
    else
        group()->addItem(item());
}

QCanvasGroupableItem::~QCanvasGroupableItem()
{
    //     RG_DEBUG << "~QCanvasGroupableItem() - this : " << this
    //                          << " - group : " << group()
    //                          << " - item : " << item() << endl;

    // remove from the item group if we're still attached to one
    if (group())
        group()->removeItem(item());
}

void
QCanvasGroupableItem::relativeMoveBy(double dx, double dy)
{
    m_item->moveBy(dx + m_group->x(),
                   dy + m_group->y());
}

void
QCanvasGroupableItem::detach()
{
    m_group = 0;
}

//////////////////////////////////////////////////////////////////////

TQCanvasItemGroup::TQCanvasItemGroup(TQCanvas *c)
        : TQCanvasItem(c)
{
    //     RG_DEBUG << "TQCanvasItemGroup() - this : " << this << endl;
}

TQCanvasItemGroup::~TQCanvasItemGroup()
{
    //     RG_DEBUG << "~TQCanvasItemGroup() - this : " << this << endl;

    // Tell all our items that we're being destroyed
    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i) {
        QCanvasGroupableItem *t = dynamic_cast<QCanvasGroupableItem*>(*i);
        if (t)
            t->detach();
    }
}

void
TQCanvasItemGroup::moveBy(double dx, double dy)
{
    TQCanvasItem::moveBy(dx, dy); // move ourselves

    TQCanvasItemList::Iterator i; // move group items
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->moveBy(dx, dy);
}

void
TQCanvasItemGroup::advance(int stage)
{
    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->advance(stage);
}

bool
TQCanvasItemGroup::collidesWith(const TQCanvasItem *item) const
{
    TQCanvasItemList::ConstIterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        if ((*i)->collidesWith(item))
            return true;

    return false;
}

void
TQCanvasItemGroup::draw(TQPainter&)
{
    // There isn't anything to do - all the items will be drawn
    // seperately by the canvas anyway. However the function has to be
    // implemented because it's an abstract virtual in TQCanvasItem.

    //     TQCanvasItemList::Iterator i;
    //     for(i = m_items.begin(); i != m_items.end(); ++i)
    //         (*i)->draw(p);
}

void
TQCanvasItemGroup::setVisible(bool yes)
{
    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->setVisible(yes);
}

void
TQCanvasItemGroup::setSelected(bool yes)
{
    TQCanvasItem::setSelected(yes);

    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->setVisible(yes);
}

void
TQCanvasItemGroup::setEnabled(bool yes)
{
    TQCanvasItem::setEnabled(yes);

    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->setEnabled(yes);
}

void
TQCanvasItemGroup::setActive(bool yes)
{
    TQCanvasItem::setActive(yes);

    TQCanvasItemList::Iterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        (*i)->setActive(yes);
}

int
TQCanvasItemGroup::rtti() const
{
    return 10002;
}

TQRect
TQCanvasItemGroup::boundingRect() const
{
    TQRect r;

    TQCanvasItemList::ConstIterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        r.unite((*i)->boundingRect());

    return r;
}

TQRect
TQCanvasItemGroup::boundingRectAdvanced() const
{
    TQRect r;

    TQCanvasItemList::ConstIterator i;
    for (i = m_items.begin(); i != m_items.end(); ++i)
        r.unite((*i)->boundingRectAdvanced());

    return r;
}

bool
TQCanvasItemGroup::collidesWith(const TQCanvasSprite *s,
                               const TQCanvasPolygonalItem *p,
                               const TQCanvasRectangle *r,
                               const TQCanvasEllipse *e,
                               const TQCanvasText *t) const
{
    if (s)
        return collidesWith(s);
    else if (p)
        return collidesWith(p);
    else if (r)
        return collidesWith(r);
    else if (e)
        return collidesWith(e);
    else if (t)
        return collidesWith(t);

    return false;

}

void
TQCanvasItemGroup::addItem(TQCanvasItem *i)
{
    m_items.append(i);
}

void
TQCanvasItemGroup::addItemWithRelativeCoords(TQCanvasItem *i)
{
    i->moveBy(x(), y());
    addItem(i);
}

void
TQCanvasItemGroup::removeItem(TQCanvasItem *i)
{
    //     RG_DEBUG << "TQCanvasItemGroup::removeItem() - this : "
    //                          << this << " - item : " << i << endl;
    m_items.remove(i);
}

//////////////////////////////////////////////////////////////////////


TQCanvasLineGroupable::TQCanvasLineGroupable(TQCanvas *c,
        TQCanvasItemGroup *g)
        : TQCanvasLine(c),
        QCanvasGroupableItem(this, g)
{}

//////////////////////////////////////////////////////////////////////

TQCanvasRectangleGroupable::TQCanvasRectangleGroupable(TQCanvas *c,
        TQCanvasItemGroup *g)
        : TQCanvasRectangle(c),
        QCanvasGroupableItem(this, g)
{}

//////////////////////////////////////////////////////////////////////

TQCanvasTextGroupable::TQCanvasTextGroupable(const TQString& label,
        TQCanvas *c,
        TQCanvasItemGroup *g)
        : TQCanvasText(label, c),
        QCanvasGroupableItem(this, g)
{}

TQCanvasTextGroupable::TQCanvasTextGroupable(TQCanvas *c,
        TQCanvasItemGroup *g)
        : TQCanvasText(c),
        QCanvasGroupableItem(this, g)
{}

//////////////////////////////////////////////////////////////////////

TQCanvasSpriteGroupable::TQCanvasSpriteGroupable(TQCanvasPixmapArray *pa,
        TQCanvas *c,
        TQCanvasItemGroup *g)
        : TQCanvasSprite(pa, c),
        QCanvasGroupableItem(this, g)
{}
