/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Bob Foster - The color manager idea; XSWT top-level node idea; some other
* important stuff
* David Orme (ASC) - Rewrote: switched to a reflection-based implementation
******************************************************************************/
package com.swtworkbench.community.xswt;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.eclipse.swt.SWT;
import com.swtworkbench.community.xswt.dataparser.DataParser;
/**
* Class StyleParser. This is Chris's original style bit parser and lookup-table
* code, but made general to deal with any class, not just SWT. However, as in
* Chris's initial implementation, the SWT class is still the default class for
* style bit look-ups with no class qualifier. Therefore, the API still
* functions as before for all the SWT.xxx cases.
*
* @author daveo
*/
public class StyleParser {
/*
* A fast way to look up SWT style bit values from their names...
*/
private static final Map mapStyles = new TreeMap();
static {
try {
// Add the SWT class by default. All other classes will be added
// automatically by ClassBuilder the first time they are
// encountered.
StyleParser.registerClassConstants("org.eclipse.swt.SWT");
} catch (XSWTException e) {
e.printStackTrace();
}
}
/**
* Method registerClassConstants. Register all public final int constants
* from className with the StyleParser so that it can look them up quickly.
*
* @param className
* The fully-qualified class name to register
* @throws XSWTException
* If something really bad happens or if the class is not found
*/
public static void registerClassConstants(String className)
throws XSWTException {
Class constantsClass;
try {
constantsClass = Class.forName(className);
registerClassConstants(constantsClass);
} catch (Throwable t) {
throw new XSWTException(t);
}
}
/**
* Method registerClassConstants. Register all public final int constants
* from className with the StyleParser so that it can look them up quickly.
*
* @param className
* The class to register
* @throws XSWTException
* If something really bad happens or if the class is not found
*/
public static void registerClassConstants(Class constantsClass)
throws XSWTException {
TreeMap classStyles = new TreeMap();
try {
Field[] fields = constantsClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (int.class.equals(field.getType())) {
int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers)
&& Modifier.isStatic(modifiers)
&& Modifier.isFinal(modifiers)) {
try {
classStyles.put(field.getName(), field.get(null));
} catch (IllegalAccessException eIllegalAccess) {
}
}
}
}
} catch (Throwable t) {
throw new XSWTException(t);
}
// Register the style bit map under the simple name
StringTokenizer stringTokenizer = new StringTokenizer(constantsClass.getName(), ".");
int tokens = stringTokenizer.countTokens();
String simpleClassName = null;
for (int i = 0; i < tokens; ++i) {
simpleClassName = stringTokenizer.nextToken();
}
mapStyles.put(simpleClassName, classStyles);
}
/**
* Method parse. Parse a style bit string into its int value. Style bit
* strings must be in the following format:
* <p>
*
* Class.STYLE - Returns the value of STYLE in Class <br>
* STYLE - Returns the value of SWT.STYLE <br>
* STYLE1 STYLE2 STYLE3 - Returns SWT.STYLE1 | SWT.STYLE2 | SWT.STYLE3 <br>
* Class.STYLE1 Class.STYLE2 - Returns Class.STYLE1 | Class.STYLE2
* <p>
*
* In all cases "Class" must be a simple (not fully-qualified) class name.
* ie: "SWT" or "GridData".
* <p>
*
* @param source
* The source string
* @return The integer value of the (possibly ored) style bit(s)
* @throws XSWTException
* If we couldn't resolve a style bit constant
*/
public static int parse(String source) throws XSWTException {
return parse(source, null, null);
}
public static int parse(String source, DataParser styleIdParser, List styleIds) throws XSWTException {
if (source == null || source.length() == 0)
return 0;
int style = 0;
StringTokenizer stringTokenizer = new StringTokenizer(source,
" |\t\r\n");
while (stringTokenizer.hasMoreTokens()) {
String token = stringTokenizer.nextToken();
// Break up Class.xxx into Class and xxx
StringTokenizer idScanner = new StringTokenizer(token, ".");
String identifier = idScanner.nextToken();
String qualifier = "";
while (idScanner.hasMoreTokens()) {
qualifier = identifier;
identifier = idScanner.nextToken();
}
int value = 0;
if (identifier.startsWith("'")) {
// convert to a char, e.g. 'N'
value = identifier.charAt(1);
} else {
if (qualifier == "")
qualifier = "SWT"; // Default to SWT.xxx
qualifier = XSWT.upperCaseFirstLetter(qualifier);
// Look up the actual value
TreeMap classStyles = (TreeMap) mapStyles.get(qualifier);
Integer classValue = null;
if (classStyles != null) {
classValue = (Integer)classStyles.get(identifier);
}
if (classValue != null) {
value = classValue.intValue();
} else {
// try parsing it as id reference
Object styleObject = null;
if (styleIdParser != null) {
styleObject = styleIdParser.parse(token, Object.class);
}
if (styleObject == null) {
throw new XSWTException(token + " is not a valid style constant or style ID");
}
if (styleIds != null) {
styleIds.add(styleObject);
}
}
}
style |= value;
}
return style;
}
}