KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > ide > misc > ProjectCapabilitySelectionGroup


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog font should be
11  * activated and used by other components.
12  *******************************************************************************/

13 package org.eclipse.ui.internal.ide.misc;
14
15 import java.text.Collator JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Arrays JavaDoc;
18 import java.util.Collection JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Comparator JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.LinkedList JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import org.eclipse.jface.dialogs.MessageDialog;
28 import org.eclipse.jface.resource.ImageDescriptor;
29 import org.eclipse.jface.viewers.CheckStateChangedEvent;
30 import org.eclipse.jface.viewers.CheckboxTableViewer;
31 import org.eclipse.jface.viewers.ICheckStateListener;
32 import org.eclipse.jface.viewers.IContentProvider;
33 import org.eclipse.jface.viewers.ISelection;
34 import org.eclipse.jface.viewers.ISelectionChangedListener;
35 import org.eclipse.jface.viewers.IStructuredSelection;
36 import org.eclipse.jface.viewers.LabelProvider;
37 import org.eclipse.jface.viewers.ListViewer;
38 import org.eclipse.jface.viewers.SelectionChangedEvent;
39 import org.eclipse.jface.viewers.StructuredSelection;
40 import org.eclipse.osgi.util.NLS;
41 import org.eclipse.swt.SWT;
42 import org.eclipse.swt.graphics.Font;
43 import org.eclipse.swt.graphics.Image;
44 import org.eclipse.swt.layout.GridData;
45 import org.eclipse.swt.layout.GridLayout;
46 import org.eclipse.swt.widgets.Composite;
47 import org.eclipse.swt.widgets.Control;
48 import org.eclipse.swt.widgets.Label;
49 import org.eclipse.swt.widgets.Text;
50 import org.eclipse.ui.internal.ide.Category;
51 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
52 import org.eclipse.ui.internal.ide.registry.Capability;
53 import org.eclipse.ui.internal.ide.registry.CapabilityRegistry;
54 import org.eclipse.ui.model.WorkbenchContentProvider;
55 import org.eclipse.ui.model.WorkbenchLabelProvider;
56
57 /**
58  * A group of controls used to view and modify the
59  * set of capabilities on a project.
60  */

