org.fusesource.ide.foundation.ui.views.ColumnViewSupport.java Source code

Java tutorial

Introduction

Here is the source code for org.fusesource.ide.foundation.ui.views.ColumnViewSupport.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/

package org.fusesource.ide.foundation.ui.views;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.properties.tabbed.ISection;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.fusesource.ide.foundation.core.functions.Function1;
import org.fusesource.ide.foundation.core.util.Objects;
import org.fusesource.ide.foundation.ui.actions.ConfigureColumnsAction;
import org.fusesource.ide.foundation.ui.chart.TableChartOptions;
import org.fusesource.ide.foundation.ui.config.ColumnConfiguration;
import org.fusesource.ide.foundation.ui.config.TableConfiguration;
import org.fusesource.ide.foundation.ui.internal.FoundationUIActivator;
import org.fusesource.ide.foundation.ui.label.ChartLabelProvider;
import org.fusesource.ide.foundation.ui.label.FunctionColumnLabelProvider;
import org.fusesource.ide.foundation.ui.label.ImageLabelProvider;
import org.fusesource.ide.foundation.ui.label.LongTimestampAsTimeThenDateLabelProvider;
import org.fusesource.ide.foundation.ui.label.TimeThenDateFunctionLabelProvider;
import org.fusesource.ide.foundation.ui.label.TimeThenDateLabelProvider;
import org.fusesource.ide.foundation.ui.tree.Refreshable;
import org.fusesource.ide.foundation.ui.util.IConfigurableColumns;
import org.fusesource.ide.foundation.ui.util.Menus;
import org.fusesource.ide.foundation.ui.util.Viewers;
import org.fusesource.ide.foundation.ui.util.Widgets;
import org.jboss.tools.jmx.jvmmonitor.ui.Activator;
import org.jboss.tools.jmx.jvmmonitor.ui.ISharedImages;

