org.openide.loaders.TemplateWizard1 Maven / Gradle / Ivy
Go to download
The NetBeans Platform is a generic base for desktop applications. It provides the services common
to almost all large desktop applications: window management, menus, settings and storage, an update
manager, and file access. Get a head start by reusing these standard components, allowing you to
concentrate fully on your application's business logic.
The newest version!
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.openide.loaders;
import java.util.*;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.SwingUtilities;
import javax.swing.JComponent;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.plaf.basic.BasicBorders;
import org.openide.awt.HtmlBrowser;
import org.openide.loaders.*;
import org.openide.nodes.*;
import org.openide.explorer.view.*;
import org.openide.util.RequestProcessor;
import org.openide.explorer.ExplorerManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.Repository;
import org.openide.util.AsyncGUIJob;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
/** Dialog that can be used in create from template.
*
* @author Jaroslav Tulach
*/
final class TemplateWizard1 extends javax.swing.JPanel implements DataFilter,
ExplorerManager.Provider, java.beans.PropertyChangeListener, AsyncGUIJob {
/** See org.openide.WizardDescriptor.PROP_CONTENT_SELECTED_INDEX
*/
private static final String PROP_CONTENT_SELECTED_INDEX = "WizardPanel_contentSelectedIndex"; // NOI18N
/** See org.openide.WizardDescriptor.PROP_CONTENT_DATA
*/
private static final String PROP_CONTENT_DATA = "WizardPanel_contentData"; // NOI18N
/** listener to changes in the wizard */
private ChangeListener listener;
/** selected template */
private DataObject template;
/** templates root */
private DataFolder templatesRoot;
/** manager for templates tree view */
private ExplorerManager manager;
/** Initialization data structure for passing data between
* asynchronous background initialization and UI update */
private static final class InitData {
HtmlBrowser browser;
String noDescMsg;
Border noDescBorder;
}; // end of InitData
/** holds init data for async initialization */
private InitData initData;
/** Creates new form NewFromTemplatePanel */
public TemplateWizard1 () {
initComponents ();
treeView = new TemplatesTreeView();
treeView.setDefaultActionAllowed(false);
treeView.setPopupAllowed(false);
treeView.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
java.awt.GridBagConstraints gridBagConstraints1 = new java.awt.GridBagConstraints();
gridBagConstraints1.gridx = 0;
gridBagConstraints1.gridy = 1;
gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints1.insets = new java.awt.Insets(0, 0, 11, 0);
gridBagConstraints1.weightx = 1.0;
gridBagConstraints1.weighty = 1.0;
add(treeView, gridBagConstraints1);
ResourceBundle bundle = org.openide.util.NbBundle.getBundle(TemplateWizard1.class);
setName (bundle.getString("LAB_TemplateChooserPanelName"));
putClientProperty(PROP_CONTENT_SELECTED_INDEX, new Integer(0));
putClientProperty(PROP_CONTENT_DATA, new String[] {getName(), "..."}); // NOI18N
// Fix of #19667 - those values will be retreived in addNotify
putClientProperty("LAB_SelectTemplateBorder", // NOI18N
bundle.getString("LAB_SelectTemplateBorder"));
putClientProperty("LAB_SelectTemplateBorder_Mnemonic", // NOI18N
bundle.getString("LAB_SelectTemplateBorder_Mnemonic"));
putClientProperty("LAB_TemplateDescriptionBorder", // NOI18N
bundle.getString("LAB_TemplateDescriptionBorder"));
putClientProperty("LAB_TemplateDescriptionBorder_Mnemonic", // NOI18N
bundle.getString("LAB_TemplateDescriptionBorder_Mnemonic"));
putClientProperty("ACSD_TemplatesTree", // NOI18N
bundle.getString("ACSD_TemplatesTree"));
putClientProperty("ACSD_TemplateWizard1", // NOI18N
bundle.getString("ACSD_TemplateWizard1"));
// bugfix #19667 end
updateRootNode (null);
templatesLabel.setLabelFor(treeView);
noBrowser.setText(bundle.getString("MSG_InitDescription"));
java.awt.CardLayout card = (java.awt.CardLayout)browserPanel.getLayout();
card.show (browserPanel, "noBrowser"); // NOI18N
// for asynchnonous lazy init of this component
Utilities.attachInitJob(this, this);
}
public void addNotify() {
// overriden to set the labels later than in constructor
// in order to fix #19667
templatesLabel.setText(
(String)getClientProperty("LAB_SelectTemplateBorder") // NOI18N
);
templatesLabel.setDisplayedMnemonic(
((String)getClientProperty("LAB_SelectTemplateBorder_Mnemonic")).charAt(0) // NOI18N
);
browserLabel.setText(
(String)getClientProperty("LAB_TemplateDescriptionBorder") // NOI18N
);
browserLabel.setDisplayedMnemonic(
((String)getClientProperty("LAB_TemplateDescriptionBorder_Mnemonic")).charAt(0)
);
treeView.getAccessibleContext().setAccessibleDescription(
(String)getClientProperty("ACSD_TemplatesTree") // NOI18N
);
getAccessibleContext().setAccessibleDescription(
(String)getClientProperty("ACSD_TemplateWizard1") // NOI18N
);
super.addNotify();
}
/** Explorer manager for templates tree view */
public ExplorerManager getExplorerManager() {
if (manager == null) {
manager = new ExplorerManager();
manager.addPropertyChangeListener(this);
}
return manager;
}
/** Forward focus to tree view. */
public boolean requestDefaultFocus() {
return treeView.requestDefaultFocus();
}
/** Preffered size */
public java.awt.Dimension getPreferredSize() {
return TemplateWizard.PREF_DIM;
}
/** Updates the root of templates.
* @param root the root folder
*/
private void updateRootNode (DataFolder root) {
if (root == null) {
FileObject fo = Repository.getDefault ().getDefaultFileSystem ().findResource ("/Templates"); // NOI18N
if (fo != null && fo.isFolder ())
root = DataFolder.findFolder (fo);
}
if (root.equals(templatesRoot))
return;
templatesRoot = root;
Children ch = new DataShadowFilterChildren(root.getNodeDelegate());
getExplorerManager().setRootContext(new DataShadowFilterNode (root.getNodeDelegate(), ch, root.getNodeDelegate().getDisplayName ()));
}
private class DataShadowFilterChildren extends FilterNode.Children {
public DataShadowFilterChildren (Node or) {
super (or);
}
/** Creates nodes for nodes.
*/
protected Node[] createNodes (Object key) {
Node n = (Node)key;
String nodeName = n.getDisplayName();
DataObject obj = null;
DataShadow shadow = (DataShadow)n.getCookie (DataShadow.class);
if (shadow != null) {
// I need DataNode here to get localized name of the
// shadow, but without the ugly "(->)" at the end
DataNode dn = new DataNode(shadow, Children.LEAF);
nodeName = dn.getDisplayName();
obj = shadow.getOriginal();
n = obj.getNodeDelegate();
}
if (obj == null)
obj = (DataObject)n.getCookie (DataObject.class);
if (obj != null) {
if (obj.isTemplate ()) {
// on normal nodes stop recursion
return new Node[] { new DataShadowFilterNode (n, Children.LEAF, nodeName) };
}
if (acceptDataObject (obj)) {
// on folders use normal filtering
return new Node[] { new DataShadowFilterNode (n, new DataShadowFilterChildren (n), nodeName) };
}
}
return new Node[] {};
}
}
private static class DataShadowFilterNode extends FilterNode {
private String name;
public DataShadowFilterNode (Node or, org.openide.nodes.Children children, String name) {
super (or, children);
this.name = name;
disableDelegation(FilterNode.DELEGATE_SET_DISPLAY_NAME);
}
public String getDisplayName() {
return name;
}
// issue 29867, rename should be prohibited
public boolean canRename () {
return false;
}
}
/** Updates description to reflect the one associated with given object.
* @param obj object
*/
private void updateDescription (DataObject obj) {
java.net.URL url = null;
if (obj != null) {
url = TemplateWizard.getDescription (obj);
}
java.awt.CardLayout card = (java.awt.CardLayout)browserPanel.getLayout();
if (url != null &&
getExplorerManager().getSelectedNodes().length != 0) {
if (browser != null) {
browser.setURL(url);
if (!browser.isVisible()) {
card.show (browserPanel, "browser"); // NOI18N
}
}
} else {
card.show (browserPanel, "noBrowser"); // NOI18N
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the FormEditor.
*/
private void initComponents() {//GEN-BEGIN:initComponents
java.awt.GridBagConstraints gridBagConstraints;
browserPanel = new javax.swing.JPanel();
noBrowser = new javax.swing.JLabel();
templatesLabel = new javax.swing.JLabel();
browserLabel = new javax.swing.JLabel();
setLayout(new java.awt.GridBagLayout());
setPreferredSize(new java.awt.Dimension(0, 0));
browserPanel.setLayout(new java.awt.CardLayout());
// same background as html browser to avoid flicking
noBrowser.setBackground(javax.swing.UIManager.getDefaults().getColor("EditorPane.background"));
noBrowser.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
// bigger minimum size then usual to behave well in card
// layout together with HtmlBrowser
noBrowser.setMinimumSize(new java.awt.Dimension(0, 25));
noBrowser.setOpaque(true);
browserPanel.add(noBrowser, "noBrowser");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weighty = 0.5;
add(browserPanel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
add(templatesLabel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
add(browserLabel, gridBagConstraints);
}//GEN-END:initComponents
private void nameFocusGained (java.awt.event.FocusEvent evt) {//GEN-FIRST:event_nameFocusGained
}//GEN-LAST:event_nameFocusGained
private void templatesTreeValueChanged (javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_templatesTreeValueChanged
}//GEN-LAST:event_templatesTreeValueChanged
/** Handles explorer manager property changes. */
public void propertyChange(java.beans.PropertyChangeEvent evt) {
if (evt.getPropertyName() == ExplorerManager.PROP_SELECTED_NODES && listener != null) {
listener.stateChanged (new ChangeEvent (this));
updateDescription (template);
}
}
private void packagesListValueChanged (javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_packagesListValueChanged
}//GEN-LAST:event_packagesListValueChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel browserLabel;
private javax.swing.JPanel browserPanel;
private javax.swing.JLabel noBrowser;
private javax.swing.JLabel templatesLabel;
// End of variables declaration//GEN-END:variables
private TemplatesTreeView treeView;
private HtmlBrowser browser;
/** Should the data object be displayed or not?
* @param obj the data object
* @return true
if the object should be displayed,
* false
otherwise
*/
public boolean acceptDataObject(DataObject obj) {
if (obj instanceof DataFolder) {
Object o = obj.getPrimaryFile ().getAttribute ("simple"); // NOI18N
return o == null || Boolean.TRUE.equals (o);
} else {
return obj.isTemplate();
}
}
/** Prepares decription area with html browser inside.
* Executed in other then event dispatch thread.
*/
public void construct() {
initData = new InitData();
initData.browser = new HtmlBrowser(false, false);
initData.browser.setName("browser");
initData.noDescMsg = NbBundle.getBundle(TemplateWizard1.class).
getString("MSG_NoDescription");
initData.noDescBorder = new EtchedBorder();
// override the Swing default CSS to make the HTMLEditorKit use the
// same font as the rest of the UI
Component comp = initData.browser.getBrowserComponent();
if (! (comp instanceof javax.swing.JEditorPane))
return;
javax.swing.text.EditorKit kit = ((javax.swing.JEditorPane) comp).getEditorKitForContentType("text/html"); // NOI18N
if (! (kit instanceof javax.swing.text.html.HTMLEditorKit))
return;
javax.swing.text.html.HTMLEditorKit htmlkit = (javax.swing.text.html.HTMLEditorKit) kit;
// XXX the style sheet is shared by all HTMLEditorKits. We must
// detect if it has been tweaked by ourselves or someone else
// (template description for example) and avoid doing the same
// thing again
if (htmlkit.getStyleSheet().getStyleSheets() != null)
return;
javax.swing.text.html.StyleSheet css = new javax.swing.text.html.StyleSheet();
java.awt.Font f = new javax.swing.JTextArea().getFont();
css.addRule(new StringBuffer("body { font-size: ").append(f.getSize()) // NOI18N
.append("; font-family: ").append(f.getName()).append("; }").toString()); // NOI18N
css.addStyleSheet(htmlkit.getStyleSheet());
htmlkit.setStyleSheet(css);
}
/** Fills description area using constructed data. Executed in event dispatch thread.
*/
public void finished() {
browser = initData.browser;
browserLabel.setLabelFor(browser);
browser.getAccessibleContext().setAccessibleName(browserLabel.getText());
browserPanel.add(browser, "browser");
updateDescription(template);
// change loading text to no description text
// install same border as html browser have
noBrowser.setText(initData.noDescMsg);
noBrowser.setBorder(initData.noDescBorder);
// we don't need initData anymore, make gc'able
initData = null;
}
/** Helper implementation of WizardDescription.Panel for TemplateWizard.Panel1.
* Provides the wizard panel with the current data--either
* the default data or already-modified settings, if the user used the previous and/or next buttons.
* This method can be called multiple times on one instance of WizardDescriptor.Panel
.
* @param settings the object representing wizard panel state, as originally supplied to {@link WizardDescriptor#WizardDescriptor(WizardDescriptor.Iterator,Object)}
*/
void implReadSettings (Object settings) {
TemplateWizard wizard = (TemplateWizard)settings;
wizard.setTitle(org.openide.util.NbBundle.getBundle(TemplateWizard.class).getString("CTL_TemplateTitle"));
updateRootNode (wizard.getTemplatesFolder ());
template = wizard.getTemplate ();
if (template != null && !template.isValid() ) {
template = null;
}
// now try to find out the path
// a bit ugly code to do that
DataObject obj = template;
DataObject stop = wizard.getTemplatesFolder ();
final LinkedList ll = new LinkedList ();
for (;;) {
if (obj == null) {
// seems that the template is not one of templates
break;
}
if (obj == stop) {
// the last object found
break;
}
String key = obj.getNodeDelegate().getName ();
ll.addFirst(key);
obj = obj.getFolder();
}
RequestProcessor.getDefault ().post (new Runnable () {
private Node selection;
public void run () {
if (selection == null) {
// go thru all the nodes and find
Node node = getExplorerManager().getRootContext();
java.util.ListIterator it = ll.listIterator();
while (it.hasNext()) {
String name = (String)it.next ();
node = node.getChildren ().findChild (name);
if (node == null) {
// end it
node = getExplorerManager().getRootContext();
break;
}
}
selection = node;
// execute the second pass
SwingUtilities.invokeLater (this);
} else {
// second pass, executed in AWT thread
try {
getExplorerManager().setSelectedNodes(new Node[] {selection});
} catch (java.beans.PropertyVetoException evt) {
// ignore
}
}
}
}, 300, Thread.MIN_PRIORITY);
}
/** Helper implementation of WizardDescription.Panel for TemplateWizard.Panel1.
* Provides the wizard panel with the opportunity to update the
* settings with its current customized state.
* Rather than updating its settings with every change in the GUI, it should collect them,
* and then only save them when requested to by this method.
* Also, the original settings passed to {@link #readSettings} should not be modified (mutated);
* rather, the (copy) passed in here should be mutated according to the collected changes.
* This method can be called multiple times on one instance of WizardDescriptor.Panel
.
* @param settings the object representing a settings of the wizard
*/
void implStoreSettings (Object settings) {
if (template != null) {
TemplateWizard wizard = (TemplateWizard)settings;
if (wizard.getTemplate() != template) {
// if template has changed then set target step names and index to default
Component c = wizard.targetChooser().getComponent();
if (c instanceof JComponent) {
((JComponent)c).putClientProperty(PROP_CONTENT_DATA, new String[] { c.getName() });
((JComponent)c).putClientProperty(PROP_CONTENT_SELECTED_INDEX, new Integer(0));
}
} else {
// bugfix #27939, if template isn't changed and PROP_CONTENT_DATA no set => set it
Component c = wizard.targetChooser().getComponent();
if (c instanceof JComponent) {
if (((JComponent)c).getClientProperty (PROP_CONTENT_DATA) == null) {
((JComponent)c).putClientProperty(PROP_CONTENT_DATA, new String[] { c.getName() });
((JComponent)c).putClientProperty(PROP_CONTENT_SELECTED_INDEX, new Integer(0));
}
}
}
wizard.setTemplateImpl (template, false);
}
}
/** Helper implementation of WizardDescription.Panel for TemplateWizard.Panel1.
* Test whether the panel is finished and it is safe to proceed to the next one.
* If the panel is valid, the "Next" (or "Finish") button will be enabled.
* @return true
if the user has entered satisfactory information
*/
boolean implIsValid () {
boolean enable = false;
Node[] n = getExplorerManager().getSelectedNodes();
if (n.length == 1) {
template = (DataObject)n[0].getCookie (DataObject.class);
enable = template != null && template.isTemplate();
}
return enable;
}
/** Add a listener to changes of the panel's validity.
* @param l the listener to add
* @see #isValid
*/
void addChangeListener (ChangeListener l) {
if (listener != null) throw new IllegalStateException ();
listener = l;
}
/** Remove a listener to changes of the panel's validity.
* @param l the listener to remove
*/
void removeChangeListener (ChangeListener l) {
listener = null;
}
/** Model for displaying only objects till template.
*/
private static final class TemplatesModel extends NodeTreeModel {
TemplatesModel() {}
public int getChildCount (Object o) {
Node n = Visualizer.findNode(o);
DataObject obj = (DataObject)n.getCookie (DataObject.class);
return obj == null || obj.isTemplate () ? 0 : super.getChildCount (o);
}
public boolean isLeaf (Object o) {
Node n = Visualizer.findNode(o);
DataObject obj = (DataObject)n.getCookie (DataObject.class);
return obj == null || obj.isTemplate ();
}
}
/** Specialized tree view for templates, non editable and with proper
* border */
private static final class TemplatesTreeView extends BeanTreeView {
TemplatesTreeView() {
tree.setEditable(false);
// install proper border
setBorder((Border)UIManager.get("Nb.ScrollPane.border")); // NOI18N
}
protected NodeTreeModel createModel() {
return new TemplatesModel();
}
}
}