blob: d6978ee074c979f5fb686a76e48f0b3e052879f1 [file] [log] [blame]
/*
* Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
* 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.emf.cdo.ui;
import org.eclipse.emf.cdo.CDOElement;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.internal.ui.bundle.OM;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewTargetChangedEvent;
import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.lifecycle.ILifecycleEvent;
import org.eclipse.net4j.util.lifecycle.ILifecycleEvent.Kind;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Tree;
import java.util.HashSet;
import java.util.Set;
/**
* @author Eike Stepper
* @since 4.4
*/
public class CDOTreeExpansionAgent
{
private final Listener listener = new Listener();
private final Set<CDOID> expandedIDs = new HashSet<CDOID>();
private final Set<CDOID> expandedWrappers = new HashSet<CDOID>();
private final CDOView view;
private final TreeViewer viewer;
public CDOTreeExpansionAgent(final CDOView view, final TreeViewer viewer)
{
CheckUtil.checkArg(view, "view");
CheckUtil.checkArg(viewer, "viewer");
this.view = view;
this.viewer = viewer;
final Tree tree = viewer.getTree();
if (!tree.isDisposed())
{
tree.getDisplay().syncExec(new Runnable()
{
public void run()
{
for (Object element : viewer.getExpandedElements())
{
addExpandedElement(element);
}
view.addListener(listener);
viewer.addTreeListener(listener);
viewer.getTree().addDisposeListener(listener);
}
});
}
}
public final CDOView getView()
{
return view;
}
public final TreeViewer getViewer()
{
return viewer;
}
public void setExpandedStates()
{
for (CDOID id : expandedIDs)
{
try
{
CDOObject object = view.getObject(id);
if (object != null)
{
EObject eObject = CDOUtil.getEObject(object);
viewer.setExpandedState(eObject, true);
}
}
catch (Exception ex)
{
// Ignore.
}
}
for (CDOID id : expandedWrappers)
{
try
{
CDOObject object = view.getObject(id);
if (object != null)
{
CDOElement wrapper = CDOElement.getFor(object);
if (wrapper != null)
{
viewer.setExpandedState(wrapper, true);
}
}
}
catch (Exception ex)
{
// Ignore.
}
}
}
public void dispose()
{
try
{
final Tree tree = viewer.getTree();
if (!tree.isDisposed())
{
tree.getDisplay().syncExec(new Runnable()
{
public void run()
{
tree.removeDisposeListener(listener);
}
});
}
viewer.removeTreeListener(listener);
view.removeListener(listener);
expandedIDs.clear();
expandedWrappers.clear();
}
catch (Exception ex)
{
OM.LOG.error(ex);
}
}
private CDOID getID(Object element)
{
if (element instanceof EObject)
{
CDOObject object = CDOUtil.getCDOObject((EObject)element, false);
if (object != null && object.cdoView() == view)
{
return object.cdoID();
}
}
return null;
}
private void addExpandedElement(Object element)
{
if (element instanceof CDOElement)
{
CDOElement wrapper = (CDOElement)element;
CDOID id = getID(wrapper.getDelegate());
if (id != null)
{
expandedWrappers.add(id);
}
}
else
{
CDOID id = getID(element);
if (id != null)
{
expandedIDs.add(id);
}
}
}
private void removeExpandedElement(Object element)
{
if (element instanceof CDOElement)
{
CDOElement wrapper = (CDOElement)element;
CDOID id = getID(wrapper.getDelegate());
if (id != null)
{
expandedWrappers.remove(id);
}
}
else
{
CDOID id = getID(element);
if (id != null)
{
expandedIDs.remove(id);
}
}
}
/**
* @author Eike Stepper
*/
private final class Listener implements IListener, ITreeViewerListener, DisposeListener
{
public void notifyEvent(IEvent event)
{
if (event instanceof CDOViewTargetChangedEvent)
{
final Tree tree = viewer.getTree();
if (!tree.isDisposed())
{
tree.getDisplay().asyncExec(new Runnable()
{
public void run()
{
if (!tree.isDisposed() && !view.isClosed())
{
setExpandedStates();
}
}
});
}
}
else if (event instanceof ILifecycleEvent)
{
ILifecycleEvent e = (ILifecycleEvent)event;
if (e.getKind() == Kind.ABOUT_TO_DEACTIVATE)
{
dispose();
}
}
}
public void treeExpanded(TreeExpansionEvent event)
{
Object element = event.getElement();
addExpandedElement(element);
}
public void treeCollapsed(TreeExpansionEvent event)
{
Object element = event.getElement();
removeExpandedElement(element);
}
public void widgetDisposed(DisposeEvent e)
{
dispose();
}
}
}