/* * This file is part of the OpenSCADA project * Copyright (C) 2006-2011 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.da.client.dataitem.details; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.openscada.core.ui.styles.StyleInformation; import org.openscada.da.client.DataItemValue; import org.openscada.da.client.dataitem.details.part.DetailsPart; import org.openscada.da.ui.connection.data.DataItemHolder; import org.openscada.da.ui.connection.data.DataSourceListener; import org.openscada.da.ui.connection.data.Item; public class DetailsViewComposite extends Composite { private final Collection<DetailsPart> detailParts = new LinkedList<DetailsPart> (); private DataItemHolder dataItem; private CTabFolder tabFolder; private Label headerLabel; private Composite header; private Label headerValueLabel; private final LocalResourceManager resourceManager = new LocalResourceManager ( JFaceResources.getResources () ); private final Display display; public DetailsViewComposite ( final Composite parent, final int style ) { super ( parent, style ); this.display = parent.getDisplay (); addDisposeListener ( new DisposeListener () { @Override public void widgetDisposed ( final DisposeEvent e ) { handleDispose (); } } ); createControls ( parent ); } private void createControls ( final Composite parent ) { final GridLayout layout = new GridLayout ( 1, false ); layout.marginHeight = layout.marginWidth = 0; setLayout ( layout ); createHeader ( this ); this.tabFolder = new CTabFolder ( this, SWT.BOTTOM | SWT.FLAT ); this.tabFolder.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, true ) ); try { for ( final DetailsPartInformation info : getPartInformation () ) { final CTabItem tabItem = new CTabItem ( this.tabFolder, SWT.NONE ); final Composite parentComposite = new Composite ( this.tabFolder, SWT.NONE ); parentComposite.setLayout ( new FillLayout () ); tabItem.setControl ( parentComposite ); createDetailsPart ( tabItem, parentComposite, info ); } } catch ( final CoreException e ) { Activator.getDefault ().getLog ().log ( e.getStatus () ); } if ( !this.detailParts.isEmpty () ) { this.tabFolder.setSelection ( 0 ); } } private void createDetailsPart ( final CTabItem tabItem, final Composite parent, final DetailsPartInformation info ) throws CoreException { tabItem.setText ( info.getLabel () ); info.getDetailsPart ().createPart ( parent ); this.detailParts.add ( info.getDetailsPart () ); } private Collection<DetailsPartInformation> getPartInformation () throws CoreException { final List<DetailsPartInformation> result = new LinkedList<DetailsPartInformation> (); for ( final IConfigurationElement element : Platform.getExtensionRegistry ().getConfigurationElementsFor ( Activator.EXTP_DETAILS_PART ) ) { if ( !"detailsPart".equals ( element.getName () ) ) //$NON-NLS-1$ { continue; } Object o; o = element.createExecutableExtension ( "class" ); //$NON-NLS-1$ if ( ! ( o instanceof DetailsPart ) ) { throw new CoreException ( new Status ( IStatus.ERROR, Activator.PLUGIN_ID, "DetailsPart is not of type 'DetailsPart'" ) ); //$NON-NLS-1$ } final DetailsPartInformation info = new DetailsPartInformation (); info.setDetailsPart ( (DetailsPart)o ); info.setLabel ( element.getAttribute ( "name" ) ); //$NON-NLS-1$ info.setSortKey ( element.getAttribute ( "sortKey" ) ); //$NON-NLS-1$ result.add ( info ); } Collections.sort ( result, new Comparator<DetailsPartInformation> () { @Override public int compare ( final DetailsPartInformation arg0, final DetailsPartInformation arg1 ) { String key1 = arg0.getSortKey (); String key2 = arg1.getSortKey (); if ( key1 == null ) { key1 = ""; //$NON-NLS-1$ } if ( key2 == null ) { key2 = ""; //$NON-NLS-1$ } return key1.compareTo ( key2 ); } } ); return result; } private void createHeader ( final Composite parent ) { this.header = new Composite ( parent, SWT.NONE ); this.header.setLayoutData ( new GridData ( SWT.FILL, SWT.BEGINNING, true, false ) ); this.header.setLayout ( new RowLayout ( SWT.HORIZONTAL ) ); this.headerLabel = new Label ( this.header, SWT.NONE ); this.headerLabel.setText ( Messages.DetailsViewComposite_EmptyDataItem ); this.headerValueLabel = new Label ( this.header, SWT.NONE ); } private void handleDispose () { for ( final DetailsPart part : this.detailParts ) { part.dispose (); } disposeDataItem (); this.resourceManager.dispose (); } /** * set the current data item * @param item data item or <code>null</code> if none should be selected */ public void setDataItem ( final Item item ) { disposeDataItem (); if ( item != null ) { if ( this.headerLabel != null ) { this.headerLabel.setText ( String.format ( Messages.DetailsViewComposite_DataItemFormat, item.getId () ) ); this.headerValueLabel.setText ( "" ); //$NON-NLS-1$ } this.dataItem = new DataItemHolder ( Activator.getDefault ().getBundle ().getBundleContext (), item, new DataSourceListener () { @Override public void updateData ( final DataItemValue value ) { DetailsViewComposite.this.updateData ( value ); } } ); for ( final DetailsPart part : this.detailParts ) { part.setDataItem ( this.dataItem ); } } else { if ( this.headerLabel != null ) { this.headerLabel.setText ( Messages.DetailsViewComposite_EmptyDataItem ); this.headerValueLabel.setText ( "" ); //$NON-NLS-1$ } // clear for ( final DetailsPart part : this.detailParts ) { part.setDataItem ( null ); } } } protected void updateData ( final DataItemValue value ) { this.display.asyncExec ( new Runnable () { @Override public void run () { updateHeader ( value ); for ( final DetailsPart part : DetailsViewComposite.this.detailParts ) { part.updateData ( value ); } } } ); } private void updateHeader ( final DataItemValue value ) { if ( this.headerValueLabel.isDisposed () ) { return; } if ( value == null ) { this.headerValueLabel.setText ( Messages.DetailsViewComposite_NoValueText ); this.headerValueLabel.setForeground ( null ); this.headerLabel.setForeground ( null ); this.header.setForeground ( null ); this.headerValueLabel.setBackground ( null ); this.headerLabel.setBackground ( null ); this.header.setBackground ( null ); return; } // set the value label this.headerValueLabel.setText ( value.toString () ); final StyleInformation style = org.openscada.da.ui.styles.Activator.getStyle ( value ); this.headerValueLabel.setForeground ( style.createForeground ( this.resourceManager ) ); this.headerValueLabel.setBackground ( style.createBackground ( this.resourceManager ) ); this.headerValueLabel.setFont ( style.createFont ( this.resourceManager ) ); this.header.setForeground ( style.createForeground ( this.resourceManager ) ); this.header.setBackground ( style.createBackground ( this.resourceManager ) ); this.header.setFont ( style.createFont ( this.resourceManager ) ); this.headerLabel.setForeground ( style.createForeground ( this.resourceManager ) ); this.headerLabel.setBackground ( style.createBackground ( this.resourceManager ) ); this.headerLabel.setFont ( style.createFont ( this.resourceManager ) ); this.header.layout (); } private void disposeDataItem () { if ( this.dataItem != null ) { this.dataItem.dispose (); this.dataItem = null; } } }