public FilterEditor()

in src/application/org.openjdk.jmc.ui/src/main/java/org/openjdk/jmc/ui/misc/FilterEditor.java [320:439]


	public <M> FilterEditor(org.eclipse.swt.widgets.Composite parent, Consumer<IItemFilter> onChange,
			IItemFilter initial, Supplier<Collection<IAttribute<?>>> attributeSupplier,
			AttributeValueProvider attributeValueProvider, Function<String, java.awt.Color> typeColorProvider,
			int style) {
		this.attributeSupplier = attributeSupplier;
		this.attributeValueProvider = attributeValueProvider;
		this.tree = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | style);
		this.onChange = onChange;
		tree.setContentProvider(new FilterArrayContentProvider());
		FocusTracker.enableFocusTracking(tree.getTree());
		initializeCellFocus();

		addColumn(tree, Messages.FilterEditor_COLUMN_ATTRIBUTE, 150, new NameLabelProvider(typeColorProvider),
				new AttributeEditingSupport(tree));
		addColumn(tree, Messages.FilterEditor_COLUMN_OPERATION, 100, new OperationLabelProvider(),
				new OperationEditingSupport(tree));
		addColumn(tree, Messages.FilterEditor_COLUMN_VALUE, 500, new ValueLabelProvider(),
				new ValueEditingSupport(tree));

		mm = MCContextMenuManager.create(tree.getControl());

		showColumnHeadersAction = ActionToolkit.checkAction(this::toggleColumnHeaders,
				Messages.FilterEditor_ACTION_SHOW_COLUMN_HEADERS, null);
		mm.appendToGroup(MCContextMenuManager.GROUP_VIEWER_SETUP, showColumnHeadersAction);

		mm.appendToGroup(MCContextMenuManager.GROUP_NEW, ActionToolkit.forListSelection(tree,
				Messages.FilterEditor_ACTION_COMBINE_OR, false, forNonEmptyFilterSelection(filters -> {
					Set<Object> expanded = asSet(tree.getExpandedElements());
					expanded.add(FilterNodeToolkit.wrapFilters(root, filters, true));
					tree.setInput(root);
					tree.setExpandedElements(expanded.toArray());
					notifyListener();
				})));
		mm.appendToGroup(MCContextMenuManager.GROUP_NEW, ActionToolkit.forListSelection(tree,
				Messages.FilterEditor_ACTION_COMBINE_AND, false, forNonEmptyFilterSelection(filters -> {
					Set<Object> expanded = asSet(tree.getExpandedElements());
					expanded.add(FilterNodeToolkit.wrapFilters(root, filters, false));
					tree.setInput(root);
					tree.setExpandedElements(expanded.toArray());
					notifyListener();
				})));
		mm.appendToGroup(MCContextMenuManager.GROUP_NEW,
				ActionToolkit.forListSelection(tree, Messages.FilterEditor_ACTION_REMOVE, false,
						(List<FilterNode> selection) -> onlyCompositeNodesSelected(selection) ? () -> {
							Object[] expanded = tree.getExpandedElements();
							for (FilterNode node : selection) {
								FilterNodeToolkit.unwrapFilter(root, (CompositeNode) node);
							}
							tree.setInput(root);
							tree.setExpandedElements(expanded);
							notifyListener();
						} : null));
		// FIXME: This action does not update its enablement until it has been unselected and reselected (list selection has changed)
		mm.appendToGroup(MCContextMenuManager.GROUP_NEW,
				ActionToolkit.forListSelection(tree, Messages.FilterEditor_ACTION_NEGATE, true,
						(List<FilterNode> filters) -> filtersNegatable(filters) ? () -> {
							for (FilterNode filter : filters) {
								if (filter instanceof CompositeNode) {
									CompositeNode composite = (CompositeNode) filter;
									composite.negated = !composite.negated;
								} else if (isAttributeFilter(filter)) {
									AttributeFilter<M> attributeFilter = asAttributeFilterM(filter);
									M value = attributeFilter instanceof AttributeValue
											? ((AttributeValue<M>) attributeFilter).getValue() : null;
									Kind kind = attributeFilter.getKind();
									Kind newKind = kind.negate();
									if (newKind != null) {
										((LeafNode) filter).filter = buildFilter(newKind,
												attributeFilter.getAttribute(), value);
									}
								}
							}
							notifyListener();
						} : null));

		IAction cutAction = ActionToolkit.forListSelection(tree, null, false,
				forNonEmptyFilterSelection(this::cutNodes));
		ActionToolkit.convertToCommandAction(cutAction, IWorkbenchCommandConstants.EDIT_CUT);
		InFocusHandlerActivator.install(tree.getControl(), cutAction);
		mm.appendToGroup(MCContextMenuManager.GROUP_EDIT, cutAction);

		IAction copyAction = ActionToolkit.forListSelection(tree, null, false,
				forNonEmptyFilterSelection(this::copyNodes));
		ActionToolkit.convertToCommandAction(copyAction, IWorkbenchCommandConstants.EDIT_COPY);
		InFocusHandlerActivator.install(tree.getControl(), copyAction);
		mm.appendToGroup(MCContextMenuManager.GROUP_EDIT, copyAction);

		IAction pasteAction = ActionToolkit.forListSelection(tree, null, false,
				(List<FilterNode> selection) -> (selection.size() <= 1) ? () -> pasteNodes(selection) : null);
		ActionToolkit.convertToCommandAction(pasteAction, IWorkbenchCommandConstants.EDIT_PASTE);
		InFocusHandlerActivator.install(tree.getControl(), pasteAction);
		mm.appendToGroup(MCContextMenuManager.GROUP_EDIT, pasteAction);

		IAction removeAction = ActionToolkit.forTreeSelection(tree, null, false,
				selection -> selection.isEmpty() || selection.getFirstElement() instanceof EmptyNode ? null
						: () -> deleteNodes(selection));
		ActionToolkit.convertToCommandAction(removeAction, IWorkbenchCommandConstants.EDIT_DELETE);
		InFocusHandlerActivator.install(tree.getControl(), removeAction);
		mm.appendToGroup(MCContextMenuManager.GROUP_EDIT, removeAction);
		mm.appendToGroup(MCContextMenuManager.GROUP_EDIT,
				ActionToolkit.action(this::clearNodes, Messages.FilterEditor_ACTION_CLEAR_ALL));

		if (initial instanceof Composite && !((Composite) initial).isUnion()) {
			for (IItemFilter f : ((Composite) initial).getFilters()) {
				root.children.add(buildTreeNode(f));
			}
		} else if (initial != null) {
			root.children.add(buildTreeNode(initial));
		}
		Transfer[] localTransfer = new Transfer[] {LocalSelectionTransfer.getTransfer()};
		tree.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, localTransfer,
				DndToolkit.createLocalDragSource(tree, this::deleteNodes));
		ViewerDropAdapter dropTarget = DndToolkit.createLocalDropListTarget(tree, CompositeNode.class, FilterNode.class,
				this::performDrop, this::validateDrop);
		dropTarget.setFeedbackEnabled(false);
		tree.addDropSupport(DND.DROP_MOVE | DND.DROP_COPY, localTransfer, dropTarget);
		ColumnViewerToolTipSupport.enableFor(tree);

		tree.setInput(root);
	}