/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2011-12 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.ui; import java.awt.Frame; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.io.*; import java.util.List; import processing.app.Preferences; import processing.core.PApplet; //import processing.core.PApplet; // scenarios: // 1) new untitled sketch (needs device, needs bounds) // 2) restoring sketch from recent menu // - device cannot be found // - device is found but it's a different size // - device is found and size is correct // 3) re-opening sketch in a new mode public class EditorState { // path to the main .pde file for the sketch // String path; // placement of the window // int windowX, windowY, windowW, windowH; Rectangle editorBounds; int dividerLocation; // width/height of the screen on which this window was placed // int displayW, displayH; // String deviceName; // not really useful b/c it's more about bounds anyway Rectangle deviceBounds; boolean isMaximized; // how far to offset a new window from the previous window static final int WINDOW_OFFSET = 28; /** * Create a fresh editor state object from the default screen device and * set its placement relative to the last opened window. * @param editors List of active editor objects */ public EditorState(List<Editor> editors) { defaultConfig(); defaultLocation(editors); } // EditorState(BufferedReader reader) throws IOException { // String line = reader.readLine(); // EditorState(String[] pieces) throws IOException { EditorState(String info) throws IOException { // String line = reader.readLine(); // String[] pieces = PApplet.split(line, '\t'); String[] pieces = PApplet.split(info, ','); // path = pieces[0]; editorBounds = new Rectangle(Integer.parseInt(pieces[0]), Integer.parseInt(pieces[1]), Integer.parseInt(pieces[2]), Integer.parseInt(pieces[3])); dividerLocation = Integer.parseInt(pieces[4]); deviceBounds = new Rectangle(Integer.parseInt(pieces[5]), Integer.parseInt(pieces[6]), Integer.parseInt(pieces[7]), Integer.parseInt(pieces[8])); // windowX = Integer.parseInt(pieces[1]); // windowY = Integer.parseInt(pieces[2]); // windowW = Integer.parseInt(pieces[3]); // windowH = Integer.parseInt(pieces[4]); // displayW = Integer.parseInt(pieces[5]); // displayH = Integer.parseInt(pieces[6]); } public String toString() { return (editorBounds.x + "," + editorBounds.y + "," + editorBounds.width + "," + editorBounds.height + "," + dividerLocation + "," + deviceBounds.x + "," + deviceBounds.y + "," + deviceBounds.width + "," + deviceBounds.height); } /** * Returns a GraphicsConfiguration so that a new Editor Frame can be * constructed. First tries to match the bounds for this state information * to an existing config (nominally, a display) and if that doesn't work, * then returns the default configuration/default display. */ GraphicsConfiguration checkConfig() { if (deviceBounds != null) { GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] screenDevices = graphicsEnvironment.getScreenDevices(); for (GraphicsDevice device : screenDevices) { GraphicsConfiguration[] configurations = device.getConfigurations(); for (GraphicsConfiguration config : configurations) { // if (config.getDevice().getIDstring().equals(deviceName)) { if (config.getBounds().equals(deviceBounds)) { return config; } } } } // otherwise go to the default config return defaultConfig(); } GraphicsConfiguration defaultConfig() { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice device = ge.getDefaultScreenDevice(); GraphicsConfiguration config = device.getDefaultConfiguration(); // deviceName = device.getIDstring(); deviceBounds = config.getBounds(); return config; } /** * Figure out the next location by sizing up the last editor in the list. * If no editors are opened, it'll just open on the main screen. * @param editors List of editors currently opened */ void defaultLocation(List<Editor> editors) { int defaultWidth = Toolkit.zoom(Preferences.getInteger("editor.window.width.default")); int defaultHeight = Toolkit.zoom(Preferences.getInteger("editor.window.height.default")); defaultWidth = Math.min(defaultWidth, deviceBounds.width); defaultHeight = Math.min(defaultHeight, deviceBounds.height); //System.out.println("default w/h = " + defaultWidth + "/" + defaultHeight); if (editors.size() == 0) { // If no current active editor, use default placement. // Center the window on ths screen, taking into account that the // upper-left corner of the device may have a non (0, 0) origin. int editorX = deviceBounds.x + (deviceBounds.width - defaultWidth) / 2; int editorY = deviceBounds.y + (deviceBounds.height - defaultHeight) / 2; editorBounds = new Rectangle(editorX, editorY, defaultWidth, defaultHeight); dividerLocation = 0; } else { // With a currently active editor, open the new window using the same // dimensions and divider location, but offset slightly. synchronized (editors) { Editor lastOpened = editors.get(editors.size() - 1); isMaximized = (lastOpened.getExtendedState() == Frame.MAXIMIZED_BOTH); editorBounds = lastOpened.getBounds(); editorBounds.x += WINDOW_OFFSET; editorBounds.y += WINDOW_OFFSET; dividerLocation = lastOpened.getDividerLocation(); if (!deviceBounds.contains(editorBounds)) { // Warp the next window to a randomish location on screen. editorBounds.x = deviceBounds.x + (int) (Math.random() * (deviceBounds.width - defaultWidth)); editorBounds.y = deviceBounds.y + (int) (Math.random() * (deviceBounds.height - defaultHeight)); } if (isMaximized) { editorBounds.width = defaultWidth; editorBounds.height = defaultHeight; } } } } void update(Editor editor) { // path = editor.getSketch().getMainFilePath(); editorBounds = editor.getBounds(); dividerLocation = editor.getDividerLocation(); GraphicsConfiguration config = editor.getGraphicsConfiguration(); // GraphicsDevice device = config.getDevice(); deviceBounds = config.getBounds(); // deviceName = device.getIDstring(); } void apply(Editor editor) { editor.setBounds(editorBounds); if (dividerLocation == 0) { dividerLocation = 2 * editor.getSize().height / 3; } editor.setDividerLocation(dividerLocation); if (isMaximized) { editor.setExtendedState(Frame.MAXIMIZED_BOTH); } } // void write(PrintWriter writer) { //// writer.print(path); // writer.print('\t'); // writeRect(writer, editorBounds); //// writer.print('\t'); //// writer.print(deviceName); // writer.print('\t'); // writeRect(writer, deviceBounds); // } // // // void writeRect(PrintWriter writer, Rectangle rect) { // writer.print(rect.x); // writer.print('\t'); // writer.print(rect.y); // writer.print('\t'); // writer.print(rect.width); // writer.print('\t'); // writer.print(rect.height); // } }