61 public class ProjectCapabilitySelectionGroup {
62     private static final String JavaDoc EMPTY_DESCRIPTION = "\n\n\n"; //$NON-NLS-1$
63

64     private CapabilityRegistry registry;
65
66     private Category[] initialCategories;
67
68     private Capability[] initialCapabilities;
69
70     private Capability[] disabledCapabilities;
71
72     private boolean modified = false;
73
74     private Text descriptionText;
75
76     private CheckboxTableViewer checkboxViewer;
77
78     private ICheckStateListener checkStateListener;
79
80     private ArrayList JavaDoc visibleCapabilities = new ArrayList JavaDoc();
81
82     private ArrayList JavaDoc checkedCapabilities = new ArrayList JavaDoc();
83
84     private Collection JavaDoc disabledCaps;
85
86     // For a given capability as key, the value will be a list of
87
// other capabilities that require the capability. Also,
88
// it may include the capability key if it was selected by the
89
// user before being required by other capabilities.
90
private HashMap JavaDoc dependents = new HashMap JavaDoc();
91
92     // For a given membership set id as key, the value is
93
// a checked capability
94
private HashMap JavaDoc memberships = new HashMap JavaDoc();
95
96     // Sort categories
97
private Comparator JavaDoc categoryComparator = new Comparator JavaDoc() {
98         private Collator JavaDoc collator = Collator.getInstance();
99
100         public int compare(Object JavaDoc ob1, Object JavaDoc ob2) {
101             Category c1 = (Category) ob1;
102             Category c2 = (Category) ob2;
103             return collator.compare(c1.getLabel(), c2.getLabel());
104         }
105     };
106
107     // Sort capabilities
108
private Comparator JavaDoc capabilityComparator = new Comparator JavaDoc() {
109         private Collator JavaDoc collator = Collator.getInstance();
110
111         public int compare(Object JavaDoc ob1, Object JavaDoc ob2) {
112             Capability c1 = (Capability) ob1;
113             Capability c2 = (Capability) ob2;
114             return collator.compare(c1.getName(), c2.getName());
115         }
116     };
117
118     /**
119      * Creates a new instance of the <code>ProjectCapabilitySelectionGroup</code>
120      *
121      * @param categories the initial collection of valid categories to select
122      * @param capabilities the intial collection of valid capabilities to select
123      * @param registry all available capabilities registered by plug-ins
124      */

125     public ProjectCapabilitySelectionGroup(Category[] categories,
126             Capability[] capabilities, CapabilityRegistry registry) {
127         this(categories, capabilities, null, registry);
128     }
129
130     /**
131      * Creates a new instance of the <code>ProjectCapabilitySelectionGroup</code>
132      *
133      * @param categories the initial collection of valid categories to select
134      * @param capabilities the intial collection of valid capabilities to select
135      * @param disabledCapabilities the collection of capabilities to show as disabled
136      * @param registry all available capabilities registered by plug-ins
137      */

138     public ProjectCapabilitySelectionGroup(Category[] categories,
139             Capability[] capabilities, Capability[] disabledCapabilities,
140             CapabilityRegistry registry) {
141         super();
142         this.initialCategories = categories;
143         this.initialCapabilities = capabilities;
144         this.disabledCapabilities = disabledCapabilities;
145         this.registry = registry;
146     }
147
148     /**
149      * Create the contents of this group. The basic layout is a checkbox
150      * list with a text field at the bottom to display the capability
151      * description.
152      */

153     public Control createContents(Composite parent) {
154         Font font = parent.getFont();
155         // Create the main composite for the other controls
156
Composite composite = new Composite(parent, SWT.NONE);
157         GridLayout layout = new GridLayout();
158         layout.numColumns = 2;
159         layout.makeColumnsEqualWidth = true;
160         composite.setLayout(layout);
161         composite.setLayoutData(new GridData(GridData.FILL_BOTH));
162
163         // Composite for category label and list...
164
Composite catComposite = new Composite(composite, SWT.NONE);
165         catComposite.setLayout(new GridLayout());
166         catComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
167
168         // Add a label to identify the list viewer of categories
169
Label categoryLabel = new Label(catComposite, SWT.LEFT);
170         categoryLabel.setText(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_categories);
171         GridData data = new GridData();
172         data.verticalAlignment = SWT.TOP;
173         categoryLabel.setLayoutData(data);
174         categoryLabel.setFont(font);
175
176         // List viewer of all available categories
177
ListViewer listViewer = new ListViewer(catComposite);
178         listViewer.getList().setLayoutData(new GridData(GridData.FILL_BOTH));
179         listViewer.getList().setFont(font);
180         listViewer.setLabelProvider(new WorkbenchLabelProvider());
181         listViewer.setContentProvider(getContentProvider());
182         listViewer.setInput(getAvailableCategories());
183
184         // Composite for capability label and table...
185
Composite capComposite = new Composite(composite, SWT.NONE);
186         capComposite.setLayout(new GridLayout());
187         capComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
188
189         // Add a label to identify the checkbox tree viewer of capabilities
190
Label capabilityLabel = new Label(capComposite, SWT.LEFT);
191         capabilityLabel.setText(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_capabilities);
192         data = new GridData();
193         data.verticalAlignment = SWT.TOP;
194         capabilityLabel.setLayoutData(data);
195         capabilityLabel.setFont(font);
196
197         // Checkbox tree viewer of capabilities in selected categories
198
checkboxViewer = CheckboxTableViewer.newCheckList(capComposite,
199                 SWT.SINGLE | SWT.TOP | SWT.BORDER);
200         checkboxViewer.getTable().setLayoutData(
201                 new GridData(GridData.FILL_BOTH));
202         checkboxViewer.getTable().setFont(font);
203         checkboxViewer.setLabelProvider(new CapabilityLabelProvider());
204         checkboxViewer.setContentProvider(getContentProvider());
205         checkboxViewer.setInput(visibleCapabilities);
206
207         // Add a label to identify the text field of capability's description
208
Label descLabel = new Label(composite, SWT.LEFT);
209         descLabel.setText(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_description);
210         data = new GridData();
211         data.verticalAlignment = SWT.TOP;
212         data.horizontalSpan = 2;
213         descLabel.setLayoutData(data);
214         descLabel.setFont(font);
215
216         // Text field to display the capability's description
217
descriptionText = new Text(composite, SWT.WRAP | SWT.MULTI
218                 | SWT.V_SCROLL | SWT.BORDER);
219         descriptionText.setText(EMPTY_DESCRIPTION);
220         descriptionText.setEditable(false);
221         data = new GridData();
222         data.horizontalAlignment = GridData.FILL;
223         data.grabExcessHorizontalSpace = true;
224         data.horizontalSpan = 2;
225         descriptionText.setLayoutData(data);
226         descriptionText.setFont(font);
227
228         // Add a text field to explain grayed out items
229
Label grayLabel = new Label(composite, SWT.LEFT);
230         grayLabel.setText(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_grayItems);
231         data = new GridData();
232         data.verticalAlignment = SWT.TOP;
233         data.horizontalSpan = 2;
234         grayLabel.setLayoutData(data);
235         grayLabel.setFont(font);
236
237         // Setup initial context
238
populateDependents();
239         populateMemberships();
240
241         // Listen for selection changes to update the description field
242
checkboxViewer
243                 .addSelectionChangedListener(new ISelectionChangedListener() {
244                     public void selectionChanged(SelectionChangedEvent event) {
245                         updateDescription(event.getSelection());
246                     }
247                 });
248
249         // Properly handle user checking and unchecking project features
250
checkboxViewer.addCheckStateListener(new ICheckStateListener() {
251             public void checkStateChanged(CheckStateChangedEvent event) {
252                 Capability cap = (Capability) event.getElement();
253                 if (event.getChecked())
254                     handleCapabilityChecked(cap);
255                 else
256                     handleCapabilityUnchecked(cap);
257                 checkboxViewer.setSelection(new StructuredSelection(cap));
258             }
259         });
260
261         // Listen for category selection and update the list of capabilities
262
listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
263             public void selectionChanged(SelectionChangedEvent event) {
264                 if (event.getSelection() instanceof IStructuredSelection) {
265                     IStructuredSelection sel = (IStructuredSelection) event
266                             .getSelection();
267                     visibleCapabilities.clear();
268                     Iterator JavaDoc itr = sel.iterator();
269                     while (itr.hasNext()) {
270                         Category cat = (Category) itr.next();
271                         visibleCapabilities.addAll(cat.getElements());
272                     }
273                     Collections.sort(visibleCapabilities, capabilityComparator);
274                     checkboxViewer.refresh();
275                     itr = visibleCapabilities.iterator();
276                     while (itr.hasNext()) {
277                         Capability cap = (Capability) itr.next();
278                         if (hasDependency(cap))
279                             checkboxViewer.setGrayed(cap, true);
280                         if (checkedCapabilities.contains(cap))
281                             checkboxViewer.setChecked(cap, true);
282                     }
283                     updateDescription(checkboxViewer.getSelection());
284                 }
285             }
286         });
287
288         // initialize
289
if (initialCapabilities != null)
290             checkedCapabilities.addAll(Arrays.asList(initialCapabilities));
291         if (initialCategories != null)
292             listViewer.setSelection(new StructuredSelection(initialCategories));
293
294         return composite;
295     }
296
297     /**
298      * Marks the capability as being checked.
299      */

