code: /*--------------------------------------------------------------*
    Copyright (C) 2006-2015 OpenSim Ltd.
  
    This file is distributed WITHOUT ANY WARRANTY. See the file
    'License' for details on this and other legal matters.
  *--------------------------------------------------------------*/
  
  package org.omnetpp.ned.editor.graph.actions;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import org.eclipse.core.resources.IProject;
  import org.eclipse.gef.ui.actions.WorkbenchPartAction;
  import org.eclipse.jface.viewers.CheckStateChangedEvent;
  import org.eclipse.jface.viewers.ICheckStateListener;
  import org.eclipse.jface.viewers.IStructuredSelection;
  import org.eclipse.jface.viewers.LabelProvider;
  import org.eclipse.jface.viewers.StructuredSelection;
  import org.eclipse.jface.window.Window;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.events.SelectionListener;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog;
  import org.eclipse.ui.part.FileEditorInput;
  import org.omnetpp.common.ui.GenericTreeContentProvider;
  import org.omnetpp.common.ui.GenericTreeLabelProvider;
  import org.omnetpp.common.ui.GenericTreeNode;
  import org.omnetpp.common.util.StringUtils;
  import org.omnetpp.ned.core.INedResources;
  import org.omnetpp.ned.core.NedResourcesPlugin;
  import org.omnetpp.ned.editor.graph.GraphicalNedEditor;
  import org.omnetpp.ned.editor.graph.misc.PaletteManager;
  import org.omnetpp.ned.model.interfaces.INedTypeInfo;
  
  
  /**
   * Dialog for filtering the palette contents by packages
   *
   * @author Andras
   */
  public class PaletteFilterAction extends WorkbenchPartAction {
  
      public PaletteFilterAction(GraphicalNedEditor part) {
          super(part);
          setText("Select &packages...");
          setId("PaletteFilter");
          setToolTipText("Select NED packages for the palette");
      }
  
      @Override
      protected boolean calculateEnabled() {
          return true;
      }
  
      @Override
      public void run() {
          GraphicalNedEditor editor = (GraphicalNedEditor)getWorkbenchPart();
  
          // collect the list of (non-empty) packages, and how many NED types they contain
          IProject project = ((FileEditorInput)editor.getEditorInput()).getFile().getProject();
          INedResources res = NedResourcesPlugin.getNedResources();
          final Map<String,Integer> packages = new LinkedHashMap<String,Integer>();  // (package,count)
          List<String> orderedQNames = new ArrayList<String>(res.getToplevelNedTypeQNames(project));
          Collections.sort(orderedQNames);
          for (String qname : orderedQNames) {
              INedTypeInfo nedType = res.getToplevelNedType(qname, project);
              String packageName = StringUtils.fallback(nedType.getPackageName(), "(default)");
              if (!packages.containsKey(packageName))
                  packages.put(packageName, 1);
              else
                  packages.put(packageName, packages.get(packageName) + 1);
          }
  
          // build a tree (note: tree nodes will be package name prefixes like
          // "inet", "inet.transport", "inet.transport.tcp" -- although we'll
          // only display their last segment in the tree).
          PaletteManager paletteManager = editor.getPaletteManager();
          Set<String> excludedPackages = paletteManager.getExcludedPackages();
  
          Set<GenericTreeNode> allNodes = new HashSet<GenericTreeNode>();
          Set<GenericTreeNode> initialSelectedNodes = new HashSet<GenericTreeNode>();
          GenericTreeNode root = new GenericTreeNode("root");
          for (String packageName : packages.keySet()) {
              GenericTreeNode node = root;
              String packageNamePrefix = null;
              for (String segment : packageName.split("\\.")) {
                  if (packageNamePrefix == null)
                      packageNamePrefix = segment;
                  else
                      packageNamePrefix += "." + segment;
                  node = getOrCreateChild(node, packageNamePrefix);
                  allNodes.add(node);
                  if (!excludedPackages.contains(packageName))
                      initialSelectedNodes.add(node);
              }
          }
  
          // display tree dialog
          CheckedTreeSelectionDialog dlg = new CheckedTreeSelectionDialog(
                  null,
                  new GenericTreeLabelProvider(new LabelProvider() {
                      @Override
                      public String getText(Object element) {
                          String packageName = (String)element;
                          int count = packages.containsKey(packageName) ? packages.get(packageName) : 0;
                          String displayName = StringUtils.isEmpty(packageName) ? "(default)" : packageName.replaceFirst("^.*\\.", "");
                          return displayName + " (" + count + ")";
                      }
                  }),
                  new GenericTreeContentProvider())
          {
              @Override
              protected Control createDialogArea(Composite parent) {
                  Control composite = super.createDialogArea(parent);
                  getTreeViewer().expandToLevel(2);
                  getTreeViewer().addCheckStateListener(new ICheckStateListener() {
                      public void checkStateChanged(CheckStateChangedEvent event) {
                          getTreeViewer().setSelection(new StructuredSelection(event.getElement()));
                          getTreeViewer().setExpandedState(event.getElement(), true);
                      }
                  });
                  getTreeViewer().getTree().addSelectionListener(new SelectionAdapter() {
                      @Override
                      public void widgetDefaultSelected(SelectionEvent e) {
                          Object element = e.item.getData();
                          //getTreeViewer().expandToLevel(element, 10);
                          getTreeViewer().setSubtreeChecked(element, !getTreeViewer().getChecked(element));
                      }
                  });
                  return composite;
              }
              @Override
              protected Composite createSelectionButtons(Composite composite) {
                  Composite buttonComposite = super.createSelectionButtons(composite);
                  final Button selectButton = createButton(buttonComposite, -1, "Select Subtree", false);
                  final Button deselectButton = createButton(buttonComposite, -1, "Deselect Subtree", false);
                  SelectionListener listener = new SelectionAdapter() {
                      @Override
                      public void widgetSelected(SelectionEvent e) {
                          Object element = ((IStructuredSelection)getTreeViewer().getSelection()).getFirstElement();
                          if (element != null)
                              getTreeViewer().setSubtreeChecked(element, e.widget == selectButton);
                      }
                  };
                  selectButton.addSelectionListener(listener);
                  deselectButton.addSelectionListener(listener);
                  return buttonComposite;
              }
          };
          dlg.setTitle("Select Packages");
          dlg.setMessage("Select packages for the palette:");
          dlg.setHelpAvailable(false);
          dlg.setInput(root);
          dlg.setStatusLineAboveButtons(false);
          dlg.setInitialSelections(initialSelectedNodes.toArray(new Object[]{}));
  
          if (dlg.open() == Window.OK) {
              // extract the result, and set it back on the paletteManager
              Object[] selectedNodes = dlg.getResult();
              Set<String> result = new HashSet<String>();
              allNodes.removeAll(Arrays.asList(selectedNodes)); // abuse allNodes as unselectedNodes
              for (GenericTreeNode node : allNodes)
                  result.add((String)node.getPayload());
              paletteManager.setExcludedPackages(result);
          }
      }
  
      private GenericTreeNode getOrCreateChild(GenericTreeNode node, String segment) {
          for (GenericTreeNode child : node.getChildren())
              if (child.getPayload().equals(segment))
                  return child;
          GenericTreeNode child = new GenericTreeNode(segment);
          node.addChild(child);
          return child;
      }
  }
  