org.eclipse.rcptt.ctx.filesystem.ui.FilesystemContextEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.rcptt.ctx.filesystem.ui.FilesystemContextEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2014 Xored Software Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.ctx.filesystem.ui;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
import org.eclipse.jface.databinding.fieldassist.ControlDecorationUpdater;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.pde.launching.IPDELauncherConstants;
import org.eclipse.rcptt.core.model.ModelException;
import org.eclipse.rcptt.ctx.filesystem.FileSystemResolver;
import org.eclipse.rcptt.ctx.filesystem.PrefixScheme;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.AddFiles;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.AddFolder;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.FSAction;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.OpenFile;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.Remove;
import org.eclipse.rcptt.ctx.filesystem.ui.actions.Rename;
import org.eclipse.rcptt.filesystem.FSCaptureParam;
import org.eclipse.rcptt.filesystem.FSFile;
import org.eclipse.rcptt.filesystem.FSFolder;
import org.eclipse.rcptt.filesystem.FSResource;
import org.eclipse.rcptt.filesystem.FilesystemContext;
import org.eclipse.rcptt.filesystem.FilesystemFactory;
import org.eclipse.rcptt.filesystem.FilesystemPackage;
import org.eclipse.rcptt.internal.ui.Q7UIPlugin;
import org.eclipse.rcptt.launching.AutLaunch;
import org.eclipse.rcptt.launching.IQ7Launch;
import org.eclipse.rcptt.ui.commons.OneSelectionListener;
import org.eclipse.rcptt.ui.context.BaseContextEditor;
import org.eclipse.rcptt.ui.controls.SectionWithComposite;
import org.eclipse.rcptt.ui.editors.EditorHeader;
import org.eclipse.rcptt.ui.launching.LaunchUtils;
import org.eclipse.rcptt.ui.utils.DefaultTreeViewerEditStrategy;
import org.eclipse.rcptt.ui.utils.UIContentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

public class FilesystemContextEditor extends BaseContextEditor {

    public FilesystemContext getContextElement() {
        try {
            return (FilesystemContext) super.getElement().getNamedElement();
        } catch (ModelException e) {
            Q7UIPlugin.log(e);
        }
        return null;
    }

