/*****************************************************************************
* Copyright (c) 2006-2008 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
* Ariel Garcia - switch to use a CheckboxTableViewer
* - make it a IGridModelListener
*****************************************************************************/
package eu.geclipse.ui.wizards;
import java.net.URL;
import java.util.ArrayList;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.ImageDescriptor;
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.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
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.Group;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.PreferencesUtil;
import eu.geclipse.core.model.GridModel;
import eu.geclipse.core.model.IGridElement;
import eu.geclipse.core.model.IGridInfoService;
import eu.geclipse.core.model.IGridModelEvent;
import eu.geclipse.core.model.IGridModelListener;
import eu.geclipse.core.model.IVirtualOrganization;
import eu.geclipse.core.reporting.ProblemException;
import eu.geclipse.ui.dialogs.ProblemDialog;
import eu.geclipse.ui.internal.Activator;
/**
* A wizard page allowing to select a VO from the list of VOs registered
* in the VO manager. It also allows to edit the VOs on the fly by opening
* the VO preferences page.
*/
public class VoSelectionWizardPage extends WizardPage
implements IGridModelListener
{
CheckboxTableViewer tableViewer;
java.util.List< IVirtualOrganization > voList;
Class< ? > voType;
boolean allowMultiSelection;
private Text infoText;
private final String PREFERENCE_PAGE_ID = "eu.geclipse.ui.internal.preference.VOPreferencePage"; //$NON-NLS-1$
public VoSelectionWizardPage( final boolean allowMultiSelection ) {
this( allowMultiSelection, null );
}
public VoSelectionWizardPage( final boolean allowMultiSelection,
final Class< ? > voType ) {
super( "eu.geclipse.ui.voSelectionWizardPage", //$NON-NLS-1$
"VO Selection Page",
null );
setDescription( "Specify the VO that should be used" );
URL imgUrl = Activator.getDefault().getBundle().getEntry( "icons/wizban/vo_wiz.gif" ); //$NON-NLS-1$
setImageDescriptor( ImageDescriptor.createFromURL( imgUrl ) );
this.allowMultiSelection = allowMultiSelection;
this.voType = voType;
this.voList = new ArrayList< IVirtualOrganization >();
}
public void createControl( final Composite parent ) {
GridData gData;
Composite mainComp = new Composite( parent, SWT.NONE );
mainComp.setLayout( new GridLayout( 1, false ) );
gData = new GridData( GridData.FILL_BOTH );
gData.grabExcessHorizontalSpace = true;
gData.grabExcessVerticalSpace = true;
mainComp.setLayoutData( gData );
Group voGroup = new Group( mainComp, SWT.NONE );
voGroup.setLayout( new GridLayout( 2, false ) );
voGroup.setText( "&Available VOs" );
gData = new GridData( SWT.FILL, SWT.FILL, true, true );
gData.heightHint = 120;
voGroup.setLayoutData( gData );
int style = SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.CHECK;
Table voTable = new Table( voGroup, style );
gData = new GridData( SWT.FILL, SWT.FILL, true, true);
voTable.setLayoutData( gData );
voTable.setHeaderVisible( false );
this.tableViewer = new CheckboxTableViewer( voTable );
this.tableViewer.setContentProvider( new ArrayContentProvider() );
this.tableViewer.setLabelProvider( new LabelProvider() {
@Override
public String getText( final Object element ) {
return ( (IVirtualOrganization) element ).getName();
}
} );
this.tableViewer.setComparator( new ViewerComparator() {
@Override
public int compare( final Viewer viewer, final Object vo1, final Object vo2 ) {
String name1 = ( (IVirtualOrganization) vo1 ).getName();
String name2 = ( (IVirtualOrganization) vo2 ).getName();
// Sort by VO name
return name1.compareTo( name2 );
}
} );
// Filter the VOs that can be used to create this type of auth-token
this.tableViewer.addFilter( new ViewerFilter() {
@Override
public boolean select( final Viewer viewer,
final Object parentElement,
final Object element )
{
boolean ret = false;
Class< ? > type = VoSelectionWizardPage.this.voType;
if ( element instanceof IVirtualOrganization ) {
IVirtualOrganization vo = (IVirtualOrganization) element;
if ( ( type == null ) || type.isAssignableFrom( vo.getClass() ) ) {
ret = true;
}
}
return ret;
}
} );
this.tableViewer.addSelectionChangedListener( new ISelectionChangedListener() {
public void selectionChanged( final SelectionChangedEvent event ) {
showSelectedInfo();
}
} );
this.tableViewer.addCheckStateListener( new ICheckStateListener() {
public void checkStateChanged( final CheckStateChangedEvent event ) {
// If allowMultiSelection is not set, then implement a radio-button behavior
if ( ! VoSelectionWizardPage.this.allowMultiSelection ) {
Object element = event.getElement();
if ( element instanceof IVirtualOrganization ) {
IVirtualOrganization vo = ( IVirtualOrganization ) element;
if ( event.getChecked() ) {
VoSelectionWizardPage.this.tableViewer.setCheckedElements( new Object[] { vo } );
VoSelectionWizardPage.this.tableViewer.refresh();
}
}
}
setPageComplete( getSelectedVos() != null );
}
} );
updateVoList();
this.tableViewer.setInput( this.voList );
// Listen on new VOs, this will update the tableViewer
GridModel.getVoManager().addGridModelListener( this );
Button editVOsButton = new Button( voGroup, SWT.PUSH );
editVOsButton.setText( "Edit &VOs..." );
gData = new GridData();
gData.horizontalAlignment = GridData.BEGINNING;
gData.verticalAlignment = GridData.BEGINNING;
editVOsButton.setLayoutData( gData );
editVOsButton.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent e ) {
PreferenceDialog dialog
= PreferencesUtil.createPreferenceDialogOn( getShell(),
VoSelectionWizardPage.this.PREFERENCE_PAGE_ID,
null,
null );
/*
* Even if the user pressed 'Cancel' VOs might have been
* added/deleted, so ignore the dialog's return value.
*/
dialog.open();
}
} );
Group infoGroup = new Group( mainComp, SWT.NONE );
infoGroup.setLayout( new GridLayout( 1, false ) );
infoGroup.setText( "&VO Info" );
gData = new GridData( SWT.FILL, SWT.FILL, true, true );
gData.heightHint = 120;
infoGroup.setLayoutData( gData );
this.infoText = new Text( infoGroup, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL );
this.infoText.setEditable( false );
gData = new GridData( GridData.FILL_BOTH );
gData.grabExcessHorizontalSpace = true;
gData.grabExcessVerticalSpace = true;
this.infoText.setLayoutData( gData );
setInitialSelection();
showSelectedInfo();
setPageComplete( getSelectedVos() != null );
setControl( mainComp );
}
/*
* (non-Javadoc)
* @see eu.geclipse.core.model.IGridModelListener#gridModelChanged(eu.geclipse.core.model.IGridModelEvent)
*/
public void gridModelChanged( final IGridModelEvent event ) {
IGridElement[] elements = event.getElements();
// We are a listener of the VoManager only
assert elements[ 0 ] instanceof IVirtualOrganization
: "VoSelectionWizardPage expects events whose source is an IVirtualOrganization."; //$NON-NLS-1$
switch ( event.getType() ) {
case IGridModelEvent.ELEMENTS_ADDED:
updateVoList();
this.tableViewer.setInput( this.voList );
// Each event contains a single element
setSelection( elements[ 0 ] );
break;
case IGridModelEvent.ELEMENTS_REMOVED:
updateVoList();
this.tableViewer.setInput( this.voList );
// If the selected VO has been deleted select the default one
IVirtualOrganization[] selectedVOs = getSelectedVos();
if ( selectedVOs == null ) {
setInitialSelection();
}
break;
default:
// Do nothing in other cases
}
setPageComplete( getSelectedVos() != null );
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.DialogPage#dispose()
*/
@Override
public void dispose() {
GridModel.getVoManager().removeGridModelListener( this );
super.dispose();
}
/**
* Get the list of checked VOs
*
* @return the array of VOs checked in the viewer
*/
public IVirtualOrganization[] getSelectedVos() {
java.util.List< IVirtualOrganization > selectedVos
= new ArrayList< IVirtualOrganization >();
for ( Object vo : this.tableViewer.getCheckedElements() ) {
selectedVos.add( ( IVirtualOrganization ) vo );
}
if ( selectedVos.size() == 0 ) {
setErrorMessage( "No valid VO is selected" );
} else {
setErrorMessage( null );
}
return
selectedVos.size() == 0
? null
: selectedVos.toArray( new IVirtualOrganization[ selectedVos.size() ] );
}
/**
* Select the given VOs by setting the checkboxes
*
* @param vos an array of VOs to check on the viewer
*/
public void setSelectedVos( final IGridElement[] vos ) {
if ( vos == null || vos.length == 0 ) {
return;
}
if ( VoSelectionWizardPage.this.allowMultiSelection ) {
this.tableViewer.setCheckedElements( vos );
} else {
assert vos.length == 1
: "VoSelectionWizardPage got more than one VO to select while allowMultiSelection=false."; //$NON-NLS-1$
this.tableViewer.setChecked( vos[ 0 ], true );
}
this.tableViewer.refresh();
}
protected void showSelectedInfo() {
int index = this.tableViewer.getTable().getSelectionIndex();
if ( index >= 0 ) {
IVirtualOrganization vo
= (IVirtualOrganization) this.tableViewer.getElementAt( index );
try {
String text = ""; //$NON-NLS-1$
text += "Name:\n\t" + vo.getName() + '\n';
text += "Type:\n\t" + vo.getTypeName() + '\n';
IGridInfoService infoService = vo.getInfoService();
if ( infoService != null ) {
text += "\nInformation Service:\n\tName:\n\t\t" + infoService.getName();
text += "\n\tURI:\n\t\t" + infoService.getURI().toString();
}
//
// This forces an Infosystem query for every click on a VO!!
// Don't show non-static info here!
/*
IGridService[] services = vo.getServices();
text += "\n\nOther Services:";
if ( ( services != null ) && ( services.length > 1 ) ) {
for ( IGridService service : services ) {
if ( service != infoService ) {
text += "\n\tName:\n\t\t" + service.getName();
URI uri = service.getURI();
if ( uri != null ) {
text += "\n\tURI:\n\t\t" + service.getURI().toString();
} else {
text += "\n\tURI:\n\t\tN/A";
}
}
}
} else {
text += "\n\tNone";
}
*/
this.infoText.setText( text );
} catch ( ProblemException pExc ) {
ProblemDialog.openProblem( getShell(),
"VO info problem",
"Unable to query services for VO " + vo.getName(),
pExc );
}
} else {
this.infoText.setText( "" ); //$NON-NLS-1$
}
// This is needed if the text is changed while the dialog is not focused
this.infoText.redraw();
}
/**
* Load the list of VOs from the manager.
*/
private void updateVoList() {
this.voList.clear();
try {
IGridElement[] vos = GridModel.getVoManager().getChildren( null );
for ( IGridElement vo : vos ) {
this.voList.add( ( IVirtualOrganization ) vo );
}
} catch ( ProblemException pExc ) {
ProblemDialog.openProblem( getShell(),
"VO list problem",
"Unable to query registered VOs",
pExc );
}
}
/**
* Set the specified VO as selected (clicked and checked) in the viewer.
*
* @param vo the VO to set as checked/selected
*/
private void setSelection( final IGridElement vo ) {
// Do nothing if there is no VO to select
if ( vo == null || ! ( vo instanceof IVirtualOrganization ) ) {
return;
}
// If allowMultiSelection is not set we implement a radio-button behavior
if ( VoSelectionWizardPage.this.allowMultiSelection ) {
this.tableViewer.setChecked( vo, true );
} else {
this.tableViewer.setCheckedElements( new Object[] { vo } );
}
this.tableViewer.refresh();
StructuredSelection sel = new StructuredSelection( vo );
this.tableViewer.setSelection( sel, true );
}
/**
* Determines which VO to select initially in the viewer.
*/
private void setInitialSelection() {
IGridElement defaultVo = GridModel.getVoManager().getDefault();
if ( defaultVo == null ) {
// No default VO, take the first entry if any, null otherwise
defaultVo = ( IGridElement ) this.tableViewer.getElementAt( 0 );
} else {
// Check if the default VO is of the requested voType
boolean show = true;
for ( ViewerFilter filter: this.tableViewer.getFilters() ) {
show &= filter.select( this.tableViewer, this.voList, defaultVo );
}
// If it is not, then select the first of the list if any, null otherwise
if ( ! show ) {
defaultVo = ( IGridElement ) this.tableViewer.getElementAt( 0 );
}
}
setSelection( defaultVo );
}
}