Clover coverage report -
Coverage timestamp: Sun Apr 18 2004 21:32:30 EDT
file stats: LOC: 295   Methods: 7
NCLOC: 176   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SHTMLBoxPainter.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  * SimplyHTML, a word processor based on Java, HTML and CSS
 3   
  * Copyright (C) 2002 Ulrich Hilger
 4   
  *
 5   
  * This program is free software; you can redistribute it and/or
 6   
  * modify it under the terms of the GNU General Public License
 7   
  * as published by the Free Software Foundation; either version 2
 8   
  * of the License, or (at your option) any later version.
 9   
  *
 10   
  * This program is distributed in the hope that it will be useful,
 11   
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13   
  * GNU General Public License for more details.
 14   
  *
 15   
  * You should have received a copy of the GNU General Public License
 16   
  * along with this program; if not, write to the Free Software
 17   
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18   
  */
 19   
 
 20   
 import javax.swing.text.AttributeSet;
 21   
 import javax.swing.text.html.CSS;
 22   
 import java.awt.Graphics;
 23   
 import javax.swing.text.View;
 24   
 import javax.swing.border.Border;
 25   
 import java.awt.Color;
 26   
 import java.awt.Insets;
 27   
 import javax.swing.text.html.CSS;
 28   
 import javax.swing.ImageIcon;
 29   
 import java.awt.Rectangle;
 30   
 import java.util.Hashtable;
 31   
 import java.util.Enumeration;
 32   
 import javax.swing.text.Element;
 33   
 import javax.swing.text.SimpleAttributeSet;
 34   
 import javax.swing.text.html.StyleSheet;
 35   
 import javax.swing.text.Style;
 36   
 
 37   
 /**
 38   
  * <p>A box painter to support individual border rendering, i.e. border width
 39   
  * and color of each side of a cell are painted independently according
 40   
  * to CSS attributes border-width and border-color.</p>
 41   
  *
 42   
  * <p>Only border-style solid is supported.</p>
 43   
  *
 44   
  * @author Ulrich Hilger
 45   
  * @author Light Development
 46   
  * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
 47   
  * @author <a href="mailto:info@lightdev.com">info@lightdev.com</a>
 48   
  * @author published under the terms and conditions of the
 49   
  *      GNU General Public License,
 50   
  *      for details see file gpl.txt in the distribution
 51   
  *      package of this software
 52   
  *
 53   
  * @version stage 11, April 27, 2003
 54   
  */
 55   
 
 56   
 public class SHTMLBoxPainter {
 57   
 
 58   
   private float topMargin;
 59   
   private float bottomMargin;
 60   
   private float leftMargin;
 61   
   private float rightMargin;
 62   
   // Bitmask, used to indicate what margins are relative:
 63   
   // bit 0 for top, 1 for bottom, 2 for left and 3 for right.
 64   
   private short marginFlags;
 65   
   private CombinedAttribute borderWidth;
 66   
   private CombinedAttribute borderColor;
 67   
   private CombinedAttribute padding;
 68   
   private CombinedAttribute margin;
 69   
   private Color bg;
 70   
 
 71   
   /**
 72   
    * construct an SHTMLBoxPainter
 73   
    */
 74  0
   public SHTMLBoxPainter(AttributeSet a) {
 75  0
     borderWidth = new CombinedAttribute(CSS.Attribute.BORDER_WIDTH, a, true);
 76  0
     borderColor = new CombinedAttribute(CSS.Attribute.BORDER_COLOR, a, true);
 77  0
     padding = new CombinedAttribute(CSS.Attribute.PADDING, a, true);
 78  0
     margin = new CombinedAttribute(CSS.Attribute.MARGIN, a, true);
 79  0
     leftMargin = Util.getPtValue(margin.getAttribute(CombinedAttribute.ATTR_LEFT));
 80  0
     rightMargin = Util.getPtValue(margin.getAttribute(CombinedAttribute.ATTR_RIGHT));
 81  0
     topMargin = Util.getPtValue(margin.getAttribute(CombinedAttribute.ATTR_TOP));
 82  0
     bottomMargin = Util.getPtValue(margin.getAttribute(CombinedAttribute.ATTR_BOTTOM));
 83  0
     bg = Util.styleSheet().getBackground(a);
 84   
   }
 85   
 
 86  0
   public Color getColor(String value) {
 87  0
     try {
 88  0
       if (value != null) {
 89  0
         return new Color(Integer.parseInt(
 90   
             value.toString().substring(1).toUpperCase(), 16));
 91   
       }
 92   
       else {
 93  0
         return Color.black;
 94   
       }
 95   
     }
 96   
     catch(Exception e) {
 97  0
       try {
 98  0
         return Color.getColor(value);
 99   
       }
 100   
       catch (Exception e2) {
 101  0
         return Color.black;
 102   
       }
 103   
     }
 104   
   }
 105   
 
 106   
   /**
 107   
    * Fetches the inset needed on a given side to
 108   
    * account for the margin, border, and padding.
 109   
    *
 110   
    * @param side The size of the box to fetch the
 111   
    *  inset for.  This can be View.TOP,
 112   
    *  View.LEFT, View.BOTTOM, or View.RIGHT.
 113   
    * @param v the view making the request.  This is
 114   
    *  used to get the AttributeSet, and may be used to
 115   
    *  resolve percentage arguments.
 116   
    * @exception IllegalArgumentException for an invalid direction
 117   
    */
 118  0
   public float getInset(int side, View v) {
 119  0
     AttributeSet a = v.getAttributes();
 120  0
     float inset = 0;
 121  0
     switch(side) {
 122  0
     case View.LEFT:
 123  0
       inset += leftMargin;
 124  0
       inset += Util.getPtValue(borderWidth.getAttribute(CombinedAttribute.ATTR_LEFT));
 125  0
       inset += Util.getPtValue(padding.getAttribute(CombinedAttribute.ATTR_LEFT));
 126  0
       break;
 127  0
     case View.RIGHT:
 128  0
       inset += rightMargin;
 129  0
       inset += Util.getPtValue(borderWidth.getAttribute(CombinedAttribute.ATTR_RIGHT));
 130  0
       inset += Util.getPtValue(padding.getAttribute(CombinedAttribute.ATTR_RIGHT));
 131  0
       break;
 132  0
     case View.TOP:
 133  0
       inset += topMargin;
 134  0
       inset += Util.getPtValue(borderWidth.getAttribute(CombinedAttribute.ATTR_TOP));
 135  0
       inset += Util.getPtValue(padding.getAttribute(CombinedAttribute.ATTR_TOP));
 136  0
       break;
 137  0
     case View.BOTTOM:
 138  0
       inset += bottomMargin;
 139  0
       inset += Util.getPtValue(borderWidth.getAttribute(CombinedAttribute.ATTR_BOTTOM));
 140  0
       inset += Util.getPtValue(padding.getAttribute(CombinedAttribute.ATTR_BOTTOM));
 141  0
       break;
 142  0
     default:
 143  0
       throw new IllegalArgumentException("Invalid side: " + side);
 144   
     }
 145   
     //System.out.println("getInset side=" + side + " inset=" + inset);
 146  0
     return inset;
 147   
   }
 148   
 
 149   
   /**
 150   
    * Paints the CSS box according to the attributes
 151   
    * given.  This should paint the border, padding,
 152   
    * and background.
 153   
    *
 154   
    * @param g the rendering surface.
 155   
    * @param x the x coordinate of the allocated area to
 156   
    *  render into.
 157   
    * @param y the y coordinate of the allocated area to
 158   
    *  render into.
 159   
    * @param w the width of the allocated area to render into.
 160   
    * @param h the height of the allocated area to render into.
 161   
    * @param v the view making the request.  This is
 162   
    *  used to get the AttributeSet, and may be used to
 163   
    *  resolve percentage arguments.
 164   
    */
 165  0
   public void paint(Graphics g, float x, float y, float w, float h, View v) {
 166   
     //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
 167   
     //hd.listAttributes(v.getAttributes(), 2);
 168  0
     Element cell = v.getElement();
 169  0
     Element thisRow = cell.getParentElement();
 170  0
     Element table = thisRow.getParentElement();
 171  0
     int rowIndex = Util.getRowIndex(cell);
 172  0
     int cellIndex = Util.getElementIndex(cell);
 173  0
     x += leftMargin;
 174  0
     y += topMargin;
 175  0
     w -= leftMargin + rightMargin;
 176  0
     h -= topMargin + bottomMargin;
 177  0
     if (bg != null) {
 178  0
       g.setColor(bg);
 179  0
       g.fillRect((int) x, (int) y, (int) w, (int) h);
 180   
     }
 181  0
     if((rowIndex == 0) ||
 182   
        canPaintBorder(cell,
 183   
        table.getElement(rowIndex-1).getElement(cellIndex),
 184   
        CombinedAttribute.ATTR_TOP, v))
 185   
     {
 186  0
       paintBorder(g, x, y, w, h, CombinedAttribute.ATTR_TOP);
 187   
     }
 188  0
     if((cellIndex == 0) ||
 189   
        canPaintBorder(cell,
 190   
        table.getElement(rowIndex).getElement(cellIndex-1),
 191   
        CombinedAttribute.ATTR_LEFT, v))
 192   
     {
 193  0
       paintBorder(g, x, y, w, h, CombinedAttribute.ATTR_LEFT);
 194   
     }
 195  0
     paintBorder(g, x, y, w, h, CombinedAttribute.ATTR_BOTTOM);
 196  0
     paintBorder(g, x, y, w, h, CombinedAttribute.ATTR_RIGHT);
 197   
   }
 198   
 
 199   
   /**
 200   
    * paint a border for a given side of a table cell
 201   
    *
 202   
    * @param g the rendering surface.
 203   
    * @param x the x coordinate of the allocated area to
 204   
    *  render into.
 205   
    * @param y the y coordinate of the allocated area to
 206   
    *  render into.
 207   
    * @param w the width of the allocated area to render into.
 208   
    * @param h the height of the allocated area to render into.
 209   
    * @param side  the side to render
 210   
    */
 211  0
   private void paintBorder(Graphics g, float x, float y, float w, float h,
 212   
                            int side)
 213   
   {
 214  0
     int thickness;
 215  0
     g.setColor(getColor(borderColor.getAttribute(
 216   
         side)));
 217  0
     thickness = (int) Util.getPtValue(borderWidth.getAttribute(
 218   
         side));
 219  0
     switch(side) {
 220  0
       case CombinedAttribute.ATTR_TOP:
 221  0
         g.fillRect((int) x, (int) y, (int) w, thickness);
 222  0
         break;
 223  0
       case CombinedAttribute.ATTR_RIGHT:
 224  0
         g.fillRect((int) x + (int) w - thickness, (int) y, thickness, (int) h);
 225  0
         break;
 226  0
       case CombinedAttribute.ATTR_BOTTOM:
 227  0
         g.fillRect((int) x, (int) y + (int) h - thickness, (int) w, thickness);
 228  0
         break;
 229  0
       case CombinedAttribute.ATTR_LEFT:
 230  0
         g.fillRect((int) x, (int) y, thickness, (int) h);
 231  0
         break;
 232   
     }
 233   
   }
 234   
 
 235   
   /**
 236   
    * find out whether or not the border of a given side of table cell can
 237   
    * be painted.
 238   
    *
 239   
    * @param cell  the cell element to adjust a border for
 240   
    * @param oCell  the other cell to look for border and margin settings
 241   
    * @param side  the side of 'cell' to adjust adjust a border for, one of
 242   
    * CombinedAttribute.ATTR_TOP, CombinedAttribute.ATTR_RIGHT,
 243   
    * CombinedAttribute.ATTR_BOTTOM and CombinedAttribute.ATTR_LEFT
 244   
    * @see CombinedAttribute
 245   
    */
 246  0
   private boolean canPaintBorder(Element cell, Element oCell, int side, View v)
 247   
   {
 248  0
     boolean canPaint = true;
 249  0
     try {
 250  0
       AttributeSet vSet = v.getAttributes();
 251  0
       SimpleAttributeSet set = new SimpleAttributeSet(vSet);
 252  0
       set.addAttributes(cell.getAttributes());
 253  0
       SimpleAttributeSet oSet = new SimpleAttributeSet(vSet);
 254  0
       oSet.addAttributes(oCell.getAttributes());
 255  0
       CombinedAttribute otherMargin = new CombinedAttribute(
 256   
           CSS.Attribute.MARGIN, oSet, true);
 257  0
       CombinedAttribute otherBorderWidth = new CombinedAttribute(
 258   
           CSS.Attribute.BORDER_WIDTH, oSet, true);
 259  0
       CombinedAttribute thisMargin = new CombinedAttribute(
 260   
           CSS.Attribute.MARGIN, set, true);
 261  0
       int oppositeSide = otherMargin.getOppositeSide(side);
 262  0
       if(intFromCA(otherMargin, oppositeSide) == 0 &&
 263   
          intFromCA(thisMargin, side) == 0 &&
 264   
          intFromCA(otherBorderWidth, oppositeSide) > 0)
 265   
       {
 266  0
         canPaint = false;
 267   
       }
 268   
     }
 269   
     catch(Exception ex) {
 270  0
       canPaint = false;
 271   
       //Util.errMsg(null, null, ex);
 272   
     }
 273  0
     return canPaint;
 274   
   }
 275   
 
 276   
   /**
 277   
    * get an integer value from a CombinedAttribute
 278   
    *
 279   
    * Caution: This only works for width values in pt
 280   
    *
 281   
    * @param attr  the CombinedAttribute to get an integer value from
 282   
    * @param side  the side of the CombinedAttribute to get the vlaue for
 283   
    *
 284   
    * @return the integer value of the given side
 285   
    */
 286  0
   private int intFromCA(CombinedAttribute attr, int side) {
 287  0
     String val = attr.getAttribute(side);
 288  0
     int iVal = 0;
 289  0
     if(val != null) {
 290  0
       iVal = (int) Util.getPtValue(val);
 291   
       //System.out.println("SHTMLBoxPainter intFromCA val=" + val + " iVal=" + iVal);
 292   
     }
 293  0
     return iVal;
 294   
   }
 295   
 }