/*******************************************************************************
* Copyright (c) 2008 Ralf Ebert
* 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:
* Ralf Ebert - initial API and implementation
*******************************************************************************/
package com.swtxml.swt.types;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Layout;
import com.swtxml.swt.SwtInfo;
import com.swtxml.util.parser.KeyValueParser;
import com.swtxml.util.parser.ParseException;
import com.swtxml.util.parser.Strictness;
import com.swtxml.util.properties.ClassProperties;
import com.swtxml.util.properties.IInjector;
import com.swtxml.util.properties.PropertiesContentAssist;
import com.swtxml.util.proposals.Match;
import com.swtxml.util.reflector.ReflectorException;
import com.swtxml.util.types.IContentAssistable;
import com.swtxml.util.types.IType;
public class LayoutType implements IType<Layout>, IContentAssistable {
private static final String LAYOUT_KEY = "layout";
// TODO: use classes.txt file (same as for widgets)
private final String[] LAYOUTS = new String[] { "fill", "row", "grid", "form" };
private final static String SWT_LAYOUT_PACKAGE = RowLayout.class.getPackage().getName();
public Layout convert(String value) {
return convert(value, Strictness.STRICT);
}
public Layout convert(String value, Strictness strictness) {
Map<String, String> layoutConstraints = KeyValueParser.parse(value, strictness);
String layoutName = layoutConstraints.remove(LAYOUT_KEY);
if (layoutName == null) {
if (strictness == Strictness.STRICT) {
throw new ParseException("no layout specified");
} else {
return null;
}
}
Layout layout = createLayout(layoutName, Strictness.STRICT);
IInjector injector = SwtInfo.LAYOUT_PROPERTIES.getProperties(layout.getClass())
.getInjector(layout);
injector.setPropertyValues(layoutConstraints);
return layout;
}
private Layout createLayout(String layoutName, Strictness strictness) {
try {
return getLayoutClass(layoutName, strictness).newInstance();
} catch (Exception e) {
if (strictness == Strictness.STRICT) {
throw new ReflectorException(e);
}
return null;
}
}
@SuppressWarnings("unchecked")
private Class<? extends Layout> getLayoutClass(String layoutName, Strictness strictness) {
String className = SWT_LAYOUT_PACKAGE + "." + StringUtils.capitalize(layoutName) + "Layout";
try {
return (Class<? extends Layout>) Class.forName(className);
} catch (Exception e) {
if (strictness == Strictness.STRICT) {
throw new ReflectorException(e);
}
return null;
}
}
public List<Match> getProposals(Match match) {
// TODO: this is a bit messy at the moment, because only the class
// property definition is used for completion, so we have to smuggle the
// "special" layout selector property in
// maybe: separate namespace layout:[grid]=""
PropertiesContentAssist assist = new PropertiesContentAssist() {
@Override
protected ClassProperties<?> getClassProperties(Map<String, String> values) {
String layoutName = values.get("layout");
if (layoutName == null) {
return null;
}
Class<? extends Layout> layoutClass = getLayoutClass(layoutName, Strictness.NICE);
if (layoutClass == null) {
return null;
}
return SwtInfo.LAYOUT_PROPERTIES.getProperties(layoutClass);
}
@Override
protected List<Match> keyProposals(Map<String, String> values, Match match) {
if (getClassProperties(values) == null) {
return match.propose(LAYOUT_KEY + ":");
}
return super.keyProposals(values, match);
}
@Override
protected List<Match> valueProposals(Map<String, String> values, String key, Match match) {
if ("layout".equals(key.toLowerCase())) {
return match.propose(LAYOUTS);
}
return super.valueProposals(values, key, match);
}
};
return assist.getProposals(match);
}
}