All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.project.ui.TemplatesPanelGUI Maven / Gradle / Ivy

There is a newer version: RELEASE240
Show newest version
/*
 * 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.project.ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import javax.swing.plaf.TreeUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.text.ChangedCharSetException;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.swing.tree.TreePath;
import org.netbeans.api.annotations.common.StaticResource;
import org.openide.ErrorManager;
import org.openide.WizardDescriptor;
import org.openide.awt.HtmlBrowser;
import org.openide.awt.Mnemonics;
import org.openide.awt.QuickSearch;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.BeanTreeView;
import org.openide.explorer.view.ListView;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.loaders.DataShadow;
import org.openide.loaders.TemplateWizard;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.nodes.NodeNotFoundException;
import org.openide.nodes.NodeOp;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;

import static org.netbeans.modules.project.ui.Bundle.*;

/**
 *
 * @author  tom
 */
public class TemplatesPanelGUI extends javax.swing.JPanel implements PropertyChangeListener {
    
    public static interface Builder extends ActionListener {

        public Children createCategoriesChildren (DataFolder folder, String filterText);
        
        public Children createTemplatesChildren (DataFolder folder, String filterText);
        
        public String getCategoriesName ();
        
        public String getTemplatesName ();
        
        public void fireChange ();
    }
    
    public static final String TEMPLATES_FOLDER = "templatesFolder";        //NOI18N
    public static final String TARGET_TEMPLATE = "targetTemplate";          //NOI18N
    private static final String ATTR_INSTANTIATING_DESC = "instantiatingWizardURL"; //NOI18N
    private static final @StaticResource String WAIT = "org/netbeans/modules/project/ui/resources/wait.gif";
    private static final Image PLEASE_WAIT_ICON = ImageUtilities.loadImage (WAIT); // NOI18N
    private static final RequestProcessor RP = new RequestProcessor(TemplatesPanelGUI.class);
    
    private Builder firer;

    private String presetTemplateName = null;
    private Node pleaseWait;
    private WizardDescriptor wiz;

    private String filterText;

    @Messages("TXT_SelectTemplate=Select Project")
    public TemplatesPanelGUI (Builder firer) {
        assert firer != null : "Builder can not be null";  //NOI18N
        this.firer = firer;
        initComponents();
        postInitComponents ();
        setName(TXT_SelectTemplate());

        QuickSearch quickSearch = QuickSearch.attach( panelFilter, BorderLayout.CENTER, createQuickSearchCallback(), true );
        adjustQuickSearch( quickSearch );
//                    @Override
//                    public void run() {
//                    }
//                });
//            }
//        });
        

        //Hack to add a text label to the quicksearch
        Component qsComponent = panelFilter.getComponent( 0 );
        if( qsComponent instanceof JComponent ) {
            for( Component c : ((JComponent)qsComponent).getComponents() ) {
                if( c instanceof JLabel ) {
                    JLabel jLabel = (JLabel) c;
                    String text = org.openide.util.NbBundle.getMessage(TemplateChooserPanelGUI.class, "LBL_TemplateChooserPanelGUI_QuicksearchLabel");
                    Mnemonics.setLocalizedText(jLabel, text);
    }
            }
        }
    }

