|
From: Harry E. <har...@us...> - 2006-09-18 07:59:09
|
Update of /cvsroot/synclast/client/src/com/synclast In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv31295/src/com/synclast Modified Files: StyleSheet.java Styled.java Added Files: SynclastException.java Log Message: This is a complete revamp of the style mechanism in Synclast. The new mechanism works kind alike CSS layer 1 applied to widgets. You create a stylesheet with a string of text that looks like a css file (see examples/SynclastUIDemo/res/*.css for examples). You set the Stylesheet on a canvas. Widgets added to that canvas will automatically pick up the styling information assoiciated with that canvas. Styles cascade according to containment, ie, if a widget doe not have a background color style but its parent does, it will get the same background. Some styles cascade, and some do not. Styles only set the "default" values for a widget. Basically, calling set() to set a widget property wil ALWAYS override any value in the stylesheet. Stylesheets can be set on a canvas before or after it is constructed, and all widgets should end up properly getting styled in either case. This means you can also change the stylesheet on a canvas at any time you want. Since Stylesheets are just parsed from a string, they can come from anywhere (the jar, constructed on the fly, downloaded from the network, etc). Though Styles are designed to be efficient, treat them with care since very complicated pages might need non trivial time to derive all their values. Style documentation on each widget still needs to be added, along with default value and cascade information. Right now, the code IS the documentation in this regard. Please report bugs as you find them. Index: StyleSheet.java =================================================================== RCS file: /cvsroot/synclast/client/src/com/synclast/StyleSheet.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** StyleSheet.java 6 Oct 2004 22:51:48 -0000 1.12 --- StyleSheet.java 18 Sep 2006 07:59:04 -0000 1.13 *************** *** 1,257 **** - /* - $Id$ - - This file is part of the Synclast UI API. - - The Synclast UI API is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - The Synclast UI API is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the Synclast UI API; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ package com.synclast; import java.util.Vector; import javax.microedition.lcdui.Font; /** ! * Provides a simple mechanism for setting user interface styles ! * that can be applied to objects that implement the Styled interface. ! * <P> ! * The toolkit has a default stylesheet that Styled classes may ! * register their default settings with (typically in a static ! * initialization block). ! * <P> ! * For simplicity and minimal size, all styles are defined in terms of ! * integer values. A class implementing Styled is free to choose ! * arbitrary constants for both properties and values; a suggested ! * convention is the use of "public static final int" constant ! * declarations. In addition, this class provides a pair of utility ! * methods for converting MIDP Font objects to and from integers. ! * <P> ! * Sample usage: ! * <pre> ! * StyleSheet sheet = new StyleSheet(); ! * sheet.setStyle(ColoredWidget.class, // or ._class for MIDP 1.0 ! * ColoredWidget.BORDER_COLOR, Color.BLUE) ! * .setStyle(InputWidget.class, InputWidget.BORDER_COLOR, ! * Color.GREEN); ! * SynclastCanvas myCanvas = new SynclastCanvas(sheet); ! * </pre> */ public class StyleSheet { ! private static StyleSheet DEFAULT; ! /** Returns the current default stylesheet. */ ! public static synchronized StyleSheet getDefault() { ! if (DEFAULT == null) { ! DEFAULT = new StyleSheet("Default"); } - return DEFAULT; } ! /** Sets the current default stylesheet. */ ! public static void setDefault(StyleSheet newDefault) { ! DEFAULT = newDefault; ! } ! ! // Parallel vectors (order is important) ! private Vector classes = new Vector(); ! // Vector of Vectors ! private Vector styleSets = new Vector(); ! ! /** ! * Creates a new style sheet based on the default style sheet. ! */ ! public StyleSheet() { ! this(getDefault()); } ! /** ! * Creates a new style sheet by looking up settings from the MIDlet ! * environment. ! */ ! public StyleSheet(String name) { ! String styles = SynclastManager.getProperty("Style-" + name); ! int p1, p2, p3, pos = 0; ! ! if (styles != null) { ! ! // This is the most inelegant code I've written in a long ! // time. Please help me improve it. ! // The format is "ClassName1:propNo1=value1,propNo2=value2;ClassName2:propNo1=value1[,...;...] ! do { ! p1 = styles.indexOf(';', pos); ! p2 = styles.indexOf(':', pos); ! Class clazz = null; ! try { ! clazz = Class.forName(styles.substring(pos, p2)); ! } catch (Exception e) { ! e.printStackTrace(); ! } ! p3 = p2 + 1; ! pos = p1; ! if (pos == -1) { pos = styles.length(); } ! do { ! p3 = styles.indexOf(',', p2 + 1); ! String nameVal; ! if ((p3 != -1) && (p3 < pos)) { ! nameVal = styles.substring(p2 + 1, p3); ! } else { ! if (p1 != -1) { ! nameVal = styles.substring(p2 + 1, p1); ! } else { ! nameVal = styles.substring(p2 + 1); ! } ! } ! ! // Now split nameVal... ! int p4 = nameVal.indexOf('='); ! // Set the indicated style ! setStyle(clazz, ! Integer.parseInt(nameVal.substring(0,p4)), ! Integer.parseInt(nameVal.substring(p4+1))); ! ! p2 = p3; ! } while ((p3 != -1) && (p3 < pos)); ! pos = p1 + 1; ! } while (p1 != -1); } } /** ! * Creates a new style sheet with the given source style sheet. */ ! public StyleSheet(StyleSheet source) { ! if (source != null) { ! update(source); ! } } /** ! * Copies all the values from the other stylesheet into this one. */ ! public void update(StyleSheet other) { ! int len = other.classes.size(); ! for (int i = 0; i < len; i++) { ! Class type = (Class) other.classes.elementAt(i); ! Vector styles = (Vector) other.styleSets.elementAt(i); ! int jlen = styles.size(); ! for (int j = 0; j < jlen; j++) { ! int[] propVal = (int[]) styles.elementAt(j); ! setStyle(type, propVal[0], propVal[1]); } } ! } ! ! /** ! * Sets a single style property to the designated value. The ! * value will be applied to instances of the specified Java class ! * and its subclasses only. ! */ ! public synchronized StyleSheet setStyle(Class type, int property, int value) { ! int pos = classes.indexOf(type); ! Vector styles; ! if (pos == -1) { ! // Need to add a new entry to both vectors ! int len = classes.size(); ! Class clazz; ! while (++pos < len) { ! // Insert it BEFORE anything that is a subclass of it. ! clazz = (Class) classes.elementAt(pos); ! if (type.isAssignableFrom(clazz)) { break; - } } ! classes.insertElementAt(type, pos); ! styles = new Vector(); ! styleSets.insertElementAt(styles, pos); ! } else { ! styles = (Vector) styleSets.elementAt(pos); ! } ! // There can be only one entry for a given Class/property combo ! int vlen = styles.size(); ! int j = 0; ! for (; j < vlen; j++) { ! int[] style = (int[]) styles.elementAt(j); ! if (style[0] == property) { ! style[1] = value; ! return this; } } ! styles.addElement(new int[] { property, value }); ! return this; } ! ! /** ! * Convenience method. Equivalent to calling ! * setStyle(type, property, StyleSheet.getFontValue(font)). */ ! public StyleSheet setStyle(Class type, int property, Font font) { ! return setStyle(type, property, getFontValue(font)); } /** ! * Retrieves the style value for the designated class and property. ! * If no value has been registered, the constant -1 is returned. */ ! public int getStyle(Class type, int property) { ! int pos = classes.indexOf(type); ! if (pos == -1) { ! Vector v = (Vector) styleSets.elementAt(pos); ! int len = v.size(); ! int[] style; ! for (int i = 0; i < len; i++) { ! style = (int[]) v.elementAt(i); ! if (style[0] == property) { ! return style[1]; ! } ! } } - return -1; } /** ! * Applies this stylesheet to the argument object. ! * This will trigger 0 or more calls to Styled.setDefault(property, value) ! * depending on the properties that have been registered with this ! * stylesheet for the particular Styled class. */ ! public void applyTo(Styled styled) { ! int len = classes.size(); ! for (int i = 0; i < len; i++) { ! Class clazz = (Class) classes.elementAt(i); ! if (clazz.isAssignableFrom(styled.getClass())) { ! Vector v = (Vector) styleSets.elementAt(i); ! int vlen = v.size(); ! for (int j = 0; j < vlen; j++) { ! int[] style = (int[]) v.elementAt(j); ! styled.setDefault(style[0], style[1]); ! } ! } ! } } /** ! * Returns a single int representing a MIDP Font, for ! * use with font style properties. */ ! public static int getFontValue(Font font) { ! return font.getStyle() | font.getSize() | font.getFace(); } /** ! * Returns the font represented by an integer value, the ! * inverse operation of getFontValue(). */ ! public static Font getFont(int value) { ! return Font.getFont(value & 96, value & 7, value & 24); } } --- 1,426 ---- package com.synclast; + import com.synclast.SynclastException; + import com.synclast.Styled; + import java.io.InputStreamReader; + import java.io.IOException; + import java.util.Hashtable; import java.util.Vector; import javax.microedition.lcdui.Font; /** ! * New StyleSheet mechanism for synclast. This class handles "CSS-like" styles of the format: ! <pre> ! [ ! [whitespace|newline]*[type_name(not whitespace or newline)][whitespace]*[{] ! [ ! [whitespace|newline]*[style_name(not whitespace or newline)][whitespace]*[:] ! [whitespace(not newline)*][style_value(not whitespace or newline)][;] ! ]* ! [whitespace|newline]*[}] ! [whitespace|newline]* ! ] ! </pre> ! For example: ! <pre> ! label { ! font-size: small; font-style: bold,underline; ! background-color: 0xff0000; ! } ! box { ! background-color: 0x00ff00; ! color: 0x000000; ! border-width: 2; ! } ! .foo { background-color: ffffff; border-color: 000000; } ! .bar { color: 0x0000ff; border-width: 1; border-color: 0x0f0f0f;} ! </pre> ! This should give you an idea about what type of formatting is allowed in stylesheets.<br/> ! Stylesheets are created by setting the string value of the stylesheet to be parsed in the constructor of the stylesheet. Other mechanisms can handle loading stylesheets from elsewhere, such as reading the value from the network or a jar, and then using the resulting string to create a stylesheet.<br/> ! Stylesheets can only be set on a SynclastCanvas. This automatically makes it available to all the widgets placed on that canvas. Setting a new stylesheet on a canvas will cause all widgets on that canvas to get the new value in that stylesheet, and forget all their old values. Since styles can effect sizing, this also causes all widgets and containers to re-layout themselves. Since this can be a relatively expensive operation, use with care. Also, since paint can be called at any time, it is recommended that you do not set a new stylesheet on a displayed canvas, since intermediate values might also be displayed (race condition).<br/> ! Widgets by default get their styles based on the styleName they declare (getStyleName). If a particular style is not found, the same value will be looked for in the container containing this widget, recursively. <code>label</code> and <code>box</code> are examples of this way of declaring styles. You may also specify that a widget get special styling by setting a <code>classStyleName</code> (<code>widget.setClassStyleName(String)</code>). This will be looked at before the standard style information for that widget. <code>.foo</code> and <code>.bar</code> are examples of this way of declaring styles. Please note that you declare a <code>classStyleName</code> in the stylesheet as <i><code>.foo</code></i> but you set it on a widget as <code>setCLassStyleName("foo")</code>. In addition, classStyleNames also cascade. The full rule set for finding the style for a widget follows these steps: ! <ol> ! <li>For each style:<ol> ! <li>Get value for classStyleName</li> ! <li>If value is null, get value for styleName</li> ! <li>if value is null, get container</li> ! <li>repeat above until non null value, or null container</li> ! <li>if value is null, use Style default value</li> ! <li>invalidate self</li> ! </ol> ! <li>If container, repeat for all contained widgets</li> ! </ol> ! Using the stylesheet above, if you have the following code snippet: ! <pre> ! BoxContainer parentBox = new BoxContainer(Graphics.LEFT); ! BoxContainer childBox = new BoxContainer(Graphics.TOP); ! Label label = new Label("Hello"); ! parentBox.add(childBox); ! childBox.add(label); ! </pre> ! (assuming parentBox is added to a SynclastCanvas), then <code>label</code> would have the following values: ! <ul> ! <li>font-size: small</li> ! <li>font-style: bold,underline</li> ! <li>background-color: 0xff0000</li> ! <li>color: 0x000000</li> ! <li>border-width: 2</li> ! </ul> ! However, if we add: ! <pre> ! label.setClassStyleName("foo"); ! </pre> ! the <code>label</code> properties now look like: ! <ul> ! <li>font-size: small</li> ! <li>font-style: bold,underline</li> ! <li><b>background-color: ffffff</b>(changed value due to .foo)</li> ! <li>color: 0x000000</li> ! <li>border-width: 2</li> ! <li><b>border-color: 000000</b>(new value from .foo)</li> ! </ul> ! and if we add: ! <pre> ! childBox.setClassStyleName("bar"); ! </pre> ! the <code>label</code> properties now look like: ! <ul> ! <li>font-size: small</li> ! <li>font-style: bold,underline</li> ! <li>background-color: ffffff</li> ! <li><b>color: 0x0000ff</b>(value from .bar on childbox)</li> ! <li><b>border-width: 1</b>(value from .bar on childbox)</li> ! <li><b>border-color: 000000</b>(does not change because value from .foo on label is more specific than value from .bar on childbox)</li> ! </ul> ! <code>classStyleName</code>s can be set on any widget. <code>styleName</code>s are declared by each non abstract widget. The name a widget uses for the StyleSheet, and the set of styles a widget declares, are documented on each widget. For a detailed description of how to make new styles for a widget subclass, see <code>Style</code>.<br> ! Normal usage is: ! <pre> ! //... read stylesheet string from somewhere (jar, network, etc)... ! StyleSheet styleSheet = new StyleSheet(styleSheetString); ! mySynclastCanvas.setStyleSheet(styleSheet); ! //... add widgets, which will automatically get styles from stylesheet ... ! //... display mySynclastCanvas ... ! </pre> ! @author Harry Evans ! */ public class StyleSheet { ! private static StyleSheet DEFAULT_STYLESHEET = null; ! private Hashtable styleMap; ! /** ! * Create a new stylesheet with a String that conforms to the StyleSheet syntax. ! * @param String the stylesheet String to parse for styles. ! */ ! public StyleSheet(String css) { ! styleMap = parseCss(css); ! if(DEFAULT_STYLESHEET == null) { ! DEFAULT_STYLESHEET = this; } } ! public StyleSheet(Class clazz, String resourceName) { ! this(readResource(clazz, resourceName)); } ! protected static String readResource(Class clazz, String resourceName) { ! try { ! InputStreamReader reader = new InputStreamReader(clazz.getResourceAsStream(resourceName)); ! int length = 0; ! char[] charArray = new char[128]; ! StringBuffer buf = new StringBuffer(); ! while((length = reader.read(charArray)) != -1) { ! buf.append(charArray, 0, length); ! } ! reader.close(); ! return buf.toString(); ! } catch(IOException e) { ! throw new SynclastException("Error reading resource. Class: " + clazz.getName() + " resourceName: " + resourceName, e); } } + /** Internal parse state constant */ + protected static final int STATE_START_STYLE = 1; + /** Internal parse state constant */ + protected static final int STATE_STYLE = 7; + /** Internal parse state constant */ + protected static final int STATE_END_STYLE = 2; + /** Internal parse state constant */ + protected static final int STATE_START_NAME = 3; + /** Internal parse state constant */ + protected static final int STATE_NAME = 8; + /** Internal parse state constant */ + protected static final int STATE_END_NAME = 4; + /** Internal parse state constant */ + protected static final int STATE_START_VALUE = 5; + /** Internal parse state constant */ + protected static final int STATE_VALUE = 9; + /** Internal parse state constant */ + protected static final int STATE_END_VALUE = 6; + /** Internal parse state constant */ + protected static final int STATE_ERROR = -1; + /** ! * Internal helper method to get the set of parsed styles */ ! protected Hashtable getStyleMap() { ! return styleMap; } /** ! * Main parse method for turning a stylesheet string into a set of styles to be used by widgets. This is very delicate. Modify at your own risk. Parsing errors will be printed on System.err, and the input ignored. ! * @param css the string to parse. ! * @return the Hashtable containing the parsed styles. */ ! protected static Hashtable parseCss(String css) { ! Hashtable map = new Hashtable(); ! StringBuffer style = null; ! StringBuffer name = null; ! StringBuffer value = null; ! String errorString = null; ! int idx = 0; ! int length = css.length(); ! int state = STATE_START_STYLE; ! char currentChar = 'z'; ! for(idx = 0; idx < length && STATE_ERROR != state; idx++) { ! currentChar = css.charAt(idx); ! //state machine ! switch(state) { ! case STATE_START_STYLE: ! if(!isWhitespace(currentChar) && !isNewline(currentChar)) { ! style = new StringBuffer().append(currentChar); ! state = STATE_STYLE; ! } ! //ignore whitespace and newlines ! break; ! case STATE_STYLE: ! if( '{' == currentChar) { ! //style name done ! state = STATE_START_NAME; ! } else if(isNewline(currentChar)) { ! errorString = "Newline after style without '{'"; ! state = STATE_ERROR; ! } else if(!isWhitespace(currentChar)) { ! style.append(currentChar); ! } else { ! state = STATE_END_STYLE; ! } ! break; ! case STATE_END_STYLE: ! if( '{' == currentChar) { ! state = STATE_START_NAME; ! } else if(!isWhitespace(currentChar)) { ! errorString = "Newline after style without '{'"; ! state = STATE_ERROR; ! } ! //ignore whitespace ! break; ! case STATE_START_NAME: ! if( '}' == currentChar) { ! state = STATE_START_STYLE; ! } else if(!isWhitespace(currentChar) && !isNewline(currentChar)) { ! name = new StringBuffer().append(currentChar); ! state = STATE_NAME; ! } ! //ignore whitespace and newline ! break; ! case STATE_NAME: ! if( ':' == currentChar) { ! state = STATE_START_VALUE; ! } else if(isNewline(currentChar)) { ! errorString = "Newline after name without ':'"; ! state = STATE_ERROR; ! } else if(!isWhitespace(currentChar)) { ! name.append(currentChar); ! } else { ! state = STATE_END_NAME; ! } ! break; ! case STATE_END_NAME: ! if( ':' == currentChar) { ! state = STATE_START_VALUE; ! } else if(!isWhitespace(currentChar)) { ! //newline or character is an error ! errorString = "Newline after name without ':'"; ! state = STATE_ERROR; ! } ! //ignore whitespace ! break; ! case STATE_START_VALUE: ! if(isNewline(currentChar)) { ! errorString = "Newline after ':' without value"; ! state = STATE_ERROR; ! } else if( !isWhitespace(currentChar)) { ! value = new StringBuffer().append(currentChar); ! state = STATE_VALUE; ! } ! //ignore whitespace ! break; ! case STATE_VALUE: ! if( ';' == currentChar) { ! storeStyleNameValue(map, style, name, value); ! state = STATE_START_NAME; ! } else if(isNewline(currentChar)) { ! errorString = "Newline after value without ';'"; ! state = STATE_ERROR; ! } else if(!isWhitespace(currentChar)) { ! value.append(currentChar); ! } else { ! state = STATE_END_VALUE; ! } ! break; ! case STATE_END_VALUE: ! if( ';' == currentChar) { ! storeStyleNameValue(map, style, name, value); ! state = STATE_START_NAME; ! } else if(isNewline(currentChar)) { ! errorString = "Newline after value without ';'"; ! state = STATE_ERROR; ! } else if(!isWhitespace(currentChar)) { ! errorString = "Text after whitespace in value (expected ';')"; ! state = STATE_ERROR; ! } ! //ignore whitespace ! break; ! default: ! //hitting default is an error ! errorString = "Unknown error (Shouldn't get here)"; ! state = STATE_ERROR; ! break; } } ! if(STATE_START_STYLE != state) { ! switch(state) { ! case STATE_STYLE: ! case STATE_END_STYLE: ! errorString = "style has no '{'"; ! break; ! case STATE_START_NAME: ! errorString = "Missing '}' on style"; ! break; ! case STATE_NAME: ! case STATE_END_NAME: ! errorString = "File ends in name (no ':', value, ';' or '}')"; ! break; ! case STATE_START_VALUE: ! errorString = "File ends after name's ':' (no value, ';' or '}')"; ! break; ! case STATE_VALUE: ! case STATE_END_VALUE: ! errorString = "File ends after value (no ';' or '}')"; ! break; ! case STATE_ERROR: ! //should have already set errorString ! break; ! default: ! errorString = "Unknown state on exit"; break; } ! //error condition. throw exception ! StringBuffer buf = new StringBuffer("Exiting parsing in invalid state."); ! buf.append("\nReason:").append(errorString); ! buf.append("\nState: ").append(state); ! buf.append("\nStyle: ").append((style == null) ? "null" : style.toString()); ! buf.append("\nName: ").append((name == null) ? "null" : name.toString()); ! buf.append("\nValue: ").append((value == null) ? "null" : value.toString()); ! buf.append("\nchar: "); ! if(isNewline(currentChar)) { ! buf.append("<newline>"); ! } else if(isWhitespace(currentChar)) { ! buf.append("<whitespace>"); ! } else { ! buf.append(currentChar); } + buf.append("\nindex: ").append(idx); + // throw new SynclastException(buf.toString()); + //Throwing an exception seems pretty heavy weight and unexpected. + //Instead we will print an error to standard error, and return an + //empty map. Stuff will still run, but not be styled by the input + //we got. + System.err.println("StyleSheet Parsing error. No values will be stored in stylesheet. Error: " + buf.toString()); + map.clear(); + return map; + } ! return map; } ! /** ! * Helper method for parsing stylesheet string */ ! protected static boolean isWhitespace(char c) { ! switch(c) { ! case ' ': ! case '\t': ! return true; ! default: ! return false; ! } } /** ! * Helper method for parsing stylesheet string */ ! protected static boolean isNewline(char c) { ! switch(c) { ! case '\r': ! case '\n': ! return true; ! default: ! return false; } } /** ! * Helper method for parsing stylesheet string */ ! protected static void storeStyleNameValue(Hashtable map, StringBuffer style, StringBuffer name, StringBuffer value) { ! String key = style.toString() + "/" + name.toString(); ! map.put(key, value.toString()); } /** ! * Principal method for get values from the stylesheet. This value returns the "raw" string value from the parsed stylesheet string. It is up to the caller (usually style) to parse this string value into a usable form (usually an int). Usually it is an error to call this method directly. You should instead be calling Style.set(Widget) or Style.get(Widget), and letting the Style class handle value parsing. This method also does all the cascade logic for fetching the style value, including both styleName and classStyleName, and all container calls. ! * @param name the name of the style to fetch ("font-style") ! * @param widget the widget this style is for ("Label") ! * @return the "raw" String value for this style. */ ! public String getStyleValue(String name, boolean cascade, Styled widget) { ! //We'll end up looping through the containment hierarchy for each ! //call to this. Previous implementation generated a list of the ! //style names in reverse containment order, that could be used for ! //each call. This made the call slightly faster, but created an ! //additional vector for each widget, making it somewhat expensive ! //memory wise. Gotta love tradeoffs ! Styled currentWidget = widget; ! //preallocate loop variables ! String value = null; ! String classStyleSelector = null; ! while(currentWidget != null) { ! //first with classStyle, then with styleName ! //since we don't track classStyles already checked, ! //we might check the same one on every loop. This is the same as ! //remembering, and having to check THAT list, and this way uses less ! //memory ! classStyleSelector = currentWidget.getClassStyleName(); ! if(classStyleSelector != null) { ! value = (String)styleMap.get("." + classStyleSelector + "/" + name); ! if(value != null) return value; ! } ! value = (String)styleMap.get(currentWidget.getStyleName() + "/" + name); ! if(value != null) return value; ! else if(!cascade) return value; ! //if we hit !cascade we are probably null, but whatever :) ! currentWidget = currentWidget.getCascadeContainer(); ! //classStyleSelector will be nulled by next call, if applicable ! //value has to be null if we reached here ! } ! return null; } /** ! * Get the default stylesheet. Useful only if you set a default stylesheet. ! * @return the default stylesheet, or null. */ ! public static StyleSheet getDefault() { ! return DEFAULT_STYLESHEET; } } --- NEW FILE: SynclastException.java --- package com.synclast; public class SynclastException extends RuntimeException { protected Throwable cause; public SynclastException() { super(); } public SynclastException(String message) { super(message); } public SynclastException(Throwable cause) { super(); this.cause = cause; } public SynclastException(String message, Throwable cause) { super(message); this.cause = cause; } public void printStackTrace() { super.printStackTrace(); if(cause != null) { System.err.println("Caused by:"); cause.printStackTrace(); } } } Index: Styled.java =================================================================== RCS file: /cvsroot/synclast/client/src/com/synclast/Styled.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** Styled.java 19 Sep 2003 06:51:09 -0000 1.5 --- Styled.java 18 Sep 2006 07:59:04 -0000 1.6 *************** *** 32,34 **** --- 32,37 ---- */ public void setDefault(int property, int value); + public Styled getCascadeContainer(); + public String getStyleName(); + public String getClassStyleName(); } |