public abstract class ColumnViewSupport extends ViewPart
        implements IConfigurableColumns, IViewPage, ISection, Refreshable {

    private Action refreshAction;
    private Action chartAction;
    private Action doubleClickAction;
    private List<Function1<?, ?>> functions = new ArrayList<>();
    private IPageSite pageSite;
    private TableConfiguration configuration;
    private boolean showChartingOptions;
    protected TableChartOptions chartOptions;
    private boolean isSectionActivated;
    private ConfigureColumnsAction configureColumnsAction;
    private TabbedPropertySheetPage tabbedPropertySheetPage;
    private IChangeListener changeListener;
    private List<Object> localMenuActions = new ArrayList<>();
    private List<Object> toolBarActions = new ArrayList<>();

    public ColumnViewSupport() {
        super();
    }

    @Override
    public void init(IPageSite pageSite) {
        this.pageSite = pageSite;
    }

    public IPageSite getPageSite() {
        if (tabbedPropertySheetPage != null) {
            IPageSite answer = tabbedPropertySheetPage.getSite();
            if (answer != null) {
                return answer;
            }
        }
        return pageSite;
    }

    @Override
    public void refresh() {
        Viewers.refresh(getViewer());
    }

    public void createControl(Composite parent) {
        createPartControl(parent);
    }

    public void addLocalMenuActions(Object... newActions) {
        for (Object action : newActions) {
            localMenuActions.add(action);
        }
    }

    public void addToolBarActions(Object... newActions) {
        for (Object action : newActions) {
            toolBarActions.add(action);
        }
    }

    public Control getControl() {
        if (getViewer() == null) {
            return null;
        }
        return getViewer().getControl();
    }

    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
    }

    public void setActionBars(IActionBars actionBars) {
    }

    @Override
    public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
        this.tabbedPropertySheetPage = tabbedPropertySheetPage;
        init(tabbedPropertySheetPage.getSite());
        createPartControl(parent);
    }

    @Override
    public void setInput(IWorkbenchPart part, ISelection selection) {
    }

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

    @Override
    public void aboutToBeShown() {
        if (!isSectionActivated) {
            isSectionActivated = true;
            addToolBarActions();
            addLocalMenus();
            if (getActionBars() != null) {
                getActionBars().updateActionBars();
            }
            setSelectionProvider();
        }
    }

    protected void setSelectionProvider() {
        IWorkbenchPartSite site = getSite();
        IPageSite pageSite = getPageSite();
        if (site != null) {
            site.setSelectionProvider(getViewer());
        }
        if (tabbedPropertySheetPage instanceof TabFolderSupport2) {
            TabFolderSupport2 tfs = (TabFolderSupport2) tabbedPropertySheetPage;
            IViewSite viewSite = tfs.getViewSite();
            if (viewSite != null) {
                viewSite.setSelectionProvider(getViewer());
                /*
                PropertySheet propertySheet = tfs.getPropertySheet();
                IWorkbenchPage page = viewSite.getPage();
                IWorkbenchPart activePart = page.getActivePart();
                if (propertySheet != null) {
                   propertySheet.getSite().getPage().addPostSelectionListener(propertySheet);
                }
                 */
            }
        }
        if (pageSite != null) {
            // NOTE the following code can cause ECLIPSE-692
            // so lets not do it for now :)
            //pageSite.setSelectionProvider(getViewer());
        }
        if (site == null && pageSite == null) {
            warnNoSite();
        }
    }

    @Override
    public void aboutToBeHidden() {
        //if (isFocused() || !propertySheet.isPinned()) {
        // hidden by selecting another tab
        deactivateSection();
        //}
    }

    protected void deactivateSection() {
        if (isSectionActivated) {
            isSectionActivated = false;

            // remove tool bar actions
            IToolBarManager toolBarManager = getToolBarManager();
            if (toolBarManager != null) {
                removeToolBarActions(toolBarManager);
                toolBarManager.update(false);
            }

            // remove local menus
            IMenuManager menuManager = getMenuManager();
            if (menuManager != null) {
                removeLocalMenus(menuManager);
                menuManager.update(false);
            }

            if (getActionBars() != null) {
                getActionBars().updateActionBars();
            }
            // clear status line
            clearStatusLine();
        }
    }

    /**
     * Clears the status line.
     */
    public void clearStatusLine() {
        /*
          IStatusLineManager manager = propertySheet.getViewSite()
            .getActionBars().getStatusLineManager();
            
          IContributionItem[] items = manager.getItems();
          for (IContributionItem item : items) {
        if (item instanceof StatusLineContributionItem) {
            ((StatusLineContributionItem) item)
                    .setText(Util.ZERO_LENGTH_STRING);
        }
          }
         */
    }

    /**
     * Activates the section.
     */
    protected void activateSection() {
    }

    @Override
    public int getMinimumHeight() {
        return 0;
    }

    @Override
    public boolean shouldUseExtraSpace() {
        return true;
    }

    @Override
    public void updateColumnConfiguration(TableConfiguration configuration) {
    }

    @Override
    public void createPartControl(Composite parent) {
    }

    public abstract ColumnViewer getViewer();

    protected abstract String getHelpID();

    protected abstract void showChartDialog();

    /**
     * Adds the tool bar actions.
     */
    private void addToolBarActions() {
        IToolBarManager toolBarManager = getToolBarManager();
        if (toolBarManager != null) {
            addToolBarActions(toolBarManager);
        }
    }

    protected void addToolBarActions(IToolBarManager manager) {
        Menus.addAction(manager, refreshAction);
        if (showChartAction()) {
            Menus.addAction(manager, chartAction);
        }
        Menus.addAction(manager, toolBarActions);
    }

    protected void removeToolBarActions(IToolBarManager manager) {
        Menus.removeAction(manager, toolBarActions);
        Menus.removeAction(manager, refreshAction);
        Menus.removeAction(manager, chartAction);
    }

    protected void addLocalMenus(IMenuManager manager) {
        Menus.addAction(manager, refreshAction);
        Menus.addAction(manager, configureColumnsAction);
        if (showChartAction()) {
            Menus.addAction(manager, chartAction);
        }
        Menus.addAction(manager, localMenuActions);
    }

    protected void removeLocalMenus(IMenuManager manager) {
        Menus.removeAction(manager, refreshAction);
        Menus.removeAction(manager, configureColumnsAction);
        Menus.removeAction(manager, chartAction);
        Menus.removeAction(manager, localMenuActions);
    }

    /*
    protected void fillContextMenu(IMenuManager manager) {
       manager.add(refreshAction);
       if (showChartAction()) {
     manager.add(chartAction);
       }
       manager.add(new ConfigureColumnsAction(this));
       // Other plug-ins can contribute there actions here
       manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }
     */

    /**
     * Adds the local menus.
     */
    private void addLocalMenus() {
        IMenuManager menuManager = getMenuManager();
        if (menuManager != null) {
            addLocalMenus(menuManager);
            menuManager.setVisible(true);
        }
    }

    protected IMenuManager getMenuManager() {
        IActionBars actionBars = getActionBars();
        IMenuManager menuManager = null;
        if (actionBars != null) {
            menuManager = actionBars.getMenuManager();
        }
        return menuManager;
    }

    protected IToolBarManager getToolBarManager() {
        IActionBars actionBars = getActionBars();
        IToolBarManager answer = null;
        if (actionBars != null) {
            answer = actionBars.getToolBarManager();
        }
        return answer;
    }

    protected IActionBars getActionBars() {
        IPageSite pageSite = getPageSite();
        IActionBars actionBars = null;
        if (pageSite != null) {
            actionBars = pageSite.getActionBars();
        }
        if (actionBars == null) {
            IViewSite viewSite = getViewSite();
            if (viewSite != null) {
                actionBars = viewSite.getActionBars();
            }
        }
        return actionBars;
    }

    protected void addFunction(Function1<?, ?> function) {
        functions.add(function);
    }

    protected void clearColumns() {
        functions.clear();
    }

    /*
    protected void hookContextMenu() {
       MenuManager menuMgr = new MenuManager("#PopupMenu");
       menuMgr.setRemoveAllWhenShown(true);
       menuMgr.addMenuListener(new IMenuListener() {
     @Override
     public void menuAboutToShow(IMenuManager manager) {
        ColumnViewSupport.this.fillContextMenu(manager);
     }
       });
       menu = menuMgr.createContextMenu(getViewer().getControl());
       getViewer().getControl().setMenu(menu);
       IWorkbenchPartSite site = getSite();
       if (site != null) {
     site.registerContextMenu(menuMgr, getViewer());
       } else if (pageSite != null) {
     // TODO use a different ID?
     pageSite.registerContextMenu(getHelpID(), menuMgr, getViewer());
       } else {
     warnNoSite();
       }
    }
        
    protected void contributeToActionBars() {
       IActionBars bars = null;
       if (getViewSite() != null) {
     bars = getViewSite().getActionBars();
       } else if (pageSite != null) {
     bars = pageSite.getActionBars();
       } else {
     warnNoSite();
     return;
       }
       fillLocalPullDown(bars.getMenuManager());
       fillLocalToolBar(bars.getToolBarManager());
    }
     */

    protected void warnNoSite() {
        FoundationUIActivator.pluginLog().logWarning("No IViewSite or IPageSite registered for " + this);
    }

    protected void makeActions() {
        refreshAction = new Action() {
            @Override
            public void run() {
                refresh();
            }
        };
        refreshAction.setId(getClass().getName() + ".refresh");
        refreshAction.setText("Refresh");
        refreshAction.setToolTipText("Refreshes the view");
        refreshAction.setImageDescriptor(Activator.getImageDescriptor(ISharedImages.REFRESH_IMG_PATH));

        configureColumnsAction = new ConfigureColumnsAction(this);

        chartAction = new Action() {
            @Override
            public void run() {
                showChartDialog();
            }
        };
        chartAction.setId(getClass().getName() + ".chart");
        chartAction.setText("Create Chart");
        chartAction.setToolTipText("Create a chart from the current table");
        chartAction.setImageDescriptor(FoundationUIActivator.getDefault().getSharedImages()
                .descriptor(FoundationUIActivator.IMAGE_CHART_ICON));

        if (doubleClickAction == null) {
            doubleClickAction = new Action() {
                @Override
                public void run() {
                    ISelection selection = getViewer().getSelection();
                    doubleClickSelection(selection);
                }
            };
            doubleClickAction.setId(getClass().getName() + ".doubleClick");
        }
    }

    public Action getDoubleClickAction() {
        return doubleClickAction;
    }

    public void setDoubleClickAction(Action doubleClickAction) {
        this.doubleClickAction = doubleClickAction;
    }

    protected void doubleClickSelection(ISelection selection) {
        ((IStructuredSelection) selection).getFirstElement();
    }

    protected void hookDoubleClickAction() {
        Widgets.setDoubleClickAction(getViewer(), doubleClickAction);
    }

    protected void showMessage(String message) {
        MessageDialog.openInformation(getViewer().getControl().getShell(), "Message View", message);
    }

    @Override
    public abstract List<String> getColumns();

    @Override
    public boolean getDefaultVisibility(String column) {
        return true;
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        getViewer().getControl().setFocus();
    }

    @Override
    public TableConfiguration getConfiguration() {
        if (configuration == null) {
            configuration = TableConfiguration.loadConfiguration(getColumnConfigurationId());
            configuration.addDefaultColumns(getColumns());
        }
        return configuration;
    }

    protected abstract TableChartOptions createChartOptions();

    public void setConfiguration(TableConfiguration configuration) {
        if (configuration != this.configuration) {
            if (this.configuration != null) {
                this.configuration.removeColumnListeners(getViewer());
            }
            this.configuration = configuration;
            if (this.configuration != null) {
                this.configuration.addColumnListeners(getViewer());
            }
        }
    }

    protected boolean showChartAction() {
        return showChartingOptions && chartOptions.isValid();
    }

    public TableChartOptions getChartOptions() {
        if (chartOptions == null) {
            chartOptions = createChartOptions();
        }
        return chartOptions;
    }

    /**
     * Based on the table configuration and defaults lets update the label provider for the column
     */
    protected void configureLabelProvider(ViewerColumn viewerColumn, ColumnConfiguration config,
            CellLabelProvider labelProvider) {
        Class<?> returnType = Objects.getReturnType(labelProvider);
        String style = config.getLabelProviderStyle();
        FunctionColumnLabelProvider flp = null;
        if (labelProvider instanceof FunctionColumnLabelProvider) {
            flp = (FunctionColumnLabelProvider) labelProvider;
            returnType = flp.getReturnType();
        }
        if (viewerColumn != null) {
            CellLabelProvider provider = config.getLabelProvider();
            if (provider != null) {
                viewerColumn.setLabelProvider(provider);
            } else {
                if (style != null && style.equals("timeThenDate")) {
                    if (flp != null) {
                        viewerColumn.setLabelProvider(new TimeThenDateFunctionLabelProvider(flp.getFunction()));
                    } else {
                        viewerColumn.setLabelProvider(new TimeThenDateLabelProvider());
                    }
                } else if (style != null && style.equals("longTimestampAsTimeThenDate")) {
                    viewerColumn.setLabelProvider(new LongTimestampAsTimeThenDateLabelProvider());
                } else if (Objects.isNumberType(returnType)) {
                    if (style == null || !style.equals("plain")) {
                        viewerColumn.setLabelProvider(new ChartLabelProvider(labelProvider, getViewer()));
                    }
                } else if (Objects.equal(style, "image") && flp != null) {
                    viewerColumn.setLabelProvider(new ImageLabelProvider(flp.getFunction()));
                }
            }
        }
    }

    /*
    protected boolean hasLabelProvider(ViewerColumn viewerColumn) {
       // lets use reflection
       Field field;
       try {
     field = ViewerColumn.class.getDeclaredField("labelProvider");
     field.setAccessible(true);
     Object provider = field.get(viewerColumn);
     return provider != null;
       } catch (Exception e) {
     Activator.getLogger().debug("Failed to get labelProvider field: " + e);
     return false;
       }
    }
     */

    protected void setInput(Object input) {
        ObservableLists.removeListener(getViewer().getInput(), getChangeListener());
        ObservableLists.addListener(input, getChangeListener());
        Viewers.setInput(getViewer(), input);
        // TODO is this needed?
        //getViewer().refresh();
    }

    protected IChangeListener getChangeListener() {
        if (changeListener == null) {
            changeListener = new IChangeListener() {
                @Override
                public void handleChange(ChangeEvent event) {
                    refreshViewerOnChange();
                }
            };
        }
        return changeListener;
    }

    /**
     * The underlying model has changed so refresh the viewer
     */
    protected void refreshViewerOnChange() {
        Viewers.refresh(getViewer());
    }

    public class ColumnFunctionComparator extends ViewerComparator {
        public static final int ASCENDING = 0;
        public static final int DESCENDING = 1;

        private int propertyIndex;
        private int defaultSortColumnIndex;
        private int direction = DESCENDING;

        public ColumnFunctionComparator() {
            this.propertyIndex = 0;
            direction = DESCENDING;
        }

        public void setDefaultSortColumn(int column) {
            defaultSortColumnIndex = column;
            setColumn(column);
        }

        public void setColumn(int column) {
            if (column == this.propertyIndex) {
                // Same column as last sort; toggle the direction
                direction = 1 - direction;
            } else {
                // New column; do an ascending sort
                this.propertyIndex = column;
                direction = ASCENDING;
            }
        }

        public void setDescending(boolean descending) {
            if (descending) {
                direction = DESCENDING;
            } else {
                direction = ASCENDING;
            }
        }

        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
            return compareByColumn(e1, e2, propertyIndex);
        }

        protected int compareByColumn(Object e1, Object e2, int sortIndex) {
            int answer = 0;
            if (sortIndex < 0 || sortIndex >= functions.size()) {
                answer = compareDefaultSortColumn(e1, e2, sortIndex);
            } else {
                Function1 function = functions.get(sortIndex);
                Object v1 = function.apply(e1);
                Object v2 = function.apply(e2);
                answer = Objects.compare(v1, v2);
                if (answer == 0) {
                    answer = compareDefaultSortColumn(e1, e2, sortIndex);
                }
            }
            if (direction == DESCENDING) {
                answer = -answer;
            }
            return answer;
        }

        public int compareDefaultSortColumn(Object e1, Object e2, int sortIndex) {
            if (sortIndex == defaultSortColumnIndex) {
                return Objects.compare(e1, e2);
            } else {
                return compareByColumn(e1, e2, defaultSortColumnIndex);
            }
        }

    }
}