com.bdaum.zoom.ui.internal.views.TableView.java Source code

Java tutorial

Introduction

Here is the source code for com.bdaum.zoom.ui.internal.views.TableView.java

Source

/*
 * This file is part of the ZoRa project: http://www.photozora.org.
 *
 * ZoRa 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 2 of the License, or
 * (at your option) any later version.
 *
 * ZoRa 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 ZoRa; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * (c) 2009 Berthold Daum  
 */

package com.bdaum.zoom.ui.internal.views;

import java.text.NumberFormat;
import java.text.ParseException;
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 java.util.StringTokenizer;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ILazyContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.piccolo2d.extras.swt.PSWTCanvas;

import com.bdaum.zoom.cat.model.asset.Asset;
import com.bdaum.zoom.cat.model.asset.AssetImpl;
import com.bdaum.zoom.cat.model.group.SortCriterionImpl;
import com.bdaum.zoom.core.BagChange;
import com.bdaum.zoom.core.Core;
import com.bdaum.zoom.core.Format;
import com.bdaum.zoom.core.IAssetProvider;
import com.bdaum.zoom.core.IVolumeManager;
import com.bdaum.zoom.core.QueryField;
import com.bdaum.zoom.core.internal.AssetProvider;
import com.bdaum.zoom.core.internal.CoreActivator;
import com.bdaum.zoom.core.internal.IMediaSupport;
import com.bdaum.zoom.css.ZColumnLabelProvider;
import com.bdaum.zoom.css.internal.CssActivator;
import com.bdaum.zoom.css.internal.IExtendedColorModel;
import com.bdaum.zoom.ui.AssetSelection;
import com.bdaum.zoom.ui.INavigationHistory;
import com.bdaum.zoom.ui.IZoomActionConstants;
import com.bdaum.zoom.ui.internal.HelpContextIds;
import com.bdaum.zoom.ui.internal.UiActivator;
import com.bdaum.zoom.ui.internal.dialogs.ConfigureColumnsDialog;
import com.bdaum.zoom.ui.internal.hover.IGalleryHover;
import com.bdaum.zoom.ui.internal.job.DecorateJob;
import com.bdaum.zoom.ui.preferences.PreferenceConstants;

@SuppressWarnings("restriction")
public class TableView extends AbstractGalleryView implements IExtendedColorModel {

    public static final String ID = "com.bdaum.zoom.ui.views.TableView"; //$NON-NLS-1$

    private static final String KEY = "key"; //$NON-NLS-1$

    private static final String COLUMNWIDTH = "COLUMNWIDTH"; //$NON-NLS-1$

    private class TableDecorateJob extends DecorateJob {

        private TableViewer viewer;
        private TableItem[] items;
        private final TableView view;

        private Runnable itemRunnable = new Runnable() {
            public void run() {
                Table table = viewer.getTable();
                if (!table.isDisposed())
                    items = table.getItems();
            }
        };

        private Runnable assetRunnable = new Runnable() {
            public void run() {
                Table table = viewer.getTable();
                for (TableItem item : items)
                    if (item != null && !item.isDisposed()) {
                        AssetImpl asset = (AssetImpl) item.getData();
                        if (asset != null)
                            switch (volumeManager.determineFileState(asset)) {
                            case IVolumeManager.REMOTE:
                                if (remoteColor != null)
                                    item.setForeground(remoteColor);
                                break;
                            case IVolumeManager.OFFLINE:
                                if (offlineColor != null)
                                    item.setForeground(offlineColor);
                                break;
                            default:
                                item.setForeground(table.getForeground());
                                break;
                            }
                    }
                table.redraw();
                items = null;
            }
        };

        public TableDecorateJob(TableView view, final TableViewer viewer) {
            super(Messages.getString("TableView.decorate_table_view")); //$NON-NLS-1$
            this.view = view;
            this.viewer = viewer;
        }

        @Override
        protected boolean mayRun() {
            return view.isVisible() && refreshing <= 0 && super.mayRun();
        }

        @Override
        protected void doRun(IProgressMonitor monitor) {
            final Table table = viewer.getTable();
            if (!table.isDisposed()) {
                Display display = table.getDisplay();
                display.syncExec(itemRunnable);
                if (items != null && items.length > 0 && items[0] != null && mayRun())
                    display.asyncExec(assetRunnable);
            }
        }
    }

