/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.ui.editparts;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import org.csstudio.sds.internal.persistence.DisplayModelLoadAdapter;
import org.csstudio.sds.internal.persistence.PersistenceUtil;
import org.csstudio.sds.model.AbstractWidgetModel;
import org.csstudio.sds.model.ContainerModel;
import org.csstudio.sds.model.DisplayModel;
import org.csstudio.sds.model.LabelModel;
import org.csstudio.sds.model.LinkingContainerModel;
import org.csstudio.sds.ui.CheckedUiRunnable;
import org.csstudio.sds.ui.figures.LinkingContainerFigure;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.ui.progress.IJobRunnable;
/**
* Controller for the linking container widget. The controller mediates between
* {@link LinkingContainerModel} and {@link LinkingContainerFigure}.
*
* @author Sven Wende
*
*/
public final class LinkingContainerEditPart extends AbstractContainerEditPart {
private IProgressMonitor _runningMonitor;
/**
* Constructor.
*/
public LinkingContainerEditPart() {
}
/**
* {@inheritDoc}
*/
@Override
public IFigure getContentPane() {
return ((LinkingContainerFigure) getFigure()).getContentsPane();
}
/**
* {@inheritDoc}
*/
@Override
protected IFigure doCreateFigure() {
LinkingContainerModel widget = (LinkingContainerModel) getContainerModel();
LinkingContainerFigure linkingContainerFigure = new LinkingContainerFigure();
linkingContainerFigure.setAutoFit(widget.isAutoZoom());
return linkingContainerFigure;
}
/**
* {@inheritDoc}
*/
@Override
protected void registerPropertyChangeHandlers() {
IWidgetPropertyChangeHandler handler = new IWidgetPropertyChangeHandler() {
@Override
public boolean handleChange(final Object oldValue,
final Object newValue, final IFigure figure) {
loadResource((IPath) newValue, (LinkingContainerFigure) figure);
return true;
}
};
setPropertyChangeHandler(LinkingContainerModel.PROP_RESOURCE, handler);
LinkingContainerModel m = (LinkingContainerModel) getContainerModel();
if(!m.isResourceLoaded()) {
loadResource(m.getResource(), (LinkingContainerFigure) getFigure());
}
}
/**
* {@inheritDoc}
*/
@Override
protected void refreshChildren() {
super.refreshChildren();
// we need to ensure the correct zoom level, when figures are added or removed
((LinkingContainerFigure) getFigure()).updateZoom();
}
private void loadResource(final IPath resource,
final LinkingContainerFigure figure) {
if (_runningMonitor != null) {
_runningMonitor.setCanceled(true);
}
_runningMonitor = new NullProgressMonitor();
ContainerLoadJob job = new ContainerLoadJob(
(LinkingContainerModel) getContainerModel(), resource, figure);
job.run(_runningMonitor);
}
/**
* {@inheritDoc}
*/
@Override
protected void createEditPolicies() {
super.createEditPolicies();
installEditPolicy(EditPolicy.CONTAINER_ROLE, null);
installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy() {
@Override
protected Command createChangeConstraintCommand(
final EditPart child, final Object constraint) {
return null;
}
@Override
protected Command getCreateCommand(final CreateRequest request) {
return null;
}
@Override
protected void showSizeOnDropFeedback(final CreateRequest request) {
}
});
installEditPolicy(EditPolicy.LAYOUT_ROLE, null);
}
private class ContainerLoadJob implements IJobRunnable {
private final LinkingContainerModel _container;
private final IPath _path;
private final LinkingContainerFigure _figure;
public ContainerLoadJob(final LinkingContainerModel container, final IPath path,
final LinkingContainerFigure figure) {
assert container != null;
assert path != null;
assert figure != null;
_container = container;
_path = path;
_figure = figure;
}
@Override
public IStatus run(final IProgressMonitor progressMonitor) {
IStatus status = Status.OK_STATUS;
if ((_path != null) && !_path.isEmpty()) {
// display a temporary message + cancel button while the display
// is loading
if (!progressMonitor.isCanceled()) {
//showMessage(progressMonitor, "Loading " + _path.toString());
if (!progressMonitor.isCanceled()) {
load(progressMonitor);
} else {
status = Status.CANCEL_STATUS;
}
} else {
status = Status.CANCEL_STATUS;
}
}
return status;
}
protected IStatus clearContainer(final IProgressMonitor progressMonitor) {
// remove old widgets
Iterator<AbstractWidgetModel> it = _container.getWidgets()
.iterator();
while (it.hasNext()) {
_container.removeWidget(it.next());
}
_container.setResourceLoaded(false);
updateZoom();
return Status.OK_STATUS;
}
protected void updateZoom() {
new CheckedUiRunnable() {
@Override
protected void doRunInUi() {
_figure.updateZoom();
}
};
}
protected void showMessage(final IProgressMonitor progressMonitor,
final String message) {
// clear the container
clearContainer(progressMonitor);
// add a temporary widget
final LabelModel loadingMessage = new LabelModel();
loadingMessage.setColor(AbstractWidgetModel.PROP_COLOR_FOREGROUND,"#0000C8");
loadingMessage.setTextValue(message);
loadingMessage.setLocation(0, 0);
int w = _container.getWidth();
loadingMessage.setWidth(w);
int h = _container.getHeight();
loadingMessage.setHeight(h);
_container.addWidget(loadingMessage);
}
/**
* Initializes the {@link ContainerModel} from the specified path.
*
* @param path
* The Path to the ContainerModel
* @throws Exception
*/
protected void load(final IProgressMonitor progressMonitor) {
InputStream input = getInputStream(_path);
if (input == null) {
showMessage(progressMonitor, "Could not load display: "
+ _path.toPortableString());
} else {
final DisplayModel tempModel = new DisplayModel();
PersistenceUtil.asyncFillModel(tempModel, input,
new DisplayModelLoadAdapter() {
@Override
public void onErrorsOccured(final List<String> errors) {
showMessage(progressMonitor, "Error occured: "
+ errors.get(0));
}
@Override
public void onDisplayModelLoaded() {
// remove old widgets
_container.removeWidgets(_container.getWidgets());
// add new widgets
List<AbstractWidgetModel> widgets = tempModel.getWidgets();
tempModel.removeWidgets(widgets);
_container.addWidgets(widgets);
// update zoom
if (!progressMonitor.isCanceled()) {
updateZoom();
}
// use background-color of the loaded display
_container.setColor(AbstractWidgetModel.PROP_COLOR_BACKGROUND, tempModel.getColor(AbstractWidgetModel.PROP_COLOR_BACKGROUND));
_container.setColor(AbstractWidgetModel.PROP_COLOR_FOREGROUND, tempModel.getColor(AbstractWidgetModel.PROP_COLOR_FOREGROUND));
// _container.setAliases(tempModel.getAliases());
_container
.setPrimarPv(tempModel.getPrimaryPV());
_container.setResourceLoaded(true);
}
});
}
}
/**
* Return the {@link InputStream} of the file that is available on the
* specified path.
*
* @param path
* The {@link IPath} to the file
*
* @return The corresponding {@link InputStream} or null
*/
private InputStream getInputStream(final IPath path) {
InputStream result = null;
// try workspace
IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(
path, false);
if (r instanceof IFile) {
try {
result = ((IFile) r).getContents();
} catch (CoreException e) {
result = null;
}
}
if (result == null) {
// try from local file system
try {
result = new FileInputStream(path.toFile());
} catch (FileNotFoundException e) {
result = null;
}
}
return result;
}
}
@Override
protected boolean determineChildrenSelectability() {
return false;
}
}