/* * kis_tool_select_rectangular.cpp -- part of Chalk * * Copyright (c) 1999 Michael Koch * 2001 John Califf * 2002 Patrick Julien * * 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_canvas_controller.h" #include "kis_canvas_subject.h" #include "kis_cursor.h" #include "kis_image.h" #include "kis_painter.h" #include "kis_layer.h" #include "kis_tool_select_rectangular.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 #include "kis_canvas.h" #include "kis_canvas_painter.h" KisToolSelectRectangular::KisToolSelectRectangular() : super(i18n("Rectangular Select Tool")) { setName("tool_select_rectangular"); setCursor(KisCursor::load("tool_rectangular_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; } KisToolSelectRectangular::~KisToolSelectRectangular() { } void KisToolSelectRectangular::activate() { super::activate(); if (!m_optWidget) return; m_optWidget->slotActivated(); } void KisToolSelectRectangular::update(KisCanvasSubject *subject) { m_subject = subject; super::update(m_subject); } void KisToolSelectRectangular::paint(KisCanvasPainter& gc) { if (m_selecting) paintOutline(gc, TQRect()); } void KisToolSelectRectangular::paint(KisCanvasPainter& gc, const TQRect& rc) { if (m_selecting) paintOutline(gc, rc); } void KisToolSelectRectangular::clearSelection() { if (m_subject) { KisCanvasController *controller = m_subject->canvasController(); KisImageSP img = m_subject->currentImg(); Q_ASSERT(controller); m_centerPos = KisPoint(0, 0); m_startPos = KisPoint(0, 0); m_endPos = KisPoint(0, 0); m_selecting = false; } } void KisToolSelectRectangular::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; } } } void KisToolSelectRectangular::move(KisMoveEvent *e) { if (m_subject && m_selecting) { paintOutline(); // move (alt) or resize rectangle 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); // square? 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 KisToolSelectRectangular::buttonRelease(KisButtonReleaseEvent *e) { if (m_subject && m_selecting && e->button() == TQt::LeftButton) { paintOutline(); if (m_startPos == m_endPos) { clearSelection(); } else { 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()) { TQApplication::setOverrideCursor(KisCursor::waitCursor()); KisPaintDeviceSP dev = img->activeDevice(); bool hasSelection = dev->hasSelection(); KisSelectedTransaction *t = 0; if (img->undo()) t = new KisSelectedTransaction(i18n("Rectangular Selection"), dev); KisSelectionSP selection = dev->selection(); TQRect rc(m_startPos.floorTQPoint(), m_endPos.floorTQPoint()); rc = rc.normalize(); // We don't want the border of the 'rectangle' to be included in our selection rc.setSize(rc.size() - TQSize(1,1)); if(! hasSelection) { selection->clear(); if(m_selectAction==SELECTION_SUBTRACT) selection->invert(); } KisSelectionSP tmpSel = new KisSelection(dev); tmpSel->select(rc); switch(m_selectAction) { case SELECTION_ADD: dev->addSelection(tmpSel); break; case SELECTION_SUBTRACT: dev->subtractSelection(tmpSel); break; default: break; } if(hasSelection) { dev->setDirty(rc); dev->emitSelectionChanged(rc); } else { dev->setDirty(); dev->emitSelectionChanged(); } if (img->undo()) img->undoAdapter()->addCommand(t); KisCanvasController *controller = m_subject -> canvasController(); controller -> kiscanvas() -> update(); TQApplication::restoreOverrideCursor(); } } m_selecting = false; } } void KisToolSelectRectangular::paintOutline() { if (m_subject) { KisCanvasController *controller = m_subject->canvasController(); KisCanvas *canvas = controller->kiscanvas(); KisCanvasPainter gc(canvas); TQRect rc; paintOutline(gc, rc); } } void KisToolSelectRectangular::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.drawRect(TQRect(start, end)); gc.setRasterOp(op); gc.setPen(old); } } void KisToolSelectRectangular::slotSetAction(int action) { if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT) m_selectAction =(enumSelectionMode)action; } void KisToolSelectRectangular::setup(TDEActionCollection *collection) { m_action = static_cast(collection->action(name())); if (m_action == 0) { m_action = new TDERadioAction(i18n("&Rectangular Selection"), "tool_rect_selection", TQt::Key_R, this, TQ_SLOT(activate()), collection, name()); TQ_CHECK_PTR(m_action); m_action->setExclusiveGroup("tools"); m_action->setToolTip(i18n("Select a rectangular area")); m_ownAction = true; } } TQWidget* KisToolSelectRectangular::createOptionWidget(TQWidget* parent) { m_optWidget = new KisSelectionOptions(parent, m_subject); TQ_CHECK_PTR(m_optWidget); m_optWidget->setCaption(i18n("Rectangular 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* KisToolSelectRectangular::optionWidget() { return m_optWidget; } #include "kis_tool_select_rectangular.moc"