Package org.openquark.gems.client

Source Code of org.openquark.gems.client.RenameRefactoringDialog$NameComboListRenderer

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* RenameRefactoringDialog.java
* Creation date: Jun 18, 2004
* By: Iulian Radu
*/
package org.openquark.gems.client;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.LayoutFocusTraversalPolicy;
import javax.swing.ListCellRenderer;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

import org.openquark.cal.compiler.CompilerMessage;
import org.openquark.cal.compiler.CompilerMessageLogger;
import org.openquark.cal.compiler.LanguageInfo;
import org.openquark.cal.compiler.MessageLogger;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.ModuleSourceDefinition;
import org.openquark.cal.compiler.ModuleSourceDefinitionGroup;
import org.openquark.cal.compiler.ModuleTypeInfo;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.Refactorer;
import org.openquark.cal.compiler.SourceIdentifier;
import org.openquark.cal.compiler.TypeClass;
import org.openquark.cal.compiler.TypeConstructor;
import org.openquark.cal.compiler.Refactorer.CALRefactoringException;
import org.openquark.cal.machine.StatusListener;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.services.CALWorkspace;
import org.openquark.cal.services.GemEntity;
import org.openquark.cal.services.IdentifierUtils;
import org.openquark.cal.services.MetaModule;
import org.openquark.cal.services.Perspective;
import org.openquark.cal.services.ResourceStore;
import org.openquark.cal.services.Status;
import org.openquark.cal.services.WorkspaceManager;
import org.openquark.cal.services.WorkspaceResource;


/**
* A dialog box used for renaming Gems (ie functions, class methods or data constructors), type classes, and type constructors.
*
* @author Peter Cardwell
*/
public final class RenameRefactoringDialog extends JDialog {
   
    private static final long serialVersionUID = -1471936909236566691L;

    /** The icon to use if everything is ok. */
    static final Icon OK_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/checkmark.gif"));
   
    /** The icon to use for error messages. */
    static final Icon ERROR_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/error.gif"));
   
    /** The icon to use for warning messages. */
    static final Icon WARNING_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/warning.gif"));
   
    /** The icon to use to indicate modules. */
    static final Icon MODULE_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/nav_module.png"));
   
    /** The icon to use to indicate functions. */
    static final Icon FUNCTION_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/Gem_Red.gif"));
   
    /** The icon to use to indicate data constructors. */
    static final Icon DATACONS_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/Gem_Yellow.gif"));
   
    /** The icon to use to indicate type classes. */
    static final Icon TYPECLASS_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/nav_typeclass.gif"));
   
    /** The icon to use to indicate type constructors. */
    static final Icon TYPECONS_ICON = new ImageIcon(GemCutter.class.getResource("/Resources/nav_typeconstructor.gif"));
   
    /**
     * @author Peter Cardwell
     *
     * A class representing the result of the refactor operation.
     * Contains the original name of the feature that was refactored,
     * the name it was changed to, and its category.
     */
    public static class Result {
      
        /** The original name of the item that was renamed. If applicable, this should be a fully qualified name. */
        private final String fromName;
       
        /** The new name of the item that was renamed. If applicable, this should be a fully qualified name. */
        private final String toName;       
       
        /** The category of the item that was renamed. */
        private final SourceIdentifier.Category category;

        Result (String fromName, String toName, SourceIdentifier.Category category) {
            this.fromName = fromName;
            this.toName = toName;
            this.category = category;
        }
       
        /**
         * @return The original name of the item that was renamed. If applicable, this should be a fully qualified name.
         */
        public String getFromName() {
            return fromName;
        }
       
        /**
         * @return The new name of the item that was renamed. If applicable, this should be a fully qualified name.
         */
        public String getToName() {
            return toName;
        }
       
        /**
         * @return The category of the item that was renamed.
         */
        public SourceIdentifier.Category getCategory() {
            return category;
        }
       
        /**
         * @return The type of the item that was renamed.
         */
        public EntityType getEntityType() {
            if (category == SourceIdentifier.Category.MODULE_NAME) {
                return EntityType.Module;
            } else if (category == SourceIdentifier.Category.TYPE_CLASS) {
                return EntityType.TypeClass;
            } else if (category == SourceIdentifier.Category.TYPE_CONSTRUCTOR) {
                return EntityType.TypeConstructor;
            } else if (category == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD ||
                       category == SourceIdentifier.Category.DATA_CONSTRUCTOR) {
                return EntityType.Gem;
            } else {
                throw new IllegalStateException("Invalid category in rename result.");
            }
        }
    }
   
    /**
     * Generic item renderer for lists used in the dialog box. Displays names and appropriate icons.
     *
     * @author Peter
     */
    static class RenameListRenderer extends JLabel implements ListCellRenderer {
       
        private static final long serialVersionUID = 6522948562916719460L;
        private final Icon itemIcon;
        private final boolean showSelections;
       
        /**
         * Constructor
         * @param icon icon to use for each item
         * @param showSelections true if the user selections should be made visible.
         */
        public RenameListRenderer(Icon icon, boolean showSelections) {
            this.itemIcon = icon;
            this.showSelections = showSelections;
            setOpaque(true);
        }
       
        /**
         * This method finds the image and text corresponding
         * to the selected value and returns the label, set up
         * to display the text and image.
         */
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
           
            if (isSelected && showSelections) {
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }
           
            String text = value.toString(); // value could be a String or a ModuleName
            Icon icon = itemIcon;
            setIcon(icon);
            setText(text);
            setFont(list.getFont());
           
