org.eclipse.team.svn.ui.composite.PropertiesComposite.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.team.svn.ui.composite.PropertiesComposite.java

Source

/*******************************************************************************
 * Copyright (c) 2005-2008 Polarion Software.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Sergiy Logvin - Initial API and implementation
 *******************************************************************************/

package org.eclipse.team.svn.ui.composite;

import java.io.FileOutputStream;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.team.svn.core.IStateFilter;
import org.eclipse.team.svn.core.connector.SVNProperty;
import org.eclipse.team.svn.core.operation.AbstractActionOperation;
import org.eclipse.team.svn.core.operation.CompositeOperation;
import org.eclipse.team.svn.core.operation.IActionOperation;
import org.eclipse.team.svn.core.operation.IResourcePropertyProvider;
import org.eclipse.team.svn.core.operation.local.RefreshResourcesOperation;
import org.eclipse.team.svn.core.operation.local.property.GetPropertiesOperation;
import org.eclipse.team.svn.core.operation.local.property.RemovePropertiesOperation;
import org.eclipse.team.svn.core.operation.remote.GetRemotePropertiesOperation;
import org.eclipse.team.svn.core.resource.IRepositoryResource;
import org.eclipse.team.svn.core.svnstorage.SVNRemoteStorage;
import org.eclipse.team.svn.core.utility.FileUtility;
import org.eclipse.team.svn.ui.RemoteResourceTransfer;
import org.eclipse.team.svn.ui.RemoteResourceTransferrable;
import org.eclipse.team.svn.ui.SVNTeamUIPlugin;
import org.eclipse.team.svn.ui.SVNUIMessages;
import org.eclipse.team.svn.ui.action.local.SetExternalDefinitionAction;
import org.eclipse.team.svn.ui.action.local.SetKeywordsAction;
import org.eclipse.team.svn.ui.action.local.SetPropertyAction;
import org.eclipse.team.svn.ui.dialog.DefaultDialog;
import org.eclipse.team.svn.ui.dialog.SetPropertyWithOverrideDialog;
import org.eclipse.team.svn.ui.panel.view.property.PropertyApplyPanel;
import org.eclipse.team.svn.ui.properties.PropertiesView;
import org.eclipse.team.svn.ui.properties.RemovePropertyDialog;
import org.eclipse.team.svn.ui.properties.ResourcePropertyEditPanel;
import org.eclipse.team.svn.ui.repository.model.RepositoryPending;
import org.eclipse.team.svn.ui.utility.ColumnedViewerComparator;
import org.eclipse.team.svn.ui.utility.UIMonitorUtility;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.ResourceTransfer;

/**
 * Property viewer composite 
 * 
 * @author Sergiy Logvin
 */
public class PropertiesComposite extends Composite {
    public static final int APPLY_TO_ALL = 0;
    public static final int APPLY_TO_FILES = 1;
    public static final int APPLY_TO_FOLDERS = 2;

    protected static final int COLUMN_NAME = 0;
    protected static final int COLUMN_VALUE = 1;

    protected SVNProperty[] properties;
    protected TableViewer propertyViewer;
    protected Text propertyText;
    protected boolean isProcessing;

    protected PropertiesView propertiesView;

    protected IResourcePropertyProvider provider;

    protected IResource wcResource;
    protected IRepositoryResource repositoryResource;
    protected IAdaptable resource;

    public PropertiesComposite(Composite parent) {
        super(parent, SWT.NONE);
        this.isProcessing = false;
        this.createControls(parent);
    }

    public synchronized void setResource(IAdaptable resource, IResourcePropertyProvider provider) {
        if (resource instanceof IResource) {
            this.repositoryResource = null;
            this.wcResource = (IResource) resource;
        } else if (resource instanceof IRepositoryResource) {
            this.repositoryResource = (IRepositoryResource) resource;
        }
        this.provider = provider;
    }

    public void setPropertiesView(PropertiesView view) {
        this.propertiesView = view;
    }