    @Override
    public EObject getCreateParam(AutLaunch launch) throws CoreException {
        String path = getContextElement().getPath();
        FileSystemResolver resolver = createResolver(launch);

        if (!resolver.isDirectory(path)) {
            FilesystemContentRootPathDialog dialog = new FilesystemContentRootPathDialog(
                    PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), path, resolver);
            if (dialog.open() == Window.OK) {
                getContextElement().setPath(dialog.getRootpath());
            } else {
                throw new CoreException(Status.CANCEL_STATUS);
            }
        }
        FSCaptureParam param = FilesystemFactory.eINSTANCE.createFSCaptureParam();
        param.setPath(getContextElement().getPath());
        param.setClear(getContextElement().isClear());
        return param;
    }

    private EditorHeader header;
    private TreeViewer viewer;

    public Control create(Composite parent, FormToolkit toolkit, IWorkbenchSite site, EditorHeader header) {
        this.header = header;

        if (getContextElement().getRoot() == null) {
            getContextElement().setRoot(FilesystemFactory.eINSTANCE.createFSFolder());
        }

        Section section = new SectionWithComposite("Folder", Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED)
                .create(parent, toolkit);
        Composite client = (Composite) section.getClient();
        GridLayoutFactory.fillDefaults().numColumns(2).spacing(10, 10).applyTo(client);

        createRootControls(toolkit, client);
        createOptionsControls(toolkit, client);
        createTree(toolkit, client);
        createButtons(toolkit, client);

        setSelection(null);

        return section;
    }

    private List<Button> buttons = new ArrayList<Button>();

    private void createButtons(FormToolkit toolkit, Composite client) {
        Composite panel = toolkit.createComposite(client);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).applyTo(panel);
        RowLayout layout = new RowLayout(SWT.VERTICAL);
        layout.pack = false;
        layout.marginBottom = 0;
        layout.marginLeft = 0;
        layout.marginTop = 0;
        layout.marginRight = 0;
        panel.setLayout(layout);

        createButton(panel, toolkit, new AddFiles());
        createButton(panel, toolkit, new AddFolder());
        createButton(panel, toolkit, removeAction = new Remove());
        createButton(panel, toolkit, openFileAction = new OpenFile());
        createButton(panel, toolkit, new Rename());

        setSelection(null);
    }

    private void createButton(Composite parent, FormToolkit toolkit, final FSAction action) {
        action.setViewer(viewer);
        Button button = toolkit.createButton(parent, action.getText(), SWT.PUSH);
        button.setData(action);
        Image image = action.getImageDescriptor().createImage();
        button.setImage(image);
        button.setToolTipText(action.getToolTipText());
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                action.run();
            }
        });
        buttons.add(button);
    }

    private void setSelection(FSResource[] selection) {
        for (Button button : buttons) {
            FSAction action = (FSAction) button.getData();
            action.setSelection(selection);
            button.setEnabled(action.isEnabled());
        }
    }

    private void createTree(FormToolkit toolkit, Composite client) {
        final Tree tree = new Tree(client, SWT.BORDER | SWT.MULTI);
        GridDataFactory.fillDefaults().grab(true, true).span(1, 1).hint(100, 50).applyTo(tree);

        viewer = new TreeViewer(tree);
        viewer.setLabelProvider(new FilesystemContextLabelProvider());
        viewer.setContentProvider(new FilesystemContextContentProvider());
        viewer.setInput(getContextElement());
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
                Object[] res = sel.toArray();
                FSResource[] resources = new FSResource[res.length];
                for (int i = 0; i < res.length; i++)
                    resources[i] = (FSResource) res[i];
                setSelection(resources);
            }
        });
        viewer.addDoubleClickListener(new IDoubleClickListener() {

            /**
             * Opens file or expands/collapses folder.
             */
            public void doubleClick(DoubleClickEvent event) {
                if (openFileAction.isEnabled()) {
                    openFileAction.run();
                } else {
                    TreeViewer viewer = (TreeViewer) event.getViewer();
                    IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                    Object selectedNode = selection.getFirstElement();
                    viewer.setExpandedState(selectedNode, !viewer.getExpandedState(selectedNode));
                }
            }
        });

        // Setups renaming
        TreeViewerEditor.create(viewer, new DefaultTreeViewerEditStrategy(viewer), ColumnViewerEditor.DEFAULT);
        viewer.setCellEditors(new CellEditor[] { new TextCellEditor(tree) });
        viewer.setCellModifier(new ICellModifier() {
            public void modify(Object element, String property, Object value) {
                TreeItem item = (TreeItem) element;
                FSResource res = (FSResource) item.getData();
                EObject parent = res.eContainer();
                Set<String> allNames = getAllNames(parent);
                allNames.remove(res.getName());

                String newValue = (String) value;
                if (allNames.contains(newValue)) {
                    return;
                }

                if (newValue != null && !newValue.isEmpty() && !newValue.equals(res.getName())) {
                    res.setName(newValue);
                }
            }

            public Object getValue(Object element, String property) {
                return ((FSResource) element).getName();
            }

            public boolean canModify(Object element, String property) {
                return true;
            }
        });
        viewer.setColumnProperties(new String[] { "" });

        viewer.getControl().addKeyListener(new KeyListener() {

            public void keyReleased(KeyEvent e) {
            }

            public void keyPressed(KeyEvent e) {
                if ((SWT.DEL == e.character) && (0 == e.stateMask)) {
                    if (removeAction.isEnabled()) {
                        removeAction.run();
                        e.doit = false;
                    }
                }
            }
        });

        UIContentAdapter adapter = new UIContentAdapter() {
            @Override
            protected void changed(Notification notification) {
                if (viewer.getControl().isDisposed()) {
                    return;
                }
                viewer.refresh();
            }
        };
        getContextElement().eAdapters().add(adapter);
    }

    private void createOptionsControls(FormToolkit toolkit, Composite client) {
        final Button clearCheckbox = toolkit.createButton(client, "Clear root folder before context application",
                SWT.CHECK);
        GridDataFactory.fillDefaults().span(3, 1).applyTo(clearCheckbox);

        UpdateValueStrategy strategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_ON_REQUEST);
        final Binding binding = dbc.bindValue(SWTObservables.observeSelection(clearCheckbox), EMFObservables
                .observeValue(getContextElement(), FilesystemPackage.Literals.FILESYSTEM_CONTEXT__CLEAR), strategy,
                null);
        clearCheckbox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (clearCheckbox.getSelection() && !isClearConfirmed()) {
                    clearCheckbox.setSelection(false);
                    return;

                }
                binding.updateTargetToModel();
            }
        });
    }

    private boolean isClearConfirmed() {
        String path = getContextElement().getPath();
        if (path == null || path.isEmpty()) {
            path = "selected root path";
        } else if (currentResolver != null) {
            String resolvedPath = currentResolver.resolve(path);
            if (resolvedPath != null) {
                path = resolvedPath;
            }
        }
        return MessageDialog.openQuestion(viewer.getControl().getShell(), "Confirm folder clear",
                String.format("Enabling this option will cause a complete "
                        + "removal of %s during context apply. Do you want to enable it?", path));
    }

    private void createRootControls(final FormToolkit toolkit, final Composite client) {
        Composite panel = toolkit.createComposite(client);
        GridDataFactory.fillDefaults().span(2, 1).applyTo(panel);
        GridLayoutFactory.fillDefaults().numColumns(3).spacing(10, 10).applyTo(panel);

        Label rootLabel = toolkit.createLabel(panel, "Root path:");
        rootLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
        rootLabel.setBackground(null);

        Text rootText = toolkit.createText(panel, "", SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, false).hint(1, SWT.DEFAULT).applyTo(rootText);
        Binding rootBinding = dbc.bindValue(SWTObservables.observeText(rootText, SWT.Modify), EMFObservables
                .observeValue(getContextElement(), FilesystemPackage.Literals.FILESYSTEM_CONTEXT__PATH),
                rootStrategy, rootStrategy);
        ControlDecorationSupport.create(rootBinding, SWT.TOP | SWT.LEFT, panel, new ControlDecorationUpdater() {
            @Override
            protected void update(ControlDecoration decoration, IStatus status) {
                decoration.setMarginWidth(2);
                super.update(decoration, status);
            }
        });

        Button browseButton = toolkit.createButton(panel, "Browse...", SWT.PUSH);
        browseButton.addSelectionListener(new OneSelectionListener() {
            @Override
            public void selected(SelectionEvent e) {
                AutLaunch launch = LaunchUtils.selectAutLaunch(client.getShell());
                if (launch == null)
                    return;

                DirectoryDialog dialog = new DirectoryDialog(client.getShell());
                String result = dialog.open();
                if (result != null) {
                    getContextElement().setPath(makeRootPath(result, launch));
                }
            }
        });
    }

    private static String substituteAndCanonicalize(String value) {
        String result = value;
        try {
            result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value,
                    false);
        } catch (CoreException e) {
            Activator.logErr(e, "Failed to substitute variables in %s", value);
        }

        try {
            result = new File(result).getCanonicalPath();
        } catch (IOException e) {
            Activator.logErr(e, "Failed to canonicalize %s", value);
        }

        return result;
    }

    private String makeRootPath(String path, AutLaunch launch) {
        String made = getResolvedPath(path, launch);
        if (made != null)
            path = made;

        return path;
    }

    private FileSystemResolver currentResolver = null;

    private FileSystemResolver createResolver(AutLaunch launch) {
        FileSystemResolver resolver = new FileSystemResolver();

        ILaunchConfiguration config = launch.getAut().getConfig();
        if (config != null) {
            { // workspace
                try {
                    String location = config.getAttribute(IPDELauncherConstants.LOCATION, (String) null);
                    if (location != null && location.length() > 0)
                        resolver.register(
                                new PrefixScheme(PrefixScheme.WORKSPACE, substituteAndCanonicalize(location)));
                } catch (CoreException e) {
                    Q7UIPlugin.log(e);
                }
            }

            { // aut
                try {
                    String location = config.getAttribute(IQ7Launch.AUT_LOCATION, (String) null);
                    if (location != null && location.length() > 0)
                        resolver.register(new PrefixScheme(PrefixScheme.AUT, substituteAndCanonicalize(location)));
                } catch (CoreException e) {
                    Q7UIPlugin.log(e);
                }
            }
        }

        { // file
            resolver.register(new PrefixScheme(PrefixScheme.FILE, null));
        }

        { // home
            resolver.register(new PrefixScheme(PrefixScheme.HOME,
                    new File(System.getProperty("user.home")).getAbsolutePath()));
        }
        return resolver;
    }

    private String getResolvedPath(String path, AutLaunch launch) {
        currentResolver = createResolver(launch);
        return currentResolver.make(path);
    }

    // --

    private UpdateValueStrategy rootStrategy = new UpdateValueStrategy() {
        {
            this.setBeforeSetValidator(new IValidator() {
                public IStatus validate(Object value) {
                    String path = (String) value;

                    // TODO: more sophisticated path validity checking
                    if (path == null || path.length() == 0) {
                        header.getRecordButton().setEnabled(false);
                        header.getReplayButton().setEnabled(false);
                        return ValidationStatus.warning("No root path provided.");
                    }

                    header.getRecordButton().setEnabled(true);
                    header.getReplayButton().setEnabled(true);
                    return ValidationStatus.ok();
                }
            });
        }
    };

    private Set<String> getAllNames(EObject parent) {
        Set<String> allNames = new HashSet<String>();
        if (parent instanceof FSFolder) {
            EList<FSFolder> folders = ((FSFolder) parent).getFolders();
            EList<FSFile> files = ((FSFolder) parent).getFiles();
            for (FSFile fsFile : files) {
                allNames.add(fsFile.getName());
            }
            for (FSFolder folder : folders) {
                allNames.add(folder.getName());
            }
        }
        return allNames;
    }

    private Remove removeAction;
    private OpenFile openFileAction;
}