diff --git a/favorites/nbproject/project.xml b/favorites/nbproject/project.xml --- a/favorites/nbproject/project.xml +++ b/favorites/nbproject/project.xml @@ -257,7 +257,11 @@ - + + org.netbeans.modules.kenai.ui + org.netbeans.modules.favorites.api + diff --git a/favorites/src/org/netbeans/modules/favorites/Actions.java b/favorites/src/org/netbeans/modules/favorites/Actions.java --- a/favorites/src/org/netbeans/modules/favorites/Actions.java +++ b/favorites/src/org/netbeans/modules/favorites/Actions.java @@ -56,6 +56,7 @@ import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.SwingUtilities; +import org.netbeans.modules.favorites.api.Favorites; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.filesystems.FileObject; @@ -147,14 +148,14 @@ Tab proj = Tab.findDefault(); proj.open(); proj.requestActive(); - proj.doSelectNode((DataObject)activatedNodes[0].getCookie(DataObject.class)); + proj.doSelectNode(activatedNodes[0].getCookie(DataObject.class)); } protected boolean enable(Node[] activatedNodes) { if (activatedNodes.length != 1) { return false; } - DataObject dobj = (DataObject)activatedNodes[0].getCookie(DataObject.class); + DataObject dobj = activatedNodes[0].getCookie(DataObject.class); if (dobj == null) { return false; } @@ -167,12 +168,14 @@ } /** Overriden to have different title in popup menu, works but ugly a bit */ + @Override public JMenuItem getPopupPresenter() { JMenuItem mi = super.getPopupPresenter(); mi.setText(NbBundle.getMessage(Select.class, "ACT_Select")); // NOI18N return mi; } + @Override protected String iconResource() { return "org/netbeans/modules/favorites/resources/actionSelect.png"; // NOI18N } @@ -181,6 +184,7 @@ return null; } + @Override protected boolean asynchronous() { return false; } @@ -207,9 +211,9 @@ if ((arr == null) || (arr.length == 0)) return false; for (int i = 0; i < arr.length; i++) { - DataObject shad = (DataObject) arr[i].getCookie (DataObject.class); + DataObject shad = arr[i].getCookie(DataObject.class); //Disable when node is not shadow in Favorites folder. - if (shad == null || shad.getFolder() != Favorites.getFolder()) { + if (shad == null || shad.getFolder() != FavoritesNode.getFolder()) { return false; } } @@ -239,9 +243,9 @@ */ protected void performAction (Node[] arr) { for (int i = 0; i < arr.length; i++) { - DataObject shad = (DataObject) arr[i].getCookie(DataObject.class); + DataObject shad = arr[i].getCookie(DataObject.class); - if (shad != null && shad.getFolder() == Favorites.getFolder()) { + if (shad != null && shad.getFolder() == FavoritesNode.getFolder()) { try { shad.delete(); } catch (IOException ex) { @@ -251,6 +255,7 @@ } } + @Override protected boolean asynchronous() { return false; } @@ -280,12 +285,12 @@ */ public boolean enable (Node[] arr) { if ((arr == null) || (arr.length == 0)) return false; - if (arr.length == 1 && arr[0] instanceof Favorites) return true; + if (arr.length == 1 && arr[0] instanceof FavoritesNode) return true; for (int i = 0; i < arr.length; i++) { - DataObject dataObject = (DataObject) arr[i].getCookie (DataObject.class); + DataObject dataObject = arr[i].getCookie(DataObject.class); //Action is disabled for root folder eg:"/" on Linux or "C:" on Win if (dataObject == null) { return false; @@ -297,7 +302,7 @@ return false; } //Allow to link only once - if (isInFavorites(fo)) { + if (Favorites.getDefault().isInFavorites(fo)) { return false; } //Check if it is root. @@ -322,23 +327,6 @@ return true; } - /** Check if given fileobject is already linked in favorites - * @return true if given fileobject is already linked - */ - private boolean isInFavorites (FileObject fo) { - DataFolder f = Favorites.getFolder(); - - DataObject [] arr = f.getChildren(); - for (int i = 0; i < arr.length; i++) { - if (arr[i] instanceof DataShadow) { - if (fo.equals(((DataShadow) arr[i]).getOriginal().getPrimaryFile())) { - return true; - } - } - } - return false; - } - /** Human presentable name of the action. This should be * presented as an item in a menu. * @return the name of the action @@ -361,7 +349,7 @@ * @param activatedNodes gives array of actually activated nodes. */ protected void performAction (final Node[] activatedNodes) { - final DataFolder f = Favorites.getFolder(); + final DataFolder f = FavoritesNode.getFolder(); final DataObject [] arr = f.getChildren(); final List listAdd = new ArrayList(); @@ -369,7 +357,7 @@ Node[] toShadows = activatedNodes; try { - if (activatedNodes.length == 1 && activatedNodes[0] instanceof Favorites) { + if (activatedNodes.length == 1 && activatedNodes[0] instanceof FavoritesNode) { // show JFileChooser FileObject fo = chooseFileObject(); if (fo == null) return; @@ -430,13 +418,13 @@ return retVal; } - static void selectAfterAddition(final DataObject createdDO) { + public static void selectAfterAddition(final DataObject createdDO) { final Tab projectsTab = Tab.findDefault(); projectsTab.open(); projectsTab.requestActive(); //Try to locate newly added node and select it if (createdDO != null) { - Node n = Favorites.getNode(); + Node n = FavoritesNode.getNode(); Node [] nodes = projectsTab.getExplorerManager().getRootContext().getChildren().getNodes(true); final Node [] toSelect = new Node[1]; boolean setSelected = false; @@ -464,7 +452,7 @@ static DataObject createShadows(final DataFolder favourities, final Node[] activatedNodes, final List listAdd) { DataObject createdDO = null; for (int i = 0; i < activatedNodes.length; i++) { - DataObject obj = (DataObject) activatedNodes[i].getCookie(DataObject.class); + DataObject obj = activatedNodes[i].getCookie(DataObject.class); if (obj != null) { try { @@ -483,7 +471,7 @@ return createdDO; } - static void reorderAfterAddition(final DataFolder favourities, final DataObject[] children, final List listAdd) { + public static void reorderAfterAddition(final DataFolder favourities, final DataObject[] children, final List listAdd) { List listDest = new ArrayList(); if (listAdd.size() > 0) { //Insert new nodes just before last (root) node @@ -520,6 +508,7 @@ } } + @Override protected boolean asynchronous() { return false; } @@ -543,6 +532,7 @@ * presented as an item in a menu. * @return the name of the action */ + @Override public String getName() { return NbBundle.getMessage ( Actions.class, "ACT_AddOnFavoritesNode"); // NOI18N diff --git a/favorites/src/org/netbeans/modules/favorites/Favorites.java b/favorites/src/org/netbeans/modules/favorites/FavoritesNode.java rename from favorites/src/org/netbeans/modules/favorites/Favorites.java rename to favorites/src/org/netbeans/modules/favorites/FavoritesNode.java --- a/favorites/src/org/netbeans/modules/favorites/Favorites.java +++ b/favorites/src/org/netbeans/modules/favorites/FavoritesNode.java @@ -78,14 +78,14 @@ * * @author Jaroslav Tulach */ -final class Favorites extends FilterNode implements Index { +public final class FavoritesNode extends FilterNode implements Index { /** default node */ private static Node node; /** node that represents root of filesystems */ private static Node root; /** Creates new ProjectRootFilterNode. */ - private Favorites(Node node) { + private FavoritesNode(Node node) { super(node, new Chldrn (node, false)); } @@ -125,8 +125,8 @@ public int indexOf(final Node node) { Index ind = getOriginal().getCookie(Index.class); if (ind != null) { - if (node instanceof Favorites.ProjectFilterNode) { - Favorites.ProjectFilterNode fn = (Favorites.ProjectFilterNode) node; + if (node instanceof FavoritesNode.ProjectFilterNode) { + FavoritesNode.ProjectFilterNode fn = (FavoritesNode.ProjectFilterNode) node; int i = ind.indexOf(fn.getOriginal()); return i; } else { @@ -238,7 +238,7 @@ */ public static synchronized Node getNode () { if (node == null) { - node = new Favorites (getFolder().getNodeDelegate ()); + node = new FavoritesNode (getFolder().getNodeDelegate ()); } return node; } @@ -282,7 +282,7 @@ /** Return a node for the current project. */ public Node getNode () { - return Favorites.getNode (); + return FavoritesNode.getNode (); } } @@ -368,7 +368,7 @@ @Override public void setName(String name) { // #113859 - keep order of children in favorites folder after rename - final DataFolder favoritesFolder = Favorites.getFolder(); + final DataFolder favoritesFolder = FavoritesNode.getFolder(); final DataObject[] children = favoritesFolder.getChildren(); super.setName(name); try { @@ -381,12 +381,12 @@ @Override public String getDisplayName () { //Change display name only for favorite nodes (links) under Favorites node. - if (Favorites.getNode().equals(this.getParentNode())) { + if (FavoritesNode.getNode().equals(this.getParentNode())) { DataShadow ds = getCookie(DataShadow.class); if (ds != null) { String name = ds.getName(); String path = FileUtil.getFileDisplayName(ds.getOriginal().getPrimaryFile()); - return NbBundle.getMessage(Favorites.class, "CTL_DisplayNameTemplate", name, path); + return NbBundle.getMessage(FavoritesNode.class, "CTL_DisplayNameTemplate", name, path); } else { return super.getDisplayName(); } @@ -462,7 +462,7 @@ if (isRoot) { return createActionsForRoot(arr); } else { - if (Favorites.getNode().equals(this.getParentNode())) { + if (FavoritesNode.getNode().equals(this.getParentNode())) { DataShadow ds = getCookie(DataShadow.class); if (ds != null) { if (ds.getOriginal().getPrimaryFile().isFolder()) { diff --git a/favorites/src/org/netbeans/modules/favorites/Tab.java b/favorites/src/org/netbeans/modules/favorites/Tab.java --- a/favorites/src/org/netbeans/modules/favorites/Tab.java +++ b/favorites/src/org/netbeans/modules/favorites/Tab.java @@ -485,7 +485,7 @@ /** Exchanges deserialized root context to projects root context * to keep the uniquennes. */ protected void validateRootContext () { - Node projectsRc = Favorites.getNode (); + Node projectsRc = FavoritesNode.getNode (); setRootContext(projectsRc); } @@ -514,7 +514,7 @@ try { Node[] toShadows = new Node[] {DataObject.find(file).getNodeDelegate()}; - final DataFolder f = Favorites.getFolder(); + final DataFolder f = FavoritesNode.getFolder(); final DataObject [] arr = f.getChildren(); final List listAdd = new ArrayList(); DataObject createdDO = null; diff --git a/favorites/src/org/netbeans/modules/favorites/api/Favorites.java b/favorites/src/org/netbeans/modules/favorites/api/Favorites.java new file mode 100644 --- /dev/null +++ b/favorites/src/org/netbeans/modules/favorites/api/Favorites.java @@ -0,0 +1,173 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.favorites.api; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.modules.favorites.Actions; +import org.netbeans.modules.favorites.FavoritesNode; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataFolder; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.loaders.DataShadow; + +// TODO tests +/** + * Singleton for access to Favorites. + * + * @author Richard Michalsky + */ +public final class Favorites { + private static Favorites INSTANCE; + private static Logger LOG = Logger.getLogger(Favorites.class.getName()); + + /** + * Returns a default instance of Favorites. + * @return + */ + public static Favorites getDefault() { + if (INSTANCE == null) + INSTANCE = new Favorites(); + return INSTANCE; + } + + /** + * Adds new files to Favorites. + * @param toAdd an array of file objects to be added to Favorites. May be empty, but not null. + * @param selectAfterAddition when true, Favorites window is focused and 1-st of added objects is selected and expanded. + * @throws IllegalArgumentException When toAdd array contains objects that are already present in Favorites as roots. + * @throws NullPointerException When toAdd array is null or contains null values. + * @throws DataObjectNotFoundException When corresponding DataObject to one of the file objects could not be found. + */ + public void add(FileObject[] toAdd, boolean selectAfterAddition) + throws IllegalArgumentException, NullPointerException, DataObjectNotFoundException { + if (toAdd.length == 0) + return; + final DataFolder f = FavoritesNode.getFolder(); + for (FileObject fo : toAdd) { + if (isInFavorites(fo)) + throw new IllegalArgumentException("File " + fo.getPath() + " already in Favorites."); + } + DataObject[] createdDOs = createShadows(f, toAdd); + + //This is done to set desired order of nodes in view + Actions.Add.reorderAfterAddition(f, f.getChildren(), Arrays.asList(createdDOs)); + if (selectAfterAddition) + Actions.Add.selectAfterAddition(createdDOs[0]); + } + + /** + * Returns true if given file object is already in Favorites as a root, + * i.e. descendants of root don't count. + * @param fo File object to query. + * @return + */ + public boolean isInFavorites (FileObject fo) { + DataFolder f = FavoritesNode.getFolder(); + DataObject [] arr = f.getChildren(); + for (int i = 0; i < arr.length; i++) { + if (arr[i] instanceof DataShadow) { + if (fo.equals(((DataShadow) arr[i]).getOriginal().getPrimaryFile())) { + return true; + } + } + } + return false; + } + + /** + * Returns list of current root file objects in Favorites. + * @return + */ + public List getFavoriteRoots() { + DataFolder f = FavoritesNode.getFolder(); + DataObject [] arr = f.getChildren(); + List ret = new ArrayList(arr.length); + + for (DataObject obj : arr) { + if (obj instanceof DataShadow) { + ret.add(((DataShadow) obj).getOriginal().getPrimaryFile()); + } + } + return ret; + } + + /** + * Removes given file objects from Favorites if they are found as roots. + * @param toRemove An array of file objects to be removed. + * @throws IOException When corresponding entry in userdir could not be deleted + * @throws NullPointerException When toRemove is null + */ + public void remove(FileObject[] toRemove) throws IOException, NullPointerException { + DataFolder f = FavoritesNode.getFolder(); + DataObject [] arr = f.getChildren(); + for (DataObject obj : arr) { + if (obj instanceof DataShadow) { + FileObject root = ((DataShadow) obj).getOriginal().getPrimaryFile(); + for (FileObject rem : toRemove) { + if (rem.equals(root)) { + obj.delete(); + } + } + } + } + } + + private static DataObject[] createShadows(final DataFolder favorites, final FileObject[] toAdd) throws DataObjectNotFoundException, IllegalArgumentException { + DataObject[] createdDO = new DataObject[toAdd.length]; + for (int i = 0; i < toAdd.length; i++) { + DataObject obj = DataObject.find(toAdd[i]); + if (obj != null) { + try { + createdDO[i] = obj.createShadow(favorites); + } catch (IOException ex) { + LOG.log(Level.WARNING, null, ex); + } + } + } + return createdDO; + } + +} diff --git a/favorites/src/org/netbeans/modules/favorites/resources/layer.xml b/favorites/src/org/netbeans/modules/favorites/resources/layer.xml --- a/favorites/src/org/netbeans/modules/favorites/resources/layer.xml +++ b/favorites/src/org/netbeans/modules/favorites/resources/layer.xml @@ -105,7 +105,7 @@ - + diff --git a/favorites/test/unit/src/org/netbeans/modules/favorites/IndexTest.java b/favorites/test/unit/src/org/netbeans/modules/favorites/IndexTest.java --- a/favorites/test/unit/src/org/netbeans/modules/favorites/IndexTest.java +++ b/favorites/test/unit/src/org/netbeans/modules/favorites/IndexTest.java @@ -68,7 +68,7 @@ } /** - * Test basic functionality of Index on Favorites node. + * Test basic functionality of Index on FavoritesNode node. */ public void testReorder () throws Exception { FileObject folder = FileUtil.createFolder ( @@ -81,12 +81,12 @@ DataObject dObj1 = DataObject.find(fo1); DataObject dObj2 = DataObject.find(fo2); - DataFolder favorites = Favorites.getFolder(); + DataFolder favorites = FavoritesNode.getFolder(); dObj1.createShadow(favorites); dObj2.createShadow(favorites); - Node n = Favorites.getNode(); + Node n = FavoritesNode.getNode(); Node n1 = n.getChildren().findChild("Test1"); assertNotNull("Node must exist", n1); diff --git a/favorites/test/unit/src/org/netbeans/modules/favorites/NodesTest.java b/favorites/test/unit/src/org/netbeans/modules/favorites/NodesTest.java --- a/favorites/test/unit/src/org/netbeans/modules/favorites/NodesTest.java +++ b/favorites/test/unit/src/org/netbeans/modules/favorites/NodesTest.java @@ -74,7 +74,7 @@ } public void testNoneOfTheNodesHaveShadowLinks () throws Exception { - doCheckDepth (Favorites.getNode (), 1); + doCheckDepth (FavoritesNode.getNode (), 1); } private void doCheckDepth (Node node, int depth) throws Exception { @@ -87,7 +87,7 @@ Action remove = Actions.remove(); for (int i = 0; i < arr.length; i++) { - File f = Favorites.fileForNode(arr[i]); + File f = FavoritesNode.fileForNode(arr[i]); //First level (link) has action remove //Further level has action add Collection set = Arrays.asList (arr[i].getActions(false)); diff --git a/favorites/test/unit/src/org/netbeans/modules/favorites/RootsTest.java b/favorites/test/unit/src/org/netbeans/modules/favorites/RootsTest.java --- a/favorites/test/unit/src/org/netbeans/modules/favorites/RootsTest.java +++ b/favorites/test/unit/src/org/netbeans/modules/favorites/RootsTest.java @@ -100,10 +100,10 @@ } } - Node[] arr = Favorites.getNode ().getChildren ().getNodes (true); + Node[] arr = FavoritesNode.getNode ().getChildren ().getNodes (true); for (int i = 0; i < arr.length; i++) { - File f = Favorites.fileForNode (arr[i]); + File f = FavoritesNode.fileForNode (arr[i]); if (f != null) { roots.remove (f); } @@ -120,7 +120,7 @@ }*/ public void testLinkToHomeDirIsThere () throws Exception { - Node[] arr = Favorites.getNode ().getChildren ().getNodes (true); + Node[] arr = FavoritesNode.getNode ().getChildren ().getNodes (true); File home = new File (System.getProperty("user.home")).getCanonicalFile(); @@ -150,14 +150,14 @@ public void testNodesUnderRootRepresentTheirFiles () throws Exception { HashSet roots = new HashSet(Arrays.asList (File.listRoots())); - Node[] arr = Favorites.getNode ().getChildren ().getNodes (true); + Node[] arr = FavoritesNode.getNode ().getChildren ().getNodes (true); for (int i = 0; i < arr.length; i++) { - File f = Favorites.fileForNode (arr[i]); + File f = FavoritesNode.fileForNode (arr[i]); if (roots.remove (f)) { Node[] nexts = arr[i].getChildren().getNodes (true); for (int j = 0; j < nexts.length; j++) { - File file = Favorites.fileForNode (nexts[i]); + File file = FavoritesNode.fileForNode (nexts[i]); assertNotNull ("For node: " + nexts[i] + " there has to be file", file); assertEquals ("Correct parent for " + nexts[i], f, file.getParentFile()); } diff --git a/favorites/test/unit/src/org/netbeans/modules/favorites/VisibilityQueryWorksTest.java b/favorites/test/unit/src/org/netbeans/modules/favorites/VisibilityQueryWorksTest.java --- a/favorites/test/unit/src/org/netbeans/modules/favorites/VisibilityQueryWorksTest.java +++ b/favorites/test/unit/src/org/netbeans/modules/favorites/VisibilityQueryWorksTest.java @@ -164,13 +164,13 @@ } public void testLinksAreVisibleAllTheTime() throws Exception { - Node[] arr = Favorites.getNode().getChildren().getNodes(true); + Node[] arr = FavoritesNode.getNode().getChildren().getNodes(true); assertNodeForDataObject("hidden object is there", hiddenDO, true, arr); assertNodeForDataObject("folder as well", folderDO, true, arr); } public void testHiddenFilesInFoldersAreHidden() throws Exception { - Node[] arr = Favorites.getNode().getChildren().getNodes(true); + Node[] arr = FavoritesNode.getNode().getChildren().getNodes(true); Node f = assertNodeForDataObject("folder as well", folderDO, true, arr); arr = f.getChildren().getNodes(true); @@ -201,7 +201,7 @@ } private void doCopyOrCut(boolean copy) throws Exception { - Node[] arr = Favorites.getNode().getChildren().getNodes(true); + Node[] arr = FavoritesNode.getNode().getChildren().getNodes(true); Node f = assertNodeForDataObject("folder is there ", rootDO, true, arr); arr = f.getChildren().getNodes(true); f = assertNodeForDataObject("folder is there ", folderDO, true, arr);