    public IActionOperation getRefreshViewOperation() {
        return new AbstractActionOperation("Operation_PShowProperties", SVNUIMessages.class) { //$NON-NLS-1$
            protected void runImpl(IProgressMonitor monitor) throws Exception {
                synchronized (PropertiesComposite.this) {
                    if (PropertiesComposite.this.provider != null
                            && PropertiesComposite.this.provider.getExecutionState() == IActionOperation.OK) {
                        if (PropertiesComposite.this.resource != null && !(PropertiesComposite.this.resource
                                .equals(PropertiesComposite.this.provider.getLocal())
                                || PropertiesComposite.this.resource
                                        .equals(PropertiesComposite.this.provider.getRemote()))) {
                            //do nothing if by this moment resource selected in Properties Composite is different 
                            //from the resource for which the Get(Remote)PropertiesOperation was executed
                            return;
                        }
                        PropertiesComposite.this.provider.refresh();
                        PropertiesComposite.this.properties = PropertiesComposite.this.provider.getProperties();
                        if (PropertiesComposite.this.properties == null) {
                            PropertiesComposite.this.properties = new SVNProperty[0];
                        }
                    } else {
                        PropertiesComposite.this.properties = null;
                    }
                }
                if (!PropertiesComposite.this.isDisposed()) {
                    PropertiesComposite.this.getDisplay().syncExec(new Runnable() {
                        public void run() {
                            if (PropertiesComposite.this.properties != null) {
                                PropertiesComposite.this.setPending(false);
                            }
                            PropertiesComposite.this.initializeComposite();
                        }
                    });
                }
            }
        };
    }

    private void createControls(Composite parent) {
        GridLayout layout = null;
        GridData data = null;

        layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        this.setLayout(layout);
        SashForm innerSashForm = new SashForm(this, SWT.VERTICAL);

        data = new GridData(GridData.FILL_BOTH);
        innerSashForm.setLayoutData(data);

        Table table = new Table(innerSashForm, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        data = new GridData(GridData.FILL_BOTH);
        data.horizontalSpan = 2;
        table.setLayoutData(data);
        TableLayout tableLayout = new TableLayout();
        table.setLayout(tableLayout);

        this.propertyText = new Text(innerSashForm, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        this.propertyText.setBackground(this.propertyText.getBackground());
        this.propertyText.setEditable(false);
        data = new GridData(GridData.FILL_BOTH);
        this.propertyText.setLayoutData(data);

        innerSashForm.setWeights(new int[] { 70, 30 });

        this.propertyViewer = new TableViewer(table);
        this.propertyViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                if (event.getSelection() instanceof IStructuredSelection) {
                    Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
                    if (selection != null && selection instanceof SVNProperty) {
                        PropertiesComposite.this.propertyText.setText(((SVNProperty) selection).value);
                    }
                }
            }
        });

        //creating a comparator right now to get column listeners
        PropertiesTableComparator comparator = new PropertiesTableComparator(this.propertyViewer);

        TableColumn col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(SVNUIMessages.PropertiesComposite_Name);
        col.addSelectionListener(comparator);
        tableLayout.addColumnData(new ColumnWeightData(30, true));
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(SVNUIMessages.PropertiesComposite_Value);
        col.addSelectionListener(comparator);
        tableLayout.addColumnData(new ColumnWeightData(70, true));

        //adding a comparator and selecting a default sort column
        this.propertyViewer.setComparator(comparator);
        comparator.setColumnNumber(PropertiesComposite.COLUMN_NAME);
        this.propertyViewer.getTable()
                .setSortColumn(this.propertyViewer.getTable().getColumn(PropertiesComposite.COLUMN_NAME));
        this.propertyViewer.getTable().setSortDirection(SWT.UP);

