com.intellij.ide.util.projectWizard.NamePathComponent.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.ide.util.projectWizard.NamePathComponent.java

Source

/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.ide.util.projectWizard;

import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.BrowseFilesListener;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.FieldPanel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;

/**
 * @author Eugene Zhuravlev
 *         Date: Dec 30, 2003
 */
public class NamePathComponent extends JPanel {
    private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.projectWizard.NamePathComponent");

    private JTextField myTfName;
    private JTextField myTfPath;
    private boolean myIsNameChangedByUser = false;
    private boolean myIsPathChangedByUser = false;
    private boolean myIsPathNameSyncEnabled = true;
    private boolean myIsNamePathSyncEnabled = true;
    private boolean myIsSyncEnabled = true;

    private FieldPanel myPathPanel;
    private JLabel myNameLabel;
    private JLabel myPathLabel;
    private boolean myForceSync;

    public NamePathComponent(String nameLabelText, String pathLabelText, char nameMnemonic, char locationMnemonic,
            final String pathChooserTitle, final String pathChooserDescription) {
        this(nameLabelText, pathLabelText, pathChooserTitle, pathChooserDescription, true);
    }

    public NamePathComponent(String nameLabelText, String pathLabelText, final String pathChooserTitle,
            final String pathChooserDescription, boolean hideIgnored) {
        this(nameLabelText, pathLabelText, pathChooserTitle, pathChooserDescription, hideIgnored, true);
    }

