Package org.apache.felix.sigil.eclipse.ui.util

Source Code of org.apache.felix.sigil.eclipse.ui.util.BackgroundLoadingSelectionDialog

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.felix.sigil.eclipse.ui.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalListener;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.progress.IJobRunnable;

public class BackgroundLoadingSelectionDialog<E> extends TitleAreaDialog implements IAccumulator<E>
{

    private final ILabelProvider DEFAULT_LABEL_PROVIDER = new LabelProvider()
    {
        @SuppressWarnings("unchecked")
        public String getText(Object element)
        {
            String result;
            if (element instanceof WrappedContentProposal<?>)
            {
                WrappedContentProposal<E> contentProposal = (org.apache.felix.sigil.eclipse.ui.util.WrappedContentProposal<E>) element;
                result = contentProposal.getLabel();
            }
            else
            {
                result = descriptor.getLabel((E) element);
            }
            return result;
        }
    };

    private final IElementDescriptor<E> DEFAULT_DESCRIPTOR = new IElementDescriptor<E>()
    {
        public String getLabel(E element)
        {
            return getName(element);
        }

        public String getName(E element)
        {
            return element == null ? "null" : element.toString();
        }
    };

    private final String selectionLabel;
    private IFilter<? super E> filter;
    private IElementDescriptor<? super E> descriptor = DEFAULT_DESCRIPTOR;
    private ILabelProvider labelProvider = DEFAULT_LABEL_PROVIDER;
    private final boolean multi;

    private final List<E> elements;

    private List<E> selection = null;
    private String selectedName = null;

    private TableViewer viewer = null;
    private Comparator<? super E> comparator;

    private HashMap<String, IJobRunnable> background = new HashMap<String, IJobRunnable>();

    public BackgroundLoadingSelectionDialog(Shell parentShell, String selectionLabel, boolean multi)
    {
        super(parentShell);
        elements = new ArrayList<E>();
        this.selectionLabel = selectionLabel;
        this.multi = multi;
    }

    public void setFilter(IFilter<? super E> filter)
    {
        this.filter = filter;
    }

    public void setDescriptor(final IElementDescriptor<? super E> descriptor)
    {
        if (descriptor != null)
        {
            this.descriptor = descriptor;
        }
        else
        {
            this.descriptor = DEFAULT_DESCRIPTOR;
        }
    }

    public IElementDescriptor<? super E> getDescriptor()
    {
        return descriptor;
    }

    public void setComparator(Comparator<? super E> comparator)
    {
        this.comparator = comparator;
    }

    public void setLabelProvider(ILabelProvider labelProvider)
    {
        if (labelProvider != null)
        {
            this.labelProvider = labelProvider;
        }
        else
        {
            this.labelProvider = DEFAULT_LABEL_PROVIDER;
        }
    }

    public void addBackgroundJob(String name, IJobRunnable job)
    {
        background.put(name, job);
    }

    @Override
    public int open()
    {
        Job[] jobs = scheduleJobs();
        try
        {
            return super.open();
        }
        finally
        {
            for (Job j : jobs)
            {
                j.cancel();
            }
        }
    }

    private Job[] scheduleJobs()
    {
        if (background.isEmpty())
        {
            return new Job[] {};
        }
        else
        {
            ArrayList<Job> jobs = new ArrayList<Job>(background.size());
            for (Map.Entry<String, IJobRunnable> e : background.entrySet())
            {
                final IJobRunnable run = e.getValue();
                Job job = new Job(e.getKey())
                {
                    @Override
                    protected IStatus run(IProgressMonitor monitor)
                    {
                        return run.run(monitor);
                    }
                };
                job.schedule();
            }

            return jobs.toArray(new Job[jobs.size()]);
        }
    }

