/* * kis_tool_select_elliptical.cpp -- part of Chalk * * 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 #include #include #include #include #include #include #include #include "kis_autobrush_resource.h" #include "kis_canvas_controller.h" #include "kis_canvas_subject.h" #include "kis_cursor.h" #include "kis_image.h" #include "kis_painter.h" #include "kis_tool_select_elliptical.h" #include "kis_layer.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_selection.h" #include "kis_selection_options.h" #include "kis_selected_transaction.h" #include "kis_canvas.h" #include "kis_canvas_painter.h" KisToolSelectElliptical::KisToolSelectElliptical() : super(i18n("Elliptical Select")) { setName("tool_select_elliptical"); setCursor(KisCursor::load("tool_elliptical_selection_cursor.png", 6, 6)); m_subject = 0; m_selecting = false; m_centerPos = KisPoint(0, 0); m_startPos = KisPoint(0, 0); m_endPos = KisPoint(0, 0); m_optWidget = 0; m_selectAction = SELECTION_ADD; } KisToolSelectElliptical::~KisToolSelectElliptical() { } void KisToolSelectElliptical::activate() { super::activate(); if (!m_optWidget) return; m_optWidget->slotActivated(); } void KisToolSelectElliptical::update(KisCanvasSubject *subject) { m_subject = subject; super::update(m_subject); } void KisToolSelectElliptical::paint(KisCanvasPainter& gc) { if (m_selecting) paintOutline(gc, TQRect()); } void KisToolSelectElliptical::paint(KisCanvasPainter& gc, const TQRect& rc) { if (m_selecting) paintOutline(gc, rc); } void KisToolSelectElliptical::clearSelection() { if (m_subject) { KisCanvasController *controller = m_subject->canvasController(); KisImageSP img = m_subject->currentImg(); Q_ASSERT(controller); // if (img && img->floatingSelection().data() != 0) { // img->unsetFloatingSelection(); // controller->canvas()->update(); // } m_startPos = KisPoint(0, 0); m_endPos = KisPoint(0, 0); m_selecting = false; } } void KisToolSelectElliptical::buttonPress(KisButtonPressEvent *e) { if (m_subject) { KisImageSP img = m_subject->currentImg(); if (img && img->activeDevice() && e->button() == TQt::LeftButton) { clearSelection(); m_startPos = m_endPos = m_centerPos = e->pos(); m_selecting = true; paintOutline(); } } } void KisToolSelectElliptical::move(KisMoveEvent *e) { if (m_subject && m_selecting) { paintOutline(); // move (alt) or resize ellipse if (e->state() & TQt::AltButton) { KisPoint trans = e->pos() - m_endPos; m_startPos += trans; m_endPos += trans; } else { KisPoint diag = e->pos() - (e->state() & TQt::ControlButton ? m_centerPos : m_startPos); // circle? if (e->state() & TQt::ShiftButton) { double size = TQMAX(fabs(diag.x()), fabs(diag.y())); double w = diag.x() < 0 ? -size : size; double h = diag.y() < 0 ? -size : size; diag = KisPoint(w, h); } // resize around center point? if (e->state() & TQt::ControlButton) { m_startPos = m_centerPos - diag; m_endPos = m_centerPos + diag; } else { m_endPos = m_startPos + diag; } } paintOutline(); m_centerPos = KisPoint((m_startPos.x() + m_endPos.x()) / 2, (m_startPos.y() + m_endPos.y()) / 2); } } void KisToolSelectElliptical::buttonRelease(KisButtonReleaseEvent *e) { if (m_subject && m_selecting && e->button() == TQt::LeftButton) { paintOutline(); if (m_startPos == m_endPos) { clearSelection(); } else { TQApplication::setOverrideCursor(KisCursor::waitCursor()); KisImageSP img = m_subject->currentImg(); if (!img) return; if (m_endPos.y() < 0) m_endPos.setY(0); if (m_endPos.y() > img->height()) m_endPos.setY(img->height()); if (m_endPos.x() < 0) m_endPos.setX(0); if (m_endPos.x() > img->width()) m_endPos.setX(img->width()); if (img && img->activeDevice()) { KisPaintDeviceSP dev = img->activeDevice(); KisSelectedTransaction *t = 0; if (img->undo()) t = new KisSelectedTransaction(i18n("Elliptical Selection"), dev); bool hasSelection = dev->hasSelection(); if(! hasSelection) { dev->selection()->clear(); if(m_selectAction==SELECTION_SUBTRACT) dev->selection()->invert(); } TQRect rc( m_startPos.floorTQPoint(), m_endPos.floorTQPoint()); rc = rc.normalize(); KisSelectionSP tmpSel = new KisSelection(dev); KisAutobrushCircleShape shape(rc.width(),rc.height(), 1, 1); TQ_UINT8 value; for (int y = 0; y <= rc.height(); y++) for (int x = 0; x <= rc.width(); x++) { value = MAX_SELECTED - shape.valueAt(x,y); tmpSel->setSelected( x+rc.x(), y+rc.y(), value); } switch(m_selectAction) { case SELECTION_ADD: dev->addSelection(tmpSel); break; case SELECTION_SUBTRACT: dev->subtractSelection(tmpSel); break; } if(hasSelection) { dev->setDirty(rc); dev->emitSelectionChanged(rc); } else { dev->setDirty(); dev->emitSelectionChanged(); } if (img->undo()) img->undoAdapter()->addCommand(t); TQApplication::restoreOverrideCursor(); } } m_selecting = false; } } void KisToolSelectElliptical::paintOutline() { if (m_subject) { KisCanvasController *controller = m_subject->canvasController(); KisCanvas *canvas = controller->kiscanvas(); KisCanvasPainter gc(canvas); TQRect rc; paintOutline(gc, rc); } } void KisToolSelectElliptical::paintOutline(KisCanvasPainter& gc, const TQRect&) { if (m_subject) { KisCanvasController *controller = m_subject->canvasController(); RasterOp op = gc.rasterOp(); TQPen old = gc.pen(); TQPen pen(TQt::DotLine); TQPoint start; TQPoint end; Q_ASSERT(controller); start = controller->windowToView(m_startPos).floorTQPoint(); end = controller->windowToView(m_endPos).floorTQPoint(); gc.setRasterOp(TQt::NotROP); gc.setPen(pen); gc.drawEllipse(TQRect(start, end)); gc.setRasterOp(op); gc.setPen(old); } } void KisToolSelectElliptical::slotSetAction(int action) { if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT) m_selectAction =(enumSelectionMode)action; } void KisToolSelectElliptical::setup(TDEActionCollection *collection) { m_action = static_cast(collection->action(name())); if (m_action == 0) { m_action = new TDERadioAction(i18n("&Elliptical Selection"), "tool_elliptical_selection" , TQt::Key_J, this, TQ_SLOT(activate()), collection, name()); TQ_CHECK_PTR(m_action); m_action->setToolTip(i18n("Select an elliptical area")); m_action->setExclusiveGroup("tools"); m_ownAction = true; } } TQWidget* KisToolSelectElliptical::createOptionWidget(TQWidget* parent) { m_optWidget = new KisSelectionOptions(parent, m_subject); TQ_CHECK_PTR(m_optWidget); m_optWidget->setCaption(i18n("Elliptical Selection")); connect (m_optWidget, TQ_SIGNAL(actionChanged(int)), this, TQ_SLOT(slotSetAction(int))); TQVBoxLayout * l = dynamic_cast(m_optWidget->layout()); l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding)); return m_optWidget; } TQWidget* KisToolSelectElliptical::optionWidget() { return m_optWidget; } #include "kis_tool_select_elliptical.moc"