Package org.eclipse.egit.ui.internal.history

Source Code of org.eclipse.egit.ui.internal.history.LocationPage$WorkspaceDialog

/*******************************************************************************
* Copyright (c) 2010, 2012 SAP AG 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:
*    Tomasz Zarna <Tomasz.Zarna@pl.ibm.com> - Allow to save patches in Workspace
*    Daniel Megert <daniel_megert@ch.ibm.com> - Create Patch... should remember previously chosen location
*    Daniel Megert <daniel_megert@ch.ibm.com> - Create Patch wizard must validate initial input
*******************************************************************************/
package org.eclipse.egit.ui.internal.history;

import java.io.File;
import java.util.ArrayList;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.op.CreatePatchOperation;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Image;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;

/**
* A wizard page to choose the target location.
* <p>
* Extracted from {@link GitCreatePatchWizard}
*/
public class LocationPage extends WizardPage {

  private static final String PATH_KEY = "GitCreatePatchWizard.LocationPage.path"; //$NON-NLS-1$
  private static final String LOCATION_KEY = "GitCreatePatchWizard.LocationPage.location"; //$NON-NLS-1$
  private static final String LOCATION_VALUE_CLIPBOARD = "clipboard"; //$NON-NLS-1$
  private static final String LOCATION_VALUE_FILE_SYSTEM = "filesystem"; //$NON-NLS-1$
  private static final String LOCATION_VALUE_WORKSPACE = "workspace"; //$NON-NLS-1$


  private Button cpRadio;

  Button fsRadio;

  private Text fsPathText;

  private Button fsBrowseButton;

  private Button wsRadio;

  private Text wsPathText;

  private Button wsBrowseButton;

  private boolean wsBrowsed = false;

  private boolean pageValid;

  private IContainer wsSelectedContainer;

  private static class LocationPageContentProvider extends
      BaseWorkbenchContentProvider {
    //Never show closed projects
    boolean showClosedProjects = false;

    public Object[] getChildren(Object element) {
      if (element instanceof IWorkspace) {
        // check if closed projects should be shown
        IProject[] allProjects = ((IWorkspace) element).getRoot().getProjects();
        if (showClosedProjects)
          return allProjects;

        ArrayList<IProject> accessibleProjects = new ArrayList<IProject>();
        for (IProject project : allProjects)
          if (project.isOpen())
            accessibleProjects.add(project);
        return accessibleProjects.toArray();
      }
      return super.getChildren(element);
    }
  }

  private class WorkspaceDialog extends TitleAreaDialog {

    protected TreeViewer wsTreeViewer;
    protected Text wsFilenameText;
    protected Image dlgTitleImage;

    private boolean modified = false;

    public WorkspaceDialog(Shell shell) {
      super(shell);
    }

    protected Control createContents(Composite parent) {
      Control control = super.createContents(parent);
      setTitle(UIText.GitCreatePatchWizard_WorkspacePatchDialogTitle);
      setMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogDescription);
      //create title image
      dlgTitleImage = UIIcons.WIZBAN_CREATE_PATCH.createImage();
      setTitleImage(dlgTitleImage);

      return control;
    }

    protected Control createDialogArea(Composite parent){
      Composite parentComposite = (Composite) super.createDialogArea(parent);

      // create a composite with standard margins and spacing
      Composite composite = new Composite(parentComposite, SWT.NONE);
      GridLayout layout = new GridLayout();
      layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
      layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
      layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
      layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
      composite.setLayout(layout);
      composite.setLayoutData(new GridData(GridData.FILL_BOTH));
      composite.setFont(parentComposite.getFont());

      getShell().setText(UIText.GitCreatePatchWizard_WorkspacePatchDialogSavePatch);

      wsTreeViewer = new TreeViewer(composite, SWT.BORDER);
      final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
      gd.widthHint= 550;
      gd.heightHint= 250;
      wsTreeViewer.getTree().setLayoutData(gd);

      wsTreeViewer.setContentProvider(new LocationPageContentProvider());
      wsTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
      wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
      wsTreeViewer.setInput(ResourcesPlugin.getWorkspace());

      //Open to whatever is selected in the workspace field
      IPath existingWorkspacePath = new Path(wsPathText.getText());
      //Ensure that this workspace path is valid
      IResource selectedResource = ResourcesPlugin.getWorkspace().getRoot().findMember(existingWorkspacePath);
      if (selectedResource != null) {
        wsTreeViewer.expandToLevel(selectedResource, 0);
        wsTreeViewer.setSelection(new StructuredSelection(selectedResource));
      }

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

      final Label label = new Label(group, SWT.NONE);
      label.setLayoutData(new GridData());
      label.setText(UIText.GitCreatePatchWizard_WorkspacePatchDialogFileName);

      wsFilenameText = new Text(group,SWT.BORDER);
      wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

      setupListeners();

      return parent;
    }