            return this;
        }
    }

   
    /**
     * A thread to perform the actual refactorings and recompilations.
     * @author Peter Cardwell
     */
    class RefactoringThread extends Thread {
       
        @Override
        public void run() {
           if (doRefactorings()) {
               dispose();
           } else {
               setVisibleButtons(new JButton[]{backButton, retryButton, cancelButton});
               setEnabledButtons(new JButton[]{backButton, retryButton, cancelButton});
               exitProgressMode();
              
               statusLabel.setText(GemCutter.getResourceString("RNRD_ErrorsEncountered"));
               statusLabel.setIcon(ERROR_ICON);
              
               // We're done with the status listener..
               refactorer.setStatusListener(null);
           }
        }
    }
   
    /** The currently selected entityType */
    private EntityType entityType;
   
    /** The currently selected module (only used when renaming a qualified entity) */
    private ModuleName moduleName;
   
    /** A list of modules that are affected by the rename operation */
    private List<ModuleName> affectedModuleNames;
   
    /** True if the currently selected module is empty. */
    private boolean emptyModule = false;
   
   
    // GUI components
    private final JLabel sourceModuleLabel = new JLabel(GemCutter.getResourceString("RNRD_Module"));
    private final JLabel oldNameLabel = new JLabel(GemCutter.getResourceString("RNRD_CurrentName"));   
    private final JComboBox oldNameCombo = new JComboBox(new DefaultComboBoxModel());
    private final JLabel newNameLabel = new JLabel(GemCutter.getResourceString("RNRD_NewName"));
    private final JTextField newNameField = new JTextField();
    private final ButtonGroup entityTypeButtonGroup = new ButtonGroup();
    private final JRadioButton gemRadioButton = new JRadioButton(GemCutter.getResourceString("RNRD_GemEntityType"));
    private final JRadioButton typeClassRadioButton = new JRadioButton(GemCutter.getResourceString("RNRD_TypeClassEntityType"));
    private final JRadioButton typeConsRadioButton = new JRadioButton(GemCutter.getResourceString("RNRD_TypeConsEntityType"));
    private final JRadioButton moduleRadioButton = new JRadioButton(GemCutter.getResourceString("RNRD_ModuleEntityType"));
    private final JComboBox sourceModuleList = new JComboBox(new DefaultComboBoxModel());
    private final JLabel titleLabel = new JLabel(GemCutter.getResourceString("RNRD_Rename"));
    private JPanel mainPanel;
   
    /** If false, the user should not be allowed to make any changes that affect the Prelude module. */
    private final boolean allowPreludeRenaming;
    /** Indicates whether the from name was passed into the constructor */
    private final boolean fromNameIsPreset;
    /** Indicates whether the category was passed into the constructor */
    private final boolean entityTypeIsPreset;
 
    /** If false, the user should be forbidden to rename gems to names that already exist. */
    private final boolean allowDuplicateRenaming;
   
    /** If true, then we are allowing an "unsafe" operation to go forward (i.e., one for which the user may need to manually
     * perform some cleanup before we recompile) */
    private boolean proposedFactoringUnsafe;
   
    /** The (unqualified) original name of the item to rename. */
    private String fromName;
    /** The (unqualified) name that the item should be renamed to. */
    private String toName;
    /** The type of renaming to perform */
    private SourceIdentifier.Category category;
    /** True if the refactoring successfully completed, false otherwise. */
    private boolean refactorSuccessful = false;
    private Action okAction = getOkAction();
    private Action retryAction = getRetryAction();
    private Action cancelAction = getCancelAction();
    private Action backAction = getBackAction();
    private Refactorer.Rename refactorer;
    private final Perspective perspective;
    private RefactoringThread refactoringThread;
    private Dimension minimumSize;
    private final WorkspaceManager workspaceManager;
    //private RenameRefactorer.StatusListener refactoringStatusListener;
    /**
     * Indicates if old module/name or new name is dirty
     * (ie: the current refactoring operation does not validly represent the ui fields)
     */
    private boolean dirtyFields = true;
    /** Indicates that this dialog is being automatically driven by an undo/redo command. */
    private final boolean automatedMode;
    private final JList errorsList = new JList(new DefaultListModel());
    private final JScrollPane informationScrollPane = new JScrollPane(errorsList);
    private final JButton okButton = new JButton(okAction);
    private final JButton retryButton = new JButton(retryAction);
    private final JButton backButton = new JButton(backAction);
    private final JButton cancelButton = new JButton(cancelAction);
    private final JLabel statusLabel = new JLabel("                         ");
    private final JLabel entityTypeLabel = new JLabel(GemCutter.getResourceString("RNRD_EntityType"));
    private final JLabel progressLabel = new JLabel(GemCutter.getResourceString("RNRD_Progress"));
    private final JProgressBar progressBar = new JProgressBar(0, 100);
   
    /** An array containing all action buttons on the dialog. This is used by setEnabledButtons() and setVisibleButtons() to know which
      * buttons to disable/hide. */
    private final JButton[] dialogButtons = new JButton[]{okButton, retryButton, cancelButton, backButton};
   
    /** An array containing all components in the dialog used for value entry. This is used by lockValueEntry() and unlockValueEntry() to
     * know which components to enable and disable. */
    private final Component[] valueEntryComponents = new Component[] {
        sourceModuleList,
        oldNameCombo,
        newNameField,
        gemRadioButton,
        typeClassRadioButton,
        typeConsRadioButton,
        moduleRadioButton,
    };
   
    /** Type safe-enum pattern enumerating the various entity types */
    static class EntityType {
        private final String description;
       
        private EntityType (String description) {
            this.description = description;
        }
       
        @Override
        public String toString() {
            return description;
        }
       
        public static final EntityType Gem =
            new EntityType("Gem");
       
        public static final EntityType TypeConstructor =
            new EntityType("Type Constructor");
       
        public static final EntityType TypeClass =
            new EntityType("Type Class");
       
        public static final EntityType Module =
            new EntityType("Module");
    }
       
    /**
     * Constructs a RenameRefactoringDialog.
     * @param parent The parent frame of this dialog
     * @param workspaceManager The workspace manager for the CAL sources.
     * @param perspective The perspective containing the current working context
     * @param fromName If not null, this means the from name should be pre-selected. entityType must be non-null if this value is non-null.
     * @param toName If not null, this means the to name should be pre-selected and the dialog operation should proceed without user input
     *  (for undoing and redoing). fromName must be non-null for this value to be non-null.
     * @param entityType If not null, this means the entity type should be pre-selected.
     * @param allowPreludeRenaming If false, the user will be prevented from renaming entities in the prelude module.
     */
    RenameRefactoringDialog(JFrame parent, WorkspaceManager workspaceManager, Perspective perspective, String fromName, String toName, EntityType entityType, boolean allowPreludeRenaming, boolean allowDuplicateRenaming) {
        super(parent, true);

        if ((workspaceManager == null) || (perspective == null)) {
            throw new NullPointerException();
        }

        if (fromName != null) {
            if (entityType == null) {
                throw new IllegalArgumentException("For the from name to be preset, the entity type must be specified");
            } else if (entityType == EntityType.Module) {
                this.moduleName = ModuleName.make(fromName);
                this.fromName = fromName;
            } else {
                QualifiedName qualifiedFromName = QualifiedName.makeFromCompoundName(fromName);
                this.moduleName = qualifiedFromName.getModuleName();
                this.fromName = qualifiedFromName.getUnqualifiedName();
            }
        }

        this.workspaceManager = workspaceManager;
        this.perspective = perspective;
        this.allowPreludeRenaming = allowPreludeRenaming;
        this.allowDuplicateRenaming = allowDuplicateRenaming;
        this.toName = toName;
        this.entityType = entityType;

        this.proposedFactoringUnsafe = false;

        this.fromNameIsPreset = (this.fromName != null);
        this.entityTypeIsPreset = (this.entityType != null);
        this.automatedMode = (this.toName != null);

        if (automatedMode && !fromNameIsPreset) {
            throw new IllegalArgumentException("If newEntityName is non-null, entityName must be non-null");
        }

        if (automatedMode) {
            // Create a listener to begin refactoring as soon as the dialog is
            // shown.
            ComponentListener componentListener = new ComponentListener() {
                public void componentHidden(ComponentEvent e) {
                }

                public void componentMoved(ComponentEvent e) {
                }

                public void componentResized(ComponentEvent e) {
                }

                public void componentShown(ComponentEvent e) {
                    // Begin refactoring
                    statusLabel.setText(GemCutter.getResourceString("RNRD_Inspecting"));
                    statusLabel.setIcon(null);
                    if ((refactoringThread == null) || (!refactoringThread.isAlive())) {
                        refactoringThread = new RefactoringThread();
                        refactoringThread.start();
                    } else {
                        throw new IllegalStateException("Tried to start new refactoring thread while another was running.");
                    }
                    removeComponentListener(this);
                }
            };

            addComponentListener(componentListener);
        }

        setLocationRelativeTo(parent);      
    }
   
    /**
     * @return the panel used for selecting which entity type to rename.
     */
    private JPanel getEntityTypeSelectPanel() {
       
        entityTypeButtonGroup.add(gemRadioButton);
        entityTypeButtonGroup.add(typeClassRadioButton);
        entityTypeButtonGroup.add(typeConsRadioButton);
        entityTypeButtonGroup.add(moduleRadioButton);
       
        JPanel radioPanel = new JPanel();
        radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.X_AXIS));
       
        radioPanel.add(Box.createHorizontalGlue());
        radioPanel.add(entityTypeLabel);
        radioPanel.add(Box.createHorizontalStrut(5));
        radioPanel.add(gemRadioButton);
        radioPanel.add(Box.createHorizontalStrut(5));
        radioPanel.add(typeConsRadioButton);
        radioPanel.add(Box.createHorizontalStrut(5));
        radioPanel.add(typeClassRadioButton);
        radioPanel.add(Box.createHorizontalStrut(5));
        radioPanel.add(moduleRadioButton);
        radioPanel.add(Box.createHorizontalGlue());
       
        return radioPanel;
    }
   
    /**
     * @return the panel that contains the buttons at the bottom of the dialog
     */
    private JPanel getButtonPanel() {
       
        JPanel buttonPanel = new JPanel();
       
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
       
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(backButton);
        buttonPanel.add(okButton);
        buttonPanel.add(retryButton);
        buttonPanel.add(Box.createHorizontalStrut(5));
        buttonPanel.add(cancelButton);
       
        return buttonPanel;
    }
       
   
   
    /**
     * Set appropriate listeners, layout the dialog, and set the dialog to its initial state.
     */
    private void initialize() {
       
        gemRadioButton.setSelected(true);
       
        // Populate the module name combo box with the workspace modules
       
        List<ModuleName> moduleList = new ArrayList<ModuleName>();
        ModuleName[] moduleNames = getWorkspace().getModuleNames();
        for (final ModuleName module : moduleNames) {
            moduleList.add(module);
        }
        Collections.sort(moduleList);
        for (int i = 0, n = moduleList.size(); i < n; i++) {
            ((DefaultComboBoxModel)sourceModuleList.getModel()).addElement(moduleList.get(i));
        }
       
        if (moduleName == null) {
            moduleName = perspective.getWorkingModuleName();
        }
        sourceModuleList.setSelectedItem(moduleName);
        sourceModuleList.setRenderer(new RenameListRenderer(MODULE_ICON, true));
       
        // Populate gem combo box with module gems
       
        oldNameCombo.setEditable(true);
        oldNameCombo.setRenderer(new NameComboListRenderer(perspective.getMetaModule((ModuleName)sourceModuleList.getSelectedItem()).getTypeInfo(), entityType));
        populateOldNameCombo();
       
        updateFromName();
       
        if (!automatedMode) {           
            toName = fromName;
        }
       
        newNameField.setText(toName);
        newNameField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {               
                toName = newNameField.getText();
                updateUIState();               
                dirtyFields = true;
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    dispose();
                }
            }
        });
       
        newNameField.getDocument().addDocumentListener(new DocumentListener() {
            public void changeOccurred() {
                toName = newNameField.getText();
                updateUIState();               
                dirtyFields = true;
            }

            public void changedUpdate(DocumentEvent e) {
                changeOccurred();
            }

            public void insertUpdate(DocumentEvent e) {
                changeOccurred();
            }

            public void removeUpdate(DocumentEvent e) {
                changeOccurred();   
            }
        });
       
        if (!fromNameIsPreset) {
            ActionListener actionListener = new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dirtyFields = true;
                   
                    if (!entityTypeIsPreset) {
                        // Check if the gemType has changed
                        if (entityType != EntityType.Gem && gemRadioButton.isSelected()) {
                            entityType = EntityType.Gem;
                            populateOldNameCombo();
                        } else if (entityType != EntityType.TypeClass && typeClassRadioButton.isSelected()) {
                            entityType = EntityType.TypeClass;
                            populateOldNameCombo();
                        } else if (entityType != EntityType.TypeConstructor && typeConsRadioButton.isSelected()) {
                            entityType = EntityType.TypeConstructor;
                            populateOldNameCombo();
                        }
                    }
                    updateUIState();
                    newNameField.requestFocus();
                    newNameField.selectAll();
                }
            };
           
            gemRadioButton.addActionListener(actionListener);
            typeClassRadioButton.addActionListener(actionListener);
            typeConsRadioButton.addActionListener(actionListener);
           
            oldNameCombo.addItemListener(new ItemListener() {
                public void itemStateChanged(ItemEvent e) {
                    dirtyFields = true;
                    updateFromName();
                    if(oldNameCombo.getSelectedItem() != null) {
                        newNameField.setText(fromName);
                    }
                    updateUIState();
                }
            });
           
            // Add keyboard listener to the text fields
           
            oldNameCombo.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    updateUIState();
                    dirtyFields = true;                   
                    newNameField.setText(fromName);
                    if ((statusLabel.getIcon() == ERROR_ICON) && (e.getKeyCode() == KeyEvent.VK_ENTER)) {
                        newNameField.requestFocus();
                    }
                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        dispose();
                    }
                }
            });           
           
            // Create a popup listener that selects the new name field text whenever an item is selected.
            PopupMenuListener popupMenuListener = new PopupMenuListener() {
                public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
                public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                    newNameField.requestFocus();
                    newNameField.selectAll();
                }
                public void popupMenuCanceled(PopupMenuEvent e) {}
            };
            oldNameCombo.addPopupMenuListener(popupMenuListener);
            sourceModuleList.addPopupMenuListener(popupMenuListener);
           
            sourceModuleList.addItemListener(new ItemListener() {
                public void itemStateChanged(ItemEvent e) {
                    moduleName = (ModuleName)sourceModuleList.getSelectedItem();
                    updateFromName();
                    if (entityType == EntityType.Module) {
                        newNameField.setText(fromName);
                    }
                    dirtyFields = true;                   
                    populateOldNameCombo();
                    updateUIState();
                }
            });
            sourceModuleList.addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    if ((statusLabel.getIcon() == ERROR_ICON) && (e.getKeyCode() == KeyEvent.VK_ENTER)) {
                        oldNameCombo.requestFocus();
                    }
                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        dispose();
                    }
                }
            });
        }
       
        // Initialize affected module list component
        informationScrollPane.setVisible(false);
        informationScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
       
        // Make the type name field have default focus
       
        if (fromNameIsPreset) {
            setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
                private static final long serialVersionUID = 5993228846759302688L;

                @Override
                public Component getDefaultComponent(Container c) { return newNameField; }
            });
        } else {
            setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
                private static final long serialVersionUID = -6709077930385639859L;

                @Override
                public Component getDefaultComponent(Container c) { return oldNameCombo; }
            });
        }
       
        // Set the title
       
        String titleText;
        if (automatedMode) {
            titleText = getTitle();
        } else if (fromNameIsPreset) {
            titleText = GemCutterMessages.getString("RNRD_RenamePreset", entityType.toString(), fromName);           
            sourceModuleList.setSelectedItem(moduleName);
            oldNameCombo.setSelectedItem(fromName);
        } else if (entityTypeIsPreset) {
            titleText = GemCutterMessages.getString("RNRD_Rename", entityType.toString());
        } else {
            titleText = GemCutter.getResourceString("RNRD_RenameGem");
        }           
        this.setTitle(titleText);
       
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent evt) {
                if(cancelButton.isEnabled()) {
                    cancelButton.doClick(0);
                }
            }
        });       
        addComponentListener(new ComponentAdapter() {
            // Listener called whenever dialog size changes
            // (eg: due to manual window resized, or setSize call)
            @Override
            public void componentResized(ComponentEvent e) {
                enforceMinimumSize(minimumSize);
                validate();
            }
        });
       
        layoutDialog();
       
        // Temporarily make the progress bar visible so that the
        // dialog box will be properly sized when in automated mode
        if (automatedMode) {
            statusLabel.setText(GemCutter.getResourceString("RNRD_Inspecting"));       
            statusLabel.setIcon(null);
            progressLabel.setVisible(true);           
            progressBar.setVisible(true);
        }
   
        errorsList.setCellRenderer(new RenameListRenderer(ERROR_ICON, false));
       
        setVisibleButtons(new JButton[] {okButton, cancelButton});
        setEnabledButtons(new JButton[] {okButton, cancelButton});
        mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
       
        pack();
        mainPanel.setMinimumSize(mainPanel.getSize());
       
        minimumSize = getSize();
       
        progressBar.setVisible(false);
        progressLabel.setVisible(false);           
       
        setResizable(false);       
       
        // Default button is OK
       
        getRootPane().setDefaultButton(okButton);
       
        updateUIState();
    }
   
    /**
     * Updates the fromName and category fields to reflect the contents of the from name field, if necessary.
     */
    private void updateFromName() {
        if (!fromNameIsPreset) {
            if (entityType == EntityType.Module) {
                fromName = ((ModuleName)sourceModuleList.getSelectedItem()).toSourceText();
            } else {
                fromName = (String) oldNameCombo.getSelectedItem();       
                if (fromName == null) {
                    fromName = "";
                }
            }
        }
       
        if (entityType == EntityType.Gem) {
            if (LanguageInfo.isValidDataConstructorName(fromName)) {
                category = SourceIdentifier.Category.DATA_CONSTRUCTOR;
            } else {
                category = SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD;
            }
        } else if (entityType == EntityType.TypeClass) {
            category = SourceIdentifier.Category.TYPE_CLASS;
        } else if (entityType == EntityType.TypeConstructor) {
            category = SourceIdentifier.Category.TYPE_CONSTRUCTOR;
        } else if (entityType == EntityType.Module) {
            category = SourceIdentifier.Category.MODULE_NAME;
        } else {
            throw new IllegalStateException("Illegal entity type");
        }
    } 
   
    /**
     * @return True if the values in the value entry fields are valid, false otherwise.
     */
    private boolean fieldsAreValid() {
        proposedFactoringUnsafe = false; // Will be set in the checks below if necessary
       
        return !emptyModule && 
            checkValidModule() &&
            checkValidOldName() &&
            checkValidNewName();
    }
   
    /**
     * Checks if the user-enetered module name is valid, and if not, disables the OK buttton and displays an error message.
     * @return True if the user-entered module name is valid (or if the module name field is not applicable), false otherwise.
     */
    private boolean checkValidModule() {
        if (entityType != EntityType.Module) {
            ModuleName selectedModuleName = (ModuleName)sourceModuleList.getSelectedItem();
            if (selectedModuleName.equals(CAL_Prelude.MODULE_NAME) && !allowPreludeRenaming) {
                statusLabel.setText(GemCutter.getResourceString("RNRD_UnmodifiableModule"));
                statusLabel.setIcon(ERROR_ICON);
                okButton.setEnabled(false);
                return false;
            }
        }
        return true;
    }   
  
    /**
     * Checks if the user-entered old name is valid, and if not, disables the OK button and displays an error message.
     * @return True if the user-entered old name is valid, false otherwise.
     */
    private boolean checkValidOldName() {
        if (fromName.length() == 0) {
            statusLabel.setText(GemCutter.getResourceString("RNRD_NameExistingEntity"));
            statusLabel.setIcon(ERROR_ICON);
            okButton.setEnabled(false);
            return false;
        }
       
        ModuleTypeInfo typeInfo = null;
        if (category != SourceIdentifier.Category.MODULE_NAME) {
            typeInfo = perspective.getMetaModule((ModuleName)sourceModuleList.getSelectedItem()).getTypeInfo();
        }
       
        boolean entityExists;
        if (category == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD) {
            entityExists = typeInfo.getFunctionOrClassMethod(fromName) != null;
           
        } else if (category == SourceIdentifier.Category.DATA_CONSTRUCTOR) {
            entityExists = typeInfo.getDataConstructor(fromName) != null;
           
        } else if (category == SourceIdentifier.Category.TYPE_CONSTRUCTOR) {
            entityExists = typeInfo.getTypeConstructor(fromName) != null;
           
        } else if (category == SourceIdentifier.Category.TYPE_CLASS) {
            entityExists = typeInfo.getTypeClass(fromName) != null;
           
        } else if (category == SourceIdentifier.Category.MODULE_NAME) {
            entityExists = (perspective.getMetaModule(ModuleName.make(fromName)) != null);
           
            if (fromName.equals(CAL_Prelude.MODULE_NAME) && !allowPreludeRenaming) {
                statusLabel.setText(GemCutter.getResourceString("RNRD_UnmodifiableModule"));
                statusLabel.setIcon(ERROR_ICON);
                okButton.setEnabled(false);
                return false;
            }
           
        } else {
            throw new IllegalStateException("TODOPC");
        }
        
        if (!entityExists) {
            statusLabel.setText(GemCutter.getResourceString("RNRD_NonexistentEntity"));
            statusLabel.setIcon(ERROR_ICON);
            okButton.setEnabled(false);
            return false;
        }
        return true;
    }

    /**
     * Checks if the user-entered new name is valid, and if not, disables the OK button and displays an error message.
     * @return True if the user-entered new name is valid, false otherwise.
     */
    private boolean checkValidNewName() {
        if (toName.length() == 0) {
            statusLabel.setText(GemCutter.getResourceString("RNRD_SpecifyNewName"));
            statusLabel.setIcon(ERROR_ICON);
            okButton.setEnabled(false);
        }
      
        ModuleTypeInfo typeInfo = null;
        if (category != SourceIdentifier.Category.MODULE_NAME) {
            typeInfo = perspective.getMetaModule((ModuleName)sourceModuleList.getSelectedItem()).getTypeInfo();
        }
       
        boolean entityExists;
        IdentifierUtils.ValidatedIdentifier validatedIdentifier;
        if (category == SourceIdentifier.Category.TYPE_CONSTRUCTOR) {
            validatedIdentifier = IdentifierUtils.makeValidTypeConstructorName(toName);
            entityExists = typeInfo.getTypeConstructor(toName) != null;
        } else if (category == SourceIdentifier.Category.TYPE_CLASS) {
            validatedIdentifier = IdentifierUtils.makeValidTypeClassName(toName);
            entityExists = typeInfo.getTypeClass(toName) != null;
        } else if (category == SourceIdentifier.Category.DATA_CONSTRUCTOR) {
            validatedIdentifier = IdentifierUtils.makeValidDataConstructorName(toName);
            entityExists = typeInfo.getDataConstructor(toName) != null;
        } else if (category == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD) {
            validatedIdentifier = IdentifierUtils.makeValidFunctionName(toName);
            entityExists = typeInfo.getFunctionOrClassMethod(toName) != null;
        } else if (category == SourceIdentifier.Category.MODULE_NAME) {
            validatedIdentifier = IdentifierUtils.makeValidModuleName(toName);
            ModuleName maybeModuleName = ModuleName.maybeMake(toName);
            entityExists = maybeModuleName != null && perspective.getMetaModule(maybeModuleName) != null;
        } else {
            throw new IllegalStateException("Illegal gem type");
        }
       
        if (!validatedIdentifier.isValid()) {
            IdentifierUtils.ValidationStatus error = validatedIdentifier.getNthError(0);
            String errorKey;
            if (error == IdentifierUtils.ValidationStatus.INVALID_CONTENT) {
                errorKey = "RNRD_InvalidName_InvalidContent";               
            } else if (error == IdentifierUtils.ValidationStatus.INVALID_START) {
                errorKey = "RNRD_InvalidName_InvalidStart";
            } else if (error == IdentifierUtils.ValidationStatus.NEED_UPPER) {
                errorKey = "RNRD_InvalidName_NeedUpper";
            } else if (error == IdentifierUtils.ValidationStatus.NEED_LOWER) {
                errorKey = "RNRD_InvalidName_NeedLower";
            } else if (error == IdentifierUtils.ValidationStatus.EXISTING_KEYWORD) {
                errorKey = "RNRD_InvalidName_ExistingKeyword";
            } else if (error == IdentifierUtils.ValidationStatus.WAS_EMPTY) {
                errorKey = "RNRD_InvalidName_WasEmpty";
            } else {
                errorKey = "RNRD_InvalidName_Unknown";
            }
           
            statusLabel.setText(GemCutter.getResourceString(errorKey));
            statusLabel.setIcon(ERROR_ICON);
            okButton.setEnabled(false);
            return false;
        }
       
        if(entityExists && !fromName.equals(toName)) {
            if (allowDuplicateRenaming) {
               proposedFactoringUnsafe = true;
               statusLabel.setText(GemCutter.getResourceString("RNRD_EntityExistsWarning"));
               statusLabel.setIcon(WARNING_ICON);
            } else {
                statusLabel.setText(GemCutter.getResourceString("RNRD_EntityExists"));
                statusLabel.setIcon(ERROR_ICON);
                okButton.setEnabled(false);
                return false;
            }
        }
       
        okButton.setEnabled(true);
        return true;
    }
   
    /**
     * @param moduleName base dependee module
     * @return list of ModuleNames of all module names dependent on the specified module
     */
    private List<ModuleName> findDependentModules(ModuleName moduleName) {
        CALWorkspace workspace = perspective.getWorkspace();
       
        List<MetaModule> allModules = new ArrayList<MetaModule>();
        allModules.addAll(perspective.getInvisibleMetaModules());
        allModules.addAll(perspective.getVisibleMetaModules());
       
        List<ModuleName> dependentModules = new ArrayList<ModuleName>();
        dependentModules.add(moduleName);

        // Find direct dependents on the modules we are looking for
        for (int i = 0; i < dependentModules.size(); i++) {
            ModuleName importedName = dependentModules.get(i);
           
            // Run through all modules and find ones that import this module
            for (final MetaModule m : allModules) {
                if (m.getImportedModule(workspace, importedName) != null) {
                   
                    // This module imports our searched module, so add it to the list
                    if (!dependentModules.contains(m.getName())) {
                        dependentModules.add(m.getName());
                    }
                }
            }
        }
       
        return dependentModules;
    }
   
    /**
     * Initialize refactorer with appropriate resources and renamings as specified by the UI.
     * @return number of modules in refactorer list
     */
    private int initializeRefactorer() {
        List<ModuleName> dependentModules = findDependentModules(moduleName);
        List<ModuleSourceDefinition> dependentModuleSources = new ArrayList<ModuleSourceDefinition>();
        for (final ModuleName moduleName2 : dependentModules) {
            dependentModuleSources.add(getWorkspace().getSourceDefinition(moduleName2));
        }

        QualifiedName qualifiedFromName;
        QualifiedName qualifiedToName;
        if (entityType == EntityType.Module) {
            qualifiedFromName = QualifiedName.make(ModuleName.make(fromName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
            qualifiedToName = QualifiedName.make(ModuleName.make(toName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
        } else {
            qualifiedFromName = QualifiedName.make(moduleName, fromName);
            qualifiedToName = QualifiedName.make(moduleName, toName);
        }
        refactorer = new Refactorer.Rename(workspaceManager.getWorkspace().asModuleContainer(), workspaceManager.getTypeChecker(), qualifiedFromName, qualifiedToName, category);
        return dependentModules.size();
    }
   
    /**
     * Calculates the affected resources and populates the affectedModuleNames list.
     * @return True if the operation completed successfully
     */
    private boolean calcResources() {
        CompilerMessageLogger logger = new MessageLogger();

        if (affectedModuleNames == null) {
            affectedModuleNames = new ArrayList<ModuleName>();
        } else {
            affectedModuleNames.clear();
        }
        List<ModuleSourceDefinition> affectedResources = refactorer.calculateModifications(logger);
       
        if (logger.getNErrors() == 0) {
            for (final ModuleSourceDefinition module : affectedResources) {
                affectedModuleNames.add(module.getModuleName());
            }
        }
       
        return !setErrorStatus(logger);
    }
   
    /**
     * Updates the contents of the source files to reflect the renaming.
     * @return True if the operation completed successfully, false otherwise.
     */
    private boolean updateSourcesMetadataAndResources() {
        CompilerMessageLogger logger = new MessageLogger();
       
        // Tie the progress bar to show refactorer progress on resources
       
        Refactorer.StatusListener refactoringStatusListener = new Refactorer.StatusListener() {
            public void willUseResource(ModuleSourceDefinition resource) {}
            public void doneUsingResource(ModuleSourceDefinition resource) {
                incrementProgressBar();
            }
        };
        refactorer.setStatusListener(refactoringStatusListener);
        refactorer.apply(logger);
        refactorer.setStatusListener(null);
       
        return !setErrorStatus(logger);       
    }
   
    /**
     * Undo the updateSources() operation. This should be used if another operation later on in the refactoring sequence fails.
     */
    private void undoSourcesMetadataAndResources() {
        CompilerMessageLogger logger = new MessageLogger();
        Refactorer.StatusListener refactoringStatusListener = new Refactorer.StatusListener() {
            public void willUseResource(ModuleSourceDefinition resource) {}
            public void doneUsingResource(ModuleSourceDefinition resource) {
                incrementProgressBar();
            }
        };
        refactorer.setStatusListener(refactoringStatusListener);
        refactorer.undo(logger);
        refactorer.setStatusListener(null);
       
        if (logger.getNErrors() > 0) {
            DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
            listModel.addElement(GemCutterMessages.getString("RNRD_ErrorUndoingSourceUpdate"));
        }
    }

    /**
     * Updates the contents of the design files to reflect the renaming.
     * @return True if the operation completed successfully, false otherwise.
     */
    private boolean updateDesigns() {
        QualifiedName qualifiedFromName;
        QualifiedName qualifiedToName;
        if (entityType == EntityType.Module) {
            qualifiedFromName = QualifiedName.make(ModuleName.make(fromName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
            qualifiedToName = QualifiedName.make(ModuleName.make(toName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
        } else {
            qualifiedFromName = QualifiedName.make(moduleName, fromName);
            qualifiedToName = QualifiedName.make(moduleName, toName);
        }
       
        Status updateDesignStatus = new Status("Update design status");
        GemCutterRenameUpdater designRenamer = new GemCutterRenameUpdater(updateDesignStatus, workspaceManager.getTypeChecker(), qualifiedToName, qualifiedFromName, category);
        designRenamer.updateDesigns(workspaceManager);
       
        return !setErrorStatus(updateDesignStatus);
    }
   
    /**
     * Undo the updateDesigns() operation. This should be used if another operation later on in the refactoring sequence fails.
     */
    private void undoUpdateDesigns() {
        QualifiedName qualifiedFromName; // initialized with "to" name (because this is undo)
        QualifiedName qualifiedToName; // initialized with "from" name (because this is undo)
        if (entityType == EntityType.Module) {
            qualifiedFromName = QualifiedName.make(ModuleName.make(toName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
            qualifiedToName = QualifiedName.make(ModuleName.make(fromName), Refactorer.Rename.UNQUALIFIED_NAME_FOR_MODULE_RENAMING);
        } else {
            qualifiedFromName = QualifiedName.make(moduleName, toName);
            qualifiedToName = QualifiedName.make(moduleName, fromName);
        }
       
        Status updateDesignStatus = new Status("Update design status");
        GemCutterRenameUpdater designRenamer = new GemCutterRenameUpdater(updateDesignStatus, workspaceManager.getTypeChecker(), qualifiedToName, qualifiedFromName, category);
        designRenamer.updateDesigns(workspaceManager);
       
        if (updateDesignStatus.getSeverity().compareTo(Status.Severity.ERROR) >= 0) {
            DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
            listModel.addElement(GemCutterMessages.getString("RNRD_ErrorUndoingDesignUpdating"));
        }
    }
   
    /**
     * @return The set of sources that are dependent on the "affected" (ie. changed) sources.
     */
    private Set<ModuleSourceDefinition> calculateDependentSources() {
        Set<ModuleSourceDefinition> dependentModules = new HashSet<ModuleSourceDefinition>();
       
        for (int i = 0, n = affectedModuleNames.size(); i < n; i++) {
            ModuleName moduleName = affectedModuleNames.get(i);
           
            for (final ModuleName dependentModuleName : workspaceManager.getDependentModuleNames(moduleName)) {
                dependentModules.add(getWorkspace().getSourceDefinition(dependentModuleName));
            }
            dependentModules.add(getWorkspace().getSourceDefinition(moduleName));
        }
       
        return dependentModules;
    }
   
    /**
     * Update the list of affected modules to reflect the renaming.
     */
    private void updateAffectedModules() {
        if (entityType == EntityType.Module) {
            final ModuleName fromNameAsModuleName = ModuleName.make(fromName);
            final ModuleName toNameAsModuleName = ModuleName.make(toName);
           
            for (int i = 0, n = affectedModuleNames.size(); i < n; i++) {
                ModuleName moduleName = affectedModuleNames.get(i);
                if (moduleName.equals(fromNameAsModuleName)) {
                    affectedModuleNames.remove(i);
                    affectedModuleNames.add(i, toNameAsModuleName);
                }
            }
        }
    }

    /**
     * Recompiles the changed modules in the workspace.
     * @return True if the operation completed successfully, false otherwise.
     */
    private boolean recompile() {
        CompilerMessageLogger logger = new MessageLogger();
        StatusListener recompileStatusListener = new StatusListener.StatusListenerAdapter() {
            @Override
            public void setModuleStatus(StatusListener.Status.Module moduleStatus, ModuleName moduleName) {
                if (moduleStatus == StatusListener.SM_LOADED) {
                    incrementProgressBar();
                }
            }
        };
        workspaceManager.addStatusListener(recompileStatusListener);       
       
        Set<ModuleSourceDefinition> dependentSources = calculateDependentSources();
        ModuleName[] moduleNames = affectedModuleNames.toArray(new ModuleName[0]);
        ModuleSourceDefinition[] moduleSourceDefintionArray = dependentSources.toArray(new ModuleSourceDefinition[0]);
        ModuleSourceDefinitionGroup sourceDefinitionGroup = new ModuleSourceDefinitionGroup(moduleSourceDefintionArray);
        workspaceManager.makeModules(moduleNames, sourceDefinitionGroup, logger);
        workspaceManager.removeStatusListener(recompileStatusListener);
       
        return !setErrorStatus(logger);
    }
   
    /**
     * Get the number of metadata files in the resource manager.
     * The value lazily calculated the first time this method is called, and then a cached value is used
     * every time thereafter.
     * @return The number of metadata files in the resource manager.
     */
    private int getMetadataCount() {
        if (metadataCount == -1) {
            metadataCount = 0;
            ModuleName[] workspaceModuleNames = getWorkspace().getModuleNames();
           
            // loop through each module in the workspace
            for (final ModuleName moduleName : workspaceModuleNames) {
               
                ResourceStore.Module resourceStore = (ResourceStore.Module)getWorkspace().getResourceManager(moduleName, WorkspaceResource.METADATA_RESOURCE_TYPE).getResourceStore();
               
                Iterator<WorkspaceResource> it = resourceStore.getResourceIterator(moduleName);
                while (it.hasNext()) {
                    metadataCount++;
                    it.next();
                }
            }
        }
       
        return metadataCount;
    }
    private int metadataCount = -1;
      
    /**
     * Perform the rename operation and recompile the workspace. If errors are encountered, attempt to undo any changes
     * that have been made so far and then display the errors in the error list pane.
     * @return True if the refactorings were successful, false otherwise
     */
    private boolean doRefactorings() {
       
        try {
           
           // Perform refactorings
          
           lockValueEntry();
           setEnabledButtons(new JButton[]{}); // Disable all buttons
           enterProgressMode();
           clearErrorStatus();
           informationScrollPane.setVisible(false);
           pack();
           initializeRefactorer();
          
          
           statusLabel.setText(GemCutter.getResourceString("RNRD_CalculatingAffectedResources"));
           statusLabel.setIcon(null);
          
           if (!calcResources()) {
            return false;
        }
          
           // Now that we know how many resources there are, we can set the maximum value for the progress bar.
           // There should be two steps for each affected module (one for the updating, one for the recompilation),
           // plus one for design updating and one for the calcResources step we just completed.
           progressBar.setMaximum(affectedModuleNames.size() + calculateDependentSources().size() + getMetadataCount() + 2);
          
           // Set the value to one since we've already completed one step at this point.
           progressBar.setValue(1);
          
           statusLabel.setText(GemCutter.getResourceString("RNRD_UpdatingSourceFiles"));
           statusLabel.setIcon(null);
           if (!updateSourcesMetadataAndResources()) {
            return false;
        }
          
           statusLabel.setText(GemCutter.getResourceString("RNRD_UpdatingDesigns"));
           statusLabel.setIcon(null);
           if (!updateDesigns()) {
               statusLabel.setText(GemCutter.getResourceString("RNRD_BackingOut"));
               statusLabel.setIcon(ERROR_ICON);
               progressBar.setMaximum(affectedModuleNames.size());
               progressBar.setValue(0);
              
               undoSourcesMetadataAndResources();
               return false;
           }
           incrementProgressBar();
          
           updateAffectedModules();
          
           // If we are allowing duplicate renamings, give the user a chance to fix the errors that will have been introduced
           if (proposedFactoringUnsafe) {
               JOptionPane.showMessageDialog(getParent(), GemCutter.getResourceString("RNRD_ManualFixPrompt"), GemCutter.getResourceString("RNRD_ManualFixPromptTitle"), JOptionPane.PLAIN_MESSAGE);
           }
          
           statusLabel.setText(GemCutter.getResourceString("RNRD_Recompiling"));
           statusLabel.setIcon(null);
           if(!recompile()) {
               statusLabel.setText(GemCutter.getResourceString("RNRD_BackingOut"));
               statusLabel.setIcon(ERROR_ICON);
               enterProgressMode();
               progressBar.setMaximum(affectedModuleNames.size() + calculateDependentSources().size() + 3);
              
               undoUpdateDesigns();
               incrementProgressBar();
               undoSourcesMetadataAndResources();
               recompile();
               return false;
           }
          
           statusLabel.setText(GemCutter.getResourceString("RNRD_RefactoringComplete"));
           statusLabel.setIcon(OK_ICON);    
          
           refactorSuccessful = true;
          
           return true;

        } catch (Exception e) {
            DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
            listModel.addElement(GemCutterMessages.getString("RNRD_ExceptionThrown"));
            informationScrollPane.setVisible(true);
            pack();
            System.out.println(e.toString());
            return false;
        }
    }
   
    /**
     * Item renderer for the combo box list used to choose a gem name. Displays names and appropriate icons.
     *
     * @author Peter Cardwell
     */
    private static class NameComboListRenderer extends JLabel implements ListCellRenderer {
       
        private static final long serialVersionUID = 561510951582323314L;
        private ModuleTypeInfo typeInfo;
        private EntityType entityType;
       
        /**
         * Constructor
         * @param typeInfo
         * @param entityType
         */
        public NameComboListRenderer(ModuleTypeInfo typeInfo, EntityType entityType) {
            this.typeInfo = typeInfo;
            this.entityType = entityType;
            setOpaque(true);
        }
       
        public void setTypeInfo(ModuleTypeInfo typeInfo) {
            this.typeInfo = typeInfo;
        }
       
        public void setEntityType(EntityType entityType) {
            this.entityType = entityType;
        }
       
        /**
         * This method finds the image and text corresponding
         * to the selected value and returns the label, set up
         * to display the text and image.
         */
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
           
            if (isSelected) {
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }
           
            String text = (String)value;
           
            Icon icon = null;
            if (entityType == EntityType.Gem) {
                if (typeInfo.getFunctionOrClassMethod(text) != null) {
                    icon = FUNCTION_ICON;
                } else if (typeInfo.getDataConstructor(text) != null) {
                    icon = DATACONS_ICON;
                }
            } else if (entityType == EntityType.TypeClass) {
                icon = TYPECLASS_ICON;
            } else if (entityType == EntityType.TypeConstructor) {
                icon = TYPECONS_ICON;
            }
            setIcon(icon);
            setText(text);
            setFont(list.getFont());
           
            return this;
        }
    }
   
    /**
     * Populates the old name combo box with entities of the relevant type from the current module.
     */
    private void populateOldNameCombo() {
        List<String> entityList = new ArrayList<String>();
        MetaModule module = perspective.getMetaModule((ModuleName)sourceModuleList.getSelectedItem());
        String emptyModuleComboStr = "";    // The string that will be displayed in the name combo box if the module is empty
        String emptyModuleStatusStr = "";   // The string that will be displayed in the status text if the module is empty
       
        if( entityType == EntityType.Gem ) {
           
            for (int i = 0, n = module.getNGemEntities(); i < n; i++) {
                GemEntity entity = module.getNthGemEntity(i);           
                entityList.add(entity.getName().getUnqualifiedName());
            }
            emptyModuleComboStr = GemCutter.getResourceString("RNRD_EmptyModuleComboGem");
            emptyModuleStatusStr = GemCutter.getResourceString("RNRD_EmptyModuleStatusGem");
           
        } else if ( entityType == EntityType.TypeConstructor ) {
           
            TypeConstructor[] typeConstructors = module.getTypeConstructors();
            for (final TypeConstructor typeCons : typeConstructors) {
                if(typeCons.getName().getModuleName().equals(module.getName())) {
                    entityList.add(typeCons.getName().getUnqualifiedName());
                }
            }
            emptyModuleComboStr = GemCutter.getResourceString("RNRD_EmptyModuleComboTypeCons");
            emptyModuleStatusStr = GemCutter.getResourceString("RNRD_EmptyModuleStatusTypeCons");
           
        } else if ( entityType == EntityType.TypeClass ) {
           
            for (int i = 0, n = module.getTypeInfo().getNTypeClasses(); i < n; i++) {
                TypeClass typeClass = module.getTypeInfo().getNthTypeClass(i);
                if(typeClass.getName().getModuleName().equals(module.getName())) {
                    entityList.add(typeClass.getName().getUnqualifiedName());
                }
            }
            emptyModuleComboStr = GemCutter.getResourceString("RNRD_EmptyModuleComboTypeClass");
            emptyModuleStatusStr = GemCutter.getResourceString("RNRD_EmptyModuleStatusTypeClass");
        }
        Collections.sort(entityList);
        ((DefaultComboBoxModel)oldNameCombo.getModel()).removeAllElements();
        for (int i = 0, n = entityList.size(); i < n; i++) {
            ((DefaultComboBoxModel)oldNameCombo.getModel()).addElement(entityList.get(i));
        }
        if (entityType != EntityType.Module) {
            if (oldNameCombo.getItemCount() > 0) {
                oldNameCombo.setSelectedIndex(0);
                oldNameCombo.setEnabled(true);
                newNameField.setEnabled(true);
                emptyModule = false;           
            } else {
                oldNameCombo.setEnabled(false);
                newNameField.setEnabled(false);
                ((DefaultComboBoxModel)oldNameCombo.getModel()).addElement (emptyModuleComboStr);
                newNameField.setText("");
                statusLabel.setText(emptyModuleStatusStr);
                statusLabel.setIcon(ERROR_ICON);
                emptyModule = true;
            }
            NameComboListRenderer renderer = (NameComboListRenderer)oldNameCombo.getRenderer();
       
            renderer.setTypeInfo(perspective.getMetaModule((ModuleName)sourceModuleList.getSelectedItem()).getTypeInfo());
            renderer.setEntityType(entityType);
        }
    }

    /**
     * Displays the dialog, and waits for it to disappear.
     * @return The result of the operation, or null if no refactoring occurred
     */
    public Result display() {
        initialize();
        super.setVisible(true);
        if(refactorSuccessful) {
            if (entityType == EntityType.Module) {
                return new Result(fromName, toName, category);
            } else {
                QualifiedName qualifiedFromName = QualifiedName.make(moduleName, fromName);
                QualifiedName qualifiedToName = QualifiedName.make(moduleName, toName);
                return new Result(qualifiedFromName.getQualifiedName(), qualifiedToName.getQualifiedName(), category);
            }
        } else {
            return null;
        }
    }

    /**
     * If the window is smaller then its minimum size then the
     * size is set to the minimum size.
     *
     * @return true if minimum dialog size has been enforced; false if not
     */
    private boolean enforceMinimumSize(Dimension minSize) {
   
        boolean wasBadSize = false;
        Dimension size = getSize();
       
        if (size.height < minSize.height) {
            size.height = minSize.height;
            wasBadSize = true;
        }
       
        if (!informationScrollPane.isVisible() && size.height > minSize.height) {
            size.height = minSize.height;
            wasBadSize = true;
        }
       
        if (size.width  < minSize.width) {
            size.width = minSize.width;
            wasBadSize = true;
        }
       
        setSize(size);
        return wasBadSize;
    }

    /**
     * @return The action associated with the back button (which unlocks the value entry boxes and re-enables the ok and cancel buttons).
     */
    private Action getBackAction() {
        if (backAction == null) {
            backAction = new AbstractAction(GemCutter.getResourceString("RNRD_Back")) {
               
                private static final long serialVersionUID = -6520848746650896219L;

                public void actionPerformed(ActionEvent evt) {
                    informationScrollPane.setVisible(false);
                    setVisibleButtons(new JButton[] {okButton, cancelButton});
                    setEnabledButtons(new JButton[] {okButton, cancelButton});
                    unlockValueEntry();
                    updateUIState();
                    pack();
                }
            };
        }

        return backAction;
    }
   
    /**
     * @return The action associated with the retry button, which does the same thing as the OK button.
     */
    private Action getRetryAction() {
        if (retryAction == null) {
            retryAction = new AbstractAction(GemCutter.getResourceString("RNRD_Retry")) {
               
                private static final long serialVersionUID = -4987680767287672031L;

                public void actionPerformed(ActionEvent evt) {
                    getOkAction().actionPerformed(evt);
                }
            };
        }
       
        return retryAction;
    }
   
    /**
     * @return The action associated with the OK button, which creates a refactoring thread and runs it.
     */
    private Action getOkAction() {
        if (okAction == null) {
            okAction = new AbstractAction(GemCutter.getResourceString("RNRD_OK")) {
                                                       
                private static final long serialVersionUID = 1157482755328668668L;

                public void actionPerformed(ActionEvent evt) {
                   
                    if (!fieldsAreValid()) {
                        return;
                    }
               
                    if (fromName.equals(toName)) {
                        // Nothing to do, so exit
                        dispose();
                    }
                   
                    if (dirtyFields) {
   
                        statusLabel.setText(GemCutter.getResourceString("RNRD_Inspecting"));
                        statusLabel.setIcon(null);
                        if ((refactoringThread == null) || (!refactoringThread.isAlive())) {
                            refactoringThread = new RefactoringThread();
                            refactoringThread.start();
                        } else {
                            throw new IllegalStateException("Tried to start new refactoring thread while another was running.");
                        }
                       
                    } else {
                       
                        if ((refactoringThread == null) || (!refactoringThread.isAlive())) {
                            refactoringThread = new RefactoringThread();
                            refactoringThread.start();
                        } else {
                            throw new IllegalStateException("Tried to start new refactoring thread while another was running.");
                        }
                    }
                }
            };
        }
       
        return okAction;
    }

    /**
     * @return The action associated with the cancel button, which closes the dialog as long as a refactoring is not occurring.
     */
    private Action getCancelAction() {
        if (cancelAction == null) {
            cancelAction = new AbstractAction(GemCutter.getResourceString("RNRD_Cancel")) {
                                                       
                private static final long serialVersionUID = 1531004724388023830L;

                synchronized public void actionPerformed(ActionEvent evt) {
                  
                    if ((refactoringThread != null) && (refactoringThread.isAlive())) {
                        throw new IllegalStateException("Cancel action occurred while refactoring was still in progress");
                    }
                    dispose();
                }
            };
        }
       
        return cancelAction;
    }

    /**
     * Ensures that all the elements of the given array are enabled, and that ONLY the elements
     * of the given array are enabled. That is, if a button is a member of dialogButtons but not
     * a member of enabledButtons, it will be disabled.
     * @param enabledButtons  The array of buttons to be enabled. Each element of this array should
     * also be an element of dialogButtons.
     */
    private void setEnabledButtons(JButton[] enabledButtons) {
        Set<JButton> enabledButtonSet = new HashSet<JButton>(Arrays.asList(enabledButtons));
       
        for (final JButton btn : dialogButtons) {
            // For each dialog button b, set b to be enabled if and only if enabledButtonSet contains b.
            btn.setEnabled (enabledButtonSet.contains(btn));
        }
       
    }

    /**
     * Ensures that all the elements of the given array are made visible, and that ONLY the elements
     * of the given array are visible. That is, if a button is a member of dialogButtons but not
     * a member of visibleButtons, it will be made invisible.
     * @param visibleButtons The array of buttons to be made visible. Each element of this array should
     * also be an element of dialogButtons.
     */
    private void setVisibleButtons(JButton[] visibleButtons) {
        Set<JButton> visibleButtonSet = new HashSet<JButton>(Arrays.asList(visibleButtons));
       
        for (final JButton btn : dialogButtons) {
            // For each dialog button b, set b to be visible if and only if visibleButtonSet contains b.
            btn.setVisible (visibleButtonSet.contains(btn));
        }
    }

    /** Set all the components returned by getValueEntryComponents() to be disabled. */
    private void lockValueEntry() {
        for (final Component valueEntryComp : valueEntryComponents) {
            valueEntryComp.setEnabled(false);
        }
    }

    /** Set all the components returned by getValueEntryComponents() to be enabled. */
    private void unlockValueEntry() {
        for (final Component valueEntryComp : valueEntryComponents) {
            valueEntryComp.setEnabled(true);
        }
    }

    /** Actions to perform by the refactoring worker thread when it completes */
    private void exitProgressMode() {
        progressBar.setValue(0);
        progressLabel.setVisible(false);
        progressBar.setVisible(false);
    }

    /** Lock the user interface and make the progress bar visible */
    private void enterProgressMode() {
        progressBar.setValue(0);
        progressLabel.setVisible(true);
        progressBar.setVisible(true);
    }
   
    /** Adds one to the value of the progress bar and repaints the dialog. */
    private void incrementProgressBar() {
        progressBar.setValue(progressBar.getValue() + 1);
        RenameRefactoringDialog.this.repaint();
    }

    /** Perform validation on the entry fields and set the status to OK if there are no problems. */
    private void updateUIState() {
       
        if (!fieldsAreValid()) {           
            return;
        }
       
        if (!proposedFactoringUnsafe) {
            // Clear errors and warnings from previous checks
            statusLabel.setText(GemCutter.getResourceString("RNRD_OkMessage"));
            statusLabel.setIcon(null);
        }
    }
   
    /** Clears the error list. */
    private void clearErrorStatus() {
        DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
        listModel.clear();
    }
    
    /**
     * If the given status object contains errors, display them in the error list and return true.
     * @param status The Status object to check for errors
     * @return True of the Status object contained errors, false otherwise.
     */
    private boolean setErrorStatus(Status status) {
        if (status.getSeverity().compareTo(Status.Severity.ERROR) < 0) {
            return false;
        }
       
        DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
        Status[] msgs = status.getChildren();
        for (int i = 0; i < msgs.length; ++i) {
            listModel.addElement(msgs[i].getMessage());
        }
       
        informationScrollPane.setVisible(true);
       
        setSize(getPreferredSize());
       
        return true;
    }

    /**
     * If the given logger contains errors, display them in the informationScrollPane and return true.
     * @param logger The logger to check for errors.  Cannot be null.
     * @return True if there were errors, false otherwise
     */
    private boolean setErrorStatus(CompilerMessageLogger logger) {
       
        if(logger.getNErrors() == 0) {
            return false;
        }
       
        List<CompilerMessage> messages = logger.getCompilerMessages();
   
        DefaultListModel listModel = (DefaultListModel) errorsList.getModel();
        for (int i = 0, n = messages.size(); i < n; i++) {
            CompilerMessage message = messages.get(i);
            if(message.getSeverity().compareTo(CompilerMessage.Severity.ERROR) < 0) {
                continue;
            }
            if (message.getException() instanceof CALRefactoringException) {
                CALRefactoringException refactoringException = (CALRefactoringException) message.getException();
                listModel.addElement(refactoringException.getDescription());
            } else {
                listModel.addElement(message.getMessage());
            }
        }
       
        informationScrollPane.setVisible(true);
        setSize(getPreferredSize());
       
        return true;
    }

    /**
     * @return the CALWorkspace on which the refactorer operates.
     */
    private CALWorkspace getWorkspace() {
        return perspective.getWorkspace();
    }
   
    /**
     * Implement this if we want to put an image in the top right corner of the dialog.
     * @return The image that should be displayed, or null if nothing should be displayed.
     */
    private ImageIcon getDialogIcon() {
        return null;
    }
   
    /**
     * @return the white title panel that appears at the top of the dialog
     */
    private JPanel getTitlePanel() {
       
        JPanel titlePanel = new JPanel();
        titlePanel.setBackground(Color.WHITE);
       
        Border compoundBorder = BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(),
                                                                   BorderFactory.createEmptyBorder(5, 5, 5, 5));
        titlePanel.setBorder(compoundBorder);
        titlePanel.setLayout(new BorderLayout(5, 5));
       
        JPanel mainTitlePanel = new JPanel();
        mainTitlePanel.setBackground(Color.WHITE);
        mainTitlePanel.setLayout(new BorderLayout(5, 5));
        titlePanel.add(mainTitlePanel, BorderLayout.NORTH);
       
        // Add the title
        titleLabel.setFont(getFont().deriveFont(Font.BOLD, getFont().getSize() + 2));
        mainTitlePanel.add(titleLabel, BorderLayout.WEST);
       
        // Add the icon in the top right corner
        mainTitlePanel.add(new JLabel(getDialogIcon()), BorderLayout.EAST);
       
        // Add the status text
        titlePanel.add(statusLabel, BorderLayout.SOUTH);
       
        return titlePanel;
    }
   
    /**
     * @return the main panel
     */
    private JPanel getMainPanel() {
        if (mainPanel == null) {
            mainPanel = new JPanel();
            getContentPane().add(mainPanel);
            mainPanel.setLayout(new GridBagLayout());
           
            int gy = -1;
           
            if (!entityTypeIsPreset) {
                gy++;
                JPanel radioPanel = getEntityTypeSelectPanel();
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 4;
                constraints.weightx = 1.0;
                constraints.weighty = 0.0;
                constraints.fill = GridBagConstraints.HORIZONTAL;
                constraints.insets = new Insets(0,5,2,2);
                mainPanel.add(radioPanel, constraints);
            }         
                  
            if(!automatedMode) {
                gy++;
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 5;
                constraints.weightx = 0.0;
                constraints.weighty = 0.0;
                constraints.fill = GridBagConstraints.HORIZONTAL;
                constraints.insets = new Insets(0,5,2,5);
                mainPanel.add(getValueEntryPanel(), constraints);           
            }     
           
            {
                gy++;
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 5;
                constraints.weightx = 1.0;
                constraints.weighty = 1.0;
                constraints.insets = new Insets(5,5,5,5);
                constraints.fill = GridBagConstraints.BOTH;
                mainPanel.add(informationScrollPane, constraints);
            }
   
            {
                gy++;
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 1;
                constraints.weightx = 0.0;
                constraints.weighty = 0.0;
                constraints.fill = GridBagConstraints.HORIZONTAL;
                constraints.insets = new Insets(5,5,5,5);
                mainPanel.add(progressLabel, constraints);
            }
           
            {
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 1;
                constraints.gridy = gy;
                constraints.gridwidth = 4;
                constraints.weightx = 0.0;
                constraints.weighty = 0.0;
                constraints.fill = GridBagConstraints.HORIZONTAL;
                constraints.insets = new Insets(5,5,5,5);
                mainPanel.add(progressBar, constraints);
            }
           
            {
                gy++;
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 5;
                constraints.weightx = 1.0;
                constraints.weighty = 1.0;
                constraints.fill = GridBagConstraints.VERTICAL;
                mainPanel.add(new JLabel(""), constraints);
            }
           
            mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        }
        return mainPanel;
    }
   
    /**
     *  Returns a JPanel containing a radio button group for selecting the entity type, a drop down list for selecting the module name,
     *  a combo box for selecting the "from" name, and a text box for entering the "to" name. Note that all but the "to" name field are
     *  not visible if the from name value is preset.
     */
    private JPanel getValueEntryPanel() {
       
        JPanel fromFieldPanel = new JPanel();
        fromFieldPanel.setLayout(new GridBagLayout());
       
        int gy = 0;
        if (!fromNameIsPreset) {
            {
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 0;
                constraints.gridy = gy;
                constraints.gridwidth = 1;
                constraints.weightx = 0.0;
                constraints.weighty = 0.0;
                constraints.fill = GridBagConstraints.HORIZONTAL;
                constraints.insets = new Insets(2,5,2,5);
                fromFieldPanel.add(sourceModuleLabel, constraints);
            }
           
            {
                GridBagConstraints constraints = new GridBagConstraints();
                constraints.gridx = 1;
                constraints.gridy = gy;
                constraints.gridwidth = 4;
                constraints.weightx = 0.0;
                constraints.weighty = 0.0;
                constraints.insets = new Insets(2,5,2,5);
                constraints.fill = GridBagConstraints.HORIZONTAL;
                fromFieldPanel.add(sourceModuleList, constraints);
            }
           
            if (entityType != EntityType.Module) {
                gy++;
                {
                    GridBagConstraints constraints = new GridBagConstraints();
                    constraints.gridx = 0;
                    constraints.gridy = gy;
                    constraints.gridwidth = 1;
                    constraints.weightx = 0.0;
                    constraints.weighty = 0.0;
                    constraints.insets = new Insets(5,5,5,5);
                    constraints.fill = GridBagConstraints.HORIZONTAL;
                    fromFieldPanel.add(oldNameLabel, constraints);
                }
               
                {
                    GridBagConstraints constraints = new GridBagConstraints();
                    constraints.gridx = 1;
                    constraints.gridy = gy;
                    constraints.gridwidth = 4;
                    constraints.weightx = 1.0;
                    constraints.weighty = 0.0;
                    constraints.insets = new Insets(5,5,5,5);
                    constraints.fill = GridBagConstraints.HORIZONTAL;
                    fromFieldPanel.add(oldNameCombo, constraints);
                }
            }
        }
       
        gy++;
        {
            GridBagConstraints constraints = new GridBagConstraints();
            constraints.gridx = 0;
            constraints.gridy = gy;
            constraints.gridwidth = 1;
            constraints.weightx = 0.0;
            constraints.weighty = 0.0;
            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.insets = new Insets(5,5,5,5);
            fromFieldPanel.add(newNameLabel, constraints);
        }
       
        {
            GridBagConstraints constraints = new GridBagConstraints();
            constraints.gridx = 1;
            constraints.gridy = gy;
            constraints.gridwidth = 4;
            constraints.weightx = 1.0;
            constraints.weighty = 0.0;
            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.insets = new Insets(5,5,5,5);
            Dimension minSize = newNameField.getMinimumSize();
            minSize.width = 250;
            newNameField.setPreferredSize(minSize);
            fromFieldPanel.add(newNameField, constraints);
        }
       
        return fromFieldPanel;
    }
   
    /**
     * {@inheritDoc}
     */
    @Override
    public void setTitle(String title) {
        super.setTitle(title);
        this.titleLabel.setText(title);
    }
   
  
    /**
     * Lay out the components in the dialog. This method should only be called once from the initialize method.
     */
    private void layoutDialog() {
       
        // Add components to the dialog
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(getTitlePanel(), BorderLayout.NORTH);
        getContentPane().add(getMainPanel(), BorderLayout.CENTER);
        if (!automatedMode) {
            getContentPane().add(getButtonPanel(), BorderLayout.SOUTH);
        }
       
    }
}
TOP

Related Classes of org.openquark.gems.client.RenameRefactoringDialog$NameComboListRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.