blob: 2fc95e567946c4174b6c4bfffa604bfd7dfea006 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.i18n;
import java.awt.BorderLayout;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.modules.properties.PropertiesDataObject; // PENDING
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.NodeAcceptor;
import org.openide.nodes.NodeOperation;
import org.openide.util.UserCancelException;
import org.openide.filesystems.FileUtil;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.queries.VisibilityQuery;
import org.openide.awt.Mnemonics;
import org.openide.util.ImageUtilities;
/**
* A static utility class grouping functions for dialogs for selection
* sources from project and other places.
*/
public class SelectorUtils {
/**
* The filter used to filter out folders and resource bundles.
*/
public static final FilteredNode.NodeFilter BUNDLES_FILTER =
new FilteredNode.NodeFilter() {
public boolean acceptNode(Node n) {
// Has to be data object.
DataObject dataObject = n.getCookie(DataObject.class);
if(dataObject == null)
return false;
// Has to be a folder or a resource class.
return
((dataObject instanceof DataFolder) && (isVisible(dataObject))) ||
(dataObject instanceof PropertiesDataObject); // PENDING same like above.
}
};
private static boolean isVisible(DataObject dobj) {
return (dobj.getPrimaryFile()==null) ||
(VisibilityQuery.getDefault().isVisible(dobj.getPrimaryFile()));
}
public static final FilteredNode.NodeFilter ALL_FILTER =
new FilteredNode.NodeFilter() {
public boolean acceptNode(Node n) {
return true;
}
};
/**
* Brings up a modal windows for selection of a resource bundle from
* the given project.
* @param prj the project to select from
* @return DataObject representing the selected bundle file or null
*/
static public DataObject selectBundle(Project prj, FileObject file) {
try {
Node root = bundlesNode(prj, file, true);
Node[] selectedNodes=
NodeOperation.getDefault().
select(
Util.getString("CTL_SelectPropDO_Dialog_Title"),
Util.getString("CTL_SelectPropDO_Dialog_RootTitle"),
root,
new NodeAcceptor() {
public boolean acceptNodes(Node[] nodes) {
if(nodes == null || nodes.length != 1) {
return false;
}
// Has to be data object.
DataObject dataObject = nodes[0].getCookie(DataObject.class);
if(dataObject == null)
return false;
// Has to be of resource class.
return dataObject.getClass().equals(PropertiesDataObject.class); // PENDING same like above.
}
}
);
return selectedNodes[0].getCookie(DataObject.class);
} catch (UserCancelException uce) {
//ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, uce);
// nobody is interested in the message
return null;
}
}
/**
* Prepare node structure for showing available bundles. The
* structure is relative to the file that should access the
* bundle.
* @param prj the <code>Project</code> <code>file</code> is in
* @param file <code>FileObject</code> to show bundles for
* @param includeFiles specifies whether to show jar files or just folders
* @return root <code>Node</code>
*/
static public Node bundlesNode(Project prj, FileObject file, boolean includeFiles) {
List<Node> nodes = new LinkedList<Node>();
if (prj == null) {
prj = FileOwnerQuery.getOwner(file);
}
ClassPath cp = ClassPath.getClassPath(file, ClassPath.EXECUTE);
if (cp != null) {
nodes.addAll(getRootNodes(prj, getRoots(ClassPath.getClassPath(file, ClassPath.SOURCE), cp), BUNDLES_FILTER, includeFiles));
}
return createRootFor(nodes, prj);
}
private static List<FileObject> getRoots(ClassPath sources, ClassPath cp) {
ArrayList<FileObject> l = new ArrayList<FileObject>(cp.entries().size());
for (ClassPath.Entry e : sources.entries()) {
if (e.getRoot() != null) {
l.add(e.getRoot());
}
}
for (ClassPath.Entry e : cp.entries()) {
// try to map it to sources
URL url = e.getURL();
SourceForBinaryQuery.Result r= SourceForBinaryQuery.findSourceRoots(url);
FileObject [] fos = r.getRoots();
if (fos.length > 0) {
for (FileObject fo : fos) {
if (!l.contains(fo)) {
l.add(fo);
}
}
} else {
if (e.getRoot()!=null)
if (!l.contains(e.getRoot())) {
l.add(e.getRoot()); // add the class-path location
// directly
}
}
}
return l;
}
private static List<Node> getRootNodes(Project prj,
List<FileObject> roots,
FilteredNode.NodeFilter filter,
boolean includeFiles) {
List<Node> nodes = new ArrayList<Node>(roots.size());
for (FileObject rfo : roots) {
try {
if (includeFiles || (FileUtil.toFile(rfo)!=null)) {
Project owner = org.netbeans.api.project.FileOwnerQuery.getOwner(rfo);
Node origNode = DataObject.find(rfo).getNodeDelegate();
FilteredNode node = new FilteredNode(origNode,filter, getDisplayName(rfo, owner, prj!=owner));
nodes.add(node);
}
} catch (org.openide.loaders.DataObjectNotFoundException ex) {}
}
return nodes;
}
private static String getDisplayName(FileObject fo, Project owner, boolean incPrjName) {
if (owner != null) {
SourceGroup grp = getSourceGroup(fo, owner);
String n = (grp!=null)?grp.getDisplayName():FileUtil.getFileDisplayName(fo);
if (incPrjName) {
ProjectInformation pi = ProjectUtils.getInformation(owner);
n += " [" + pi.getDisplayName() + "]";
}
return n;
} else
return FileUtil.getFileDisplayName(fo);
}
private static SourceGroup getSourceGroup(FileObject file, Project prj) {
Sources src = ProjectUtils.getSources(prj);
SourceGroup[] srcgrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
for (SourceGroup srcGrp : srcgrps) {
if (file == srcGrp.getRootFolder())
return srcGrp;
}
return null;
}
/**
* Prepare node structure showing sources
* @param prj the project to select from
* @param filter NodeFilter used to filter only relevant information
* @return root Node of source files from <code>prj</code> filtered
* by <code>filter</code>
**/
static public Node sourcesNode(Project prj, FilteredNode.NodeFilter filter) {
Sources src = ProjectUtils.getSources(prj);
SourceGroup[] srcgrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
java.util.List<Node> nodes = new ArrayList<Node>();
for (SourceGroup srcGrp : srcgrps) {
try {
FileObject rfo = srcGrp.getRootFolder();
FilteredNode node = new FilteredNode(DataObject.find(rfo).getNodeDelegate(),
filter);
// node.setName(srcGrp.getName());
node.setDisplayName(srcGrp.getDisplayName());
// node.setIcon(srcGrp.getIcon());
nodes.add(node);
} catch (org.openide.loaders.DataObjectNotFoundException ex) {}
}
return createRootFor(nodes, prj);
}
private static Node createRootFor(java.util.List<Node> nodes, Project prj) {
// create a root for all gathered nodes
Children ch = new Children.Array();
Node[] nodesArray = new Node[ nodes.size() ];
nodes.toArray( nodesArray );
ch.add( nodesArray );
final Icon icon = ProjectUtils.getInformation(prj).getIcon();
AbstractNode ret = new AbstractNode(ch) {
@Override
public Image getIcon(int type) {
return ImageUtilities.icon2Image(icon);
}
@Override
public Image getOpenedIcon(int type) {
return getIcon(type);
}
};
ret.setDisplayName(ProjectUtils.getInformation(prj).getDisplayName());
return ret;
}
/** Instantiate a template object.
* Asks user for the target file's folder and creates the file.
* @param project the project the template should be instantiated in
* @param refFile the file for which bundle is created
* @param template the template to use
* @return the generated DataObject
* @exception UserCancelException if the user cancels the action
* @exception IOException on I/O error
* @see DataObject#createFromTemplate
*/
public static DataObject instantiateTemplate(Project project, FileObject refFile, DataObject template) throws IOException {
// Create component for for file name input.
ObjectNameInputPanel panel = new ObjectNameInputPanel();
Node repositoryNode = SelectorUtils.bundlesNode(project, refFile, false);
// Selects one folder from data systems.
DataFolder dataFolder =
NodeOperation.getDefault().select
(
I18nUtil.getBundle().getString ("CTL_Template_Dialog_Title"),
I18nUtil.getBundle().getString ("CTL_Template_Dialog_RootTitle"),
repositoryNode,
new NodeAcceptor() {
public boolean acceptNodes(Node[] nodes) {
if(nodes == null || nodes.length != 1) {
return false;
}
DataFolder cookie = nodes[0].getCookie(DataFolder.class);
return (cookie != null && cookie.getPrimaryFile().canWrite());
}
},
panel
)[0].getCookie(DataFolder.class);
String name = panel.getText();
DataObject newObject;
if(name.equals ("")) { // NOI18N
newObject = template.createFromTemplate(dataFolder);
} else {
newObject = template.createFromTemplate(dataFolder, name);
}
try {
return newObject;
} catch(ClassCastException cce) {
throw new UserCancelException();
}
}
public static DataObject selectOrCreateBundle(FileObject refFile,
DataObject template,
DataObject actBundle) {
Node rootNode = bundlesNode(null, refFile, true);
FileObject actFile = (actBundle != null) ?
actBundle.getPrimaryFile() :
null;
FileSelector fs = new FileSelector(refFile, template, actFile);
fs.getDialog(I18nUtil.getBundle().getString ("CTL_SelectPropDO_Dialog_Title"), null) // NOI18N
.setVisible(true);
return fs.isConfirmed() ? fs.getSelectedDataObject() : null;
}
/** Panel used by <code>instantiateTemplate</code> method. */
private static class ObjectNameInputPanel extends JPanel {
/** Generated Serialized Version UID. */
static final long serialVersionUID = 1980214734060402958L;
/** Text field. */
JTextField text;
/** Constructs panel. */
public ObjectNameInputPanel () {
BorderLayout layout = new BorderLayout();
layout.setVgap(5);
layout.setHgap(5);
setLayout(layout);
// label and text field with mnemonic
String labelText = I18nUtil.getBundle().getString ("LBL_TemplateName");
JLabel label = new JLabel();
Mnemonics.setLocalizedText(label, labelText);
text = new JTextField();
text.getAccessibleContext().setAccessibleDescription(I18nUtil.getBundle().getString ("ACS_TEXT_ObjectNameInputPanel"));
label.setLabelFor(text);
add(BorderLayout.WEST, label);
add(BorderLayout.CENTER, text);
}
/** Requets focus for text field. */
public void requestFocus () {
text.requestFocus ();
}
/** Getter for <code>text</code>. */
public String getText () {
return text.getText ();
}
/** Setter for <code>text</code>. */
public void setText (String s) {
setText(s);
}
} // End of nested class ObjectNameInputPanel
}