blob: a97ec01bb6ce85ef4654f46448024e3489ed60b1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* 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:
* Pierre Allard,
* Regent L'Archeveque,
* Olivier L. Larouche - initial API and implementation
* SPDX-License-Identifier: EPL-1.0
*
*******************************************************************************/
package org.eclipse.apogy.common.emf.ui.composites;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.apogy.common.databinding.converters.DateToStringConverter;
import org.eclipse.apogy.common.emf.ApogyCommonEMFPackage;
import org.eclipse.apogy.common.emf.CollectionTimedTimeSource;
import org.eclipse.apogy.common.emf.TimeSource;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.Spinner;
public class CollectionTimedTimeSourceComposite extends BrowseableTimeSourceComposite {
private CollectionTimedTimeSource collectionTimedTimeSource;
protected Adapter collectionTimedTimeSourceAdapter = null;
// Looping
protected Button loopingEnabledButton;
// Jump Buttons
protected Button jumpToNextButton;
protected Button jumpToPreviousButton;
// Time line controls.
protected Label timeLineStartTimeValueLabel = null;
protected Label timeLineEndTimeValueLabel = null;
protected Slider timeScale;
public CollectionTimedTimeSourceComposite(Composite parent, int style,
CollectionTimedTimeSource acceleratedTimeSource) {
super(parent, style, acceleratedTimeSource);
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (CollectionTimedTimeSourceComposite.this.collectionTimedTimeSource != null) {
CollectionTimedTimeSourceComposite.this.collectionTimedTimeSource.eAdapters()
.remove(getCollectionTimedTimeSourceAdapter());
}
if (CollectionTimedTimeSourceComposite.this.bindingContext != null) {
CollectionTimedTimeSourceComposite.this.bindingContext.dispose();
}
}
});
setCollectionTimedTimeSource(acceleratedTimeSource);
}
public CollectionTimedTimeSource getCollectionTimedTimeSource() {
return this.collectionTimedTimeSource;
}
public void setCollectionTimedTimeSource(CollectionTimedTimeSource collectionTimedTimeSource) {
if (this.collectionTimedTimeSource != null) {
this.collectionTimedTimeSource.eAdapters().remove(getCollectionTimedTimeSourceAdapter());
}
this.collectionTimedTimeSource = collectionTimedTimeSource;
if (collectionTimedTimeSource != null) {
collectionTimedTimeSource.eAdapters().add(getCollectionTimedTimeSourceAdapter());
}
super.setBrowseableTimeSource(collectionTimedTimeSource);
}
@Override
protected void createContent() {
Composite top = new Composite(this, SWT.NONE);
top.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
top.setLayout(new GridLayout(1, true));
// Setup Composite
Composite setupComposite = createSettingsComposite(top, SWT.NONE);
setupComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1));
// Time Line
Composite timeLineComposite = createTimeLineComposite(top, SWT.NONE);
timeLineComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
// Buttons Composite for time direction controls and reset.
Composite buttonsComposite = createButtonsComposite(top, SWT.NONE);
buttonsComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1));
Composite composite = new Composite(this, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
}
@Override
protected Composite createButtonsComposite(Composite parent, int style) {
Composite buttonsComposite = new Composite(parent, style);
buttonsComposite.setLayout(new GridLayout(6, false));
// RESET
this.playResetButton = new Button(buttonsComposite, SWT.PUSH);
GridData resetButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
resetButtonGridData.minimumWidth = 75;
resetButtonGridData.widthHint = 75;
this.playResetButton.setLayoutData(resetButtonGridData);
this.playResetButton.setText("Reset");
this.playResetButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getBrowseableTimeSource().reset();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// Jump Previous
this.jumpToPreviousButton = new Button(buttonsComposite, SWT.PUSH);
GridData jumpToPreviousButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
jumpToPreviousButtonGridData.minimumWidth = 75;
jumpToPreviousButtonGridData.widthHint = 75;
this.jumpToPreviousButton.setLayoutData(jumpToPreviousButtonGridData);
this.jumpToPreviousButton.setText("Previous");
this.jumpToPreviousButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getCollectionTimedTimeSource().jumpToPrevious();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// REVERSE
this.playReverseButton = new Button(buttonsComposite, SWT.PUSH);
GridData reverseButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
reverseButtonGridData.minimumWidth = 75;
reverseButtonGridData.widthHint = 75;
this.playReverseButton.setLayoutData(reverseButtonGridData);
this.playReverseButton.setText("Reverse");
this.playReverseButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getBrowseableTimeSource().playReverse();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// PAUSE
this.playPauseButton = new Button(buttonsComposite, SWT.PUSH);
GridData pauseButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
pauseButtonGridData.minimumWidth = 75;
pauseButtonGridData.widthHint = 75;
this.playPauseButton.setLayoutData(pauseButtonGridData);
this.playPauseButton.setText("Pause");
this.playPauseButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getBrowseableTimeSource().pause();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// FORWARD
this.playForwardButton = new Button(buttonsComposite, SWT.PUSH);
GridData forwardButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
forwardButtonGridData.minimumWidth = 75;
forwardButtonGridData.widthHint = 75;
this.playForwardButton.setLayoutData(forwardButtonGridData);
this.playForwardButton.setText("Forward");
this.playForwardButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getBrowseableTimeSource().playForward();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// Jump Next
this.jumpToNextButton = new Button(buttonsComposite, SWT.PUSH);
GridData jumpToNextButtonGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
jumpToNextButtonGridData.minimumWidth = 75;
jumpToNextButtonGridData.widthHint = 75;
this.jumpToNextButton.setLayoutData(jumpToNextButtonGridData);
this.jumpToNextButton.setText("Next");
this.jumpToNextButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getBrowseableTimeSource() != null) {
getCollectionTimedTimeSource().jumpToNext();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
return buttonsComposite;
}
@Override
protected Composite createSettingsComposite(Composite parent, int style) {
Composite settingsComposite = new Composite(parent, SWT.BORDER);
settingsComposite.setLayout(new GridLayout(2, false));
Label updatePeriodLabel = new Label(settingsComposite, SWT.None);
updatePeriodLabel.setText("Update period (s):");
this.updatePeriodSpinner = new Spinner(settingsComposite, SWT.BORDER);
this.updatePeriodSpinner.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
GridData updatePeriodSpinnerGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
updatePeriodSpinnerGridData.widthHint = 100;
updatePeriodSpinnerGridData.minimumWidth = 100;
this.updatePeriodSpinner.setLayoutData(updatePeriodSpinnerGridData);
this.updatePeriodSpinner.setDigits(3);
this.updatePeriodSpinner.setMinimum(1);
this.updatePeriodSpinner.setMaximum(60000);
this.updatePeriodSpinner.setIncrement(1);
this.updatePeriodSpinner.setSelection(1000);
this.updatePeriodSpinner.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
int selection = CollectionTimedTimeSourceComposite.this.updatePeriodSpinner.getSelection();
int digits = CollectionTimedTimeSourceComposite.this.updatePeriodSpinner.getDigits();
int period = (int) Math.round((selection / Math.pow(10, digits)) * 1000);
ApogyCommonTransactionFacade.INSTANCE.basicSet(getBrowseableTimeSource(),
ApogyCommonEMFPackage.Literals.BROWSEABLE_TIME_SOURCE__UPDATE_PERIOD, period);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
Label timeAccelerationLabel = new Label(settingsComposite, SWT.None);
timeAccelerationLabel.setText("Time Acceleration:");
this.timeAccelerationSpinner = new Spinner(settingsComposite, SWT.BORDER);
GridData timeAccelerationSpinnerGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
timeAccelerationSpinnerGridData.widthHint = 100;
timeAccelerationSpinnerGridData.minimumWidth = 100;
this.timeAccelerationSpinner.setLayoutData(timeAccelerationSpinnerGridData);
this.timeAccelerationSpinner.setDigits(1);
this.timeAccelerationSpinner.setMinimum(1);
this.timeAccelerationSpinner.setMaximum(100000);
this.timeAccelerationSpinner.setIncrement(1);
this.timeAccelerationSpinner.setSelection(100);
this.timeAccelerationSpinner.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
int selection = CollectionTimedTimeSourceComposite.this.timeAccelerationSpinner.getSelection();
int digits = CollectionTimedTimeSourceComposite.this.timeAccelerationSpinner.getDigits();
float acceleration = (float) (selection / Math.pow(10, digits));
ApogyCommonTransactionFacade.INSTANCE.basicSet(getBrowseableTimeSource(),
ApogyCommonEMFPackage.Literals.BROWSEABLE_TIME_SOURCE__TIME_ACCERATION, acceleration);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
Label loopingEnabledLabel = new Label(settingsComposite, SWT.None);
loopingEnabledLabel.setText("Loop Enable");
this.loopingEnabledButton = new Button(settingsComposite, SWT.FLAT | SWT.CHECK);
this.loopingEnabledButton.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false, 1, 1));
return settingsComposite;
}
protected Composite createTimeLineComposite(Composite parent, int style) {
Composite timeLineComposite = new Composite(parent, style);
timeLineComposite.setLayout(new GridLayout(3, false));
Composite composite_1 = new Composite(timeLineComposite, SWT.NONE);
composite_1.setLayout(new GridLayout(2, false));
// Start Time Label
Label startTimeLabel = new Label(composite_1, SWT.NONE);
startTimeLabel.setText("Start Time:");
// Start Time Value
this.timeLineStartTimeValueLabel = new Label(composite_1, SWT.NONE);
this.timeLineStartTimeValueLabel.setAlignment(SWT.LEFT);
this.timeLineStartTimeValueLabel.setText("N/A");
Composite composite_2 = new Composite(timeLineComposite, SWT.NONE);
composite_2.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
composite_2.setLayout(new GridLayout(2, false));
// End Time Label
Label endTimeLabel = new Label(composite_2, SWT.NONE);
endTimeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
endTimeLabel.setAlignment(SWT.RIGHT);
endTimeLabel.setText("End Time:");
// End Time Value
this.timeLineEndTimeValueLabel = new Label(composite_2, SWT.NONE);
this.timeLineEndTimeValueLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
this.timeLineEndTimeValueLabel.setAlignment(SWT.RIGHT);
this.timeLineEndTimeValueLabel.setText("N/A");
new Label(timeLineComposite, SWT.NONE);
// Time slider
this.timeScale = new Slider(timeLineComposite, SWT.HORIZONTAL);
this.timeScale.setDragDetect(true);
this.timeScale.setThumb(1);
this.timeScale.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.timeScale.setMinimum(0);
this.timeScale.setMaximum(100);
new Label(timeLineComposite, SWT.NONE);
this.timeScale.addMouseListener(new MouseListener() {
@Override
public void mouseUp(MouseEvent e) {
if (getCollectionTimedTimeSource() != null) {
int selection = CollectionTimedTimeSourceComposite.this.timeScale.getSelection();
Date earliest = getCollectionTimedTimeSource().getEarliestDate();
Date latest = getCollectionTimedTimeSource().getLatestDate();
if (earliest != null && latest != null) {
long startTime = earliest.getTime();
long endTime = latest.getTime();
long delta = Math.round((selection / 100.0) * (endTime - startTime));
Date selectedTime = new Date(startTime + delta);
ApogyCommonTransactionFacade.INSTANCE.basicSet(getCollectionTimedTimeSource(),
ApogyCommonEMFPackage.Literals.TIMED__TIME, selectedTime);
}
}
}
@Override
public void mouseDown(MouseEvent e) {
if (getCollectionTimedTimeSource() != null) {
getCollectionTimedTimeSource().pause();
}
}
@Override
public void mouseDoubleClick(MouseEvent e) {
}
});
return timeLineComposite;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected DataBindingContext initDataBindings() {
DataBindingContext dataBindingContext = super.initDataBindings();
TransactionalEditingDomain domain = ApogyCommonTransactionFacade.INSTANCE
.getTransactionalEditingDomain(getTimeSource());
// Bind StartTime.
if (this.timeLineStartTimeValueLabel != null) {
IObservableValue startTimeLabelValue = PojoProperties.value("text")
.observe(this.timeLineStartTimeValueLabel);
IObservableValue startTimeObserveValue;
if (domain != null) {
startTimeObserveValue = EMFEditProperties
.value(domain,
FeaturePath.fromList(
ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__EARLIEST_DATE))
.observe(getTimeSource());
} else {
startTimeObserveValue = EMFProperties
.value(FeaturePath
.fromList(ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__EARLIEST_DATE))
.observe(getTimeSource());
}
UpdateValueStrategy startTimeValueStrategy = new UpdateValueStrategy();
startTimeValueStrategy.setConverter(new DateToStringConverter(new SimpleDateFormat(DATE_FORMAT_STRING)));
dataBindingContext.bindValue(startTimeLabelValue, startTimeObserveValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), startTimeValueStrategy);
}
// Bind EndTime.
if (this.timeLineEndTimeValueLabel != null) {
IObservableValue endTimeLabelValue = PojoProperties.value("text").observe(this.timeLineEndTimeValueLabel);
IObservableValue endTimeObserveValue;
if (domain != null) {
endTimeObserveValue = EMFEditProperties
.value(domain,
FeaturePath.fromList(
ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__LATEST_DATE))
.observe(getTimeSource());
} else {
endTimeObserveValue = EMFProperties
.value(FeaturePath
.fromList(ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__LATEST_DATE))
.observe(getTimeSource());
}
UpdateValueStrategy endTimeValueStrategy = new UpdateValueStrategy();
endTimeValueStrategy.setConverter(new DateToStringConverter(new SimpleDateFormat(DATE_FORMAT_STRING)));
dataBindingContext.bindValue(endTimeLabelValue, endTimeObserveValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), endTimeValueStrategy);
}
// Bind Loop
if (this.loopingEnabledButton != null) {
IObservableValue loopButtonValue = WidgetProperties.selection().observe(this.loopingEnabledButton);
IObservableValue loopObserveValue;
if (domain != null) {
loopObserveValue = EMFEditProperties
.value(domain,
FeaturePath.fromList(
ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__LOOP_ENABLE))
.observe(getTimeSource());
} else {
loopObserveValue = EMFProperties
.value(FeaturePath
.fromList(ApogyCommonEMFPackage.Literals.COLLECTION_TIMED_TIME_SOURCE__LOOP_ENABLE))
.observe(getTimeSource());
}
UpdateValueStrategy loopValueStrategy = new UpdateValueStrategy();
dataBindingContext.bindValue(loopButtonValue, loopObserveValue, loopValueStrategy, loopValueStrategy);
}
return dataBindingContext;
}
protected void setTimeScaleTime(Date time) {
if (!this.timeScale.isDisposed()) {
if (getCollectionTimedTimeSource() != null) {
if (this.timeScale != null && time != null) {
Date earliest = getCollectionTimedTimeSource().getEarliestDate();
Date latest = getCollectionTimedTimeSource().getLatestDate();
long timeSpan = latest.getTime() - earliest.getTime();
long delta = time.getTime() - earliest.getTime();
double ratio = 0.0;
if (timeSpan != 0.0) {
ratio = (double) delta / (double) timeSpan;
}
int selection = (int) Math.round(this.timeScale.getMaximum() * ratio);
this.timeScale.setSelection(selection);
this.timeScale.setToolTipText(time.toString());
}
} else {
this.timeScale.setSelection(0);
}
}
}
protected Adapter getCollectionTimedTimeSourceAdapter() {
if (this.collectionTimedTimeSourceAdapter == null) {
this.collectionTimedTimeSourceAdapter = new AdapterImpl() {
@Override
public void notifyChanged(final Notification msg) {
if (msg.getNotifier() instanceof TimeSource) {
int featureId = msg.getFeatureID(TimeSource.class);
switch (featureId) {
case ApogyCommonEMFPackage.TIME_SOURCE__TIME: {
if (msg.getNewValue() instanceof Date) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
Date currentTime = (Date) msg.getNewValue();
setTimeScaleTime(currentTime);
}
});
}
}
break;
default:
break;
}
}
}
};
}
return this.collectionTimedTimeSourceAdapter;
}
}