blob: f6da1a44fc113a6bc06d4e725755e0e46b07da14 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 ALL4TEC & CEA LIST.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ALL4TEC & CEA LIST - initial API and implementation
******************************************************************************/
package org.polarsys.esf.core.common.ui.view;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.polarsys.esf.core.common.ui.CommonUIActivator;
/**
* Abstract base of all the Pages to use in a PageBookView,
* and which includes a tree.
*
* This implementation doesn't manage the columns in the tree,
* but it inherits of all the standard mechanisms like the filters, the editing domain mechanisms, etc.
*
* @author $Author: jdumont $
* @version $Revision: 83 $
*/
public abstract class AbstractColumnViewerPage
extends AbstractPage {
/**
* Name of the required column.
* The required column is mandatory and can't be hidden.
*/
private String mRequiredColumnName = null;
/** Arrays of the optional columns names, which can be displayed in the tree view. */
private String[] mColumnsNamesArray = null;
/**
* Default constructor, which allows to specify if the viewer must be read only or not.
*
* @param pReadOnlyMode <code>true</code> if this view is in read only mode, <code>false</code> otherwise
*/
public AbstractColumnViewerPage(final boolean pReadOnlyMode) {
// Call the advanced constructor with default values
this(StringUtils.EMPTY, new String[0], pReadOnlyMode);
}
/**
* Advanced constructor which takes the name of the required column, an array with the optional columns name,
* and a boolean which specifies if the viewer must be in read only mode or not.
*
* The required column will mandatory be visible and can't be hidden.
*
* @param pRequiredColumnName The name of the required column name
* @param pColumnsName The array of optional columns name. This list must not contain the required column name
* @param pReadOnlyMode <code>true</code> if this view is in read only mode, <code>false</code> otherwise
*/
public AbstractColumnViewerPage(
final String pRequiredColumnName,
final String[] pColumnsName,
final boolean pReadOnlyMode) {
// Call the parent constructor
super(pReadOnlyMode);
// Remember the given columns names
mRequiredColumnName = pRequiredColumnName;
mColumnsNamesArray = pColumnsName.clone();
}
/**
* {@inheritDoc}
*/
@Override
protected void setViewerProviders() {
// We call the createRequiredViewerColumn() and then we associate
// the providers to associate the default label provider to the required column
createRequiredViewerColumn();
super.setViewerProviders();
createInitialViewerColumns();
}
/**
* Create the required column in the viewer.
* @return The created column
*/
protected abstract ViewerColumn createRequiredViewerColumn();
/**
* Create the initial viewer columns, from the optional ones, which must be initially displayed.
* By default, no optional columns are initially displayed.
*/
protected void createInitialViewerColumns() {
// Nothing to do
}
/**
* {@inheritDoc}
*/
@Override
protected abstract ColumnViewer createViewer(final Composite pParent);
/**
* {@inheritDoc}
*/
@Override
public ColumnViewer getViewer() {
return (ColumnViewer) super.getViewer();
}
/**
* {@inheritDoc}
*
* Overridden to add the actions for the columns, the headers and the lines visibility.
*/
@Override
protected void addMenuBarActions() {
addColumnsVisibilityAction();
addMenuBarSeparator();
addHideHeaderAction();
addHideLinesAction();
super.addMenuBarActions();
}
/**
* Add the columns visibility action to the menu bar.
*/
protected void addColumnsVisibilityAction() {
addMenuBarAction(createColumnsVisibilityAction());
}
/**
* Add the hide header action to the menu bar.
*/
protected void addHideHeaderAction() {
addMenuBarAction(createHideHeaderAction(isViewerHeaderInitiallyVisible()));
}
/**
* Add the hide lines action to the menu bar.
*/
protected void addHideLinesAction() {
addMenuBarAction(createHideLinesAction(isViewerLinesInitiallyVisible()));
}
/**
* Return <code>true</code>if the header of the viewer is initially visible.
* @return <code>true</code>if the header of the viewer is initially visible.
*/
protected abstract boolean isViewerHeaderInitiallyVisible();
/**
* Return <code>true</code>if the lines of the viewer are initially visible.
* @return <code>true</code>if the lines of the viewer are initially visible.
*/
protected abstract boolean isViewerLinesInitiallyVisible();
/**
* Create and return the columns visibility action
* linked to the managed viewer.
*
* @return A new instance of the column visibility action
*/
protected IAction createColumnsVisibilityAction() {
return new ColumnsVisibilityAction();
}
/**
* Create and return the hide lines action.
*
* @param pVisible <code>true</code> if the lines are visible by default, <code>false</code> otherwise
* @return A new instance of the hide lines action
*/
protected IAction createHideLinesAction(final boolean pVisible) {
// Create the action, with the right label and display it as a checkbox
final Action vHideLinesAction = new Action(
CommonUIActivator.getMessages().getString("AbstractColumnViewerPage.action.showlines"), //$NON-NLS-1$
IAction.AS_CHECK_BOX) {
/**
* {@inheritDoc}
*/
@Override
public void run() {
AbstractColumnViewerPage.this.setLinesVisible(isChecked());
}
};
// Set the initial state to the action
vHideLinesAction.setChecked(pVisible);
return vHideLinesAction;
}
/**
* Create and return the hide header action.
*
* @param pVisible <code>true</code> if the header is visible by default, <code>false</code> otherwise
* @return A new instance of the hide header action
*/
protected IAction createHideHeaderAction(final boolean pVisible) {
// Create the action, with the right label and display it as a checkbox
final Action vHideHeaderAction = new Action(
CommonUIActivator.getMessages().getString("AbstractColumnViewerPage.action.showheaders"), //$NON-NLS-1$
IAction.AS_CHECK_BOX) {
/**
* {@inheritDoc}
*/
@Override
public void run() {
AbstractColumnViewerPage.this.setHeaderVisible(isChecked());
}
};
// Set the initial state to the action
vHideHeaderAction.setChecked(pVisible);
return vHideHeaderAction;
}
/**
* Set the visibility of the lines in the viewer.
*
* @param pVisible <code>true</code> if the lines must be visible, <code>false</code> otherwise
*/
public abstract void setLinesVisible(final boolean pVisible);
/**
* Set the visibility of the header in the viewer.
*
* @param pVisible <code>true</code> if the header must be visible, <code>false</code> otherwise
*/
public abstract void setHeaderVisible(final boolean pVisible);
/**
* Create a new column at the end of the viewer, with the name given in parameter.
*
* @param pColumnName The name of the column
* @return The created tree viewer column, or null if the concrete implementation of this page doesn't support
* the column viewers
*/
protected abstract ViewerColumn createViewerColumn(final String pColumnName);
/**
* Create a new column in the viewer, at the specified location, with the name given in parameter.
*
* @param pColumnName The name of the column
* @param pIndex The location index where the column must be created in the viewer
* @return The created tree viewer column, or null if the concrete implementation of this page doesn't support
* the column viewers
*/
protected abstract ViewerColumn createViewerColumn(final String pColumnName, final int pIndex);
/**
* Create a new column at the end of the viewer, with the name given in parameter, and associate to it a
* label provider also given in parameter.
*
* @param pColumnName The name of the column
* @param pColumnLabelProvider The column label provider to use in the column
*
* @return The created tree viewer column, or null if the concrete implementation of this page doesn't support
* the column viewers
*/
protected abstract ViewerColumn createViewerColumn(
final String pColumnName,
final ColumnLabelProvider pColumnLabelProvider);
/**
* Create a new column at the end of the viewer, with the name given in parameter, and associate to it a
* label provider and an editing support also given in parameter.
*
* @param pColumnName The name of the column
* @param pColumnLabelProvider The column label provider to use in the column
* @param pEditingSupport The editing support to use in the column
*
* @return The created tree viewer column, or null if the concrete implementation of this page doesn't support
* the column viewers
*/
protected abstract ViewerColumn createViewerColumn(
final String pColumnName,
final ColumnLabelProvider pColumnLabelProvider,
final EditingSupport pEditingSupport);
/**
* Create a new column at the end of the viewer, with the name given in parameter, and associate to it a
* label provider and an editing support according to the property whose ID is given in parameter.
*
* @param pColumnName The name of the column
* @param pPropertyID The id of the property to display in the column
*
* @return The created tree viewer column, or null if the concrete implementation of this page doesn't support
* the column viewers
*/
protected abstract ViewerColumn createViewerColumn(final String pColumnName, final String pPropertyID);
/**
* Show a list of columns whose name is given in parameter.
*
* @param pColumnsNamesArray The array of the columns names to display.
*/
protected void showColumns(final String[] pColumnsNamesArray) {
boolean vRefreshNeeded = false;
if (pColumnsNamesArray != null) {
// Loop on the names to find and display the corresponding column
for (String vColumnName : pColumnsNamesArray) {
// Check if the column in not already visible
if (!isColumnVisible(vColumnName)) {
// Show the column and remember that a refresh is needed on the tree
vRefreshNeeded = showColumn(vColumnName) || vRefreshNeeded;
}
}
// Refresh the tree content if at least one new column is displayed
if (vRefreshNeeded) {
getViewer().refresh();
}
}
}
/**
* Hide a list of columns, whose name is given in parameter.
*
* @param pColumnsNamesArray The array of the columns names to hide.
*/
protected void hideColumns(final String[] pColumnsNamesArray) {
if (pColumnsNamesArray != null) {
// Loop on the names to find and hide the corresponding column
for (final String vColumnName : pColumnsNamesArray) {
// Check if the column is really visible and then hide it
if (isColumnVisible(vColumnName)) {
hideColumn(vColumnName);
}
}
}
}
/**
* Show a column, whose name is given in parameter.
* The column may be created if needed.
*
* @param pColumnName The column name
* @return <code>true</code> if a column was found and shown, <code>false</code> otherwise
*/
protected abstract boolean showColumn(final String pColumnName);
/**
* Hide the column whose name is given in parameter.
*
* @param pColumnName The column name
* @return <code>true</code> if a column was found and hidden, <code>false</code> otherwise
*/
protected abstract boolean hideColumn(final String pColumnName);
/**
* Return a map containing in key the name of the columns
* and in value a flag specifying if it is currently visible or not.
*
* This map will contain the name of all the optional columns which may
* be added in the viewer, but not the required column which is considered
* as always visible.
*
* @return A map containing in key the name of the columns in the viewer,
* and in value a flag specifying if the column is visible or not
*/
protected Map<String, Boolean> getColumnsVisibility() {
// Create the returned map
final Map<String, Boolean> vColumnsVisibilityMap = new HashMap<String, Boolean>(mColumnsNamesArray.length);
// Loop on the names of optional columns
for (final String vColumnName : mColumnsNamesArray) {
// Add in the map the corresponding key and flag value
vColumnsVisibilityMap.put(vColumnName, isColumnVisible(vColumnName));
}
return vColumnsVisibilityMap;
}
/**
* Return the names of the optional columns which can be displayed in the tree view.
*
* @return The names of the optional columns which can be displayed in the tree view.
*/
public String[] getColumnsName() {
return mColumnsNamesArray;
}
/**
* Return the name of the required column for the tree view.
*
* @return The required column name
*/
public String getRequiredColumnName() {
return mRequiredColumnName;
}
/**
* Return <code>true</code> if a column exists in the viewer,
* and <code>false</code> otherwise.
*
* @param pColumnName The name of the column to check
* @return <code>true</code> if the table column is visible, <code>false</code> otherwise
*/
protected abstract boolean isColumnVisible(final String pColumnName);
/**
* Custom action used to manage and change the visibility of the columns of the viewer.
*
* @author $Author: jdumont $
* @version $Revision: 83 $
*/
private class ColumnsVisibilityAction
extends Action {
/**
* Default constructor.
*/
ColumnsVisibilityAction() {
super(CommonUIActivator.getMessages()
.getString("AbstractColumnViewerPage.menu.columnsvisibility")); //$NON-NLS-1$
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
final List<String> vColumnsNameArray = new ArrayList<String>();
final List<String> vVisibleColumnsNamesArray = new ArrayList<String>();
// Get the map specifying the visibility of each column
final Map<String, Boolean> vColumnsVisibilityMap = getColumnsVisibility();
// Loop on all the column visibility map to build two arrays :
// - one for all the columns names
// - one with only the name of visible columns
for (final String vColumnName : vColumnsVisibilityMap.keySet()) {
// Remember the column name
vColumnsNameArray.add(vColumnName);
// Remember the name of the visible column
if (vColumnsVisibilityMap.get(vColumnName)) {
vVisibleColumnsNamesArray.add(vColumnName);
}
}
// Open a dialog to allow the user which columns must be visible
final Object[] vResultsArray = openColumnsSelectionDialog(
vColumnsNameArray,
vVisibleColumnsNamesArray);
if (vResultsArray != null) {
// Loop on the results array to build a set containing all the
// names of the column to show
Set<String> vShownColumnsNamesSet = new HashSet<String>();
for (final Object vResult : vResultsArray) {
// NB : The result is normally already a String with the column name
vShownColumnsNamesSet.add(vResult.toString());
}
// Then build the list of columns to hide, by removing from the whole list
// of columns, those to hide
Set<String> vHiddenColumnsNamesSet = new HashSet<String>(vColumnsVisibilityMap.keySet());
vHiddenColumnsNamesSet.removeAll(vShownColumnsNamesSet);
// Finally, hide and show the columns according to the user choices
hideColumns(vHiddenColumnsNamesSet.toArray(new String[vHiddenColumnsNamesSet.size()]));
showColumns(vShownColumnsNamesSet.toArray(new String[vShownColumnsNamesSet.size()]));
}
}
/**
* Open a dialog allowing the user to select which columns must
* be visible in the viewer.
*
* The array of selected columns is directly returned.
*
* @param pColumnsNamesArray The array of all the column names
* @param pVisibleColumnsNamesArray The array of all the columns names already currently visible
* @return The array of all the columns names to show
*/
private Object[] openColumnsSelectionDialog(
final List<String> pColumnsNamesArray,
final List<String> pVisibleColumnsNamesArray) {
Object[] vResultsArray = null;
// Build the selection dialog
final ListSelectionDialog vDialog = new ListSelectionDialog(
PlatformUI.getWorkbench().getDisplay().getActiveShell(),
pColumnsNamesArray,
new ArrayContentProvider(),
new LabelProvider(),
CommonUIActivator.getMessages()
.getString("AbstractColumnViewerPage.label.columnsvisibility")); //$NON-NLS-1$
// Set the dialog title and select by default the columns which are currently visible
vDialog.setTitle(CommonUIActivator.getMessages()
.getString("AbstractColumnViewerPage.title.columnsvisibility")); //$NON-NLS-1$
vDialog.setInitialElementSelections(pVisibleColumnsNamesArray);
// Finally open the dialog and remember of its result if the user validate its choice
if (vDialog.open() == Window.OK) {
vResultsArray = vDialog.getResult();
}
return vResultsArray;
}
}
}