    private class ThumbnailLabelProvider extends OwnerDrawLabelProvider {

        @Override
        protected void measure(Event event, Object element) {
            event.width = thumbsize;
            event.height = thumbsize;
        }

        @Override
        protected void erase(Event event, Object element) {
            // do nothing
        }

        @Override
        protected void paint(Event event, Object element) {
            Image image = getImage(element);
            if (image != null) {
                GC gc = event.gc;
                Rectangle bounds = image.getBounds();
                int width = thumbsize; // event.width;
                int height = thumbsize; // event.height;
                double fac = Math.min(((float) width) / bounds.width, ((float) height) / bounds.height);
                int w = (int) (bounds.width * fac);
                int h = (int) (bounds.height * fac);
                gc.drawImage(image, 0, 0, bounds.width, bounds.height, event.x + (width - w) / 2,
                        event.y + (width - h) / 2, w, h);
            }
        }
    }

    private class MetaDataLabelProvider extends ZColumnLabelProvider {

        private final QueryField qfield;

        public MetaDataLabelProvider(QueryField qfield) {
            this.qfield = qfield;
        }

        @Override
        public String getText(Object element) {
            if (element instanceof Asset) {
                Asset a = (Asset) element;
                IMediaSupport mediaSupport = CoreActivator.getDefault().getMediaSupport(a.getFormat());
                if (mediaSupport != null && !qfield.testFlags(mediaSupport.getPropertyFlags()))
                    return Messages.getString("TableView.na"); //$NON-NLS-1$
                if (qfield == QueryField.SCORE)
                    return (scoreFormatter != null) ? scoreFormatter.format(a.getScore()) : ""; //$NON-NLS-1$
                String text = qfield.value2text(qfield.obtainFieldValue(a), ""); //$NON-NLS-1$
                return qfield.addUnit(text, " ", ""); //$NON-NLS-1$ //$NON-NLS-2$
            }
            return element.toString();
        }

    }

    public class ViewEditingSupport extends EditingSupport {

        private final QueryField qfield;

        public ViewEditingSupport(ColumnViewer viewer, QueryField qfield) {
            super(viewer);
            this.qfield = qfield;
        }

        @Override
        protected boolean canEdit(Object element) {
            if (dbIsReadonly())
                return false;
            if (element instanceof AssetImpl)
                return qfield.isEditable((AssetImpl) element);
            return false;
        }

        @Override
        protected CellEditor getCellEditor(Object element) {
            if (element instanceof AssetImpl)
                return determineCellEditor(qfield, (Composite) getViewer().getControl(), 32);
            return null;
        }

        @Override
        protected Object getValue(Object element) {
            if (element instanceof Asset) {
                Object fieldValue = qfield.obtainFieldValue((Asset) element);
                if (qfield.getCard() == QueryField.CARD_MODIFIABLEBAG)
                    return fieldValue;
                if (fieldValue instanceof Integer && qfield.getEnumeration() == null)
                    return String.valueOf(fieldValue);
                if (fieldValue instanceof Double) {
                    NumberFormat nf = NumberFormat.getInstance();
                    if (qfield.getType() == QueryField.T_CURRENCY) {
                        int digits = Format.getCurrencyDigits();
                        nf.setMaximumFractionDigits(digits);
                        nf.setMinimumFractionDigits(digits);
                    } else
                        nf.setMaximumFractionDigits(qfield.getMaxlength());
                    return nf.format(fieldValue);
                }
                return fieldValue;
            }
            return null;
        }

        @Override
        protected void setValue(Object element, Object value) {
            if (element instanceof Asset && value != null) {
                if (qfield.getCard() == QueryField.CARD_MODIFIABLEBAG) {
                    if (value instanceof BagChange)
                        updateAssets(value, qfield.obtainFieldValue((Asset) element), qfield);
                    return;
                }
                switch (qfield.getType()) {
                case QueryField.T_INTEGER:
                case QueryField.T_POSITIVEINTEGER:
                    if (!(value instanceof Integer))
                        value = Integer.valueOf(Integer.parseInt(value.toString()));
                    break;
                case QueryField.T_FLOAT:
                case QueryField.T_POSITIVEFLOAT:
                case QueryField.T_CURRENCY:
                    if (!(value instanceof Double)) {
                        NumberFormat nf = NumberFormat.getInstance();
                        nf.setMaximumFractionDigits(8);
                        try {
                            value = new Double(nf.parse(value.toString()).doubleValue());
                        } catch (ParseException e) {
                            return;
                        }
                    }
                }
                updateAssetsIfNecessary(qfield, value, qfield.obtainFieldValue((Asset) element));
            }
        }
    }

