com.netxforge.netxstudio.screens.AbstractSmartTableScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.netxforge.netxstudio.screens.AbstractSmartTableScreen.java

Source

/*******************************************************************************
 * Copyright (c) 25 nov. 2012 NetXForge.
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details. You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>
 * 
 * Contributors: Christophe Bouhier - initial API and implementation and/or
 * initial documentation
 *******************************************************************************/
package com.netxforge.netxstudio.screens;

import java.util.Comparator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
import org.eclipse.emf.spi.cdo.FSMUtil;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IMemento;

import com.netxforge.base.cdo.CDO;
import com.netxforge.netxstudio.screens.AbstractSmartTableViewer.SelectionHistory;
import com.netxforge.netxstudio.screens.editing.CDOEditingService;
import com.netxforge.netxstudio.screens.editing.util.CDOMementoUtil;
import com.netxforge.netxstudio.screens.internal.ScreensActivator;
import com.netxforge.screens.editing.base.IDataServiceInjection;
import com.netxforge.screens.editing.base.util.MementoUtil;

/**
 * An abstract implementation of a screen with an embedded tableviewer.
 * 
 * 
 * @author Christophe Bouhier
 * 
 */
public abstract class AbstractSmartTableScreen extends AbstractScreen implements IDataServiceInjection {

    private LazyTableViewer lazyTableViewer;

    /*
     * Expose so clients can utilize methods like matches().
     */
    protected AbstractPatternItemsFilter lazyItemsFilter;

    /*
     * Expose so clients can utilize
     */
    protected AdapterFactoryItemDelegator adapterFactoryItemDelegator;