    public NamePathComponent(String nameLabelText, String pathLabelText, final String pathChooserTitle,
            final String pathChooserDescription, boolean hideIgnored, boolean bold) {
        super(new GridBagLayout());

        myTfName = new JTextField();
        myTfName.setDocument(new NameFieldDocument());
        myTfName.setPreferredSize(new Dimension(200, myTfName.getPreferredSize().height));

        myTfPath = new JTextField();
        myTfPath.setDocument(new PathFieldDocument());
        myTfPath.setPreferredSize(new Dimension(200, myTfPath.getPreferredSize().height));

        myNameLabel = new JLabel(nameLabelText);
        if (bold)
            myNameLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD));
        myNameLabel.setLabelFor(myTfName);
        Insets insets = new Insets(0, 0, 5, 4);
        this.add(myNameLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0));

        insets = new Insets(0, 0, 5, 0);
        this.add(myTfName, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
                GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, insets, 0, 0));
        // todo: review texts
        final FileChooserDescriptor chooserDescriptor = (FileChooserDescriptor) BrowseFilesListener.SINGLE_DIRECTORY_DESCRIPTOR
                .clone();
        chooserDescriptor.setHideIgnored(hideIgnored);
        final BrowseFilesListener browseButtonActionListener = new BrowseFilesListener(myTfPath, pathChooserTitle,
                pathChooserDescription, chooserDescriptor) {
            @Override
            public void actionPerformed(ActionEvent e) {
                super.actionPerformed(e);
                myIsPathChangedByUser = true;
            }
        };
        myPathPanel = new FieldPanel(myTfPath, null, null, browseButtonActionListener, null);
        myPathLabel = new JLabel(pathLabelText);
        myPathLabel.setLabelFor(myTfPath);
        if (bold)
            myPathLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD));
        insets = new Insets(0, 0, 5, 4);
        this.add(myPathLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0));
        insets = new Insets(0, 0, 5, 0);
        this.add(myPathPanel, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
                GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, insets, 0, 0));
    }

    public boolean validateNameAndPath(WizardContext context) throws ConfigurationException {
        final String name = getNameValue();
        if (name.length() == 0) {
            final ApplicationInfo info = ApplicationManager.getApplication().getComponent(ApplicationInfo.class);
            throw new ConfigurationException(IdeBundle.message("prompt.new.project.file.name",
                    info.getVersionName(), context.getPresentationName()));
        }

        final String projectFileDirectory = getPath();
        if (projectFileDirectory.length() == 0) {
            throw new ConfigurationException(
                    IdeBundle.message("prompt.enter.project.file.location", context.getPresentationName()));
        }

        final boolean shouldPromptCreation = isPathChangedByUser();
        if (!ProjectWizardUtil.createDirectoryIfNotExists(
                IdeBundle.message("directory.project.file.directory", context.getPresentationName()),
                projectFileDirectory, shouldPromptCreation)) {
            return false;
        }

        final File file = new File(projectFileDirectory);
        if (file.exists() && !file.canWrite()) {
            throw new ConfigurationException(
                    String.format("Directory '%s' is not writable!\nPlease choose another project location.",
                            projectFileDirectory));
        }

        boolean shouldContinue = true;
        final File projectDir = new File(getPath(), Project.DIRECTORY_STORE_FOLDER);
        if (projectDir.exists()) {
            int answer = Messages.showYesNoDialog(
                    IdeBundle.message("prompt.overwrite.project.folder", projectDir.getAbsolutePath(),
                            context.getPresentationName()),
                    IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
            shouldContinue = (answer == Messages.YES);
        }

        return shouldContinue;
    }

    public String getNameValue() {
        return myTfName.getText().trim();
    }

    public void setNameValue(String name) {
        final boolean isNameChangedByUser = myIsNameChangedByUser;
        setNamePathSyncEnabled(false);
        try {
            myTfName.setText(name);
        } finally {
            myIsNameChangedByUser = isNameChangedByUser;
            setNamePathSyncEnabled(true);
        }
    }

    public String getPath() {
        return myTfPath.getText().trim().replace(File.separatorChar, '/');
    }

    public void setPath(String path) {
        final boolean isPathChangedByUser = myIsPathChangedByUser;
        setPathNameSyncEnabled(false);
        try {
            myTfPath.setText(path);
        } finally {
            myIsPathChangedByUser = isPathChangedByUser;
            setPathNameSyncEnabled(true);
        }
    }

    public JTextField getNameComponent() {
        return myTfName;
    }

    @NotNull
    public JLabel getPathLabel() {
        return myPathLabel;
    }

    public JTextField getPathComponent() {
        return myTfPath;
    }

    @NotNull
    public FieldPanel getPathPanel() {
        return myPathPanel;
    }

    public void setPathComponentVisible(boolean visible) {
        myPathPanel.setVisible(visible);
    }

    public void setNameComponentVisible(boolean visible) {
        myTfName.setVisible(visible);
        myNameLabel.setVisible(visible);
    }

    public boolean isNameChangedByUser() {
        return myIsNameChangedByUser;
    }

    public boolean isPathChangedByUser() {
        return myIsPathChangedByUser;
    }

    public boolean isSyncEnabled() {
        return myIsSyncEnabled;
    }

    public void setSyncEnabled(boolean isSyncEnabled) {
        myIsSyncEnabled = isSyncEnabled;
    }

    private boolean isPathNameSyncEnabled() {
        if (!isSyncEnabled()) {
            return false;
        }
        return myIsPathNameSyncEnabled;
    }

    private void setPathNameSyncEnabled(boolean isPathNameSyncEnabled) {
        myIsPathNameSyncEnabled = isPathNameSyncEnabled;
    }

    private boolean isNamePathSyncEnabled() {
        if (!isSyncEnabled()) {
            return false;
        }
        return myIsNamePathSyncEnabled;
    }

    private void setNamePathSyncEnabled(boolean isNamePathSyncEnabled) {
        myIsNamePathSyncEnabled = isNamePathSyncEnabled;
    }

    public void syncNameToPath(boolean b) {
        myForceSync = b;
        if (b)
            ((PathFieldDocument) myTfPath.getDocument()).syncPathAndName();
    }

    public void addChangeListener(final Runnable callback) {
        DocumentAdapter adapter = new DocumentAdapter() {
            @Override
            protected void textChanged(DocumentEvent e) {
                callback.run();
            }
        };
        myTfName.getDocument().addDocumentListener(adapter);
        myTfPath.getDocument().addDocumentListener(adapter);
    }

    private class NameFieldDocument extends PlainDocument {
        public NameFieldDocument() {
            addDocumentListener(new DocumentAdapter() {
                @Override
                public void textChanged(DocumentEvent event) {
                    myIsNameChangedByUser = true;
                    syncNameAndPath();
                }
            });
        }

        @Override
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
            boolean ok = true;
            for (int idx = 0; idx < str.length() && ok; idx++) {
                char ch = str.charAt(idx);
                ok = ch != File.separatorChar && ch != '\\' && ch != '/' && ch != '|' && ch != ':';
            }
            if (ok) {
                super.insertString(offs, str, a);
            }
        }

        private void syncNameAndPath() {
            if (isNamePathSyncEnabled() && (myForceSync || !myIsPathChangedByUser)) {
                try {
                    setPathNameSyncEnabled(false);
                    final String name = getText(0, getLength());
                    final String path = myTfPath.getText().trim();
                    final int lastSeparatorIndex = path.lastIndexOf(File.separator);
                    if (lastSeparatorIndex >= 0) {
                        setPath(path.substring(0, lastSeparatorIndex + 1) + name);
                    }
                } catch (BadLocationException e) {
                    LOG.error(e);
                } finally {
                    setPathNameSyncEnabled(true);
                }
            }
        }
    }

    private class PathFieldDocument extends PlainDocument {
        public PathFieldDocument() {
            addDocumentListener(new DocumentAdapter() {
                @Override
                public void textChanged(DocumentEvent event) {
                    myIsPathChangedByUser = true;
                    syncPathAndName();
                }
            });
        }

        private void syncPathAndName() {
            if (isPathNameSyncEnabled() && (myForceSync || !myIsNameChangedByUser)) {
                try {
                    setNamePathSyncEnabled(false);
                    final String path = getText(0, getLength());
                    final int lastSeparatorIndex = path.lastIndexOf(File.separator);
                    if (lastSeparatorIndex >= 0 && (lastSeparatorIndex + 1) < path.length()) {
                        setNameValue(path.substring(lastSeparatorIndex + 1));
                    }
                } catch (BadLocationException e) {
                    LOG.error(e);
                } finally {
                    setNamePathSyncEnabled(true);
                }
            }
        }
    }

}