blob: 99b78024fc39a732f67f9a90e029cde3eba7d73a [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.widgets;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewTargetChangedEvent;
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.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Scale;
import java.util.HashSet;
import java.util.Set;
/**
* @author Eike Stepper
* @since 4.4
*/
public class TimeSlider extends Scale implements IListener, ITreeViewerListener
{
private static final int MIN = 0;
private static final int MAX = 100000;
private static final double FACTOR = MAX - MIN;
private final Set<CDOID> expandedIDs = new HashSet<CDOID>();
private long startTimeStamp;
private long endTimeStamp;
private long absoluteTimeWindowLength;
private double stepSize;
private long timeStamp;
private CDOStaleReferencePolicy.DynamicProxy.Enhanced staleReferencePolicy;
private CDOView view;
private TreeViewer viewer;
public TimeSlider(Composite parent, int style)
{
super(parent, style);
setMinimum(MIN);
setMaximum(MAX);
setSelection(MAX);
setPageIncrement(MAX - MIN);
addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
long value = getSelection();
long timeStamp = startTimeStamp + Math.round(stepSize * value);
setTimeStamp(timeStamp);
if (viewer != null)
{
viewer.refresh();
setExpandedStates();
}
}
protected void setExpandedStates()
{
for (CDOID id : expandedIDs)
{
try
{
CDOObject object = view.getObject(id);
viewer.setExpandedState(object, true);
}
catch (Exception ex)
{
// Ignore
}
}
}
});
}
public final long getTimeStamp()
{
return timeStamp;
}
public void setTimeStamp(long timeStamp)
{
if (timeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
{
timeStamp = endTimeStamp;
}
else if (timeStamp < startTimeStamp)
{
timeStamp = startTimeStamp;
}
else if (timeStamp > endTimeStamp)
{
timeStamp = endTimeStamp;
}
if (this.timeStamp != timeStamp)
{
this.timeStamp = timeStamp;
final int newSelection = (int)((timeStamp - startTimeStamp) / stepSize);
Display display = getDisplay();
if (display == Display.getCurrent())
{
if (getSelection() != newSelection)
{
setSelection(newSelection);
}
}
else
{
display.asyncExec(new Runnable()
{
public void run()
{
if (getSelection() != newSelection)
{
setSelection(newSelection);
}
}
});
}
timeStampChanged(timeStamp);
}
}
public void connect(CDOView view, TreeViewer viewer)
{
if (this.view != view)
{
disconnect();
if (view != null)
{
this.view = view;
this.viewer = viewer;
CDOBranchPointRange lifetime = null;
if (this.viewer != null)
{
for (Object element : viewer.getExpandedElements())
{
CDOID id = getID(element);
if (id != null)
{
expandedIDs.add(id);
}
}
this.viewer.addTreeListener(this);
Object input = viewer.getInput();
if (input instanceof EObject)
{
lifetime = CDOUtil.getLifetime(CDOUtil.getCDOObject((EObject)input));
}
}
if (lifetime == null)
{
CDOSession session = view.getSession();
CDOBranch branch = view.getBranch();
CDOBranchPoint firstPoint = branch.getPoint(session.getRepositoryInfo().getCreationTime());
CDOBranchPoint lastPoint = branch.getHead();
lifetime = CDOBranchUtil.createRange(firstPoint, lastPoint);
}
startTimeStamp = lifetime.getStartPoint().getTimeStamp();
endTimeStamp = lifetime.getEndPoint().getTimeStamp();
if (endTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
{
CDOSession session = view.getSession();
endTimeStamp = session.getLastUpdateTime();
}
absoluteTimeWindowLength = endTimeStamp - startTimeStamp;
stepSize = absoluteTimeWindowLength / FACTOR;
setTimeStamp(view.getTimeStamp());
staleReferencePolicy = new CDOStaleReferencePolicy.DynamicProxy.Enhanced(view);
view.addListener(this);
setEnabled(true);
}
else
{
setEnabled(false);
}
}
}
public void disconnect()
{
if (view != null)
{
if (staleReferencePolicy != null)
{
view.removeListener(this);
staleReferencePolicy.dispose();
staleReferencePolicy = null;
if (viewer != null)
{
expandedIDs.clear();
viewer.removeTreeListener(this);
viewer = null;
}
}
view = null;
}
}
public void notifyEvent(IEvent event)
{
if (event instanceof CDOViewTargetChangedEvent)
{
CDOViewTargetChangedEvent e = (CDOViewTargetChangedEvent)event;
setTimeStamp(e.getBranchPoint().getTimeStamp());
}
else if (event instanceof ILifecycleEvent)
{
ILifecycleEvent e = (ILifecycleEvent)event;
if (e.getKind() == Kind.ABOUT_TO_DEACTIVATE)
{
disconnect();
}
}
}
public void treeExpanded(TreeExpansionEvent event)
{
CDOID id = getID(event.getElement());
if (id != null)
{
expandedIDs.add(id);
}
}
public void treeCollapsed(TreeExpansionEvent event)
{
CDOID id = getID(event.getElement());
if (id != null)
{
expandedIDs.remove(id);
}
}
@Override
public void dispose()
{
disconnect();
super.dispose();
}
protected void timeStampChanged(long timeStamp)
{
if (view != null)
{
view.setTimeStamp(timeStamp);
}
}
@Override
protected void checkSubclass()
{
// Allow overriding.
}
private CDOID getID(Object element)
{
if (element instanceof EObject)
{
CDOObject object = CDOUtil.getCDOObject((EObject)element, false);
if (object != null)
{
return object.cdoID();
}
}
return null;
}
}