diff --git a/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java b/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java index c1871f81..ad15a64a 100644 --- a/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java +++ b/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java @@ -121,9 +121,10 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP * Loads specified {@link Project}. * * @param project - * @param freshStart + * @param freshStart + * @param optional file name when loading from a file */ - void loadProject(Project project, boolean freshStart); + void loadProject(Project project, boolean freshStart, String filename); /** * Creates a new project. diff --git a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java index 2cccb1e2..b297b6ee 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java +++ b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java @@ -273,13 +273,13 @@ public class Presenter implements IPlugInPort { } @Override - public void loadProject(Project project, boolean freshStart) { + public void loadProject(Project project, boolean freshStart, String filename) { LOG.info(String.format("loadProject(%s, %s)", project.getTitle(), freshStart)); this.currentProject = project; drawingManager.clearComponentAreaMap(); drawingManager.clearContinuityArea(); updateSelection(EMPTY_SELECTION); - messageDispatcher.dispatchMessage(EventType.PROJECT_LOADED, project, freshStart); + messageDispatcher.dispatchMessage(EventType.PROJECT_LOADED, project, freshStart, filename); messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.LAYER_STATE_CHANGED, currentProject.getLockedLayers()); messageDispatcher.dispatchMessage(EventType.LAYER_VISIBILITY_CHANGED, currentProject.getHiddenLayers()); @@ -291,7 +291,7 @@ public class Presenter implements IPlugInPort { try { Project project = new Project(); instantiationManager.fillWithDefaultProperties(project, null); - loadProject(project, true); + loadProject(project, true, null); projectFileManager.startNewFile(); } catch (Exception e) { LOG.error("Could not create new file", e); @@ -306,7 +306,7 @@ public class Presenter implements IPlugInPort { try { warnings = new ArrayList(); Project project = (Project) projectFileManager.deserializeProjectFromFile(fileName, warnings); - loadProject(project, true); + loadProject(project, true, fileName); projectFileManager.fireFileStatusChanged(); if (!warnings.isEmpty()) { StringBuilder builder = new StringBuilder("File was opened, but there were some issues with it:

"); diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index 01e2ed7f..0799783c 100644 Binary files a/diylc/diylc-library/lib/diylc-core.jar and b/diylc/diylc-library/lib/diylc-core.jar differ diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index 01e2ed7f..0799783c 100644 Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java b/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java index 1fa6ecaa..d07955cd 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java @@ -69,7 +69,7 @@ import org.diylc.images.IconLoader; import org.diylc.presenter.Presenter; import org.diylc.swing.IDynamicSubmenuHandler; import org.diylc.swing.ISwingUI; -import org.diylc.swing.gui.actionBar.ActionBarPlugin; +import org.diylc.swing.gui.actionbar.ActionBarPlugin; import org.diylc.swing.gui.editor.PropertyEditorDialog; import org.diylc.swing.plugins.autosave.AutoSavePlugin; import org.diylc.swing.plugins.canvas.CanvasPlugin; diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/TemplateDialog.java b/diylc/diylc-swing/src/org/diylc/swing/gui/TemplateDialog.java index 8385bd84..2286372d 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/TemplateDialog.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/TemplateDialog.java @@ -185,7 +185,7 @@ public class TemplateDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { - plugInPort.loadProject(presenter.getCurrentProject(), true); + plugInPort.loadProject(presenter.getCurrentProject(), true, null); dispose(); } }); diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/ActionBarPlugin.java b/diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/ActionBarPlugin.java similarity index 98% rename from diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/ActionBarPlugin.java rename to diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/ActionBarPlugin.java index 0daab3e0..4cf795df 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/ActionBarPlugin.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/ActionBarPlugin.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License along with DIYLC. If not, see * . */ -package org.diylc.swing.gui.actionBar; +package org.diylc.swing.gui.actionbar; import java.awt.BorderLayout; import java.util.EnumSet; diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/MiniToolbar.java b/diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/MiniToolbar.java similarity index 94% rename from diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/MiniToolbar.java rename to diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/MiniToolbar.java index b3b02b8b..40aaeeb2 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/actionBar/MiniToolbar.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/actionbar/MiniToolbar.java @@ -19,7 +19,7 @@ along with DIYLC. If not, see . */ -package org.diylc.swing.gui.actionBar; +package org.diylc.swing.gui.actionbar; import java.awt.Component; import java.awt.Cursor; diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/autosave/AutoSavePlugin.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/autosave/AutoSavePlugin.java index 1fb21043..f47d7ba4 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/autosave/AutoSavePlugin.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/autosave/AutoSavePlugin.java @@ -1,27 +1,28 @@ /* + * + * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC 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 3 of the + * License, or (at your option) any later version. + * + * DIYLC 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 DIYLC. If not, see + * . + */ +package org.diylc.swing.plugins.autosave; - DIY Layout Creator (DIYLC). - Copyright (c) 2009-2018 held jointly by the individual authors. - - This file is part of DIYLC. - - DIYLC 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 3 of the License, or - (at your option) any later version. - - DIYLC 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 DIYLC. If not, see . - -*/ -package org.diylc.swing.plugins.autosave; - import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; @@ -37,71 +38,99 @@ import org.diylc.common.EventType; import org.diylc.common.IPlugIn; import org.diylc.common.IPlugInPort; import org.diylc.core.IView; - -public class AutoSavePlugin implements IPlugIn { - + +public class AutoSavePlugin implements IPlugIn { + private static final String AUTO_SAVE_PATH = Utils.getUserDataDirectory("diylc") + "autoSave"; - - private static final Logger LOG = Logger.getLogger(AutoSavePlugin.class); - + + private static final Logger LOG = Logger.getLogger(AutoSavePlugin.class); + public static long BACKUP_FREQ_MS = 60 * 1000; - public static int MAX_TOTAL_SIZE_MB = 64; - - private ExecutorService executor; - - private IPlugInPort plugInPort; - private long lastSave = 0; - - public AutoSavePlugin(IView view) { - executor = Executors.newSingleThreadExecutor(); - } - - @Override - public void connect(IPlugInPort plugInPort) { + public static int MAX_TOTAL_SIZE_MB = 64; + + private ExecutorService executor; + + private IPlugInPort plugInPort; + private long lastSave = 0; + + public AutoSavePlugin(IView view) { + executor = Executors.newSingleThreadExecutor(); + } + + @Override + public void connect(IPlugInPort plugInPort) { this.plugInPort = plugInPort; // create the directory if needed File dir = new File(AUTO_SAVE_PATH); if (!dir.exists()) - dir.mkdirs(); - } - - @Override - public EnumSet getSubscribedEventTypes() { - return EnumSet.of(EventType.PROJECT_MODIFIED); - } - - @Override - public void processMessage(EventType eventType, Object... params) { - if (eventType == EventType.PROJECT_MODIFIED) { - if (System.currentTimeMillis() - lastSave > BACKUP_FREQ_MS) { - executor.execute(new Runnable() { - - @Override - public void run() { - Thread.currentThread().setPriority(Thread.MIN_PRIORITY); - - lastSave = System.currentTimeMillis(); - String fileName = generateBackupFileName(plugInPort.getCurrentFileName()); - plugInPort.saveProjectToFile(fileName, true); - cleanupExtra(); - } - }); - } - } + dir.mkdirs(); } - + + @Override + public EnumSet getSubscribedEventTypes() { + return EnumSet.of(EventType.PROJECT_MODIFIED, EventType.PROJECT_LOADED); + } + + @Override + public void processMessage(EventType eventType, Object... params) { + if (eventType == EventType.PROJECT_MODIFIED) { + if (System.currentTimeMillis() - lastSave > BACKUP_FREQ_MS) { + executor.execute(new Runnable() { + + @Override + public void run() { + Thread.currentThread().setPriority(Thread.MIN_PRIORITY); + + lastSave = System.currentTimeMillis(); + String fileName = generateBackupFileName(plugInPort.getCurrentFileName()); + plugInPort.saveProjectToFile(fileName, true); + cleanupExtra(); + } + }); + } + } else if (eventType == EventType.PROJECT_LOADED) { + String fileName = (String) params[2]; + if (fileName != null) { + String backupName = generateBackupFileName(fileName); + try { + copyFileUsingStream(new File(fileName), new File(backupName)); + LOG.info("Copied loaded file to " + backupName); + } catch (IOException e) { + LOG.error("Could not copy the loaded file to backup", e); + } + } + } + } + + private static void copyFileUsingStream(File source, File dest) throws IOException { + InputStream is = null; + OutputStream os = null; + try { + is = new FileInputStream(source); + os = new FileOutputStream(dest); + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) > 0) { + os.write(buffer, 0, length); + } + } finally { + is.close(); + os.close(); + } + } + private String generateBackupFileName(String baseFileName) { if (baseFileName == null) baseFileName = "Untitled"; File file = new File(baseFileName); String name = file.getName(); - + // remove extension if (name.toLowerCase().endsWith(".diy")) - name = name.substring(name.length() - 4); - + name = name.substring(0, name.length() - 4); + // append date and time - Date date = new Date(); + Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss"); file = new File(AUTO_SAVE_PATH + File.separator + name + "." + dateFormat.format(date) + ".diy"); // make sure that it doesn't already exist @@ -112,16 +141,16 @@ public class AutoSavePlugin implements IPlugIn { } return file.getAbsolutePath(); } - + private void cleanupExtra() { File[] files = new File(AUTO_SAVE_PATH).listFiles(); // sort files by date Arrays.sort(files, new Comparator() { @Override - public int compare(File o1, File o2) { + public int compare(File o1, File o2) { return new Long(o1.lastModified()).compareTo(o2.lastModified()); - } + } }); long totalSize = 0; long maxTotalSize = MAX_TOTAL_SIZE_MB * 1024 * 1024; @@ -134,5 +163,5 @@ public class AutoSavePlugin implements IPlugIn { files[i].delete(); i++; } - } -} + } +} diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/edit/EditMenuPlugin.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/edit/EditMenuPlugin.java index 7e051a74..303fd462 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/edit/EditMenuPlugin.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/edit/EditMenuPlugin.java @@ -93,7 +93,7 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner { @Override public void actionPerformed(Project currentState) { - plugInPort.loadProject(currentState, false); + plugInPort.loadProject(currentState, false, null); } }); clipboard.addFlavorListener(new FlavorListener() { diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/file/ProjectPreview.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/file/ProjectPreview.java index 59bcce40..7d497365 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/file/ProjectPreview.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/file/ProjectPreview.java @@ -104,7 +104,7 @@ public class ProjectPreview extends JPanel implements PropertyChangeListener, IF } nameLabel.setText(selectedProject.getTitle()); - presenter.loadProject(selectedProject, true); + presenter.loadProject(selectedProject, true, null); if (update) { if (renderComponent.isShowing()) {