Source for javax.swing.text.html.StyleSheet

   1: /* StyleSheet.java -- 
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text.html;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Font;
  43: import java.awt.Graphics;
  44: 
  45: import java.io.IOException;
  46: import java.io.Reader;
  47: import java.io.Serializable;
  48: import java.io.StringReader;
  49: 
  50: import java.net.MalformedURLException;
  51: import java.net.URL;
  52: 
  53: import java.util.Enumeration;
  54: import java.util.Vector;
  55: 
  56: import javax.swing.text.AttributeSet;
  57: import javax.swing.text.Element;
  58: import javax.swing.text.MutableAttributeSet;
  59: import javax.swing.text.SimpleAttributeSet;
  60: import javax.swing.text.Style;
  61: import javax.swing.text.StyleContext;
  62: import javax.swing.text.View;
  63: 
  64: 
  65: /**
  66:  * This class adds support for defining the visual characteristics of HTML views
  67:  * being rendered. This enables views to be customized by a look-and-feel, mulitple
  68:  * views over the same model can be rendered differently. Each EditorPane has its 
  69:  * own StyleSheet, but by default one sheet will be shared by all of the HTMLEditorKit
  70:  * instances. An HTMLDocument can also have a StyleSheet, which holds specific CSS
  71:  * specs. 
  72:  * 
  73:  *  In order for Views to store less state and therefore be more lightweight, 
  74:  *  the StyleSheet can act as a factory for painters that handle some of the 
  75:  *  rendering tasks. Since the StyleSheet may be used by views over multiple
  76:  *  documents the HTML attributes don't effect the selector being used.
  77:  *  
  78:  *  The rules are stored as named styles, and other information is stored to 
  79:  *  translate the context of an element to a rule.
  80:  * 
  81:  * @author Lillian Angel (langel@redhat.com)
  82:  */
  83: public class StyleSheet extends StyleContext
  84: {
  85: 
  86:   /** The base URL */
  87:   URL base;
  88:   
  89:   /** Base font size (int) */
  90:   int baseFontSize;
  91:   
  92:   /** The style sheets stored. */
  93:   StyleSheet[] styleSheet;
  94:   
  95:   /**
  96:    * Constructs a StyleSheet.
  97:    */
  98:   public StyleSheet()
  99:   {
 100:     super();
 101:     baseFontSize = 4; // Default font size from CSS
 102:   }
 103: 
 104:   /**
 105:    * Gets the style used to render the given tag. The element represents the tag
 106:    * and can be used to determine the nesting, where the attributes will differ
 107:    * if there is nesting inside of elements.
 108:    * 
 109:    * @param t - the tag to translate to visual attributes
 110:    * @param e - the element representing the tag
 111:    * @return the set of CSS attributes to use to render the tag.
 112:    */
 113:   public Style getRule(HTML.Tag t, Element e)
 114:   {
 115:     // FIXME: Not implemented.
 116:     return null;
 117:   }
 118:   
 119:   /**
 120:    * Gets the rule that best matches the selector. selector is a space
 121:    * separated String of element names. The attributes of the returned 
 122:    * Style will change as rules are added and removed.
 123:    * 
 124:    * @param selector - the element names separated by spaces
 125:    * @return the set of CSS attributes to use to render
 126:    */
 127:   public Style getRule(String selector)
 128:   {
 129:     // FIXME: Not implemented.
 130:     return null; 
 131:   }
 132:   
 133:   /**
 134:    * Adds a set if rules to the sheet. The rules are expected to be in valid
 135:    * CSS format. This is called as a result of parsing a <style> tag
 136:    * 
 137:    * @param rule - the rule to add to the sheet
 138:    */
 139:   public void addRule(String rule)
 140:   {
 141:     CssParser cp = new CssParser();
 142:     try
 143:     {
 144:       cp.parse(base, new StringReader(rule), false, false);
 145:     }
 146:     catch (IOException io)
 147:     {
 148:       // Do nothing here.
 149:     }
 150:   }
 151:   
 152:   /**
 153:    * Translates a CSS declaration into an AttributeSet. This is called
 154:    * as a result of encountering an HTML style attribute.
 155:    * 
 156:    * @param decl - the declaration to get
 157:    * @return the AttributeSet representing the declaration
 158:    */
 159:   public AttributeSet getDeclaration(String decl)
 160:   {
 161:     if (decl == null)
 162:       return SimpleAttributeSet.EMPTY;
 163:     // FIXME: Not implemented.
 164:     return null;     
 165:   }
 166:   
 167:   /**
 168:    * Loads a set of rules that have been specified in terms of CSS grammar.
 169:    * If there are any conflicts with existing rules, the new rule is added.
 170:    * 
 171:    * @param in - the stream to read the CSS grammar from.
 172:    * @param ref - the reference URL. It is the location of the stream, it may
 173:    * be null. All relative URLs specified in the stream will be based upon this
 174:    * parameter.
 175:    * @throws IOException - For any IO error while reading
 176:    */
 177:   public void loadRules(Reader in, URL ref) throws IOException
 178:   {
 179:     CssParser cp = new CssParser();
 180:     cp.parse(ref, in, false, false);
 181:   }
 182:   
 183:   /**
 184:    * Gets a set of attributes to use in the view. This is a set of
 185:    * attributes that can be used for View.getAttributes
 186:    * 
 187:    * @param v - the view to get the set for
 188:    * @return the AttributeSet to use in the view.
 189:    */
 190:   public AttributeSet getViewAttributes(View v)
 191:   {
 192:     // FIXME: Not implemented.
 193:     return null;
 194:   }
 195:   
 196:   /**
 197:    * Removes a style previously added.
 198:    * 
 199:    * @param nm - the name of the style to remove
 200:    */
 201:   public void removeStyle(String nm)
 202:   {
 203:     // FIXME: Not implemented.
 204:     super.removeStyle(nm);
 205:   }
 206:   
 207:   /**
 208:    * Adds the rules from ss to those of the receiver. ss's rules will
 209:    * override the old rules. An added StyleSheet will never override the rules
 210:    * of the receiving style sheet.
 211:    * 
 212:    * @param ss - the new StyleSheet.
 213:    */
 214:   public void addStyleSheet(StyleSheet ss)
 215:   {
 216:     if (styleSheet == null)
 217:       styleSheet = new StyleSheet[] {ss};
 218:     else
 219:       System.arraycopy(new StyleSheet[] {ss}, 0, styleSheet, 
 220:                        styleSheet.length, 1);
 221:   }
 222:   
 223:   /**
 224:    * Removes ss from those of the receiver
 225:    * 
 226:    * @param ss - the StyleSheet to remove.
 227:    */
 228:   public void removeStyleSheet(StyleSheet ss)
 229:   {
 230:     if (styleSheet.length == 1 && styleSheet[0].equals(ss))
 231:       styleSheet = null;
 232:     else
 233:       {
 234:         for (int i = 0; i < styleSheet.length; i++)
 235:           {
 236:             StyleSheet curr = styleSheet[i];
 237:             if (curr.equals(ss))
 238:               {
 239:                 StyleSheet[] tmp = new StyleSheet[styleSheet.length - 1];
 240:                 if (i != 0 && i != (styleSheet.length - 1))
 241:                   {
 242:                     System.arraycopy(styleSheet, 0, tmp, 0, i);
 243:                     System.arraycopy(styleSheet, i + 1, tmp, i,
 244:                                      styleSheet.length - i - 1);
 245:                   }
 246:                 else if (i == 0)
 247:                   System.arraycopy(styleSheet, 1, tmp, 0, styleSheet.length - 1);
 248:                 else
 249:                   System.arraycopy(styleSheet, 0, tmp, 0, styleSheet.length - 1);
 250:                 
 251:                 styleSheet = tmp;
 252:                 break;
 253:               }
 254:           }
 255:       }
 256:   }
 257:   
 258:   /**
 259:    * Returns an array of the linked StyleSheets. May return null.
 260:    * 
 261:    * @return - An array of the linked StyleSheets.
 262:    */
 263:   public StyleSheet[] getStyleSheets()
 264:   {
 265:     return styleSheet;
 266:   }
 267:   
 268:   /**
 269:    * Imports a style sheet from the url. The rules are directly added to the
 270:    * receiver.
 271:    * 
 272:    * @param url - the URL to import the StyleSheet from.
 273:    */
 274:   public void importStyleSheet(URL url)
 275:   {
 276:     // FIXME: Not implemented
 277:   }
 278:   
 279:   /**
 280:    * Sets the base url. All import statements that are relative, will be
 281:    * relative to base.
 282:    * 
 283:    * @param base -
 284:    *          the base URL.
 285:    */
 286:   public void setBase(URL base)
 287:   {
 288:     this.base = base;
 289:   }
 290:   
 291:   /**
 292:    * Gets the base url.
 293:    * 
 294:    * @return - the base
 295:    */
 296:   public URL getBase()
 297:   {
 298:     return base;
 299:   }
 300:   
 301:   /**
 302:    * Adds a CSS attribute to the given set.
 303:    * 
 304:    * @param attr - the attribute set
 305:    * @param key - the attribute to add
 306:    * @param value - the value of the key
 307:    */
 308:   public void addCSSAttribute(MutableAttributeSet attr, CSS.Attribute key,
 309:                               String value)
 310:   {
 311:     attr.addAttribute(key, value);
 312:   }
 313:   
 314:   /**
 315:    * Adds a CSS attribute to the given set.
 316:    * This method parses the value argument from HTML based on key. 
 317:    * Returns true if it finds a valid value for the given key, 
 318:    * and false otherwise.
 319:    * 
 320:    * @param attr - the attribute set
 321:    * @param key - the attribute to add
 322:    * @param value - the value of the key
 323:    * @return true if a valid value was found.
 324:    */
 325:   public boolean addCSSAttributeFromHTML(MutableAttributeSet attr, CSS.Attribute key,
 326:                                          String value)
 327:   {
 328:     // FIXME: Need to parse value from HTML based on key.
 329:     attr.addAttribute(key, value);
 330:     return attr.containsAttribute(key, value);
 331:   }
 332:   
 333:   /**
 334:    * Converts a set of HTML attributes to an equivalent set of CSS attributes.
 335:    * 
 336:    * @param htmlAttrSet - the set containing the HTML attributes.
 337:    * @return the set of CSS attributes
 338:    */
 339:   public AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet)
 340:   {
 341:     // FIXME: Not implemented.
 342:     return null;    
 343:   }
 344: 
 345:   /**
 346:    * Adds an attribute to the given set and returns a new set. This is implemented
 347:    * to convert StyleConstants attributes to CSS before forwarding them to the superclass.
 348:    * The StyleConstants attribute do not have corresponding CSS entry, the attribute
 349:    * is stored (but will likely not be used).
 350:    * 
 351:    * @param old - the old set
 352:    * @param key - the non-null attribute key
 353:    * @param value - the attribute value
 354:    * @return the updated set 
 355:    */
 356:   public AttributeSet addAttribute(AttributeSet old, Object key,
 357:                                    Object value)
 358:   {
 359:     // FIXME: Not implemented.
 360:     return super.addAttribute(old, key, value);       
 361:   }
 362:   
 363:   /**
 364:    * Adds a set of attributes to the element. If any of these attributes are
 365:    * StyleConstants, they will be converted to CSS before forwarding to the 
 366:    * superclass.
 367:    * 
 368:    * @param old - the old set
 369:    * @param attr - the attributes to add
 370:    * @return the updated attribute set
 371:    */
 372:   public AttributeSet addAttributes(AttributeSet old, AttributeSet attr)
 373:   {
 374:     // FIXME: Not implemented.
 375:     return super.addAttributes(old, attr);           
 376:   }
 377:   
 378:   /**
 379:    * Removes an attribute from the set. If the attribute is a
 380:    * StyleConstants, it will be converted to CSS before forwarding to the 
 381:    * superclass.
 382:    * 
 383:    * @param old - the old set
 384:    * @param key - the non-null attribute key
 385:    * @return the updated set 
 386:    */
 387:   public AttributeSet removeAttribute(AttributeSet old, Object key)
 388:   {
 389:     // FIXME: Not implemented.
 390:     return super.removeAttribute(old, key);    
 391:   }
 392:   
 393:   /**
 394:    * Removes an attribute from the set. If any of the attributes are
 395:    * StyleConstants, they will be converted to CSS before forwarding to the 
 396:    * superclass.
 397:    * 
 398:    * @param old - the old set
 399:    * @param attrs - the attributes to remove
 400:    * @return the updated set 
 401:    */
 402:   public AttributeSet removeAttributes(AttributeSet old, AttributeSet attrs)
 403:   {
 404:     // FIXME: Not implemented.
 405:     return super.removeAttributes(old, attrs);    
 406:   }
 407:   
 408:   /**
 409:    * Removes a set of attributes for the element. If any of the attributes is a
 410:    * StyleConstants, they will be converted to CSS before forwarding to the 
 411:    * superclass.
 412:    * 
 413:    * @param old - the old attribute set
 414:    * @param names - the attribute names
 415:    * @return the update attribute set
 416:    */
 417:   public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
 418:   {
 419:     // FIXME: Not implemented.
 420:     return super.removeAttributes(old, names);        
 421:   }
 422:   
 423:   /**
 424:    * Creates a compact set of attributes that might be shared. This is a hook
 425:    * for subclasses that want to change the behaviour of SmallAttributeSet.
 426:    * 
 427:    * @param a - the set of attributes to be represented in the compact form.
 428:    * @return the set of attributes created
 429:    */
 430:   protected StyleContext.SmallAttributeSet createSmallAttributeSet(AttributeSet a)
 431:   {
 432:     return super.createSmallAttributeSet(a);     
 433:   }
 434:   
 435:   /**
 436:    * Creates a large set of attributes. This set is not shared. This is a hook
 437:    * for subclasses that want to change the behaviour of the larger attribute
 438:    * storage format.
 439:    * 
 440:    * @param a - the set of attributes to be represented in the larger form.
 441:    * @return the large set of attributes.
 442:    */
 443:   protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
 444:   {
 445:     return super.createLargeAttributeSet(a);     
 446:   }
 447:   
 448:   /**
 449:    * Gets the font to use for the given set.
 450:    * 
 451:    * @param a - the set to get the font for.
 452:    * @return the font for the set
 453:    */
 454:   public Font getFont(AttributeSet a)
 455:   {
 456:     return super.getFont(a);    
 457:   }
 458:   
 459:   /**
 460:    * Takes a set of attributes and turns it into a foreground
 461:    * color specification. This is used to specify things like, brigher, more hue
 462:    * etc.
 463:    * 
 464:    * @param a - the set to get the foreground color for
 465:    * @return the foreground color for the set
 466:    */
 467:   public Color getForeground(AttributeSet a)
 468:   {
 469:     return super.getForeground(a);     
 470:   }
 471:   
 472:   /**
 473:    * Takes a set of attributes and turns it into a background
 474:    * color specification. This is used to specify things like, brigher, more hue
 475:    * etc.
 476:    * 
 477:    * @param a - the set to get the background color for
 478:    * @return the background color for the set
 479:    */
 480:   public Color getBackground(AttributeSet a)
 481:   {
 482:     return super.getBackground(a);     
 483:   }
 484:   
 485:   /**
 486:    * Gets the box formatter to use for the given set of CSS attributes.
 487:    * 
 488:    * @param a - the given set
 489:    * @return the box formatter
 490:    */
 491:   public BoxPainter getBoxPainter(AttributeSet a)
 492:   {
 493:     return new BoxPainter(a);     
 494:   }
 495:   
 496:   /**
 497:    * Gets the list formatter to use for the given set of CSS attributes.
 498:    * 
 499:    * @param a - the given set
 500:    * @return the list formatter
 501:    */
 502:   public ListPainter getListPainter(AttributeSet a)
 503:   {
 504:     return new ListPainter(a);         
 505:   }
 506:   
 507:   /**
 508:    * Sets the base font size between 1 and 7.
 509:    * 
 510:    * @param sz - the new font size for the base.
 511:    */
 512:   public void setBaseFontSize(int sz)
 513:   {
 514:     if (sz <= 7 && sz >= 1)
 515:       baseFontSize = sz;
 516:   }
 517:   
 518:   /**
 519:    * Sets the base font size from the String. It can either identify
 520:    * a specific font size (between 1 and 7) or identify a relative
 521:    * font size such as +1 or -2.
 522:    * 
 523:    * @param size - the new font size as a String.
 524:    */
 525:   public void setBaseFontSize(String size)
 526:   {
 527:     size.trim();
 528:     int temp = 0;
 529:     try
 530:       {
 531:         if (size.length() == 2)
 532:           {
 533:             int i = new Integer(size.substring(1)).intValue();
 534:             if (size.startsWith("+"))
 535:               temp = baseFontSize + i;
 536:             else if (size.startsWith("-"))
 537:               temp = baseFontSize - i;
 538:           }
 539:         else if (size.length() == 1)
 540:           temp = new Integer(size.substring(0)).intValue();
 541: 
 542:         if (temp <= 7 && temp >= 1)
 543:           baseFontSize = temp;
 544:       }
 545:     catch (NumberFormatException nfe)
 546:       {
 547:         // Do nothing here
 548:       }
 549:   }
 550:   
 551:   /**
 552:    * TODO
 553:    * 
 554:    * @param pt - TODO
 555:    * @return TODO
 556:    */
 557:   public static int getIndexOfSize(float pt)
 558:   {
 559:     // FIXME: Not implemented.
 560:     return 0;
 561:   }
 562:   
 563:   /**
 564:    * Gets the point size, given a size index.
 565:    * 
 566:    * @param index - the size index
 567:    * @return the point size.
 568:    */
 569:   public float getPointSize(int index)
 570:   {
 571:     // FIXME: Not implemented.
 572:     return 0;    
 573:   }
 574:   
 575:   /**
 576:    * Given the string of the size, returns the point size value.
 577:    * 
 578:    * @param size - the string representation of the size.
 579:    * @return - the point size value.
 580:    */
 581:   public float getPointSize(String size)
 582:   {
 583:     // FIXME: Not implemented.
 584:     return 0;    
 585:   }
 586:   
 587:   /**
 588:    * Converst a color string to a color. If it is not found, null is returned.
 589:    * 
 590:    * @param color - the color string such as "RED" or "#NNNNNN"
 591:    * @return the Color, or null if not found.
 592:    */
 593:   public Color stringToColor(String color)
 594:   {
 595:     color = color.toLowerCase();
 596:     if (color.equals("black") || color.equals("#000000"))
 597:       return Color.BLACK;
 598:     else if (color.equals("aqua") || color.equals("#00FFFF"))
 599:       return new Color(127, 255, 212);
 600:     else if (color.equals("gray") || color.equals("#808080"))
 601:       return Color.GRAY;
 602:     else if (color.equals("navy") || color.equals("#000080"))
 603:       return new Color(0, 0, 128);
 604:     else if (color.equals("silver") || color.equals("#C0C0C0"))
 605:       return Color.LIGHT_GRAY;
 606:     else if (color.equals("green") || color.equals("#008000"))
 607:       return Color.GREEN;
 608:     else if (color.equals("olive") || color.equals("#808000"))
 609:       return new Color(128, 128, 0);
 610:     else if (color.equals("teal") || color.equals("#008080"))
 611:       return new Color(0, 128, 128);
 612:     else if (color.equals("blue") || color.equals("#0000FF"))
 613:       return Color.BLUE;
 614:     else if (color.equals("lime") || color.equals("#00FF00"))
 615:       return new Color(0, 255, 0);
 616:     else if (color.equals("purple") || color.equals("#800080"))
 617:       return new Color(128, 0, 128);
 618:     else if (color.equals("white") || color.equals("#FFFFFF"))
 619:       return Color.WHITE;
 620:     else if (color.equals("fuchsia") || color.equals("#FF00FF"))
 621:       return Color.MAGENTA;
 622:     else if (color.equals("maroon") || color.equals("#800000"))
 623:       return new Color(128, 0, 0);
 624:     else if (color.equals("Red") || color.equals("#FF0000"))
 625:       return Color.RED;
 626:     else if (color.equals("Yellow") || color.equals("#FFFF00"))
 627:       return Color.YELLOW;
 628:     return null; 
 629:   }
 630:   
 631:   /**
 632:    * This class carries out some of the duties of CSS formatting. This enables views
 633:    * to present the CSS formatting while not knowing how the CSS values are cached.
 634:    * 
 635:    * This object is reponsible for the insets of a View and making sure
 636:    * the background is maintained according to the CSS attributes.
 637:    * 
 638:    * @author Lillian Angel (langel@redhat.com)
 639:    */
 640:   public static class BoxPainter extends Object implements Serializable
 641:   {
 642:     
 643:     /**
 644:      * Attribute set for painter
 645:      */
 646:     AttributeSet as;
 647:     
 648:     /**
 649:      * Package-private constructor.
 650:      * 
 651:      * @param as - AttributeSet for painter
 652:      */
 653:     BoxPainter(AttributeSet as)
 654:     {
 655:       this.as = as;
 656:     }
 657:     
 658:     /**
 659:      * Gets the inset needed on a given side to account for the margin, border
 660:      * and padding.
 661:      * 
 662:      * @param size - the size of the box to get the inset for. View.TOP, View.LEFT,
 663:      * View.BOTTOM or View.RIGHT.
 664:      * @param v - the view making the request. This is used to get the AttributeSet,
 665:      * amd may be used to resolve percentage arguments.
 666:      * @return the inset
 667:      * @throws IllegalArgumentException - for an invalid direction.
 668:      */
 669:     public float getInset(int size, View v)
 670:     {
 671:       // FIXME: Not implemented.
 672:       return 0;       
 673:     }
 674:     
 675:     /**
 676:      * Paints the CSS box according to the attributes given. This should
 677:      * paint the border, padding and background.
 678:      * 
 679:      * @param g - the graphics configuration
 680:      * @param x - the x coordinate
 681:      * @param y - the y coordinate
 682:      * @param w - the width of the allocated area
 683:      * @param h - the height of the allocated area
 684:      * @param v - the view making the request
 685:      */
 686:     public void paint(Graphics g, float x, float y, float w, float h, View v)
 687:     {
 688:       // FIXME: Not implemented.
 689:     }
 690:   }
 691:   
 692:   /**
 693:    * This class carries out some of the CSS list formatting duties. Implementations
 694:    * of this class enable views to present the CSS formatting while not knowing anything
 695:    * about how the CSS values are being cached.
 696:    * 
 697:    * @author Lillian Angel (langel@redhat.com)
 698:    */
 699:   public static class ListPainter extends Object implements Serializable
 700:   {
 701:     
 702:     /**
 703:      * Attribute set for painter
 704:      */
 705:     AttributeSet as;
 706:     
 707:     /**
 708:      * Package-private constructor.
 709:      * 
 710:      * @param as - AttributeSet for painter
 711:      */
 712:     ListPainter(AttributeSet as)
 713:     {
 714:       this.as = as;
 715:     }
 716:     
 717:     /**
 718:      * Paints the CSS list decoration according to the attributes given.
 719:      * 
 720:      * @param g - the graphics configuration
 721:      * @param x - the x coordinate
 722:      * @param y - the y coordinate
 723:      * @param w - the width of the allocated area
 724:      * @param h - the height of the allocated area
 725:      * @param v - the view making the request
 726:      * @param item - the list item to be painted >=0.
 727:      */
 728:     public void paint(Graphics g, float x, float y, float w, float h, View v,
 729:                       int item)
 730:     {
 731:       // FIXME: Not implemented.
 732:     }
 733:   }
 734:   
 735:   /**
 736:    * The parser callback for the CSSParser.
 737:    */
 738:   class CssParser implements CSSParser.CSSParserCallback
 739:   {
 740:     /** 
 741:      * A vector of all the selectors. 
 742:      * Each element is an array of all the selector tokens 
 743:      * in a single rule. 
 744:      */
 745:     Vector selectors;
 746: 
 747:     /** A vector of all the selector tokens in a rule. */
 748:     Vector selectorTokens;
 749: 
 750:     /**  Name of the current property. */
 751:     String propertyName;
 752: 
 753:     /** The set of CSS declarations */
 754:     MutableAttributeSet declaration;
 755: 
 756:     /** 
 757:      * True if parsing a declaration, that is the Reader will not 
 758:      * contain a selector. 
 759:      */
 760:     boolean parsingDeclaration;
 761: 
 762:     /** True if the attributes are coming from a linked/imported style. */
 763:     boolean isLink;
 764: 
 765:     /** The base URL */
 766:     URL base;
 767: 
 768:     /** The parser */
 769:     CSSParser parser;
 770: 
 771:     /**
 772:      * Constructor
 773:      */
 774:     CssParser()
 775:     {
 776:       selectors = new Vector();
 777:       selectorTokens = new Vector();
 778:       parser = new CSSParser();
 779:       base = StyleSheet.this.base;
 780:       declaration = new SimpleAttributeSet();
 781:     }
 782: 
 783:     /**
 784:      * Parses the passed in CSS declaration into an AttributeSet.
 785:      * 
 786:      * @param s - the declaration
 787:      * @return the set of attributes containing the property and value.
 788:      */
 789:     public AttributeSet parseDeclaration(String s)
 790:     {
 791:       try
 792:       {
 793:         return parseDeclaration(new StringReader(s));
 794:       }
 795:       catch (IOException e)
 796:       {
 797:          // Do nothing here.
 798:       }
 799:       return null;
 800:     }
 801: 
 802:     /**
 803:      * Parses the passed in CSS declaration into an AttributeSet.
 804:      * 
 805:      * @param r - the reader
 806:      * @return the attribute set
 807:      * @throws IOException from the reader
 808:      */
 809:     public AttributeSet parseDeclaration(Reader r) throws IOException
 810:     {
 811:       parse(base, r, true, false);
 812:       return declaration;
 813:     }
 814: 
 815:     /**
 816:      * Parse the given CSS stream
 817:      * 
 818:      * @param base - the url
 819:      * @param r - the reader
 820:      * @param parseDec - True if parsing a declaration
 821:      * @param isLink - True if parsing a link
 822:      */
 823:    public void parse(URL base, Reader r, boolean parseDec, boolean isLink) throws IOException
 824:    {
 825:      parsingDeclaration = parseDec;
 826:      this.isLink = isLink;
 827:      this.base = base;
 828:      
 829:      // flush out all storage
 830:      propertyName = null;
 831:      selectors.clear();
 832:      selectorTokens.clear();
 833:      declaration.removeAttributes(declaration);
 834:      
 835:      parser.parse(r, this, parseDec);
 836:    }
 837: 
 838:    /**
 839:     * Invoked when a valid @import is encountered, 
 840:     * will call importStyleSheet if a MalformedURLException 
 841:     * is not thrown in creating the URL.
 842:     *
 843:     * @param s - the string after @import
 844:     */ 
 845:    public void handleImport(String s)
 846:     {
 847:       if (s != null)
 848:         {
 849:           try
 850:             {
 851:               if (s.startsWith("url(") && s.endsWith(")"))
 852:                 s = s.substring(4, s.length() - 1);
 853:               if (s.indexOf("\"") >= 0)
 854:                 s = s.replaceAll("\"","");
 855: 
 856:               URL url = new URL(s);
 857:               if (url == null && base != null)
 858:                 url = new URL(base, s);
 859:               
 860:               importStyleSheet(url);
 861:             }
 862:           catch (MalformedURLException e)
 863:             {
 864:               // Do nothing here.
 865:             }
 866:         }
 867:     }
 868: 
 869:    /**
 870:      * A selector has been encountered.
 871:      * 
 872:      * @param s - a selector (e.g. P or UL or even P,)
 873:      */
 874:    public void handleSelector(String s)
 875:    {
 876:      if (s.endsWith(","))
 877:        s = s.substring(0, s.length() - 1);
 878:      
 879:      selectorTokens.addElement(s);
 880:      addSelector();
 881:    }
 882: 
 883:    /**
 884:     * Invoked when the start of a rule is encountered.
 885:     */
 886:    public void startRule()
 887:    {
 888:      addSelector();
 889:    }
 890: 
 891:    /**
 892:     * Invoked when a property name is encountered.
 893:     *
 894:     * @param s - the property
 895:     */
 896:    public void handleProperty(String s)
 897:    {
 898:      propertyName = s;
 899:    }
 900: 
 901:   /**
 902:    * Invoked when a property value is encountered.
 903:    *
 904:    * @param s - the value
 905:    */
 906:    public void handleValue(String s)
 907:    {
 908:      // call addCSSAttribute
 909:      // FIXME: Not implemented
 910:    }
 911:    
 912:    /**
 913:     * Invoked when the end of a rule is encountered.
 914:     */
 915:    public void endRule()
 916:    {
 917:      // FIXME: Not implemented
 918:      // add rules
 919:      propertyName = null;
 920:    }
 921: 
 922:    /**
 923:     * Adds the selector to the vector.
 924:     */
 925:    private void addSelector()
 926:    {
 927:      int length = selectorTokens.size();
 928:      if (length > 0)
 929:        {
 930:          Object[] sel = new Object[length];
 931:          System.arraycopy(selectorTokens.toArray(), 0, sel, 0, length);
 932:          selectors.add(sel);
 933:          selectorTokens.clear();
 934:        }
 935:    }
 936:   }
 937: }