300     private void markCapabilityChecked(Capability target, Capability dependent) {
301         // Check the target capability
302
if (!checkedCapabilities.contains(target))
303             checkedCapabilities.add(target);
304         checkboxViewer.setChecked(target, true);
305
306         // Gray the target to show the user its required
307
// by another capability.
308
if (target != dependent)
309             checkboxViewer.setGrayed(target, true);
310
311         // Update the dependent map for the target capability
312
addDependency(target, dependent);
313
314         // Update the membership set for the target capability
315
String JavaDoc[] ids = registry.getMembershipSetIds(target);
316         for (int j = 0; j < ids.length; j++)
317             memberships.put(ids[j], target);
318     }
319
320     /**
321      * Marks the capability as being unchecked.
322      */

323     private void markCapabilityUnchecked(Capability target) {
324         // Uncheck the target capability
325
checkedCapabilities.remove(target);
326         checkboxViewer.setChecked(target, false);
327
328         // Ungray the target as there is no dependency on it
329
checkboxViewer.setGrayed(target, false);
330
331         // Remove the dependency entry
332
dependents.remove(target);
333
334         // Update the membership set for the target capability
335
String JavaDoc[] ids = registry.getMembershipSetIds(target);
336         for (int j = 0; j < ids.length; j++) {
337             if (memberships.get(ids[j]) == target)
338                 memberships.remove(ids[j]);
339         }
340     }
341
342     /**
343      * Returns the list of categories that have capabilities
344      * registered against it.
345      */

