From fba2ecc384d6bced4d879bd34fe8c5db8dc4067e Mon Sep 17 00:00:00 2001 From: bancika Date: Thu, 20 Apr 2017 11:07:08 +0200 Subject: [PATCH] Added 'Recent Files' --- .../src/org/diylc/common/IPlugInPort.java | 1 + .../src/org/diylc/presenter/Presenter.java | 17 +++++ .../src/org/diylc/images/IconLoader.java | 2 +- .../src/org/diylc/images/document_plain.png | Bin 0 -> 547 bytes .../src/org/diylc/images/history.png | Bin 0 -> 957 bytes .../src/org/diylc/swing/ActionFactory.java | 2 +- .../diylc/swing/IDynamicSubmenuHandler.java | 10 +++ .../src/org/diylc/swing/ISwingUI.java | 19 +++-- .../src/org/diylc/swing/gui/MainFrame.java | 68 +++++++++++++++--- .../swing/plugins/file/FileMenuPlugin.java | 29 +++++++- diylc/diylc-swing/update.xml | 4 ++ 11 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 diylc/diylc-swing/src/org/diylc/images/document_plain.png create mode 100644 diylc/diylc-swing/src/org/diylc/images/history.png create mode 100644 diylc/diylc-swing/src/org/diylc/swing/IDynamicSubmenuHandler.java diff --git a/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java b/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java index c3098c9d..c6ba12de 100644 --- a/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java +++ b/diylc/diylc-core/src/org/diylc/common/IPlugInPort.java @@ -45,6 +45,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP public static final String OUTLINE_KEY = "outline"; public static final String THEME_KEY = "theme"; public static final String RECENT_COMPONENTS_KEY = "recentComponents"; + public static final String RECENT_FILES_KEY = "recentFiles"; public static final String SHOW_RULERS_KEY = "showRulers"; public static final String SHOW_GRID_KEY = "showGrid"; diff --git a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java index 8335c7d6..5a39fa5a 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/Presenter.java +++ b/diylc/diylc-core/src/org/diylc/presenter/Presenter.java @@ -84,6 +84,8 @@ public class Presenter implements IPlugInPort { public static final int ICON_SIZE = 32; + private static final int MAX_RECENT_FILES = 5; + private Project currentProject; private Map> componentTypes; /** @@ -248,12 +250,25 @@ public class Presenter implements IPlugInPort { builder.append(" recentFiles = (List) ConfigurationManager.getInstance().readObject(RECENT_FILES_KEY, null); + if (recentFiles == null) + recentFiles = new ArrayList(); + recentFiles.remove(fileName); + recentFiles.add(0, fileName); + while (recentFiles.size() > MAX_RECENT_FILES) + recentFiles.remove(recentFiles.size() - 1); + ConfigurationManager.getInstance().writeValue(RECENT_FILES_KEY, recentFiles); + } + @Override public boolean allowFileAction() { if (projectFileManager.isModified()) { @@ -282,6 +297,8 @@ public class Presenter implements IPlugInPort { try { currentProject.setFileVersion(CURRENT_VERSION); projectFileManager.serializeProjectToFile(currentProject, fileName, isBackup); + if (!isBackup) + addToRecentFiles(fileName); } catch (Exception ex) { LOG.error("Could not save file", ex); if (!isBackup) { diff --git a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java index f877b576..41ae7bad 100644 --- a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java +++ b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java @@ -39,7 +39,7 @@ public enum IconLoader { "messages.png"), SearchBox("search-box.png"), Screwdriver("screwdriver.png"), Hammer("hammer.png"), FlipHorizontal( "flip_horizontal.png"), FlipVertical("flip_vertical.png"), MagicWand("magic_wand.png"), PinGrey("pin_grey.png"), PinGreen( "pin_green.png"), CoffeebeanEdit("coffeebean_edit.png"), ApplicationEdit("application_edit.png"), ComponentAdd( - "component_add.png"); + "component_add.png"), History("history.png"), DocumentPlain("document_plain.png"); protected String name; diff --git a/diylc/diylc-swing/src/org/diylc/images/document_plain.png b/diylc/diylc-swing/src/org/diylc/images/document_plain.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ccb761d29af65755c95e65c0031cb6dadeb488 GIT binary patch literal 547 zcmV+;0^I$HP)WdKcYATc!{L3L*!GB7YTATcpIGch_bG$1Q5F)%RM{uz1z000McNliru z)&&<0F*%$asVx8i010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00DbR zL_t(|+Kp1NO2j}AoxSA1Lar4H@fR!Ykq(G`QwKYk*@cQz&e15!f z!H+Fw4k1Kf5LUO(X!GEjX6BdHxqXxw>1+(YfM-A~R zz8Gy%7-PT`wfC;kyn)u|7fejg?egO!v*sNnNeX{Kq<7X9IG3CS+Hlyol2=pA2j)k` zc47Gl1eVqlL~#VQ+A!of8u#^TDFZ!<6fEe3fV`MZ2lQ|z)&bDaoN@FbmK1~=A`bVT z1rBro12^bX@eZs2B6_?glahdjm-%JTPZ2kqxmprv zcM>PiTW7yO#+MWc`ePIUs`5rxwoWu4{|8avj*86?#F33nyEM&lW}P|4tiWK%@H6w0 l`J@6v%n?`rgAVge>Ni_b8MwhCI+p+d002ovPDHLkV1lHI*w6p~ literal 0 HcmV?d00001 diff --git a/diylc/diylc-swing/src/org/diylc/images/history.png b/diylc/diylc-swing/src/org/diylc/images/history.png new file mode 100644 index 0000000000000000000000000000000000000000..4f7ebd8e06e7ac59e3151b2219f4b643e8dc3cb3 GIT binary patch literal 957 zcmV;u148_XP)WdKcSATc)}L3L*!GB7YTATcmHGch_dH6SZ6F)%Q7;N&F$000McNliru z)&&<0G8b#+_aOiP010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00R|C zL_t(|+HI3tNK+G~%UovD3YuNkoh%bIA}HuZ?1GvVNGZMa*oEk&DC;Te zxiGQ_A`P?amQa~4oh+@j#nN;dy3M)Mrt|D^Tj>Z*XMrjblRKVzHNT(@$`oO29t>a%FB;76;xDhcyzlKh55S> zh$gUj{YJDtZ^GW)dB|OpqheXLITBHq=H!^GjK(F>?rz6dauuYx!> zuEfvZ5h?{C_vwrIDcXjmi*z^qz4|_=}HdUbHF!k!ilk*CVt}c7; zQ3a!-lj)R?uUerDxxlK`Xtz1IP-ryT+w1Ni{kZ5ubQ5E8tJTLQlf3%I_0yLZS)P{W ztTwMtM8nYQm*8a0ndwn=bvgXOV1T*;C-H-b6XGOzInR&W+P81r@%;S8L|xsBKAlbq zl}ZVN!2pF)1D*#)M@OS1{!RD@e`( z{xAXozj*p25lf~2&*TFG-fKKB+|g>aYNIg|Ceu=sl;v getAvailableItems(); +} diff --git a/diylc/diylc-swing/src/org/diylc/swing/ISwingUI.java b/diylc/diylc-swing/src/org/diylc/swing/ISwingUI.java index 1af5be28..8844d701 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/ISwingUI.java +++ b/diylc/diylc-swing/src/org/diylc/swing/ISwingUI.java @@ -48,9 +48,8 @@ public interface ISwingUI extends IView { void injectMenuAction(Action action, String menuName); /** - * Injects a custom submenu into application's main menu. If action is set to null - * {@link Separator} will be added. If the specified menu does not exist it will be automatically - * created. + * Injects a custom submenu into application's main menu. If the specified menu does not exist it + * will be automatically created. * * @param name * @param icon @@ -58,6 +57,18 @@ public interface ISwingUI extends IView { */ void injectSubmenu(String name, Icon icon, String parentMenuName); + /** + * Injects a dynamic submenu into application's main menu. Items are read from the + * handler and notifications are sent to the handler when an item is + * clicked on. + * + * @param name + * @param icon + * @param parentMenuName + * @param handler + */ + void injectDynamicSubmenu(String name, Icon icon, String parentMenuName, IDynamicSubmenuHandler handler); + /** * Runs a task in background while showing busy cursor and a glass pane. * @@ -69,7 +80,7 @@ public interface ISwingUI extends IView { * @return {@link JFrame} that can be used to reference secondary dialogs and frames */ JFrame getOwnerFrame(); - + /** * */ 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 6972dabc..bb46e83e 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/MainFrame.java @@ -8,9 +8,6 @@ import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; @@ -28,12 +25,15 @@ import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; +import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; import javax.swing.SwingConstants; import javax.swing.SwingWorker; import javax.swing.Timer; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; import org.apache.log4j.Logger; import org.diylc.appframework.miscutils.ConfigurationManager; @@ -46,6 +46,7 @@ import org.diylc.common.PropertyWrapper; import org.diylc.core.IView; 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.editor.PropertyEditorDialog; import org.diylc.swing.plugins.autosave.AutoSavePlugin; @@ -94,10 +95,10 @@ public class MainFrame extends JFrame implements ISwingUI { DialogFactory.getInstance().initialize(this); this.presenter = new Presenter(this); - + canvasPlugin = new CanvasPlugin(this); - presenter.installPlugin(new ToolBox(this)); + presenter.installPlugin(new ToolBox(this)); presenter.installPlugin(new FileMenuPlugin(this)); presenter.installPlugin(new EditMenuPlugin(this)); presenter.installPlugin(new ConfigPlugin(this)); @@ -106,12 +107,12 @@ public class MainFrame extends JFrame implements ISwingUI { presenter.installPlugin(new HelpMenuPlugin(this)); presenter.installPlugin(new StatusBar(this)); - + presenter.installPlugin(canvasPlugin); - + presenter.installPlugin(new ComponentTree(this, canvasPlugin.getCanvasPanel())); presenter.installPlugin(new FramePlugin()); - + presenter.installPlugin(new AutoSavePlugin(this)); presenter.createNewProject(); @@ -302,6 +303,52 @@ public class MainFrame extends JFrame implements ISwingUI { menuMap.put(name, submenu); } + @Override + public void injectDynamicSubmenu(String name, Icon icon, String parentMenuName, final IDynamicSubmenuHandler handler) { + LOG.info(String.format("injectDynamicSubmenu(%s, icon, %s)", name, parentMenuName)); + final JMenu menu = findOrCreateMenu(parentMenuName); + final JMenu submenu = new JMenu(name); + submenu.setIcon(icon); + menu.add(submenu); + menuMap.put(name, submenu); + + final JMenuItem emptyItem = new JMenuItem(""); + emptyItem.setEnabled(false); + submenu.add(emptyItem); + + submenu.addMenuListener(new MenuListener() { + + @Override + public void menuSelected(MenuEvent e) { + submenu.removeAll(); + List items = handler.getAvailableItems(); + if (items == null || items.isEmpty()) + submenu.add(emptyItem); + else + for (String item : items) { + final JMenuItem menuItem = new JMenuItem(item); + menuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + handler.onActionPerformed(menuItem.getText()); + } + }); + submenu.add(menuItem); + } + submenu.revalidate(); + submenu.repaint(); + submenu.doClick(); + } + + @Override + public void menuDeselected(MenuEvent e) {} + + @Override + public void menuCanceled(MenuEvent e) {} + }); + } + @Override public void executeBackgroundTask(final ITask task) { getGlassPane().setVisible(true); @@ -326,7 +373,7 @@ public class MainFrame extends JFrame implements ISwingUI { getGlassPane().setVisible(false); LOG.error("Background task execution interrupted", e); task.failed(e); - } + } } }; worker.execute(); @@ -365,7 +412,8 @@ public class MainFrame extends JFrame implements ISwingUI { fileName = "Untitled"; } String modified = (Boolean) params[1] ? " (modified)" : ""; - setTitle(String.format("DIYLC G3 version %s.%s - %s %s", plugInPort.getCurrentVersionNumber().getMinor(), plugInPort.getCurrentVersionNumber().getBuild(), fileName, modified)); + setTitle(String.format("DIYLC G3 version %s.%s - %s %s", plugInPort.getCurrentVersionNumber().getMinor(), + plugInPort.getCurrentVersionNumber().getBuild(), fileName, modified)); } } } diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/file/FileMenuPlugin.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/file/FileMenuPlugin.java index 06731d42..767b7d5f 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/file/FileMenuPlugin.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/file/FileMenuPlugin.java @@ -1,12 +1,16 @@ package org.diylc.swing.plugins.file; import java.util.EnumSet; +import java.util.List; +import org.apache.log4j.Logger; +import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.common.EventType; import org.diylc.common.IPlugIn; import org.diylc.common.IPlugInPort; import org.diylc.images.IconLoader; import org.diylc.swing.ActionFactory; +import org.diylc.swing.IDynamicSubmenuHandler; import org.diylc.swing.ISwingUI; /** @@ -14,7 +18,9 @@ import org.diylc.swing.ISwingUI; * * @author Branislav Stojkovic */ -public class FileMenuPlugin implements IPlugIn { +public class FileMenuPlugin implements IPlugIn, IDynamicSubmenuHandler { + + private static final Logger LOG = Logger.getLogger(FileMenuPlugin.class); private static final String FILE_TITLE = "File"; private static final String TRACE_MASK_TITLE = "Trace Mask"; @@ -23,6 +29,7 @@ public class FileMenuPlugin implements IPlugIn { private TraceMaskDrawingProvider traceMaskDrawingProvider; private ISwingUI swingUI; + private IPlugInPort plugInPort; public FileMenuPlugin(ISwingUI swingUI) { super(); @@ -31,6 +38,7 @@ public class FileMenuPlugin implements IPlugIn { @Override public void connect(IPlugInPort plugInPort) { + this.plugInPort = plugInPort; this.drawingProvider = new ProjectDrawingProvider(plugInPort, false, true); this.traceMaskDrawingProvider = new TraceMaskDrawingProvider(plugInPort); @@ -40,6 +48,7 @@ public class FileMenuPlugin implements IPlugIn { swingUI.injectMenuAction(actionFactory.createImportAction(plugInPort, swingUI), FILE_TITLE); swingUI.injectMenuAction(actionFactory.createSaveAction(plugInPort, swingUI), FILE_TITLE); swingUI.injectMenuAction(actionFactory.createSaveAsAction(plugInPort, swingUI), FILE_TITLE); + swingUI.injectDynamicSubmenu("Recent Files", IconLoader.History.getIcon(), FILE_TITLE, this); swingUI.injectMenuAction(null, FILE_TITLE); swingUI.injectMenuAction(actionFactory.createExportPDFAction(drawingProvider, swingUI), FILE_TITLE); swingUI.injectMenuAction(actionFactory.createExportPNGAction(drawingProvider, swingUI), FILE_TITLE); @@ -62,4 +71,22 @@ public class FileMenuPlugin implements IPlugIn { public void processMessage(EventType eventType, Object... params) { // Do nothing. } + + // Dynamic menu for recent files + + @Override + public void onActionPerformed(String name) { + LOG.info("Openning recent file: " + name); + if (!plugInPort.allowFileAction()) { + LOG.info("Aborted openning recent file"); + return; + } + this.plugInPort.loadProjectFromFile(name); + } + + @SuppressWarnings("unchecked") + @Override + public List getAvailableItems() { + return (List) ConfigurationManager.getInstance().readObject(IPlugInPort.RECENT_FILES_KEY, null); + } } diff --git a/diylc/diylc-swing/update.xml b/diylc/diylc-swing/update.xml index 6ed442b9..5519639c 100644 --- a/diylc/diylc-swing/update.xml +++ b/diylc/diylc-swing/update.xml @@ -1646,6 +1646,10 @@ 2017-04-10 20:00:00.000 CET + + NEW_FEATURE + Added 'Recent Files' to the main menu to keep track of the previous 10 files + NEW_FEATURE Hold Control key to zoom with mouse wheel. Zooming tracks mouse cursor position