/* * 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.gui; import pixelitor.io.DropListener; import pixelitor.menus.view.ZoomLevel; import pixelitor.utils.Messages; import javax.swing.*; import java.awt.Dimension; import java.awt.dnd.DropTarget; import java.beans.PropertyVetoException; import java.util.List; import static java.awt.Color.GRAY; /** * The desktop area of the app */ public class Desktop { private static final int CASCADE_HORIZONTAL_SHIFT = 15; private static final int CASCADE_VERTICAL_SHIFT = 25; public static final Desktop INSTANCE = new Desktop(); private final JDesktopPane desktopPane; private Desktop() { desktopPane = new JDesktopPane(); GlobalKeyboardWatch.setAlwaysVisibleComponent(desktopPane); GlobalKeyboardWatch.registerBrushSizeActions(); new DropTarget(desktopPane, new DropListener()); desktopPane.setBackground(GRAY); } public static ZoomLevel calcFitScreenZoom(int imageWidth, int imageHeight, boolean alsoZoomInToFitScreen) { Dimension desktopSize = INSTANCE.getDesktopSize(); double desktopWidth = desktopSize.getWidth(); double desktopHeight = desktopSize.getHeight(); double imageToDesktopHorizontalRatio = imageWidth / desktopWidth; double imageToDesktopVerticalRatio = imageHeight / (desktopHeight - 35); // subtract because of internal frame header double maxImageToDesktopRatio = Math.max(imageToDesktopHorizontalRatio, imageToDesktopVerticalRatio); double idealZoomPercent = 100.0 / maxImageToDesktopRatio; ZoomLevel[] zoomLevels = ZoomLevel.values(); ZoomLevel maximallyZoomedOut = zoomLevels[0]; if (maximallyZoomedOut.getPercentValue() > idealZoomPercent) { // the image is so big that it will have scroll bars even if it is maximally zoomed out return maximallyZoomedOut; } ZoomLevel lastOK = maximallyZoomedOut; // iterate all the zoom levels from zoomed out to zoomed in for (ZoomLevel level : zoomLevels) { if (level.getPercentValue() > idealZoomPercent) { // found one that is too much zoomed in return lastOK; } if (!alsoZoomInToFitScreen) { // we don't want to zoom in more than 100% if (lastOK == ZoomLevel.Z100) { return lastOK; } } lastOK = level; } // if we get here, it means that the image is so small that even at maximal zoom // it fits the screen, set it then to the maximal zoom return lastOK; } public JDesktopPane getDesktopPane() { return desktopPane; } public void activateImageFrame(ImageFrame frame) { assert frame != null; desktopPane.getDesktopManager().activateFrame(frame); } public void cascadeWindows() { List<ImageComponent> icList = ImageComponents.getICList(); int locX = 0; int locY = 0; for (ImageComponent ic : icList) { ImageFrame frame = ic.getFrame(); frame.setLocation(locX, locY); frame.setToNaturalSize(locX, locY); try { frame.setIcon(false); frame.setMaximum(false); } catch (PropertyVetoException e) { e.printStackTrace(); } locX += CASCADE_HORIZONTAL_SHIFT; locY += CASCADE_VERTICAL_SHIFT; // wrap int maxWidth = desktopPane.getWidth() - CASCADE_HORIZONTAL_SHIFT; int maxHeight = desktopPane.getHeight() - CASCADE_VERTICAL_SHIFT; if (locX > maxWidth) { locX = 0; } if (locY > maxHeight) { locY = 0; } } } public void tileWindows() { List<ImageComponent> icList = ImageComponents.getICList(); int numWindows = icList.size(); int numRows = (int) Math.sqrt(numWindows); int numCols = numWindows / numRows; int extra = numWindows % numRows; int frameWidth = desktopPane.getWidth() / numCols; int frameHeight = desktopPane.getHeight() / numRows; int currRow = 0; int currCol = 0; for (ImageComponent ic : icList) { ImageFrame frame = ic.getFrame(); try { frame.setIcon(false); frame.setMaximum(false); } catch (PropertyVetoException e) { e.printStackTrace(); } int frameX = currCol * frameWidth; int frameY = currRow * frameHeight; frame.reshape(frameX, frameY, frameWidth, frameHeight); currRow++; if (currRow == numRows) { currRow = 0; currCol++; if (currCol == numCols - extra) { numRows++; frameHeight = desktopPane.getHeight() / numRows; } } } } public void addNewImageComponent(ImageComponent ic) { int numImages = ImageComponents.getNumOpenImages(); // called deliberately after numImages is set ImageComponents.addIC(ic); int locX = CASCADE_HORIZONTAL_SHIFT * numImages; int locY = CASCADE_VERTICAL_SHIFT * numImages; int maxWidth = desktopPane.getWidth() - CASCADE_HORIZONTAL_SHIFT; locX %= maxWidth; int maxHeight = desktopPane.getHeight() - CASCADE_VERTICAL_SHIFT; locY %= maxHeight; ImageFrame frame = new ImageFrame(ic, locX, locY); ic.setFrame(frame); desktopPane.add(frame); try { frame.setSelected(true); desktopPane.getDesktopManager().activateFrame(frame); ImageComponents.newImageOpened(ic.getComp()); } catch (PropertyVetoException e) { Messages.showException(e); } } public Dimension getDesktopSize() { return desktopPane.getSize(); } }