Package bndtools.views

Source Code of bndtools.views.RepositoriesView

package bndtools.views;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bndtools.api.ILogger;
import org.bndtools.api.Logger;
import org.bndtools.utils.Function;
import org.bndtools.utils.swt.FilterPanelPart;
import org.bndtools.utils.swt.SWTConcurrencyUtil;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.dnd.URLTransfer;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ResourceTransfer;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.ServiceRegistration;

import aQute.bnd.build.Workspace;
import aQute.bnd.osgi.Jar;
import aQute.bnd.service.Actionable;
import aQute.bnd.service.RepositoryListenerPlugin;
import aQute.bnd.service.RepositoryPlugin;
import aQute.lib.converter.Converter;
import aQute.lib.io.IO;
import bndtools.Activator;
import bndtools.Plugin;
import bndtools.central.Central;
import bndtools.central.RepositoryUtils;
import bndtools.model.repo.ContinueSearchElement;
import bndtools.model.repo.RepositoryBundle;
import bndtools.model.repo.RepositoryBundleVersion;
import bndtools.model.repo.RepositoryTreeLabelProvider;
import bndtools.model.repo.SearchableRepositoryTreeContentProvider;
import bndtools.utils.SelectionDragAdapter;
import bndtools.wizards.workspace.AddFilesToRepositoryWizard;

public class RepositoriesView extends ViewPart implements RepositoryListenerPlugin {
    final static Pattern LABEL_PATTERN = Pattern.compile("(-)?(!)?([^{}]+)(?:\\{([^}]+)\\})?");
    private static final String DROP_TARGET = "dropTarget";

    private static final ILogger logger = Logger.getLogger(RepositoriesView.class);

    private final FilterPanelPart filterPart = new FilterPanelPart(Plugin.getDefault().getScheduler());
    private final SearchableRepositoryTreeContentProvider contentProvider = new SearchableRepositoryTreeContentProvider();
    private TreeViewer viewer;

    private Action collapseAllAction;
    private Action refreshAction;
    private Action addBundlesAction;

    private ServiceRegistration registration;

