/***************************************************************************** * 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.customization.properties.generation.layout; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.papyrus.customization.properties.generation.Activator; import org.eclipse.papyrus.customization.properties.generation.generators.IGenerator; import org.eclipse.papyrus.customization.properties.generation.messages.Messages; import org.eclipse.papyrus.views.properties.contexts.ContextsFactory; import org.eclipse.papyrus.views.properties.contexts.Property; import org.eclipse.papyrus.views.properties.contexts.Section; import org.eclipse.papyrus.views.properties.contexts.View; import org.eclipse.papyrus.views.properties.environment.CompositeWidgetType; import org.eclipse.papyrus.views.properties.environment.LayoutType; import org.eclipse.papyrus.views.properties.environment.Namespace; import org.eclipse.papyrus.views.properties.environment.Type; import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager; import org.eclipse.papyrus.views.properties.ui.CompositeWidget; import org.eclipse.papyrus.views.properties.ui.Layout; import org.eclipse.papyrus.views.properties.ui.PropertyEditor; import org.eclipse.papyrus.views.properties.ui.UiFactory; import org.eclipse.papyrus.views.properties.ui.ValueAttribute; import org.eclipse.papyrus.views.properties.util.PropertiesUtil; /** * Default implementation for ILayoutGenerator * PropertyEditors are grouped by their property type (Strings, booleans, ...) * Boolean and integer sections have two columns, while the other ones have only one columns * * All multiple value editors are displayed after all the single value editors. * * @author Camille Letavernier */ public class StandardLayoutGenerator implements ILayoutGenerator { protected final TreeMap<Category, List<PropertyEditor>> editorsByCategory = new TreeMap<Category, List<PropertyEditor>>(); protected final Set<Namespace> namespaces = new HashSet<Namespace>(); public synchronized List<Section> layoutElements(List<PropertyEditor> editors, View parent) { editorsByCategory.clear(); namespaces.clear(); namespaces.addAll(ConfigurationManager.instance.getBaseNamespaces()); sortEditors(editors); Section section = createSection(parent); for(Map.Entry<Category, List<PropertyEditor>> mapping : editorsByCategory.entrySet()) { Category category = mapping.getKey(); List<PropertyEditor> categorizedEditors = mapping.getValue(); CompositeWidget container = layoutCategorizedEditors(category, categorizedEditors); section.getWidget().getWidgets().add(container); } return Collections.singletonList(section); } protected CompositeWidget layoutCategorizedEditors(Category category, List<PropertyEditor> editors) { CompositeWidgetType compositeType = ConfigurationManager.instance.getDefaultCompositeType(); LayoutType propertiesLayoutType = ConfigurationManager.instance.getDefaultLayoutType(); CompositeWidget container = UiFactory.eINSTANCE.createCompositeWidget(); container.setWidgetType(compositeType); Layout layout = UiFactory.eINSTANCE.createLayout(); container.setLayout(layout); ValueAttribute numColumns = UiFactory.eINSTANCE.createValueAttribute(); numColumns.setName("numColumns"); //$NON-NLS-1$ numColumns.setValue(category.getNumColumns().toString()); layout.getAttributes().add(numColumns); layout.setLayoutType(propertiesLayoutType); container.getWidgets().addAll(editors); return container; } protected void sortEditors(List<PropertyEditor> editors) { for(PropertyEditor editor : editors) { Category category = new Category(editor.getProperty()); getByCategory(category).add(editor); if(editor.getWidgetType() == null) { Activator.log.warn(String.format("Editor for property %s doesn't have a WidgetType", editor.getProperty().getName())); //$NON-NLS-1$ continue; } namespaces.add(editor.getWidgetType().getNamespace()); } } protected Section createSection(View parent) { CompositeWidget sectionRoot = createSectionRoot(); Section section = ContextsFactory.eINSTANCE.createSection(); section.setName(parent.getName()); section.setSectionFile(String.format("ui/%s.xwt", section.getName().replaceAll(" ", ""))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ URI compositeURI = URI.createURI(section.getSectionFile()); compositeURI = compositeURI.resolve(parent.eResource().getURI()); Resource resource = parent.eResource().getResourceSet().createResource(compositeURI); section.setWidget(sectionRoot); resource.getContents().add(sectionRoot); return section; } protected CompositeWidget createSectionRoot() { CompositeWidgetType compositeType = ConfigurationManager.instance.getDefaultCompositeType(); namespaces.add(compositeType.getNamespace()); LayoutType propertiesLayoutType = ConfigurationManager.instance.getDefaultLayoutType(); namespaces.add(propertiesLayoutType.getNamespace()); CompositeWidget sectionRoot = UiFactory.eINSTANCE.createCompositeWidget(); sectionRoot.setWidgetType(compositeType); Layout layout = UiFactory.eINSTANCE.createLayout(); layout.setLayoutType(propertiesLayoutType); sectionRoot.setLayout(layout); sectionRoot.getAttributes().addAll(createNamespaces(namespaces)); return sectionRoot; } protected List<ValueAttribute> createNamespaces(Collection<Namespace> namespaces) { List<ValueAttribute> xmlNamespaces = new LinkedList<ValueAttribute>(); for(Namespace namespace : namespaces) { if(namespace == null) { continue; } ValueAttribute attribute = UiFactory.eINSTANCE.createValueAttribute(); attribute.setName(PropertiesUtil.getQualifiedName(namespace)); attribute.setValue(PropertiesUtil.getPrefixedValue(namespace)); xmlNamespaces.add(attribute); } return xmlNamespaces; } protected List<PropertyEditor> getByCategory(Category category) { if(!editorsByCategory.containsKey(category)) { editorsByCategory.put(category, new LinkedList<PropertyEditor>()); } return editorsByCategory.get(category); } protected class Category implements Comparable<Category> { public Type editorType; public int multiplicity; public Integer getNumColumns() { switch(editorType) { case BOOLEAN: return 2; case ENUMERATION: return 1; case INTEGER: return 2; case REFERENCE: return 1; case STRING: return 1; } return 1; //Cannot happen } public Category(Property property) { this.editorType = property.getType(); this.multiplicity = property.getMultiplicity(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((editorType == null) ? 0 : editorType.hashCode()); result = prime * result + multiplicity; return result; } @Override public boolean equals(Object obj) { if(this == obj) { return true; } if(obj == null) { return false; } if(!(obj instanceof Category)) { return false; } Category other = (Category)obj; if(!getOuterType().equals(other.getOuterType())) { return false; } if(editorType != other.editorType) { return false; } if(multiplicity != other.multiplicity) { return false; } return true; } public int compareTo(Category category) { if(category == null) { return -1; } if(category.multiplicity != multiplicity) { return multiplicity == 1 ? -1 : 1; } int result = getTypeIndex().compareTo(category.getTypeIndex()); return result; } public Integer getTypeIndex() { int i = 0; for(Type type : orderedTypes) { if(type == editorType) { return i; } i++; } return orderedTypes.length; } @Override public String toString() { return (multiplicity == 1 ? "Single" : "Multiple") + editorType.toString(); //$NON-NLS-1$ //$NON-NLS-2$ } private StandardLayoutGenerator getOuterType() { return StandardLayoutGenerator.this; } } /** * The order in which the types are displayed */ public static Type[] orderedTypes = new Type[]{ Type.STRING, Type.BOOLEAN, Type.INTEGER, Type.ENUMERATION, Type.REFERENCE }; public String getName() { return Messages.StandardLayoutGenerator_name; } public void setGenerator(IGenerator generator) { //Ignored } }