| /******************************************************************************* |
| * Copyright (c) 2009 STMicroelectronics. |
| * 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 |
| * |
| * Contributors: |
| * Marzia Maugeri <marzia.maugeri@st.com> - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.linuxtools.dataviewers.abstractviewers; |
| |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.viewers.CellLabelProvider; |
| import org.eclipse.jface.viewers.ColumnViewer; |
| import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; |
| import org.eclipse.jface.viewers.IContentProvider; |
| import org.eclipse.jface.viewers.IOpenListener; |
| import org.eclipse.jface.viewers.OpenEvent; |
| import org.eclipse.linuxtools.dataviewers.listeners.STDisposeListener; |
| import org.eclipse.linuxtools.dataviewers.listeners.STHeaderListener; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Item; |
| import org.eclipse.swt.widgets.ScrollBar; |
| import org.eclipse.swt.widgets.Scrollable; |
| |
| /** |
| * The AbstractSTViewer is a wrapper handling a viewer like TreeTable or Table. |
| */ |
| public abstract class AbstractSTViewer { |
| |
| private IDialogSettings viewerSettings = null; |
| |
| private ISTDataViewersField[] fields = null; |
| |
| private ColumnViewer viewer; |
| |
| private STDataViewersComparator comparator; |
| |
| private STDataViewersHideShowManager hideShowManager; |
| |
| /** |
| * Creates a new instance of the receiver under the given parent. |
| * |
| * @param parent |
| * is the parent control |
| * @param style is the SWT style bits to customize the style of the tree/table |
| * |
| */ |
| public AbstractSTViewer(Composite parent, int style) { |
| this(parent, style, true); |
| } |
| |
| /** |
| * Creates a new instance of the receiver under the given parent. |
| * |
| * @param parent |
| * is the parent control |
| * @param style is the SWT style bits to customize the style of the tree/table |
| * @param init setup is a flag indicating when a customization of AbstractSTViewer needs to set up additional information |
| * useful to create the Viewer |
| * |
| */ |
| public AbstractSTViewer(Composite parent, int style, boolean init) { |
| if (init) { |
| init(parent, style); |
| } |
| } |
| |
| /* |
| * Initializes this view with the given view site. A memento is passed to the view which contains a snapshot of the |
| * views state from a previous session. Where possible, the view should try to recreate that state within the part |
| * controls. <p> This implementation will ignore the memento and initialize the view in a fresh state. Subclasses |
| * may override the implementation to perform any state restoration as needed. |
| */ |
| |
| /** |
| * Initializes the viewers. It sets: the columns of the viewers, a viewer setting (similar to memento) a column |
| * manager a viewer comparator ColumnViewerToolTipSupport an OpenListener a KeyListener a PaintListener a |
| * DisposeListener the input the content provider |
| * @param parent The parent composite. |
| * @param style SWT style to be used. |
| */ |
| private void init(Composite parent, int style) { |
| viewer = createViewer(parent, style); |
| viewerSettings = createSTAbstractDataViewersSettings(); |
| |
| fields = getAllFields(); |
| |
| createColumns(); |
| restoreColumnOrder(); |
| |
| // building columns manager |
| // (needs the columns to be created first) |
| STDataViewersHideShowManager manager = buildHideShowManager(); |
| manager.restoreState(viewerSettings); |
| setHideShowManager(manager); |
| |
| // building the column comparator |
| // (needs the columns to be created first) |
| STDataViewersComparator comparator = buildComparator(); |
| comparator.restoreState(viewerSettings); |
| setComparator(comparator); |
| setSortIndicators(); |
| |
| IContentProvider cp = createContentProvider(); |
| |
| viewer.setContentProvider(cp); |
| viewer.setUseHashlookup(true); |
| |
| GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| viewer.getControl().setLayoutData(data); |
| |
| viewer.setInput(null); |
| |
| ColumnViewerToolTipSupport.enableFor(viewer); |
| |
| Scrollable scrollable = (Scrollable) viewer.getControl(); |
| ScrollBar bar = scrollable.getVerticalBar(); |
| if (bar != null) { |
| bar.setSelection(restoreVerticalScrollBarPosition()); |
| } |
| bar = scrollable.getHorizontalBar(); |
| if (bar != null) { |
| bar.setSelection(restoreHorizontalScrollBarPosition()); |
| } |
| |
| viewer.addOpenListener(new IOpenListener() { |
| @Override |
| public void open(OpenEvent event) { |
| handleOpenEvent(event); |
| } |
| }); |
| |
| viewer.getControl().addKeyListener(new KeyAdapter() { |
| @Override |
| public void keyPressed(KeyEvent e) { |
| handleKeyPressed(e); |
| } |
| }); |
| |
| viewer.getControl().addDisposeListener(createDisposeListener()); |
| |
| } |
| |
| // ////////////////////////// |
| // Columns manager utilities |
| // ////////////////////////// |
| |
| /** |
| * Build a hide/show manager from the default settings. It is different if it is for a TreeViewer or a TableViewer. |
| * |
| * @return AbstractSTViewerHideShowManager |
| */ |
| protected STDataViewersHideShowManager buildHideShowManager() { |
| return new STDataViewersHideShowManager(this); |
| } |
| |
| /** |
| * Set this manager to be the new hide/show manager. This should only be called if the columns have been created. |
| * This method should not be called by customers, it is used by the hide/show action to update the viewer. |
| * |
| * @param manager The new manager. |
| */ |
| public void setHideShowManager(STDataViewersHideShowManager manager) { |
| hideShowManager = manager; |
| hideShowManager.updateColumns(); |
| } |
| |
| // ////////////////// |
| // Sorting utilities |
| // ////////////////// |
| |
| /** |
| * Build a comparator from the default settings. |
| * |
| * @return STProfTableComparator Newly created comparator with default settings. |
| */ |
| protected STDataViewersComparator buildComparator() { |
| return new STDataViewersComparator(getColumns()); |
| } |
| |
| /** |
| * Return the table sorter portion of the sorter. |
| * |
| * @return TableSorter The currently set comparator |
| */ |
| public STDataViewersComparator getTableSorter() { |
| return comparator; |
| } |
| |
| /** |
| * Set the comparator to be the new comparator. This should only be called if the viewer has been created. |
| * |
| * @param comparator The comparator to be used. |
| */ |
| public void setComparator(STDataViewersComparator comparator) { |
| this.comparator = comparator; |
| viewer.setComparator(comparator); |
| updateForNewComparator(comparator); |
| } |
| |
| /** |
| * Update the viewer for comparator updates |
| * |
| * @param comparator |
| */ |
| private void updateForNewComparator(STDataViewersComparator comparator) { |
| comparator.saveState(viewerSettings); |
| viewer.refresh(); |
| setSortIndicators(); |
| } |
| |
| /** |
| * Sets the sort indicator on top of target column |
| */ |
| private void setSortIndicators() { |
| Item topc = getTableSorter().getTopColumn(); |
| updateDirectionIndicator(topc); |
| } |
| |
| // /////////////////////// |
| // Save/restore utilities |
| // /////////////////////// |
| |
| /** |
| * Creates the container for the settings of this viewer |
| * |
| * @return The dialog settings. |
| */ |
| private IDialogSettings createSTAbstractDataViewersSettings() { |
| IDialogSettings settings = getDialogSettings().getSection(STDataViewersSettings.TAG_SECTION_VIEWER_STATE); |
| if (settings == null) { |
| settings = getDialogSettings().addNewSection(STDataViewersSettings.TAG_SECTION_VIEWER_STATE); |
| } |
| return settings; |
| } |
| |
| /** |
| * Restores the viewer's column order. Called just after the columns are created. |
| */ |
| private void restoreColumnOrder() { |
| int[] order = restoreColumnOrderSetting(); |
| if (order != null && order.length == fields.length) { |
| setColumnOrder(order); |
| } |
| } |
| |
| /** |
| * Restores the vertical scrollbar position |
| * |
| * @return the position |
| */ |
| private int restoreVerticalScrollBarPosition() { |
| if (viewerSettings == null) { |
| // no settings saved |
| return 0; |
| } |
| |
| String position = viewerSettings.get(STDataViewersSettings.TAG_VIEWER_STATE_VERTICAL_POSITION); |
| if (position == null) { |
| // no vertical position saved |
| return 0; |
| } |
| |
| try { |
| return Integer.parseInt(position); |
| } catch (NumberFormatException nfe) { |
| // invalid entry |
| return 0; |
| } |
| } |
| |
| /** |
| * Restores the horizontal scrollbar position |
| * |
| * @return the position |
| */ |
| private int restoreHorizontalScrollBarPosition() { |
| if (viewerSettings == null) |
| // no settings saved |
| return 0; |
| |
| String position = viewerSettings.get(STDataViewersSettings.TAG_VIEWER_STATE_HORIZONTAL_POSITION); |
| if (position == null) |
| // no horizontal position saved |
| return 0; |
| |
| try { |
| return Integer.parseInt(position); |
| } catch (NumberFormatException nfe) { |
| // invalid entry |
| return 0; |
| } |
| } |
| |
| /** |
| * Restore the order of the columns using the dialog settings |
| * |
| * @return column order |
| */ |
| private int[] restoreColumnOrderSetting() { |
| if (viewerSettings == null) { |
| // no settings saved |
| return null; |
| } |
| |
| String[] columnOrder = viewerSettings.getArray(STDataViewersSettings.TAG_VIEWER_STATE_COLUMN_ORDER); |
| if (columnOrder == null) { |
| // no column order saved |
| return null; |
| } |
| |
| int n = columnOrder.length; |
| if (n != getAllFields().length) { |
| // bad column count |
| return null; |
| } |
| |
| try { |
| int[] values = new int[n]; |
| for (int i = 0; i < n; i++) { |
| int val = Integer.parseInt(columnOrder[i]); |
| values[i] = val; |
| } |
| return values; |
| } catch (NumberFormatException nfe) { |
| // invalid entry |
| return null; |
| } |
| } |
| |
| /** |
| * Used to save the state of the viewer before its disposal |
| * |
| */ |
| public void saveState() { |
| if (viewerSettings == null) { |
| viewerSettings = getDialogSettings().getSection(STDataViewersSettings.TAG_SECTION_VIEWER_STATE); |
| } |
| if (viewerSettings == null) { |
| viewerSettings = getDialogSettings().addNewSection(STDataViewersSettings.TAG_SECTION_VIEWER_STATE); |
| } |
| |
| // save column order |
| int[] columnOrder = getColumnOrder(); |
| String[] columnOrderStrings = new String[columnOrder.length]; |
| for (int i = 0; i < columnOrder.length; i++) { |
| columnOrderStrings[i] = columnOrder[i] + ""; |
| } |
| viewerSettings.put(STDataViewersSettings.TAG_VIEWER_STATE_COLUMN_ORDER, columnOrderStrings); |
| |
| // save hide show manager |
| if (getHideShowManager() != null) |
| getHideShowManager().saveState(viewerSettings); |
| |
| // save sort |
| if (getTableSorter() != null) |
| getTableSorter().saveState(viewerSettings); |
| |
| // save vertical position |
| Scrollable scrollable = (Scrollable) viewer.getControl(); |
| ScrollBar bar = scrollable.getVerticalBar(); |
| int position = (bar != null) ? bar.getSelection() : 0; |
| viewerSettings.put(STDataViewersSettings.TAG_VIEWER_STATE_VERTICAL_POSITION, position); |
| |
| // save horizontal position |
| bar = scrollable.getHorizontalBar(); |
| position = (bar != null) ? bar.getSelection() : 0; |
| viewerSettings.put(STDataViewersSettings.TAG_VIEWER_STATE_HORIZONTAL_POSITION, position); |
| } |
| |
| // ////////////////////////// |
| // Listeners for this viewer |
| // ////////////////////////// |
| |
| /** |
| * Creates the dispose listener used by the viewer to save its state when it is closed. This method is called at the |
| * end of the viewer initialization (init() method). |
| * |
| * @return the new header listener |
| */ |
| private DisposeListener createDisposeListener() { |
| return new STDisposeListener(this); |
| } |
| |
| /** |
| * Creates the header listener used by the columns to check when their header is selected (used by sorting). This |
| * method is called at column creation. |
| * |
| * @return the new header listener |
| */ |
| protected SelectionListener createHeaderListener() { |
| return new STHeaderListener(this); |
| } |
| |
| // //////////////////////// |
| // Getters for this viewer |
| // //////////////////////// |
| |
| /** |
| * Get the viewer's settings |
| * |
| * @return the IDialogSettings used to save the viewer's settings |
| */ |
| public IDialogSettings getViewerSettings() { |
| return viewerSettings; |
| } |
| |
| /** |
| * Get the wrapped viewer |
| * |
| * @return the JFace viewer wrapped in this ST viewer |
| */ |
| public ColumnViewer getViewer() { |
| return viewer; |
| } |
| |
| /** |
| * Get the input of the viewer |
| * |
| * @return the inputed object |
| */ |
| public Object getInput() { |
| return viewer.getInput(); |
| } |
| |
| /** |
| * Get the hideShowManager that manages the columns hiding and width. |
| * |
| * @return the hideShowManager |
| */ |
| public STDataViewersHideShowManager getHideShowManager() { |
| return hideShowManager; |
| } |
| |
| // /////////////////////////////////////////////////////////// |
| // Methods that can be overridden by customers when |
| // subclassing AbstractSTTreeViewer and AbstractSTTableViewer |
| // /////////////////////////////////////////////////////////// |
| |
| /** |
| * Handle key pressed events, called each time a key pressed event is detected in the viewer |
| * <p> |
| * Subclasses may override it. |
| * </p> |
| * |
| * @param event Unused parameter. |
| */ |
| protected void handleKeyPressed(KeyEvent event) { |
| // nothing, intended to be overridden |
| } |
| |
| /** |
| * Handle the open event, called each time the viewer is opened |
| * <p> |
| * Subclasses may override it. |
| * </p> |
| * |
| * @param event Unused event. |
| */ |
| protected void handleOpenEvent(OpenEvent event) { |
| // nothing, intended to be overridden |
| } |
| |
| // /////////////////////////////////////////////// |
| // Abstract methods to implement when subclassing |
| // AbstractSTTreeViewer or AbstractSTTableViewer |
| // /////////////////////////////////////////////// |
| |
| /** |
| * Gets the fields (e.g. the columns description) of that viewer |
| * |
| * <p> |
| * This is where you should define the columns of your viewers and the data they are going to display (label |
| * provider). |
| * </p> |
| * |
| * @return the fields of that viewer |
| */ |
| public abstract ISTDataViewersField[] getAllFields(); |
| |
| /** |
| * Creates the content provider used by the viewer. This method is called once at viewer initialization. |
| * |
| * @return a new content provider |
| */ |
| protected abstract IContentProvider createContentProvider(); |
| |
| /** |
| * Permit to provide the sort dialog dialogSettings (used to persist the state of the sort dialog) |
| * <p> |
| * This implementation is generally like: |
| * </p> |
| * <p> |
| * <code>protected IDialogSettings getDialogSettings() {<br> |
| * return </code>PLUGINActivator<code>.getDefault().getDialogSettings();<br> |
| * } </code> |
| * </p> |
| * <p> |
| * Note that your plugin has to be an <code>AbstractUIPlugin</code> in order to provide the |
| * <code>getDialogSettings()</code> method. |
| * </p> |
| * <p> |
| * If your plugin implements MANY view or viewers, this method should return a particular section of the plugin |
| * dialog setting: |
| * </p> |
| * <p> |
| * <code> |
| * protected IDialogSettings getDialogSettings() <br> |
| * IDialogSettings settings = </code>PLUGINActivator<code>.getDefault().getDialogSettings().getSection(</code> |
| * SECTION_NAME<code>); <br> |
| * if (settings == null) { <br> |
| * settings = </code>PLUGINActivator<code>.getDefault().getDialogSettings().addNewSection(</code>SECTION_NAME |
| * <code>);<br> |
| * }<br> |
| * return settings; |
| * </code> |
| * </p> |
| * <p> |
| * Note that if you use multiple instantiated views (not singleton) or many views with the same viewer, using the |
| * code above they will all have the same dialog settings thus the last one which is closed will save the state for |
| * all the others.<br> |
| * If you want to avoid that you can add a view-dependent SECTION_NAME parameter to the constructor of the VIEWER in |
| * the VIEW class and then use it in the <code>getDialogSettings()</code> method. Here is an example: |
| * </p> |
| * <p> |
| * In the view class (extending <code>AbstractSTDataView</code>): |
| * </p> |
| * <p> |
| * <code> |
| * private static final String SETTINGS_SECTION = </code>SECTION_NAME<code>;<br> |
| * <br> |
| * protected AbstractSTViewer createAbstractSTViewer(Composite parent) {<br> |
| * return new MyViewer(parent, SETTINGS_SECTION);<br> |
| * } |
| * </code> |
| * </p> |
| * <p> |
| * In the viewer class (extending <code>AbstractST{Tree|Table}Viewer</code>): |
| * </p> |
| * <p> |
| * <code> |
| * private final String settingsSection;<br> |
| * <br> |
| * public CallHierarchyViewer(Composite parent, String settingsSection) {<br> |
| * super(parent);<br> |
| * this.settingsSection = settingsSection;<br> |
| * }<br> |
| * <br> |
| * protected IDialogSettings getDialogSettings() <br> |
| * IDialogSettings settings = </code>PLUGINActivator<code>.getDefault().getDialogSettings().getSection(</code> |
| * this.settingsSection<code>); <br> |
| * if (settings == null) { <br> |
| * settings = </code>PLUGINActivator<code>.getDefault().getDialogSettings().addNewSection(</code> |
| * this.settingsSection<code>);<br> |
| * }<br> |
| * return settings; |
| * </code> |
| * </p> |
| * |
| * @return the IDialogSettings used to store/load the dialog state |
| */ |
| public abstract IDialogSettings getDialogSettings(); |
| |
| // ////////////////////////////////////////////////////////////// |
| // These following methods are intended to be implemented in |
| // AbstractSTTreeViewer and AbstractSTTableViewer because |
| // they are different for the two types of viewers. |
| // They are not intended to be implemented by customer. |
| // ////////////////////////////////////////////////////////////// |
| |
| // Viewer creation utilities |
| |
| /** |
| * The method called to create the wrapped control (TreeViewer, TableViewer) |
| * @param parent The composite to be parent. |
| * @param style The SWT style to be used. |
| * @return The newly created viewer. |
| * |
| */ |
| protected abstract ColumnViewer createViewer(Composite parent, int style); |
| |
| /** |
| * Creates the columns in the control. |
| * |
| */ |
| protected abstract void createColumns(); |
| |
| protected CellLabelProvider createColumnLabelProvider(Item column) { |
| return new STOwnerDrawLabelProvider(column); |
| } |
| |
| // Columns utilities |
| |
| /** |
| * Update the direction indicator as column is now the primary column. |
| * |
| * @param column |
| * the column that has to be the sorted column |
| */ |
| public abstract void updateDirectionIndicator(Item column); |
| |
| /** |
| * Get the wrapped viewer's columns order. Used to get the columns order since the TreeViewer and the TableViewer |
| * don't share the same API to get the columns. |
| * |
| * @return the columns order of the viewer |
| */ |
| public abstract int[] getColumnOrder(); |
| |
| /** |
| * Set the wrapped viewer's columns order. Used to set the columns order since the TreeViewer and the TableViewer |
| * don't share the same API to get the columns. |
| * @param order The new column order. |
| * |
| */ |
| protected abstract void setColumnOrder(int[] order); |
| |
| /** |
| * Get the wrapped viewer's columns. Used get the columns list since the TreeViewer and the TableViewer don't share |
| * the same API to get the columns. |
| * |
| * @return the columns of the viewer |
| */ |
| public abstract Item[] getColumns(); |
| |
| /** |
| * Get the wrapped viewer's column index for a given column. Used get the columns list since the TreeViewer and the |
| * TableViewer don't share the same API to get the columns. |
| * |
| * @param column The column whose index is looked for. |
| * |
| * @return the index of the column in the viewer |
| */ |
| public abstract int getColumnIndex(Item column); |
| |
| /** |
| * Get the width of the target column of the viewer |
| * |
| * @param column |
| * A column under the form of an Item object which is the common superclass of TreeColumn and TableColumn |
| * |
| * @return The width of the column |
| */ |
| public abstract int getColumnWidth(Item column); |
| |
| /** |
| * Set the width of the target column of the viewer |
| * |
| * @param column |
| * A column under the form of an Item object which is the common superclass of TreeColumn and TableColumn |
| * @param width |
| * The new width |
| */ |
| public abstract void setColumnWidth(Item column, int width); |
| |
| /** |
| * Set the resizable state of the target column of the viewer |
| * |
| * @param column |
| * A column under the form of an Item object which is the common superclass of TreeColumn and TableColumn |
| * @param resizable |
| * The new resizable state |
| */ |
| public abstract void setColumnResizable(Item column, boolean resizable); |
| |
| } |