org.symbian.tools.mtw.ui/src/org/symbian/tools/tmw/internal/ui/wizard/FacetsSelectionPanel.java
changeset 463 aea4c83725d8
child 465 87920e15f8eb
equal deleted inserted replaced
462:cdc4995b1677 463:aea4c83725d8
       
     1 package org.symbian.tools.tmw.internal.ui.wizard;
       
     2 
       
     3 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.gdfill;
       
     4 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.gdhhint;
       
     5 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.gdhspan;
       
     6 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.gdwhint;
       
     7 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.gl;
       
     8 import static org.eclipse.wst.common.project.facet.ui.internal.util.GridLayoutUtil.glmargins;
       
     9 import static org.eclipse.wst.common.project.facet.ui.internal.util.SwtUtil.getPreferredWidth;
       
    10 import static org.eclipse.wst.common.project.facet.ui.internal.util.SwtUtil.runOnDisplayThread;
       
    11 
       
    12 import java.lang.reflect.Method;
       
    13 import java.text.MessageFormat;
       
    14 import java.util.ArrayList;
       
    15 import java.util.Arrays;
       
    16 import java.util.HashMap;
       
    17 import java.util.List;
       
    18 import java.util.Map;
       
    19 import java.util.Set;
       
    20 import java.util.SortedSet;
       
    21 
       
    22 import org.eclipse.core.runtime.IStatus;
       
    23 import org.eclipse.jface.dialogs.Dialog;
       
    24 import org.eclipse.jface.resource.CompositeImageDescriptor;
       
    25 import org.eclipse.jface.resource.ImageDescriptor;
       
    26 import org.eclipse.jface.resource.ImageRegistry;
       
    27 import org.eclipse.jface.viewers.CheckStateChangedEvent;
       
    28 import org.eclipse.jface.viewers.CheckboxTableViewer;
       
    29 import org.eclipse.jface.viewers.ICheckStateListener;
       
    30 import org.eclipse.jface.viewers.ILabelProviderListener;
       
    31 import org.eclipse.jface.viewers.ISelection;
       
    32 import org.eclipse.jface.viewers.ISelectionChangedListener;
       
    33 import org.eclipse.jface.viewers.ISelectionProvider;
       
    34 import org.eclipse.jface.viewers.IStructuredContentProvider;
       
    35 import org.eclipse.jface.viewers.IStructuredSelection;
       
    36 import org.eclipse.jface.viewers.ITableLabelProvider;
       
    37 import org.eclipse.jface.viewers.ITreeContentProvider;
       
    38 import org.eclipse.jface.viewers.LabelProvider;
       
    39 import org.eclipse.jface.viewers.SelectionChangedEvent;
       
    40 import org.eclipse.jface.viewers.StructuredSelection;
       
    41 import org.eclipse.jface.viewers.TableViewer;
       
    42 import org.eclipse.jface.viewers.Viewer;
       
    43 import org.eclipse.jface.viewers.ViewerSorter;
       
    44 import org.eclipse.jface.window.ToolTip;
       
    45 import org.eclipse.swt.SWT;
       
    46 import org.eclipse.swt.custom.SashForm;
       
    47 import org.eclipse.swt.events.DisposeEvent;
       
    48 import org.eclipse.swt.events.DisposeListener;
       
    49 import org.eclipse.swt.graphics.Image;
       
    50 import org.eclipse.swt.graphics.ImageData;
       
    51 import org.eclipse.swt.graphics.Point;
       
    52 import org.eclipse.swt.widgets.Composite;
       
    53 import org.eclipse.swt.widgets.Control;
       
    54 import org.eclipse.swt.widgets.Display;
       
    55 import org.eclipse.swt.widgets.Event;
       
    56 import org.eclipse.swt.widgets.Label;
       
    57 import org.eclipse.swt.widgets.Listener;
       
    58 import org.eclipse.swt.widgets.Table;
       
    59 import org.eclipse.swt.widgets.TableItem;
       
    60 import org.eclipse.ui.ISharedImages;
       
    61 import org.eclipse.ui.PlatformUI;
       
    62 import org.eclipse.wst.common.project.facet.core.IFacetedProjectWorkingCopy;
       
    63 import org.eclipse.wst.common.project.facet.core.IProjectFacet;
       
    64 import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
       
    65 import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectEvent;
       
    66 import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectListener;
       
    67 import org.eclipse.wst.common.project.facet.core.events.IProjectFacetsChangedEvent;
       
    68 import org.eclipse.wst.common.project.facet.core.runtime.RuntimeManager;
       
    69 import org.eclipse.wst.common.project.facet.core.runtime.events.IRuntimeLifecycleEvent;
       
    70 import org.eclipse.wst.common.project.facet.core.runtime.events.IRuntimeLifecycleListener;
       
    71 import org.eclipse.wst.common.project.facet.ui.IDecorationsProvider;
       
    72 import org.eclipse.wst.common.project.facet.ui.internal.FacetUiPlugin;
       
    73 import org.eclipse.wst.common.project.facet.ui.internal.util.BasicToolTip;
       
    74 import org.eclipse.wst.common.project.facet.ui.internal.util.HeaderToolTip;
       
    75 import org.symbian.tools.tmw.core.TMWCore;
       
    76 
       
    77 /**
       
    78  * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
       
    79  */
       
    80 
       
    81 public final class FacetsSelectionPanel extends Composite implements ISelectionProvider {
       
    82     private final Composite topComposite;
       
    83     private final SashForm sform1;
       
    84     private final CheckboxTableViewer tableViewer;
       
    85     private final Table table;
       
    86     private final FixedFacetToolTip fixedFacetToolTip;
       
    87     private final TableViewer problemsView;
       
    88     private boolean showToolTips;
       
    89     private final IFacetedProjectWorkingCopy fpjwc;
       
    90     private final List<IFacetedProjectListener> registeredWorkingCopyListeners;
       
    91     private final Map<IProjectFacet, IProjectFacetVersion> selectedVersions;
       
    92     private final List<ISelectionChangedListener> selectionListeners;
       
    93     private Object selection;
       
    94 
       
    95     /**
       
    96      * Holds images used throughout the panel.
       
    97      */
       
    98 
       
    99     private final ImageRegistry imageRegistry;
       
   100 
       
   101     private final IRuntimeLifecycleListener runtimeLifecycleListener;
       
   102 
       
   103     public interface IFilter {
       
   104         boolean check(IProjectFacetVersion fv);
       
   105     }
       
   106 
       
   107     public FacetsSelectionPanel(final Composite parent, final IFacetedProjectWorkingCopy fpjwc) {
       
   108         super(parent, SWT.NONE);
       
   109 
       
   110         this.fpjwc = fpjwc;
       
   111         this.registeredWorkingCopyListeners = new ArrayList<IFacetedProjectListener>();
       
   112         this.selectedVersions = new HashMap<IProjectFacet, IProjectFacetVersion>();
       
   113         this.selection = null;
       
   114         this.selectionListeners = new ArrayList<ISelectionChangedListener>();
       
   115         this.showToolTips = false;
       
   116 
       
   117         // Initialize the image registry.
       
   118 
       
   119         this.imageRegistry = new ImageRegistry();
       
   120         // Layout the panel.
       
   121 
       
   122         setLayout(glmargins(gl(1), 0, 0));
       
   123 
       
   124         this.topComposite = new Composite(this, SWT.NONE);
       
   125         this.topComposite.setLayout(glmargins(gl(4), 0, 0));
       
   126 
       
   127         this.sform1 = new SashForm(this.topComposite, SWT.VERTICAL | SWT.SMOOTH);
       
   128         this.sform1.setLayoutData(gdhspan(gdfill(), 4));
       
   129 
       
   130         this.table = new Table(this.sform1, SWT.BORDER | SWT.CHECK);
       
   131         this.tableViewer = new CheckboxTableViewer(this.table);
       
   132 
       
   133         this.tableViewer.setLabelProvider(new FacetColumnLabelProvider());
       
   134         this.tableViewer.setContentProvider(new ContentProvider());
       
   135         this.tableViewer.setSorter(new Sorter());
       
   136 
       
   137         new FacetToolTip(this.table);
       
   138         this.fixedFacetToolTip = new FixedFacetToolTip(this.table);
       
   139 
       
   140         this.tableViewer.setInput(new Object());
       
   141 
       
   142         this.tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
       
   143             public void selectionChanged(final SelectionChangedEvent e) {
       
   144                 FacetsSelectionPanel.this.handleSelectionChangedEvent();
       
   145             }
       
   146         });
       
   147 
       
   148         this.tableViewer.addCheckStateListener(new ICheckStateListener() {
       
   149             public void checkStateChanged(final CheckStateChangedEvent e) {
       
   150                 FacetsSelectionPanel.this.handleCheckStateChanged(e);
       
   151             }
       
   152         });
       
   153 
       
   154         this.table.addListener(SWT.MouseDown, new Listener() {
       
   155             public void handleEvent(final Event event) {
       
   156                 handleMouseDownEvent(event);
       
   157             }
       
   158         });
       
   159 
       
   160         this.problemsView = new TableViewer(this.sform1, SWT.BORDER);
       
   161         this.problemsView.setContentProvider(new ProblemsContentProvider());
       
   162         this.problemsView.setLabelProvider(new ProblemsLabelProvider());
       
   163         this.problemsView.setInput(new Object());
       
   164 
       
   165         addDisposeListener(new DisposeListener() {
       
   166             public void widgetDisposed(final DisposeEvent e) {
       
   167                 handleDisposeEvent();
       
   168             }
       
   169         });
       
   170 
       
   171         Dialog.applyDialogFont(parent);
       
   172 
       
   173         // Setup runtime lifecycle listener.
       
   174 
       
   175         this.runtimeLifecycleListener = new IRuntimeLifecycleListener() {
       
   176             public void handleEvent(final IRuntimeLifecycleEvent event) {
       
   177                 handleValidationProblemsChangedEvent();
       
   178             }
       
   179         };
       
   180 
       
   181         RuntimeManager
       
   182                 .addListener(this.runtimeLifecycleListener, IRuntimeLifecycleEvent.Type.VALIDATION_STATUS_CHANGED);
       
   183 
       
   184         // Bind to the model.
       
   185 
       
   186         addWorkingCopyListener(new IFacetedProjectListener() {
       
   187             public void handleEvent(final IFacetedProjectEvent event) {
       
   188                 handleProjectFacetsChangedEvent(event);
       
   189             }
       
   190         }, IFacetedProjectEvent.Type.PROJECT_FACETS_CHANGED);
       
   191 
       
   192         handleProjectFacetsChangedEvent(null);
       
   193 
       
   194         addWorkingCopyListener(new IFacetedProjectListener() {
       
   195             public void handleEvent(final IFacetedProjectEvent event) {
       
   196                 handleValidationProblemsChangedEvent();
       
   197             }
       
   198         }, IFacetedProjectEvent.Type.VALIDATION_PROBLEMS_CHANGED, IFacetedProjectEvent.Type.PROJECT_MODIFIED);
       
   199 
       
   200         handleValidationProblemsChangedEvent();
       
   201 
       
   202         addWorkingCopyListener(new IFacetedProjectListener() {
       
   203             public void handleEvent(final IFacetedProjectEvent event) {
       
   204                 handleModelChangedEvent(event);
       
   205             }
       
   206         }, IFacetedProjectEvent.Type.FIXED_FACETS_CHANGED, IFacetedProjectEvent.Type.SELECTED_PRESET_CHANGED,
       
   207                 IFacetedProjectEvent.Type.TARGETED_RUNTIMES_CHANGED);
       
   208 
       
   209         // Set the preferred dimensions of the panel.
       
   210 
       
   211         final int prefWidthTree = getPreferredWidth(this.table);
       
   212         final int prefWidth = prefWidthTree + 80;
       
   213 
       
   214         this.topComposite.setLayoutData(gdwhint(gdhhint(gdfill(), 500), prefWidth));
       
   215 
       
   216         this.sform1.setWeights(new int[] { 70, 30 });
       
   217 
       
   218         // Select the first item in the table.
       
   219 
       
   220         if (this.table.getItemCount() > 0) {
       
   221             final TableItem firstItem = this.table.getItem(0);
       
   222             this.tableViewer.setSelection(new StructuredSelection(firstItem.getData()));
       
   223         }
       
   224 
       
   225         handleSelectionChangedEvent();
       
   226     }
       
   227 
       
   228     public IFacetedProjectWorkingCopy getFacetedProjectWorkingCopy() {
       
   229         return this.fpjwc;
       
   230     }
       
   231 
       
   232     public boolean isSelectionValid() {
       
   233         return (this.fpjwc.validate().getSeverity() != IStatus.ERROR);
       
   234     }
       
   235 
       
   236     public boolean setFocus() {
       
   237         return this.table.setFocus();
       
   238     }
       
   239 
       
   240     public void addSelectionChangedListener(final ISelectionChangedListener listener) {
       
   241         this.selectionListeners.add(listener);
       
   242     }
       
   243 
       
   244     public void removeSelectionChangedListener(final ISelectionChangedListener listener) {
       
   245         this.selectionListeners.remove(listener);
       
   246     }
       
   247 
       
   248     public ISelection getSelection() {
       
   249         if (this.selection != null) {
       
   250             return new StructuredSelection(this.selection);
       
   251         } else {
       
   252             return new StructuredSelection(new Object[0]);
       
   253         }
       
   254     }
       
   255 
       
   256     public void setSelection(final ISelection selection) {
       
   257         throw new UnsupportedOperationException();
       
   258     }
       
   259 
       
   260     private void notifySelectionChangedListeners() {
       
   261         final SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
       
   262 
       
   263         for (ISelectionChangedListener listener : this.selectionListeners) {
       
   264             listener.selectionChanged(event);
       
   265         }
       
   266     }
       
   267 
       
   268     private ImageRegistry getImageRegistry() {
       
   269         return this.imageRegistry;
       
   270     }
       
   271 
       
   272     public Image getImage(final IProjectFacet facet, final boolean showDecorations) {
       
   273         final boolean isFixed = getFacetedProjectWorkingCopy().isFixedProjectFacet(facet);
       
   274         final String id = (isFixed && showDecorations ? "F:" : "f:") + facet.getId(); //$NON-NLS-1$ //$NON-NLS-2$
       
   275 
       
   276         Image image = getImageRegistry().get(id);
       
   277 
       
   278         if (image == null) {
       
   279             final IDecorationsProvider decprov = (IDecorationsProvider) facet.getAdapter(IDecorationsProvider.class);
       
   280 
       
   281             ImageDescriptor imgdesc = decprov.getIcon();
       
   282 
       
   283             if (isFixed && showDecorations) {
       
   284                 imgdesc = new FixedFacetImageDescriptor(imgdesc);
       
   285             }
       
   286 
       
   287             getImageRegistry().put(id, imgdesc);
       
   288             image = getImageRegistry().get(id);
       
   289         }
       
   290 
       
   291         return image;
       
   292     }
       
   293 
       
   294     private void refresh() {
       
   295         // Somehow the checked state of nested items gets lost when a refresh
       
   296         // is performed, so we have to do this workaround.
       
   297 
       
   298         final Object[] checked = this.tableViewer.getCheckedElements();
       
   299         this.tableViewer.refresh();
       
   300         this.tableViewer.setCheckedElements(checked);
       
   301     }
       
   302 
       
   303     public boolean getShowToolTips() {
       
   304         return this.showToolTips;
       
   305     }
       
   306 
       
   307     public void setShowToolTips(final boolean showToolTips) {
       
   308         this.showToolTips = showToolTips;
       
   309     }
       
   310 
       
   311     private void addWorkingCopyListener(final IFacetedProjectListener listener,
       
   312             final IFacetedProjectEvent.Type... types) {
       
   313         this.fpjwc.addListener(listener, types);
       
   314         this.registeredWorkingCopyListeners.add(listener);
       
   315     }
       
   316 
       
   317     public IProjectFacet getSelectedProjectFacet() {
       
   318         final IProjectFacetVersion fv = getSelectedProjectFacetVersion();
       
   319 
       
   320         if (fv != null) {
       
   321             return fv.getProjectFacet();
       
   322         }
       
   323 
       
   324         return null;
       
   325     }
       
   326 
       
   327     public IProjectFacetVersion getSelectedProjectFacetVersion() {
       
   328         if (this.selection != null && this.selection instanceof IProjectFacetVersion) {
       
   329             return (IProjectFacetVersion) this.selection;
       
   330         }
       
   331 
       
   332         return null;
       
   333     }
       
   334 
       
   335     private IProjectFacetVersion getSelectedVersion(final IProjectFacet f) {
       
   336         final Set<IProjectFacetVersion> availableVersions = this.fpjwc.getAvailableVersions(f);
       
   337 
       
   338         if (availableVersions.isEmpty()) {
       
   339             throw new IllegalStateException();
       
   340         }
       
   341 
       
   342         IProjectFacetVersion selectedVersion = this.fpjwc.getProjectFacetVersion(f);
       
   343 
       
   344         if (selectedVersion == null) {
       
   345             selectedVersion = this.selectedVersions.get(f);
       
   346 
       
   347             if (selectedVersion == null) {
       
   348                 selectedVersion = f.getDefaultVersion();
       
   349             }
       
   350 
       
   351             if (!availableVersions.contains(selectedVersion)) {
       
   352                 selectedVersion = this.fpjwc.getHighestAvailableVersion(f);
       
   353             }
       
   354         }
       
   355 
       
   356         this.selectedVersions.put(f, selectedVersion);
       
   357 
       
   358         return selectedVersion;
       
   359     }
       
   360 
       
   361     private void handleSelectionChangedEvent() {
       
   362         Object selection = ((IStructuredSelection) this.tableViewer.getSelection()).getFirstElement();
       
   363 
       
   364         if (selection != null && selection instanceof IProjectFacet) {
       
   365             selection = getSelectedVersion((IProjectFacet) selection);
       
   366         }
       
   367 
       
   368         if (selection != this.selection) {
       
   369             this.selection = selection;
       
   370 
       
   371             notifySelectionChangedListeners();
       
   372         }
       
   373     }
       
   374 
       
   375     private void handleCheckStateChanged(final CheckStateChangedEvent event) {
       
   376         final Object el = event.getElement();
       
   377         final boolean checked = event.getChecked();
       
   378 
       
   379         final IProjectFacet f = (IProjectFacet) el;
       
   380 
       
   381         if (this.fpjwc.getFixedProjectFacets().contains(f)) {
       
   382             if (!checked) {
       
   383                 this.tableViewer.setChecked(el, true);
       
   384 
       
   385                 final String msg = MessageFormat
       
   386                         .format("Project facet {0} cannot be deselected. It is critical to the proper function of this project.",
       
   387                                 f.getLabel());
       
   388 
       
   389                 this.fixedFacetToolTip.setMessage(msg);
       
   390 
       
   391                 final Point cursorLocation = getDisplay().getCursorLocation();
       
   392                 this.fixedFacetToolTip.show(this.table.toControl(cursorLocation));
       
   393             }
       
   394 
       
   395             return;
       
   396         }
       
   397 
       
   398         if (checked) {
       
   399             this.fpjwc.addProjectFacet(getSelectedVersion(f));
       
   400         } else {
       
   401             this.fpjwc.removeProjectFacet(f);
       
   402         }
       
   403 
       
   404         this.fpjwc.setSelectedPreset(null);
       
   405     }
       
   406 
       
   407     private void handleMouseDownEvent(final Event event) {
       
   408         handleMouseDownEventHelper(event, this.table.getItems());
       
   409     }
       
   410 
       
   411     private boolean handleMouseDownEventHelper(final Event event, final TableItem[] items) {
       
   412         for (TableItem item : items) {
       
   413             if (item.getBounds(1).contains(event.x, event.y)) {
       
   414                 final TableItem[] newSelection = new TableItem[] { item };
       
   415 
       
   416                 if (!Arrays.equals(this.table.getSelection(), newSelection)) {
       
   417                     this.table.setSelection(new TableItem[] { item });
       
   418                     this.tableViewer.editElement(item.getData(), 1);
       
   419                 }
       
   420 
       
   421                 return true;
       
   422             }
       
   423         }
       
   424 
       
   425         return false;
       
   426     }
       
   427 
       
   428     private void handleDisposeEvent() {
       
   429         this.imageRegistry.dispose();
       
   430 
       
   431         for (IFacetedProjectListener listener : this.registeredWorkingCopyListeners) {
       
   432             this.fpjwc.removeListener(listener);
       
   433         }
       
   434 
       
   435         RuntimeManager.removeListener(this.runtimeLifecycleListener);
       
   436     }
       
   437 
       
   438     private void handleProjectFacetsChangedEvent(final IFacetedProjectEvent event) {
       
   439         if (!Thread.currentThread().equals(getDisplay().getThread())) {
       
   440             final Runnable uiRunnable = new Runnable() {
       
   441                 public void run() {
       
   442                     handleProjectFacetsChangedEvent(event);
       
   443                 }
       
   444             };
       
   445 
       
   446             getDisplay().asyncExec(uiRunnable);
       
   447 
       
   448             return;
       
   449         }
       
   450 
       
   451         if (event != null) {
       
   452             final IFacetedProjectWorkingCopy fpjwc = event.getWorkingCopy();
       
   453 
       
   454             final IProjectFacetsChangedEvent evt = (IProjectFacetsChangedEvent) event;
       
   455 
       
   456             for (IProjectFacetVersion fv : evt.getAllAffectedFacets()) {
       
   457                 final IProjectFacet f = fv.getProjectFacet();
       
   458                 final boolean checked = fpjwc.hasProjectFacet(fv);
       
   459 
       
   460                 this.tableViewer.setChecked(f, checked);
       
   461                 this.tableViewer.update(f, null);
       
   462             }
       
   463         } else {
       
   464             final List<IProjectFacet> facets = new ArrayList<IProjectFacet>();
       
   465 
       
   466             for (IProjectFacetVersion fv : this.fpjwc.getProjectFacets()) {
       
   467                 facets.add(fv.getProjectFacet());
       
   468             }
       
   469 
       
   470             this.tableViewer.setCheckedElements(facets.toArray());
       
   471             this.tableViewer.update(this.fpjwc.getAvailableFacets().keySet().toArray(), null);
       
   472         }
       
   473     }
       
   474 
       
   475     private void handleValidationProblemsChangedEvent() {
       
   476         if (!Thread.currentThread().equals(getDisplay().getThread())) {
       
   477             final Runnable uiRunnable = new Runnable() {
       
   478                 public void run() {
       
   479                     handleValidationProblemsChangedEvent();
       
   480                 }
       
   481             };
       
   482 
       
   483             getDisplay().asyncExec(uiRunnable);
       
   484 
       
   485             return;
       
   486         }
       
   487 
       
   488         this.problemsView.refresh();
       
   489 
       
   490         if (getFilteredProblems().length == 0) {
       
   491             if (this.sform1.getMaximizedControl() == null) {
       
   492                 this.sform1.setMaximizedControl(this.tableViewer.getControl());
       
   493             }
       
   494         } else {
       
   495             if (this.sform1.getMaximizedControl() != null) {
       
   496                 this.sform1.setMaximizedControl(null);
       
   497             }
       
   498         }
       
   499     }
       
   500 
       
   501     private void handleModelChangedEvent(final IFacetedProjectEvent event) {
       
   502         switch (event.getType()) {
       
   503         case FIXED_FACETS_CHANGED:
       
   504         case TARGETED_RUNTIMES_CHANGED: {
       
   505             final Runnable runnable = new Runnable() {
       
   506                 public void run() {
       
   507                     refresh();
       
   508                 }
       
   509             };
       
   510 
       
   511             runOnDisplayThread(getDisplay(), runnable);
       
   512 
       
   513             break;
       
   514         }
       
   515         }
       
   516     }
       
   517 
       
   518     private TableItem getTreeItem(final int x, final int y) {
       
   519         return getTreeItemHelper(x, y, this.table.getItems());
       
   520     }
       
   521 
       
   522     private static TableItem getTreeItemHelper(final int x, final int y, final TableItem[] items) {
       
   523         for (TableItem item : items) {
       
   524             if (item.getBounds().contains(x, y)) {
       
   525                 return item;
       
   526             }
       
   527         }
       
   528 
       
   529         return null;
       
   530     }
       
   531 
       
   532     private IStatus[] getFilteredProblems() {
       
   533         final IStatus[] unfiltered = this.fpjwc.validate().getChildren();
       
   534         boolean somethingToRemove = false;
       
   535 
       
   536         for (IStatus st : unfiltered) {
       
   537             if (st.getCode() == IFacetedProjectWorkingCopy.PROBLEM_PROJECT_NAME) {
       
   538                 somethingToRemove = true;
       
   539                 break;
       
   540             }
       
   541         }
       
   542 
       
   543         if (!somethingToRemove) {
       
   544             return unfiltered;
       
   545         }
       
   546 
       
   547         final List<IStatus> filtered = new ArrayList<IStatus>();
       
   548 
       
   549         for (IStatus st : unfiltered) {
       
   550             if (st.getCode() != IFacetedProjectWorkingCopy.PROBLEM_PROJECT_NAME) {
       
   551                 filtered.add(st);
       
   552             }
       
   553         }
       
   554 
       
   555         return filtered.toArray(new IStatus[filtered.size()]);
       
   556     }
       
   557 
       
   558     private final class ContentProvider
       
   559 
       
   560     implements ITreeContentProvider
       
   561 
       
   562     {
       
   563         public Object[] getElements(final Object element) {
       
   564             final IFacetedProjectWorkingCopy fpjwc = getFacetedProjectWorkingCopy();
       
   565             final List<Object> list = new ArrayList<Object>();
       
   566             for (Map.Entry<IProjectFacet, SortedSet<IProjectFacetVersion>> entry : fpjwc.getAvailableFacets()
       
   567                     .entrySet()) {
       
   568                 final IProjectFacet f = entry.getKey();
       
   569                 final SortedSet<IProjectFacetVersion> availableVersions = entry.getValue();
       
   570 
       
   571                 if (f.getCategory() == null && !availableVersions.isEmpty()) {
       
   572                     list.add(f);
       
   573                 }
       
   574             }
       
   575 
       
   576             return list.toArray();
       
   577         }
       
   578 
       
   579         public Object[] getChildren(final Object parent) {
       
   580             return new Object[0];
       
   581         }
       
   582 
       
   583         public Object getParent(final Object element) {
       
   584             if (element instanceof IProjectFacet) {
       
   585                 final IProjectFacet f = (IProjectFacet) element;
       
   586                 return f.getCategory();
       
   587             } else {
       
   588                 return null;
       
   589             }
       
   590         }
       
   591 
       
   592         public boolean hasChildren(final Object element) {
       
   593             return false;
       
   594         }
       
   595 
       
   596         public void dispose() {
       
   597         }
       
   598 
       
   599         public void inputChanged(final Viewer viewer, final Object oldObject, final Object newObject) {
       
   600         }
       
   601     }
       
   602 
       
   603     private final class FacetColumnLabelProvider extends LabelProvider {
       
   604         @Override
       
   605         public String getText(final Object element) {
       
   606             return ((IProjectFacet) element).getLabel();
       
   607         }
       
   608 
       
   609         @Override
       
   610         public Image getImage(final Object element) {
       
   611             return FacetsSelectionPanel.this.getImage((IProjectFacet) element, true);
       
   612         }
       
   613     }
       
   614 
       
   615     private static final class FixedFacetImageDescriptor
       
   616 
       
   617     extends CompositeImageDescriptor
       
   618 
       
   619     {
       
   620         private static final String OVERLAY_IMG_LOCATION = "images/lock.gif"; //$NON-NLS-1$
       
   621 
       
   622         private static final ImageData OVERLAY = FacetUiPlugin.getImageDescriptor(OVERLAY_IMG_LOCATION).getImageData();
       
   623 
       
   624         private final ImageData base;
       
   625         private final Point size;
       
   626 
       
   627         public FixedFacetImageDescriptor(final ImageDescriptor base) {
       
   628             this.base = base.getImageData();
       
   629             this.size = new Point(this.base.width, this.base.height);
       
   630         }
       
   631 
       
   632         protected void drawCompositeImage(final int width, final int height) {
       
   633             drawImage(this.base, 0, 0);
       
   634             drawImage(OVERLAY, 0, height - OVERLAY.height);
       
   635         }
       
   636 
       
   637         protected Point getSize() {
       
   638             return this.size;
       
   639         }
       
   640     }
       
   641 
       
   642     private static final class Sorter extends ViewerSorter {
       
   643         public int compare(final Viewer viewer, final Object a, final Object b) {
       
   644             return getLabel(a).compareToIgnoreCase(getLabel(b));
       
   645         }
       
   646 
       
   647         private static String getLabel(final Object obj) {
       
   648             return ((IProjectFacet) obj).getLabel();
       
   649         }
       
   650     }
       
   651 
       
   652     private final class FacetToolTip extends HeaderToolTip {
       
   653         public FacetToolTip(final Control control) {
       
   654             super(control);
       
   655         }
       
   656 
       
   657         @Override
       
   658         protected final boolean shouldCreateToolTip(final Event event) {
       
   659             if (getShowToolTips() == false) {
       
   660                 return false;
       
   661             }
       
   662 
       
   663             final TableItem treeItem = getTreeItem(event.x, event.y);
       
   664             String description = null;
       
   665 
       
   666             if (treeItem != null && treeItem.getBounds(0).contains(event.x, event.y)) {
       
   667                 final Object treeItemData = treeItem.getData();
       
   668 
       
   669                 if (treeItemData instanceof IProjectFacet) {
       
   670                     description = ((IProjectFacet) treeItemData).getDescription();
       
   671                 }
       
   672             }
       
   673 
       
   674             return (description != null && description.trim().length() > 0);
       
   675         }
       
   676 
       
   677         @Override
       
   678         protected String getToolTipTitle(final Event event) {
       
   679             final IProjectFacet f = (IProjectFacet) getTreeItem(event.x, event.y).getData();
       
   680             return getSelectedVersion(f).toString();
       
   681         }
       
   682 
       
   683         @Override
       
   684         protected Composite createContentArea(final Event event, final Composite parent) {
       
   685             final Display display = parent.getDisplay();
       
   686 
       
   687             final Composite composite = new Composite(parent, SWT.NONE);
       
   688             composite.setLayout(gl(1));
       
   689             composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
       
   690 
       
   691             final Label label = new Label(composite, SWT.WRAP);
       
   692             label.setLayoutData(gdfill());
       
   693             label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
       
   694 
       
   695             final IProjectFacet f = (IProjectFacet) getTreeItem(event.x, event.y).getData();
       
   696             label.setText(f.getDescription());
       
   697 
       
   698             return composite;
       
   699         }
       
   700     }
       
   701 
       
   702     private final class FixedFacetToolTip extends BasicToolTip {
       
   703         private static final int FAKE_EVENT_TYPE = -9999;
       
   704 
       
   705         public FixedFacetToolTip(final Control control) {
       
   706             super(control);
       
   707             setPopupDelay(0);
       
   708         }
       
   709 
       
   710         public void show(final Point location) {
       
   711             // The JFace ToolTip class does not support alternative methods of tool tip activation.
       
   712             // An enhancement request https://bugs.eclipse.org/bugs/show_bug.cgi?id=174844 tracks
       
   713             // this issue. When that enhancement request has been resolved, this hacky 
       
   714             // implementation should be replaced with something more sensible.
       
   715 
       
   716             final Event fakeEvent = new Event();
       
   717             fakeEvent.type = FAKE_EVENT_TYPE;
       
   718             fakeEvent.x = location.x;
       
   719             fakeEvent.y = location.y;
       
   720 
       
   721             try {
       
   722                 final Method method = ToolTip.class.getDeclaredMethod("toolTipCreate", Event.class); //$NON-NLS-1$
       
   723 
       
   724                 method.setAccessible(true);
       
   725                 method.invoke(this, fakeEvent);
       
   726             } catch (Exception e) {
       
   727                 TMWCore.log(null, e);
       
   728             }
       
   729         }
       
   730 
       
   731         @Override
       
   732         protected final boolean shouldCreateToolTip(final Event event) {
       
   733             return (event.type == FAKE_EVENT_TYPE);
       
   734         }
       
   735     }
       
   736 
       
   737     private final class ProblemsContentProvider implements IStructuredContentProvider {
       
   738         public Object[] getElements(final Object element) {
       
   739             return getFilteredProblems();
       
   740         }
       
   741 
       
   742         public void inputChanged(final Viewer viewer, final Object oldObject, final Object newObject) {
       
   743         }
       
   744 
       
   745         public void dispose() {
       
   746         }
       
   747     }
       
   748 
       
   749     private final class ProblemsLabelProvider implements ITableLabelProvider {
       
   750         public String getColumnText(final Object element, final int column) {
       
   751             return ((IStatus) element).getMessage();
       
   752         }
       
   753 
       
   754         public Image getColumnImage(final Object element, final int column) {
       
   755             final ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
       
   756             final String imageType;
       
   757 
       
   758             if (((IStatus) element).getSeverity() == IStatus.ERROR) {
       
   759                 imageType = ISharedImages.IMG_OBJS_ERROR_TSK;
       
   760             } else {
       
   761                 imageType = ISharedImages.IMG_OBJS_WARN_TSK;
       
   762             }
       
   763 
       
   764             return sharedImages.getImage(imageType);
       
   765         }
       
   766 
       
   767         public boolean isLabelProperty(final Object obj, final String s) {
       
   768             return false;
       
   769         }
       
   770 
       
   771         public void dispose() {
       
   772         }
       
   773 
       
   774         public void addListener(final ILabelProviderListener listener) {
       
   775         }
       
   776 
       
   777         public void removeListener(ILabelProviderListener listener) {
       
   778         }
       
   779     }
       
   780 }