com.aptana.ide.syncing.ui.old.views.SmartSyncDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.aptana.ide.syncing.ui.old.views.SmartSyncDialog.java

Source

/**
 * 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.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(StringUtil.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(StringUtil.format(DELETED_LABEL, deleted));
        skippedLabel.setText(StringUtil.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();
    }

}