/* * Copyright 2017 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor 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 Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.selection; import pixelitor.Composition; import pixelitor.history.History; import pixelitor.history.NewSelectionEdit; import pixelitor.history.PixelitorEdit; import pixelitor.history.SelectionChangeEdit; import pixelitor.utils.Messages; import pixelitor.utils.test.RandomGUITest; import java.awt.Rectangle; import java.awt.Shape; public class SelectionBuilder { private final SelectionType selectionType; private final SelectionInteraction selectionInteraction; private final Composition comp; private Shape replacedShape; private boolean finished = false; /** * Called in mousePressed */ public SelectionBuilder(SelectionType selectionType, SelectionInteraction selectionInteraction, Composition comp) { this.selectionInteraction = selectionInteraction; this.selectionType = selectionType; this.comp = comp; Selection selection = comp.getSelection(); if (selection == null) { return; } startNewShape(selectionInteraction, selection); } /** * Called if there is already a selection in mousePressed */ private void startNewShape(SelectionInteraction selectionInteraction, Selection selection) { assert selection.isAlive() : "dead selection"; comp.setBuiltSelection(new Selection(null, comp.getIC())); if (selectionInteraction == SelectionInteraction.REPLACE) { replacedShape = selection.getShape(); // selection.stopMarching(); // selection.repaint(); comp.setSelection(null); selection.die(); } else { // // the current shape becomes the previous shape // // and will be replaced as mouse dragged events come // selection.setLastShape(selection.getShape()); selection.setFrozen(true); // selection.setHidden(false, false); // unhide } } /** * As the mouse is dragged or released, the current * selection shape is continuously updated */ public void updateSelection(Object mouseInfo) { Selection builtSelection = comp.getBuiltSelection(); boolean noPreviousSelection = builtSelection == null; if (noPreviousSelection) { Shape newShape = selectionType.createShape(mouseInfo, null); builtSelection = new Selection(newShape, comp.getIC()); comp.setBuiltSelection(builtSelection); } else { assert builtSelection.isAlive() : "dead selection"; Shape shape = builtSelection.getShape(); Shape newShape = selectionType.createShape(mouseInfo, shape); builtSelection.setShape(newShape); if (!builtSelection.isMarching()) { builtSelection.startMarching(); } } } /** * The mouse has been released and the currently drawn shape must be combined * with the already existing shape according to the selection interaction type */ public void combineShapes() { Selection oldSelection = comp.getSelection(); Selection builtSelection = comp.getBuiltSelection(); Shape newShape = builtSelection.getShape(); newShape = comp.clipShapeToCanvasSize(newShape); if (oldSelection != null) { // needs to combine the shapes Shape oldShape = oldSelection.getShape(); Shape combinedShape = selectionInteraction.combine(oldShape, newShape); Rectangle newBounds = combinedShape.getBounds(); if (newBounds.isEmpty()) { // nothing after combine builtSelection.setShape(oldShape); // for the correct deselect undo oldSelection.die(); comp.promoteSelection(); comp.deselect(true); if (!RandomGUITest.isRunning()) { Messages.showInfo("Nothing selected", "As a result of the " + selectionInteraction.toString().toLowerCase() + " operation, nothing is selected now."); } } else { oldSelection.die(); builtSelection.setShape(combinedShape); comp.promoteSelection(); PixelitorEdit edit = new SelectionChangeEdit(comp, oldShape, selectionInteraction.getNameForUndo()); History.addEdit(edit); } } else { // we can get here if either (1) a new selection // was created or (2) a selection was replaced if (newShape.getBounds().isEmpty()) { // the new shape can be empty if it has width or height = 0 comp.deselect(false); oldSelection = null; } else { builtSelection.setShape(newShape); comp.promoteSelection(); PixelitorEdit edit; if (replacedShape != null) { edit = new SelectionChangeEdit(comp, replacedShape, selectionInteraction.getNameForUndo()); } else { edit = new NewSelectionEdit(comp, builtSelection.getShape()); } History.addEdit(edit); } } finished = true; } public void cancelIfNotFinished() { if(!finished) { Selection builtSelection = comp.getBuiltSelection(); if (builtSelection != null) { builtSelection.die(); comp.setBuiltSelection(null); } // if we had a frozen selection, unfreeze Selection selection = comp.getSelection(); if (selection != null && selection.isFrozen()) { selection.setFrozen(false); } } } }