|
What this is
Other links
The source code/* * 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.netbeans.modules.refactoring.ui; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import javax.jmi.reflect.RefObject; import javax.swing.*; import javax.swing.text.Position; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import org.netbeans.jmi.javamodel.*; import org.netbeans.modules.javacore.internalapi.InvalidationListener; import org.netbeans.modules.javacore.internalapi.JavaMetamodel; import org.netbeans.modules.javacore.internalapi.ProgressEvent; import org.netbeans.modules.javacore.internalapi.ProgressListener; import org.netbeans.modules.refactoring.RefactoringSupportImpl; import org.netbeans.modules.refactoring.api.RefactoringElement; import org.netbeans.modules.refactoring.api.RefactoringSupport; import org.netbeans.modules.refactoring.api.ui.ParametersPanel; import org.netbeans.modules.refactoring.api.ui.RefactoringUI; import org.openide.ErrorManager; import org.openide.explorer.ExplorerPanel; import org.openide.text.CloneableEditorSupport; import org.openide.text.PositionBounds; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; import org.openide.util.Utilities; import org.openide.windows.Mode; import org.openide.windows.WindowManager; import org.openide.windows.Workspace; /** * Panel for showing proposed changes (refactoring elements) of any refactoring. * * @author Pavel Flaska, Martin Matula */ public class RefactoringPanel extends JPanel implements InvalidationListener, ProgressListener { // PRIVATE FIELDS /* tree contains elements which will be changed by refactoring action */ private transient JTree tree = null; /* toolbar button causing refresh of the data */ private transient JButton refreshButton = null; /* button lying in the toolbar allows expansion of all nodes in a tree */ private transient JToggleButton expandButton = null; /* progress bar */ private transient JProgressBar progressBar = null; private transient JButton refactorButton = null; private transient JButton cancelButton = null; private transient ButtonL buttonListener = null; private final RefactoringUI ui; private final boolean isQuery; private transient boolean isVisible = false; private transient Collection elements = null; private transient ParametersPanel parametersPanel = null; private transient JScrollPane scrollPane = null; private transient JPanel southPanel; private static final int MAX_ROWS = 50; public RefactoringPanel(RefactoringUI ui) { this.ui = ui; this.isQuery = ui.isQuery(); initialize(); refresh(); } public static void checkEventThread() { if (!SwingUtilities.isEventDispatchThread()) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new IllegalStateException("This must happen in event thread!")); //NOI18N } } /* initializes all the ui */ private void initialize() { checkEventThread(); setLayout(new BorderLayout()); // add panel with buttons JButton[] buttons = getButtons(); //if (buttons.length != 0) { // there will be at least one button on panel southPanel = new JPanel(new GridBagLayout()); for (int i = 0; i < buttons.length; i++) { GridBagConstraints c = new GridBagConstraints(); c.gridy = 0; c.insets = new Insets(5, 5, 5, 0); southPanel.add(buttons[i], c); } JPanel pp = new JPanel(new BorderLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridy = 0; c.insets = new Insets(5, 5, 5, 5); c.weightx = 1; c.fill = c.HORIZONTAL; southPanel.add(pp, c); progressBar = new JProgressBar(); progressBar.setVisible(false); pp.add(progressBar, BorderLayout.CENTER); if (!isQuery) { add(southPanel, BorderLayout.SOUTH); } //} // put the toolbar to the panel. If the getToolBar() returns null, // suppose the toolbar does not exist. JToolBar toolBar = getToolBar(); if (toolBar != null) add(toolBar, BorderLayout.WEST); } /** * Returns the toolbar. In this default implementation, toolbar is * oriented vertically in the west and contains 'expand tree' toggle * button and refresh button. * Override this method and return null if you do not want toolbar * in your panel. * * @return toolBar with actions for refactoring panel */ private JToolBar getToolBar() { checkEventThread(); refreshButton = new JButton( new ImageIcon(Utilities.loadImage( "org/netbeans/modules/refactoring/resources/refresh.gif")) // NOI18N ); Dimension dim = new Dimension(24, 24); refreshButton.setMaximumSize(dim); refreshButton.setMinimumSize(dim); refreshButton.setPreferredSize(dim); refreshButton.setToolTipText( NbBundle.getMessage(RefactoringPanel.class, "HINT_refresh") // NOI18N ); refreshButton.addActionListener(getButtonListener()); // expand button settings expandButton = new JToggleButton( new ImageIcon(Utilities.loadImage( "org/netbeans/modules/refactoring/resources/expandTree.gif")) // NOI18N ); expandButton.setMaximumSize(dim); expandButton.setMinimumSize(dim); expandButton.setPreferredSize(dim); expandButton.setSelected(true); expandButton.setToolTipText( NbBundle.getMessage(RefactoringPanel.class, "HINT_expandAll") // NOI18N ); expandButton.addActionListener(getButtonListener()); // create toolbar JToolBar toolBar = new JToolBar(JToolBar.VERTICAL); toolBar.setFloatable(false); toolBar.add(refreshButton); toolBar.add(expandButton); return toolBar; } /** * Returns array of available buttons. Initially, it returns only * basic "do refactoring/cancel refactoring" button. Override this method, * if you want to provide any other buttons with different action to be * performed. * * @return array of avasilable buttons. */ private JButton[] getButtons() { checkEventThread(); if (isQuery) { refactorButton = null; // cancelButton = new JButton(NbBundle.getMessage(RefactoringPanel.class, "LBL_CloseRefactor")); // NOI18N // cancelButton.setToolTipText(NbBundle.getMessage(RefactoringPanel.class, "HINT_CloseRefactor")); // NOI18N // cancelButton.addActionListener(getButtonListener()); // return new JButton[] {cancelButton}; return new JButton[] {}; } else { refactorButton = new JButton(NbBundle.getMessage(RefactoringPanel.class, "LBL_DoRefactor")); // NOI18N refactorButton.setToolTipText(NbBundle.getMessage(RefactoringPanel.class, "HINT_DoRefactor")); // NOI18N refactorButton.setMnemonic(NbBundle.getMessage(RefactoringPanel.class, "MNEM_DoRefactor").charAt(0)); refactorButton.addActionListener(getButtonListener()); // cancelButton = new JButton(NbBundle.getMessage(RefactoringPanel.class, "LBL_CancelRefactor")); // NOI18N // cancelButton.setToolTipText(NbBundle.getMessage(RefactoringPanel.class, "HINT_CancelRefactor")); // NOI18N // cancelButton.addActionListener(getButtonListener()); // return new JButton[] {refactorButton, cancelButton}; return new JButton[] {refactorButton}; } } private CheckNode createNode(Object representedObject, HashMap nodes, CheckNode root) { //checkEventThread(); CheckNode node = (CheckNode) nodes.get(representedObject); if (node != null) { return node; } Object parent = null; String resourceID = null; String displayName = null; boolean cannotEnable = false; if (representedObject instanceof RefactoringElement) { RefactoringElement re = (RefactoringElement) representedObject; displayName = re.getDisplayText(); if (!isQuery && re.getStatus() == RefactoringElement.GUARDED) { displayName = displayName + " [" + // NOI18N NbBundle.getMessage(RefactoringPanel.class, "LBL_InGuardedBlock") + "]"; cannotEnable = true; } displayName = normalize(displayName); parent = re.getJavaElement(); resourceID = null; } else if (representedObject instanceof NamedElement) { if (representedObject instanceof Feature) { parent = ((NamedElement) representedObject).refImmediateComposite(); displayName = ((NamedElement) representedObject).getName(); if (representedObject instanceof JavaClass) { resourceID = IconStrings.CLASS; } else if (representedObject instanceof Field) { resourceID = IconStrings.FIELD_PUBLIC; } else if (representedObject instanceof Method) { resourceID = IconStrings.METHOD_PUBLIC; } else if (representedObject instanceof Constructor) { resourceID = IconStrings.CONSTRUCTOR_PUBLIC; displayName = ((JavaClass)((Constructor) representedObject).getDeclaringClass()).getName(); } else if (representedObject instanceof Initializer) { resourceID = IconStrings.CONSTRUCTOR_PUBLIC; displayName = "<initializer>"; // NOI18N } } else if (representedObject instanceof JavaPackage) { resourceID = IconStrings.JAVA_PACKAGE; displayName = ((JavaPackage) representedObject).getName(); if ("".equals(displayName)) displayName = NbBundle.getMessage(RefactoringPanel.class, "LBL_DefaultPackage"); parent = null; } else if (representedObject instanceof ClassDefinition) { displayName = "<anonymous class>"; // NOI18N parent = representedObject; do { parent = ((RefObject)parent).refImmediateComposite(); } while (parent!=null && !(parent instanceof Feature)); } else if (representedObject instanceof Resource) { resourceID = IconStrings.SOURCE_OPTIONS; String relativeName = ((Resource) representedObject).getName(); displayName = relativeName.substring(relativeName.lastIndexOf('/') + 1); parent = ((Resource) representedObject).refImmediateComposite(); } } node = new CheckNode(representedObject, displayName, resourceID == null ? null : new ImageIcon(Utilities.loadImage(resourceID + ".gif"))); if (cannotEnable) node.setDisabled(); //if (isQuery) // node.getPosition(); CheckNode parentNode = parent == null ? root : createNode(parent, nodes, root); parentNode.add(node); nodes.put(representedObject, node); return node; } /** * Overrides default ExplorerPanel behaviour. Does nothing now. */ protected void updateTitle() { } /** * Method is responsible for making changes in sources. */ private void refactor() { checkEventThread(); disableComponents(RefactoringPanel.this); RequestProcessor.getDefault().post(new Runnable() { public void run() { RefactoringSupport.getDefault().doRefactoring(elements, ui.getName(), RefactoringPanel.this); JavaMetamodel.getUndoManager().saveAll(); SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(progressBar.getMaximum()); RefactoringPanel.this.close(); } }); } }); } /** * Cancel refactor action. This default implementation is closing window * only. It can return result state. In this implementation it returns * everytime 0. * * @return result of cancel operation. Zero represent successful cancel. */ private int cancel() { checkEventThread(); this.close(); return 0; } void close() { if (isQuery) { RefactoringPanelContainer.getUsagesComponent().removePanel(this); } else { RefactoringPanelContainer.getRefactoringComponent().removePanel(this); } closeNotify(); } /* * Initializes button listener. The subclasses must not need this listener. * This is the reason of lazy initialization. */ private ButtonL getButtonListener() { if (buttonListener == null) buttonListener = new ButtonL(); return buttonListener; } RequestProcessor rp = new RequestProcessor(); /* expandAll nodes in the tree */ public void expandAll() { checkEventThread(); final Cursor old = getCursor(); expandButton.setEnabled(false); scrollPane.getViewport().remove(tree); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); rp.post(new Runnable() { public void run() { int row = 0; while (row < tree.getRowCount()) { tree.expandRow(row); row++; } SwingUtilities.invokeLater(new Runnable() { public void run() { scrollPane.setViewportView(tree); setCursor(old); expandButton.setEnabled(true); } }); }}); } /* collapseAll nodes in the tree */ public void collapseAll() { checkEventThread(); expandButton.setEnabled(false); final Cursor old = getCursor(); scrollPane.getViewport().remove(tree); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); rp.post(new Runnable() { public void run() { int row = tree.getRowCount() - 1; while (row > 0) { tree.collapseRow(row); row--; } SwingUtilities.invokeLater(new Runnable() { public void run() { scrollPane.setViewportView(tree); setCursor(old); expandButton.setEnabled(true); } }); }}); } public void invalidateObject() { if (isQuery) { return; } Runnable invalidate = new Runnable() { public void run() { setRefactoringEnabled(false); } }; if (SwingUtilities.isEventDispatchThread()) { invalidate.run(); } else { SwingUtilities.invokeLater(invalidate); } } private void refresh() { checkEventThread(); JavaMetamodel.getUndoManager().saveAll(); // create parameters panel for refactoring if (parametersPanel == null) { parametersPanel = new ParametersPanel(ui); } // show parameters dialog Collection tempElements = parametersPanel.showDialog(); // if no elements were returned, action was either cancelled or preview // was skipped -> finish if (tempElements == null) { return; } elements = tempElements; final String description = ui.getDescription(); setName(ui.getName()); RequestProcessor.getDefault().post(new Runnable() { public void run() { HashSet editorSupports = new HashSet(); int errorsNum = 0; if (!isQuery) { for (Iterator iter = elements.iterator(); iter.hasNext(); ) { RefactoringElement elem = (RefactoringElement) iter.next(); if (elem.getStatus() == RefactoringElement.GUARDED) { errorsNum++; } } } int occurencesNum = elements.size(); StringBuffer errorsDesc = new StringBuffer(); errorsDesc.append(" [" + occurencesNum); // NOI18N errorsDesc.append(' '); errorsDesc.append(occurencesNum == 1 ? NbBundle.getMessage(RefactoringPanel.class, "LBL_Occurence") : NbBundle.getMessage(RefactoringPanel.class, "LBL_Occurences") ); if (errorsNum > 0) { errorsDesc.append(','); errorsDesc.append(' '); errorsDesc.append("" + errorsNum); // NOI18N errorsDesc.append(' '); errorsDesc.append(errorsNum == 1 ? NbBundle.getMessage(RefactoringPanel.class, "LBL_Error") : NbBundle.getMessage(RefactoringPanel.class, "LBL_Errors") ); errorsDesc.append(""); // NOI18N } errorsDesc.append(']'); final CheckNode root = new CheckNode(null, description + errorsDesc.toString(), new ImageIcon(Utilities.loadImage("org/netbeans/modules/refactoring/resources/" + (isQuery ? "query.gif" : "refactoring.gif")))); HashMap nodes = new HashMap(); start(new ProgressEvent(this, ProgressEvent.START, 0, elements.size()/10)); int i=0; JavaMetamodel.getDefaultRepository().beginTrans(false); try { for (Iterator it = elements.iterator(); it.hasNext();i++) { RefactoringElement e = (RefactoringElement) it.next(); createNode(e, nodes, root); PositionBounds pb = e.getPosition(); if (pb != null) { CloneableEditorSupport ces = pb.getBegin().getCloneableEditorSupport(); editorSupports.add(ces); } if (i % 10 == 0) step(new ProgressEvent(this,ProgressEvent.STEP)); } } finally { JavaMetamodel.getDefaultRepository().endTrans(); } JavaMetamodel.getUndoManager().watch(editorSupports, RefactoringPanel.this); stop(new ProgressEvent(this, ProgressEvent.STOP)); SwingUtilities.invokeLater(new Runnable() { public void run() { if (tree == null) { // add panel with appropriate content tree = new JTree(root) { public TreePath getNextMatch(String prefix, int startingRow, Position.Bias bias) { try { return super.getNextMatch(prefix,startingRow, bias); } catch (NullPointerException e) { //Work around for 43112 } return null; } }; tree.setCellRenderer(new CheckRenderer(isQuery)); CheckNodeListener l = new CheckNodeListener(isQuery); tree.addMouseListener(l); tree.addKeyListener(l); tree.setToggleClickCount(0); scrollPane = new JScrollPane(tree); RefactoringPanel.this.add(scrollPane, BorderLayout.CENTER); } else { tree.setModel(new DefaultTreeModel(root)); } tree.setRowHeight((int) ((CheckRenderer) tree.getCellRenderer()).getPreferredSize().getHeight()); if (elements.size() < MAX_ROWS) expandAll(); else expandButton.setSelected(false); setRefactoringEnabled(true); } }); } }); if (!isVisible) { // dock it into output window area and display RefactoringPanelContainer cont = isQuery ? RefactoringPanelContainer.getUsagesComponent() : RefactoringPanelContainer.getRefactoringComponent(); cont.requestActive(); cont.addPanel(this); isVisible = true; } setRefactoringEnabled(false); } void setRefactoringEnabled(boolean enabled) { checkEventThread(); if (tree != null) { if (!enabled) { CheckNode c = (CheckNode) tree.getModel().getRoot(); c.setNeedsRefresh(); tree.setModel(new DefaultTreeModel(c, false)); } // tree.validate(); tree.setEnabled(enabled); if (refactorButton != null) { refactorButton.setEnabled(enabled); } } } // disables all components in a given container private static void disableComponents(Container c) { checkEventThread(); Component children[] = c.getComponents(); for (int i = 0; i < children.length; i++) { if (children[i].isEnabled()) { children[i].setEnabled(false); } if (children[i] instanceof Container) { disableComponents((Container) children[i]); } } } //////////////////////////////////////////////////////////////////////////// // INNER CLASSES //////////////////////////////////////////////////////////////////////////// private class ButtonL implements ActionListener { public void actionPerformed(ActionEvent event) { Object o = event.getSource(); // Cancel button pressed, remove refactoring panel if (o == cancelButton) { cancel(); } else if (o == refactorButton) { refactor(); } // expandAll button selected/deselected else if (o == expandButton && tree != null) { if (expandButton.isSelected()) expandAll(); else collapseAll(); } else if (o == refreshButton) { refresh(); } } } // end ButtonL //////////////////////////////////////////////////////////////////////////// private static String normalize(String input) { int size = input.length(); char[] c = new char[size]; input.getChars(0, size, c, 0); boolean wb = false; int pos = 0; char[] nc = new char[size]; for (int i = 0; i < size; i++) { if (Character.isWhitespace(c[i])) { if (!wb) { nc[pos++] = ' '; wb = true; } } else { nc[pos++] = c[i]; wb = false; } } return new String(nc, 0, pos); } /** Processes returned problems from refactoring operations and notifies * user (in case of non-fatal problems gives user a chance to continue or cancel). * @param problem Problems returned from a refactoring operation. * @return |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.