/****************************************************************************** * Copyright (c) 2008-2013, Linagora * * 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 * * Contributors: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.services.su.wizards.pages; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.IWizardNode; import org.eclipse.jface.wizard.WizardSelectionPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Image; 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.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.plugin.AbstractUIPlugin; import com.ebmwebsourcing.petals.common.internal.provisional.preferences.PreferencesManager; import com.ebmwebsourcing.petals.common.internal.provisional.swt.DefaultSelectionListener; import com.ebmwebsourcing.petals.common.internal.provisional.swt.DefaultTreeContentProvider; import com.ebmwebsourcing.petals.common.internal.provisional.swt.PhantomText; import com.ebmwebsourcing.petals.common.internal.provisional.ui.FixedShellTooltip; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PetalsConstants; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PlatformUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.StringUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.SwtFactory; import com.ebmwebsourcing.petals.services.PetalsServicesPlugin; import com.ebmwebsourcing.petals.services.su.extensions.ExtensionManager; import com.ebmwebsourcing.petals.services.su.extensions.IComponentDescription; import com.ebmwebsourcing.petals.services.su.extensions.PetalsKeyWords; import com.ebmwebsourcing.petals.services.su.wizards.AbstractServiceUnitWizard; import com.ebmwebsourcing.petals.services.su.wizards.FinishServiceCreationStrategy; import com.ebmwebsourcing.petals.services.su.wizards.PetalsMode; /** * Choose the kind of SU to create. * @author Vincent Zurczak - EBM WebSourcing */ public class ChoicePage extends WizardSelectionPage { public static final String PAGE_NAME = "ChoicePage"; private final Map<PetalsKeyWords,Image> keywordToImage; private Image helpImg; private final Image bcImg; private final Image seImg; private Font boldFont; private FixedShellTooltip helpTooltip; private final PetalsMode petalsMode; private final FinishServiceCreationStrategy strategy; /** * Constructor. * @param strategy */ public ChoicePage( PetalsMode petalsMode, FinishServiceCreationStrategy strategy ) { super( PAGE_NAME ); this.petalsMode = petalsMode; this.strategy = strategy; setTitle( petalsMode == PetalsMode.provides ? "Petals Service Provider" : "Petals Service Consumer" ); setDescription( "Select the Petals component to configure and its version." ); this.bcImg = PetalsServicesPlugin.loadImage( "icons/obj16/choice_bc_16x16.png" ); this.seImg = PetalsServicesPlugin.loadImage( "icons/obj16/choice_se_16x16.png" ); this.keywordToImage = new HashMap<PetalsKeyWords,Image> (); for( PetalsKeyWords kw : PetalsKeyWords.values()) { try { Image img = kw.getImageDescriptor().createImage(); this.keywordToImage.put( kw, img ); } catch( Exception e ) { PetalsServicesPlugin.log( e, IStatus.ERROR ); } } } /* * (non-Javadoc) * @see org.eclipse.jface.dialogs.IDialogPage * #createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl( Composite parent ) { // Create the composite container and define its layout final Composite container = SwtFactory.createComposite( parent ); setControl( container ); SwtFactory.applyNewGridLayout( container, 2, false, 15, 0, 0, 15 ); SwtFactory.applyHorizontalGridData( container ); // Add a tool tip to display in case of problem this.helpTooltip = new FixedShellTooltip( getShell(), true, 90 ) { @Override public void populateTooltip( Composite parent ) { GridLayout layout = new GridLayout(); layout.verticalSpacing = 2; parent.setLayout( layout ); parent.setLayoutData( new GridData( GridData.FILL_BOTH )); parent.setBackground( getShell().getDisplay().getSystemColor( SWT.COLOR_LIST_BACKGROUND )); try { ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin( PetalsConstants.PETALS_COMMON_PLUGIN_ID, "icons/petals/thinking_hard.png" ); if( desc != null ) ChoicePage.this.helpImg = desc.createImage(); parent.setBackgroundMode( SWT.INHERIT_DEFAULT ); Label imgLabel = new Label( parent, SWT.NONE ); imgLabel.setImage( ChoicePage.this.helpImg ); imgLabel.setLayoutData( new GridData( SWT.CENTER, SWT.DEFAULT, true, true )); } catch( Exception e ) { PetalsServicesPlugin.log( e, IStatus.WARNING ); } FontData[] fd = PlatformUtils.getModifiedFontData( getFont().getFontData(), SWT.BOLD ); ChoicePage.this.boldFont = new Font( getShell().getDisplay(), fd ); Label titleLabel = new Label( parent, SWT.NONE ); titleLabel.setFont( ChoicePage.this.boldFont ); GridData layoutData = new GridData( SWT.CENTER, SWT.DEFAULT, true, true ); layoutData.verticalIndent = 5; titleLabel.setLayoutData( layoutData ); titleLabel.setText( "What does this error mean?" ); Label l = new Label( parent, SWT.WRAP ); l.setText( "This wizard will generate, among other things, Maven artifacts." ); layoutData = new GridData(); layoutData.verticalIndent = 8; l.setLayoutData( layoutData ); RowLayout rowLayout = new RowLayout( SWT.HORIZONTAL ); rowLayout.marginLeft = 0; rowLayout.marginTop = 0; rowLayout.marginRight = 0; rowLayout.marginBottom = 0; rowLayout.spacing = 0; Composite rowComposite = new Composite( parent, SWT.NONE ); rowComposite.setLayout( rowLayout ); rowComposite.setLayoutData( new GridData( SWT.CENTER, SWT.DEFAULT, true, true )); new Label( rowComposite, SWT.WRAP ).setText( "Unfortunately, there is a problem with the " ); Link link = new Link( rowComposite, SWT.WRAP | SWT.NO_FOCUS ); link.setText( "<A>the Petals Maven preferences</A>" ); new Label( rowComposite, SWT.WRAP ).setText( "." ); new Label( parent, SWT.WRAP ).setText( "Please, make them correct." ); link.addSelectionListener( new DefaultSelectionListener() { @Override public void widgetSelected( SelectionEvent e ) { try { PreferencesUtil.createPreferenceDialogOn( new Shell(), "com.ebmwebsourcing.petals.services.prefs.maven", null, null ).open(); } catch( Exception e1 ) { PetalsServicesPlugin.log( e1, IStatus.ERROR ); } } }); } }; // Prepare the input Comparator<AbstractServiceUnitWizard> comparator = new Comparator<AbstractServiceUnitWizard>() { @Override public int compare( AbstractServiceUnitWizard o1, AbstractServiceUnitWizard o2 ) { String v1 = o1.getComponentVersionDescription().getComponentVersion(); String v2 = o2.getComponentVersionDescription().getComponentVersion(); return - v1.compareTo( v2 ); // negative so that the most recent is first } }; final Map<String,Collection<AbstractServiceUnitWizard>> componentNameToHandler = new TreeMap<String,Collection<AbstractServiceUnitWizard>> (); final Map<PetalsKeyWords,Set<String>> keywordToComponentName = new TreeMap<PetalsKeyWords,Set<String>> (); for( AbstractServiceUnitWizard handler : ExtensionManager.INSTANCE.findComponentWizards( this.petalsMode )) { for( PetalsKeyWords keyword : handler.getComponentVersionDescription().getKeyWords()) { Set<String> list = keywordToComponentName.get( keyword ); if( list == null ) list = new TreeSet<String> (); String componentName = handler.getComponentVersionDescription().getComponentName(); list.add( componentName ); keywordToComponentName.put( keyword, list ); Collection<AbstractServiceUnitWizard> handlers = componentNameToHandler.get( componentName ); if( handlers == null ) handlers = new TreeSet<AbstractServiceUnitWizard>( comparator ); handlers.add( handler ); componentNameToHandler.put( componentName, handlers ); } } // Add the selection area final PhantomText searchText = new PhantomText( container, SWT.SINGLE | SWT.BORDER ); searchText.setDefaultValue( "Search..." ); GridDataFactory.swtDefaults().grab( true, false ).align( SWT.FILL, SWT.TOP ).span( 2, 1 ).applyTo( searchText ); final TreeViewer componentsViewer = new TreeViewer( container, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION ); GridDataFactory.fillDefaults().span( 2, 1 ).hint( 380, 300 ).applyTo( componentsViewer.getTree()); componentsViewer.setLabelProvider( new LabelProvider() { @Override public String getText( Object element ) { String result; if( element instanceof String ) { IComponentDescription desc = componentNameToHandler.get( element ).iterator().next().getComponentVersionDescription(); String componentName = desc.getComponentName(); String componentAlias = desc.getComponentAlias(); String annotation = desc.getComponentAnnotation(); StringBuilder sb = new StringBuilder(); if( StringUtils.isEmpty( componentName )) sb.append( componentAlias ); // Generic component else sb.append( componentAlias + " - " + componentName ); if( ! StringUtils.isEmpty( annotation )) sb.append( " ( " + annotation + " )" ); result = sb.toString(); } else { result = super.getText( element ); } return result; } @Override public Image getImage( Object element ) { Image result = null; if( element instanceof PetalsKeyWords ) { result = ChoicePage.this.keywordToImage.get( element ); } else { IComponentDescription desc = componentNameToHandler.get( element ).iterator().next().getComponentVersionDescription(); result = desc.isBc() ? ChoicePage.this.bcImg : ChoicePage.this.seImg; } return result; } }); componentsViewer.setContentProvider( new DefaultTreeContentProvider() { @Override public Object[] getElements( Object inputElement ) { return keywordToComponentName.keySet().toArray(); } @Override public Object[] getChildren( Object parentElement ) { Object[] result; if( parentElement instanceof PetalsKeyWords ) { Collection<String> componentNames = keywordToComponentName.get( parentElement ); result = componentNames == null ? new Object[ 0 ] : componentNames.toArray(); } else { result = new Object[ 0 ]; } return result; } @Override public boolean hasChildren( Object element ) { return element instanceof PetalsKeyWords; } }); componentsViewer.addFilter( new ViewerFilter() { @Override public boolean select( Viewer viewer, Object parentElement, Object element ) { boolean result = false; String filter = searchText.getTextValue().trim().toLowerCase(); if( filter.length() == 0 ) result = true; else if( element instanceof PetalsKeyWords ) { Set<String> names = keywordToComponentName.get( element ); if( names != null ) { for( String s : names ) { if( select( viewer, null, s )) { result = true; break; } } } } else if( element instanceof String ) result = ((String) element).toLowerCase().contains( filter ); return result; } }); componentsViewer.setInput( new Object()); if( keywordToComponentName.size() > 0 ) componentsViewer.expandToLevel( keywordToComponentName.keySet().iterator().next(), 1 ); // Display the available versions new Label( container, SWT.NONE ).setText( "Component Version:" ); final ComboViewer versionCombo = new ComboViewer( container, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY ); GridData layoutData = new GridData(); layoutData.widthHint = 130; versionCombo.getCombo().setLayoutData( layoutData ); versionCombo.setContentProvider( new ArrayContentProvider()); versionCombo.setLabelProvider( new LabelProvider() { @Override public String getText( Object element ) { return ((AbstractServiceUnitWizard) element).getComponentVersionDescription().getComponentVersion(); } }); final Label descriptionLabel = new Label( container, SWT.NONE ); GridDataFactory.swtDefaults().span( 2, 1 ).indent( 0, 10 ).applyTo( descriptionLabel ); // Selection listeners searchText.addModifyListener( new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { componentsViewer.refresh(); if( searchText.getTextValue().trim().length() == 0 ) componentsViewer.collapseAll(); else componentsViewer.expandAll(); } }); componentsViewer.addSelectionChangedListener( new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent event ) { // Get the selection Object o = ((IStructuredSelection) event.getSelection()).getFirstElement(); Collection<?> input; if( o == null || o instanceof PetalsKeyWords ) input = Collections.emptyList(); else input = componentNameToHandler.get( o ); // Default selection - there is always one versionCombo.setInput( input ); versionCombo.getCombo().setVisibleItemCount( input.size() > 0 ? input.size() : 1 ); if( ! input.isEmpty()) { versionCombo.setSelection( new StructuredSelection( input.iterator().next())); versionCombo.getCombo().notifyListeners( SWT.Selection, new Event()); } else { setPageComplete( false ); setSelectedNode( null ); descriptionLabel.setText( "" ); descriptionLabel.getParent().layout(); } } }); versionCombo.addSelectionChangedListener( new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent event ) { AbstractServiceUnitWizard suWizard = (AbstractServiceUnitWizard) ((IStructuredSelection) event.getSelection()).getFirstElement(); if( suWizard == null ) return; setPageComplete( true ); setSelectedNode( getWizardNode( suWizard )); String desc = ChoicePage.this.petalsMode == PetalsMode.provides ? suWizard.getComponentVersionDescription().getProvideDescription() : suWizard.getComponentVersionDescription().getConsumeDescription(); descriptionLabel.setText( desc ); descriptionLabel.getParent().layout(); } }); // Initialize if( PreferencesManager.isMavenTemplateConfigurationValid()) this.helpTooltip.hide(); componentsViewer.getTree().setFocus(); } /** * @param wizard * @return */ protected IWizardNode getWizardNode(AbstractServiceUnitWizard wizard) { wizard.setStrategy(this.strategy); return new ComponentWizardDescriptionWizardNode(wizard); } /* * (non-Javadoc) * @see org.eclipse.jface.dialogs.DialogPage * #dispose() */ @Override public void dispose() { this.helpTooltip.dispose(); if( this.helpImg != null && ! this.helpImg.isDisposed()) this.helpImg.dispose(); if( this.seImg != null && ! this.seImg.isDisposed()) this.seImg.dispose(); if( this.bcImg != null && ! this.bcImg.isDisposed()) this.bcImg.dispose(); if( this.boldFont != null && ! this.boldFont.isDisposed()) this.boldFont.dispose(); for( Image img : this.keywordToImage.values()) { if( img != null && ! img.isDisposed()) img.dispose(); } super.dispose(); } }