org.tigris.subversion.subclipse.ui.wizards.generatediff.PatchFileSelectionPage.java Source code

Java tutorial

Introduction

Here is the source code for org.tigris.subversion.subclipse.ui.wizards.generatediff.PatchFileSelectionPage.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 2006 Subclipse project 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:
 *     Subclipse project committers - initial API and implementation
 ******************************************************************************/
package org.tigris.subversion.subclipse.ui.wizards.generatediff;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.tigris.subversion.subclipse.ui.IHelpContextIds;
import org.tigris.subversion.subclipse.ui.ISVNUIConstants;
import org.tigris.subversion.subclipse.ui.Policy;
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
import org.tigris.subversion.subclipse.ui.util.ResourceSelectionTree;
import org.tigris.subversion.subclipse.ui.util.WorkspaceDialog;

/**
 * Page to select a patch file. Overriding validatePage was necessary to allow
 * entering a file name that already exists.
 */
class PatchFileSelectionPage extends WizardPage {
    private Text filenameCombo;
    private Button browseButton;
    private Button saveInFilesystem;
    private Button saveInWorkspace;
    private Button saveToClipboard;
    private ResourceSelectionTree resourceSelectionTree;
    private IResource[] resources;
    protected Text wsPathText;
    private Button wsBrowseButton;
    private boolean wsBrowsed = false;
    private HashMap statusMap;

    public final int CLIPBOARD = 1;
    public final int FILESYSTEM = 2;
    public final int WORKSPACE = 3;

    public PatchFileSelectionPage(String pageName, String title, ImageDescriptor image,
            IStructuredSelection selection, HashMap statusMap) {
        super(pageName, title, image);
        this.statusMap = statusMap;
        Object[] selectedResources = selection.toArray();
        resources = new IResource[selectedResources.length];
        for (int i = 0; i < selectedResources.length; i++)
            resources[i] = (IResource) selectedResources[i];
        setPageComplete(false);
    }

    /**
     * Allow the user to finish if a valid file has been entered. 
     */
    protected boolean validatePage() {
        boolean valid = false;

        switch (getSaveType()) {
        case WORKSPACE:
            valid = validateWorkspaceLocation();
            break;
        case FILESYSTEM:
            File file = new File(getFilesystemFile());
            valid = isValidFile(file);
            break;
        case CLIPBOARD:
            valid = true;
            break;
        }

        // Avoid draw flicker by clearing error message
        // if all is valid.
        if (valid) {
            setMessage(null);
            setErrorMessage(null);
        } else {
            setErrorMessage(Policy.bind("GenerateSVNDiff.EnterFilename")); //$NON-NLS-1$
        }
        setPageComplete(valid && getSelectedResources().length > 0);
        return valid;
    }

    private boolean isValidFile(File file) {
        if (!file.isAbsolute())
            return false;
        if (file.isDirectory())
            return false;
        File parent = file.getParentFile();
        if (parent == null)
            return false;
        if (!parent.exists())
            return false;
        if (!parent.isDirectory())
            return false;
        if (!file.exists()) {
            try {
                if (!file.createNewFile()) {
                    return false;
                }
                file.delete();
            } catch (IOException e) {
                return false;
            }
        }
        return true;
    }

    /**
     * Answers a full path to a file system file or <code>null</code> if the user
     * selected to save the patch in the workspace. 
     */
    public String getFilesystemFile() {
        if (saveInFilesystem.getSelection()) {
            return filenameCombo.getText();
        }
        return null;
    }