346     private ArrayList JavaDoc getAvailableCategories() {
347         ArrayList JavaDoc results = registry.getUsedCategories();
348         Collections.sort(results, categoryComparator);
349         if (registry.getMiscCategory() != null)
350             results.add(registry.getMiscCategory());
351         return results;
352     }
353
354     /**
355      * Return <code>true</code> if the user may have made changes
356      * to the capabilities of the project. Otherwise <code>false</code>
357      * if no changes were made.
358      *
359      * @return <code>true</true> when possible changes may have been made,
360      * <code>false</code> otherwise
361      */

362     public boolean getCapabilitiesModified() {
363         return modified;
364     }
365
366     /**
367      * Returns the content provider for the viewers
368      */

369     private IContentProvider getContentProvider() {
370         return new WorkbenchContentProvider() {
371             public Object JavaDoc[] getChildren(Object JavaDoc parentElement) {
372                 if (parentElement instanceof ArrayList JavaDoc)
373                     return ((ArrayList JavaDoc) parentElement).toArray();
374                 else
375                     return null;
376             }
377         };
378     }
379
380     /**
381      * The user has changed the project capability selection.
382      * Set the modified flag and clear the caches.
383      */

384     private void capabilitiesModified() {
385         modified = true;
386     }
387
388     /**
389      * Add a dependency between the target and dependent
390      * capabilities
391      */

392     private void addDependency(Capability target, Capability dependent) {
393         ArrayList JavaDoc descriptors = (ArrayList JavaDoc) dependents.get(target);
394         if (descriptors == null) {
395             descriptors = new ArrayList JavaDoc();
396             descriptors.add(dependent);
397             dependents.put(target, descriptors);
398         } else if (!descriptors.contains(dependent)) {
399             descriptors.add(dependent);
400         }
401     }
402
403     /**
404      * Returns true if the capability has any
405      * dependencies on it.
406      */

407     private boolean hasDependency(Capability capability) {
408         ArrayList JavaDoc descriptors = (ArrayList JavaDoc) dependents.get(capability);
409         if (descriptors == null)
410             return false;
411         if (descriptors.size() == 1 && descriptors.get(0) == capability)
412             return false;
413         return true;
414     }
415
416     /**
417      * Returns whether the category is considered disabled
418      */

419     private boolean isDisabledCapability(Capability cap) {
420         if (disabledCaps == null) {
421             if (disabledCapabilities == null)
422                 disabledCaps = new ArrayList JavaDoc(0);
423             else
424                 disabledCaps = Arrays.asList(disabledCapabilities);
425         }
426         return disabledCaps.contains(cap);
427     }
428
429     /**
430      * Populate the dependents map based on the
431      * current set of capabilities.
432      */

433     private void populateDependents() {
434         if (initialCapabilities == null)
435             return;
436
437         LinkedList JavaDoc capabilities = new LinkedList JavaDoc();
438         capabilities.addAll(Arrays.asList(initialCapabilities));
439
440         while (!capabilities.isEmpty()) {
441             // Retrieve the target capability
442
Capability target;
443             target = (Capability) capabilities.removeFirst();
444             // Add the capability as a dependent of itself.
445
// It will indicate to the uncheck handler to not uncheck this
446
// capability automatically even if a another capability which
447
// depended on it is unchecked.
448
addDependency(target, target);
449
450             if (registry.hasPrerequisites(target)) {
451                 // Retrieve the prerequisite capabilities...
452
String JavaDoc[] prereqIds = registry.getPrerequisiteIds(target);
453                 Capability[] prereqCapabilities;
454                 prereqCapabilities = registry.findCapabilities(prereqIds);
455                 // For each prerequisite capability...
456
for (int i = 0; i < prereqCapabilities.length; i++) {
457                     // Update the dependent map for the prerequisite capability
458
addDependency(prereqCapabilities[i], target);
459                     // Recursive if prerequisite capability also has prerequisites
460
if (registry.hasPrerequisites(prereqCapabilities[i]))
461                         capabilities.addLast(prereqCapabilities[i]);
462                 }
463             }
464         }
465     }
466
467     /**
468      * Populate the memberships map based on the
469      * current set of capabilities.
470      */