    protected Button createButton(Composite parent, int id,
        String label, boolean defaultButton) {
      Button button = super.createButton(parent, id, label,
          defaultButton);
      if (id == IDialogConstants.OK_ID)
        button.setEnabled(false);
      return button;
    }

    private void validateDialog() {
      String fileName = wsFilenameText.getText();

      if (fileName.equals("")) //$NON-NLS-1$
        if (modified) {
          setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogEnterFileName);
          getButton(IDialogConstants.OK_ID).setEnabled(false);
          return;
        } else {
          setErrorMessage(null);
          getButton(IDialogConstants.OK_ID).setEnabled(false);
          return;
        }

      // make sure that the filename is valid
      if (!(ResourcesPlugin.getWorkspace().validateName(fileName,
          IResource.FILE)).isOK() && modified) {
        setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchEnterValidFileName);
        getButton(IDialogConstants.OK_ID).setEnabled(false);
        return;
      }

      // Make sure that a container has been selected
      if (getSelectedContainer() == null) {
        setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogEnterValidLocation);
        getButton(IDialogConstants.OK_ID).setEnabled(false);
        return;
      } else {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IPath fullPath = wsSelectedContainer.getFullPath().append(
            fileName);
        if (workspace.getRoot().getFolder(fullPath).exists()) {
          setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchFolderExists);
          getButton(IDialogConstants.OK_ID).setEnabled(false);
          return;
        }
      }

      setErrorMessage(null);
      getButton(IDialogConstants.OK_ID).setEnabled(true);
    }

    protected void okPressed() {
      IFile file = wsSelectedContainer.getFile(new Path(
          wsFilenameText.getText()));
      if (file != null)
        wsPathText.setText(file.getFullPath().toString());

      validatePage();
      super.okPressed();
    }

    private IContainer getSelectedContainer() {
      Object obj = ((IStructuredSelection)wsTreeViewer.getSelection()).getFirstElement();
      if (obj instanceof IContainer)
        wsSelectedContainer = (IContainer) obj;
      else if (obj instanceof IFile)
        wsSelectedContainer = ((IFile) obj).getParent();
      return wsSelectedContainer;
    }

    protected void cancelPressed() {
      validatePage();
      super.cancelPressed();
    }

    public boolean close() {
      if (dlgTitleImage != null)
        dlgTitleImage.dispose();
      return super.close();
    }

    void setupListeners(){
      wsTreeViewer.addSelectionChangedListener(
          new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
              IStructuredSelection s = (IStructuredSelection)event.getSelection();
              Object obj=s.getFirstElement();
              if (obj instanceof IContainer)
                wsSelectedContainer = (IContainer) obj;
              else if (obj instanceof IFile){
                IFile tempFile = (IFile) obj;
                wsSelectedContainer = tempFile.getParent();
                wsFilenameText.setText(tempFile.getName());
              }
              validateDialog();
            }
          });

      wsTreeViewer.addDoubleClickListener(
          new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
              ISelection s= event.getSelection();
              if (s instanceof IStructuredSelection) {
                Object item = ((IStructuredSelection)s).getFirstElement();
                if (wsTreeViewer.getExpandedState(item))
                  wsTreeViewer.collapseToLevel(item, 1);
                else
                  wsTreeViewer.expandToLevel(item, 1);
              }
              validateDialog();
            }
          });

      wsFilenameText.addModifyListener(new ModifyListener() {
        public void modifyText(ModifyEvent e) {
          modified = true;
          validateDialog();
        }
      });
    }
  }

  /**
   * @param pageName
   * @param title
   * @param titleImage
   */
  protected LocationPage(String pageName, String title,
      ImageDescriptor titleImage) {
    super(pageName, title, titleImage);
  }

  public void createControl(Composite parent) {
    final Composite composite = new Composite(parent, SWT.NULL);
    GridLayout gridLayout = new GridLayout();
    gridLayout.numColumns = 3;
    composite.setLayout(gridLayout);
    composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    initializeDialogUnits(composite);

    String selectedOption= getDialogSettings().get(LOCATION_KEY);
    if (selectedOption == null)
      selectedOption = LOCATION_VALUE_CLIPBOARD;

    // clipboard
    GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
    gd.horizontalSpan = 3;
    cpRadio = new Button(composite, SWT.RADIO);
    cpRadio.setText(UIText.GitCreatePatchWizard_Clipboard);
    cpRadio.setLayoutData(gd);
    cpRadio.setSelection(LOCATION_VALUE_CLIPBOARD.equals(selectedOption));

    // filesystem
    boolean isFileSystemSelected = LOCATION_VALUE_FILE_SYSTEM.equals(selectedOption);
    fsRadio = new Button(composite, SWT.RADIO);
    fsRadio.setText(UIText.GitCreatePatchWizard_File);
    fsRadio.setSelection(isFileSystemSelected);

    fsPathText = new Text(composite, SWT.BORDER);
    gd = new GridData(GridData.FILL_HORIZONTAL);
    fsPathText.setLayoutData(gd);
    fsPathText.setText(createFileName());
    fsPathText.setEnabled(isFileSystemSelected);

    fsBrowseButton = new Button(composite, SWT.PUSH);
    fsBrowseButton.setText(UIText.GitCreatePatchWizard_Browse);
    UIUtils.setButtonLayoutData(fsBrowseButton);
    fsBrowseButton.setEnabled(isFileSystemSelected);

    // workspace
    boolean isWorkspaceSelected = LOCATION_VALUE_WORKSPACE.equals(selectedOption);
    wsRadio = new Button(composite, SWT.RADIO);
    wsRadio.setText(UIText.GitCreatePatchWizard_Workspace);
    wsRadio.setSelection(isWorkspaceSelected);

    wsPathText = new Text(composite, SWT.BORDER);
    wsPathText.setLayoutData(gd);
    wsPathText.setEnabled(isWorkspaceSelected);

    wsBrowseButton = new Button(composite, SWT.PUSH);
    wsBrowseButton.setText(UIText.GitCreatePatchWizard_Browse);
    UIUtils.setButtonLayoutData(wsBrowseButton);
    wsBrowseButton.setEnabled(isWorkspaceSelected);

    cpRadio.addListener(SWT.Selection, new Listener() {
      public void handleEvent(Event event) {
        // disable other input controls
        if (((Button) event.widget).getSelection()) {
          fsPathText.setEnabled(false);
          fsBrowseButton.setEnabled(false);
          wsPathText.setEnabled(false);
          wsBrowseButton.setEnabled(false);
          getDialogSettings().put(LOCATION_KEY, LOCATION_VALUE_CLIPBOARD);
          validatePage();
        }
      }
    });

    fsRadio.addListener(SWT.Selection, new Listener() {

      public void handleEvent(Event event) {
        if (((Button) event.widget).getSelection()) {
          // enable filesystem input controls
          fsPathText.setEnabled(true);
          fsBrowseButton.setEnabled(true);
          wsPathText.setEnabled(false);
          wsBrowseButton.setEnabled(false);
          // set focus to filesystem input text control
          fsPathText.setFocus();
          getDialogSettings().put(LOCATION_KEY, LOCATION_VALUE_FILE_SYSTEM);
          validatePage();
        }
      }
    });

    fsPathText.addModifyListener(new ModifyListener() {

      public void modifyText(ModifyEvent e) {
        if (validatePage()) {
          IPath filePath= Path.fromOSString(fsPathText.getText()).removeLastSegments(1);
          getDialogSettings().put(PATH_KEY, filePath.toPortableString());
        }
      }
    });

    fsBrowseButton.addListener(SWT.Selection, new Listener() {
      public void handleEvent(Event event) {
        final FileDialog dialog = new FileDialog(getShell(),
            SWT.PRIMARY_MODAL | SWT.SAVE);
        if (pageValid) {
          final File file = new File(fsPathText.getText());
          dialog.setFilterPath(file.getParent());
          dialog.setFileName(file.getName());
        } else
          dialog.setFileName(""); //$NON-NLS-1$
        dialog.setText(""); //$NON-NLS-1$
        final String path = dialog.open();
        if (path != null)
          fsPathText.setText(new Path(path).toOSString());
        validatePage();
      }
    });

    wsRadio.addListener(SWT.Selection, new Listener() {

      public void handleEvent(Event event) {
        if (((Button) event.widget).getSelection()) {
          fsPathText.setEnabled(false);
          fsBrowseButton.setEnabled(false);
          // enable workspace input controls
          wsPathText.setEnabled(true);
          wsBrowseButton.setEnabled(true);
          // set focus to workspace input text control
          wsPathText.setFocus();
          getDialogSettings().put(LOCATION_KEY, LOCATION_VALUE_WORKSPACE);
          validatePage();
        }
      }
    });

    wsPathText.addModifyListener(new ModifyListener() {

      public void modifyText(ModifyEvent e) {
        if (validatePage()) {
          IPath filePath= Path.fromOSString(wsPathText.getText()).removeLastSegments(1);
          getDialogSettings().put(PATH_KEY, filePath.toPortableString());
        }
      }
    });

    wsBrowseButton.addListener(SWT.Selection, new Listener() {
      public void handleEvent(Event event) {
        final WorkspaceDialog dialog = new WorkspaceDialog(getShell());
        wsBrowsed = true;
        dialog.open();
        validatePage();
      }
    });

    Dialog.applyDialogFont(composite);
    setControl(composite);

    validatePage();
  }

  private String createFileName() {
    String suggestedFileName = getCommit() != null ? CreatePatchOperation
        .suggestFileName(getCommit()) : getRepository().getWorkTree()
        .getName().concat(".patch"); //$NON-NLS-1$
    String path = getDialogSettings().get(PATH_KEY);
    if (path != null)
      return Path.fromPortableString(path).append(suggestedFileName).toOSString();

    return (new File(System.getProperty("user.dir", ""), suggestedFileName)).getPath(); //$NON-NLS-1$ //$NON-NLS-2$
  }

  private RevCommit getCommit() {
    return ((GitCreatePatchWizard)getWizard()).getCommit();
  }

  private Repository getRepository() {
    return ((GitCreatePatchWizard)getWizard()).getRepository();
  }

  /**
   * Allow the user to finish if a valid file has been entered.
   *
   * @return page is valid
   */
  protected boolean validatePage() {
    if (wsRadio.getSelection())
      pageValid = validateWorkspaceLocation();
    else if (fsRadio.getSelection())
      pageValid = validateFilesystemLocation();
    else if (cpRadio.getSelection())
      pageValid = true;

    /**
     * Avoid draw flicker by clearing error message if all is valid.
     */
    if (pageValid) {
      setMessage(null);
      setErrorMessage(null);
    }
    setPageComplete(pageValid);
    return pageValid;
  }

  /**
   * The following conditions must hold for the file system location to be
   * valid:
   * - the path must be valid and non-empty
   * - the path must be absolute
   * - the specified file must be of type file
   * - the parent must exist (new folders can be created via the browse button)
   *
   * @return if the location is valid
   */
  private boolean validateFilesystemLocation() {
    final String pathString = fsPathText.getText().trim();
    if (pathString.length() == 0
        || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$
      setErrorMessage(UIText.GitCreatePatchWizard_FilesystemError);
      return false;
    }

    final File file = new File(pathString);
    if (!file.isAbsolute()) {
      setErrorMessage(UIText.GitCreatePatchWizard_FilesystemInvalidError);
      return false;
    }

    if (file.isDirectory()) {
      setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryError);
      return false;
    }

    if (pathString.endsWith("/") || pathString.endsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$
      setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError);
      return false;
    }

    final File parent = file.getParentFile();
    if (!(parent.exists() && parent.isDirectory())) {
      setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError);
      return false;
    }
    return true;
  }

  /**
   * The following conditions must hold for the workspace location to be valid:
   * - a parent must be selected in the workspace tree view
   * - the resource name must be valid
   *
   * @return if the location is valid
   */
  private boolean validateWorkspaceLocation() {
    //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 (wsRadio.getSelection() && wsBrowsed)
        setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchEnterValidFileName);
      else
        setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchSelectByBrowsing);
      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.
    //
    // The path will always be in format project/{folders}*/file - this
    // is controlled by the workspace location dialog and by
    // validatePath method when path has been entered manually.

    IPath pathToWorkspaceFile = new Path(wsPathText.getText());
    IStatus status = ResourcesPlugin.getWorkspace().validatePath(wsPathText.getText(), IResource.FILE);
    if (status.isOK()) {
      //Trim file name from path
      IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
      IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
      if (container == null) {
        if (wsRadio.getSelection())
          setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchSelectByBrowsing);
        return false;
      } else if (!container.isAccessible()) {
        if (wsRadio.getSelection())
          setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchProjectClosed);
        return false;
      } else if (ResourcesPlugin.getWorkspace().getRoot().getFolder(
          pathToWorkspaceFile).exists()) {
        setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchFolderExists);
        return false;
      }
    } else {
      setErrorMessage(status.getMessage());
      return false;
    }
    return true;
  }

  /**
   * @return answers a full path to a file system file or
   *         <code>null</code> if the user selected to save the patch in
   *         the clipboard.
   */
  public File getFile() {
    if (pageValid && fsRadio.getSelection())
      return new File(fsPathText.getText().trim());
    if (pageValid && wsRadio.getSelection()) {
      final String filename= wsPathText.getText().trim();
      IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
      final IFile file = root.getFile(new Path(filename));
      return file.getLocation().toFile();
    }
    return null;
  }
}
TOP

Related Classes of org.eclipse.egit.ui.internal.history.LocationPage$WorkspaceDialog

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.