        this.propertyViewer.setContentProvider(new IStructuredContentProvider() {
            public Object[] getElements(Object inputElement) {
                if (PropertiesComposite.this.isProcessing) {
                    return (Object[]) inputElement;
                }
                if (PropertiesComposite.this.wcResource == null
                        && PropertiesComposite.this.repositoryResource == null) {
                    return new SVNProperty[0];
                }
                return PropertiesComposite.this.properties;
            }

            public void dispose() {
            }

            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            }
        });

        this.propertyViewer.setLabelProvider(new ITableLabelProvider() {

            public Image getColumnImage(Object element, int columnIndex) {
                return null;
            }

            public String getColumnText(Object element, int columnIndex) {
                if (PropertiesComposite.this.isProcessing) {
                    if (columnIndex == 0 && PropertiesComposite.this.wcResource != null) {
                        return SVNUIMessages.getString(RepositoryPending.PENDING);
                    }
                    return ""; //$NON-NLS-1$
                }
                SVNProperty data = (SVNProperty) element;
                if (columnIndex == 0) {
                    return data.name;
                }
                return FileUtility.formatMultilineText(data.value);
            }

            public void addListener(ILabelProviderListener listener) {
            }

            public void dispose() {
            }

            public boolean isLabelProperty(Object element, String property) {
                return true;
            }

            public void removeListener(ILabelProviderListener listener) {
            }
        });

        MenuManager menuMgr = new MenuManager();
        Menu menu = menuMgr.createContextMenu(table);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                synchronized (PropertiesComposite.this) {
                    manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
                    final IStructuredSelection tSelection = (IStructuredSelection) PropertiesComposite.this.propertyViewer
                            .getSelection();
                    if (tSelection.size() == 1 && tSelection.getFirstElement() instanceof String) {
                        return;
                    }
                    Action tAction = null;
                    boolean isEditAllowed = PropertiesComposite.this.provider != null
                            && PropertiesComposite.this.provider.isEditAllowed();
                    if (PropertiesComposite.this.wcResource != null
                            && PropertiesComposite.this.repositoryResource == null) {
                        manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_Add) {
                            public void run() {
                                PropertiesComposite.this.editProperty(null);
                            }
                        });
                        tAction.setEnabled(isEditAllowed);
                        manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_Edit) {
                            public void run() {
                                SVNProperty data = (SVNProperty) tSelection.getFirstElement();
                                PropertiesComposite.this.editProperty(data);
                            }
                        });
                        tAction.setEnabled(isEditAllowed && tSelection.size() == 1);
                        manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_Remove) {
                            public void run() {
                                SVNProperty[] data = (SVNProperty[]) tSelection.toList()
                                        .toArray(new SVNProperty[tSelection.size()]);
                                PropertiesComposite.this.removeProperty(data);
                            }
                        });
                        tAction.setEnabled(isEditAllowed && tSelection.size() > 0);
                        manager.add(new Separator());
                        manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_SetKeywords) {
                            public void run() {
                                PropertiesComposite.this.setKeywords();
                            }
                        });
                        manager.add(tAction = new Action(SVNUIMessages.Action_SetExternals) {
                            public void run() {
                                IActionOperation op = SetExternalDefinitionAction.getAction(
                                        PropertiesComposite.this.wcResource, PropertiesComposite.this.getShell());
                                if (op != null) {
                                    UIMonitorUtility.doTaskScheduledDefault(op);
                                }
                            }
                        });
                        tAction.setEnabled(PropertiesComposite.this.wcResource instanceof IContainer);
                        manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_ApplyRecursively) {
                            public void run() {
                                SVNProperty[] data = (SVNProperty[]) tSelection.toList()
                                        .toArray(new SVNProperty[tSelection.size()]);
                                PropertiesComposite.this.setPropertyRecursive(data);
                            }
                        });
                        tAction.setEnabled(isEditAllowed && tSelection.size() > 0
                                && PropertiesComposite.this.wcResource instanceof IContainer);
                    }
                    manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_SaveValueToFile) {
                        public void run() {
                            SVNProperty data = (SVNProperty) tSelection.getFirstElement();
                            PropertiesComposite.this.saveValueToFile(data);
                        }
                    });
                    tAction.setEnabled(PropertiesComposite.this.provider != null && tSelection.size() == 1);

                    manager.add(new Separator());
                    manager.add(tAction = new Action(SVNUIMessages.PropertiesComposite_Refresh) {
                        public void run() {
                            synchronized (PropertiesComposite.this) {
                                if (PropertiesComposite.this.repositoryResource != null) {
                                    PropertiesComposite.this.provider = new GetRemotePropertiesOperation(
                                            PropertiesComposite.this.repositoryResource);
                                }
                                CompositeOperation composite = new CompositeOperation("Operation_PRefresh", //$NON-NLS-1$
                                        SVNUIMessages.class);
                                if (PropertiesComposite.this.provider != null
                                        && PropertiesComposite.this.provider.getExecutionState() != IStatus.OK) {
                                    composite.add(PropertiesComposite.this.provider);
                                    composite.add(PropertiesComposite.this.getRefreshViewOperation(),
                                            new IActionOperation[] { PropertiesComposite.this.provider });
                                } else {
                                    composite.add(PropertiesComposite.this.getRefreshViewOperation());
                                }

                                UIMonitorUtility.doTaskScheduledActive(composite);
                            }
                        }
                    });
                    tAction.setImageDescriptor(
                            SVNTeamUIPlugin.instance().getImageDescriptor("icons/common/refresh.gif")); //$NON-NLS-1$
                    tAction.setEnabled(PropertiesComposite.this.provider != null);
                }
            }
        });
        menuMgr.setRemoveAllWhenShown(true);
        table.setMenu(menu);

        this.propertyViewer.addDropSupport(DND.DROP_LINK,
                new Transfer[] { ResourceTransfer.getInstance(), RemoteResourceTransfer.getInstance() },
                new DropTargetAdapter() {

                    public void dragEnter(DropTargetEvent event) {
                        event.detail = DND.DROP_LINK;
                    }

                    public void drop(DropTargetEvent event) {
                        if (PropertiesComposite.this.propertiesView == null) {
                            return;
                        }
                        if (event.data instanceof IResource[]) {
                            IResource resource = ((IResource[]) event.data)[0];
                            if (IStateFilter.SF_VERSIONED
                                    .accept(SVNRemoteStorage.instance().asLocalResource(resource))) {
                                PropertiesComposite.this.propertiesView.setResource(resource,
                                        new GetPropertiesOperation(resource), true);
                            }
                            return;
                        }
                        if (event.data instanceof RemoteResourceTransferrable) {
                            IRepositoryResource resource = ((RemoteResourceTransferrable) event.data).resources[0];
                            PropertiesComposite.this.propertiesView.setResource(resource,
                                    new GetRemotePropertiesOperation(resource), false);
                        }
                    }
                });

        this.propertyViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent e) {
                synchronized (PropertiesComposite.this) {
                    if (PropertiesComposite.this.provider != null
                            && PropertiesComposite.this.provider.isEditAllowed()) {
                        IStructuredSelection selection = (IStructuredSelection) e.getSelection();
                        if (selection.size() == 1) {
                            SVNProperty data = (SVNProperty) selection.getFirstElement();
                            PropertiesComposite.this.editProperty(data);
                        }
                    }
                }
            }
        });
    }

    protected void removeProperty(SVNProperty[] data) {
        RemovePropertyDialog dialog = new RemovePropertyDialog(this.getShell(), data.length == 1,
                this.wcResource instanceof IFile);
        if (dialog.open() != 0) {
            return;
        }
        CompositeOperation composite = new CompositeOperation("Operation_PRemoveProperty", SVNUIMessages.class); //$NON-NLS-1$

        composite.add(
                new RemovePropertiesOperation(new IResource[] { this.wcResource }, data, dialog.isRecursive()));
        composite.add(
                this.getRefreshOperation(dialog.isRecursive() ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO));
        UIMonitorUtility.doTaskScheduledActive(composite);
    }

    protected void setKeywords() {
        SetKeywordsAction.doSetKeywords(new IResource[] { this.wcResource });
    }

    protected void setPropertyRecursive(SVNProperty[] data) {
        PropertyApplyPanel panel = new PropertyApplyPanel(data.length == 1);
        DefaultDialog dialog = new DefaultDialog(this.getShell(), panel);

        if (dialog.open() == 0) {
            SetPropertyAction.doSetProperty(new IResource[] { this.wcResource }, data, null, true,
                    panel.getApplyMethod(), panel.useMask(), panel.getFilterMask(), false,
                    this.getRefreshViewOperation());
        }
    }

    protected void editProperty(SVNProperty data) {
        boolean propertyAlreadyExists = false;
        boolean override = true;
        IResource[] resources = new IResource[] { this.wcResource };
        final ResourcePropertyEditPanel panel = new ResourcePropertyEditPanel(
                data == null ? null : new SVNProperty[] { data }, resources, false);
        DefaultDialog dialog = new DefaultDialog(this.getShell(), panel);

        if (dialog.open() != 0) {
            return;
        }

        for (int i = 0; i < this.properties.length; i++) {
            if (this.properties[i].name.equals(panel.getPropertyName())) {
                propertyAlreadyExists = true;
                break;
            }
        }
        if (propertyAlreadyExists && data == null) {
            SetPropertyWithOverrideDialog overrideDialog = new SetPropertyWithOverrideDialog(this.getShell(),
                    panel.getPropertyName());
            if (overrideDialog.open() != 0) {
                override = false;
            }
        }
        if (override) {
            SetPropertyAction.doSetProperty(resources, panel, this.getRefreshViewOperation());
        }
    }

    protected void saveValueToFile(final SVNProperty data) {
        FileDialog fileDialog = new FileDialog(this.getShell(), SWT.SAVE);
        fileDialog.setFileName(data.name);
        final String fileName = fileDialog.open();

        AbstractActionOperation saveValue = new AbstractActionOperation("Operation_PSaveValueToFile", //$NON-NLS-1$
                SVNUIMessages.class) {
            protected void runImpl(IProgressMonitor monitor) throws Exception {
                FileOutputStream output = null;
                if (fileName != null) {
                    output = new FileOutputStream(fileName);
                    byte[] value = data.value.getBytes();
                    output.write(value);
                }
                if (output != null) {
                    output.close();
                }
            }
        };
        UIMonitorUtility.doTaskBusyDefault(saveValue);
    }

    protected IActionOperation getRefreshOperation(int depth) {
        CompositeOperation composite = new CompositeOperation("Operation_PRefreshView", SVNUIMessages.class); //$NON-NLS-1$
        composite.add(this.getRefreshViewOperation());
        if (this.wcResource != null) {
            composite.add(new RefreshResourcesOperation(new IResource[] { this.wcResource },
                    IResource.DEPTH_INFINITE, RefreshResourcesOperation.REFRESH_ALL));
        }
        return composite;
    }

    public void initializeComposite() {
        if (this.isProcessing) {
            this.propertyViewer.setInput(new String[] { "" }); //$NON-NLS-1$
            this.propertyViewer.getTable().setLinesVisible(false);
        } else {
            this.propertyViewer.setInput(this.properties);
            this.propertyViewer.getTable().setLinesVisible(true);
        }
        this.propertyText.setText(""); //$NON-NLS-1$
    }

    public void setPending(boolean isProcessing) {
        this.isProcessing = isProcessing;
    }

    public synchronized void disconnectComposite() {
        this.wcResource = null;
        this.properties = null;
        this.provider = null;
    }

    protected class PropertiesTableComparator extends ColumnedViewerComparator {

        public PropertiesTableComparator(Viewer tableViewer) {
            super(tableViewer);
        }

        public int compareImpl(Viewer viewer, Object row1, Object row2) {
            if (row1 instanceof SVNProperty) {
                SVNProperty data1 = (SVNProperty) row1;
                SVNProperty data2 = (SVNProperty) row2;
                return this.column == PropertiesComposite.COLUMN_NAME
                        ? ColumnedViewerComparator.compare(data1.name, data2.name)
                        : ColumnedViewerComparator.compare(data1.value, data2.value);
            }
            return 0;
        }

    }

}