Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/views/ContainerItemProvider.java')
-rw-r--r--plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/views/ContainerItemProvider.java385
1 files changed, 385 insertions, 0 deletions
diff --git a/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/views/ContainerItemProvider.java b/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/views/ContainerItemProvider.java
new file mode 100644
index 0000000000..f10da07c76
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/views/ContainerItemProvider.java
@@ -0,0 +1,385 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ui.views;
+
+import org.eclipse.net4j.internal.util.container.ContainerEventAdapter;
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class ContainerItemProvider<CONTAINER extends IContainer> extends ItemProvider<CONTAINER>
+{
+ private Map<Object, Node> nodes = new HashMap();
+
+ private ContainerNode root;
+
+ private IElementFilter rootElementFilter;
+
+ public ContainerItemProvider()
+ {
+ }
+
+ public ContainerItemProvider(IElementFilter rootElementFilter)
+ {
+ this.rootElementFilter = rootElementFilter;
+ }
+
+ public IElementFilter getRootElementFilter()
+ {
+ return rootElementFilter;
+ }
+
+ @Override
+ public boolean hasChildren(Object element)
+ {
+ try
+ {
+ Node node = getNode(element);
+ return !node.getChildren().isEmpty();
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ public Object[] getChildren(Object element)
+ {
+ try
+ {
+ Node node = getNode(element);
+ List<Node> children = node.getChildren();
+ for (Iterator it = children.iterator(); it.hasNext();)
+ {
+ Object child = it.next();
+ if (!LifecycleUtil.isActive(child))
+ {
+ it.remove();
+ }
+ }
+
+ Object[] result = new Object[children.size()];
+ for (int i = 0; i < result.length; i++)
+ {
+ result[i] = children.get(i).getElement();
+ }
+
+ return result;
+ }
+ catch (RuntimeException ex)
+ {
+ return NO_CHILDREN;
+ }
+ }
+
+ public Object getParent(Object element)
+ {
+ try
+ {
+ Node node = getNode(element);
+ Node parentNode = node.getParent();
+ return parentNode == null ? null : parentNode.getElement();
+ }
+ catch (RuntimeException ex)
+ {
+ return null;
+ }
+ }
+
+ @Override
+ protected void connectInput(CONTAINER input)
+ {
+ root = (ContainerNode)createNode(null, input);
+ nodes.put(input, root);
+ }
+
+ @Override
+ protected void disconnectInput(CONTAINER input)
+ {
+ root.dispose();
+ root = null;
+ nodes.clear();
+ }
+
+ protected void elementAdded(Object element, Object parent)
+ {
+ }
+
+ protected void elementRemoved(Object element, Object parent)
+ {
+ }
+
+ protected ContainerNode getRoot()
+ {
+ return root;
+ }
+
+ protected Map<Object, Node> getNodes()
+ {
+ return nodes;
+ }
+
+ protected Node getNode(Object element)
+ {
+ Node node = root;
+ if (element != getInput())
+ {
+ node = nodes.get(element);
+ }
+
+ if (node == null)
+ {
+ throw new IllegalStateException("No node for " + element);
+ }
+
+ return node;
+ }
+
+ protected Node createNode(Node parent, Object element)
+ {
+ if (element instanceof IContainer)
+ {
+ return new ContainerNode(parent, (IContainer)element);
+ }
+
+ return new LeafNode(parent, element);
+ }
+
+ protected boolean filterRootElement(Object element)
+ {
+ if (rootElementFilter != null)
+ {
+ return rootElementFilter.filter(element);
+ }
+
+ return true;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface Node
+ {
+ public void dispose();
+
+ public Object getElement();
+
+ public Node getParent();
+
+ public List<Node> getChildren();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public abstract class AbstractNode implements Node
+ {
+ private Node parent;
+
+ private List<Node> children;
+
+ public AbstractNode(Node parent)
+ {
+ this.parent = parent;
+ }
+
+ public void dispose()
+ {
+ parent = null;
+ if (children != null)
+ {
+ for (Node child : children)
+ {
+ child.dispose();
+ }
+
+ children.clear();
+ children = null;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return getElement().toString();
+ }
+
+ public final Node getParent()
+ {
+ return parent;
+ }
+
+ public final List<Node> getChildren()
+ {
+ if (children == null)
+ {
+ children = createChildren();
+ }
+
+ return children;
+ }
+
+ protected abstract List<Node> createChildren();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public class ContainerNode extends AbstractNode
+ {
+ private IContainer container;
+
+ private IListener containerListener = new ContainerEventAdapter()
+ {
+ @Override
+ protected void onAdded(IContainer container, Object element)
+ {
+ if (container == ContainerNode.this.container)
+ {
+ Node node = addChild(getChildren(), element);
+ if (node != null)
+ {
+ refreshElement(container, false);
+ revealElement(element);
+ elementAdded(element, container);
+ }
+ }
+ }
+
+ @Override
+ protected void onRemoved(IContainer container, Object element)
+ {
+ if (container == ContainerNode.this.container)
+ {
+ Node node = nodes.remove(element);
+ if (node != null)
+ {
+ getChildren().remove(node);
+ node.dispose();
+ refreshElement(container, false);
+ elementRemoved(element, container);
+ }
+ }
+ }
+ };
+
+ public ContainerNode(Node parent, IContainer container)
+ {
+ super(parent);
+ this.container = container;
+ }
+
+ @Override
+ public void dispose()
+ {
+ container.removeListener(containerListener);
+ container = null;
+ super.dispose();
+ }
+
+ public IContainer getContainer()
+ {
+ return container;
+ }
+
+ public Object getElement()
+ {
+ return container;
+ }
+
+ @Override
+ public String toString()
+ {
+ return container == null ? super.toString() : container.toString();
+ }
+
+ @Override
+ protected List<Node> createChildren()
+ {
+ Object[] elements = container.getElements();
+ List<Node> children = new ArrayList(elements.length);
+ for (int i = 0; i < elements.length; i++)
+ {
+ Object element = elements[i];
+ addChild(children, element);
+ }
+
+ container.addListener(containerListener);
+ return children;
+ }
+
+ protected Node addChild(List<Node> children, Object element)
+ {
+ if (this != root || filterRootElement(element))
+ {
+ Node node = createNode(this, element);
+ nodes.put(element, node);
+ children.add(node);
+ return node;
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public class LeafNode implements Node
+ {
+ private Node parent;
+
+ private Object element;
+
+ public LeafNode(Node parent, Object element)
+ {
+ this.parent = parent;
+ this.element = element;
+ }
+
+ public void dispose()
+ {
+ parent = null;
+ element = null;
+ }
+
+ public Node getParent()
+ {
+ return parent;
+ }
+
+ public Object getElement()
+ {
+ return element;
+ }
+
+ public List<Node> getChildren()
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public String toString()
+ {
+ return element == null ? super.toString() : element.toString();
+ }
+ }
+}

Back to the top