    private static final String SORT_COLUMN = "sortColumn"; //$NON-NLS-1$

    private static final String SORT_DIRECTION = "sortDirection"; //$NON-NLS-1$

    private TableViewer gallery;

    private String sortColumn;

    private int sortDirection = SWT.DOWN;

    private TableViewerColumn imageColumn;

    private Map<String, Integer> columnWidths = new HashMap<String, Integer>();

    protected Widget selectedColumn;

    private TableViewerColumn scoreColumn;

    private Color offlineColor;

    private Color remoteColor;

    private List<QueryField> displayedFields = new ArrayList<QueryField>();

    private int thumbsizeLowWatermark;

    @Override
    public void init(IViewSite site, IMemento memento) throws PartInitException {
        super.init(site, memento);
        if (memento != null) {
            sortColumn = memento.getString(SORT_COLUMN);
            try {
                Integer i = memento.getInteger(SORT_DIRECTION);
                sortDirection = i != null ? i : SWT.DOWN;
            } catch (Exception e) {
                // do nothing
            }
            IMemento child = memento.getChild(COLUMNWIDTH);
            if (child != null)
                for (String key : child.getAttributeKeys())
                    columnWidths.put(key, child.getInteger(key));
        }
    }

    @Override
    public void saveState(IMemento memento) {
        if (memento != null) {
            if (sortColumn != null) {
                memento.putString(SORT_COLUMN, sortColumn);
                memento.putInteger(SORT_DIRECTION, sortDirection);
            }
            IMemento child = memento.getChild(COLUMNWIDTH);
            if (child == null)
                child = memento.createChild(COLUMNWIDTH);
            for (Map.Entry<String, Integer> entry : columnWidths.entrySet())
                child.putInteger(entry.getKey(), entry.getValue());
        }
        super.saveState(memento);
    }

    @Override
    public void createPartControl(Composite parent) {
        thumbsizeLowWatermark = thumbsize;
        createGallery(parent, false);
        makeActions(getViewSite().getActionBars());
        installListeners();
        // Hover
        installHoveringController();
        addCueListener();
        // Contributions
        contributeToActionBars();
        setDecorator(gallery.getControl(), new TableDecorateJob(this, gallery));
        setSortCriterion();
        updateActions(false);
        InstanceScope.INSTANCE.getNode(UiActivator.PLUGIN_ID)
                .addPreferenceChangeListener(new IPreferenceChangeListener() {
                    public void preferenceChange(PreferenceChangeEvent event) {
                        if (PreferenceConstants.TABLECOLUMNS.equals(event.getKey())) {
                            recreateGallery();
                        }
                    }
                });
    }