471     private void populateMemberships() {
472         if (initialCapabilities == null)
473             return;
474
475         Iterator JavaDoc itr = (Arrays.asList(initialCapabilities)).iterator();
476         while (itr.hasNext()) {
477             Capability cap = (Capability) itr.next();
478             String JavaDoc[] ids = registry.getMembershipSetIds(cap);
479             for (int j = 0; j < ids.length; j++) {
480                 memberships.put(ids[j], cap);
481             }
482         }
483     }
484
485     /**
486      * Handle the case of a capability being checked
487      * by ensuring the action is allowed and the prerequisite
488      * capabilities are also checked.
489      */

490     private void handleCapabilityChecked(Capability capability) {
491         // Cannot allow a disabled capability to be checked
492
if (isDisabledCapability(capability)) {
493             MessageDialog
494                     .openWarning(
495                             checkboxViewer.getControl().getShell(),
496                             IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
497                             NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_disabledCapability, capability.getName()));
498             checkboxViewer.setChecked(capability, false);
499             return;
500         }
501
502         // Cannot allow an invalid capability to be checked
503
if (!capability.isValid()) {
504             MessageDialog
505                     .openWarning(
506                             checkboxViewer.getControl().getShell(),
507                             IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
508                             NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_invalidCapability, capability.getName()));
509             checkboxViewer.setChecked(capability, false);
510             return;
511         }
512
513         // Is there a membership set problem...
514
String JavaDoc[] ids = registry.getMembershipSetIds(capability);
515         for (int i = 0; i < ids.length; i++) {
516             Capability member = (Capability) memberships.get(ids[i]);
517             if (member != null && member != capability) {
518                 MessageDialog
519                         .openWarning(
520                                 checkboxViewer.getControl().getShell(),
521                                 IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
522                                 NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_membershipConflict, capability.getName(), member.getName()));
523                 checkboxViewer.setChecked(capability, false);
524                 return;
525             }
526         }
527
528         // Handle prerequisite by auto-checking them if possible
529
if (registry.hasPrerequisites(capability)) {
530             // Check for any prerequisite problems...
531
// Retrieve all the prerequisite capabilities, including
532
// any prerequisite of the prerequisites!
533
LinkedList JavaDoc capabilities = new LinkedList JavaDoc();
534             capabilities.addLast(capability);
535             while (!capabilities.isEmpty()) {
536                 Capability target;
537                 target = (Capability) capabilities.removeFirst();
538                 // Retrieve the capability's immediate prerequisites
539
String JavaDoc[] prereqIds = registry.getPrerequisiteIds(target);
540                 Capability[] prereqCapabilities;
541                 prereqCapabilities = registry.findCapabilities(prereqIds);
542                 for (int i = 0; i < prereqCapabilities.length; i++) {
543                     // If the prerequisite is missing, warn the user and
544
// do not allow the check to proceed.
545
if (prereqCapabilities[i] == null
546                             || isDisabledCapability(prereqCapabilities[i])
547                             || !prereqCapabilities[i].isValid()) {
548                         MessageDialog
549                                 .openWarning(
550                                         checkboxViewer.getControl().getShell(),
551                                         IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
552                                         NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_missingPrereqs, capability.getName(), prereqIds[i]));
553                         checkboxViewer.setChecked(capability, false);
554                         return;
555                     }
556                     // If there is a membership problem, warn the user and
557
// do not allow the check to proceed
558
ids = registry.getMembershipSetIds(prereqCapabilities[i]);
559                     for (int j = 0; j < ids.length; j++) {
560                         Capability member = (Capability) memberships
561                                 .get(ids[j]);
562                         if (member != null && member != prereqCapabilities[i]) {
563                             MessageDialog
564                                     .openWarning(
565                                             checkboxViewer.getControl()
566                                                     .getShell(),
567                                             IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
568                                             NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_membershipPrereqConflict, new Object JavaDoc[] {capability.getName(), prereqCapabilities[i].getName(), member.getName()}));
569                             checkboxViewer.setChecked(capability, false);
570                             return;
571                         }
572                     }
573                     // If the prerequisite capability has prerequisites
574
// also, then add it to be processed.
575
if (registry.hasPrerequisites(prereqCapabilities[i]))
576                         capabilities.addLast(prereqCapabilities[i]);
577                 }
578             }
579
580             // Auto-check all prerequisite capabilities
581
capabilities = new LinkedList JavaDoc();
582             capabilities.addLast(capability);
583             // For each capability that has prerequisites...
584
while (!capabilities.isEmpty()) {
585                 Capability target;
586                 target = (Capability) capabilities.removeFirst();
587                 // Retrieve the prerequisite capabilities...
588
String JavaDoc[] prereqIds = registry.getPrerequisiteIds(target);
589                 Capability[] prereqCapabilities;
590                 prereqCapabilities = registry.findCapabilities(prereqIds);
591                 // For each prerequisite capability...
592
for (int i = 0; i < prereqCapabilities.length; i++) {
593                     // Mark it as being checked
594
markCapabilityChecked(prereqCapabilities[i], target);
595                     // Recursive if prerequisite capability also has prerequisites
596
if (registry.hasPrerequisites(prereqCapabilities[i]))
597                         capabilities.addLast(prereqCapabilities[i]);
598                 }
599             }
600         }
601
602         // Mark the capability as checked. Adds itself as a
603
// dependent - this will indicate to the uncheck handler
604
// to not uncheck this capability automatically even if
605
// another capability which depends on it is unchecked.
606
markCapabilityChecked(capability, capability);
607
608         // Notify those interested
609
capabilitiesModified();
610         notifyCheckStateListner();
611     }
612
613     /**
614      * Handle the case of a capability being unchecked
615      * by ensuring the action is allowed.
616      */

