blob: cfa76ef78ffd0c8e63d9bc03fe78d17e29ba4a5f [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.designer.model;
import com.intellij.designer.palette.DefaultPaletteItem;
import com.intellij.designer.palette.PaletteGroup;
import com.intellij.designer.palette.PaletteItem;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Alexander Lobas
*/
public abstract class MetaManager extends ModelLoader {
private static final String META = "meta";
private static final String PALETTE = "palette";
private static final String GROUP = "group";
private static final String NAME = "name";
private static final String ITEM = "item";
private static final String TAG = "tag";
private static final String WRAP_IN = "wrap-in";
private final Map<String, MetaModel> myTag2Model = new HashMap<String, MetaModel>();
private final Map<String, MetaModel> myTarget2Model = new HashMap<String, MetaModel>();
private final List<PaletteGroup> myPaletteGroups = new ArrayList<PaletteGroup>();
private final List<MetaModel> myWrapModels = new ArrayList<MetaModel>();
private Map<Object, Object> myCache = new HashMap<Object, Object>();
protected MetaManager(Project project, String name) {
super(project);
load(name);
}
@Override
protected void loadDocument(Element rootElement) throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
Map<MetaModel, List<String>> modelToMorphing = new HashMap<MetaModel, List<String>>();
for (Element element : rootElement.getChildren(META)) {
loadModel(classLoader, element, modelToMorphing);
}
for (Element element : rootElement.getChild(PALETTE).getChildren(GROUP)) {
loadGroup(element);
}
Element wrapInElement = rootElement.getChild(WRAP_IN);
if (wrapInElement != null) {
for (Element element : wrapInElement.getChildren(ITEM)) {
myWrapModels.add(myTag2Model.get(element.getAttributeValue("tag")));
}
}
for (Map.Entry<MetaModel, List<String>> entry : modelToMorphing.entrySet()) {
MetaModel meta = entry.getKey();
List<MetaModel> morphingModels = new ArrayList<MetaModel>();
for (String tag : entry.getValue()) {
MetaModel morphingModel = myTag2Model.get(tag);
if (morphingModel != null) {
morphingModels.add(morphingModel);
}
}
if (!morphingModels.isEmpty()) {
meta.setMorphingModels(morphingModels);
}
}
}
@NotNull
@SuppressWarnings("unchecked")
protected MetaModel loadModel(ClassLoader classLoader, Element element, Map<MetaModel, List<String>> modelToMorphing) throws Exception {
String modelValue = element.getAttributeValue("model");
Class<RadComponent> model = modelValue == null ? null : (Class<RadComponent>)classLoader.loadClass(modelValue);
String target = element.getAttributeValue("class");
String tag = element.getAttributeValue(TAG);
MetaModel meta = createModel(model, target, tag);
String layout = element.getAttributeValue("layout");
if (layout != null) {
meta.setLayout((Class<RadLayout>)classLoader.loadClass(layout));
}
String delete = element.getAttributeValue("delete");
if (delete != null) {
meta.setDelete(Boolean.parseBoolean(delete));
}
Element presentation = element.getChild("presentation");
if (presentation != null) {
meta.setPresentation(presentation.getAttributeValue("title"), presentation.getAttributeValue("icon"));
}
Element palette = element.getChild("palette");
if (palette != null) {
meta.setPaletteItem(createPaletteItem(palette));
}
Element creation = element.getChild("creation");
if (creation != null) {
meta.setCreation(creation.getTextTrim());
}
Element properties = element.getChild("properties");
if (properties != null) {
loadProperties(meta, properties);
}
Element morphing = element.getChild("morphing");
if (morphing != null) {
modelToMorphing.put(meta, StringUtil.split(morphing.getAttribute("to").getValue(), " "));
}
loadOther(meta, element);
if (tag != null) {
myTag2Model.put(tag, meta);
}
if (target != null) {
myTarget2Model.put(target, meta);
}
return meta;
}
@NotNull
protected MetaModel createModel(Class<RadComponent> model, String target, String tag) throws Exception {
return new MetaModel(model, target, tag);
}
@NotNull
protected DefaultPaletteItem createPaletteItem(Element palette) {
return new DefaultPaletteItem(palette);
}
@NotNull
protected VariationPaletteItem createVariationPaletteItem(PaletteItem paletteItem, MetaModel model, Element itemElement) {
return new VariationPaletteItem(paletteItem, model, itemElement);
}
@NotNull
protected PaletteGroup createPaletteGroup(String name) {
return new PaletteGroup(name);
}
protected void loadProperties(MetaModel meta, Element properties) throws Exception {
Attribute inplace = properties.getAttribute("inplace");
if (inplace != null) {
meta.setInplaceProperties(StringUtil.split(inplace.getValue(), " "));
}
Attribute top = properties.getAttribute("top");
if (top != null) {
meta.setTopProperties(StringUtil.split(top.getValue(), " "));
}
Attribute normal = properties.getAttribute("normal");
if (normal != null) {
meta.setNormalProperties(StringUtil.split(normal.getValue(), " "));
}
Attribute important = properties.getAttribute("important");
if (important != null) {
meta.setImportantProperties(StringUtil.split(important.getValue(), " "));
}
Attribute expert = properties.getAttribute("expert");
if (expert != null) {
meta.setExpertProperties(StringUtil.split(expert.getValue(), " "));
}
Attribute deprecated = properties.getAttribute("deprecated");
if (deprecated != null) {
meta.setDeprecatedProperties(StringUtil.split(deprecated.getValue(), " "));
}
}
protected void loadOther(MetaModel meta, Element element) throws Exception {
}
@NotNull
protected PaletteGroup loadGroup(Element element) throws Exception {
PaletteGroup group = createPaletteGroup(element.getAttributeValue(NAME));
for (Element itemElement : element.getChildren(ITEM)) {
MetaModel model = getModelByTag(itemElement.getAttributeValue(TAG));
PaletteItem paletteItem = model.getPaletteItem();
if (!itemElement.getChildren().isEmpty()) {
// Replace the palette item shown in the palette; it might provide a custom
// title, icon or creation logic (and this is done here rather than in the
// default palette item, since when loading elements back from XML, there's
// no variation matching. We don't want for example to call the default
// LinearLayout item "LinearLayout (Horizontal)", since that item would be
// shown in the component tree for any <LinearLayout> found in the XML, including
// those which set orientation="vertical". In the future, consider generalizing
// this such that the {@link MetaModel} can hold multiple {@link PaletteItem}
// instances, and perform attribute matching.
if (itemElement.getAttribute("title") != null) {
paletteItem = createVariationPaletteItem(paletteItem, model, itemElement);
}
group.addItem(paletteItem);
for (Element grandChild : itemElement.getChildren(ITEM)) {
group.addItem(createVariationPaletteItem(paletteItem, model, grandChild));
}
}
else {
group.addItem(paletteItem);
}
}
myPaletteGroups.add(group);
return group;
}
@SuppressWarnings("unchecked")
public <K, V> Map<K, V> getCache(Object key) {
return (Map<K, V>)myCache.get(key);
}
public void setCache(Object key, Object value) {
myCache.put(key, value);
}
@Nullable
public MetaModel getModelByTag(String tag) {
return myTag2Model.get(tag);
}
@Nullable
public MetaModel getModelByTarget(String target) {
return myTarget2Model.get(target);
}
public List<MetaModel> getWrapInModels() {
return myWrapModels;
}
public List<PaletteGroup> getPaletteGroups() {
return myPaletteGroups;
}
}