/*
 *  kis_tool_select_freehand.h - part of Krayon^WChalk
 *
 *  Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
 *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
 *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
#include <tqapplication.h>
#include <tqpainter.h>
#include <tqregion.h>
#include <tqwidget.h>
#include <tqlayout.h>

#include <tdeaction.h>
#include <kdebug.h>
#include <kcommand.h>
#include <tdelocale.h>

#include <kis_layer.h>
#include <kis_selection_options.h>
#include <kis_canvas_controller.h>
#include <kis_canvas_subject.h>
#include <kis_cursor.h>
#include <kis_image.h>
#include <kis_tool_select_outline.h>
#include <kis_vec.h>
#include <kis_undo_adapter.h>
#include <kis_button_press_event.h>
#include <kis_button_release_event.h>
#include <kis_move_event.h>
#include "kis_selected_transaction.h"
#include "kis_painter.h"
#include "kis_paintop_registry.h"
#include "kis_canvas.h"
#include "kis_canvas_painter.h"

KisToolSelectOutline::KisToolSelectOutline()
    : super(i18n("Select Outline"))
{
    setName("tool_select_outline");
    setCursor(KisCursor::load("tool_outline_selection_cursor.png", 5, 5));

    m_subject = 0;
    m_dragging = false;
    m_optWidget = 0;
    m_selectAction = SELECTION_ADD;
}

KisToolSelectOutline::~KisToolSelectOutline()
{
}

void KisToolSelectOutline::activate()
{
    super::activate();

    if (!m_optWidget)
        return;

    m_optWidget->slotActivated();
}

void KisToolSelectOutline::update (KisCanvasSubject *subject)
{
    m_subject = subject;
    super::update(m_subject);
}

void KisToolSelectOutline::buttonPress(KisButtonPressEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_dragging = true;

        m_dragStart = event->pos();
        m_dragEnd = event->pos();
        m_points.clear();
        m_points.append(m_dragStart);
    }
}

void KisToolSelectOutline::move(KisMoveEvent *event)
{
    if (m_dragging) {
        m_dragStart = m_dragEnd;
        m_dragEnd = event->pos();
        m_points.append (m_dragEnd);
        // draw new lines on canvas
        draw();
    }
}

void KisToolSelectOutline::buttonRelease(KisButtonReleaseEvent *event)
{
    if (!m_subject)
        return;

    if (m_dragging && event->button() == Qt::LeftButton) {
        m_dragging = false;
        deactivate();

        KisImageSP img = m_subject->currentImg();

        if (img && img->activeDevice()) {
            TQApplication::setOverrideCursor(KisCursor::waitCursor());
            KisPaintDeviceSP dev = img->activeDevice();
            bool hasSelection = dev->hasSelection();
            KisSelectedTransaction *t = 0;
            if (img->undo()) t = new KisSelectedTransaction(i18n("Outline Selection"), dev);
            KisSelectionSP selection = dev->selection();

            if (!hasSelection) {
                selection->clear();
            }

            KisPainter painter(selection.data());

            painter.setPaintColor(KisColor(TQt::black, selection->colorSpace()));
            painter.setFillStyle(KisPainter::FillStyleForegroundColor);
            painter.setStrokeStyle(KisPainter::StrokeStyleNone);
            painter.setBrush(m_subject->currentBrush());
            painter.setOpacity(OPACITY_OPAQUE);
            KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("paintbrush", 0, &painter);
            painter.setPaintOp(op);    // And now the painter owns the op and will destroy it.

            switch (m_selectAction) {
            case SELECTION_ADD:
                painter.setCompositeOp(COMPOSITE_OVER);
                break;
            case SELECTION_SUBTRACT:
                painter.setCompositeOp(COMPOSITE_SUBTRACT);
                break;
            default:
                break;
            }

            painter.paintPolygon(m_points);


            if(hasSelection) {
                TQRect dirty(painter.dirtyRect());
                dev->setDirty(dirty);
                dev->emitSelectionChanged(dirty);
            } else {
                dev->setDirty();
                dev->emitSelectionChanged();
            }

            if (img->undo())
                img->undoAdapter()->addCommand(t);

            TQApplication::restoreOverrideCursor();
        }

        m_points.clear();
    }
}

void KisToolSelectOutline::paint(KisCanvasPainter& gc)
{
    draw(gc);
}

void KisToolSelectOutline::paint(KisCanvasPainter& gc, const TQRect&)
{
    draw(gc);
}

void KisToolSelectOutline::draw()
{
    if (m_subject) {
        KisCanvasController *controller = m_subject->canvasController();
        KisCanvas *canvas = controller->kiscanvas();
        KisCanvasPainter gc(canvas);

        draw(gc);
    }
}

void KisToolSelectOutline::draw(KisCanvasPainter& gc)
{
    if (!m_subject)
        return;

    if (m_dragging && !m_points.empty()) {
        TQPen pen(TQt::white, 0, TQt::DotLine);

        gc.setPen(pen);
        gc.setRasterOp(TQt::XorROP);

        KisCanvasController *controller = m_subject->canvasController();
        KisPoint start, end;
        TQPoint startPos;
        TQPoint endPos;

        startPos = controller->windowToView(m_dragStart.floorTQPoint());
        endPos = controller->windowToView(m_dragEnd.floorTQPoint());
        gc.drawLine(startPos, endPos);
    }
}

void KisToolSelectOutline::deactivate()
{
    if (m_subject) {
        KisCanvasController *controller = m_subject->canvasController();
        KisCanvas *canvas = controller->kiscanvas();
        KisCanvasPainter gc(canvas);

        TQPen pen(TQt::white, 0, TQt::DotLine);

        gc.setPen(pen);
        gc.setRasterOp(TQt::XorROP);

        KisPoint start, end;
        TQPoint startPos;
        TQPoint endPos;

        for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {

            if (it == m_points.begin())
            {
                start = (*it);
            } else {
                end = (*it);

                startPos = controller->windowToView(start.floorTQPoint());
                endPos = controller->windowToView(end.floorTQPoint());

                gc.drawLine(startPos, endPos);

                start = end;
            }
        }
    }
}

void KisToolSelectOutline::setup(TDEActionCollection *collection)
{
    m_action = static_cast<TDERadioAction *>(collection->action(name()));

    if (m_action == 0) {
        m_action = new TDERadioAction(i18n("&Outline Selection"),
                        "tool_outline_selection",
                        0,
                        this,
                        TQT_SLOT(activate()),
                        collection,
                        name());
        TQ_CHECK_PTR(m_action);
        m_action->setExclusiveGroup("tools");
        m_action->setToolTip(i18n("Select an outline"));
        m_ownAction = true;
    }
}


TQWidget* KisToolSelectOutline::createOptionWidget(TQWidget* parent)
{
    m_optWidget = new KisSelectionOptions(parent, m_subject);
    TQ_CHECK_PTR(m_optWidget);
    m_optWidget->setCaption(i18n("Outline Selection"));

    connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));

    TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->layout());
    l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));

    return m_optWidget;
}

TQWidget* KisToolSelectOutline::optionWidget()
{
        return m_optWidget;
}

void KisToolSelectOutline::slotSetAction(int action) {
    if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
        m_selectAction =(enumSelectionMode)action;
}

#include "kis_tool_select_outline.moc"