    public AbstractSmartTableScreen(Composite parent, int style) {
        super(parent, style);

        this.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (getLazyTableViewer() != null) {
                    getLazyTableViewer().removeAdapterFactory();
                }
            }
        });
    }

    @Override
    public void injectData() {
        final CDOView view = delegateGetCDOView();
        lazyTableViewer.setSelectionHistory(new LazySelectionHistory(view));

    }

    public void buildUI(Composite parent, String pattern) {
        lazyTableViewer = new LazyTableViewer(this.getShell(), true);

        adapterFactoryItemDelegator = new AdapterFactoryItemDelegator(CDOEditingService.getAdapterFactory());

        // Set our adapter factory for additional facilities.
        lazyTableViewer.setAdapterFactory(CDOEditingService.getAdapterFactory());

        // Set a default or custom label provider. The default uses EMF.edit to
        // retrieve the ItemProvider getText()
        IBaseLabelProvider provider = delegateGetListLabelProvider();
        lazyTableViewer.setListLabelProvider(provider);

        // Do we have a custom selection decorator.
        ILabelDecorator decorator = delegateGetListSelectionDecorator();
        if (decorator != null) {
            lazyTableViewer.setListSelectionLabelDecorator(decorator);
        }

        lazyTableViewer.buildUI(parent);
    }

    /**
     * A selection history which can restore a CDO Object using it's CDOID.
     * 
     * 
     * @author Christophe Bouhier
     */
    public class LazySelectionHistory extends SelectionHistory {

        private final String MEM_KEY_LAZY_OID = "MEM_KEY_LAZY_OID";
        private CDOView view;

        public LazySelectionHistory(CDOView view) {
            this.view = view;
        }

        @Override
        protected Object restoreItemFromMemento(IMemento memento) {

            String[] attributeKeys = memento.getAttributeKeys();
            if (attributeKeys.length == 1) {
                return CDOMementoUtil.retrieveCDOObject(memento, view, attributeKeys[0]);
            }
            return null;
        }

        @Override
        protected void storeItemToMemento(Object item, IMemento memento) {

            if (item instanceof CDOObject) {

                if (FSMUtil.isClean((CDOObject) item)) {
                    String cdoLongIDAsString = CDO.cdoLongIDAsString((CDOObject) item);

                    // This is the root memento, find children matching our ID.
                    IMemento[] children = memento.getChildren(this.infoNodeName);

                    for (IMemento m : children) {
                        // find a key matching our ID.
                        String[] attributeKeys = m.getAttributeKeys();
                        for (String key : attributeKeys) {
                            if (key.equals(MEM_KEY_LAZY_OID + cdoLongIDAsString)) {
                                return; // We know this one already.
                            }
                        }
                    }
                    // Remember clean CDOObjects only.

                    // Remember in a child node.
                    CDOMementoUtil.rememberCDOObject(memento.createChild(this.infoNodeName), (CDOObject) item,
                            MEM_KEY_LAZY_OID + cdoLongIDAsString);
                }
            }
        }
    }

    public class LazyTableViewer extends AbstractSmartTableViewer {

        public LazyTableViewer(Shell shell, boolean multi) {
            super(shell, multi);
        }

        public LazyTableViewer(Shell shell) {
            super(shell);
        }

        public TableViewer getTableViewer() {
            return this.tblViewer;
        }

        @Override
        protected Control createExtendedContentArea(Composite parent) {
            return null;
        }

        @Override
        public void handleDoubleClick() {
            delegateHandleDoubleClick();
        }

        @Override
        protected IStatus validateItem(Object item) {
            return delegateValidateItem(item);
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * com.netxforge.netxstudio.screens.AbstractLazyTableViewer#createFilter
         * ()
         */
        @Override
        protected IItemsFilter createFilter() {

            TextSearchPattern pattern = new TextSearchPattern();
            Control patternControl = LazyTableViewer.this.getPatternControl();
            if (patternControl instanceof Text) {
                pattern.setPattern(((Text) patternControl).getText());
            }

            // Note: We need to realize each time, the constructor reads the
            // pattern control (Text widget)
            // to get the current pattern to match against.
            lazyItemsFilter = new AbstractPatternItemsFilter(pattern) {

                @Override
                public boolean isConsistentItem(Object item) {
                    return true;
                }

                @Override
                public boolean matchItem(Object item) {
                    // As we are a generic implementation this delegates to the
                    // concrete implememtation of the IScreen.
                    return AbstractSmartTableScreen.this.delegateMatchItem(item);
                }
            };

            return lazyItemsFilter;
        }

        @Override
        protected void fillContentProvider(AbstractContentProvider contentProvider, IItemsFilter itemsFilter,
                IProgressMonitor progressMonitor) throws CoreException {

            if (ScreensActivator.DEBUG) {
                ScreensActivator.TRACE.trace(ScreensActivator.TRACE_SCREENS_OPTION, "filling content provider");
                ScreensActivator.TRACE.trace(ScreensActivator.TRACE_SCREENS_OPTION,
                        "items filter pattern: " + itemsFilter.getPattern());

            }

            final Resource delegateGetResource = delegateGetResource();

            // Do in UI thread.

            Display.getDefault().asyncExec(new Runnable() {

                public void run() {
                    if (!tblViewer.getInput().equals(delegateGetResource)) {
                        tblViewer.setInput(delegateGetResource);
                    }
                }
            });

            contentProvider.addCollection(delegateGetResource.getContents(), itemsFilter);

        }

        @Override
        public String getElementName(Object item) {
            return null;
        }

        @Override
        protected void buildColumns(TableViewer viewer) {
            delegateBuildColumns(viewer);

        }

        @Override
        protected <T> Comparator<T> getItemsComparator() {
            return delegateGetItemsComparator();
        }

    }

    /**
     * Matches items based on the default EMF
     * {@link AdapterFactoryItemDelegator#getText(Object)} method. Clients can
     * override to match items in a customized way. I.e. this could be any
     * EStructuralFeature of the EObject.
     * 
     * @param item
     * @return
     */
    protected boolean delegateMatchItem(Object item) {
        String match = adapterFactoryItemDelegator.getText(item);

        boolean result = lazyItemsFilter.matches(match);

        // make this optional, it cloudes the trace!

        // if (ScreensActivator.DEBUG) {
        // ScreensActivator.TRACE.trace(ScreensActivator.TRACE_SCREENS_OPTION,
        // "matching:" + item + " with text" + match
        // + " using pattern "
        // + lazyItemsFilter.patternMatcher.getPattern());
        //
        // ScreensActivator.TRACE.trace(ScreensActivator.TRACE_SCREENS_OPTION,
        // "result " + result);
        // }

        return result;
    }

    /*
     * Clients can override. the default implementation does nothing.
     */
    protected void delegateHandleDoubleClick() {

    }

    /*
     * Clients must implement. The source for populating items.
     */
    protected abstract List<?> delegateGetItems();

    /*
     * Clients must implement. The source for populating items.
     */
    protected abstract Resource delegateGetResource();

    /*
     * Clients can override to validation of selected items. In the context of
     * an editor (Not a selector) the need for this is limited.
     */
    protected IStatus delegateValidateItem(Object item) {
        return Status.OK_STATUS;
    }

    /*
     * Clients must implement.
     */
    public abstract CDOView delegateGetCDOView();

    /*
     * Clients must implement to provide a comparator.
     */
    public abstract <T> Comparator<T> delegateGetItemsComparator();

    /*
     * Clients can override to add columns. The default Impl. doesn't add any
     * columns.
     */
    protected void delegateBuildColumns(TableViewer viewer) {
    }

    /*
     * Clients can override to add a custom label provider.
     */
    protected IBaseLabelProvider delegateGetListLabelProvider() {
        return new LabelProvider() {

            @Override
            public String getText(Object element) {
                return adapterFactoryItemDelegator.getText(element);
            }
        };
    }

    /*
     * Clients can override to add a custom label decorator for the selected
     * element.
     */
    protected ILabelDecorator delegateGetListSelectionDecorator() {
        return null;
    }

    public Viewer getViewer() {
        return lazyTableViewer.getTableViewer();
    }

    public EMFDataBindingContext initDataBindings_() {
        return null;
    }

    @Override
    public void saveState(IMemento memento) {
        lazyTableViewer.saveState(memento);
        // sash state vertical.
        CDOMementoUtil.rememberStructuredViewerSelection(memento, lazyTableViewer.getTableViewer(),
                MementoUtil.MEM_KEY_SELECTION_TABLE);

        // Note: Not compatible with the refresh algorithm of the underlying
        // viewer.
        MementoUtil.rememberStructuredViewerColumns(memento, lazyTableViewer.getTableViewer(),
                MementoUtil.MEM_KEY_COLUMNS_TABLE);

        if (lazyItemsFilter != null) {

            TextSearchPattern pattern = (TextSearchPattern) lazyItemsFilter.getPattern();
            MementoUtil.rememberString(memento, pattern.getPattern(), MementoUtil.MEM_KEY_SEARCH_PATTERN);
        }
    }

    @Override
    public void restoreState(IMemento memento) {
        String pattern = null;
        if (memento != null) {
            lazyTableViewer.restoreState(memento);

            CDOMementoUtil.retrieveStructuredViewerSelection(memento, lazyTableViewer.getTableViewer(),
                    MementoUtil.MEM_KEY_SELECTION_TABLE, delegateGetCDOView());
            MementoUtil.retrieveStructuredViewerColumns(memento, lazyTableViewer.getTableViewer(),
                    MementoUtil.MEM_KEY_COLUMNS_TABLE);

            pattern = MementoUtil.retrieveString(memento, MementoUtil.MEM_KEY_SEARCH_PATTERN);
        }

        if (pattern == null || pattern.equals("?*")) {
            this.getLazyTableViewer().setPattern("?"); // Show all when not set.
        } else {
            this.getLazyTableViewer().setPattern(pattern);
        }
        // this.getLazyTableViewer().applyFilter(); // Just show the history/
        // lazyTableViewer.applyFilter(); // Trigger the initial filtering,
        // which
        // will show history.

    }

    public LazyTableViewer getLazyTableViewer() {
        return lazyTableViewer;
    }

    @Override
    public IAction[] getActions() {
        return new IAction[] { lazyTableViewer.getRemoveHistoryItemAction() };
    }

}