    /**
     * Answers a workspace file or <code>null</code> if the user selected to save
     * the patch outside of the workspace.
     */
    public IFile getWorkspaceFile() {
        if (saveInWorkspace.getSelection() && wsPathText.getText().length() > 0) {
            return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(wsPathText.getText()));
        }
        return null;
    }

    /**
     * Allow the user to chose to save the patch to the workspace or outside
     * of the workspace.
     */
    public void createControl(Composite parent) {

        Composite composite = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout();
        composite.setLayout(layout);
        composite.setLayoutData(new GridData());
        setControl(composite);
        initializeDialogUnits(composite);

        // set F1 help
        PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.PATCH_SELECTION_PAGE);

        // Clipboard
        saveToClipboard = new Button(composite, SWT.RADIO);
        saveToClipboard.setText(Policy.bind("GenerateSVNDiff.SaveToClipboard")); //$NON-NLS-1$
        saveToClipboard.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                validatePage();
                updateEnablements();
            }
        });

        // File System
        saveInFilesystem = new Button(composite, SWT.RADIO);
        saveInFilesystem.setText(Policy.bind("GenerateSVNDiff.SaveInFileSystem")); //$NON-NLS-1$
        saveInFilesystem.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                validatePage();
                updateEnablements();
            }
        });

        Composite nameGroup = new Composite(composite, SWT.NONE);
        layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = 0;
        nameGroup.setLayout(layout);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
        nameGroup.setLayoutData(data);

        filenameCombo = new Text(nameGroup, SWT.BORDER);
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        filenameCombo.setLayoutData(gd);
        filenameCombo.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                setPageComplete(validatePage());
            }
        });

        FocusListener focusListener = new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                ((Text) e.getSource()).selectAll();
            }

            public void focusLost(FocusEvent e) {
                ((Text) e.getSource()).setText(((Text) e.getSource()).getText());
            }
        };
        filenameCombo.addFocusListener(focusListener);

        browseButton = new Button(nameGroup, SWT.NULL);
        browseButton.setText(Policy.bind("GenerateSVNDiff.Browse")); //$NON-NLS-1$
        data = new GridData(GridData.HORIZONTAL_ALIGN_END);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        browseButton.setLayoutData(data);
        browseButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                FileDialog d = new FileDialog(getShell(), SWT.PRIMARY_MODAL | SWT.SAVE);
                d.setText(Policy.bind("GenerateSVNDiff.SavePatchAs")); //$NON-NLS-1$
                d.setFileName(Policy.bind("GenerateSVNDiff.patchTxt")); //$NON-NLS-1$
                String file = d.open();
                if (file != null) {
                    IPath path = new Path(file);
                    setFilesystemFilename(path.toOSString());
                }
            }
        });

        // Workspace
        saveInWorkspace = new Button(composite, SWT.RADIO);
        saveInWorkspace.setText(Policy.bind("GenerateSVNDiff.SaveInWorkspace")); //$NON-NLS-1$
        saveInWorkspace.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                validatePage();
                updateEnablements();
            }
        });

        final Composite pathGroup = new Composite(composite, SWT.NONE);
        layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = 0;
        pathGroup.setLayout(layout);
        data = new GridData(SWT.FILL, SWT.FILL, true, false);
        pathGroup.setLayoutData(data);

        wsPathText = new Text(pathGroup, SWT.BORDER);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.verticalAlignment = GridData.CENTER;
        gd.grabExcessVerticalSpace = false;
        gd.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
        wsPathText.setLayoutData(gd);
        wsPathText.setEditable(false);

        wsBrowseButton = new Button(pathGroup, SWT.NULL);
        gd = new GridData();
        gd.horizontalAlignment = GridData.FILL;
        int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        gd.widthHint = Math.max(widthHint, wsBrowseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
        wsBrowseButton.setLayoutData(gd);
        wsBrowseButton.setText(Policy.bind("GenerateSVNDiff.Browse")); //$NON-NLS-1$   
        wsBrowseButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                final WorkspaceDialog dialog = new WorkspaceDialog(getShell(),
                        Policy.bind("GenerateSVNDiff.workspaceDialogTitle"), //$NON-NLS-1$
                        Policy.bind("GenerateSVNDiff.workspaceDialogMessage"),
                        SVNUIPlugin.getPlugin().getImageDescriptor(ISVNUIConstants.IMG_WIZBAN_DIFF), wsPathText);
                wsBrowsed = true;
                dialog.open();
                validatePage();
            }
        });

        resourceSelectionTree = new ResourceSelectionTree(composite, SWT.NONE,
                Policy.bind("GenerateSVNDiff.Changes"), ResourceSelectionTree.dedupeResources(resources), statusMap, //$NON-NLS-1$
                null, true, null, null);
        ((CheckboxTreeViewer) resourceSelectionTree.getTreeViewer()).setAllChecked(true);

        resourceSelectionTree.getTreeViewer().addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                validatePage();
            }
        });

        saveToClipboard.setSelection(true);
        validatePage();
        updateEnablements();
    }

    /**
     * Sets the file name in the file system text.
     */
    protected void setFilesystemFilename(String filename) {
        filenameCombo.setText(filename);
    }

    public IResource[] getSelectedResources() {
        return resourceSelectionTree.getSelectedResources();
    }

    /**
     * Enable and disable controls based on the selected radio button.
     */
    protected void updateEnablements() {
        int type = getSaveType();

        browseButton.setEnabled(type == FILESYSTEM);
        filenameCombo.setEnabled(type == FILESYSTEM);
        wsPathText.setEnabled(type == WORKSPACE);
        wsBrowseButton.setEnabled(type == WORKSPACE);
        if (type == WORKSPACE)
            wsBrowsed = false;
    }

    /**
     * Answers the type of the patch file destination.
     */
    public int getSaveType() {
        if (saveInFilesystem.getSelection()) {
            return FILESYSTEM;
        } else if (saveToClipboard.getSelection()) {
            return CLIPBOARD;
        } else {
            return WORKSPACE;
        }
    }

    /**
     * The following conditions must hold for the file system location to be valid:
     * - a parent must be selected in the workspace tree view
     * - the resource name must be valid 
     */
    private boolean validateWorkspaceLocation() {
        int type = getSaveType();
        //make sure that the field actually has a filename in it - making
        //sure that the user has had a chance to browse the workspace first
        if (wsPathText.getText().equals("")) { //$NON-NLS-1$
            if (type == WORKSPACE && wsBrowsed)
                setErrorMessage(Policy.bind("GenerateSVNDiff.validFileName")); //$NON-NLS-1$   
            return false;
        }

        //Make sure that all the segments but the last one (i.e. project + all
        //folders) exist - file doesn't have to exist. It may have happened that
        //some folder refactoring has been done since this path was last saved.
        //
        //Assume that the path will always be in format project/{folders}*/file - this
        //is controlled by the workspace location dialog

        IPath pathToWorkspaceFile = new Path(wsPathText.getText());
        //Trim file name from path
        IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);

        IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
        if (container == null) {
            if (type == WORKSPACE)
                setErrorMessage(Policy.bind("GenerateSVNDiff.validFileName")); //$NON-NLS-1$   
            return false;
        }

        return true;
    }

}