/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.syncing.ui.old.views;
import java.io.File;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
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.Group;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import org.eclipse.ui.progress.UIJob;
import com.aptana.core.io.efs.EFSUtils;
import com.aptana.core.logging.IdeLog;
import com.aptana.core.util.EclipseUtil;
import com.aptana.core.util.FileUtil;
import com.aptana.core.util.StringUtil;
import com.aptana.ide.core.io.ConnectionPointType;
import com.aptana.ide.core.io.CoreIOPlugin;
import com.aptana.ide.core.io.IConnectionPoint;
import com.aptana.ide.core.io.WorkspaceConnectionPoint;
import com.aptana.ide.core.io.preferences.PermissionDirection;
import com.aptana.ide.core.io.preferences.PreferenceUtils;
import com.aptana.ide.syncing.core.old.ConnectionPointSyncPair;
import com.aptana.ide.syncing.core.old.ILogger;
import com.aptana.ide.syncing.core.old.ISyncEventHandler;
import com.aptana.ide.syncing.core.old.ISyncResource;
import com.aptana.ide.syncing.core.old.SyncFile;
import com.aptana.ide.syncing.core.old.SyncFolder;
import com.aptana.ide.syncing.core.old.SyncJob;
import com.aptana.ide.syncing.core.old.SyncModelBuilder;
import com.aptana.ide.syncing.core.old.SyncState;
import com.aptana.ide.syncing.core.old.Synchronizer;
import com.aptana.ide.syncing.core.old.VirtualFileSyncPair;
import com.aptana.ide.syncing.core.old.handlers.SyncEventHandlerAdapterWithProgressMonitor;
import com.aptana.ide.syncing.ui.SyncingUIPlugin;
import com.aptana.ide.syncing.ui.internal.SyncUtils;
import com.aptana.ide.syncing.ui.old.SyncingConsole;
import com.aptana.ide.syncing.ui.preferences.IPreferenceConstants;
import com.aptana.ide.ui.io.Utils;
import com.aptana.ide.ui.io.navigator.RemoteNavigatorView;
import com.aptana.ui.UIPlugin;
import com.aptana.ui.ftp.preferences.UpdatePermissionsComposite;
import com.aptana.ui.util.SWTUtils;
import com.aptana.ui.util.UIUtils;
import com.aptana.ui.widgets.SearchComposite;
/**
* @author Kevin Sawicki (ksawicki@aptana.com)
* @author Michael Xia (mxia@aptana.com)
*/
@SuppressWarnings("deprecation")
public class SmartSyncDialog extends TitleAreaDialog implements SelectionListener, ModifyListener,
DirectionToolBar.Client, OptionsToolBar.Client, SyncJob.Client, SearchComposite.Client
{
private static final String ICON = "icons/full/elcl16/arrow_up_down.png"; //$NON-NLS-1$
private static final String ICON_UPDATE = "icons/full/obj16/sync.png"; //$NON-NLS-1$
private static final String ICON_SKIP = "icons/full/obj16/skip.png"; //$NON-NLS-1$
private static final String ICON_DELETE = "icons/full/obj16/delete.png"; //$NON-NLS-1$
private static final String IMAGE_LOCAL_SITE = "icons/full/wizban/local_site.png"; //$NON-NLS-1$
private static final String IMAGE_REMOTE_SITE = "icons/full/wizban/remote_site.png"; //$NON-NLS-1$
private static final String CLOSE_ICON = "icons/full/elcl16/close.png"; //$NON-NLS-1$
/**
* Key to store the dialog settings for the initial directory to open when exporting themes (saves last directory).
*/
private static final String LOG_EXPORT_DIRECTORY = "logExportDirectory"; //$NON-NLS-1$
private static final String CLOSE_WHEN_DONE = "com.aptana.ide.syncing.views.CLOSE_WHEN_DONE"; //$NON-NLS-1$
private static final String COMPARE_IN_BACKGROUND = IPreferenceConstants.COMPARE_IN_BACKGROUND;
private static final String USE_CRC = IPreferenceConstants.USE_CRC;
private static final String SKIPPED_LABEL = Messages.SmartSyncDialog_NumFilesToSkip;
private static final String UPDATED_LABEL = Messages.SmartSyncDialog_NumFilesToUpdate;
private static final String DELETED_LABEL = Messages.SmartSyncDialog_NumFilesToDelete;
private static final String SYNC_LABEL = Messages.SmartSyncDialog_Comparing;
private Composite dialogArea;
private Label updatedLabel;
private Label skippedLabel;
private Label deletedLabel;
private Font boldFont;
private SmartSyncViewer syncViewer;
private Button startSync;
private Button cancel;
private Button closeWhenDone;
private Button deleteRemoteFiles;
private Button deleteLocalFiles;
private Button useCrc;
private Button syncInBackground;
private UpdatePermissionsComposite uploadPermComposite;
private UpdatePermissionsComposite downloadPermComposite;
private Composite loadingComp;
private Label loadingLabel;
private DirectionToolBar directionBar;
private OptionsToolBar optionsBar;
private SyncFolder root;
private String end1;
private String end2;
private Synchronizer syncer;
private IFileStore source;
private IFileStore dest;
private IConnectionPoint sourceConnectionPoint;
private IConnectionPoint destConnectionPoint;
private ISyncEventHandler handler;
private boolean compareInBackground;
private Composite swappable;
private Composite errorComp;
private Label errorLabel;
private Link retryLink;
private Composite synced;
private Label syncedIcon;
private Label syncedText;
private SyncJob syncJob;
private int skipped;
private Job buildSmartSync;
private IFileStore[] sourceFilesToBeSynced;
private IFileStore[] destFilesToBeSynced;
private Image titleImage;
private Button left_arrow;
private Button right_arrow;
private Label sync_label;
private GridData filterLayoutData;
private CLabel filterLabel;
private Composite filterComp;
private ViewerFilter viewerFilter;
private String searchText;
private Button saveLog;
private Pattern searchPattern;
private SearchComposite searchComposite;
/**
* Creates a new sync dialog.
*
* @param parent
* the parent shell
* @param file1
* the first file element
* @param file2
* the second file element
* @param end1
* the first end point
* @param end2
* the second end point
*/
public SmartSyncDialog(Shell parent, IConnectionPoint sourceManager, IConnectionPoint destManager,
IFileStore source, IFileStore dest, String end1, String end2)
{
super(parent);
sourceConnectionPoint = sourceManager;
destConnectionPoint = destManager;
setShellStyle(getDefaultOrientation() | SWT.RESIZE | SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
this.source = source;
this.dest = dest;
this.end1 = end1;
this.end2 = end2;
this.compareInBackground = getCoreUIPreferenceStore().getBoolean(COMPARE_IN_BACKGROUND);
this.syncer = new Synchronizer(getCoreUIPreferenceStore().getBoolean(USE_CRC), 1000);
if (source != null)
{
this.syncer.setClientFileManager(sourceManager);
this.syncer.setClientFileRoot(source);
}
if (dest != null)
{
this.syncer.setServerFileManager(destManager);
this.syncer.setServerFileRoot(dest);
}
this.syncer.setLogger(new ILogger()
{
public void logWarning(String message, Throwable th)
{
SyncingConsole.println(message);
}
public void logInfo(String message, Throwable th)
{
SyncingConsole.println(message);
}
public void logError(String message, Throwable th)
{
SyncingConsole.println(message);
}
});
}
/**
* Creates a new sync dialog on a list of selected files.
*
* @param parent
* the parent shell
* @param conf
* the file manager pair
* @param sourceFilesToBeSynced
* the selected files to be synced
* @throws CoreException
* @throws CoreException
*/
public SmartSyncDialog(Shell parent, ConnectionPointSyncPair conf, IFileStore[] sourceFilesToBeSynced,
IFileStore[] destFilesToBeSynced) throws CoreException
{
this(parent, conf.getSourceFileManager(), conf.getDestinationFileManager(), conf.getSourceFileManager()
.getRoot(), conf.getDestinationFileManager().getRoot(), conf.getSourceFileManager().getName(), conf
.getDestinationFileManager().getName());
this.syncer.setClientFileManager(conf.getSourceFileManager());
this.syncer.setServerFileManager(conf.getDestinationFileManager());
sourceConnectionPoint = conf.getSourceFileManager();
destConnectionPoint = conf.getDestinationFileManager();
this.syncer.setClientFileRoot(sourceConnectionPoint.getRoot());
this.syncer.setServerFileRoot(destConnectionPoint.getRoot());
if (sourceFilesToBeSynced == null || sourceFilesToBeSynced.length == 0)
{
this.sourceFilesToBeSynced = null;
}
else
{
this.sourceFilesToBeSynced = sourceFilesToBeSynced;
if (sourceFilesToBeSynced.length == 1)
{
IPath path = EFSUtils.getRelativePath(sourceConnectionPoint, sourceFilesToBeSynced[0]);
if (path == null || Path.EMPTY.equals(path))
{
// the selection is from the project level, so we are doing a full sync
this.sourceFilesToBeSynced = null;
}
else
{
end1 = MessageFormat.format("{0} ({1})", end1, path); //$NON-NLS-1$
if (destFilesToBeSynced == null || destFilesToBeSynced.length == 0)
{
// checks if the path exists on remote also
IFileStore fileStore = destConnectionPoint.getRoot().getFileStore(path);
if (Utils.exists(fileStore))
{
this.destFilesToBeSynced = new IFileStore[] { fileStore };
return;
}
}
}
}
}
if (destFilesToBeSynced == null || destFilesToBeSynced.length == 0)
{
this.destFilesToBeSynced = null;
}
else
{
this.destFilesToBeSynced = destFilesToBeSynced;
if (destFilesToBeSynced.length == 1)
{
IPath path = EFSUtils.getRelativePath(destConnectionPoint, destFilesToBeSynced[0]);
if (path == null || Path.EMPTY.equals(path))
{
// can't find the path
this.destFilesToBeSynced = null;
}
else
{
end2 = MessageFormat.format("{0} ({1})", end2, path); //$NON-NLS-1$
}
}
}
}
private void disconnectAndClose()
{
// disconnects explicitly upon closing if the sync is completed
Job disconnectJob = new Job("disconnect the sync file manager") //$NON-NLS-1$
{
@Override
protected IStatus run(IProgressMonitor monitor)
{
if (buildSmartSync != null)
{
if (buildSmartSync.getResult() == null)
{
buildSmartSync.cancel();
}
try
{
buildSmartSync.join();
}
catch (InterruptedException e)
{
}
}
if (syncJob != null)
{
if (syncJob.getResult() == null)
{
syncJob.cancel();
}
try
{
syncJob.join();
}
catch (InterruptedException e)
{
}
}
syncer.disconnect();
return Status.OK_STATUS;
}
};
disconnectJob.setPriority(Job.INTERACTIVE);
try
{
disconnectJob.setSystem(false);
}
catch (IllegalStateException ise)
{
// ignore
}
disconnectJob.schedule();
close();
}
/**
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
protected void configureShell(Shell newShell)
{
super.configureShell(newShell);
newShell.setText(Messages.SmartSyncDialog_Title);
newShell.setImage(SyncingUIPlugin.getImage(ICON));
}
private Composite createDirectionOptions(Composite parent)
{
Composite main = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(3, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
main.setLayout(layout);
main.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
optionsBar = new OptionsToolBar(main, this);
optionsBar.setPresentationType(getPresentationTypePref());
optionsBar.setShowDatesSelected(getShowModificationTimePref());
optionsBar.setEnabled(false);
directionBar = new DirectionToolBar(main, this, end1, end2);
directionBar.setSelection(getDirectionPref());
directionBar.setEnabled(false);
GridData gridData = new GridData(SWT.END, SWT.CENTER, true, false);
directionBar.getControl().setLayoutData(gridData);
return main;
}
private Composite createHeader(Composite parent)
{
Composite top = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
top.setLayout(layout);
top.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
Composite description = new Composite(top, SWT.NONE);
layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.verticalSpacing = 0;
description.setLayout(layout);
description.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Label descriptionLabel = new Label(description, SWT.LEFT);
FontData[] data = SWTUtils.resizeFont(top.getFont(), 4);
for (int i = 0; i < data.length; i++)
{
data[i].setStyle(SWT.BOLD);
}
final Font headerFont = new Font(top.getDisplay(), data);
descriptionLabel.setFont(headerFont);
descriptionLabel.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
headerFont.dispose();
}
});
Composite endpoints = new Composite(description, SWT.NONE);
layout = new GridLayout(3, true);
layout.marginHeight = 0;
layout.marginWidth = 10;
layout.verticalSpacing = 0;
endpoints.setLayout(layout);
endpoints.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
Label local_site = new Label(endpoints, SWT.VERTICAL);
local_site.setImage(SyncingUIPlugin.getImage(IMAGE_LOCAL_SITE));
GridData gridData = new GridData(SWT.CENTER, SWT.CENTER, false, true);
local_site.setLayoutData(gridData);
Composite directions = new Composite(endpoints, SWT.NONE);
layout = new GridLayout(2, false);
layout.marginWidth = 0;
layout.marginTop = 0;
directions.setLayout(layout);
gridData = new GridData(SWT.CENTER, SWT.CENTER, false, true);
directions.setLayoutData(gridData);
left_arrow = new Button(directions, SWT.TOGGLE);
left_arrow.setImage(SyncingUIPlugin.getImage("icons/full/wizban/sync_arrow_left.png")); //$NON-NLS-1$
gridData = new GridData(SWT.RIGHT, SWT.CENTER, false, true);
left_arrow.setLayoutData(gridData);
left_arrow.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
if (!left_arrow.getSelection())
{
directionBar.setSelection(DirectionToolBar.UPLOAD);
}
else if (right_arrow.getSelection())
{
directionBar.setSelection(DirectionToolBar.BOTH);
}
else
{
directionBar.setSelection(DirectionToolBar.DOWNLOAD);
}
updateSyncArrows(directionBar.getSelection());
load(false);
}
});
right_arrow = new Button(directions, SWT.TOGGLE);
right_arrow.setImage(SyncingUIPlugin.getImage("icons/full/wizban/sync_arrow_right.png")); //$NON-NLS-1$
gridData = new GridData(SWT.LEFT, SWT.CENTER, false, true);
right_arrow.setLayoutData(gridData);
right_arrow.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
if (!right_arrow.getSelection())
{
directionBar.setSelection(DirectionToolBar.DOWNLOAD);
}
else if (left_arrow.getSelection())
{
directionBar.setSelection(DirectionToolBar.BOTH);
}
else
{
directionBar.setSelection(DirectionToolBar.UPLOAD);
}
updateSyncArrows(directionBar.getSelection());
load(false);
}
});
Label remote_site = new Label(endpoints, SWT.VERTICAL | SWT.CENTER);
remote_site.setImage(SyncingUIPlugin.getImage(IMAGE_REMOTE_SITE));
gridData = new GridData(SWT.CENTER, SWT.CENTER, false, true);
remote_site.setLayoutData(gridData);
if (this.sourceFilesToBeSynced == null || this.sourceFilesToBeSynced.length <= 1)
{
Label end1Label = new Label(endpoints, SWT.CENTER);
end1Label.setText(FileUtil.compressPath(source.toString(), 30));
end1Label.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
}
else
{
// multiple files/folders are selected; adds a custom label
Composite end1Comp = new Composite(endpoints, SWT.NONE);
layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
end1Comp.setLayout(layout);
end1Comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
Label end1Label = new Label(end1Comp, SWT.CENTER);
end1Label.setText(FileUtil.compressPath(source.toString(), 30));
end1Label.setLayoutData(new GridData(SWT.CENTER, SWT.HORIZONTAL, false, false));
final Label end1Extra = new Label(end1Comp, SWT.NONE);
end1Extra.setText(Messages.SmartSyncDialog_LBL_MultipleFiles);
end1Extra.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
// uses a custom tooltip
end1Extra.setToolTipText(null);
new LabelToolTip(end1Extra, sourceConnectionPoint, sourceFilesToBeSynced);
}
sync_label = new Label(endpoints, SWT.VERTICAL | SWT.CENTER);
gridData = new GridData(SWT.CENTER, SWT.CENTER, false, true);
gridData.widthHint = 150;
sync_label.setLayoutData(gridData);
sync_label.setText(StringUtil.EMPTY);
if (destFilesToBeSynced == null || destFilesToBeSynced.length <= 1)
{
Label end2Label = new Label(endpoints, SWT.CENTER);
end2Label.setText(FileUtil.compressPath(dest.toString(), 30));
end2Label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
else
{
// multiple files/folders are selected; adds a custom label
Composite end2Comp = new Composite(endpoints, SWT.NONE);
end2Comp.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).create());
end2Comp.setLayoutData(GridDataFactory.fillDefaults().create());
Label end2Label = new Label(end2Comp, SWT.CENTER);
end2Label.setText(FileUtil.compressPath(dest.toString(), 30));
end2Label.setLayoutData(GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.CENTER).create());
Label end2Extra = new Label(end2Comp, SWT.NONE);
end2Extra.setText(Messages.SmartSyncDialog_LBL_MultipleFiles);
end2Extra.setLayoutData(GridDataFactory.swtDefaults().grab(true, false).create());
// uses a custom tooltip
end2Extra.setToolTipText(null);
new LabelToolTip(end2Extra, destConnectionPoint, destFilesToBeSynced);
}
Label shadow_sep_h = new Label(endpoints, SWT.SEPARATOR | SWT.SHADOW_IN | SWT.HORIZONTAL);
gridData = new GridData(SWT.FILL, SWT.CENTER, false, true);
gridData.horizontalSpan = 3;
gridData.verticalIndent = 15;
shadow_sep_h.setLayoutData(gridData);
Composite status = new Composite(description, SWT.NONE);
layout = new GridLayout(7, false);
layout.marginWidth = 40;
layout.marginTop = 12;
status.setLayout(layout);
status.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Label updatedSymbol = new Label(status, SWT.VERTICAL);
updatedSymbol.setImage(SyncingUIPlugin.getImage(ICON_UPDATE));
updatedLabel = new Label(status, SWT.LEFT);
updatedLabel.setText(UPDATED_LABEL);
Label skippedSymbol = new Label(status, SWT.VERTICAL);
skippedSymbol.setImage(SyncingUIPlugin.getImage(ICON_SKIP));
skippedLabel = new Label(status, SWT.LEFT);
skippedLabel.setText(SKIPPED_LABEL);
Label deletedSymbol = new Label(status, SWT.VERTICAL);
deletedSymbol.setImage(SyncingUIPlugin.getImage(ICON_DELETE));
deletedLabel = new Label(status, SWT.LEFT);
deletedLabel.setText(DELETED_LABEL);
searchComposite = createSearchComposite(status);
filterComp = createFilterComposite(status);
return top;
}
private SearchComposite createSearchComposite(Composite myComposite)
{
SearchComposite search = new SearchComposite(myComposite, this);
search.setSearchOnEnter(false);
search.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
search.setInitialText(Messages.SmartSyncDialog_searchText);
return search;
}
private Composite createFilterComposite(final Composite myComposite)
{
Composite filter = new Composite(myComposite, SWT.NONE);
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = 2;
gridLayout.marginHeight = 0;
gridLayout.marginBottom = 2;
filter.setLayout(gridLayout);
filterLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
filterLayoutData.exclude = true;
filter.setLayoutData(filterLayoutData);
filterLabel = new CLabel(filter, SWT.LEFT);
filterLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
ToolBar toolBar = new ToolBar(filter, SWT.FLAT);
toolBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH);
toolItem.setImage(SyncingUIPlugin.getImage(CLOSE_ICON));
toolItem.addSelectionListener(new SelectionListener()
{
public void widgetSelected(SelectionEvent e)
{
removeFilter();
}
public void widgetDefaultSelected(SelectionEvent e)
{
}
});
return filter;
}
protected void hideFilterLable()
{
filterLayoutData.exclude = true;
filterComp.setVisible(false);
filterComp.getParent().layout();
}
protected void showFilterLabel(Image image, String text)
{
filterLabel.setImage(image);
filterLabel.setText(text);
filterLayoutData.exclude = false;
filterComp.setVisible(true);
filterComp.getParent().layout();
}
protected void removeFilter()
{
hideFilterLable();
}
private Composite createDeleteOptions(Composite parent)
{
Composite deletes = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 8;
layout.marginWidth = 8;
deletes.setLayout(layout);
deletes.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
deleteLocalFiles = new Button(deletes, SWT.CHECK);
deleteLocalFiles.setText(Messages.SmartSyncDialog_DeleteExtra + "'" + end1 + "'"); //$NON-NLS-1$ //$NON-NLS-2$
deleteLocalFiles.setToolTipText(Messages.SmartSyncDialog_DeleteExtraTooltip + end1 + "'"); //$NON-NLS-1$
deleteLocalFiles.setSelection(getDeleteLocalPreference());
deleteLocalFiles.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
deleteLocalFiles.addSelectionListener(this);
deleteRemoteFiles = new Button(deletes, SWT.CHECK);
deleteRemoteFiles.setText(Messages.SmartSyncDialog_DeleteExtra + "'" + end2 + "'"); //$NON-NLS-1$ //$NON-NLS-2$
deleteRemoteFiles.setToolTipText(Messages.SmartSyncDialog_DeleteExtraTooltip + "'" + end2 + "'"); //$NON-NLS-1$ //$NON-NLS-2$
deleteRemoteFiles.setSelection(getDeleteRemotePreference());
deleteRemoteFiles.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
deleteRemoteFiles.addSelectionListener(this);
closeWhenDone = new Button(deletes, SWT.CHECK);
closeWhenDone.setText(Messages.SmartSyncDialog_CloseWhenDone);
closeWhenDone.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
closeWhenDone.setSelection(getSyncingPreferenceStore().getBoolean(CLOSE_WHEN_DONE));
closeWhenDone.addSelectionListener(this);
return deletes;
}
private Composite createFooter(Composite parent)
{
Composite footer = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
footer.setLayout(layout);
footer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
createDeleteOptions(footer);
createDirectionOptions(footer);
return footer;
}
private Composite createAdvancedSection(Composite parent)
{
final Composite advanced = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 8;
advanced.setLayout(layout);
advanced.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
final Cursor hand = new Cursor(advanced.getDisplay(), SWT.CURSOR_HAND);
final Font boldFont = new Font(advanced.getDisplay(), SWTUtils.boldFont(advanced.getFont()));
advanced.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
if (hand != null && !hand.isDisposed())
{
hand.dispose();
}
if (boldFont != null && !boldFont.isDisposed())
{
boldFont.dispose();
}
}
});
final Label advancedIcon = new Label(advanced, SWT.LEFT);
advancedIcon.setImage(SyncingUIPlugin.getImage("icons/full/obj16/maximize.png")); //$NON-NLS-1$
advancedIcon.setCursor(hand);
advancedIcon.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
Label advancedLabel = new Label(advanced, SWT.LEFT);
advancedLabel.setText(Messages.SmartSyncDialog_AdvancedOptions);
advancedLabel.setCursor(hand);
advancedLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
advancedLabel.setFont(boldFont);
final Composite advancedOptions = new Composite(advanced, SWT.NONE);
layout = new GridLayout();
layout.marginLeft = 15;
advancedOptions.setLayout(layout);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
gridData.horizontalSpan = 2;
gridData.exclude = true;
advancedOptions.setLayoutData(gridData);
advancedOptions.setVisible(false);
MouseAdapter expander = new MouseAdapter()
{
public void mouseDown(MouseEvent e)
{
if (advancedOptions.isVisible())
{
advancedOptions.setVisible(false);
advancedIcon.setImage(SyncingUIPlugin.getImage("icons/full/obj16/maximize.png")); //$NON-NLS-1$
((GridData) advancedOptions.getLayoutData()).exclude = true;
}
else
{
advancedOptions.setVisible(true);
advancedIcon.setImage(SyncingUIPlugin.getImage("icons/full/obj16/minimize.png")); //$NON-NLS-1$
((GridData) advancedOptions.getLayoutData()).exclude = false;
}
dialogArea.layout(true, true);
}
};
advancedIcon.addMouseListener(expander);
advancedLabel.addMouseListener(expander);
useCrc = new Button(advancedOptions, SWT.CHECK);
useCrc.setText(Messages.SmartSyncDialog_UseCrc);
useCrc.setSelection(getCoreUIPreferenceStore().getBoolean(USE_CRC));
useCrc.addSelectionListener(this);
syncInBackground = new Button(advancedOptions, SWT.CHECK);
syncInBackground.setText(Messages.SmartSyncDialog_SyncInBackground);
syncInBackground.setSelection(getCoreUIPreferenceStore().getBoolean(COMPARE_IN_BACKGROUND));
syncInBackground.addSelectionListener(this);
Group group = new Group(advancedOptions, SWT.NONE);
group.setText(Messages.SmartSyncDialog_LBL_PermforUploads);
group.setLayout(GridLayoutFactory.fillDefaults().create());
group.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
uploadPermComposite = new UpdatePermissionsComposite(group, PermissionDirection.UPLOAD);
uploadPermComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
group = new Group(advancedOptions, SWT.NONE);
group.setText(Messages.SmartSyncDialog_LBL_PermForDownloads);
group.setLayout(GridLayoutFactory.fillDefaults().create());
group.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
downloadPermComposite = new UpdatePermissionsComposite(group, PermissionDirection.DOWNLOAD);
downloadPermComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
return advanced;
}
private Composite createMainSection(Composite parent)
{
Composite main = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
main.setLayout(layout);
main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
swappable = createTable(main);
createFooter(main);
return main;
}
private Composite createErrorSection(Composite parent)
{
Composite main = new Composite(parent, SWT.NONE);
main.setLayout(new GridLayout());
main.setBackgroundMode(SWT.INHERIT_DEFAULT);
// main.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
GridData gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
gridData.exclude = true;
main.setLayoutData(gridData);
errorLabel = new Label(main, SWT.CENTER | SWT.WRAP);
final Font font = new Font(main.getDisplay(), "Arial", 12, SWT.NONE); //$NON-NLS-1$
errorLabel.setFont(font);
errorLabel.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
font.dispose();
}
});
errorLabel.setForeground(main.getDisplay().getSystemColor(SWT.COLOR_GRAY));
errorLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
retryLink = new Link(main, SWT.NONE);
retryLink.setText("<a>" + Messages.SmartSyncDialog_Retry + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
retryLink.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, true));
retryLink.addSelectionListener(this);
main.setVisible(false);
return main;
}
private void updateStatLabels()
{
int deleted = 0;
int updated = 0;
int skipped = 0;
int selection = directionBar.getSelection();
ISyncResource[] resources = syncViewer.getCurrentResources();
for (ISyncResource resource : resources)
{
if (resource.isSkipped())
{
skipped++;
}
else if ((selection == DirectionToolBar.BOTH || selection == DirectionToolBar.DOWNLOAD)
&& deleteLocalFiles.getSelection() && resource.getSyncState() == SyncState.ClientItemOnly)
{
deleted++;
}
else if ((selection == DirectionToolBar.BOTH || selection == DirectionToolBar.UPLOAD)
&& deleteRemoteFiles.getSelection() && resource.getSyncState() == SyncState.ServerItemOnly)
{
deleted++;
}
else
{
if (resource.getPair() != null)
{
updated++;
}
}
}
updatedLabel.setText(MessageFormat.format(UPDATED_LABEL, updated));
if (deleted == 0)
{
deletedLabel.setFont(updatedLabel.getFont());
deletedLabel.setForeground(null);
}
else
{
// makes the delete label bold and red to make user aware there are
// going to be files deleted
if (boldFont == null)
{
FontData[] data = SWTUtils.boldFont(deletedLabel.getFont());
boldFont = new Font(deletedLabel.getDisplay(), data);
deletedLabel.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
boldFont.dispose();
}
});
}
deletedLabel.setFont(boldFont);
deletedLabel.setForeground(deletedLabel.getDisplay().getSystemColor(SWT.COLOR_RED));
}
deletedLabel.setText(MessageFormat.format(DELETED_LABEL, deleted));
skippedLabel.setText(MessageFormat.format(SKIPPED_LABEL, skipped));
this.skipped = skipped;
skippedLabel.getParent().layout(true, true);
startSync.setEnabled(deleted + updated > 0);
}
private void updateSyncArrows(int selection)
{
switch (selection)
{
case DirectionToolBar.BOTH:
left_arrow.setSelection(true);
right_arrow.setSelection(true);
sync_label.setText(Messages.SmartSyncDialog_BothDirection);
break;
case DirectionToolBar.UPLOAD:
case DirectionToolBar.FORCE_UPLOAD:
left_arrow.setSelection(false);
right_arrow.setSelection(true);
sync_label.setText(Messages.SmartSyncDialog_Upload);
break;
case DirectionToolBar.FORCE_DOWNLOAD:
case DirectionToolBar.DOWNLOAD:
left_arrow.setSelection(true);
right_arrow.setSelection(false);
sync_label.setText(Messages.SmartSyncDialog_Download);
break;
}
}
private Composite createTable(Composite parent)
{
Composite main = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.horizontalSpacing = 0;
main.setLayout(layout);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.heightHint = 400;
main.setLayoutData(gridData);
// main.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
syncViewer = new SmartSyncViewer(main, end1, end2);
syncViewer.setPresentationType(getPresentationTypePref());
syncViewer.setShowDatesSelected(getShowModificationTimePref());
syncViewer.setCellModifier(new ICellModifier()
{
public void modify(Object element, String property, Object value)
{
// Only allow checking of skipped box when sync isn't
// running
if (startSync.getText().equals(Messages.SmartSyncDialog_StartSync))
{
if (element instanceof Item)
{
element = ((Item) element).getData();
}
ISyncResource resource = (ISyncResource) element;
resource.setSkipped(Boolean.parseBoolean(value.toString()));
syncViewer.update(element, null);
if (resource instanceof SyncFolder)
{
// refreshes the children of the folder
Collection<ISyncResource> children = ((SyncFolder) resource).getAllChildren();
for (ISyncResource child : children)
{
syncViewer.update(child, null);
}
}
if (!resource.isSkipped() && resource.getParent() != null)
{
resource.getParent().setSkipped(false, false);
syncViewer.update(resource.getParent(), null);
}
updateStatLabels();
}
}
public Object getValue(Object element, String property)
{
return Boolean.valueOf(((ISyncResource) element).isSkipped());
}
public boolean canModify(Object element, String property)
{
return Messages.SmartSyncDialog_ColumnSkip.equals(property);
}
});
viewerFilter = new ViewerFilter()
{
public boolean select(Viewer viewer, Object parentElement, Object element)
{
if (element instanceof SyncFile || element instanceof SyncFolder)
{
ISyncResource resource = (ISyncResource) element;
if (searchText == null)
{
return true;
}
String path = resource.getPath().toString();
Matcher m = searchPattern.matcher(path);
return m.find();
}
return false;
}
};
syncViewer.addFilter(viewerFilter);
errorComp = createErrorSection(main);
loadingComp = createLoadingSection(main);
synced = createSyncedSection(main);
return main;
}
private Composite createSyncedSection(Composite parent)
{
Composite main = new Composite(parent, SWT.NONE);
main.setLayout(new GridLayout(2, false));
main.setBackgroundMode(SWT.INHERIT_DEFAULT);
// main.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
GridData gridData = new GridData(SWT.CENTER, SWT.CENTER, true, false);
gridData.exclude = true;
main.setLayoutData(gridData);
syncedIcon = new Label(main, SWT.CENTER);
syncedIcon.setImage(SyncingUIPlugin.getImage("icons/full/obj16/synced.png")); //$NON-NLS-1$
syncedIcon.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
syncedText = new Label(main, SWT.CENTER | SWT.WRAP);
final Font font = new Font(main.getDisplay(), "Arial", 12, SWT.NONE); //$NON-NLS-1$
syncedText.setFont(font);
syncedText.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
font.dispose();
}
});
syncedText.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
syncedText.setText(end1 + " and " + end2 + Messages.SmartSyncDialog_InSync); //$NON-NLS-1$
main.setVisible(false);
return main;
}
private Composite createLoadingSection(Composite parent)
{
Composite loadingComp = new Composite(parent, SWT.NONE);
loadingComp.setLayout(new GridLayout());
loadingComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
loadingComp.setBackgroundMode(SWT.INHERIT_DEFAULT);
// loadingComp.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
loadingLabel = new Label(loadingComp, SWT.NONE);
loadingLabel.setText(SYNC_LABEL + "..."); //$NON-NLS-1$
loadingLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
ProgressBar loadingBar = new ProgressBar(loadingComp, SWT.SMOOTH | SWT.INDETERMINATE);
loadingBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
return loadingComp;
}
protected void createButtonsForButtonBar(Composite parent)
{
// create OK and Cancel buttons by default
startSync = createButton(parent, IDialogConstants.PROCEED_ID, Messages.SmartSyncDialog_StartSync, true);
GridData gridData = new GridData(SWT.FILL, SWT.END, false, false);
GC gc = new GC(startSync);
// calculates the ideal width
gridData.widthHint = Math.max(gc.stringExtent(Messages.SmartSyncDialog_StartSync).x,
gc.stringExtent(Messages.SmartSyncDialog_RunInBackground).x) + 50;
gc.dispose();
startSync.setLayoutData(gridData);
startSync.addSelectionListener(this);
saveLog = createButton(parent, IDialogConstants.DETAILS_ID, "Save Log...", false); //$NON-NLS-1$
saveLog.addSelectionListener(this);
saveLog.setEnabled(false);
cancel = createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
cancel.addSelectionListener(this);
}
private void setEnabled(boolean enabled)
{
directionBar.setEnabled(enabled);
optionsBar.setEnabled(enabled);
boolean syncEnabled = enabled && syncViewer.getCurrentResources().length > 0;
if (!startSync.isDisposed())
{
startSync.setEnabled(syncEnabled);
}
if (enabled)
{
updateFileButtonsState();
updateSyncArrows(directionBar.getSelection());
}
}
/**
* @see org.eclipse.jface.window.Window#open()
*/
@Override
public int open()
{
setBlockOnOpen(false);
if (!compareInBackground)
{
super.open();
}
load(true);
return OK;
}
private void load(final boolean showSyncedMessage)
{
if (!compareInBackground)
{
setEnabled(false);
GridData data = (GridData) loadingComp.getLayoutData();
data.exclude = false;
loadingComp.setVisible(true);
loadingComp.getParent().layout(true, true);
}
final boolean forceUp = compareInBackground ? false
: (directionBar.getSelection() == DirectionToolBar.FORCE_UPLOAD);
final boolean forceDown = compareInBackground ? false
: (directionBar.getSelection() == DirectionToolBar.FORCE_DOWNLOAD);
if (buildSmartSync != null)
{
// cancels the existing one
buildSmartSync.cancel();
}
buildSmartSync = new Job("Generating Synchronize Status") //$NON-NLS-1$
{
protected IStatus run(final IProgressMonitor monitor)
{
syncer.setEventHandler(new SyncEventHandlerAdapterWithProgressMonitor(monitor)
{
public boolean syncEvent(final VirtualFileSyncPair item, int index, int totalItems,
IProgressMonitor monitor)
{
if (item != null)
{
if (!compareInBackground)
{
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
if (loadingLabel == null || loadingLabel.isDisposed())
{
return;
}
String name = getFilename(item);
if (name != null)
{
loadingLabel.setText(SYNC_LABEL + name);
loadingLabel.getParent().layout(true, true);
}
}
});
}
}
return super.syncEvent(item, index, totalItems, monitor);
}
});
VirtualFileSyncPair[] items = new VirtualFileSyncPair[0];
Exception error = null;
try
{
if (forceUp)
{
IFileStore[] clientFiles = (sourceFilesToBeSynced == null) ? EFSUtils.getFiles(source, true,
false, null) : EFSUtils.getAllFiles(sourceFilesToBeSynced, true, false, monitor);
items = syncer.createSyncItems(clientFiles, new IFileStore[0], monitor);
Map<String, VirtualFileSyncPair> pairs = new HashMap<String, VirtualFileSyncPair>();
for (VirtualFileSyncPair item : items)
{
pairs.put(item.getRelativePath(), item);
}
IFileStore[] serverFiles = EFSUtils.getFiles(dest, true, false, monitor);
VirtualFileSyncPair pair;
for (IFileStore file : serverFiles)
{
pair = pairs.get(EFSUtils.getRelativePath(destConnectionPoint.getRoot(), file, null));
if (pair != null)
{
pair.setDestinationFile(file);
pair.setSyncState(SyncState.ClientItemIsNewer);
}
}
}
else if (forceDown)
{
IFileStore[] serverFiles = (destFilesToBeSynced == null) ? EFSUtils.getFiles(dest, true, false,
null) : SyncUtils.getDownloadFiles(sourceConnectionPoint, destConnectionPoint,
destFilesToBeSynced, false, true, monitor);
items = syncer.createSyncItems(new IFileStore[0], serverFiles, monitor);
Map<String, VirtualFileSyncPair> pairs = new HashMap<String, VirtualFileSyncPair>();
for (VirtualFileSyncPair item : items)
{
pairs.put(item.getRelativePath(), item);
}
IFileStore[] clientFiles = EFSUtils.getFiles(source, true, false, monitor);
VirtualFileSyncPair pair;
for (IFileStore file : clientFiles)
{
pair = pairs.get(Synchronizer.getCanonicalPath(sourceConnectionPoint.getRoot(), file));
if (pair != null)
{
pair.setSourceFile(file);
pair.setSyncState(SyncState.ServerItemIsNewer);
}
}
}
else
{
if (sourceFilesToBeSynced == null && destFilesToBeSynced == null)
{
items = syncer.getSyncItems(sourceConnectionPoint, destConnectionPoint, source, dest,
monitor);
}
else
{
IFileStore[] clientFiles = (sourceFilesToBeSynced == null) ? EFSUtils.getFiles(source,
true, false, null) : EFSUtils.getAllFiles(sourceFilesToBeSynced, true, false,
monitor);
IFileStore[] serverFiles = (destFilesToBeSynced == null) ? EFSUtils.getFiles(dest, true,
false, null) : SyncUtils.getDownloadFiles(sourceConnectionPoint,
destConnectionPoint, destFilesToBeSynced, false, true, monitor);
items = syncer.createSyncItems(clientFiles, serverFiles, monitor);
}
}
}
catch (OperationCanceledException e)
{
return Status.CANCEL_STATUS;
}
catch (Exception e1)
{
IdeLog.logError(SyncingUIPlugin.getDefault(), Messages.SmartSyncDialog_ErrorSmartSync, e1);
error = e1;
}
if (monitor.isCanceled())
{
return Status.CANCEL_STATUS;
}
if (items != null && error == null)
{
// no error
root = SyncModelBuilder.buildSyncFolder(sourceConnectionPoint, destConnectionPoint, items);
UIJob update = new UIJob("Loading Sync") //$NON-NLS-1$
{
public IStatus runInUIThread(IProgressMonitor monitor)
{
if (compareInBackground)
{
SmartSyncDialog.super.open();
}
if (loadingComp != null && !loadingComp.isDisposed())
{
GridData data = (GridData) loadingComp.getLayoutData();
data.exclude = true;
loadingComp.setVisible(false);
data = (GridData) errorComp.getLayoutData();
data.exclude = true;
errorComp.setVisible(false);
syncViewer.setInput(root);
if (syncViewer.getCurrentResources().length > 0)
{
data = (GridData) synced.getLayoutData();
data.grabExcessVerticalSpace = true;
data.exclude = true;
synced.setVisible(false);
data = (GridData) syncViewer.getTree().getLayoutData();
data.exclude = false;
syncViewer.setVisible(true);
setEnabled(true);
startSync.setFocus();
}
else if (showSyncedMessage)
{
data = (GridData) syncViewer.getTree().getLayoutData();
data.exclude = true;
syncViewer.setVisible(false);
data = (GridData) synced.getLayoutData();
data.grabExcessVerticalSpace = true;
data.exclude = false;
synced.setVisible(true);
cancel.setText(Messages.SmartSyncDialog_Close);
setEnabled(true);
syncer.disconnect();
}
else
{
setEnabled(true);
}
swappable.getParent().layout(true, true);
updateStatLabels();
}
return Status.OK_STATUS;
}
};
update.schedule();
}
else
{
final StringBuilder errorMessage = new StringBuilder();
if (error != null)
{
// when it is UnknownHostException, adds some more details in the message
if (error instanceof UnknownHostException)
{
errorMessage.append(MessageFormat.format(Messages.SmartSyncDialog_UnknownHostError, end1,
end2));
}
else
{
errorMessage.append(Messages.SmartSyncDialog_ErrorSync);
errorMessage.append("\n " + Messages.SmartSyncDialog_ErrorMessage + error.getMessage()); //$NON-NLS-1$
}
}
UIJob showError = new UIJob("Showing sync error") //$NON-NLS-1$
{
public IStatus runInUIThread(IProgressMonitor monitor)
{
if (compareInBackground)
{
SmartSyncDialog.super.open();
}
if (loadingComp != null && !loadingComp.isDisposed())
{
GridData data = (GridData) loadingComp.getLayoutData();
data.exclude = true;
loadingComp.setVisible(false);
data = (GridData) syncViewer.getTree().getLayoutData();
data.exclude = true;
syncViewer.setVisible(false);
data = (GridData) errorComp.getLayoutData();
data.exclude = false;
errorComp.setVisible(true);
errorLabel.setText(errorMessage.toString());
swappable.getParent().layout(true, true);
setEnabled(false);
syncer.disconnect();
}
return Status.OK_STATUS;
}
};
showError.schedule();
}
return Status.OK_STATUS;
}
};
buildSmartSync.setPriority(Job.LONG);
try
{
buildSmartSync.setSystem(false);
}
catch (IllegalStateException ise)
{
// ignore
}
buildSmartSync.schedule();
}
protected void dispose()
{
if (titleImage != null)
{
setTitleImage(null);
titleImage.dispose();
titleImage = null;
}
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent)
{
dialogArea = (Composite) super.createDialogArea(parent);
titleImage = SyncingUIPlugin.getImageDescriptor("/icons/full/wizban/sync.png").createImage(); //$NON-NLS-1$
dialogArea.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
dispose();
}
});
setTitleImage(titleImage);
getShell().setText("Synchronize"); //$NON-NLS-1$
setTitle("Synchronize files between two endpoints"); //$NON-NLS-1$
Composite displayArea = new Composite(dialogArea, SWT.NONE);
displayArea.setLayout(new GridLayout());
displayArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
createHeader(displayArea);
createMainSection(displayArea);
createAdvancedSection(displayArea);
syncViewer.setSyncDirection(directionBar.getSelection());
return dialogArea;
}
@Override
protected Control createContents(Composite parent)
{
Control composite = super.createContents(parent);
setEnabled(false);
updateDeleteStates();
if (getShell() != null && getParentShell() != null)
{
SWTUtils.center(getShell(), getParentShell());
}
return composite;
}
/**
* Sets the handler for syncing events.
*
* @param handler
* the handler to set
*/
public void setHandler(ISyncEventHandler handler)
{
this.handler = handler;
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e)
{
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(SelectionEvent)
*/
public void widgetSelected(SelectionEvent e)
{
Object source = e.getSource();
if (source == deleteLocalFiles)
{
saveDeleteLocalPreference(deleteLocalFiles.getSelection());
updateDeleteStates();
}
else if (source == deleteRemoteFiles)
{
saveDeleteRemotePreference(deleteRemoteFiles.getSelection());
updateDeleteStates();
}
else if (source == cancel)
{
cancel();
}
else if (source == closeWhenDone)
{
getSyncingPreferenceStore().setValue(CLOSE_WHEN_DONE, closeWhenDone.getSelection());
}
else if (source == useCrc)
{
getCoreUIPreferenceStore().setValue(USE_CRC, useCrc.getSelection());
}
else if (source == syncInBackground)
{
getCoreUIPreferenceStore().setValue(COMPARE_IN_BACKGROUND, syncInBackground.getSelection());
}
else if (source == retryLink)
{
load(true);
}
else if (source == startSync)
{
savePermissions();
String text = startSync.getText();
if (text.equals(Messages.SmartSyncDialog_StartSync))
{
startSync.setText(Messages.SmartSyncDialog_RunInBackground);
startSync.getParent().layout();
startSync();
}
else if (text.equals(Messages.SmartSyncDialog_RunInBackground))
{
setReturnCode(CANCEL);
close();
}
}
else if (source == saveLog)
{
FileDialog fileDialog = new FileDialog(getShell(), SWT.SAVE);
IDialogSettings editorSettings = SyncingUIPlugin.getDefault().getDialogSettings();
String value = editorSettings.get(LOG_EXPORT_DIRECTORY);
if (value != null)
{
fileDialog.setFilterPath(value);
}
DateFormat fileFormat = new SimpleDateFormat("yyyyMMddHHmmss"); //$NON-NLS-1$
Date d = new Date();
fileDialog.setFileName("Aptana Synchronize Log " + fileFormat.format(d) + ".txt"); //$NON-NLS-1$ //$NON-NLS-2$
String path = fileDialog.open();
if (path == null)
{
return;
}
File logFile = new File(path);
editorSettings.put(LOG_EXPORT_DIRECTORY, logFile.getParent());
SyncExporter exporter = new SyncExporter();
ISyncResource[] resources = syncViewer.getCurrentResources();
exporter.export(logFile, resources);
}
}
private void savePermissions()
{
PreferenceUtils.setUpdatePermissions(uploadPermComposite.getUpdatePermissions(), PermissionDirection.UPLOAD);
PreferenceUtils
.setSpecificPermissions(uploadPermComposite.getSpecificPermissions(), PermissionDirection.UPLOAD);
PreferenceUtils.setFilePermissions(uploadPermComposite.getFilePermissions(), PermissionDirection.UPLOAD);
PreferenceUtils.setFolderPermissions(uploadPermComposite.getFolderPermissions(), PermissionDirection.UPLOAD);
PreferenceUtils
.setUpdatePermissions(downloadPermComposite.getUpdatePermissions(), PermissionDirection.DOWNLOAD);
PreferenceUtils.setSpecificPermissions(downloadPermComposite.getSpecificPermissions(),
PermissionDirection.DOWNLOAD);
PreferenceUtils.setFilePermissions(downloadPermComposite.getFilePermissions(), PermissionDirection.DOWNLOAD);
PreferenceUtils
.setFolderPermissions(downloadPermComposite.getFolderPermissions(), PermissionDirection.DOWNLOAD);
}
/**
* @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
*/
public void modifyText(ModifyEvent e)
{
}
/**
* @see com.aptana.ide.syncing.ui.views.views.DirectionToolBar.Client#selectionChanged(boolean)
*/
public void selectionChanged(int direction, boolean reload)
{
updateFileButtonsState();
updateSyncArrows(directionBar.getSelection());
syncViewer.setSyncDirection(directionBar.getSelection());
saveDirectionPref(direction);
if (reload)
{
load(false);
}
else
{
syncViewer.refreshAndExpandTo(2);
}
}
/**
* @see com.aptana.ide.syncing.ui.views.views.OptionsToolBar.Client#stateChanged(int)
*/
public void stateChanged(int type)
{
syncViewer.setPresentationType(type);
savePresentationTypePref(type);
}
/**
* @see com.aptana.ide.syncing.ui.views.views.OptionsToolBar.Client#showDatesSelected(boolean)
*/
public void showDatesSelected(boolean show)
{
syncViewer.setShowDatesSelected(show);
saveShowModificationTimePref(show);
}
public void syncItem(final VirtualFileSyncPair item)
{
// syncing on a specific item has started
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
ISyncResource resource = root.find(item);
if (resource != null)
{
resource.setTransferState(ISyncResource.SYNCING);
if (dialogArea != null && !dialogArea.isDisposed())
{
syncViewer.showProgress(item);
}
}
}
});
}
public void syncProgress(final VirtualFileSyncPair item, final long bytes)
{
// updates the progress on a specific item
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
ISyncResource resource = root.find(item);
if (resource != null)
{
resource.setTransferredBytes(bytes);
if (dialogArea != null && !dialogArea.isDisposed())
{
syncViewer.update(resource, null);
}
}
}
});
}
public void syncDone(final VirtualFileSyncPair item, boolean allDone)
{
// syncing is completed for a specific item
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
ISyncResource resource = root.find(item);
if (resource != null)
{
resource.setTransferState(ISyncResource.SYNCED);
if (dialogArea != null && !dialogArea.isDisposed())
{
syncViewer.update(resource, null);
syncViewer.reveal(resource);
}
}
}
});
if (allDone)
{
syncJobDone();
}
}
public void syncError(final VirtualFileSyncPair item, boolean allDone)
{
// an error was encountered during syncing
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
ISyncResource resource = root.find(item);
if (resource != null)
{
resource.setTransferState(ISyncResource.ERROR);
if (syncViewer != null && !syncViewer.getTree().isDisposed())
{
syncViewer.update(resource, null);
syncViewer.reveal(resource);
}
}
}
});
if (allDone)
{
syncJobDone();
}
}
private void startSync()
{
// disables the options when sync has started
directionBar.setEnabled(false);
optionsBar.setEnabled(false);
right_arrow.setEnabled(false);
left_arrow.setEnabled(false);
List<VirtualFileSyncPair> pairs = new ArrayList<VirtualFileSyncPair>();
ISyncResource[] resources = syncViewer.getCurrentResources();
for (ISyncResource resource : resources)
{
VirtualFileSyncPair pair = resource.getPair();
if (!resource.isSkipped() && pair != null)
{
pairs.add(pair);
}
}
boolean deleteLocal = deleteLocalFiles.getEnabled() && deleteLocalFiles.getSelection();
boolean deleteRemote = deleteRemoteFiles.getEnabled() && deleteRemoteFiles.getSelection();
deleteRemoteFiles.setEnabled(false);
deleteLocalFiles.setEnabled(false);
int direction = -1;
int selection = directionBar.getSelection();
if (selection == DirectionToolBar.DOWNLOAD || selection == DirectionToolBar.FORCE_DOWNLOAD)
{
direction = SyncJob.DOWNLOAD;
}
else if (selection == DirectionToolBar.UPLOAD || selection == DirectionToolBar.FORCE_UPLOAD)
{
direction = SyncJob.UPLOAD;
}
else if (selection == DirectionToolBar.BOTH)
{
direction = SyncJob.BOTH;
}
if (syncJob != null)
{
// cancels the previous job if exists
syncJob.cancel();
}
syncJob = new SyncJob(syncer, pairs, direction, deleteRemote, deleteLocal, this, MessageFormat.format(
Messages.SmartSyncDialog_Endpoints, end1, end2));
syncJob.schedule();
}
private void syncJobDone()
{
if (handler != null)
{
handler.syncDone(null, null);
}
if (source != null && dest != null)
{
String comment = ""; //firstEdit ? "" : commentStr; //$NON-NLS-1$
SmartSyncEventManager.getManager().fireEvent(syncJob.getCompletedPairs(), sourceConnectionPoint,
destConnectionPoint, comment);
}
UIJob updateEndJob = new UIJob("Updating sync") //$NON-NLS-1$
{
public IStatus runInUIThread(IProgressMonitor monitor)
{
if (closeWhenDone != null && !closeWhenDone.isDisposed())
{
if (closeWhenDone.getSelection())
{
setReturnCode(CANCEL);
disconnectAndClose();
}
else
{
cancel.setText(Messages.SmartSyncDialog_Close);
startSync.setEnabled(false);
int errorCount = syncJob.getErrorCount();
if (errorCount == 0)
{
// completely synced
if (skipped > 0)
{
// adds more words to the success text if there are skipped files
syncedText.setText(end1 + " and " + end2 + Messages.SmartSyncDialog_InSync //$NON-NLS-1$
+ "\n " + Messages.SmartSyncDialog_SkippedFilesInSync); //$NON-NLS-1$
}
}
else
{
GridData data = (GridData) syncedIcon.getLayoutData();
data.exclude = true;
syncedIcon.setVisible(false);
syncedText.setText(errorCount + Messages.SmartSyncDialog_SyncError);
}
GridData data = (GridData) synced.getLayoutData();
data.exclude = false;
synced.setVisible(true);
setEnabled(false);
swappable.layout(true, true);
right_arrow.setEnabled(true);
left_arrow.setEnabled(true);
saveLog.setEnabled(true);
}
}
else
{
// disconnect directly
syncer.disconnect();
}
refresh(monitor);
return Status.OK_STATUS;
}
/**
* Performs post-sync refresh.
*/
private void refresh(IProgressMonitor monitor)
{
IConnectionPoint clientConnection = syncer.getClientFileManager();
if (clientConnection instanceof WorkspaceConnectionPoint)
{
IResource resource = ((WorkspaceConnectionPoint) clientConnection).getResource();
IViewPart viewPart = UIUtils.findView(IPageLayout.ID_PROJECT_EXPLORER);
if (viewPart instanceof CommonNavigator)
{
CommonViewer viewer = ((CommonNavigator) viewPart).getCommonViewer();
viewer.refresh(resource);
}
}
IConnectionPoint serverConnection = syncer.getServerFileManager();
ConnectionPointType type = CoreIOPlugin.getConnectionPointManager().getType(serverConnection);
if (type != null && type.getCategory().isRemote())
{
IViewPart viewPart = UIUtils.findView(RemoteNavigatorView.ID);
if (viewPart instanceof RemoteNavigatorView)
{
RemoteNavigatorView view = (RemoteNavigatorView) viewPart;
view.getCommonViewer().refresh(serverConnection);
}
}
}
};
EclipseUtil.setSystemForJob(updateEndJob);
updateEndJob.schedule();
}
private void updateDeleteStates()
{
syncViewer.setDeleteLocalFiles(deleteLocalFiles.getSelection());
syncViewer.setDeleteRemoteFiles(deleteRemoteFiles.getSelection());
updateStatLabels();
boolean syncEnabled = syncViewer.getCurrentResources().length > 0;
startSync.setEnabled(syncEnabled);
}
private void updateFileButtonsState()
{
int selection = directionBar.getSelection();
switch (selection)
{
case DirectionToolBar.UPLOAD:
deleteLocalFiles.setEnabled(false);
deleteRemoteFiles.setEnabled(true);
break;
case DirectionToolBar.DOWNLOAD:
deleteLocalFiles.setEnabled(true);
deleteRemoteFiles.setEnabled(false);
break;
case DirectionToolBar.FORCE_DOWNLOAD:
case DirectionToolBar.FORCE_UPLOAD:
deleteLocalFiles.setEnabled(false);
deleteRemoteFiles.setEnabled(false);
break;
default:
deleteRemoteFiles.setEnabled(true);
deleteLocalFiles.setEnabled(true);
}
}
private void cancel()
{
if (buildSmartSync != null)
{
buildSmartSync.cancel();
}
if (syncJob != null)
{
syncJob.cancel();
}
disconnectAndClose();
}
private static String getFilename(VirtualFileSyncPair item)
{
if (item.getDestinationFile() != null)
{
return item.getDestinationFile().getName();
}
if (item.getSourceFile() != null)
{
return item.getSourceFile().getName();
}
return null;
}
private static IPreferenceStore getCoreUIPreferenceStore()
{
return UIPlugin.getDefault().getPreferenceStore();
}
private static IPreferenceStore getSyncingPreferenceStore()
{
return SyncingUIPlugin.getDefault().getPreferenceStore();
}
private static int getPresentationTypePref()
{
String viewPref = getSyncingPreferenceStore().getString(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_MODE);
if (com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_TREE.equals(viewPref))
{
return OptionsToolBar.TREE_VIEW;
}
return OptionsToolBar.FLAT_VIEW;
}
private static int getDirectionPref()
{
String directionPref = getSyncingPreferenceStore().getString(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE);
if (com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_BOTH.equals(directionPref))
{
return DirectionToolBar.BOTH;
}
if (com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_UPLOAD.equals(directionPref))
{
return DirectionToolBar.UPLOAD;
}
if (com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_DOWNLOAD.equals(directionPref))
{
return DirectionToolBar.DOWNLOAD;
}
if (com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_FORCE_UPLOAD.equals(directionPref))
{
return DirectionToolBar.FORCE_UPLOAD;
}
return DirectionToolBar.FORCE_DOWNLOAD;
}
private static boolean getDeleteLocalPreference()
{
return getSyncingPreferenceStore().getBoolean(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DELETE_LOCAL_FILES);
}
private static boolean getDeleteRemotePreference()
{
return getSyncingPreferenceStore().getBoolean(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DELETE_REMOTE_FILES);
}
private static boolean getShowModificationTimePref()
{
return getSyncingPreferenceStore().getBoolean(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.SHOW_MODIFICATION_TIME);
}
private static void savePresentationTypePref(int type)
{
IPreferenceStore prefs = getSyncingPreferenceStore();
switch (type)
{
case OptionsToolBar.FLAT_VIEW:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_FLAT);
break;
case OptionsToolBar.TREE_VIEW:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.VIEW_TREE);
break;
}
}
private static void saveDirectionPref(int direction)
{
IPreferenceStore prefs = getSyncingPreferenceStore();
switch (direction)
{
case DirectionToolBar.BOTH:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_BOTH);
break;
case DirectionToolBar.UPLOAD:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_UPLOAD);
break;
case DirectionToolBar.DOWNLOAD:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_DOWNLOAD);
break;
case DirectionToolBar.FORCE_UPLOAD:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_FORCE_UPLOAD);
break;
case DirectionToolBar.FORCE_DOWNLOAD:
prefs.setValue(com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_MODE,
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DIRECTION_FORCE_DOWNLOAD);
}
}
private static void saveDeleteLocalPreference(boolean selected)
{
getSyncingPreferenceStore().setValue(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DELETE_LOCAL_FILES, selected);
}
private static void saveDeleteRemotePreference(boolean selected)
{
getSyncingPreferenceStore().setValue(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.DELETE_REMOTE_FILES, selected);
}
private static void saveShowModificationTimePref(boolean selected)
{
getSyncingPreferenceStore().setValue(
com.aptana.ide.syncing.ui.preferences.IPreferenceConstants.SHOW_MODIFICATION_TIME, selected);
}
/**
* The custom tooltip class for the end point label.
*/
private static class LabelToolTip extends ToolTip
{
private IConnectionPoint connectionPoint;
private IFileStore[] files;
LabelToolTip(Control control, IConnectionPoint connectionPoint, IFileStore[] files)
{
super(control, ToolTip.NO_RECREATE, false);
this.connectionPoint = connectionPoint;
this.files = files;
}
@Override
protected Composite createToolTipContentArea(Event event, Composite parent)
{
Composite contentArea = new Composite(parent, SWT.NONE);
contentArea.setLayout(new GridLayout());
StringBuilder buf = new StringBuilder();
for (IFileStore file : files)
{
buf.append(EFSUtils.getRelativePath(connectionPoint, file, null));
buf.append('\n');
}
Text text;
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
GC gc = new GC(contentArea);
if (gc.textExtent(buf.toString()).y > 200)
{
// uses scrollbar when there are many files
text = new Text(contentArea, SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL);
gridData.heightHint = 200;
}
else
{
text = new Text(contentArea, SWT.MULTI | SWT.READ_ONLY);
}
gc.dispose();
text.setLayoutData(gridData);
text.setText(buf.toString());
return contentArea;
}
}
public void search(String text, boolean isCaseSensitive, boolean isRegularExpression)
{
searchText = text;
searchPattern = searchComposite.createSearchPattern();
syncViewer.refresh();
}
}