/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.dal.ui.internal.connectionview;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.csstudio.dal.ui.dnd.rfc.ProcessVariableExchangeUtil;
import org.csstudio.dal.ui.util.LayoutUtil;
import org.csstudio.platform.model.pvs.IProcessVariableAddress;
import org.csstudio.platform.model.pvs.IProcessVariableAdressProvider;
import org.csstudio.platform.simpledal.ConnectionState;
import org.csstudio.platform.simpledal.IConnector;
import org.csstudio.platform.simpledal.IProcessVariableConnectionService;
import org.csstudio.platform.simpledal.ProcessVariableConnectionServiceFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
/**
* A view that displays the state of all channel connections that were opened
* using the {@link IProcessVariableConnectionService} that has been created via
* {@link ProcessVariableConnectionServiceFactory#getDefault()}.
*
* @author Sven Wende
*
*/
public final class ConnectionStateView extends ViewPart {
/**
* The view�s ID.
*/
public static final String VIEW_ID = "org.csstudio.platform.ui.ConnectionStateView";
/**
* The viewer.
*/
private TableViewer _viewer;
/**
* A UI job used to refresh the view at a fixed delay.
*/
private UIJob _updateJob;
private SortDirection _sortDirection = SortDirection.BY_NAME;
class FilterByConnectionStateMouseListener extends MouseAdapter {
private final Set<ConnectionState> _connectionStates;
public FilterByConnectionStateMouseListener(
final Set<ConnectionState> connectionStates) {
assert connectionStates != null;
_connectionStates = connectionStates;
}
/**
* {@inheritDoc}
*/
@Override
public void mouseUp(final MouseEvent e) {
final ViewerFilter filter = new ViewerFilter() {
@Override
public boolean select(final Viewer viewer, final Object parentElement,
final Object element) {
final IConnector s = (IConnector) element;
return _connectionStates.contains(s
.getLatestConnectionState());
}
};
_viewer.setFilters(new ViewerFilter[] { filter });
}
}
// private Button createFilterButton(Composite parent, String label,
// ConnectionState... connectionStates) {
//
// Button button = new Button(parent, SWT.NONE);
// button.setText(label);
// button
// .addMouseListener(new FilterByConnectionStateMouseListener(
// states));
//
// return button;
// }
class FilterButton {
private final Button _swtButton;
private final Set<ConnectionState> _connectionStates;
private final String _baseLabel;
public FilterButton(final Composite parent, final int style, final String label,
final ConnectionState... connectionStates) {
_swtButton = new Button(parent, style);
assert connectionStates != null;
assert label != null;
// remember label
_baseLabel = label;
// remember connection states
_connectionStates = new HashSet<ConnectionState>();
for (final ConnectionState s : connectionStates) {
_connectionStates.add(s);
}
// add action listener
_swtButton.addMouseListener(new FilterByConnectionStateMouseListener(
_connectionStates));
// initialize label
refreshLabel(Collections.EMPTY_LIST);
}
public void refreshLabel(final List<IConnector> statistics) {
assert statistics != null;
int count = 0;
if (statistics != null) {
for (final IConnector s : statistics) {
if (_connectionStates
.contains(s.getLatestConnectionState())) {
count++;
}
}
}
_swtButton.setText(_baseLabel + " (" + count + ")");
}
}
/**
* {@inheritDoc}
*/
@Override
public void createPartControl(final Composite parent) {
// layout
parent.setLayout(new GridLayout());
// create button panel
final Composite buttons = new Composite(parent, SWT.NONE);
buttons.setLayout(new FillLayout());
buttons.setLayoutData(LayoutUtil
.createGridDataForHorizontalFillingCell());
final FilterButton buttonAll = new FilterButton(buttons, SWT.FLAT, "all",
ConnectionState.values());
final FilterButton buttonConnected = new FilterButton(buttons, SWT.FLAT,
"connected", ConnectionState.CONNECTED);
final FilterButton buttonNotConnected = new FilterButton(buttons, SWT.FLAT,
"not connected", ConnectionState.CONNECTION_LOST,
ConnectionState.INITIAL, ConnectionState.CONNECTION_FAILED,
ConnectionState.DISCONNECTED, ConnectionState.UNKNOWN);
// create the viewer and ...
_viewer = createChannelTable(parent);
// .. initialize layout
_viewer.getControl().setLayoutData(
LayoutUtil.createGridDataForFillingCell());
// .. initialize content provider
_viewer.setContentProvider(new IStructuredContentProvider(){
/**
* {@inheritDoc}
*/
@Override
public void inputChanged(final Viewer viewer, final Object oldInput,
final Object newInput) {
}
/**
* {@inheritDoc}
*/
@Override
public Object[] getElements(final Object parent) {
final List<IConnector> statistics =((IProcessVariableConnectionService) parent)
.getConnectors();
// refresh the filter button states
buttonAll.refreshLabel(statistics);
buttonConnected.refreshLabel(statistics);
buttonNotConnected.refreshLabel(statistics);
return statistics.toArray();
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
}
});
// ... initialize label provider
_viewer.setLabelProvider(new LabelProvider());
_viewer.setInput(ProcessVariableConnectionServiceFactory.getDefault()
.getProcessVariableConnectionService());
// ... initialize comparators (important for sorting)
_viewer.setComparator(new ViewerComparator() {
@Override
public int compare(final Viewer viewer, final Object e1, final Object e2) {
return _sortDirection.getComparator().compare(
(IConnector) e1, (IConnector) e2);
}
});
// ... initialize tooltip support
ColumnViewerToolTipSupport.enableFor(_viewer, ToolTip.NO_RECREATE);
// ... initialize context menu
final MenuManager menuManager = new MenuManager();
// menuManager.addMenuListener(new IMenuListener() {
//
// public void menuAboutToShow(final IMenuManager manager) {
// manager.add(new GroupMarker(
// IWorkbenchActionConstants.MB_ADDITIONS));
// }
// });
menuManager
.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
_viewer.getControl().setMenu(
menuManager.createContextMenu(_viewer.getControl()));
getViewSite().registerContextMenu(menuManager, _viewer);
getViewSite().setSelectionProvider(_viewer);
// initialize the update job
_updateJob = new UIJob("Update Connector State View") {
@Override
public IStatus runInUIThread(final IProgressMonitor monitor) {
_viewer.refresh();
if (!monitor.isCanceled()) {
_updateJob.schedule(2000);
return Status.OK_STATUS;
} else {
return Status.CANCEL_STATUS;
}
}
};
_updateJob.schedule(5000);
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
_updateJob.cancel();
super.dispose();
}
/**
* {@inheritDoc}
*/
@Override
public void setFocus() {
}
private TableViewer createChannelTable(final Composite parent) {
// define column names
final String[] columnNames = new String[] {
"PROP_DESCRIPTION", "PROP_NAME", "PROP_VALUE" }; //$NON-NLS-1$ //$NON-NLS-2$
// create table
final Table table = new Table(parent, SWT.FULL_SELECTION | SWT.MULTI
| SWT.HIDE_SELECTION | SWT.DOUBLE_BUFFERED | SWT.SCROLL_PAGE);
table.setLinesVisible(true);
table.setLayoutData(LayoutUtil.createGridDataForFillingCell());
table.setHeaderVisible(true);
// create viewer
final TableViewer viewer = new TableViewer(table);
TableViewerColumn tvColumn;
tvColumn = new TableViewerColumn(viewer, SWT.NONE);
tvColumn.getColumn().setText("Channel");
tvColumn.getColumn().setMoveable(false);
tvColumn.getColumn().setWidth(300);
tvColumn = new TableViewerColumn(viewer, SWT.NONE);
tvColumn.getColumn().setText("Connection State");
tvColumn.getColumn().setMoveable(false);
tvColumn.getColumn().setWidth(200);
tvColumn = new TableViewerColumn(viewer, SWT.NONE);
tvColumn.getColumn().setText("Latest Value");
tvColumn.getColumn().setMoveable(false);
tvColumn.getColumn().setWidth(200);
viewer.setUseHashlookup(true);
// define column properties
viewer.setColumnProperties(columnNames);
// DnD
ProcessVariableExchangeUtil.addProcessVariableAdressDragSupport(viewer
.getControl(), DND.DROP_MOVE | DND.DROP_COPY,
new IProcessVariableAdressProvider() {
@Override
public List<IProcessVariableAddress> getProcessVariableAdresses() {
final List<IProcessVariableAddress> result = new ArrayList<IProcessVariableAddress>();
final IStructuredSelection sel = (IStructuredSelection) viewer
.getSelection();
final Iterator<IProcessVariableAdressProvider> it = sel
.iterator();
while (it.hasNext()) {
result.add(it.next().getPVAdress());
}
return result;
}
@Override
public IProcessVariableAddress getPVAdress() {
final IStructuredSelection sel = (IStructuredSelection) viewer
.getSelection();
final IProcessVariableAdressProvider pvProvider = (IProcessVariableAdressProvider) sel
.getFirstElement();
return pvProvider != null ? pvProvider.getPVAdress()
: null;
}
});
return viewer;
}
class ChangeSortDirectionListener implements SelectionListener {
private final SortDirection _sortDirection;
public ChangeSortDirectionListener(final SortDirection sortDirection) {
assert sortDirection != null;
_sortDirection = sortDirection;
}
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
}
@Override
public void widgetSelected(final SelectionEvent e) {
ConnectionStateView.this._sortDirection = this._sortDirection;
}
}
}