    public void setTemplatesFolder (final FileObject folder) {
        final DataFolder dobj = DataFolder.findFolder (folder);
        dobj.addPropertyChangeListener(new PropertyChangeListener() {
            @Override public void propertyChange(PropertyChangeEvent evt) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override public void run() {
                        setSelectedCategoryByName(OpenProjectListSettings.getInstance().getLastSelectedProjectCategory());
                    }
                });
            }
        });
        ((ExplorerProviderPanel)this.categoriesPanel).setRootNode(new FilterNode (
            dobj.getNodeDelegate(), this.firer.createCategoriesChildren(dobj, filterText)));
    }

    private FileObject getCurrentTemplatesFolder() {
        FileObject res = null;
        Node rootNode = ((ExplorerProviderPanel)categoriesPanel).getExplorerManager().getRootContext();
        if( null != rootNode ) {
            DataObject dob = rootNode.getLookup().lookup( DataObject.class );
            if( null != dob ) {
                res = dob.getPrimaryFile();
            }
        }
        return res;
    }

    public void setSelectedCategoryByName (final String categoryName) {
        if (categoryName != null) {
            ((org.netbeans.modules.project.ui.TemplatesPanelGUI.ExplorerProviderPanel) this.categoriesPanel).setSelectedNode(categoryName);
            //expand explicitly selected category
            SwingUtilities.invokeLater(new Runnable() {
                @Override public void run() {
                    Node[] sel = ((ExplorerProviderPanel)categoriesPanel).getSelectedNodes();
                    if (sel.length == 1) {
                        ((CategoriesPanel) categoriesPanel).btv.expandNode(sel[0]);
                    }
                }
            });
        } else {
            // if categoryName is null then select first category leastwise
            ((CategoriesPanel)this.categoriesPanel).selectFirst ();
        }
    }
    
    public String getSelectedCategoryName () {
        return ((ExplorerProviderPanel)this.categoriesPanel).getSelectionPath();
    }
    
    public void setSelectedTemplateByName (final String templateName) {
        presetTemplateName = templateName;
        final TemplatesPanel tempExplorer = ((TemplatesPanel)this.projectsPanel);
    
        SwingUtilities.invokeLater (new Runnable () {
            @Override public void run () {
                if (templateName != null) {
                    tempExplorer.setSelectedNode(templateName);
                    if (tempExplorer.getSelectionPath() == null) {
                        presetTemplateName = null;
                        tempExplorer.selectFirst();
                    }
                } else {
                    tempExplorer.selectFirst ();
                }
            }
        });

    }
    
    public String getSelectedTemplateName () {
        return ((TemplatesPanel)this.projectsPanel).getSelectionPath();
    }
    
    public FileObject getSelectedTemplate () {
        Node[] nodes = ((ExplorerProviderPanel) this.projectsPanel).getSelectedNodes();
        if (nodes != null && nodes.length == 1) {
            DataObject dobj = nodes[0].getLookup().lookup(DataObject.class);
            if (dobj != null) {
                while (dobj instanceof DataShadow) {
                    dobj = ((DataShadow)dobj).getOriginal();
                }
                return dobj.getPrimaryFile();
            }
        }
        return null;
    }

    @Override
    public void addNotify() {
        super.addNotify();
        jScrollPane1.setViewportView(description);
        jLabel3.setLabelFor(description);
    }
    
    @Override
    public void removeNotify() {
        super.removeNotify();
        jScrollPane1.setViewportView(null);
        jLabel3.setLabelFor(null);
    }

    void setWizardDescriptor(WizardDescriptor wiz) {
        this.wiz = wiz;
    }

    @Messages("TemplatesPanelGUI_note_samples=Note that samples are instructional and may not include all
security mechanisms required for a production environment.") @Override public void propertyChange (PropertyChangeEvent event) { if (event.getSource() == this.categoriesPanel) { if (ExplorerManager.PROP_SELECTED_NODES.equals (event.getPropertyName ())) { Node[] selectedNodes = (Node[]) event.getNewValue(); if (selectedNodes != null && selectedNodes.length == 1) { assert pleaseWait == null || !pleaseWait.equals (selectedNodes[0]) : "Cannot be fired a propertyChange with PleaseWaitNode, but was " + selectedNodes[0]; try { ((ExplorerProviderPanel)this.projectsPanel).setSelectedNodes(new Node[0]); } catch (PropertyVetoException e) { /*Ignore it*/ } DataObject template = (DataObject) selectedNodes[0].getLookup().lookup(DataFolder.class); if (template != null) { FileObject fo = template.getPrimaryFile(); String templatePath = fo.getPath(); if (!template.isValid()) { // in ergonomics IDE, it is possible that dataObject // no longer valid. If so, try to find it again // (layer was replaced.) fo = FileUtil.getConfigFile(templatePath); if (fo != null) { try { template = DataObject.find(fo); } catch (DataObjectNotFoundException ex) { Exceptions.printStackTrace(ex); } } } ((ExplorerProviderPanel)this.projectsPanel).setRootNode( new FilterNode (selectedNodes[0], this.firer.createTemplatesChildren((DataFolder)template, filterText))); // after change of root select the first template to make easy move in wizard this.setSelectedTemplateByName (presetTemplateName); if (wiz != null) { if (templatePath.matches("Templates/Project/Samples($|/.+)")) { wiz.putProperty(WizardDescriptor.PROP_INFO_MESSAGE, TemplatesPanelGUI_note_samples()); } else { wiz.putProperty(WizardDescriptor.PROP_INFO_MESSAGE, null); } } } } } } else if (event.getSource() == this.projectsPanel) { if (ExplorerManager.PROP_SELECTED_NODES.equals (event.getPropertyName())) { Node[] selectedNodes = (Node[]) event.getNewValue (); if (selectedNodes != null && selectedNodes.length == 1) { DataObject template = selectedNodes[0].getLookup().lookup(DataObject.class); if (template != null) { URL descURL = getDescription (template); if (descURL != null) { try { //this.description.setPage (descURL); // Set page does not work well if there are mutiple calls to that // see issue #49067. This is a hotfix for the bug which causes // synchronous loading of the content. It should be improved later // by doing it in request processor. //this.description.read( descURL.openStream(), descURL ); // #52801: handlig changed charset String charset = findEncodingFromURL (descURL.openStream ()); ErrorManager.getDefault ().log (ErrorManager.INFORMATIONAL, "Url " + descURL + " has charset " + charset); // NOI18N if (charset != null) { description.putClientProperty ("charset", charset); // NOI18N } this.description.read( descURL.openStream(), descURL ); } catch (ChangedCharSetException x) { Document doc = description.getEditorKit ().createDefaultDocument (); doc.putProperty ("IgnoreCharsetDirective", Boolean.valueOf (true)); // NOI18N try { description.read (descURL.openStream (), doc); } catch (IOException ioe) { ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ioe); this.description.setText(null); } } catch (IOException e) { ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, e); this.description.setText(null); } description.setCaretPosition(0); } else { this.description.setText(null); } } } else { // bugfix #46738, Description in New Project dialog doesn't show description of selected categories this.description.setText(null); } this.firer.fireChange (); } } } @Messages("LBL_TemplatesPanel_PleaseWait=Please wait...") private void postInitComponents () { Mnemonics.setLocalizedText(jLabel1, this.firer.getCategoriesName()); Mnemonics.setLocalizedText(jLabel2, this.firer.getTemplatesName()); this.description.setEditorKit(new HTMLEditorKit()); description.putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE ); // please wait node, see issue 52900 pleaseWait = new AbstractNode (Children.LEAF) { @Override public Image getIcon (int ignore) { return PLEASE_WAIT_ICON; } }; pleaseWait.setName(LBL_TemplatesPanel_PleaseWait()); Children ch = new Children.Array (); ch.add (new Node[] {pleaseWait}); final Node root = new AbstractNode (ch); SwingUtilities.invokeLater (new Runnable () { @Override public void run() { ((ExplorerProviderPanel)categoriesPanel).setRootNode (root); } }); ((ExplorerProviderPanel)projectsPanel).addDefaultActionListener( firer ); description.addHyperlinkListener(new ClickHyperlinks()); } /** 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 Form Editor. */ // //GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); categoriesPanel = new CategoriesPanel (); projectsPanel = new TemplatesPanel (); jLabel3 = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane(); description = new javax.swing.JEditorPane(); panelFilter = new javax.swing.JPanel(); setPreferredSize(new java.awt.Dimension(500, 230)); setLayout(new java.awt.GridBagLayout()); jLabel1.setLabelFor(categoriesPanel); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(TemplatesPanelGUI.class, "CTL_Categories")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 0.4; gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6); add(jLabel1, gridBagConstraints); jLabel2.setLabelFor(projectsPanel); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(TemplatesPanelGUI.class, "CTL_Templates")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 0.6; gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0); add(jLabel2, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 0.4; gridBagConstraints.weighty = 0.8; gridBagConstraints.insets = new java.awt.Insets(2, 0, 6, 6); add(categoriesPanel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 0.6; gridBagConstraints.weighty = 0.8; gridBagConstraints.insets = new java.awt.Insets(2, 6, 6, 0); add(projectsPanel, gridBagConstraints); jLabel3.setLabelFor(description); org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(TemplatesPanelGUI.class, "CTL_Description")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(2, 0, 0, 0); add(jLabel3, gridBagConstraints); description.setEditable(false); description.setPreferredSize(new java.awt.Dimension(100, 66)); jScrollPane1.setViewportView(description); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 0.2; gridBagConstraints.insets = new java.awt.Insets(2, 0, 0, 0); add(jScrollPane1, gridBagConstraints); panelFilter.setLayout(new java.awt.BorderLayout()); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0); add(panelFilter, gridBagConstraints); }// //GEN-END:initComponents private static final class ClickHyperlinks implements HyperlinkListener { public @Override void hyperlinkUpdate(HyperlinkEvent evt) { if (EventType.ACTIVATED == evt.getEventType() && evt.getURL() != null) { HtmlBrowser.URLDisplayer.getDefault().showURL(evt.getURL()); } } } private URL getDescription (DataObject dobj) { //XXX: Some templates are using templateWizardURL others instantiatingWizardURL. What is correct? FileObject fo = dobj.getPrimaryFile(); URL desc = (URL) fo.getAttribute(ATTR_INSTANTIATING_DESC); if (desc != null) { return desc; } desc = TemplateWizard.getDescription (dobj); return desc; } private abstract static class ExplorerProviderPanel extends JPanel implements ExplorerManager.Provider, PropertyChangeListener, VetoableChangeListener { private ExplorerManager manager; protected ExplorerProviderPanel () { this.manager = new ExplorerManager (); this.manager.addPropertyChangeListener(this); this.manager.addVetoableChangeListener(this); this.initGUI (); } public void setRootNode (Node node) { this.manager.setRootContext(node); } public Node getRootNode () { return this.manager.getRootContext(); } public Node[] getSelectedNodes () { return this.manager.getSelectedNodes(); } public void setSelectedNodes (Node[] nodes) throws PropertyVetoException { this.manager.setSelectedNodes(nodes); } public void setSelectedNode (String path) { if (path == null) { return; } StringTokenizer tk = new StringTokenizer (path,"/"); //NOI18N final String[] names = new String[tk.countTokens()]; for (int i=0;tk.hasMoreTokens();i++) { names[i] = tk.nextToken(); } RP.post(new Runnable() { @Override public void run() { try { Node node = NodeOp.findPath(manager.getRootContext(), names); if (node != null) { setSelectedNodes(new Node[] {node}); } } catch (PropertyVetoException e) { //Skip it, not important } catch (NodeNotFoundException x) { // OK, never mind } } }); } public String getSelectionPath () { Node[] selectedNodes = this.manager.getSelectedNodes(); if (selectedNodes == null || selectedNodes.length != 1) { return null; } Node rootNode = this.manager.getRootContext(); String[] path = NodeOp.createPath(selectedNodes[0],rootNode); StringBuilder builder = new StringBuilder(); for (int i=0; i< path.length; i++) { builder.append('/'); //NOI18N builder.append(path[i]); } assert builder.length() > 1 : "NodeOp.createPath() returned empty path for node " + selectedNodes[0] + " with root node " + rootNode; // NOI18N return builder.length() > 1 ? builder.substring(1) : null; } @Override public ExplorerManager getExplorerManager() { return this.manager; } @Override public void propertyChange(final PropertyChangeEvent event) { // workaround of issue 43502, update of Help button set back the focus // to component which is active when this change starts //XXX: this workaround causes problems in the selection of templates // and should be removed, this workaround can be workarounded in the // setSelectedTemplateByName when template name is null // select the first template only if no template is already selected, // but nicer solution is to remove this workaround at all. SwingUtilities.invokeLater (new Runnable () { @Override public void run() { firePropertyChange(event.getPropertyName(), event.getOldValue(), event.getNewValue()); } }); } @Override public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { if (ExplorerManager.PROP_SELECTED_NODES.equals (evt.getPropertyName())) { Node[] newValue = (Node[]) evt.getNewValue(); if (newValue == null || (newValue.length != 1 && newValue.length != 0)) { throw new PropertyVetoException ("Invalid length",evt); //NOI18N } } } @Override public void requestFocus () { this.createComponent().requestFocus(); } protected abstract JComponent createComponent (); private void initGUI () { this.setLayout (new GridBagLayout()); GridBagConstraints c = new GridBagConstraints (); c.gridx = GridBagConstraints.RELATIVE; c.gridy = GridBagConstraints.RELATIVE; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.NORTHWEST; c.weightx = 1.0; c.weighty = 1.0; JComponent component = this.createComponent (); ((GridBagLayout)this.getLayout()).setConstraints(component, c); this.add (component); } void addDefaultActionListener( ActionListener al ) { //do nothing by default } public void selectFirst() { RP.post(new Runnable() { @Override public void run() { final Children ch = getRootNode().getChildren(); // XXX what is the best way to wait for >0 node to appear without necessarily waiting for them all? if (ch.getNodesCount(true) > 0) { // blocks EventQueue.invokeLater(new Runnable() { // #210326 @Override public void run() { if (getSelectedNodes().length == 0) { // last minute try { getExplorerManager().setSelectedNodes(new Node[] {ch.getNodeAt(0)}); } catch (PropertyVetoException x) { Logger.getLogger(TemplatesPanelGUI.class.getName()).log(Level.INFO, "race condition while selecting first of " + getRootNode(), x); } } } }); } } }); } } private static class CategoriesBeanTreeView extends BeanTreeView { CategoriesBeanTreeView() { this.tree.setEditable(false); //#219709 - workaround for JDK bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8003400 tree.setLargeModel( false ); } @Override protected void showSelection(TreePath[] treePaths) { //#240260 - need to ajust path bounds to show the selected node completely. //Most likely the tree model includes 'please wait' node that the path bounds are calculated. //So when the wait node is removed later on the bounds are actually invalid. tree.getSelectionModel().setSelectionPaths(treePaths); if (treePaths.length == 1) { showPathWithoutExpansion(treePaths[0]); } } /** Make a path visible. * @param path the path */ private void showPathWithoutExpansion(TreePath path) { Rectangle rect = tree.getPathBounds(path); if (rect != null) { //PENDING TreeUI tmp = tree.getUI(); int correction = 0; if (tmp instanceof BasicTreeUI) { correction = ((BasicTreeUI) tmp).getLeftChildIndent(); correction += ((BasicTreeUI) tmp).getRightChildIndent(); } rect.x = Math.max(0, rect.x - correction); rect.y += rect.height; if (rect.y >= 0) { //#197514 - do not scroll to negative y values tree.scrollRectToVisible(rect); } } } } private static final class CategoriesPanel extends ExplorerProviderPanel { private CategoriesBeanTreeView btv; @Messages({ "ACSN_CategoriesPanel=Categories of types new objects", "ACSD_CategoriesPanel=List of categories of new objects which can be choosen" }) @Override protected synchronized JComponent createComponent() { if (this.btv == null) { this.btv = new CategoriesBeanTreeView (); this.btv.setRootVisible(false); this.btv.setPopupAllowed(false); this.btv.setFocusable(false); this.btv.setDefaultActionAllowed(false); this.btv.getAccessibleContext().setAccessibleName(ACSN_CategoriesPanel()); this.btv.getAccessibleContext().setAccessibleDescription(ACSD_CategoriesPanel()); this.btv.setDragSource(false); this.btv.setDropTarget(false); Border b = (Border)UIManager.get("Nb.ScrollPane.border"); // NOI18N if (b != null) { this.btv.setBorder(b); } } return this.btv; } } private static class TemplatesListView extends ListView implements ActionListener { TemplatesListView() { super (); // bugfix #44717, Enter key must work regardless if TemplatesPanels is focused list.unregisterKeyboardAction (KeyStroke.getKeyStroke (KeyEvent.VK_ENTER, 0, false)); setDefaultProcessor( this ); ToolTipManager.sharedInstance ().unregisterComponent (list); } @Override public void actionPerformed(ActionEvent e) { // Do nothing } } private static final class TemplatesPanel extends ExplorerProviderPanel { private ListView list; @Messages({ "ACSN_TemplatesPanel=Types of new objects", "ACSD_TemplatesPanel=List of types of new objects which can be choosen" }) @Override protected synchronized JComponent createComponent() { if (this.list == null) { this.list = new TemplatesListView (); this.list.setPopupAllowed(false); this.list.getAccessibleContext().setAccessibleName(ACSN_TemplatesPanel()); this.list.getAccessibleContext().setAccessibleDescription(ACSD_TemplatesPanel()); Border b = (Border)UIManager.get("Nb.ScrollPane.border"); if (b != null) { this.list.setBorder(b); // NOI18N } } return this.list; } @Override void addDefaultActionListener( ActionListener al ) { createComponent(); ((TemplatesListView)list).setDefaultProcessor( al ); } } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel categoriesPanel; private javax.swing.JEditorPane description; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JPanel panelFilter; private javax.swing.JPanel projectsPanel; // End of variables declaration//GEN-END:variables void warmUp (FileObject templatesFolder) { if (templatesFolder != null) { DataFolder df = DataFolder.findFolder (templatesFolder); if (df != null) { df.getChildren(); } } } void doFinished (FileObject temlatesFolder, String category, String template) { assert temlatesFolder != null; this.categoriesPanel.addPropertyChangeListener(this); this.projectsPanel.addPropertyChangeListener(this); this.setTemplatesFolder (temlatesFolder); this.setSelectedCategoryByName (category); this.setSelectedTemplateByName (template); categoriesPanel.requestFocus (); if (description.getEditorKit() instanceof HTMLEditorKit) { // override the Swing default CSS to make the HTMLEditorKit use the // same font as the rest of the UI. // XXX the style sheet is shared by all HTMLEditorKits. We must // detect if it has been tweaked by ourselves or someone else // (code completion javadoc popup for example) and avoid doing the // same thing again HTMLEditorKit htmlkit = (HTMLEditorKit) description.getEditorKit(); StyleSheet css = htmlkit.getStyleSheet(); if (css.getStyleSheets() != null) { description.setFont( jLabel1.getFont() ); return; } StyleSheet css2 = new StyleSheet(); Font f = jLabel1.getFont(); css2.addRule(new StringBuffer("body { font-size: ").append(f.getSize()) // NOI18N .append("; font-family: ").append(f.getName()).append("; }").toString()); // NOI18N css2.addStyleSheet(css); htmlkit.setStyleSheet(css2); } } // encoding support; copied from html/HtmlEditorSupport private static String findEncodingFromURL (InputStream stream) { try { byte[] arr = new byte[4096]; int len = stream.read (arr, 0, arr.length); String txt = new String(arr, 0, (len >= 0 ) ? len : 0, StandardCharsets.ISO_8859_1).toUpperCase(Locale.ENGLISH); // encoding return findEncoding (txt); } catch (IOException x) { Logger.getLogger(TemplatesPanelGUI.class.getName()).log(Level.INFO, null, x); } return null; } /** Tries to guess the mime type from given input stream. Tries to find * <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> * @param txt the string to search in (should be in upper case) * @return the encoding or null if no has been found */ private static String findEncoding (String txt) { int headLen = txt.indexOf (""); // NOI18N if (headLen == -1) { headLen = txt.length(); } int content = txt.indexOf ("CONTENT-TYPE"); // NOI18N if (content == -1 || content > headLen) { return null; } int charset = txt.indexOf ("CHARSET=", content); // NOI18N if (charset == -1) { return null; } int charend = txt.indexOf ('"', charset); int charend2 = txt.indexOf ('\'', charset); if (charend == -1 && charend2 == -1) { return null; } if (charend2 != -1) { if (charend == -1 || charend > charend2) { charend = charend2; } } return txt.substring (charset + "CHARSET=".length (), charend); // NOI18N } private QuickSearch.Callback createQuickSearchCallback() { return new QuickSearch.Callback() { @Override public void quickSearchUpdate( String searchText ) { if( null != searchText ) searchText = searchText.toLowerCase(); filterText = searchText; refreshContent(); } @Override public void showNextSelection( boolean forward ) { } @Override public String findMaxPrefix( String prefix ) { return prefix; } @Override public void quickSearchConfirmed() { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { ((CategoriesPanel)categoriesPanel).btv.requestFocus(); } }); } @Override public void quickSearchCanceled() { filterText = null; refreshContent(); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { clearQuickSearchField(); ((CategoriesPanel)categoriesPanel).btv.requestFocus(); } }); } }; } private void refreshContent() { FileObject folder = getCurrentTemplatesFolder(); if( null != folder ) { setTemplatesFolder( folder ); setSelectedCategoryByName( null ); } } private void adjustQuickSearch( QuickSearch qs ) { qs.setAlwaysShown( true ); Component qsComponent = panelFilter.getComponent( 0 ); if( qsComponent instanceof JComponent ) { ((JComponent)qsComponent).setBorder( BorderFactory.createEmptyBorder() ); } JTextField textField = getQuickSearchField(); if( null != textField ) textField.setMaximumSize( null ); } private JTextField getQuickSearchField() { Component qsComponent = panelFilter.getComponent( 0 ); if( qsComponent instanceof JComponent ) { for( Component c : ((JComponent)qsComponent).getComponents() ) { if( c instanceof JTextField ) { return ( JTextField ) c; } } } return null; } private void clearQuickSearchField() { JTextField textField = getQuickSearchField(); if( null != textField ) textField.setText( null ); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy