/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.views.properties.runtime;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.catalog.PropertiesURIHandler;
import org.eclipse.papyrus.views.properties.contexts.Context;
import org.eclipse.papyrus.views.properties.contexts.Section;
import org.eclipse.papyrus.views.properties.contexts.Tab;
import org.eclipse.papyrus.views.properties.contexts.View;
import org.eclipse.papyrus.views.properties.modelelement.DataSource;
import org.eclipse.papyrus.views.properties.xwt.XWTTabDescriptor;
import org.eclipse.papyrus.xwt.DefaultLoadingContext;
import org.eclipse.papyrus.xwt.ILoadingContext;
import org.eclipse.papyrus.xwt.XWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.views.properties.tabbed.ITabDescriptor;
/**
* A default implementation for {@link DisplayEngine}
*
* @author Camille Letavernier
*/
public class DefaultDisplayEngine implements DisplayEngine {
private ILoadingContext loadingContext = new DefaultLoadingContext(getClass().getClassLoader());
private Set<String> displayedSections = new HashSet<String>();
private Set<Control> controls = new HashSet<Control>();
private boolean allowDuplicate;
/**
* Constructs a new DisplayEnginet that doesn't allow the duplication of sections
*/
public DefaultDisplayEngine() {
this(false);
}
/**
* Constructor.
*
* @param allowDuplicate
* If false, two calls of {@link #createSection(Composite, Section, DataSource)} with the same
* section will display the section only once : only the first call is taken into account
* The main property view doesn't allow duplication, to avoid redundancy when two views link to
* the same section.
*/
public DefaultDisplayEngine(boolean allowDuplicate) {
this.allowDuplicate = allowDuplicate;
}
public List<ITabDescriptor> getTabDescriptors(Set<View> views) {
Map<String, XWTTabDescriptor> result = new LinkedHashMap<String, XWTTabDescriptor>();
Set<String> selectedSections = new HashSet<String>();
for(View view : views) {
for(Section section : view.getSections()) {
if(selectedSections.contains(section.getName())) {
continue;
}
Tab tab = section.getTab();
if(tab == null) {
Activator.log.warn("Null tab for " + section); //$NON-NLS-1$
continue;
}
XWTTabDescriptor descriptor;
if(result.containsKey(tab.getId())) {
descriptor = result.get(tab.getId());
} else {
descriptor = new XWTTabDescriptor(tab);
result.put(tab.getId(), descriptor);
}
descriptor.addSection(section, view, this);
selectedSections.add(section.getName());
}
}
disposeControls();
return new LinkedList<ITabDescriptor>(result.values());
}
/**
* Disposes the controls created by this DisplayEngine
* This should not dispose the engine itself, which can be reused.
*/
protected void disposeControls() {
for(Control control : controls) {
control.dispose();
}
displayedSections.clear();
controls.clear();
}
/**
* {@inheritDoc}
*/
public void dispose() {
disposeControls();
}
public Control createSection(Composite parent, Section section, DataSource source) {
if(source == null) {
return null;
}
if(!allowDuplicate && displayedSections.contains(section.getName())) {
return null;
}
Control control = createSection(parent, section, loadXWTFile(section), source);
displayedSections.add(section.getName());
if(control != null) {
controls.add(control);
}
return control;
}
public void refreshSection(Composite parent, Section section, DataSource source) {
for(Control control : parent.getChildren()) {
control.dispose();
}
Control control = createSection(parent, section, loadXWTFile(section), source);
displayedSections.add(section.getName());
if(control != null) {
controls.add(control);
}
}
public Control createSection(Composite parent, Section section, URL sectionFile, DataSource source) {
if(sectionFile == null) {
sectionFile = loadXWTFile(section);
if(sectionFile == null) {
return null;
}
}
ILoadingContext xwtContext = XWT.getLoadingContext();
XWT.setLoadingContext(loadingContext);
Control control = null;
try {
control = (Control)XWT.load(parent, sectionFile, source);
if(control != null) {
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
controls.add(control);
}
} catch (Exception ex) {
Activator.log.error("Error while loading " + section.getSectionFile(), ex); //$NON-NLS-1$
disposeControls();
Label label = new Label(parent, SWT.NONE);
label.setText("An error occured in the property view. The file " + section.getSectionFile() + " could not be loaded"); //$NON-NLS-1$ //$NON-NLS-2$
}
layout(parent);
XWT.setLoadingContext(xwtContext);
return control;
}
private URL loadXWTFile(Section section) {
EObject tab = section.eContainer();
Context context = (Context)tab.eContainer();
if(context.eResource() == null) {
context = ConfigurationManager.instance.getContext(context.getName());
Activator.log.warn("No resource for Context : " + context + " ; refreshing the model"); //$NON-NLS-1$ //$NON-NLS-2$
}
URI sectionURI = URI.createURI(section.getSectionFile());
URI baseURI = context.eResource().getURI();
if(PropertiesURIHandler.PROPERTIES_SCHEME.equals(baseURI.scheme())) {
PropertiesURIHandler handler = new PropertiesURIHandler();
baseURI = handler.getConvertedURI(baseURI);
}
sectionURI = sectionURI.resolve(baseURI);
try {
URL url = new URL(sectionURI.toString());
return url;
} catch (IOException ex) {
Activator.log.error(ex);
}
return null;
}
private void layout(Composite parent) {
parent.getParent().getParent().layout();
parent.getParent().layout();
parent.layout();
}
public void removeSection(Composite parent) {
for(Control control : parent.getChildren()) {
control.dispose();
}
layout(parent);
}
}