AddingMRUList

This is a tutorial on how to create most recently used files for the Netbeans Platform based application.

Note: this tutorial utilize the new NbPreferences available in the upcoming Netbeans 6

Create the persistence mechanism

Just a boiler plate code to create persistence mechanism. The importance things in here is the NbPreferences that wrap the java Preferences to provide Nb specific location for persistence. If you do not like to use NbPreferences, you could replace it with java Preferences. Also note, this class is singleton.

public class MRUFilesOptions implements Options {
    protected static String DEFAULT_NODE_NAME = "prefs";
    protected String nodeName = null;
    private EventListenerList listenerList;
 
    public static final String MRU_FILE_LIST_PROPERTY = "MRUFileList";
 
    private List<String> mruFileList;
    private int maxSize;
 
    private static MRUFilesOptions instance; // The single instance
    static {
        instance = new MRUFilesOptions();
    }
 
    /**
     * Returns the single instance, creating one if it's the
     * first time this method is called.
     *
     * @return The single instance.
     */
    public static MRUFilesOptions getInstance() {
        return instance;
    }
 
    /** {@inheritDoc} */
    protected MRUFilesOptions() {
        nodeName = "mrufiles";
        maxSize = 9; // default is 9
        mruFileList = new ArrayList<String>(maxSize);
        listenerList = new EventListenerList();
        retrieve();
    }
 
    public List<String> getMRUFileList() {
        return mruFileList;
    }
 
    public void setMRUFileList(List<String> list) {
        this.mruFileList.clear();
        this.mruFileList.addAll(list.subList(0, Math.min(list.size(), maxSize)));
        firePropertyChange(MRU_FILE_LIST_PROPERTY, null, mruFileList);
        store();
    }
 
    public void addFile(String absolutePath) {
        // remove the old
        mruFileList.remove(absolutePath);
 
        // add to the top
        mruFileList.add(0, absolutePath);
        while (mruFileList.size() > maxSize) {
            mruFileList.remove(mruFileList.size() - 1);
        }
        firePropertyChange(MRU_FILE_LIST_PROPERTY, null, mruFileList);
        store();
    }
 
    protected void store() {
        Preferences prefs = getPreferences();
 
        // clear the backing store
        try {
            prefs.clear();
        } catch (BackingStoreException ex) { }
 
        for (int i = 0; i < mruFileList.size(); i++) {
            String str = mruFileList.get(i);
            prefs.put(MRU_FILE_LIST_PROPERTY + i, str);
        }
    }
 
    protected void retrieve() {
        mruFileList.clear();
        Preferences prefs = getPreferences();
 
        for (int i = 0; i < maxSize; i++) {
            String str = prefs.get(MRU_FILE_LIST_PROPERTY + i, null);
            if (str != null) {
                mruFileList.add(str);
            } else {
                break;
            }
        }
    }
 
    /** {@inheritDoc} */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        listenerList.add(PropertyChangeListener.class, listener);
    }
 
    /** {@inheritDoc} */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        listenerList.remove(PropertyChangeListener.class, listener);
    }
 
    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == PropertyChangeListener.class) {
                ((PropertyChangeListener) listeners[i+1]).propertyChange(event);
            }
        }
    }
 
    /** Return the backing store Preferences
     * @return Preferences
     */
    protected final Preferences getPreferences() {
        String name = DEFAULT_NODE_NAME;
        if (nodeName != null) {
            name = nodeName;
        }
 
        Preferences prefs = NbPreferences.forModule(this.getClass()).node("options").node(name);
 
        return prefs;
    }
}

Create the action

Just another boiler plate code for creating action. The importance things in here is the getMenuPresenter, this menu presenter need to return submenu that containt the most recently used files and must be dynamic. On the actionPerformed just call the DataObject OpenCookie.

public final class MRUFilesAction extends CallableSystemAction {
 
    /** {@inheritDoc}
     * do nothing
     */
    public void performAction() {
        // do nothing
    }
 
    /** {@inheritDoc} */
    public String getName() {
        return NbBundle.getMessage(MRUFilesAction.class, "CTL_MRUFilesAction");
    }
 
 
    /** {@inheritDoc} */
    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }
 
    /** {@inheritDoc} */
    protected boolean asynchronous() {
        return false;
    }
 
    /** {@inheritDoc}
     * Overide to provide SubMenu for MRUFiles (Most Recently Used Files)
     */
    public JMenuItem getMenuPresenter() {
        JMenu menu = new MRUFilesMenu(getName());
        return menu;
    }
 
 
 
    class MRUFilesMenu extends JMenu implements DynamicMenuContent {
 
        public MRUFilesMenu(String s) {
            super(s);
 
            MRUFilesOptions opts = MRUFilesOptions.getInstance();
            opts.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent evt) {
                    if (!evt.getPropertyName().equals(MRUFilesOptions.MRU_FILE_LIST_PROPERTY)) {
                       return;
                    }
                    updateMenu();
                }
            });
 
            updateMenu();
        }
 
        public JComponent[] getMenuPresenters() {
            return new JComponent[] {this};
        }
 
        public JComponent[] synchMenuPresenters(JComponent[] items) {
            return getMenuPresenters();
        }
 
        private void updateMenu() {
            removeAll();
            MRUFilesOptions opts = MRUFilesOptions.getInstance();
            List<String> list = opts.getMRUFileList();
            for (String name : list) {
                Action action = createAction(name);
                action.putValue(Action.NAME,name);
                JMenuItem menuItem = new JMenuItem(action);
                add(menuItem);
            }
        }
 
 
        private Action createAction(String actionCommand) {
            Action action = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    menuItemActionPerformed(e);
                }
            };
 
            action.putValue(Action.ACTION_COMMAND_KEY, actionCommand);
            return action;
        }
 
        private void menuItemActionPerformed(ActionEvent evt) {
            String command = evt.getActionCommand();
            File file = new File(command);
 
            try {
                DataObject data = DataObject.find(FileUtil.toFileObject(file));
                OpenCookie cookie = data.getCookie(OpenCookie.class);
                cookie.open();
            } catch (OutOfMemoryError ex) {
                String msg = Application.getMessage("MSG_OutOfMemoryError.Text");
                NotifyDescriptor nd =  new NotifyDescriptor.Message(msg, NotifyDescriptor.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(nd);
            } catch (Exception ex) {
                NotifyDescriptor nd =  new NotifyDescriptor.Message(ex.getMessage(), NotifyDescriptor.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(nd);
            }
        }
    }
}

Register the action

As usual in Nb Platform you register the action in the layer xml file

<filesystem>
    <folder name="Actions">
        <folder name="File">
            <file name="kiyut-sketsa-actions-MRUFilesAction.instance">
                <attr name="instanceClass"
                    stringvalue="kiyut.sketsa.actions.MRUFilesAction"/>
            </file>
         ....
         </folder>
      <folder>
    <folder name="Menu">
        <folder name="File">
            <file name="kiyut-sketsa-actions-MRUFilesAction.shadow">
                <attr name="originalFile" 
                    stringvalue="Actions/File/kiyut-sketsa-actions-MRUFilesAction.instance"/>
                <attr name="position" intvalue="300"/>
            </file>
        ....
        </folder>
    <folder>
    ....

What’s left

Everything is done now. Just do not forget to call addFile in OpenAction, OpenCookie, Data Loader Open, etc into the MRUFilesOptions like the code below.

MRUFilesOptions opts = MRUFilesOptions.getInstance();
opts.addFile(newFile.getAbsolutePath());

You may also call addFile when the user saving the file as well.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo