/*****************************************************************************
* Copyright (c) 2006, 2007 g-Eclipse Consortium
* 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
*
* Initial development of the original code was made for the
* g-Eclipse project founded by European Union
* project number: FP6-IST-034327 http://www.geclipse.eu/
*
* Contributors:
* Mathias Stuempert - initial API and implementation
*****************************************************************************/
package eu.geclipse.ui.widgets;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.osgi.framework.Bundle;
import eu.geclipse.core.ExtensionManager;
import eu.geclipse.core.Extensions;
import eu.geclipse.core.model.GridModel;
import eu.geclipse.core.model.IGridContainer;
import eu.geclipse.core.model.IGridElement;
import eu.geclipse.core.model.IGridProject;
import eu.geclipse.core.model.IGridResource;
import eu.geclipse.core.model.IVirtualOrganization;
import eu.geclipse.ui.internal.Activator;
import eu.geclipse.ui.providers.ArrayTableLabelProvider;
public class GridProjectStructureComposite extends Composite {
private static final int LABEL_COLUMN = 1;
protected TableEditor editor;
private Tree previewTree;
private TreeItem rootItem;
private Table table;
private CheckboxTableViewer viewer;
private Hashtable< String, Class< ? > > creatorTargets;
private Hashtable<String, Class<?>> elementClasses;
public GridProjectStructureComposite( final Composite parent, final int style ) {
super(parent, style);
GridData gData;
setLayout( new GridLayout( 3, false ) );
gData = new GridData( GridData.FILL_BOTH );
gData.grabExcessHorizontalSpace = true;
gData.grabExcessVerticalSpace = true;
setLayoutData( gData );
Composite previewComp = new Composite( this, SWT.NONE );
previewComp.setLayout( new GridLayout( 1, false ) );
gData = new GridData( GridData.FILL_VERTICAL );
gData.grabExcessVerticalSpace = true;
previewComp.setLayoutData( gData );
Label previewLabel = new Label( previewComp, SWT.NONE );
previewLabel.setText( "Preview:" );
gData = new GridData();
previewLabel.setLayoutData( gData );
this.previewTree = new Tree( previewComp, SWT.BORDER );
gData = new GridData( GridData.FILL_VERTICAL );
gData.grabExcessVerticalSpace = true;
gData.widthHint = 150;
this.previewTree.setLayoutData( gData );
this.rootItem = new TreeItem( this.previewTree, SWT.NONE );
this.rootItem.setText( "My Cloud/Grid Project" );
this.rootItem.setImage(
PlatformUI.getWorkbench()
.getSharedImages()
.getImage( IDE.SharedImages.IMG_OBJ_PROJECT )
);
Composite settingsComp = new Composite( this, SWT.NONE );
settingsComp.setLayout( new GridLayout( 1, false ) );
gData = new GridData( GridData.FILL_BOTH );
gData.grabExcessVerticalSpace = true;
gData.grabExcessHorizontalSpace = true;
settingsComp.setLayoutData( gData );
Label settingsLabel = new Label( settingsComp, SWT.NONE );
settingsLabel.setText( "Available Folders:" );
gData = new GridData();
settingsLabel.setLayoutData( gData );
this.table = new Table( settingsComp, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK | SWT.FULL_SELECTION );
this.table.setHeaderVisible( true );
gData = new GridData( GridData.FILL_BOTH );
gData.grabExcessHorizontalSpace = true;
gData.grabExcessVerticalSpace = true;
this.table.setLayoutData( gData );
TableColumn nameColumn = new TableColumn( this.table, SWT.NONE );
nameColumn.setText( "Folder ID" );
nameColumn.setWidth( 150 );
TableColumn labelColumn = new TableColumn( this.table, SWT.None );
labelColumn.setText( "Folder Label" );
labelColumn.setWidth( 100 );
this.editor = new TableEditor( this.table );
this.editor.grabHorizontal = true;
this.editor.minimumWidth = 100;
this.editor.horizontalAlignment = SWT.LEFT;
this.table.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent e ) {
startEditing( ( TableItem ) e.item );
}
} );
this.viewer = new CheckboxTableViewer( this.table );
this.viewer.setContentProvider( new ArrayContentProvider() );
this.viewer.setLabelProvider( new ArrayTableLabelProvider() );
this.viewer.addCheckStateListener( new ICheckStateListener() {
public void checkStateChanged( final CheckStateChangedEvent e ) {
updateTree();
}
} );
Composite buttonComp = new Composite( settingsComp, SWT.NONE );
GridLayout buttonLayout = new GridLayout( 3, false );
buttonLayout.marginHeight = 0;
buttonLayout.marginWidth = 0;
buttonComp.setLayout( buttonLayout );
buttonComp.setLayoutData( new GridData( SWT.BEGINNING, SWT.BEGINNING, false, false ) );
Button selectAllButton = new Button( buttonComp, SWT.NONE );
selectAllButton.setText( "Select All" );
selectAllButton.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, false ) );
selectAllButton.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent e ) {
selectAll();
}
} );
Button deselectAllButton = new Button( buttonComp, SWT.NONE );
deselectAllButton.setText( "Deselect All" );
deselectAllButton.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, false ) );
deselectAllButton.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent e ) {
deselectAll();
}
} );
Button invertButton = new Button( buttonComp, SWT.NONE );
invertButton.setText( "Invert Selection" );
invertButton.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, false ) );
invertButton.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent e ) {
invertSelection();
}
} );
loadProjectFolders();
initialize();
updateTree();
}
public Hashtable< String, String > getProjectFolders() {
Hashtable< String, String > result = new Hashtable< String, String >();
List< String[] > input = ( List< String[] > ) this.viewer.getInput();
TableItem[] items = this.table.getItems();
for ( int i = 0 ; i < items.length ; i++ ) {
if ( items[i].getChecked() ) {
String id = input.get( i )[2];
String label = items[i].getText( 1 );
result.put( id, label );
}
}
return result;
}
public void performDefaults() {
loadProjectFolders();
updateTree();
}
public void setProject( final IProject project ) throws CoreException {
Hashtable< String, String > projectFolders = new Hashtable< String, String >();
IGridProject gridProject = ( IGridProject ) GridModel.getRoot().findElement( project );
IResource[] members = project.members();
for ( IResource resource : members ) {
String name = resource.getName();
IGridElement element = gridProject.findChild( name );
if ( ( element != null ) && ( element instanceof IGridContainer ) ) {
String id = gridProject.getProjectFolderID( ( IGridContainer ) element );
if ( id != null ) {
projectFolders.put( id, name );
}
}
}
setProjectFolders( projectFolders );
}
public void setProjectFolders( final Hashtable< String, String > projectFolders ) {
List< String[] > input = ( List< String[] > ) this.viewer.getInput();
TableItem[] items = this.table.getItems();
for ( int i = 0 ; i < input.size() ; i++ ) {
String id = input.get( i )[2];
String name = projectFolders.get( id );
if ( name != null ) {
items[ i ].setChecked( true );
items[ i ].setText( 1, name );
} else {
items[ i ].setChecked( false );
}
}
updateTree();
}
protected void selectAll() {
this.viewer.setAllChecked( true );
updateTree();
}
protected void deselectAll() {
this.viewer.setAllChecked( false );
updateTree();
}
protected void invertSelection() {
List< String[] > elements = ( List< String[] > ) this.viewer.getInput();
for ( String[] element : elements ) {
boolean state = this.viewer.getChecked( element );
this.viewer.setChecked( element, ! state );
}
updateTree();
}
protected void updateTree() {
this.rootItem.removeAll();
Object[] checked = this.viewer.getCheckedElements();
TableItem[] data = this.table.getItems();
TreeItem[] treeItems = new TreeItem[ checked.length ];
int index = 0;
for ( TableItem row : data ) {
if ( row.getChecked() ) {
treeItems[ index ] = new TreeItem( this.rootItem, SWT.NONE );
treeItems[ index ].setText( row.getText( LABEL_COLUMN ) );
treeItems[ index ].setImage(
PlatformUI.getWorkbench()
.getSharedImages()
.getImage( ISharedImages.IMG_OBJ_FOLDER )
);
index++;
}
}
for ( String name : this.creatorTargets.keySet() ) {
Class< ? > creatorTarget = this.creatorTargets.get( name );
TreeItem parentItem = findParentForTarget( checked,
treeItems,
creatorTarget, true );
// IGridWorkflowDescripion extends IGridJobDescription, so both classes fit into the same target.
// So first let's check exact target (comparing classes), then use isAssignable()
if( parentItem == null ) {
parentItem = findParentForTarget( checked, treeItems, creatorTarget, false );
}
if( parentItem == null ) {
parentItem = this.rootItem;
}
TreeItem leafItem = new TreeItem( parentItem, SWT.NONE );
leafItem.setText( name );
leafItem.setImage(
PlatformUI.getWorkbench()
.getSharedImages()
.getImage( ISharedImages.IMG_OBJ_FILE )
);
}
this.rootItem.setExpanded( true );
for ( TreeItem child : this.rootItem.getItems() ) {
child.setExpanded( true );
}
}
private TreeItem findParentForTarget( final Object[] checked,
final TreeItem[] treeItems,
final Class<?> creatorTarget,
final boolean equalClass )
{
TreeItem parentItem = null;
for ( int i = 0 ; i < checked.length && parentItem == null; i++ ) {
try {
String elementClassName = ( ( String[] ) checked[i] ) [ 3 ];
Class<?> elementClass = this.elementClasses.get( elementClassName );
if( elementClass == null ) {
elementClass = Class.forName( elementClassName );
}
if( equalClass ) {
if( elementClass.equals( creatorTarget ) ) {
parentItem = treeItems[ i ];
}
} else {
if ( elementClass.isAssignableFrom( creatorTarget ) ) {
parentItem = treeItems[ i ];
}
}
} catch ( ClassNotFoundException cnfExc ) {
Activator.logException( cnfExc );
}
}
return parentItem;
}
private void initialize() {
if ( this.creatorTargets == null ) {
this.creatorTargets = new Hashtable< String, Class< ? > >();
ExtensionManager extm = new ExtensionManager();
List< IConfigurationElement > creators = GridModel.getCreatorRegistry().getConfigurations();
for ( IConfigurationElement creator : creators ) {
IConfigurationElement[] targets
= creator.getChildren( Extensions.GRID_ELEMENT_CREATOR_TARGET_ELEMENT );
if ( targets != null ) {
for ( IConfigurationElement target : targets ) {
String name = target.getAttribute( Extensions.GRID_ELEMENT_CREATOR_TARGET_NAME_ATTRIBUTE );
String className = target.getAttribute( Extensions.GRID_ELEMENT_CREATOR_TARGET_CLASS_ATTRIBUTE );
String contributor = target.getContributor().getName();
Bundle bundle = Platform.getBundle( contributor );
if ( bundle != null ) {
try {
Class< ? > cls = bundle.loadClass( className );
if ( ! IGridResource.class.isAssignableFrom( cls )
&& ! IVirtualOrganization.class.isAssignableFrom( cls ) ) {
this.creatorTargets.put( name, cls );
}
} catch ( ClassNotFoundException cnfExc ) {
Activator.logException( cnfExc );
}
}
}
}
}
}
}
private void loadProjectFolders() {
if( elementClasses == null ) {
this.elementClasses = new Hashtable<String, Class<?>>();
}
List< String[] > input = new ArrayList< String[] >();
List< String[] > checked = new ArrayList< String[] >();
ExtensionManager extm = new ExtensionManager();
List< IConfigurationElement > configurationElements
= extm.getConfigurationElements( Extensions.PROJECT_FOLDER_POINT, Extensions.PROJECT_FOLDER_ELEMENT );
for ( IConfigurationElement element : configurationElements ) {
String id = element.getAttribute( Extensions.PROJECT_FOLDER_ID_ATTRIBUTE );
String name = element.getAttribute( Extensions.PROJECT_FOLDER_NAME_ATTRIBUTE );
String label = element.getAttribute( Extensions.PROJECT_FOLDER_LABEL_ATTRIBUTE );
String cls = element.getAttribute( Extensions.PROJECT_FOLDER_ELEMENTCLASS_ATTRIBUTE );
try {
String contributor = element.getContributor().getName();
Bundle bundle = Platform.getBundle( contributor );
Class<?> elementClass = bundle.loadClass( cls );
this.elementClasses.put( cls, elementClass );
} catch( ClassNotFoundException exception ) {
Activator.logException( exception );
}
boolean preset = Boolean.parseBoolean( element.getAttribute( Extensions.PROJECT_FOLDER_PRESET_ATTRIBUTE ) );
String[] row = new String[] { name, label, id, cls };
input.add( row );
if ( preset ) {
checked.add( row );
}
}
this.viewer.setInput( input );
this.viewer.setCheckedElements( checked.toArray() );
}
private void startEditing( final TableItem item ) {
Control oldEditor = this.editor.getEditor();
if ( oldEditor != null ) {
oldEditor.dispose();
}
if ( item != null ) {
Text text = new Text( this.table, SWT.NONE );
text.setText( item.getText( LABEL_COLUMN ) );
text.addModifyListener( new ModifyListener() {
public void modifyText( final ModifyEvent e ) {
Text t = ( Text ) GridProjectStructureComposite.this.editor.getEditor();
GridProjectStructureComposite.this.editor.getItem().setText( LABEL_COLUMN, t.getText() );
updateTree();
}
} );
text.selectAll();
text.setFocus();
this.editor.setEditor( text, item, LABEL_COLUMN );
}
}
}