org.ganoro.phing.ui.internal.preferences.AddCustomDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.ganoro.phing.ui.internal.preferences.AddCustomDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.ganoro.phing.ui.internal.preferences;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.FileSystemElement;
import org.eclipse.ui.externaltools.internal.ui.TreeAndListGroup;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.model.WorkbenchViewerComparator;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import org.ganoro.phing.core.IAntClasspathEntry;
import org.ganoro.phing.core.IPhingCoreConstants;
import org.ganoro.phing.ui.PhingUi;

import com.ibm.icu.text.MessageFormat;

public class AddCustomDialog extends StatusDialog {

    private ZipFileStructureProvider providerCache;
    private IImportStructureProvider currentProvider;

    //A boolean to indicate if the user has typed anything
    private boolean entryChanged = false;

    private Combo sourceNameField;
    private List libraryEntries;
    private List existingNames;

    private String noNameErrorMsg;
    private String alreadyExistsErrorMsg;

    private TreeAndListGroup selectionGroup;

    private Text nameField;

    private String name = IPhingCoreConstants.EMPTY_STRING;
    private IAntClasspathEntry library = null;
    private String className = IPhingCoreConstants.EMPTY_STRING;

    private boolean editing = false;

    private String helpContext;

    /**
     * Creates a new dialog with the given shell and title.
     */
    public AddCustomDialog(Shell parent, List libraryEntries, List existingNames, String helpContext) {
        super(parent);
        this.libraryEntries = libraryEntries;
        this.existingNames = existingNames;
        this.helpContext = helpContext;
        setShellStyle(getShellStyle() | SWT.RESIZE);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
     */
    protected Control createDialogArea(Composite parent) {
        Composite topComposite = (Composite) super.createDialogArea(parent);
        topComposite.setSize(topComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));

        Composite topGroup = new Composite(topComposite, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        topGroup.setLayout(layout);
        topGroup.setFont(topComposite.getFont());
        topGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

        createNameGroup(topGroup);
        createRootDirectoryGroup(topGroup);
        createFileSelectionGroup(topComposite);

        if (library != null) {
            setSourceName(library.getLabel());
        }
        return topComposite;
    }

    private void createNameGroup(Composite topComposite) {
        Label label = new Label(topComposite, SWT.NONE);
        label.setFont(topComposite.getFont());
        label.setText(AntPreferencesMessages.AddCustomDialog__Name__3);

        nameField = new Text(topComposite, SWT.BORDER);
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;

        nameField.setLayoutData(data);
        nameField.setFont(topComposite.getFont());
        nameField.setText(name);
        nameField.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                updateStatus();
            }
        });
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
     */
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, helpContext);
    }

    /**
     * Clears the cached structure provider after first finalizing
     * it properly.
     */
    private void clearProviderCache() {
        if (providerCache != null) {
            closeZipFile(providerCache.getZipFile());
            providerCache = null;
        }
    }

    /**
     * Attempts to close the passed zip file, and answers a boolean indicating success.
     */
    private boolean closeZipFile(ZipFile file) {
        try {
            file.close();
        } catch (IOException e) {
            PhingUi.log(MessageFormat.format(AntPreferencesMessages.AddCustomDialog_Could_not_close_zip_file__0__4,
                    new String[] { file.getName() }), e);
            return false;
        }

        return true;
    }

    /**
     *   Create the group for creating the root directory
     */
    private void createRootDirectoryGroup(Composite parent) {
        Label groupLabel = new Label(parent, SWT.NONE);
        groupLabel.setText(AntPreferencesMessages.AddCustomDialog__Location);
        groupLabel.setFont(parent.getFont());

        // source name entry field
        sourceNameField = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
        data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
        sourceNameField.setLayoutData(data);
        sourceNameField.setFont(parent.getFont());

        sourceNameField.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateFromSourceField();
            }
        });

        Iterator libraries = libraryEntries.iterator();
        while (libraries.hasNext()) {
            ClasspathEntry entry = (ClasspathEntry) libraries.next();
            sourceNameField.add(entry.getLabel());
        }

        sourceNameField.addKeyListener(new KeyAdapter() {
            /*
             * @see KeyListener.keyPressed
             */
            public void keyPressed(KeyEvent e) {
                //If there has been a key pressed then mark as dirty
                entryChanged = true;
            }
        });

        sourceNameField.addFocusListener(new FocusAdapter() {
            /*
             * @see FocusListener.focusLost(FocusEvent)
             */
            public void focusLost(FocusEvent e) {
                //Clear the flag to prevent constant update
                if (entryChanged) {
                    entryChanged = false;
                    updateFromSourceField();
                }
            }
        });
    }

    /**
     * Update the receiver from the source name field.
     */
    private void updateFromSourceField() {
        setSourceName(sourceNameField.getText());
        updateStatus();
    }

    /**
     * Check the field values and display a message in the status if needed.
     */
    private void updateStatus() {
        StatusInfo status = new StatusInfo();
        String customName = nameField.getText().trim();
        if (customName.length() == 0) {
            status.setError(noNameErrorMsg);
        } else if (!editing) {
            Iterator names = existingNames.iterator();
            while (names.hasNext()) {
                String aName = (String) names.next();
                if (aName.equals(customName)) {
                    status.setError(MessageFormat.format(alreadyExistsErrorMsg, new String[] { customName }));
                    updateStatus(status);
                    return;
                }
            }
        }
        if (selectionGroup.getListTableSelection().isEmpty()) {
            status.setError(AntPreferencesMessages.AddCustomDialog_mustSelect);
        }
        updateStatus(status);
    }

    /**
     * Sets the source name of the import to be the supplied path.
     * Adds the name of the path to the list of items in the
     * source combo and selects it.
     *
     * @param path the path to be added
     */
    private void setSourceName(String path) {

        if (path.length() > 0) {

            String[] currentItems = this.sourceNameField.getItems();
            int selectionIndex = -1;
            for (int i = 0; i < currentItems.length; i++) {
                if (currentItems[i].equals(path)) {
                    selectionIndex = i;
                    break;
                }
            }
            if (selectionIndex < 0) {
                int oldLength = currentItems.length;
                String[] newItems = new String[oldLength + 1];
                System.arraycopy(currentItems, 0, newItems, 0, oldLength);
                newItems[oldLength] = path;
                this.sourceNameField.setItems(newItems);
                selectionIndex = oldLength;
            }
            this.sourceNameField.select(selectionIndex);

            resetSelection();
        }
    }

    /*
    * Create the file selection widget
    */
    private void createFileSelectionGroup(Composite parent) {
        //Just create with a dummy root.
        FileSystemElement dummyRoot = new FileSystemElement("Dummy", null, true); //$NON-NLS-1$
        this.selectionGroup = new TreeAndListGroup(parent, dummyRoot, getFolderProvider(),
                new WorkbenchLabelProvider(), getFileProvider(), new WorkbenchLabelProvider(), SWT.NONE, 400, 150,
                false);

        ISelectionChangedListener listener = new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateStatus();
            }
        };

        WorkbenchViewerComparator comparator = new WorkbenchViewerComparator();
        this.selectionGroup.setTreeComparator(comparator);
        this.selectionGroup.setListSorter(comparator);
        this.selectionGroup.addSelectionChangedListener(listener);
        selectionGroup.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                if (getButton(IDialogConstants.OK_ID).isEnabled()) {
                    buttonPressed(IDialogConstants.OK_ID);
                }
            }
        });
    }

    /**
     *   Returns whether the specified source currently exists
     *   and is valid (ie.- proper format)
     */
    protected boolean ensureSourceIsValid() {
        ZipFile specifiedFile = getSpecifiedSourceFile();

        if (specifiedFile == null) {
            return false;
        }

        return closeZipFile(specifiedFile);
    }

    /**
    *   Answer the root FileSystemElement that represents the contents of the
    *   currently-specified .zip file.  If this FileSystemElement is not
    *   currently defined then create and return it.
    */
    private MinimizedFileSystemElement getFileSystemTree() {
        IImportStructureProvider provider = null;
        MinimizedFileSystemElement element = null;
        ZipFile sourceFile = getSpecifiedSourceFile();
        if (sourceFile == null) {
            File file = new File(sourceNameField.getText());
            if (file.exists()) {
                provider = FileSystemStructureProvider.INSTANCE;
                element = selectFiles(file, provider);
            }
        } else {
            //zip file set as location
            provider = getStructureProvider(sourceFile);
            element = selectFiles(((ZipFileStructureProvider) provider).getRoot(), provider);
        }
        this.currentProvider = provider;
        return element;
    }

    /**
     * Invokes a file selection operation using the specified file system and
     * structure provider.  If the user specifies files then this selection is
     * cached for later retrieval and is returned.
     */
    private MinimizedFileSystemElement selectFiles(final Object rootFileSystemObject,
            final IImportStructureProvider structureProvider) {

        final MinimizedFileSystemElement[] results = new MinimizedFileSystemElement[1];

        BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
            public void run() {
                //Create the root element from the supplied file system object
                results[0] = createRootElement(rootFileSystemObject, structureProvider);
            }
        });

        return results[0];
    }

    /**
     * Creates and returns a <code>MinimizedFileSystemElement</code> if the specified
     * file system object merits one.
     */
    private MinimizedFileSystemElement createRootElement(Object fileSystemObject,
            IImportStructureProvider provider) {
        boolean isContainer = provider.isFolder(fileSystemObject);
        String elementLabel = provider.getLabel(fileSystemObject);

        // Use an empty label so that display of the element's full name
        // doesn't include a confusing label
        MinimizedFileSystemElement dummyParent = new MinimizedFileSystemElement(IPhingCoreConstants.EMPTY_STRING,
                null, true);
        dummyParent.setPopulated();
        MinimizedFileSystemElement result = new MinimizedFileSystemElement(elementLabel, dummyParent, isContainer);
        result.setFileSystemObject(fileSystemObject);

        //Get the files for the element so as to build the first level
        result.getFiles(provider);

        return dummyParent;
    }

    /**
     *   Answer a handle to the zip file currently specified as being the source.
     *   Return <code>null</code> if this file does not exist or is not of valid format.
     */
    private ZipFile getSpecifiedSourceFile() {
        try {
            String expanded = sourceNameField.getText();
            expanded = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(expanded);
            return new ZipFile(expanded);
        } catch (ZipException e) {
            StatusInfo status = new StatusInfo();
            status.setError(AntPreferencesMessages.AddCustomDialog_Bad_Format);
            updateStatus(status);
        } catch (IOException e) {
            StatusInfo status = new StatusInfo();
            status.setError(AntPreferencesMessages.AddCustomDialog_Unreadable);
            updateStatus(status);
        } catch (CoreException e) {
            StatusInfo status = new StatusInfo();
            status.setError(AntPreferencesMessages.AddCustomDialog_13);
            updateStatus(status);
        }

        sourceNameField.setFocus();
        return null;
    }

    /**
     * Returns a structure provider for the specified zip file.
     */
    private ZipFileStructureProvider getStructureProvider(ZipFile targetZip) {
        if (providerCache == null) {
            providerCache = new ZipFileStructureProvider(targetZip);
        } else if (!providerCache.getZipFile().getName().equals(targetZip.getName())) {
            clearProviderCache();
            // ie.- new value, so finalize & remove old value
            providerCache = new ZipFileStructureProvider(targetZip);
        } else if (!providerCache.getZipFile().equals(targetZip)) {
            closeZipFile(targetZip); // ie.- duplicate handle to same .zip
        }

        return providerCache;
    }

    /**
     *   Repopulate the view based on the currently entered directory.
     */
    private void resetSelection() {
        MinimizedFileSystemElement currentRoot = getFileSystemTree();
        selectionGroup.setRoot(currentRoot);

        if (className.length() != 0) {
            StringTokenizer tokenizer = new StringTokenizer(className, "."); //$NON-NLS-1$
            selectClass(currentRoot, tokenizer);
        }
    }

    private void selectClass(MinimizedFileSystemElement currentParent, StringTokenizer tokenizer) {
        if (!tokenizer.hasMoreTokens()) {
            return;
        }
        List folders = currentParent.getFolders(currentProvider);
        if (folders.size() == 1) {
            MinimizedFileSystemElement element = (MinimizedFileSystemElement) folders.get(0);
            if (element.getLabel(null).equals("/")) { //$NON-NLS-1$
                selectionGroup.selectAndRevealFolder(element);
                selectClass(element, tokenizer);
                return;
            }
        }
        String currentName = tokenizer.nextToken();
        if (tokenizer.hasMoreTokens()) {
            Iterator allFolders = folders.iterator();
            while (allFolders.hasNext()) {
                MinimizedFileSystemElement folder = (MinimizedFileSystemElement) allFolders.next();
                if (folder.getLabel(null).equals(currentName)) {
                    selectionGroup.selectAndRevealFolder(folder);
                    selectClass(folder, tokenizer);
                    return;
                }
            }
        } else {
            List files = currentParent.getFiles(currentProvider);
            Iterator iter = files.iterator();
            while (iter.hasNext()) {
                MinimizedFileSystemElement file = (MinimizedFileSystemElement) iter.next();
                if (file.getLabel(null).equals(currentName + ".class")) { //$NON-NLS-1$
                    selectionGroup.selectAndRevealFile(file);
                    return;
                }
            }
        }
    }

    /**
     * Returns a content provider for <code>MinimizedFileSystemElement</code>s that returns
     * only files as children.
     */
    private ITreeContentProvider getFileProvider() {
        return new WorkbenchContentProvider() {
            public Object[] getChildren(Object o) {
                if (o instanceof MinimizedFileSystemElement) {
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
                    return element.getFiles(currentProvider).toArray();
                }
                return new Object[0];
            }
        };
    }

    /**
     * Returns a content provider for <code>MinimizedFileSystemElement</code>s that returns
     * only folders as children.
     */
    private ITreeContentProvider getFolderProvider() {
        return new WorkbenchContentProvider() {
            public Object[] getChildren(Object o) {
                if (o instanceof MinimizedFileSystemElement) {
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
                    return element.getFolders(currentProvider).toArray();
                }
                return new Object[0];
            }

            public boolean hasChildren(Object o) {
                if (o instanceof MinimizedFileSystemElement) {
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
                    if (element.isPopulated()) {
                        return getChildren(element).length > 0;
                    }

                    //If we have not populated then wait until asked
                    return true;
                }
                return false;
            }
        };
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#cancelPressed()
     */
    protected void cancelPressed() {
        clearProviderCache();
        super.cancelPressed();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#okPressed()
     */
    protected void okPressed() {
        clearProviderCache();
        name = nameField.getText().trim();
        library = (ClasspathEntry) libraryEntries.get(sourceNameField.getSelectionIndex());
        IStructuredSelection selection = this.selectionGroup.getListTableSelection();
        MinimizedFileSystemElement element = (MinimizedFileSystemElement) selection.getFirstElement();
        if (element == null) {
            super.okPressed();
            return;
        }
        Object file = element.getFileSystemObject();
        if (file instanceof ZipEntry) {
            className = ((ZipEntry) file).getName();
        } else {
            className = ((File) file).getAbsolutePath();
            IPath classPath = new Path(className);
            IPath libraryPath = new Path(library.getEntryURL().getPath());
            int matching = classPath.matchingFirstSegments(libraryPath);
            classPath = classPath.removeFirstSegments(matching);
            classPath = classPath.setDevice(null);
            className = classPath.toString();
        }
        int index = className.lastIndexOf('.');
        className = className.substring(0, index);
        className = className.replace('/', '.');
        super.okPressed();
    }

    protected String getName() {
        return name;
    }

    protected void setName(String name) {
        this.name = name;
    }

    protected void setLibraryEntry(IAntClasspathEntry library) {
        this.library = library;
        editing = true;
    }

    protected IAntClasspathEntry getLibraryEntry() {
        return this.library;
    }

    protected String getClassName() {
        return className;
    }

    protected void setClassName(String className) {
        this.className = className;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#create()
     */
    public void create() {
        super.create();
        getButton(IDialogConstants.OK_ID).setEnabled(!(library == null));
    }

    protected void setAlreadyExistsErrorMsg(String alreadyExistsErrorMsg) {
        this.alreadyExistsErrorMsg = alreadyExistsErrorMsg;
    }

    protected void setNoNameErrorMsg(String noNameErrorMsg) {
        this.noNameErrorMsg = noNameErrorMsg;
    }
}