617     private void handleCapabilityUnchecked(Capability capability) {
618         ArrayList JavaDoc descriptors = (ArrayList JavaDoc) dependents.get(capability);
619
620         // Note, there is no need to handle the case where descriptors size
621
// is zero because it cannot happen. For this method to be called, the
622
// item must have been checked previously. If it was checked by the user,
623
// then the item itself would be a dependent. If the item was checked
624
// because it was required by another capability, then that other capability
625
// would be a dependent.
626

627         if (descriptors.size() == 1 && descriptors.get(0) == capability) {
628             // If the only dependent is itself, then its ok to uncheck
629
capabilitiesModified();
630             markCapabilityUnchecked(capability);
631
632             // Remove this capability as a dependent on its prerequisite
633
// capabilities. Recursive if a prerequisite capability
634
// no longer has any dependents.
635
if (registry.hasPrerequisites(capability)) {
636                 LinkedList JavaDoc capabilities = new LinkedList JavaDoc();
637                 capabilities.addLast(capability);
638                 // For each capability that has prerequisite capabilities
639
while (!capabilities.isEmpty()) {
640                     Capability target;
641                     target = (Capability) capabilities.removeFirst();
642                     // Retrieve the prerequisite capabilities...
643
String JavaDoc[] prereqIds = registry.getPrerequisiteIds(target);
644                     Capability[] prereqCapabilities;
645                     prereqCapabilities = registry.findCapabilities(prereqIds);
646                     // For each prerequisite capability...
647
for (int i = 0; i < prereqCapabilities.length; i++) {
648                         // Retrieve the list of dependents on the prerequisite capability...
649
Capability prereqCap = prereqCapabilities[i];
650                         ArrayList JavaDoc prereqDependents = (ArrayList JavaDoc) dependents
651                                 .get(prereqCap);
652                         // Remove the dependent target capability...
653
prereqDependents.remove(target);
654                         if (prereqDependents.isEmpty()) {
655                             // Unchecked the prerequisite capability
656
markCapabilityUnchecked(prereqCap);
657                             // Recursive if prerequisite capability also has
658
// prerequisite capabilities
659
if (registry.hasPrerequisites(prereqCap))
660                                 capabilities.addLast(prereqCap);
661                         } else if (prereqDependents.size() == 1
662                                 && prereqDependents.get(0) == prereqCap) {
663                             // Only dependent is itself so ungray the item to let the
664
// user know no other capability is dependent on it
665
checkboxViewer.setGrayed(prereqCap, false);
666                         }
667                     }
668                 }
669             }
670
671             // Notify those interested
672
notifyCheckStateListner();
673         } else {
674             // At least one other capability depends on it being checked
675
// so force it to remain checked and warn the user.
676
checkboxViewer.setChecked(capability, true);
677             // Get a copy and remove the target capability
678
ArrayList JavaDoc descCopy = (ArrayList JavaDoc) descriptors.clone();
679             descCopy.remove(capability);
680             // Show the prereq problem to the user
681
if (descCopy.size() == 1) {
682                 Capability cap = (Capability) descCopy.get(0);
683                 MessageDialog
684                         .openWarning(
685                                 checkboxViewer.getControl().getShell(),
686                                 IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
687                                 NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_requiredPrereq, capability.getName(), cap.getName()));
688             } else {
689                 StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
690                 Iterator JavaDoc itr = descCopy.iterator();
691                 while (itr.hasNext()) {
692                     Capability cap = (Capability) itr.next();
693                     msg.append("\n "); //$NON-NLS-1$
694
msg.append(cap.getName());
695                 }
696                 MessageDialog
697                         .openWarning(
698                                 checkboxViewer.getControl().getShell(),
699                                 IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_errorTitle,
700                                 NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_requiredPrereqs, capability.getName(), msg));
701             }
702         }
703     }
704
705     /**
706      * Returns the collection of capabilities selected
707      * by the user. The collection is not in prerequisite
708      * order.
709      *
710      * @return array of selected capabilities
711      */

