/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com)
*
* OpenSCADA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenSCADA 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 Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenSCADA. If not, see
* <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License.
*/
package org.openscada.ae.ui.testing.views;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.openscada.ae.MonitorStatusInformation;
import org.openscada.ae.ui.connection.data.MonitorStatusBean;
import org.openscada.core.subscription.SubscriptionState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MonitorsView extends AbstractConditionQueryViewPart
{
private final static Logger logger = LoggerFactory.getLogger ( MonitorsView.class );
public static final String VIEW_ID = "org.openscada.ae.ui.testing.views.MonitorsView";
private Label stateLabel;
private final Map<String, MonitorStatusBean> monitorSet = new HashMap<String, MonitorStatusBean> ();
private final WritableSet monitors;
private TableViewer viewer;
public MonitorsView ()
{
this.monitors = new WritableSet ( SWTObservables.getRealm ( Display.getDefault () ) );
}
@Override
protected Realm getRealm ()
{
return this.monitors.getRealm ();
}
@Override
public void createPartControl ( final Composite parent )
{
final GridLayout layout = new GridLayout ( 1, false );
layout.horizontalSpacing = layout.verticalSpacing = 0;
layout.marginHeight = layout.marginWidth = 0;
parent.setLayout ( layout );
this.stateLabel = new Label ( parent, SWT.NONE );
this.stateLabel.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false ) );
final Composite wrapper = new Composite ( parent, SWT.NONE );
wrapper.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, true ) );
this.viewer = new TableViewer ( wrapper, SWT.FULL_SELECTION | SWT.MULTI );
TableColumnLayout tableLayout;
wrapper.setLayout ( tableLayout = new TableColumnLayout () );
TableColumn col;
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "ID" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 50 ) );
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "State" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 50 ) );
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "Timestamp" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 100 ) );
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "Value" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 50 ) );
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "Ack User" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 50 ) );
col = new TableColumn ( this.viewer.getTable (), SWT.NONE );
col.setText ( "Ack Timestamp" );
tableLayout.setColumnData ( col, new ColumnWeightData ( 100 ) );
this.viewer.getTable ().setLayout ( layout );
this.viewer.getTable ().setHeaderVisible ( true );
this.viewer.setComparator ( new ViewerComparator () {
@Override
public int compare ( final Viewer viewer, final Object e1, final Object e2 )
{
if ( e1 instanceof MonitorStatusBean && e2 instanceof MonitorStatusBean )
{
final MonitorStatusBean b1 = (MonitorStatusBean)e1;
final MonitorStatusBean b2 = (MonitorStatusBean)e2;
return b1.getId ().compareTo ( b2.getId () );
}
return 0;
}
} );
this.viewer.setContentProvider ( new ObservableSetContentProvider () );
this.viewer.setLabelProvider ( new MonitorsLabelProvider ( BeansObservables.observeMaps ( this.monitors, MonitorStatusBean.class, new String[] { "id", MonitorStatusBean.PROP_STATUS, MonitorStatusBean.PROP_STATUS_TIMESTAMP, MonitorStatusBean.PROP_VALUE, MonitorStatusBean.PROP_LAST_AKN_USER, MonitorStatusBean.PROP_LAST_AKN_TIMESTAMP } ) ) );
this.viewer.setInput ( this.monitors );
getViewSite ().setSelectionProvider ( this.viewer );
hookContextMenu ();
addSelectionListener ();
}
private void hookContextMenu ()
{
final MenuManager menuMgr = new MenuManager ( "#PopupMenu", VIEW_ID );
menuMgr.setRemoveAllWhenShown ( true );
menuMgr.addMenuListener ( new IMenuListener () {
public void menuAboutToShow ( final IMenuManager manager )
{
fillContextMenu ( manager );
}
} );
final Menu menu = menuMgr.createContextMenu ( this.viewer.getControl () );
this.viewer.getControl ().setMenu ( menu );
getSite ().registerContextMenu ( menuMgr, this.viewer );
}
private void fillContextMenu ( final IMenuManager manager )
{
// Other plug-ins can contribute there actions here
manager.add ( new Separator () );
manager.add ( new Separator ( IWorkbenchActionConstants.MB_ADDITIONS ) );
}
@Override
public void setFocus ()
{
this.viewer.getControl ().setFocus ();
}
@Override
protected void clear ()
{
super.clear ();
scheduleJob ( new Runnable () {
public void run ()
{
MonitorsView.this.monitorSet.clear ();
MonitorsView.this.monitors.clear ();
MonitorsView.this.stateLabel.setText ( "<no query selected>" );
}
} );
}
@Override
public void handleDataChanged ( final MonitorStatusInformation[] addedOrUpdated, final String[] removed, final boolean full )
{
scheduleJob ( new Runnable () {
public void run ()
{
performDataChanged ( addedOrUpdated, removed );
}
} );
}
protected void performDataChanged ( final MonitorStatusInformation[] addedOrUpdated, final String[] removed )
{
logger.debug ( "Got data change" );
try
{
Collection<MonitorStatusBean> infos = new LinkedList<MonitorStatusBean> ();
if ( removed != null )
{
for ( final String id : removed )
{
final MonitorStatusBean info = this.monitorSet.remove ( id );
if ( info != null )
{
infos.add ( info );
}
}
}
this.monitors.removeAll ( infos );
infos = new LinkedList<MonitorStatusBean> ();
if ( addedOrUpdated != null )
{
for ( final MonitorStatusInformation info : addedOrUpdated )
{
if ( this.monitorSet.containsKey ( info.getId () ) )
{
// update
final MonitorStatusBean infoBean = this.monitorSet.get ( info.getId () );
infoBean.update ( info );
}
else
{
// add
final MonitorStatusBean infoBean = new MonitorStatusBean ( this.entry.getConnection (), info );
this.monitorSet.put ( info.getId (), infoBean );
infos.add ( infoBean );
}
}
}
this.monitors.addAll ( infos );
}
catch ( final Throwable e )
{
logger.warn ( "Failed to handle data", e );
}
}
@Override
public void handleStatusChanged ( final SubscriptionState status )
{
triggerStateUpdate ( status );
}
private void triggerStateUpdate ( final SubscriptionState status )
{
if ( this.stateLabel.isDisposed () )
{
return;
}
scheduleJob ( new Runnable () {
public void run ()
{
if ( MonitorsView.this.stateLabel.isDisposed () )
{
return;
}
MonitorsView.this.stateLabel.setText ( status.toString () );
}
} );
}
}