    private void createGallery(Composite parent, boolean recreate) {
        gallery = new TableViewer(parent,
                SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(gallery.getControl(), HelpContextIds.TABLE_VIEW);
        themeChanged();
        gallery.setContentProvider(new ILazyContentProvider() {
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
                // do nothing
            }

            public void dispose() {
                // do nothing
            }

            public void updateElement(int index) {
                IAssetProvider assetProvider = getAssetProvider();
                if (assetProvider != null) {
                    Asset asset = assetProvider.getAsset(index);
                    if (asset != null) {
                        synchronized (gallery) {
                            gallery.replace(asset, index);
                        }
                    }
                }
            }
        });
        final Table table = gallery.getTable();
        if (!recreate)
            setAppStarting(table);
        table.setLinesVisible(true);
        table.setHeaderVisible(true);
        // Construct columns
        List<String> props = new ArrayList<String>();
        imageColumn = new TableViewerColumn(gallery, SWT.NONE);
        TableColumn icolumn = imageColumn.getColumn();
        icolumn.setWidth(thumbsize);
        icolumn.setResizable(false);
        icolumn.setText(Messages.getString("TableView.configure")); //$NON-NLS-1$
        imageColumn.setLabelProvider(new ThumbnailLabelProvider());
        icolumn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                ConfigureColumnsDialog dialog = new ConfigureColumnsDialog(getSite().getShell());
                dialog.create();
                dialog.getShell().setLocation(gallery.getControl().toDisplay(e.x, e.y));
                dialog.open();
            }
        });
        props.add("$"); //$NON-NLS-1$
        QueryField scoreField = QueryField.SCORE;
        scoreColumn = createColumn(table, scoreField, Messages.getString("TableView.score"), 50, //$NON-NLS-1$
                new MetaDataLabelProvider(scoreField));
        props.add(scoreField.getKey());
        StringTokenizer st = new StringTokenizer(
                UiActivator.getDefault().getPreferenceStore().getString(PreferenceConstants.TABLECOLUMNS), "\n"); //$NON-NLS-1$
        displayedFields.clear();
        while (st.hasMoreTokens()) {
            String id = st.nextToken();
            QueryField qfield = QueryField.findQueryField(id);
            if (qfield != null) {
                displayedFields.add(qfield);
                createColumn(table, qfield, qfield.getLabel(), 120, new MetaDataLabelProvider(qfield));
                props.add(id);
            }
        }
        gallery.setColumnProperties(props.toArray(new String[props.size()]));
        gallery.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                if (refreshing <= 0) {
                    stopAudio();
                    selection = doGetAssetSelection();
                    fireSelection();
                }
            }
        });
        ZColumnViewerToolTipSupport.enableFor(gallery);
        addKeyListener();
        addGestureListener(gallery.getTable());
        addExplanationListener(false);
        addDragDropSupport();
        hookContextMenu();
        hookDoubleClickAction();
    }

    private TableViewerColumn createColumn(final Table table, QueryField qfield, String label, int defaultWidth,
            CellLabelProvider labelProvider) {
        final String key = qfield.getKey();
        TableViewerColumn tableViewerColumn = new TableViewerColumn(gallery, SWT.NONE);
        final TableColumn column = tableViewerColumn.getColumn();
        column.setText(label);
        column.setData(KEY, key);
        Integer w = columnWidths.get(key);
        column.setWidth(w != null ? w : defaultWidth);
        column.setResizable(true);
        column.addControlListener(new ControlAdapter() {
            @Override
            public void controlResized(ControlEvent e) {
                int width = column.getWidth();
                if (width > 0)
                    columnWidths.put(key, width);
            }
        });
        column.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (refreshing > 0)
                    return;
                switchSort(table, key, column);
            }
        });
        tableViewerColumn.setLabelProvider(labelProvider);
        if (key.equals(sortColumn)) {
            table.setSortColumn(column);
            table.setSortDirection(sortDirection);
        }
        if (qfield.canEdit() && qfield.getKey() != null && !(qfield.isStruct() && qfield.getCard() != 1)
                && qfield.getType() != QueryField.T_NONE)
            tableViewerColumn.setEditingSupport(new ViewEditingSupport(gallery, qfield));
        return tableViewerColumn;
    }

    private void switchSort(final Table table, final String key, final TableColumn column) {
        if (key.equals(sortColumn))
            sortDirection = sortDirection == SWT.DOWN ? SWT.UP : SWT.DOWN;
        else {
            sortColumn = key;
            sortDirection = SWT.DOWN;
        }
        table.setSortColumn(column);
        table.setSortDirection(sortDirection);
        setSortCriterion();
    }

    private void setSortCriterion() {
        if (sortColumn != null)
            getNavigationHistory().sortChanged(new SortCriterionImpl(sortColumn, null, sortDirection == SWT.UP));
    }

    @Override
    public void sortChanged() {
        redrawCollection(null, null);
        fireSelection();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        super.keyReleased(e);
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // do nothing
    }

    protected void hookDoubleClickAction() {
        gallery.getTable().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDoubleClick(MouseEvent e) {
                IStructuredSelection sel = gallery.getStructuredSelection();
                Event event = new Event();
                event.data = sel.getFirstElement();
                event.stateMask = e.stateMask;
                viewImageAction.runWithEvent(event);
            }
        });
    }

    @Override
    protected void makeActions(IActionBars bars) {
        createScaleContributionItem(MINTHUMBSIZE, MAXTHUMBSIZE / 2);
        super.makeActions(bars);
    }

    @Override
    protected void fillContextMenu(IMenuManager manager) {
        updateActions(true);
        boolean readOnly = dbIsReadonly();
        fillEditAndSearchGroup(manager, readOnly);
        fillRotateGroup(manager, readOnly);
        fillVoiceNote(manager, readOnly);
        fillMetaData(manager, readOnly);
        fillRelationsGroup(manager);
        manager.add(new Separator(IZoomActionConstants.MB_SUBMENUS));
        fillShowAndDeleteGroup(manager, readOnly);
        super.fillAdditions(manager);
    }

    @Override
    public void setFocus() {
        gallery.getControl().setFocus();
    }

    @Override
    protected void fireSizeChanged() {
        Object firstElement = ((IStructuredSelection) getSelection()).getFirstElement();
        Object item = null;
        if (firstElement instanceof AssetImpl)
            item = firstElement;
        firstElement = ((IStructuredSelection) getSelection()).getFirstElement();
        if (thumbsizeLowWatermark > thumbsize)
            recreateGallery();
        else {
            imageColumn.getColumn().setWidth(thumbsize);
            gallery.refresh();
        }
        thumbsizeLowWatermark = Math.min(thumbsizeLowWatermark, thumbsize);
        if (firstElement != null)
            gallery.reveal(item);
    }

    private void recreateGallery() {
        try {
            ++refreshing;
            ISelection sel = gallery.getSelection();
            unhookContextMenu();
            hoveringController.uninstall();
            gallery.setItemCount(0);
            Table oldTable = gallery.getTable();
            oldTable.setVisible(false);
            Composite parent = oldTable.getParent();
            for (TableColumn column : oldTable.getColumns())
                column.dispose();
            oldTable.dispose();
            createGallery(parent, true);
            gallery.setItemCount(getAssetProvider().getAssetCount());
            parent.layout();
            installHoveringController();
            gallery.setSelection(sel);
            gallery.getControl().setFocus();
        } finally {
            --refreshing;
        }
    }

    public boolean cursorOverImage(int x, int y) {
        ViewerCell cell = gallery.getCell(new Point(x, y));
        return (cell != null) ? (cell.getElement() instanceof AssetImpl) : false;
    }

    @Override
    public void themeChanged() {
        CssActivator.getDefault().applyExtendedStyle(gallery.getTable(), this);
    }

    public void setOfflineColor(org.eclipse.swt.graphics.Color c) {
        offlineColor = c;
    }

    public void setSelectedOfflineColor(Color selectedOfflineColor) {
        // do nothing
    }

    public void setRemoteColor(org.eclipse.swt.graphics.Color c) {
        remoteColor = c;
    }

    public void setTitleColor(org.eclipse.swt.graphics.Color c) {
        // not used
    }

    public void setSelectedRemoteColor(Color selectedRemoteColor) {
        // do nothing
    }

    public boolean applyColorsTo(Object element) {
        return element instanceof PSWTCanvas;
    }

    @Override
    public IAssetProvider getAssetProvider() {
        IAssetProvider assetProvider = Core.getCore() == null ? null : Core.getCore().getAssetProvider();
        return assetProvider instanceof AssetProvider ? ((AssetProvider) assetProvider).getSlave(ID) : null;
    }

    @Override
    protected boolean doRedrawCollection(Collection<? extends Asset> assets, QueryField node) {
        thumbsizeLowWatermark = thumbsize;
        if (gallery == null || gallery.getControl().isDisposed())
            return false;
        if (assets == null) {
            AssetSelection oldSelection = (AssetSelection) (selection == null ? AssetSelection.EMPTY : selection);
            if (fetchAssets()) {
                IAssetProvider assetProvider = getAssetProvider();
                scoreFormatter = assetProvider.getScoreFormatter();
                TableColumn scolumn = scoreColumn.getColumn();
                if (scoreFormatter != null) {
                    scolumn.setText(scoreFormatter.getLabel());
                    scolumn.setResizable(true);
                    scolumn.setWidth(50);
                    Integer w = columnWidths.get(QueryField.SCORE.getKey());
                    scolumn.setWidth(w != null ? w : 50);
                } else {
                    scolumn.setWidth(0);
                    scolumn.setResizable(false);
                }
                gallery.setItemCount(assetProvider.getAssetCount());
                gallery.refresh();
                if (oldSelection.isPicked()) {
                    gallery.setSelection(oldSelection);
                    selection = new AssetSelection(oldSelection.toList());
                } else {
                    selection = new AssetSelection(assetProvider);
                    gallery.getTable().selectAll();
                }
            }
        } else {
            String[] props = null;
            if (node != null) {
                final List<String> nodes = new ArrayList<String>();
                QueryField.Visitor qfVisitor = new QueryField.Visitor() {
                    @Override
                    public void doVisitorWork(QueryField qf) {
                        String key = qf.getKey();
                        if (key != null)
                            nodes.add(key);
                    }
                };
                qfVisitor.visit(node);
                props = nodes.toArray(new String[nodes.size()]);
            }
            gallery.update(assets.toArray(), props);
        }
        return true;
    }

    @Override
    public void setAssetSelection(AssetSelection assetSelection) {
        selection = assetSelection;
        if (assetSelection.isPicked())
            gallery.setSelection(assetSelection, true);
        else
            gallery.getTable().selectAll();
        fireSelection();
    }

    public Object findObject(MouseEvent e) {
        return findObject(e.x, e.y);
    }

    public Object findObject(int x, int y) {
        ViewerCell cell = gallery.getCell(new Point(x, y));
        return (cell != null && cell.getElement() instanceof AssetImpl) ? (AssetImpl) cell.getElement() : null;
    }

    public AssetSelection getAssetSelection() {
        if (selection instanceof AssetSelection)
            return (AssetSelection) selection;
        return doGetAssetSelection();
    }

    protected AssetSelection doGetAssetSelection() {
        IStructuredSelection s = gallery.getStructuredSelection();
        AssetSelection sel = new AssetSelection(s.size());
        for (Object item : s.toArray())
            sel.add((Asset) item);
        return sel;
    }

    @Override
    protected int getSelectionCount(boolean local) {
        if (local) {
            int i = 0;
            @SuppressWarnings("unchecked")
            Iterator<Object> iterator = gallery.getStructuredSelection().iterator();
            while (iterator.hasNext()) {
                Asset a = (Asset) iterator.next();
                if (a.getFileState() != IVolumeManager.PEER && ++i >= 2)
                    return i;
            }
            return i;
        }
        return ((IStructuredSelection) getSelection()).size();
    }

    public Control getControl() {
        return gallery.getControl();
    }

    @Override
    public boolean assetsChanged() {
        INavigationHistory navigationHistory = getNavigationHistory();
        if (navigationHistory != null) {
            AssetSelection selectedAssets = navigationHistory.getSelectedAssets();
            if (selectedAssets.isPicked()) {
                gallery.setSelection(selectedAssets);
                if (!selectedAssets.isEmpty())
                    gallery.reveal(selectedAssets.get(0));
            } else
                gallery.getTable().selectAll();
            selection = selectedAssets;
            return true;
        }
        return false;
    }

    @Override
    public void catalogModified() {
        IAssetProvider assetProvider = getAssetProvider();
        if (assetProvider != null)
            assetProvider.resetProcessor();
        super.catalogModified();
    }

    @Override
    public void assetsModified(final Collection<? extends Asset> assets, final QueryField node) {
        Shell shell = getSite().getShell();
        if (!shell.isDisposed()) {
            boolean invalid = CoreActivator.getDefault().resetInfrastructure(getAssetProvider(), assets, node);
            Display display = shell.getDisplay();
            if (assets == null || invalid) {
                display.asyncExec(() -> {
                    if (!shell.isDisposed()) {
                        redrawCollection(assets, node);
                        if (selection instanceof AssetSelection) {
                            Object firstElement = ((AssetSelection) selection).getFirstElement();
                            if (firstElement != null)
                                gallery.reveal(firstElement);
                        }
                    }
                });
            } else if (node == null || affectsDisplayedFields(node)) {
                display.asyncExec(() -> {
                    if (!shell.isDisposed())
                        for (Asset asset : assets)
                            gallery.update(asset, null);
                });
            }
            display.asyncExec(() -> {
                if (!shell.isDisposed())
                    updateActions(false);
            });
        }
    }

    private boolean affectsDisplayedFields(QueryField node) {
        for (QueryField field : displayedFields)
            if (QueryField.belongsTo(field, node))
                return true;
        return false;
    }

    public void setSelection(ISelection selection) {
        assetsChanged();
    }

    @Override
    public IGalleryHover getGalleryHover(MouseEvent event) {
        return (event.x > gallery.getTable().getColumn(0).getWidth()) ? null : new GalleryHover();
    }

    @Override
    protected void setDefaultPartName() {
        setPartName(Messages.getString("TableView.table")); //$NON-NLS-1$
    }

}