/* (non-Javadoc)
  * @see org.eclipse.swt.widgets.Control#setEnabled(boolean)
  */
 public void setEnabled(boolean enabled) {
   fTree.getControl().setEnabled(enabled);
   if (enabled) {
     updateButtons();
   } else {
     fSelectButton.setEnabled(false);
     fSelectAllButton.setEnabled(false);
     fDeselectButton.setEnabled(false);
     fDeselectAllButton.setEnabled(false);
     fSelectRequiredButton.setEnabled(false);
     fCountLabel.setText(""); // $NON-NLS-1$
   }
   fModeLabel.setEnabled(enabled);
   fPluginModeButton.setEnabled(enabled);
   fFeaureModeButton.setEnabled(enabled);
   fShowLabel.setEnabled(enabled);
   fShowPluginsButton.setEnabled(enabled);
   fShowSourceButton.setEnabled(enabled);
   boolean isPluginMode = !fFeaureModeButton.getSelection();
   fGroupLabel.setEnabled(enabled && isPluginMode);
   if (fGroupCombo != null) {
     fGroupCombo.setEnabled(enabled && isPluginMode);
   } else {
     fGroupComboPart.setEnabled(enabled && isPluginMode);
   }
 }
 private void handleGroupChange() {
   int index;
   if (fGroupCombo != null) {
     index = fGroupCombo.getSelectionIndex();
   } else {
     index = fGroupComboPart.getSelectionIndex();
   }
   if (index != fGrouping) {
     // Refresh tree
     fGrouping = index;
     fTree.getControl().setRedraw(false);
     fTree.refresh(false);
     fTree.expandAll();
     updateCheckState();
     updateButtons();
     fTree.getControl().setRedraw(true);
   }
 }
 private void updateCheckState() {
   List result = new ArrayList();
   // Checked error statuses
   if (fMissing != null) {
     result.addAll(fMissing);
   }
   if (fFeaureModeButton.getSelection()) {
     // Checked features and plugins
     result.addAll(((TargetDefinition) fTargetDefinition).getFeaturesAndBundles());
   } else {
     // Bundles with errors are already included from fMissing, do not add twice
     IResolvedBundle[] bundles = fTargetDefinition.getBundles();
     for (int i = 0; i < bundles.length; i++) {
       if (bundles[i].getStatus().isOK()) {
         result.add(bundles[i]);
       }
     }
   }
   fTree.setCheckedElements(result.toArray());
 }
  /**
   * Set the container to display in the tree or <code>null</code> to disable the tree
   *
   * @param input bundle container or <code>null</code>
   */
  public void setInput(ITargetDefinition input) {
    fTargetDefinition = input;

    // Update the cached data
    fFileBundleMapping = null;
    fAllBundles.clear();

    if (input == null || !input.isResolved()) {
      fTree.setInput(Messages.TargetContentsGroup_10);
      setEnabled(false);
      return;
    }

    IResolvedBundle[] allResolvedBundles = input.getAllBundles();
    if (allResolvedBundles == null || allResolvedBundles.length == 0) {
      fTree.setInput(Messages.TargetContentsGroup_11);
      setEnabled(false);
      return;
    }

    for (int i = 0; i < allResolvedBundles.length; i++) {
      fAllBundles.add(allResolvedBundles[i]);
    }

    boolean isFeatureMode =
        ((TargetDefinition) fTargetDefinition).getUIMode() == TargetDefinition.MODE_FEATURE;
    fFeaureModeButton.setSelection(isFeatureMode);
    fPluginModeButton.setSelection(!isFeatureMode);
    fGroupLabel.setEnabled(!isFeatureMode);

    fTree.getControl().setRedraw(false);
    fTree.setInput(fTargetDefinition);
    fTree.expandAll();
    updateCheckState();
    updateButtons();
    setEnabled(true);
    fTree.getControl().setRedraw(true);
  }
  private void updateButtons() {
    if (fTargetDefinition != null && !fTree.getSelection().isEmpty()) {
      Object[] selection = ((IStructuredSelection) fTree.getSelection()).toArray();
      boolean hasResolveBundle = false;
      boolean hasParent = false;
      boolean allSelected = true;
      boolean noneSelected = true;
      for (int i = 0; i < selection.length; i++) {
        if (!hasResolveBundle || !hasParent) {
          if (selection[i] instanceof IResolvedBundle) {
            hasResolveBundle = true;
          } else {
            hasParent = true;
          }
        }
        boolean checked = fTree.getChecked(selection[i]);
        if (checked) {
          noneSelected = false;
        } else {
          allSelected = false;
        }
      }
      // Selection is available if not everything is already selected and not both a parent and
      // child item are selected
      fSelectButton.setEnabled(!allSelected && !(hasResolveBundle && hasParent));
      fDeselectButton.setEnabled(!noneSelected && !(hasResolveBundle && hasParent));
    } else {
      fSelectButton.setEnabled(false);
      fDeselectButton.setEnabled(false);
    }

    int total = fAllBundles.size();
    if (fFeaureModeButton.getSelection()) {
      if (fTargetDefinition == null) {
        total = 0;
      } else {
        total = fTargetDefinition.getAllFeatures().length;
        total += ((TargetDefinition) fTargetDefinition).getOtherBundles().length;
      }
    }
    if (fMissing != null) {
      total += fMissing.size();
    }

    fSelectAllButton.setEnabled(fTargetDefinition != null && fTree.getCheckedLeafCount() != total);
    fDeselectAllButton.setEnabled(fTargetDefinition != null && fTree.getCheckedLeafCount() != 0);
    fSelectRequiredButton.setEnabled(
        fTargetDefinition != null
            && fTree.getCheckedLeafCount() > 0
            && fTree.getCheckedLeafCount() != total);

    if (fTargetDefinition != null) {
      fCountLabel.setText(
          MessageFormat.format(
              Messages.TargetContentsGroup_9,
              new String[] {
                Integer.toString(fTree.getCheckedLeafCount()), Integer.toString(total)
              }));
    } else {
      fCountLabel.setText(""); // $NON-NLS-1$
    }
  }
  /**
   * Uses the target state to determine all bundles required by the currently checked bundles and
   * returns them so they can be checked in the tree.
   *
   * @param allBundles list of all bundles to search requirements in
   * @param checkedBundles list of bundles to get requirements for
   * @return list of resolved bundles from the collection to be checked
   */
  private Object[] getRequiredPlugins(final Collection allBundles, final Object[] checkedBundles) {
    final Set dependencies = new HashSet();
    IRunnableWithProgress op =
        new IRunnableWithProgress() {
          public void run(IProgressMonitor monitor) {
            try {
              monitor.beginTask(Messages.TargetContentsGroup_5, 150);

              // Get all the bundle locations
              List allLocations = new ArrayList(allBundles.size());
              for (Iterator iterator = allBundles.iterator(); iterator.hasNext(); ) {
                IResolvedBundle current = (IResolvedBundle) iterator.next();
                try {
                  // Some bundles, such as those with errors, may not have locations
                  URI location = current.getBundleInfo().getLocation();
                  if (location != null) {
                    allLocations.add(new File(location).toURL());
                  }
                } catch (MalformedURLException e) {
                  PDEPlugin.log(e);
                  monitor.setCanceled(true);
                  return;
                }
              }
              if (monitor.isCanceled()) {
                return;
              }
              monitor.worked(20);

              // Create a PDE State containing all of the target bundles
              PDEState state =
                  new PDEState(
                      (URL[]) allLocations.toArray(new URL[allLocations.size()]),
                      true,
                      new SubProgressMonitor(monitor, 50));
              if (monitor.isCanceled()) {
                return;
              }

              // Figure out which of the models have been checked
              IPluginModelBase[] models = state.getTargetModels();
              List checkedModels = new ArrayList(checkedBundles.length);
              for (int i = 0; i < checkedBundles.length; i++) {
                if (checkedBundles[i] instanceof IResolvedBundle) {
                  BundleInfo bundle = ((IResolvedBundle) checkedBundles[i]).getBundleInfo();
                  for (int j = 0; j < models.length; j++) {
                    if (models[j]
                            .getBundleDescription()
                            .getSymbolicName()
                            .equals(bundle.getSymbolicName())
                        && models[j]
                            .getBundleDescription()
                            .getVersion()
                            .toString()
                            .equals(bundle.getVersion())) {
                      checkedModels.add(models[j]);
                      break;
                    }
                  }
                }
              }
              monitor.worked(20);
              if (monitor.isCanceled()) {
                return;
              }

              // Get implicit dependencies as a list of strings
              // This is wasteful since the dependency calculation puts them back into BundleInfos
              NameVersionDescriptor[] implicitDependencies =
                  fTargetDefinition.getImplicitDependencies();
              List implicitIDs = new ArrayList();
              if (implicitDependencies != null) {
                for (int i = 0; i < implicitDependencies.length; i++) {
                  implicitIDs.add(implicitDependencies[i].getId());
                }
              }
              monitor.worked(10);

              // Get all dependency bundles
              // exclude "org.eclipse.ui.workbench.compatibility" - it is only needed for pre-3.0
              // bundles
              dependencies.addAll(
                  DependencyManager.getDependencies(
                      checkedModels.toArray(),
                      (String[]) implicitIDs.toArray(new String[implicitIDs.size()]),
                      state.getState(),
                      new String[] {"org.eclipse.ui.workbench.compatibility"})); // $NON-NLS-1$
              monitor.worked(50);

            } finally {
              monitor.done();
            }
          }
        };
    try {
      // Calculate the dependencies
      new ProgressMonitorDialog(fTree.getControl().getShell()).run(true, true, op);

      // We want to check the dependents, the source of the dependents, and the source of the
      // originally checked
      Set checkedNames = new HashSet(checkedBundles.length);
      for (int i = 0; i < checkedBundles.length; i++) {
        if (checkedBundles[i] instanceof IResolvedBundle) {
          checkedNames.add(((IResolvedBundle) checkedBundles[i]).getBundleInfo().getSymbolicName());
        }
      }

      List toCheck = new ArrayList();
      for (Iterator iterator = fAllBundles.iterator(); iterator.hasNext(); ) {
        IResolvedBundle bundle = (IResolvedBundle) iterator.next();
        if (bundle.isSourceBundle()) {
          String name = bundle.getSourceTarget().getSymbolicName();
          if (name != null && (dependencies.contains(name) || checkedNames.contains(name))) {
            toCheck.add(bundle);
          }
        } else if (dependencies.contains(bundle.getBundleInfo().getSymbolicName())) {
          toCheck.add(bundle);
        }
      }
      return toCheck.toArray();
    } catch (InvocationTargetException e) {
      PDEPlugin.log(e);
    } catch (InterruptedException e) {
    }

    return new Object[0];
  }
  /**
   * Creates the tree in this group
   *
   * @param parent parent composite
   * @param style toolkit for form style or <code>null</code> for dialog style
   */
  private TreeViewer createTree(Composite parent, FormToolkit toolkit) {
    FilteredCheckboxTree tree = new FilteredCheckboxTree(parent, toolkit);
    tree.setLayoutData(new GridData(GridData.FILL_BOTH));
    tree.getPatternFilter().setIncludeLeadingWildcard(true);
    tree.getFilterControl().setFont(parent.getFont());

    fTree = tree.getCheckboxTreeViewer();
    ((GridData) fTree.getControl().getLayoutData()).heightHint = 300;
    fTree.getControl().setFont(parent.getFont());
    fTree.setUseHashlookup(true);
    fTree.setContentProvider(new TreeContentProvider());
    fTree.setLabelProvider(new StyledBundleLabelProvider(true, false));
    fTree.addDoubleClickListener(
        new IDoubleClickListener() {
          public void doubleClick(DoubleClickEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            Object first = selection.getFirstElement();
            fTree.setChecked(first, !fTree.getChecked(first));
            saveIncludedBundleState();
            contentChanged();
            updateButtons();
            fTree.update(
                fTargetDefinition.getBundleContainers(),
                new String[] {IBasicPropertyConstants.P_TEXT});
          }
        });
    fTree.addCheckStateListener(
        new ICheckStateListener() {
          public void checkStateChanged(CheckStateChangedEvent event) {
            saveIncludedBundleState();
            contentChanged();
            updateButtons();
            fTree.update(
                fTargetDefinition.getBundleContainers(),
                new String[] {IBasicPropertyConstants.P_TEXT});
          }
        });
    fTree.addSelectionChangedListener(
        new ISelectionChangedListener() {
          public void selectionChanged(SelectionChangedEvent event) {
            updateButtons();
          }
        });
    fTree.setSorter(
        new ViewerSorter() {
          public int compare(Viewer viewer, Object e1, Object e2) {
            if (fFeaureModeButton.getSelection()) {
              if (e1 == OTHER_CATEGORY) {
                return 1;
              }
              if (e2 == OTHER_CATEGORY) {
                return -1;
              }
            }
            if (e1 instanceof IResolvedBundle && !(e2 instanceof IResolvedBundle)) {
              return -1;
            }
            if (e2 instanceof IResolvedBundle && !(e1 instanceof IResolvedBundle)) {
              return 1;
            }
            if (e1 instanceof IResolvedBundle && e2 instanceof IResolvedBundle) {
              IStatus status1 = ((IResolvedBundle) e1).getStatus();
              IStatus status2 = ((IResolvedBundle) e2).getStatus();
              if (!status1.isOK() && status2.isOK()) {
                return -1;
              }
              if (status1.isOK() && !status2.isOK()) {
                return 1;
              }
            }
            return super.compare(viewer, e1, e2);
          }
        });

    fMenuManager = new MenuManager();
    fMenuManager.add(
        new Action(
            Messages.TargetContentsGroup_collapseAll,
            PlatformUI.getWorkbench()
                .getSharedImages()
                .getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL)) {
          public void run() {
            fTree.collapseAll();
          }
        });
    Menu contextMenu = fMenuManager.createContextMenu(tree);
    tree.setMenu(contextMenu);

    return fTree;
  }
  public void saveIncludedBundleState() {
    if (fFeaureModeButton.getSelection()) {
      // Create a list of checked bundle infos
      List included = new ArrayList();
      int missingCount = 0;
      Object[] checked = fTree.getCheckedLeafElements();
      for (int i = 0; i < checked.length; i++) {
        if (checked[i] instanceof IFeatureModel) {
          included.add(
              new NameVersionDescriptor(
                  ((IFeatureModel) checked[i]).getFeature().getId(),
                  null,
                  NameVersionDescriptor.TYPE_FEATURE));
        }
        if (checked[i] instanceof IResolvedBundle) {
          // Missing features are included as IResolvedBundles, save them as features instead
          if (((IResolvedBundle) checked[i]).getStatus().getCode()
              == IResolvedBundle.STATUS_PLUGIN_DOES_NOT_EXIST) {
            included.add(
                new NameVersionDescriptor(
                    ((IResolvedBundle) checked[i]).getBundleInfo().getSymbolicName(),
                    null,
                    NameVersionDescriptor.TYPE_PLUGIN));
            missingCount++;
          } else if (((IResolvedBundle) checked[i]).getStatus().getCode()
              == IResolvedBundle.STATUS_FEATURE_DOES_NOT_EXIST) {
            included.add(
                new NameVersionDescriptor(
                    ((IResolvedBundle) checked[i]).getBundleInfo().getSymbolicName(),
                    null,
                    NameVersionDescriptor.TYPE_FEATURE));
            missingCount++;
          } else {
            included.add(
                new NameVersionDescriptor(
                    ((IResolvedBundle) checked[i]).getBundleInfo().getSymbolicName(), null));
          }
        }
      }

      if (included.size() == 0) {
        fTargetDefinition.setIncluded(new NameVersionDescriptor[0]);
      } else if (included.size() == 0
          || included.size() - missingCount
              == fTargetDefinition.getAllFeatures().length
                  + ((TargetDefinition) fTargetDefinition).getOtherBundles().length) {
        fTargetDefinition.setIncluded(null);
      } else {
        fTargetDefinition.setIncluded(
            (NameVersionDescriptor[]) included.toArray(new NameVersionDescriptor[included.size()]));
      }
    } else {
      // Figure out if there are multiple bundles sharing the same id
      Set multi = new HashSet(); // BSNs of bundles with multiple versions available
      Set all = new HashSet();
      for (Iterator iterator = fAllBundles.iterator(); iterator.hasNext(); ) {
        IResolvedBundle rb = (IResolvedBundle) iterator.next();
        if (!all.add(rb.getBundleInfo().getSymbolicName())) {
          multi.add(rb.getBundleInfo().getSymbolicName());
        }
      }

      // Create a list of checked bundle infos
      List included = new ArrayList();
      Object[] checked = fTree.getCheckedLeafElements();
      for (int i = 0; i < checked.length; i++) {
        if (checked[i] instanceof IResolvedBundle) {
          // Create the bundle info object
          String bsn = ((IResolvedBundle) checked[i]).getBundleInfo().getSymbolicName();
          NameVersionDescriptor info = null;
          if (multi.contains(bsn)) {
            // include version info
            info =
                new NameVersionDescriptor(
                    bsn, ((IResolvedBundle) checked[i]).getBundleInfo().getVersion());
          } else {
            // don't store version info
            info = new NameVersionDescriptor(bsn, null);
          }
          included.add(info);
        }
      }

      if (included.size() == 0) {
        fTargetDefinition.setIncluded(new NameVersionDescriptor[0]);
      } else if (included.size() == fAllBundles.size() + fMissing.size()) {
        fTargetDefinition.setIncluded(null);
      } else {
        fTargetDefinition.setIncluded(
            (NameVersionDescriptor[]) included.toArray(new NameVersionDescriptor[included.size()]));
      }
    }
  }
 /**
  * This method clears any current target information and puts "Resolve Cancelled" into the tree.
  * Setting the input to null results in "Resolving..." to be put into the table which may not be
  * accurate.
  */
 public void setCancelled() {
   fTargetDefinition = null;
   fTree.setInput(Messages.TargetContentsGroup_resolveCancelled);
   setEnabled(false);
 }