/***************************************************************************** * 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 - updated to new problem reporting * - added handling of default VO when adding/importing *****************************************************************************/ package eu.geclipse.ui.internal.preference; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; 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.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import eu.geclipse.core.model.GridModel; import eu.geclipse.core.model.IGridElement; import eu.geclipse.core.model.IGridModelEvent; import eu.geclipse.core.model.IGridModelListener; import eu.geclipse.core.model.IGridProject; import eu.geclipse.core.model.IVirtualOrganization; import eu.geclipse.core.model.IVoManager; import eu.geclipse.core.reporting.ProblemException; import eu.geclipse.ui.comparators.TableColumnComparator; import eu.geclipse.ui.dialogs.ProblemDialog; import eu.geclipse.ui.internal.Activator; import eu.geclipse.ui.internal.wizards.VoImportWizard; import eu.geclipse.ui.listeners.TableColumnListener; import eu.geclipse.ui.wizards.wizardselection.ExtPointWizardSelectionListPage; /** * The VO preferences page which allows add, remove and edit the available VOs. */ public class VoPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IGridModelListener { /** * Content provider for the {@link VoPreferencePage}. */ static class VoContentProvider implements IStructuredContentProvider { /** * The shell of the input. */ private Shell shell; /* (non-Javadoc) * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements( final Object inputElement ) { IGridElement[] result = null; if ( inputElement instanceof IVoManager ) { IVoManager manager = ( IVoManager ) inputElement; try { result = manager.getChildren( null ); Arrays.sort( result, new Comparator< IGridElement >() { public int compare( final IGridElement vo1, final IGridElement vo2 ) { return vo1.getName().compareTo( vo2.getName() ); } } ); } catch ( ProblemException pExc ) { if ( this.shell != null ) { ProblemDialog.openProblem( this.shell, Messages.getString("VoPreferencePage.content_provider_problem"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.query_vo_failed"), //$NON-NLS-1$ pExc ); } else { Activator.logException( pExc ); } } } return result; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { // empty implementation } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged( final Viewer viewer, final Object oldInput, final Object newInput ) { if ( viewer != null ) { this.shell = viewer.getControl().getShell(); } } } /** * Label provider for the {@link VoPreferencePage}. */ static class VoLabelProvider extends LabelProvider implements ITableLabelProvider { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) */ public Image getColumnImage( final Object element, final int columnIndex ) { return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) */ public String getColumnText( final Object element, final int columnIndex ) { String text = null; if ( element instanceof IVirtualOrganization ) { switch ( columnIndex ) { case 0: text = ( ( IVirtualOrganization ) element ).getName(); break; case 1: text = ( ( IVirtualOrganization ) element ).getTypeName(); break; } } return text; } } /** * The table viewer used to display the VOs. * Package visibility to avoid warning about synthetic accessor * performance issue. */ CheckboxTableViewer voViewer; /** * The button that triggers the creation of a new VO. */ private Button addButton; /** * The button that triggers the opening of the VO import wizard. */ private Button importButton; /** * The button that triggers the deletion of an existing VO. */ private Button removeButton; /** * The button that triggers the editing of an existing VO. */ private Button editButton; /** * Standard constructor for the VO preference page. */ public VoPreferencePage() { super(); setDescription( Messages.getString("VoPreferencePage.description") ); //$NON-NLS-1$ } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.DialogPage#dispose() */ @Override public void dispose() { GridModel.getVoManager().removeGridModelListener( this ); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) */ public void init( final IWorkbench workbench ) { setPreferenceStore( Activator.getDefault().getPreferenceStore() ); } /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents( final Composite parent ) { initializeDialogUnits( parent ); noDefaultAndApplyButton(); GridData gData; GridLayout layout= new GridLayout( 2, false ); layout.marginHeight = 0; layout.marginWidth = 0; parent.setLayout( layout ); Label voLabel = new Label( parent, SWT.NONE ); voLabel.setText( Messages.getString("VoPreferencePage.vo_list_label") ); //$NON-NLS-1$ gData = new GridData(); gData.horizontalSpan = 2; gData.grabExcessHorizontalSpace = true; voLabel.setLayoutData( gData ); Table voTable = new Table( parent, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION ); voTable.setHeaderVisible( true ); voTable.setLinesVisible( true ); gData = new GridData( GridData.FILL_BOTH ); gData.horizontalSpan = 1; gData.grabExcessHorizontalSpace = true; gData.grabExcessVerticalSpace = true; gData.widthHint = 200; gData.heightHint = 100; voTable.setLayoutData( gData ); voTable.addMouseListener( new MouseAdapter() { @Override public void mouseDoubleClick( final MouseEvent e ) { IVirtualOrganization selectedVo = getSelectedVo(); if ( selectedVo != null ) { editVO( selectedVo ); } } } ); voTable.addKeyListener( new KeyAdapter() { @Override public void keyPressed( final KeyEvent event ) { if (event.character == SWT.DEL && event.stateMask == 0) { removeSelectedVOs(); } } }); TableColumn nameColumn = new TableColumn( voTable, SWT.LEFT ); nameColumn.setText( Messages.getString("VoPreferencePage.name_column_text") ); //$NON-NLS-1$ nameColumn.setWidth( 100 ); TableColumn typeColumn = new TableColumn( voTable, SWT.CENTER ); typeColumn.setText( Messages.getString("VoPreferencePage.type_column_text") ); //$NON-NLS-1$ typeColumn.setWidth( 100 ); final IVoManager manager = GridModel.getVoManager(); this.voViewer = new CheckboxTableViewer( voTable ); this.voViewer.setLabelProvider( new VoLabelProvider() ); this.voViewer.setContentProvider( new VoContentProvider() ); TableColumnListener columnListener = new TableColumnListener( this.voViewer ); nameColumn.addSelectionListener( columnListener ); typeColumn.addSelectionListener( columnListener ); // Initially we sort the VOs by name, ascending voTable.setSortColumn( nameColumn ); voTable.setSortDirection( SWT.UP ); this.voViewer.setComparator( new TableColumnComparator( nameColumn ) ); this.voViewer.setInput( manager ); this.voViewer.addSelectionChangedListener( new ISelectionChangedListener() { public void selectionChanged( final SelectionChangedEvent event ) { updateButtons(); } } ); manager.addGridModelListener( this ); IVirtualOrganization defaultVo = ( IVirtualOrganization ) manager.getDefault(); if ( defaultVo != null ) { this.voViewer.setCheckedElements( new Object[] { defaultVo } ); } this.voViewer.addCheckStateListener( new ICheckStateListener() { public void checkStateChanged( final CheckStateChangedEvent event ) { Object element = event.getElement(); if ( element instanceof IVirtualOrganization ) { IVirtualOrganization vo = ( IVirtualOrganization ) element; try { if ( !event.getChecked() ) { manager.setDefault( null ); } else { // We want a radio-button behavior, as there is only one default VO VoPreferencePage.this.voViewer.setCheckedElements( new Object[] { vo } ); VoPreferencePage.this.voViewer.refresh(); manager.setDefault( vo ); } } catch ( ProblemException pExc ) { // TODO mathias Activator.logException( pExc ); } } } } ); Composite buttons = new Composite( parent, SWT.NULL ); gData = new GridData( GridData.VERTICAL_ALIGN_BEGINNING ); gData.horizontalSpan = 1; buttons.setLayoutData( gData ); GridLayout gLayout = new GridLayout( 1, false ); gLayout.marginHeight = 0; gLayout.marginWidth = 0; buttons.setLayout( gLayout ); this.addButton = new Button( buttons, SWT.PUSH ); this.addButton.setText( Messages.getString("VoPreferencePage.add_button") ); //$NON-NLS-1$ gData = new GridData( GridData.FILL_HORIZONTAL ); this.addButton.setLayoutData( gData ); this.importButton = new Button( buttons, SWT.PUSH ); this.importButton.setText( Messages.getString("VoPreferencePage.import_button") ); //$NON-NLS-1$ gData = new GridData( GridData.FILL_HORIZONTAL ); this.importButton.setLayoutData( gData ); this.editButton = new Button( buttons, SWT.PUSH ); this.editButton.setText( Messages.getString("VoPreferencePage.edit_button") ); //$NON-NLS-1$ gData = new GridData( GridData.FILL_HORIZONTAL ); this.editButton.setLayoutData( gData ); this.removeButton = new Button( buttons, SWT.PUSH ); this.removeButton.setText( Messages.getString("VoPreferencePage.remove_button") ); //$NON-NLS-1$ gData = new GridData( GridData.FILL_HORIZONTAL ); this.removeButton.setLayoutData( gData ); Label separator = new Label(buttons, SWT.NONE); separator.setVisible(false); gData = new GridData(); gData.horizontalAlignment= GridData.FILL; gData.heightHint= 4; separator.setLayoutData(gData); this.addButton.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent e ) { editVO( null ); } } ); this.importButton.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent e ) { importVOs(); } } ); this.editButton.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent e ) { IVirtualOrganization selectedVo = getSelectedVo(); if ( selectedVo != null ) { editVO( selectedVo ); } } } ); this.removeButton.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent e ) { removeSelectedVOs(); } } ); updateButtons(); return parent; } /** * Get the currently selected VO. * * @return The VO that is currently selected in the table control. */ public IVirtualOrganization getSelectedVo() { IVirtualOrganization selectedVo = null; IStructuredSelection selection = ( IStructuredSelection ) this.voViewer.getSelection(); Object obj = selection.getFirstElement(); if ( obj instanceof IVirtualOrganization ) { selectedVo = ( IVirtualOrganization ) obj; } return selectedVo; } /** * Get the currently selected VOs. * * @return The VOs that are currently selected in the table control. */ public List< IVirtualOrganization > getSelectedVos() { IStructuredSelection selection = ( IStructuredSelection ) this.voViewer.getSelection(); List< ? > selectionList = selection.toList(); List< IVirtualOrganization > result = new ArrayList< IVirtualOrganization >(); for ( Object element : selectionList ) { if ( element instanceof IVirtualOrganization ) { IVirtualOrganization vo = ( IVirtualOrganization ) element; result.add( vo ); } } return result; } /** * Trigger the new VO wizard to pop up in order to create a new VO if vo * parameter is null or edit existing vo if vo parameter is specified. * * @param vo To {@link IVirtualOrganization} to be edited. */ protected void editVO( final IVirtualOrganization vo ) { URL imgUrl = Activator.getDefault().getBundle().getEntry( "icons/wizban/vo_wiz.gif" ); //$NON-NLS-1$ Wizard wizard = new Wizard() { @Override public void addPages() { ExtPointWizardSelectionListPage page = new ExtPointWizardSelectionListPage( "pagename", //$NON-NLS-1$ "eu.geclipse.ui.newVoWizards", //$NON-NLS-1$ Messages.getString("VoPreferencePage.create_new_vo"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.create_new_vo_long"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.no_vo_providers") ); //$NON-NLS-1$ page.setInitData( vo ); if ( vo != null ) { page.setPreselectedId( vo.getWizardId(), true ); } addPage( page ); } @Override public boolean performFinish() { return false; } }; wizard.setForcePreviousAndNextButtons( true ); wizard.setNeedsProgressMonitor( true ); wizard.setWindowTitle( Messages.getString("VoPreferencePage.create_new_vo") ); //$NON-NLS-1$ wizard.setDefaultPageImageDescriptor( ImageDescriptor.createFromURL( imgUrl ) ); WizardDialog dialog = new WizardDialog( this.getShell(), wizard ); dialog.open(); /* * If no VOs were present before calling the wizard, there is now a default * VO to mark as checked. */ checkDefaultVo(); } protected void importVOs() { VoImportWizard wizard; try { wizard = new VoImportWizard(); WizardDialog dialog = new WizardDialog( getShell(), wizard ); dialog.open(); /* * If no VOs were present before importing, the VoManager will have set * the first new one as default. Thus we have to update the viewer's * checked element. */ checkDefaultVo(); } catch( ProblemException problemException ) { ProblemDialog.openProblem( getShell(), Messages.getString("VoPreferencePage.couldNotOpenImportVoWizard"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.couldNotOpenImportVoWizard"), //$NON-NLS-1$ problemException ); } } /** * Remove all VOs that are currently selected in the table control. */ protected void removeSelectedVOs() { List< IVirtualOrganization > vos = getSelectedVos(); if ( ! vos.isEmpty() ) { boolean confirm = MessageDialog.openConfirm( getShell(), Messages.getString("VoPreferencePage.delete_vos"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.really_delete_vos") ); //$NON-NLS-1$ if ( confirm ) { IGridElement[] projectElements = {}; // Collect a list of children of the GridRoot try { projectElements = GridModel.getRoot().getChildren( null ); } catch ( ProblemException pExc ) { // GridRoot is not a lazy container } IVoManager manager = GridModel.getVoManager(); IGridProject igp = null; for ( IVirtualOrganization vo : vos ) { // Check if the given VO is used by some GridProject on the WS boolean used = false; for ( IGridElement element : projectElements ) { igp = ( IGridProject ) element; // Projects have a ProjectVO wrapper, not the real VO IVirtualOrganization realVo = null; IVirtualOrganization projectVo = igp.getVO(); // HiddenProject doesn't have a VO if ( projectVo != null ) { realVo = ( IVirtualOrganization ) projectVo.getAdapter( IVirtualOrganization.class ); if ( ( realVo != null ) && ( vo == realVo ) ) { used = true; break; } } } if ( used ) { MessageDialog.openError( this.getShell(), Messages.getString("VoPreferencePage.error"), //$NON-NLS-1$ String.format( Messages.getString("VoPreferencePage.vo_in_use"), //$NON-NLS-1$ vo.getName(), igp.getName() ) ); } else { try { manager.delete( vo ); } catch ( ProblemException pExc ) { ProblemDialog.openProblem( this.getShell(), Messages.getString("VoPreferencePage.error"), //$NON-NLS-1$ Messages.getString("VoPreferencePage.delete_vo_failed") //$NON-NLS-1$ + " " + vo.getName(), //$NON-NLS-1$ pExc ); } } } /* * If the default VO was removed, another one was selected arbitrarily * by the VoManager. So we have to update the viewer's checked element. */ checkDefaultVo(); updateButtons(); } } } /** * Mark the default VO checked in the voViewer table. */ private void checkDefaultVo() { IVoManager manager = GridModel.getVoManager(); if ( ( manager.getChildCount() > 0 ) && ! this.voViewer.getControl().isDisposed() ) { Object[] checked = new Object[] { manager.getDefault() }; VoPreferencePage.this.voViewer.setCheckedElements( checked ); } } /** * Update the enabled state of the button controls. */ protected void updateButtons() { ISelection selection = this.voViewer.getSelection(); boolean selectionAvailable = !selection.isEmpty(); this.addButton.setEnabled( true ); this.importButton.setEnabled( true ); this.removeButton.setEnabled( selectionAvailable ); this.editButton.setEnabled( selectionAvailable ); } /* (non-Javadoc) * @see org.eclipse.compare.IContentChangeListener#contentChanged(org.eclipse.compare.IContentChangeNotifier) */ public void gridModelChanged( final IGridModelEvent source ) { this.voViewer.refresh(); IVoManager manager = GridModel.getVoManager(); IGridElement defaultVo = manager.getDefault(); if ( defaultVo != null ) { this.voViewer.setCheckedElements( new Object[] { defaultVo } ); } updateButtons(); } /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#performOk() */ @Override public boolean performOk() { try { GridModel.getVoManager().saveElements(); } catch ( ProblemException pExc ) { // TODO mathias Activator.logException( pExc ); } return super.performOk(); } /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ @Override protected void performDefaults() { try { GridModel.getVoManager().loadElements(); } catch ( ProblemException pExc ) { // TODO mathias Activator.logException( pExc ); } super.performDefaults(); } }