712     public Capability[] getSelectedCapabilities() {
713         Capability[] capabilities = new Capability[checkedCapabilities.size()];
714         checkedCapabilities.toArray(capabilities);
715         return capabilities;
716     }
717
718     /**
719      * Return the current listener interested when the check
720      * state of a capability actually changes.
721      *
722      * @return Returns a ICheckStateListener
723      */

724     public ICheckStateListener getCheckStateListener() {
725         return checkStateListener;
726     }
727
728     /**
729      * Set the current listener interested when the check
730      * state of a capability actually changes.
731      *
732      * @param checkStateListener The checkStateListener to set
733      */

734     public void setCheckStateListener(ICheckStateListener checkStateListener) {
735         this.checkStateListener = checkStateListener;
736     }
737
738     /**
739      * Notify the check state listener that a capability
740      * check state has changed. The event past will
741      * always be <code>null</code> as it could be
742      * triggered by code instead of user input.
743      */

744     private void notifyCheckStateListner() {
745         if (checkStateListener != null)
746             checkStateListener.checkStateChanged(null);
747     }
748
749     /**
750      * Updates the description field for the selected capability
751      */

752     private void updateDescription(ISelection selection) {
753         String JavaDoc text = EMPTY_DESCRIPTION;
754         if (selection instanceof IStructuredSelection) {
755             IStructuredSelection sel = (IStructuredSelection) selection;
756             Capability cap = (Capability) sel.getFirstElement();
757             if (cap != null)
758                 text = cap.getDescription();
759         }
760         descriptionText.setText(text);
761     }
762
763     class CapabilityLabelProvider extends LabelProvider {
764         private Map JavaDoc imageTable;
765
766         public void dispose() {
767             if (imageTable != null) {
768                 Iterator JavaDoc itr = imageTable.values().iterator();
769                 while (itr.hasNext())
770                     ((Image) itr.next()).dispose();
771                 imageTable = null;
772             }
773         }
774
775         public Image getImage(Object JavaDoc element) {
776             ImageDescriptor descriptor = ((Capability) element)
777                     .getIconDescriptor();
778             if (descriptor == null)
779                 return null;
780
781             //obtain the cached image corresponding to the descriptor
782
if (imageTable == null) {
783                 imageTable = new Hashtable JavaDoc(40);
784             }
785             Image image = (Image) imageTable.get(descriptor);
786             if (image == null) {
787                 image = descriptor.createImage();
788                 imageTable.put(descriptor, image);
789             }
790             return image;
791         }
792
793         public String JavaDoc getText(Object JavaDoc element) {
794             Capability cap = (Capability) element;
795             String JavaDoc text = cap.getName();
796             if (isDisabledCapability(cap))
797                 text = NLS.bind(IDEWorkbenchMessages.ProjectCapabilitySelectionGroup_disabledLabel, text );
798             return text;
799         }
800     }
801 }
802
803
Popular Tags