Java tutorial
/******************************************************************************* * Copyright (c) 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: * Greg Watson - Initial API and implementation * John Eblen - Modified to work also as a widget for conversion wizards *******************************************************************************/ package org.eclipse.ptp.rdt.sync.ui.widgets; import java.io.File; import java.net.URI; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.window.Window; import org.eclipse.ptp.internal.rdt.sync.ui.RDTSyncUIPlugin; import org.eclipse.ptp.internal.rdt.sync.ui.SynchronizeParticipantRegistry; import org.eclipse.ptp.internal.rdt.sync.ui.messages.Messages; import org.eclipse.ptp.internal.rdt.sync.ui.preferences.SyncFileFilterDialog; import org.eclipse.ptp.rdt.sync.core.PreferenceSyncFileFilterStorage; import org.eclipse.ptp.rdt.sync.core.AbstractSyncFileFilter; import org.eclipse.ptp.rdt.sync.core.SyncManager; import org.eclipse.ptp.rdt.sync.ui.ISynchronizeParticipant; import org.eclipse.ptp.rdt.sync.ui.ISynchronizeParticipantDescriptor; import org.eclipse.swt.SWT; 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.DirectoryDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; /** * Widget to allow the user to select a local and remote project location. Intended to be used by new sync * project wizards that require this information. * * If title is supplied then the widget will be placed in a group. * * @since 5.0 * */ public class SyncProjectWidget extends Composite { private static final int SIZING_TEXT_FIELD_WIDTH = 250; private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private Text fLocalProjectLocationText; private Button fUseDefaultLocationButton; private Button fLocalBrowseButton; private PreferenceSyncFileFilterStorage fCustomFilter; private ISynchronizeParticipant fSelectedParticipant; private String fMessage; private String fErrorMessage; private int fMessageType; private boolean fIsComplete; private final boolean fHasLocalGroup; private String fProjectName = EMPTY_STRING; /** * Return a widget for wizards that create new sync projects * * @param parent * parent composite * @param style * style or SWT.NONE * @param context * runnable context, or null * @return widget * @since 7.0 */ public static SyncProjectWidget newProjectWidget(Composite parent, int style, IRunnableContext context) { return new SyncProjectWidget(parent, style, context, true); } /** * Return a widget for wizards that convert existing projects to sync projects * * @param parent * parent composite * @param style * style or SWT.NONE * @param context * runnable context, or null * @return widget * @since 7.0 */ public static SyncProjectWidget convertProjectWidget(Composite parent, int style, IRunnableContext context) { return new SyncProjectWidget(parent, style, context, false); } /** * Private constructor. Clients should use provided static factory methods. * * @param parent * parent composite * @param style * style or SWT.NONE * @param context * runnable context, or null * @param isForNewProject * whether widget is for creating a new sync project or converting an existing project to a sync project */ private SyncProjectWidget(Composite parent, int style, IRunnableContext context, boolean isForNewProject) { super(parent, style); GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; setLayout(layout); fHasLocalGroup = isForNewProject; if (isForNewProject) { createLocalGroup(this); } createRemoteGroup(this, context); createFilterGroup(this); } /** * @param parent */ private final void createFilterGroup(Composite parent) { // File filter button final Button filterButton = new Button(parent, SWT.PUSH); filterButton.setText(Messages.SyncProjectWidget_Modify_file_filtering); filterButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); filterButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { PreferenceSyncFileFilterStorage tmpFilter; if (fCustomFilter == null) { tmpFilter = SyncManager.getDefaultFileFilter(); } else { tmpFilter = new PreferenceSyncFileFilterStorage(fCustomFilter); } int filterReturnCode = SyncFileFilterDialog.openBlocking(filterButton.getShell(), tmpFilter); if (filterReturnCode == Window.OK) { fCustomFilter = tmpFilter; } } }); } /** * @param parent */ private final void createLocalGroup(Composite parent) { Group localGroup = new Group(parent, SWT.SHADOW_ETCHED_IN); localGroup.setText(Messages.SyncProjectWidget_Local_directory); localGroup.setLayout(new GridLayout(3, false)); localGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); fUseDefaultLocationButton = new Button(localGroup, SWT.CHECK); fUseDefaultLocationButton.setText(Messages.SyncProjectWidget_Use_default_location); fUseDefaultLocationButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); fUseDefaultLocationButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setLocalProjectLocation(); } }); fUseDefaultLocationButton.setSelection(true); Label label = new Label(localGroup, SWT.NONE); label.setText(Messages.SyncProjectWidget_Local_directory_label); label.setFont(parent.getFont()); fLocalProjectLocationText = new Text(localGroup, SWT.BORDER); GridData locationData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); locationData.widthHint = SIZING_TEXT_FIELD_WIDTH; fLocalProjectLocationText.setLayoutData(locationData); fLocalProjectLocationText.setFont(parent.getFont()); fLocalProjectLocationText.addListener(SWT.Modify, new Listener() { @Override public void handleEvent(Event e) { setPageComplete(validatePage()); notifyListeners(SWT.Modify, e); } }); fLocalProjectLocationText.setEnabled(false); fLocalBrowseButton = new Button(localGroup, SWT.PUSH); fLocalBrowseButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); fLocalBrowseButton.setText(Messages.SyncProjectWidget_Browse); fLocalBrowseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DirectoryDialog dirDialog = new DirectoryDialog(getShell()); dirDialog.setText(Messages.SyncProjectWidget_Select_project_local_directory); String selectedDir = dirDialog.open(); fLocalProjectLocationText.setText(selectedDir); } }); } /** * @param parent * @param context */ private final void createRemoteGroup(Composite parent, IRunnableContext context) { Group remoteGroup = new Group(parent, SWT.SHADOW_ETCHED_IN); remoteGroup.setText(Messages.SyncProjectWidget_Remote_directory); remoteGroup.setLayout(new GridLayout(1, false)); remoteGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); // For now, assume only one provider, to reduce the number of GUI elements. // TODO: Add error handling if there are no providers ISynchronizeParticipantDescriptor[] providers = SynchronizeParticipantRegistry.getDescriptors(); fSelectedParticipant = providers[0].getParticipant(); fSelectedParticipant.createConfigurationArea(remoteGroup, context); // Without this, participant uses the old project name from the last time it was invoked. fSelectedParticipant.setProjectName(EMPTY_STRING); } /** * @return */ public String getSyncConfigName() { return fSelectedParticipant.getSyncConfigName(); } /** * @return */ public AbstractSyncFileFilter getCustomFileFilter() { return fCustomFilter; } /** * @return */ public String getErrorMessage() { setPageComplete(validatePage()); // Necessary to update message when participant changes return fErrorMessage; } /** * @return */ public String getMessage() { setPageComplete(validatePage()); // Necessary to update message when participant changes return fMessage; } /** * @return */ public int getMessageType() { setPageComplete(validatePage()); // Necessary to update message when participant changes return fMessageType; } /** * @return */ public String getProjectLocalLocation() { if (!fHasLocalGroup) { return null; } if (fLocalProjectLocationText == null) { return EMPTY_STRING; } return fLocalProjectLocationText.getText().trim(); } private String getProjectName() { return fProjectName; } /** * @return */ public ISynchronizeParticipant getSynchronizeParticipant() { return fSelectedParticipant; } /** * @return */ public boolean isPageComplete() { return fIsComplete; } /** * */ private void setLocalProjectLocation() { // Build string if default location is indicated. if (fUseDefaultLocationButton.getSelection()) { String name = getProjectName(); if (!name.equals(EMPTY_STRING)) { fLocalProjectLocationText.setText(Platform.getLocation().toOSString() + File.separator + name); } else { fLocalProjectLocationText.setText(Platform.getLocation().toOSString()); } // If user just unchecked default location, erase field contents. } else if (!fLocalProjectLocationText.isEnabled()) { fLocalProjectLocationText.setText(EMPTY_STRING); } // These two values should never match. fLocalProjectLocationText.setEnabled(!fUseDefaultLocationButton.getSelection()); } /** * @param complete */ private void setPageComplete(boolean complete) { fIsComplete = complete; } public void setProjectName(String name) { fProjectName = name; if (fHasLocalGroup) { setLocalProjectLocation(); } if (fSelectedParticipant != null) { fSelectedParticipant.setProjectName(name); } } /** * @return */ public boolean useDefaults() { if (!fHasLocalGroup) { return false; } return fUseDefaultLocationButton.getSelection(); } /** * @return */ private boolean validateLocalLocation() { if (getProjectName().equals(EMPTY_STRING)) { fErrorMessage = Messages.SyncProjectWidget_Project_name_must_be_specified; return false; } IProject handle = ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName()); URI location = URIUtil.toURI(fLocalProjectLocationText.getText()); // Check if project exists if (handle.exists()) { fErrorMessage = Messages.SyncProjectWidget_Project_already_exists; return false; } // Validate location according to built-in rules if (!fUseDefaultLocationButton.getSelection()) { IStatus locationStatus = ResourcesPlugin.getWorkspace().validateProjectLocationURI(handle, location); if (!locationStatus.isOK()) { fErrorMessage = locationStatus.getMessage(); return false; } } // Check if location is an existing file or directory try { IFileStore fs = EFS.getStore(location); IFileInfo f = fs.fetchInfo(); if (f.exists()) { if (f.isDirectory()) { fMessage = Messages.SyncProjectWidget_Directory_already_exists; fMessageType = IMessageProvider.WARNING; } else { fErrorMessage = Messages.SyncProjectWidget_9; return false; } } } catch (CoreException e) { RDTSyncUIPlugin.log(e.getStatus()); } return true; } /** * @return */ private boolean validatePage() { fMessage = null; fMessageType = IMessageProvider.NONE; fErrorMessage = null; if (fHasLocalGroup) { return (validateLocalLocation() && validateRemoteLocation()); } else { return validateRemoteLocation(); } } /** * @return */ private boolean validateRemoteLocation() { fErrorMessage = fSelectedParticipant.getErrorMessage(); return fSelectedParticipant.getErrorMessage() == null && fSelectedParticipant.isConfigComplete(); } }