    @Override
    public void createPartControl(Composite parent) {
        // CREATE CONTROLS
        Composite mainPanel = new Composite(parent, SWT.NONE);
        Control filterPanel = filterPart.createControl(mainPanel, 5, 5);
        Tree tree = new Tree(mainPanel, SWT.FULL_SELECTION | SWT.MULTI);
        filterPanel.setBackground(tree.getBackground());

        viewer = new TreeViewer(tree);
        viewer.setContentProvider(contentProvider);
        ColumnViewerToolTipSupport.enableFor(viewer);

        viewer.setLabelProvider(new RepositoryTreeLabelProvider(false));
        getViewSite().setSelectionProvider(viewer);

        createActions();

        // LISTENERS
        filterPart.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent event) {
                String filter = (String) event.getNewValue();
                updatedFilter(filter);
            }
        });
        ViewerDropAdapter dropAdapter = new ViewerDropAdapter(viewer) {
            @Override
            public boolean validateDrop(Object target, int operation, TransferData transferType) {
                if (canDrop(target, transferType))
                    return true;

                boolean valid = false;
                if (target instanceof RepositoryPlugin) {
                    if (((RepositoryPlugin) target).canWrite()) {

                        if (URLTransfer.getInstance().isSupportedType(transferType))
                            return true;

                        if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) {
                            ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
                            if (selection instanceof IStructuredSelection) {
                                for (Iterator< ? > iter = ((IStructuredSelection) selection).iterator(); iter.hasNext();) {
                                    Object element = iter.next();
                                    if (element instanceof RepositoryBundle || element instanceof RepositoryBundleVersion) {
                                        valid = true;
                                        break;
                                    }
                                    if (element instanceof IFile) {
                                        valid = true;
                                        break;
                                    }
                                    if (element instanceof IAdaptable) {
                                        IFile file = (IFile) ((IAdaptable) element).getAdapter(IFile.class);
                                        if (file != null) {
                                            valid = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        } else {
                            valid = true;
                        }
                    }
                }
                return valid;
            }

            @Override
            public void dragEnter(DropTargetEvent event) {
                super.dragEnter(event);
                event.detail = DND.DROP_COPY;
            }

            @Override
            public boolean performDrop(Object data) {
                if (RepositoriesView.this.performDrop(getCurrentTarget(), getCurrentEvent().currentDataType)) {
                    viewer.refresh(getCurrentTarget(), true);
                    return true;
                }

                boolean copied = false;
                if (URLTransfer.getInstance().isSupportedType(getCurrentEvent().currentDataType)) {
                    try {
                        URL url = new URL((String) URLTransfer.getInstance().nativeToJava(getCurrentEvent().currentDataType));
                        File tmp = File.createTempFile("dwnl", ".jar");
                        IO.copy(url, tmp);
                        copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), new File[] {
                            tmp
                        });
                    } catch (Exception e) {
                        return false;
                    }
                } else if (data instanceof String[]) {
                    String[] paths = (String[]) data;
                    File[] files = new File[paths.length];
                    for (int i = 0; i < paths.length; i++) {
                        files[i] = new File(paths[i]);
                    }
                    copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files);
                } else if (data instanceof IResource[]) {
                    IResource[] resources = (IResource[]) data;
                    File[] files = new File[resources.length];
                    for (int i = 0; i < resources.length; i++) {
                        files[i] = resources[i].getLocation().toFile();
                    }
                    copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files);
                } else if (data instanceof IStructuredSelection) {
                    File[] files = convertSelectionToFiles((IStructuredSelection) data);
                    if (files != null && files.length > 0)
                        copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files);
                }
                return copied;
            }
        };
        dropAdapter.setFeedbackEnabled(false);
        dropAdapter.setExpandEnabled(false);

        viewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] {
                URLTransfer.getInstance(), FileTransfer.getInstance(), ResourceTransfer.getInstance(), LocalSelectionTransfer.getTransfer()
        }, dropAdapter);
        viewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] {
            LocalSelectionTransfer.getTransfer()
        }, new SelectionDragAdapter(viewer));

        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                boolean writableRepoSelected = false;
                IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
                Object element = selection.getFirstElement();
                if (element instanceof RepositoryPlugin) {
                    RepositoryPlugin repo = (RepositoryPlugin) element;
                    writableRepoSelected = repo.canWrite();
                }
                addBundlesAction.setEnabled(writableRepoSelected);
            }
        });
        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseUp(MouseEvent ev) {
                Object element = ((IStructuredSelection) viewer.getSelection()).getFirstElement();
                if (element instanceof ContinueSearchElement) {
                    try {
                        getViewSite().getPage().showView(Plugin.JPM_BROWSER_VIEW_ID, null, IWorkbenchPage.VIEW_VISIBLE);
                    } catch (PartInitException e) {
                        Plugin.getDefault().getLog().log(e.getStatus());
                    }
                }
            }
        });
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                if (!event.getSelection().isEmpty()) {
                    IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                    Object element = selection.getFirstElement();
                    if (element instanceof IAdaptable) {
                        URI uri = (URI) ((IAdaptable) element).getAdapter(URI.class);
                        if (uri != null) {
                            IWorkbenchPage page = getSite().getPage();
                            try {
                                IFileStore fileStore = EFS.getLocalFileSystem().getStore(uri);
                                IDE.openEditorOnFileStore(page, fileStore);
                            } catch (PartInitException e) {
                                logger.logError("Error opening editor for " + uri, e);
                            }
                        }
                    } else if (element instanceof ContinueSearchElement) {
                        try {
                            getViewSite().getPage().showView(Plugin.JPM_BROWSER_VIEW_ID, null, IWorkbenchPage.VIEW_VISIBLE);
                        } catch (PartInitException e) {
                            Plugin.getDefault().getLog().log(e.getStatus());
                        }
                    }

                }
            }
        });

        createContextMenu();

        // LOAD
        Central.onWorkspaceInit(new Function<Workspace,Void>() {
            public Void run(Workspace a) {
                final List<RepositoryPlugin> repositories = RepositoryUtils.listRepositories(true);
                SWTConcurrencyUtil.execForControl(viewer.getControl(), true, new Runnable() {
                    public void run() {
                        viewer.setInput(repositories);
                    }
                });
                return null;
            }
        });

        // LAYOUT
        GridLayout layout = new GridLayout(1, false);
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        mainPanel.setLayout(layout);

        tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        filterPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

        // Toolbar
        createActions();
        fillToolBar(getViewSite().getActionBars().getToolBarManager());

        // Register as repository listener
        registration = Activator.getDefault().getBundleContext().registerService(RepositoryListenerPlugin.class.getName(), this, null);
    }

    @Override
    public void setFocus() {
        filterPart.setFocus();
    }

    private static File[] convertSelectionToFiles(ISelection selection) {
        if (!(selection instanceof IStructuredSelection))
            return new File[0];

        IStructuredSelection structSel = (IStructuredSelection) selection;
        List<File> files = new ArrayList<File>(structSel.size());

        for (Iterator< ? > iter = structSel.iterator(); iter.hasNext();) {
            Object element = iter.next();
            if (element instanceof IFile)
                files.add(((IFile) element).getLocation().toFile());
            else if (element instanceof IAdaptable) {
                IAdaptable adaptable = (IAdaptable) element;
                IFile ifile = (IFile) adaptable.getAdapter(IFile.class);
                if (ifile != null) {
                    files.add(ifile.getLocation().toFile());
                } else {
                    File file = (File) adaptable.getAdapter(File.class);
                    if (file != null) {
                        files.add(file);
                    }
                }
            }
        }

        return files.toArray(new File[files.size()]);
    }

    @Override
    public void dispose() {
        registration.unregister();
        super.dispose();
    }

    boolean addFilesToRepository(RepositoryPlugin repo, File[] files) {
        AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, files);
        WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard);
        dialog.open();
        viewer.refresh(repo);
        return true;
    }

    private void updatedFilter(String filterString) {
        String newFilter;
        if (filterString == null || filterString.length() == 0 || filterString.trim().equals("*"))
            newFilter = null;
        else
            newFilter = "*" + filterString.trim() + "*";

        contentProvider.setFilter(newFilter);
        viewer.refresh();
        if (newFilter != null)
            viewer.expandToLevel(2);
    }

    void createActions() {
        collapseAllAction = new Action() {
            @Override
            public void run() {
                viewer.collapseAll();
            }
        };
        collapseAllAction.setText("Collapse All");
        collapseAllAction.setToolTipText("Collapse All");
        collapseAllAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/collapseall.gif"));

        refreshAction = new Action() {
            @Override
            public void run() {
                doRefresh();
            }
        };
        refreshAction.setText("Refresh");
        refreshAction.setToolTipText("Refresh Repositories Tree");
        refreshAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/arrow_refresh.png"));

        addBundlesAction = new Action() {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
                Object element = selection.getFirstElement();
                if (element != null && element instanceof RepositoryPlugin) {
                    RepositoryPlugin repo = (RepositoryPlugin) element;
                    if (repo.canWrite()) {
                        AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, new File[0]);
                        WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard);
                        dialog.open();

                        viewer.refresh(repo);
                    }
                }
            }
        };
        addBundlesAction.setEnabled(false);
        addBundlesAction.setText("Add");
        addBundlesAction.setToolTipText("Add Bundles to Repository");
        addBundlesAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/brick_add.png"));
    }

    void createContextMenu() {
        MenuManager mgr = new MenuManager();
        Menu menu = mgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
        getSite().registerContextMenu(mgr, viewer);

        mgr.addMenuListener(new IMenuListener() {

            public void menuAboutToShow(IMenuManager manager) {
                try {
                    manager.removeAll();
                    IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
                    if (!selection.isEmpty()) {
                        Object firstElement = selection.getFirstElement();
                        if (firstElement instanceof Actionable) {
                            //
                            // Use the Actionable interface to fill the menu
                            // Should extend this to allow other menu entries
                            // from the view, but currently there are none
                            //
                            final Actionable act = (Actionable) firstElement;
                            Map<String,Runnable> actions = act.actions();
                            if (actions != null) {
                                for (final Entry<String,Runnable> e : actions.entrySet()) {
                                    String label = e.getKey();
                                    boolean enabled = true;
                                    boolean checked = false;
                                    String description = null;
                                    Matcher m = LABEL_PATTERN.matcher(label);
                                    if (m.matches()) {
                                        if (m.group(1) != null)
                                            enabled = false;

                                        if (m.group(2) != null)
                                            checked = true;

                                        label = m.group(3);

                                        description = m.group(4);
                                    }
                                    Action a = new Action(label) {
                                        @Override
                                        public void run() {
                                            try {
                                                e.getValue().run();
                                            } catch (Exception e) {
                                                throw new RuntimeException(e);
                                            }
                                            viewer.refresh(act);
                                        }
                                    };
                                    a.setEnabled(enabled);
                                    if (description != null)
                                        a.setDescription(description);
                                    a.setChecked(checked);
                                    manager.add(a);
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

    private void doRefresh() {
        // Remember names of expanded repositories
        Set<String> expandedRepoNames = new HashSet<String>();
        Object[] expandedElems = viewer.getExpandedElements();
        for (Object expandedElem : expandedElems) {
            if (expandedElem instanceof RepositoryPlugin) {
                expandedRepoNames.add(((RepositoryPlugin) expandedElem).getName());
            }
        }

        // Reload repositories
        List<RepositoryPlugin> repos = RepositoryUtils.listRepositories(true);
        viewer.setInput(repos);

        // Expand any repos that have the same name as a repository that
        // was expanded before the reload.
        for (RepositoryPlugin repo : repos) {
            if (expandedRepoNames.contains(repo.getName())) {
                viewer.setExpandedState(repo, true);
            }
        }
    }

    private void fillToolBar(IToolBarManager toolBar) {
        toolBar.add(refreshAction);
        toolBar.add(collapseAllAction);
        toolBar.add(addBundlesAction);
        toolBar.add(new Separator());
    }

    public void bundleAdded(final RepositoryPlugin repository, Jar jar, File file) {
        if (viewer != null)
            SWTConcurrencyUtil.execForControl(viewer.getControl(), true, new Runnable() {
                public void run() {
                    viewer.refresh(repository);
                }
            });
    }

    public void bundleRemoved(final RepositoryPlugin repository, Jar jar, File file) {
        if (viewer != null)
            SWTConcurrencyUtil.execForControl(viewer.getControl(), true, new Runnable() {
                public void run() {
                    viewer.refresh(repository);
                }
            });
    }

    public void repositoryRefreshed(final RepositoryPlugin repository) {
        if (viewer != null)
            SWTConcurrencyUtil.execForControl(viewer.getControl(), true, new Runnable() {
                public void run() {
                    viewer.refresh(repository);
                }
            });
    }

    public void repositoriesRefreshed() {
        if (viewer != null)
            SWTConcurrencyUtil.execForControl(viewer.getControl(), true, new Runnable() {
                public void run() {
                    doRefresh();
                }
            });
    }

    /**
     * Handle the drop on targets that understand drops.
     *
     * @param target
     *            The current target
     * @param data
     *            The transfer data
     * @return true if the data is acceptable, otherwise false
     */
    boolean canDrop(Object target, TransferData data) {
        try {
            Class< ? > type = toJavaType(data);
            if (type != null) {
                target.getClass().getMethod(DROP_TARGET, type);
                return true;
            }
        } catch (Exception e) {
            // Ignore
        }
        return false;
    }

    /**
     * Try a drop on the target. A drop is allowed if the target implements a {@code dropTarget} method that returns a
     * boolean.
     *
     * @param target
     *            the target being dropped upon
     * @param data
     *            the data
     * @return true if dropped and processed, false if not
     */
    boolean performDrop(Object target, TransferData data) {
        try {
            Object java = toJava(data);
            if (java == null)
                return false;

            Method m = target.getClass().getMethod(DROP_TARGET, java.getClass());
            return (Boolean) m.invoke(target, java);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Return the class of the dropped object
     *
     * <pre>
     *    URLTransfer             URI
     *    FileTransfer            File[]
     *    TextTransfer            String
     *    ImageTransfer           ImageData
     * </pre>
     *
     * @param data
     *            the dropped object
     * @return the class of the dropped object, or null when it's unknown
     * @throws Exception
     *             upon error
     */
    Class< ? > toJavaType(TransferData data) throws Exception {
        if (URLTransfer.getInstance().isSupportedType(data))
            return URI.class;
        if (FileTransfer.getInstance().isSupportedType(data))
            return File[].class;
        if (TextTransfer.getInstance().isSupportedType(data))
            return String.class;
        //        if (ImageTransfer.getInstance().isSupportedType(data))
        //            return Image.class;
        return null;
    }

    /**
     * Return a native data type that represents the dropped object
     *
     * <pre>
     *    URLTransfer             URI
     *    FileTransfer            File[]
     *    TextTransfer            String
     *    ImageTransfer           ImageData
     * </pre>
     *
     * @param data
     *            the dropped object
     * @return a native data type that represents the dropped object, or null when the data type is unknown
     * @throws Exception
     *             upon error
     */
    Object toJava(TransferData data) throws Exception {
        if (URLTransfer.getInstance().isSupportedType(data))
            return Converter.cnv(URI.class, URLTransfer.getInstance().nativeToJava(data));
        else if (FileTransfer.getInstance().isSupportedType(data)) {
            return Converter.cnv(File[].class, FileTransfer.getInstance().nativeToJava(data));
        } else if (TextTransfer.getInstance().isSupportedType(data)) {
            return TextTransfer.getInstance().nativeToJava(data);
        }
        // Need to write the transfer code since the ImageTransfer turns it into
        // something very Eclipsy
        //        else if (ImageTransfer.getInstance().isSupportedType(data))
        //            return ImageTransfer.getInstance().nativeToJava(data);

        return null;
    }

}
TOP

Related Classes of bndtools.views.RepositoriesView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.