    @Override
    protected Control createDialogArea(Composite parent)
    {
        // Create Controls
        Composite container = (Composite) super.createDialogArea(parent);
        Composite composite = new Composite(container, SWT.NONE);

        new Label(composite, SWT.NONE).setText(selectionLabel);

        ContentProposalAdapter proposalAdapter = null;
        Text txtSelection = null;

        Table table = null;
        if (multi)
        {
            table = new Table(composite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
            viewer = new TableViewer(table);
            viewer.setContentProvider(new ArrayContentProvider());
            viewer.addFilter(new ViewerFilter()
            {
                public boolean select(Viewer viewer, Object parentElement, Object element)
                {
                    @SuppressWarnings("unchecked")
                    E castedElement = (E) element;
                    return filter == null || filter.select(castedElement);
                }
            });
            if (comparator != null)
            {
                viewer.setSorter(new ViewerSorter()
                {
                    @Override
                    public int compare(Viewer viewer, Object o1, Object o2)
                    {
                        @SuppressWarnings("unchecked")
                        E e1 = (E) o1;
                        @SuppressWarnings("unchecked")
                        E e2 = (E) o2;
                        return comparator.compare(e1, e2);
                    }
                });
            }
            synchronized (elements)
            {
                viewer.setInput(elements);
            }

            if (labelProvider != null)
            {
                viewer.setLabelProvider(labelProvider);
            }
        }
        else
        {
            txtSelection = new Text(composite, SWT.BORDER);
            ControlDecoration selectionDecor = new ControlDecoration(txtSelection,
                SWT.LEFT | SWT.TOP);
            FieldDecoration proposalDecor = FieldDecorationRegistry.getDefault().getFieldDecoration(
                FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
            selectionDecor.setImage(proposalDecor.getImage());
            selectionDecor.setDescriptionText(proposalDecor.getDescription());

            ExclusionContentProposalProvider<E> proposalProvider = new ExclusionContentProposalProvider<E>(
                elements, filter, descriptor);

            proposalAdapter = new ContentProposalAdapter(txtSelection,
                new TextContentAdapter(), proposalProvider, null, null);
            proposalAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
            if (labelProvider != null)
            {
                proposalAdapter.setLabelProvider(labelProvider);
            }

            if (selectedName != null)
            {
                txtSelection.setText(selectedName);
            }
        }
        updateSelection();
        updateButtons();

        // Hookup listeners
        if (proposalAdapter != null)
        {
            proposalAdapter.addContentProposalListener(new IContentProposalListener()
            {
                public void proposalAccepted(IContentProposal proposal)
                {
                    @SuppressWarnings("unchecked")
                    WrappedContentProposal<E> valueProposal = (org.apache.felix.sigil.eclipse.ui.util.WrappedContentProposal<E>) proposal;
                    E selected = valueProposal.getElement();
                    selection = new ArrayList<E>(1);
                    selection.add(selected);

                    elementSelected(selected);

                    updateButtons();
                }
            });
        }
        if (txtSelection != null)
        {
            txtSelection.addModifyListener(new ModifyListener()
            {
                public void modifyText(ModifyEvent e)
                {
                    selectedName = ((Text) e.widget).getText();
                    updateButtons();
                }
            });
        }
        if (viewer != null)
        {
            viewer.addSelectionChangedListener(new ISelectionChangedListener()
            {
                public void selectionChanged(SelectionChangedEvent event)
                {
                    IStructuredSelection sel = (IStructuredSelection) event.getSelection();
                    selection = new ArrayList<E>(sel.size());
                    for (Iterator<?> iter = sel.iterator(); iter.hasNext();)
                    {
                        @SuppressWarnings("unchecked")
                        E element = (E) iter.next();
                        selection.add(element);
                    }
                    updateButtons();
                }
            });
            viewer.addOpenListener(new IOpenListener()
            {
                public void open(OpenEvent event)
                {
                    if (canComplete())
                    {
                        setReturnCode(IDialogConstants.OK_ID);
                        close();
                    }
                }
            });
        }

        // Layout
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        if (multi)
        {
            composite.setLayout(new GridLayout(1, false));
            GridData layoutTable = new GridData(SWT.FILL, SWT.FILL, true, true);
            layoutTable.heightHint = 200;
            table.setLayoutData(layoutTable);
        }
        else
        {
            composite.setLayout(new GridLayout(2, false));
            txtSelection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        }

        return container;
    }

    protected void elementSelected(E selection)
    {
    }

    @Override
    protected Control createButtonBar(Composite parent)
    {
        Control bar = super.createButtonBar(parent);
        updateButtons();
        return bar;
    }

    /**
     * Can be called from any thread
     */
    protected final void updateButtons()
    {
        Runnable updateButtonsRunnable = new Runnable()
        {
            public void run()
            {
                Shell shell = getShell();
                if (shell != null && !shell.isDisposed())
                {
                    Button okButton = getButton(IDialogConstants.OK_ID);
                    if (okButton != null && !okButton.isDisposed())
                    {
                        okButton.setEnabled(canComplete());
                    }
                }
            }
        };
        Shell shell = getShell();
        if (shell != null)
        {
            onUIThread(shell, updateButtonsRunnable);
        }
    }

    /**
     * Subclasses may override but must call super.canComplete
     * @return
     */
    protected synchronized boolean canComplete()
    {
        boolean result = false;

        if (selection != null)
        {
            if (multi)
            {
                result = selection.size() > 0;
            }
            else
            {
                E sel = getSelectedElement();
                result = sel != null && descriptor.getName(sel).equals(selectedName);
            }
        }

        return result;
    }

    public final void addElement(E added)
    {
        addElements(Collections.singleton(added));
    }

    /**
     * Can be called from any thread
     */
    public final void addElements(Collection<? extends E> added)
    {
        final LinkedList<E> toAdd = new LinkedList<E>();
        synchronized (elements)
        {
            for (E e : added)
            {
                if (!elements.contains(e))
                {
                    elements.add(e);
                    toAdd.add(e);
                }
            }
            Collections.sort(elements, comparator);
        }
        if (viewer != null)
        {
            onUIThread(viewer.getControl(), new Runnable()
            {
                public void run()
                {
                    if (!viewer.getControl().isDisposed())
                    {
                        viewer.add(toAdd.toArray());
                        viewer.refresh();
                    }
                }
            });
        }
        else
        {

        }
        updateSelection();
        updateButtons();
    }

    protected void updateSelection()
    {
        onUIThread(getShell(), new Runnable()
        {
            public void run()
            {
                if (selectedName != null)
                {
                    ArrayList<E> newSelection = new ArrayList<E>();
                    synchronized (elements)
                    {
                        for (E e : elements)
                        {
                            if (selectedName.equals(descriptor.getName(e)))
                            {
                                newSelection.add(e);
                                break;
                            }
                        }
                    }
                    selection = newSelection;
                }
                else
                {
                    selection = Collections.emptyList();
                }
                if (viewer != null && !viewer.getControl().isDisposed())
                {
                    viewer.setSelection(selection.isEmpty() ? StructuredSelection.EMPTY
                        : new StructuredSelection(selection));
                }
            }
        });
    }

    private static final void onUIThread(Control control, Runnable r)
    {
        if (control != null && !control.isDisposed())
        {
            try
            {
                Display display = control.getDisplay();
                if (Thread.currentThread() == display.getThread())
                {
                    // We are on the UI thread already, just do the work
                    r.run();
                }
                else
                {
                    // Not on the UI thread, need to bung over the runnable
                    display.asyncExec(r);
                }
            }
            catch (SWTError e)
            {
                if (e.code == SWT.ERROR_WIDGET_DISPOSED)
                {
                    // ignore
                }
                else
                {
                    throw e;
                }
            }
        }
    }

    public String getSelectedName()
    {
        return selectedName;
    }

    public void setSelectedName(String selectedName)
    {
        this.selectedName = selectedName;
        boolean change = false;
        if (selectedName == null)
        {
            if (selection != null && !selection.isEmpty())
            {
                change = true;
            }
        }
        else
        {
            if (selection == null)
            {
                change = true;
            }
            else if (selection.size() != 1
                || !descriptor.getLabel(selection.get(0)).equals(selectedName))
            {
                change = true;
            }
        }

        if (change)
        {
            updateSelection();
            updateButtons();
        }
    }

    public List<E> getSelectedElements()
    {
        return selection;
    }

    public E getSelectedElement()
    {
        E result;
        if (selection == null || selection.isEmpty())
        {
            result = null;
        }
        else
        {
            result = selection.get(0);
        }
        return result;
    }
}
TOP

Related Classes of org.apache.felix.sigil.eclipse.ui.util.BackgroundLoadingSelectionDialog

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.