Package org.locationtech.udig.feature.panel

Source Code of org.locationtech.udig.feature.panel.FeaturePanelPage$SelectionChangedListener

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2010, Refractions Research Inc.
* (C) 2001, 2009 IBM Corporation and others
* ------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
* --------
* 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
*/
package org.locationtech.udig.feature.panel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.locationtech.udig.feature.editor.FeatureEditorPlugin;
import org.locationtech.udig.feature.editor.IFeaturePage;
import org.locationtech.udig.project.ui.IFeaturePanel;
import org.locationtech.udig.project.ui.IFeatureSite;
import org.locationtech.udig.project.ui.feature.FeaturePanelEntry;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.IContributedContentsView;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.part.PageBookView;
import org.eclipse.ui.views.properties.tabbed.AbstractOverridableTabListPropertySection;
import org.eclipse.ui.views.properties.tabbed.IOverridableTabListContentProvider;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

/**
* A tabbed UI showing feature panels.
* <p>
* The use of ISelectionListener.selectionChanged(IWorkbenchPart,ISelection) is
* used to track what is going on; it is the responsibility of the container to
* feed this page events via this method.
* <ul>
* <li>IWorkbenchPart - is checked to see if it can adapt to a Map
* <li>ISelection -
* </ul>
*
* @see TabbedPropertySheetPage
*/
public class FeaturePanelPage extends Page implements IFeaturePage, ILabelProviderListener,
        ISelectionListener {
    /**
     * FeatureSite allowing page to interact with the current EditManager etc...
     */
    private IFeatureSite site;

    /**
     * Normal tabbed propert composite will display fine
     */
    private FeaturePanelComposite tabbedPropertyComposite;

    /**
     * Subclass of form view tricked out for display
     */
    private FeaturePanelWidgetFactory widgetFactory;

    /**
     * This is the contributor that is hosting this page
     */
    private FeaturePanelPageContributor contributor;

    private FeaturePanelRegistry registry;

    /**
     * In the event we are provided a selection from another workbench part this
     * selection contributor will due the dead.
     */
    private FeaturePanelPageContributor selectionContributor = null;

    /**
     * The currently active schema, which may not match the schema from the
     * workbench part that created this instance.
     */
    private SimpleFeatureType currentSchema;

    protected IStructuredContentProvider tabListContentProvider;

    private ISelection currentSelection;

    private boolean activePropertySheet;

    private FeaturePanelViewer tabbedPropertyViewer;

    private IFeaturePanel currentTab;

    private Map<FeaturePanelTabDescriptor, IFeaturePanel> descriptorToTab;

    private Map<IFeaturePanel, Composite> tabToComposite;

    private List<String> selectionQueue;

    private boolean selectionQueueLocked;

    private List<TabSelectionListener> tabSelectionListeners;

    private IWorkbenchWindow cachedWorkbenchWindow;

    private boolean hasTitleBar = true;

    /**
     * A listener that is interested in part activation events.
     */
    private IPartListener partActivationListener = new IPartListener() {

        public void partActivated(IWorkbenchPart part) {
            handlePartActivated(part);
        }

        public void partBroughtToTop(IWorkbenchPart part) {
        }

        public void partClosed(IWorkbenchPart part) {
        }

        public void partDeactivated(IWorkbenchPart part) {
        }

        public void partOpened(IWorkbenchPart part) {
        }
    };

    /**
     * This is used to communicate a selected SimpleFeatureType to the page.
     * This can be used adapt a normal workbench part up as a
     * IFeaturePanelPageContributor.
     */
    private class IFeaturePanelPageContributorFromSelection implements FeaturePanelPageContributor {

        private SimpleFeatureType schema;

        /**
         * Constructor that takes in a contributor id taken from a selection.
         *
         * @param contributorId
         *            the contributor id.
         */
        public IFeaturePanelPageContributorFromSelection(SimpleFeatureType schema) {
            this.schema = schema;
        }

        /**
         * @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
         */
        public SimpleFeatureType getSchema() {
            return schema;
        }
    }

    /**
     * Label provider for the ListViewer.
     */
    class TabbedPropertySheetPageLabelProvider extends LabelProvider {
        public String getText(Object element) {
            if (element instanceof FeaturePanelTabDescriptor) {
                return ((FeaturePanelTabDescriptor) element).getLabel();
            }
            return null;
        }
    }

    /**
     * SelectionChangedListener for the ListViewer.
     */
    class SelectionChangedListener implements ISelectionChangedListener {

        /**
         * Shows the tab associated with the selection.
         */
        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            IFeaturePanel tab = null;
            FeaturePanelTabDescriptor descriptor = (FeaturePanelTabDescriptor) selection
                    .getFirstElement();

            if (descriptor == null) {
                // pretend the tab is empty.
                hideTab(currentTab);
            } else {
                // create tab if necessary
                // can not cache based on the id - tabs may have the same id,
                // but different section depending on the selection
                //
                tab = descriptorToTab.get(descriptor);

                if (tab != currentTab) {
                    hideTab(currentTab);
                }

                Composite tabComposite = (Composite) tabToComposite.get(tab);
                if (tabComposite == null) {
                    tabComposite = createTabComposite();
                    tab.createPartControl(tabComposite);
                    try {
                        tab.init(site, null);
                    } catch (PartInitException e) {
                        IStatus status = new Status(IStatus.ERROR, descriptor.getEntry().getId(),
                                "Problem initializing feature panel", e);
                        FeatureEditorPlugin.getDefault().getLog().log(status);
                    }
                    tabToComposite.put(tab, tabComposite);
                }
                // force widgets to be resized
                // tab.setInput(tabbedPropertyViewer.getWorkbenchPart(),(ISelection)
                // tabbedPropertyViewer.getInput());

                // store tab selection
                storeCurrentTabSelection(descriptor.getLabel());

                if (tab != currentTab) {
                    showTab(tab);
                }
                tab.refresh();
            }
            tabbedPropertyComposite.getTabComposite().layout(true);
            currentTab = tab;
            resizeScrolledComposite();

            if (descriptor != null) {
                handleTabSelection(descriptor);
            }
        }

        /**
         * Shows the given tab.
         */
        private void showTab(IFeaturePanel target) {
            if (target != null) {
                Composite tabComposite = (Composite) tabToComposite.get(target);
                if (tabComposite != null) {
                    /**
                     * the following method call order is important - do not
                     * change it or the widgets might be drawn incorrectly
                     */
                    tabComposite.moveAbove(null);
                    target.aboutToBeShown();
                    tabComposite.setVisible(true);
                }
            }
        }

        /**
         * Hides the given tab.
         */
        private void hideTab(IFeaturePanel currentTab) {
            if (currentTab != null) {
                Composite tabComposite = tabToComposite.get(currentTab);
                if (tabComposite != null) {
                    currentTab.aboutToBeHidden();
                    tabComposite.setVisible(false);
                }
            }
        }

    }

    /**
     * create a new tabbed property sheet page.
     *
     * @param tabbedPropertySheetPageContributor
     *            the tabbed property sheet page contributor.
     */
    public FeaturePanelPage(FeaturePanelPageContributor featurePanelPageContributor) {
        this(featurePanelPageContributor, true);
    }

    /**
     * create a new tabbed property sheet page.
     *
     * @param tabbedPropertySheetPageContributor
     *            the tabbed property sheet page contributor.
     * @param showTitleBar
     *            boolean indicating if the title bar should be shown; default
     *            value is <code>true</code>
     * @since 3.5
     */
    public FeaturePanelPage(FeaturePanelPageContributor contributor, boolean showTitleBar) {
        hasTitleBar = showTitleBar;
        this.contributor = contributor;
        tabToComposite = new HashMap<IFeaturePanel, Composite>();
        selectionQueue = new ArrayList<String>(10);
        tabSelectionListeners = new ArrayList<TabSelectionListener>();
        initContributor(contributor.getSchema());
    }

    /**
     * Handle the part activated event.
     *
     * @param part
     *            the new activated part.
     */
    protected void handlePartActivated(IWorkbenchPart part) {
        // Check if the part is a PageBookView with this page as its
        // current page.
        boolean thisActivated = part instanceof PageBookView
                && ((PageBookView) part).getCurrentPage() == this;

        // When the active part changes and does not select a FeatureType
        // we still need to trigger aboutToBeHidden() and aboutToBeShown().
        if (!thisActivated && !part.equals(contributor)) {
            // check if this view is a proxy for another contributor
            IContributedContentsView view = (IContributedContentsView) part
                    .getAdapter(IContributedContentsView.class);

            if (view != null && view.getContributingPart() != null
                    && view.getContributingPart().equals(contributor)) {
                // this view is a proxy for our current contributor
            } else {
                // we are actually switching contributors
                if (activePropertySheet) {
                    if (currentTab != null) {
                        currentTab.aboutToBeHidden();
                    }
                    activePropertySheet = false;
                }
                return;
            }
        }
        if (!activePropertySheet && currentTab != null) {
            currentTab.aboutToBeShown();
            currentTab.refresh();
        }
        activePropertySheet = true;
    }

    /**
     * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        widgetFactory = new FeaturePanelWidgetFactory();
        tabbedPropertyComposite = new FeaturePanelComposite(parent, widgetFactory, hasTitleBar);
        widgetFactory.paintBordersFor(tabbedPropertyComposite);
        tabbedPropertyComposite.setLayout(new FormLayout());
        FormData formData = new FormData();
        formData.left = new FormAttachment(0, 0);
        formData.right = new FormAttachment(100, 0);
        formData.top = new FormAttachment(0, 0);
        formData.bottom = new FormAttachment(100, 0);
        tabbedPropertyComposite.setLayoutData(formData);

        FeaturePanelList list = tabbedPropertyComposite.getList();
        tabbedPropertyViewer = new FeaturePanelViewer(list);
        tabbedPropertyViewer.setContentProvider(tabListContentProvider);
        tabbedPropertyViewer.setLabelProvider(new TabbedPropertySheetPageLabelProvider());
        tabbedPropertyViewer.addSelectionChangedListener(new SelectionChangedListener());
        tabbedPropertyComposite.getScrolledComposite().addControlListener(new ControlAdapter() {

            public void controlResized(ControlEvent e) {
                resizeScrolledComposite();
            }
        });

        /**
         * Add a part activation listener.
         */
        cachedWorkbenchWindow = getSite().getWorkbenchWindow();
        cachedWorkbenchWindow.getPartService().addPartListener(partActivationListener);

        /**
         * Add a label provider change listener.
         */
        if (hasTitleBar) {
            registry.getLabelProvider().addListener(this);
        }
    }

    /**
     * Initialize the contributor
     *
     * @param contributorId
     *            the contributor id.
     */
    private void initContributor(SimpleFeatureType schema) {
        descriptorToTab = new HashMap<FeaturePanelTabDescriptor, IFeaturePanel>();

        if (currentSchema == schema) {
            // default contributor from the workbench part.
            registry = FeaturePanelRegistryFactory.getInstance().createRegistry(contributor);
        } else {
            // selection contributor.
            selectionContributor = new IFeaturePanelPageContributorFromSelection(schema);
            registry = FeaturePanelRegistryFactory.getInstance().createRegistry(
                    selectionContributor);
        }

        currentSchema = schema;
        tabListContentProvider = getTabListContentProvider();
        hasTitleBar = hasTitleBar && registry.getLabelProvider() != null;

        if (tabbedPropertyViewer != null) {
            tabbedPropertyViewer.setContentProvider(tabListContentProvider);
        }

        /**
         * Add a label provider change listener.
         */
        if (hasTitleBar) {
            registry.getLabelProvider().addListener(this);
        }

    }

    /**
     * Gets the tab list content provider for the contributor.
     *
     * @return the tab list content provider for the contributor.
     */
    protected IStructuredContentProvider getTabListContentProvider() {
        return registry.getTabListContentProvider();
    }

    /**
     * Dispose the contributor with the provided contributor id. This happens on
     * part close as well as when contributors switch between the workbench part
     * and contributor from a selection.
     */
    private void disposeContributor() {
        /**
         * If the current tab is about to be disposed we have to call
         * aboutToBeHidden
         */
        if (currentTab != null) {
            currentTab.aboutToBeHidden();
            currentTab = null;
        }

        disposeTabs(descriptorToTab.values());
        descriptorToTab = new HashMap();

        /**
         * Remove the label provider change listener.
         */
        if (hasTitleBar && registry != null) {
            registry.getLabelProvider().removeListener(this);
        }

        if (selectionContributor != null) {
            /**
             * remove the selection contributed registry.
             */
            FeaturePanelRegistryFactory.getInstance().disposeRegistry(selectionContributor);
            selectionContributor = null;
        }
    }

    /**
     * @see org.eclipse.ui.part.IPage#dispose()
     */
    public void dispose() {

        disposeContributor();

        if (widgetFactory != null) {
            widgetFactory.dispose();
            widgetFactory = null;
        }
        /**
         * Remove the part activation listener.
         */
        if (cachedWorkbenchWindow != null) {
            cachedWorkbenchWindow.getPartService().removePartListener(partActivationListener);
            cachedWorkbenchWindow = null;
        }

        if (registry != null) {
            // registry.dispose();
            registry = null;
        }
        currentSchema = null;
        currentSelection = null;
    }

    /**
     * @see org.eclipse.ui.part.IPage#getControl()
     */
    public Control getControl() {
        return tabbedPropertyComposite;
    }

    /**
     * @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars)
     */
    public void setActionBars(IActionBars actionBars) {
        // Override the undo and redo global action handlers
        // to use the contributor action handlers
        IActionBars partActionBars = null;
        if (contributor instanceof IEditorPart) {
            IEditorPart editorPart = (IEditorPart) contributor;
            partActionBars = editorPart.getEditorSite().getActionBars();
        } else if (contributor instanceof IViewPart) {
            IViewPart viewPart = (IViewPart) contributor;
            partActionBars = viewPart.getViewSite().getActionBars();
        }

        if (partActionBars != null) {
            IAction action = partActionBars.getGlobalActionHandler(ActionFactory.UNDO.getId());
            if (action != null) {
                actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), action);
            }
            action = partActionBars.getGlobalActionHandler(ActionFactory.REDO.getId());
            if (action != null) {
                actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
            }
        }
    }

    /**
     * @see org.eclipse.ui.part.IPage#setFocus()
     */
    public void setFocus() {
        getControl().setFocus();
    }

    /**
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
     *      org.eclipse.jface.viewers.ISelection)
     */
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        setInput(part, selection);
        tabbedPropertyViewer.refresh();
    }

    /**
     * Stores the current tab label in the selection queue. Tab labels are used
     * to carry the tab context from one input object to another. The queue
     * specifies the selection priority. So if the first tab in the queue is not
     * available for the input we try the second tab and so on. If none of the
     * tabs are available we default to the first tab available for the input.
     */
    private void storeCurrentTabSelection(String label) {
        if (!selectionQueueLocked) {
            selectionQueue.remove(label);
            selectionQueue.add(0, label);
        }
    }

    /**
     * Resize the scrolled composite enclosing the sections, which may result in
     * the addition or removal of scroll bars.
     *
     * @since 3.5
     */
    public void resizeScrolledComposite() {
        Point currentTabSize = new Point(0, 0);
        if (currentTab != null) {
            Composite sizeReference = (Composite) tabToComposite.get(currentTab);
            if (sizeReference != null) {
                currentTabSize = sizeReference.computeSize(SWT.DEFAULT, SWT.DEFAULT);
            }
        }
        tabbedPropertyComposite.getScrolledComposite().setMinSize(currentTabSize);

        ScrollBar verticalScrollBar = tabbedPropertyComposite.getScrolledComposite()
                .getVerticalBar();
        if (verticalScrollBar != null) {
            Rectangle clientArea = tabbedPropertyComposite.getScrolledComposite().getClientArea();
            int increment = clientArea.height - 5;
            verticalScrollBar.setPageIncrement(increment);
        }

        ScrollBar horizontalScrollBar = tabbedPropertyComposite.getScrolledComposite()
                .getHorizontalBar();
        if (horizontalScrollBar != null) {
            Rectangle clientArea = tabbedPropertyComposite.getScrolledComposite().getClientArea();
            int increment = clientArea.width - 5;
            horizontalScrollBar.setPageIncrement(increment);
        }
    }

    private void disposeTabs(Collection tabs) {
        for (Iterator iter = tabs.iterator(); iter.hasNext();) {
            IFeaturePanel tab = (IFeaturePanel) iter.next();
            Composite composite = (Composite) tabToComposite.remove(tab);
            tab.dispose();
            if (composite != null) {
                composite.dispose();
            }
        }
    }

    /**
     * Returns the last known selected tab for the given input.
     */
    private int getLastTabSelection(IWorkbenchPart part, ISelection input) {
        List<FeaturePanelTabDescriptor> descriptors = registry.getTabDescriptors(part, input);
        if (!descriptors.isEmpty()) {
            for (String text : selectionQueue) {
                int i = 0;
                for (FeaturePanelTabDescriptor descriptor : descriptors) {
                    if (text.equals(descriptor.getLabel())) {
                        return i;
                    }
                    i++;
                }
            }
        }
        return 0;
    }

    /**
     * Update the current tabs to represent the given input object. When tabs
     * apply for both the old and new input they are reused otherwise they are
     * disposed. If the current visible tab will not be reused (i.e. will be
     * disposed) we have to send it an aboutToBeHidden() message.
     *
     * @since 3.4
     */
    protected void updateTabs(List<FeaturePanelTabDescriptor> descriptors) {
        Map<FeaturePanelTabDescriptor, IFeaturePanel> newTabs = new HashMap<FeaturePanelTabDescriptor, IFeaturePanel>(
                descriptors.size() * 2);
        boolean disposingCurrentTab = (currentTab != null);
        for (FeaturePanelTabDescriptor descriptor : descriptors) {
            IFeaturePanel tab = descriptorToTab.remove(descriptor);

            if (tab != null && tab.controlsHaveBeenCreated()) {
                if (tab == currentTab) {
                    disposingCurrentTab = false;
                }
            } else {
                tab = createTab(descriptor);
            }

            newTabs.put(descriptor, tab);
        }
        if (disposingCurrentTab) {
            /**
             * If the current tab is about to be disposed we have to call
             * aboutToBeHidden
             */
            currentTab.aboutToBeHidden();
            currentTab = null;
        }
        disposeTabs(descriptorToTab.values());
        descriptorToTab = newTabs;
    }

    /**
     * Create the tab contents for the provided tab descriptor.
     *
     * @param tabDescriptor
     *            the tab descriptor.
     * @return the tab contents.
     * @since 3.4
     */
    protected IFeaturePanel createTab(FeaturePanelTabDescriptor tabDescriptor) {
        FeaturePanelEntry entry = tabDescriptor.getEntry();
        return entry.createFeaturePanel();
    }

    /**
     * Helper method for creating property tab composites.
     *
     * @return the property tab composite.
     */
    private Composite createTabComposite() {
        Composite result = widgetFactory.createComposite(tabbedPropertyComposite.getTabComposite(),
                SWT.NO_FOCUS);
        result.setVisible(false);
        result.setLayout(new FillLayout());
        FormData data = new FormData();
        if (hasTitleBar) {
            data.top = new FormAttachment(tabbedPropertyComposite.getTitle(), 0);
        } else {
            data.top = new FormAttachment(0, 0);
        }
        data.bottom = new FormAttachment(100, 0);
        data.left = new FormAttachment(0, 0);
        data.right = new FormAttachment(100, 0);
        result.setLayoutData(data);
        return result;
    }

    private void setInput(IWorkbenchPart part, ISelection selection) {
        if (selection != null && selection.equals(currentSelection)) {
            return;
        }

        this.currentSelection = selection;

        // see if the selection provides a new contributor
        validateRegistry(selection);
        List<FeaturePanelTabDescriptor> descriptors = registry.getTabDescriptors(part,
                currentSelection);
        // If there are no descriptors for the given input we do not need to
        // touch the tab objects. We might reuse them for the next valid
        // input.
        if (!descriptors.isEmpty()) {
            updateTabs(descriptors);
            ILabelProvider header = null;
            for( FeaturePanelTabDescriptor descriptor : descriptors ){
                header = descriptor.getEntry().getLabelProvider();
            }
            if( header != null ){
                tabbedPropertyViewer.setLabelProvider( new TabLabelProvider( header ));
            }
            else {
                tabbedPropertyViewer.setLabelProvider( null );
            }
        }
        // update tabs list
        tabbedPropertyViewer.setInput(part, currentSelection);
        int lastTabSelectionIndex = getLastTabSelection(part, currentSelection);
        Object selectedTab = tabbedPropertyViewer.getElementAt(lastTabSelectionIndex);
        selectionQueueLocked = true;
        try {
            if (selectedTab == null) {
                tabbedPropertyViewer.setSelection(null);
            } else {
                tabbedPropertyViewer.setSelection(new StructuredSelection(selectedTab));
            }
        } finally {
            selectionQueueLocked = false;
        }
        refreshTitleBar();
    }

    /**
     * Refresh the currently active tab.
     */
    public void refresh() {
        if (currentTab != null) {
            currentTab.refresh();
        }
    }

    /**
     * Get the currently active tab.
     *
     * @return the currently active tab.
     * @since 3.4
     */
    public IFeaturePanel getCurrentTab() {
        return currentTab;
    }

    /**
     * Handle the tab selected change event.
     *
     * @param tabDescriptor
     *            the new selected tab.
     */
    private void handleTabSelection(FeaturePanelTabDescriptor tabDescriptor) {
        if (selectionQueueLocked) {
            /*
             * don't send tab selection events for non user changes.
             */
            return;
        }
        for (TabSelectionListener listener : tabSelectionListeners) {
            listener.tabSelected(tabDescriptor);
        }
    }

    /**
     * Add a tab selection listener.
     *
     * @param listener
     *            a tab selection listener.
     */
    public void addTabSelectionListener(TabSelectionListener listener) {
        tabSelectionListeners.add(listener);
    }

    /**
     * Remove a tab selection listener.
     *
     * @param listener
     *            a tab selection listener.
     */
    public void removeTabSelectionListener(TabSelectionListener listener) {
        tabSelectionListeners.remove(listener);
    }

    /**
     * Override the tabs with a new set of tabs. The tab list is obtained from
     * the {@link AbstractOverridableTabListPropertySection} by the
     * {@link IOverridableTabListContentProvider}.
     *
     * @since 3.4
     */
    public void overrideTabs() {
        if (tabListContentProvider instanceof IOverridableTabListContentProvider) {
            IOverridableTabListContentProvider overridableTabListContentProvider = (IOverridableTabListContentProvider) tabListContentProvider;
            overridableTabListContentProvider.overrideTabs();
        }
    }

    /**
     * Get the widget factory.
     *
     * @return the widget factory.
     */
    public FeaturePanelWidgetFactory getWidgetFactory() {
        return widgetFactory;
    }

    /**
     * Update the title bar of the contributor has a label provider.
     */
    private void refreshTitleBar() {
        if (hasTitleBar) {
            FeaturePanelTitle title = tabbedPropertyComposite.getTitle();
            if (currentTab == null) {
                /**
                 * No tabs are shown so hide the title bar, otherwise you see
                 * "No properties available" and a title bar for the selection.
                 */
                title.setTitle(null, null);
            } else {
                String text = registry.getLabelProvider().getText(currentSelection);
                Image image = registry.getLabelProvider().getImage(currentSelection);
                title.setTitle(text, image);
            }
        }
    }

    /**
     * @see org.eclipse.jface.viewers.ILabelProviderListener#labelProviderChanged(org.eclipse.jface.viewers.LabelProviderChangedEvent)
     */
    public void labelProviderChanged(LabelProviderChangedEvent event) {
        refreshTitleBar();
    }

    /**
     * Retrieve the contributor from the selection; the contributor is
     * responsible for obtaining a Schema.
     *
     * @param object
     *            - the selected element
     * @return the IFeaturePanelPageContributor or null if not applicable
     */
    private FeaturePanelPageContributor getFeaturePanelPageContributor(Object object) {
        if (object instanceof FeaturePanelPageContributor) {
            return (FeaturePanelPageContributor) object;
        }

        if (object instanceof IAdaptable
                && ((IAdaptable) object).getAdapter(FeaturePanelPageContributor.class) != null) {
            return (FeaturePanelPageContributor) (((IAdaptable) object)
                    .getAdapter(FeaturePanelPageContributor.class));
        }

        if (Platform.getAdapterManager().hasAdapter(object,
                FeaturePanelPageContributor.class.getName())) {
            return (FeaturePanelPageContributor) Platform.getAdapterManager().loadAdapter(object,
                    FeaturePanelPageContributor.class.getName());
        }

        return null;
    }

    /**
     * The workbench part creates this instance of the TabbedFeaturePanelPage
     * and implements ITabbedFeaturePanelPageContributor which is unique
     * contributor id. This unique contributor id is used to load a registry
     * with the extension point This id matches the registry.
     * <p>
     * It is possible for elements in a selection to implement
     * ITabbedFeaturePanelPageContributor to provide a different contributor id
     * and thus a differenent registry.
     *
     * @param selection
     *            the current selection in the active workbench part.
     */
    private void validateRegistry(ISelection selection) {
        if (selection == null) {
            return;
        }

        if (!(selection instanceof IStructuredSelection)) {
            return;
        }

        IStructuredSelection structuredSelection = (IStructuredSelection) selection;
        if (structuredSelection.size() == 0) {
            return;
        }

        FeaturePanelPageContributor newContributor = getFeaturePanelPageContributor(structuredSelection
                .getFirstElement());

        if (newContributor == null) {
            /**
             * selection does not implement or adapt
             * ITabbedFeaturePanelPageContributor.
             */
            newContributor = contributor;
        }

        SimpleFeatureType selectionSchema = newContributor.getSchema();
        if (selectionSchema == null) {
            return;
        }
        if (selectionSchema.equals(currentSchema)) {
            // selection has the same contributor id as current, so leave
            // existing registry.
            return;
        }

        /**
         * Selection implements ITabbedFeaturePanelPageContributor different
         * than current contributor id, so make sure all elements implement the
         * new id. If all contributor id do not match, then fall back to default
         * contributor from the workbench part.
         */
        Iterator i = structuredSelection.iterator();
        i.next();
        while (i.hasNext()) {
            newContributor = getFeaturePanelPageContributor(i.next());
            if (newContributor == null || !newContributor.getSchema().equals(selectionSchema)) {
                /**
                 * fall back to use the default contributor id from the
                 * workbench part.
                 */
                if (selectionContributor != null) {
                    disposeContributor();
                    // currentSchema = contributor.getSchema();
                    initContributor(contributor.getSchema());
                }
                return;
            }
        }

        /**
         * All the elements in the selection implement a new contributor id, so
         * use that id.
         */
        disposeContributor();
        currentSchema = selectionSchema;
        initContributor(currentSchema);
        overrideActionBars();
    }

    /**
     * Override the action bars for the selection based contributor.
     */
    private void overrideActionBars() {
        if (registry.getActionProvider() != null) {
            ActionProvider actionProvider = registry.getActionProvider();
            actionProvider.setActionBars(contributor, getSite().getActionBars());
        }
    }

    /**
     * Returns the currently selected tab.
     *
     * @return the currently selected tab or <code>null</code> if there is no
     *         tab selected.
     * @since 3.5
     */
    public FeaturePanelTabDescriptor getSelectedTab() {
        int selectedTab = tabbedPropertyViewer.getSelectionIndex();
        if (selectedTab != -1) {
            Object object = tabbedPropertyViewer.getElementAt(selectedTab);
            if (object instanceof FeaturePanelTabDescriptor) {
                return (FeaturePanelTabDescriptor) object;
            }
        }
        return null;
    }

    /**
     * Returns the list of currently active tabs.
     */
    public List<FeaturePanelTabDescriptor> getActiveTabs() {
        List<FeaturePanelTabDescriptor> elements = tabbedPropertyViewer.getElements();
        if (elements != null && elements.size() > 0) {
            return elements;
        }
        return elements;
    }

    /**
     * Set the currently selected tab to be that of the provided tab id.
     *
     * @param id
     *            The string id of the tab to select.
     */
    public void setSelectedTab(String id) {
        List<FeaturePanelTabDescriptor> elements = tabbedPropertyViewer.getElements();
        if (elements != null && elements.size() > 0) {
            for (FeaturePanelTabDescriptor tabDescriptor : elements) {
                if (tabDescriptor.getId() != null && tabDescriptor.getId().equals(id)) {
                    tabbedPropertyViewer.setSelection(new StructuredSelection(tabDescriptor), true);
                }
            }
        }
    }

    /**
     * Returns text of the feature panel title for given selection. If selection
     * is null, then currentSelection is used
     *
     * @param selection
     *            Selection whose properties title text is to be returned
     * @return String representing title text.
     *
     */
    public String getTitleText(ISelection selection) {
        if (selection == null) {
            selection = currentSelection;
        }
        return registry.getLabelProvider().getText(selection);
    }

    /**
     * Returns the title image for given selection. If selection is null, then
     * currentSelection is used.
     *
     * @param selection
     *            Selection whose properties title image is to be returned
     * @return Image that is used as a title image.
     *
     */
    public Image getTitleImage(ISelection selection) {
        if (selection == null) {
            selection = currentSelection;
        }
        return registry.getLabelProvider().getImage(selection);
    }

    public void editFeatureChanged(SimpleFeature feature) {
        if (feature != null) {
            StructuredSelection selection = new StructuredSelection(feature);
            selectionChanged(null, selection);
        } else {
            selectionChanged(null, null);
        }
    }

    public IFeatureSite getFeatureSite() {
        return this.site;
    }

    public void setFeatureSite(IFeatureSite site) {
        this.site = site;
    }
}
TOP

Related Classes of org.locationtech.udig.feature.panel.FeaturePanelPage$SelectionChangedListener

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.