summaryrefslogtreecommitdiff
path: root/javax
diff options
context:
space:
mode:
Diffstat (limited to 'javax')
-rw-r--r--javax/swing/JLabel.java35
-rw-r--r--javax/swing/JTree.java88
-rw-r--r--javax/swing/text/ComponentView.java19
-rw-r--r--javax/swing/text/CompositeView.java2
-rw-r--r--javax/swing/text/FlowView.java31
-rw-r--r--javax/swing/text/GlyphView.java71
-rw-r--r--javax/swing/text/ParagraphView.java16
-rw-r--r--javax/swing/text/View.java21
-rw-r--r--javax/swing/text/html/BlockView.java204
-rw-r--r--javax/swing/text/html/CSS.java56
-rw-r--r--javax/swing/text/html/CSSBorder.java420
-rw-r--r--javax/swing/text/html/HTMLDocument.java152
-rw-r--r--javax/swing/text/html/HTMLEditorKit.java10
-rw-r--r--javax/swing/text/html/HTMLWriter.java50
-rw-r--r--javax/swing/text/html/InlineView.java102
-rw-r--r--javax/swing/text/html/ListView.java3
-rw-r--r--javax/swing/text/html/ParagraphView.java119
-rw-r--r--javax/swing/text/html/StyleSheet.java278
-rw-r--r--javax/swing/text/html/TableView.java616
-rw-r--r--javax/swing/text/html/parser/DocumentParser.java4
-rw-r--r--javax/swing/text/html/parser/ParserDelegator.java4
21 files changed, 1936 insertions, 365 deletions
diff --git a/javax/swing/JLabel.java b/javax/swing/JLabel.java
index 3e0f28ed7..721287b21 100644
--- a/javax/swing/JLabel.java
+++ b/javax/swing/JLabel.java
@@ -431,11 +431,11 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically and horizontally centered
* JLabel object with no text and the given icon.
*
- * @param image The icon to use with the label.
+ * @param image The icon to use with the label, <code>null</code> permitted.
*/
public JLabel(Icon image)
{
- this("", image, CENTER);
+ this(null, image, CENTER);
}
/**
@@ -443,19 +443,21 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* given icon and horizontal alignment. By default, the text is TRAILING
* the image.
*
- * @param image The icon to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param image The icon to use with the label, <code>null</code> premitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(Icon image, int horizontalAlignment)
{
- this("", image, horizontalAlignment);
+ this(null, image, horizontalAlignment);
}
/**
* Creates a new horizontally leading and vertically centered JLabel
* object with no icon and the given text.
*
- * @param text The text to use with the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
*/
public JLabel(String text)
{
@@ -466,8 +468,10 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically centered JLabel object with no icon and the
* given text and horizontal alignment.
*
- * @param text The text to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(String text, int horizontalAlignment)
{
@@ -478,12 +482,21 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically centered JLabel object with the given text,
* icon, and horizontal alignment.
*
- * @param text The text to use with the label.
- * @param icon The icon to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
+ * @param icon The icon to use with the label, <code>null</code> premitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(String text, Icon icon, int horizontalAlignment)
{
+ if (horizontalAlignment != SwingConstants.LEFT
+ && horizontalAlignment != SwingConstants.RIGHT
+ && horizontalAlignment != SwingConstants.CENTER
+ && horizontalAlignment != SwingConstants.LEADING
+ && horizontalAlignment != SwingConstants.TRAILING)
+ throw new IllegalArgumentException();
+
this.text = text;
this.icon = icon;
this.horizontalAlignment = horizontalAlignment;
diff --git a/javax/swing/JTree.java b/javax/swing/JTree.java
index c6f08b49c..332ec7424 100644
--- a/javax/swing/JTree.java
+++ b/javax/swing/JTree.java
@@ -1230,8 +1230,32 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void treeNodesRemoved(TreeModelEvent ev)
{
- // TODO: The API docs suggest that this method should do something
- // but I cannot really see what has to be done here ...
+ if (ev != null)
+ {
+ TreePath parent = ev.getTreePath();
+ Object[] children = ev.getChildren();
+ TreeSelectionModel sm = getSelectionModel();
+ if (children != null)
+ {
+ TreePath path;
+ Vector toRemove = new Vector();
+ // Collect items that we must remove.
+ for (int i = children.length - 1; i >= 0; i--)
+ {
+ path = parent.pathByAddingChild(children[i]);
+ if (nodeStates.containsKey(path))
+ toRemove.add(path);
+ // Clear selection while we are at it.
+ if (sm != null)
+ removeDescendantSelectedPaths(path, true);
+ }
+ if (toRemove.size() > 0)
+ removeDescendantToggledPaths(toRemove.elements());
+ TreeModel model = getModel();
+ if (model == null || model.isLeaf(parent.getLastPathComponent()))
+ nodeStates.remove(parent);
+ }
+ }
}
/**
@@ -1243,9 +1267,38 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void treeStructureChanged(TreeModelEvent ev)
{
- // Set state of new path.
- TreePath path = ev.getTreePath();
- setExpandedState(path, isExpanded(path));
+ if (ev != null)
+ {
+ TreePath parent = ev.getTreePath();
+ if (parent != null)
+ {
+ if (parent.getPathCount() == 1)
+ {
+ // We have a new root, clear everything.
+ clearToggledPaths();
+ Object root = treeModel.getRoot();
+ if (root != null && treeModel.isLeaf(root))
+ nodeStates.put(parent, Boolean.TRUE);
+ }
+ else if (nodeStates.containsKey(parent))
+ {
+ Vector toRemove = new Vector();
+ boolean expanded = isExpanded(parent);
+ toRemove.add(parent);
+ removeDescendantToggledPaths(toRemove.elements());
+ if (expanded)
+ {
+ TreeModel model = getModel();
+ if (model != null
+ || model.isLeaf(parent.getLastPathComponent()))
+ collapsePath(parent);
+ else
+ nodeStates.put(parent, Boolean.TRUE);
+ }
+ }
+ removeDescendantSelectedPaths(parent, false);
+ }
+ }
}
}
@@ -1399,8 +1452,10 @@ public class JTree extends JComponent implements Scrollable, Accessible
* This contains the state of all nodes in the tree. Al/ entries map the
* TreePath of a note to to its state. Valid states are EXPANDED and
* COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
+ *
+ * This is package private to avoid accessor methods.
*/
- private Hashtable nodeStates = new Hashtable();
+ Hashtable nodeStates = new Hashtable();
protected transient TreeCellEditor cellEditor;
@@ -2201,20 +2256,35 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void setSelectionPath(TreePath path)
{
+ clearSelectionPathStates();
selectionModel.setSelectionPath(path);
}
public void setSelectionPaths(TreePath[] paths)
{
+ clearSelectionPathStates();
selectionModel.setSelectionPaths(paths);
}
+
+ /**
+ * This method, and all calls to it, should be removed once the
+ * DefaultTreeModel fires events properly. Maintenance of the nodeStates
+ * table should really be done in the TreeModelHandler.
+ */
+ private void clearSelectionPathStates()
+ {
+ TreePath[] oldPaths = selectionModel.getSelectionPaths();
+ if (oldPaths != null)
+ for (int i = 0; i < oldPaths.length; i++)
+ nodeStates.remove(oldPaths[i]);
+ }
public void setSelectionRow(int row)
{
TreePath path = getPathForRow(row);
if (path != null)
- selectionModel.setSelectionPath(path);
+ setSelectionPath(path);
}
public void setSelectionRows(int[] rows)
@@ -2289,11 +2359,13 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void removeSelectionPath(TreePath path)
{
+ clearSelectionPathStates();
selectionModel.removeSelectionPath(path);
}
public void removeSelectionPaths(TreePath[] paths)
{
+ clearSelectionPathStates();
selectionModel.removeSelectionPaths(paths);
}
@@ -2302,7 +2374,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
TreePath path = getPathForRow(row);
if (path != null)
- selectionModel.removeSelectionPath(path);
+ removeSelectionPath(path);
}
public void removeSelectionRows(int[] rows)
diff --git a/javax/swing/text/ComponentView.java b/javax/swing/text/ComponentView.java
index 555120396..8de4de60f 100644
--- a/javax/swing/text/ComponentView.java
+++ b/javax/swing/text/ComponentView.java
@@ -397,7 +397,24 @@ public class ComponentView extends View
{
public void run()
{
- setParentImpl();
+ Document doc = getDocument();
+ try
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ setParentImpl();
+ Container host = getContainer();
+ if (host != null)
+ {
+ preferenceChanged(null, true, true);
+ host.repaint();
+ }
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
}
});
}
diff --git a/javax/swing/text/CompositeView.java b/javax/swing/text/CompositeView.java
index ab587a9e1..d4467f314 100644
--- a/javax/swing/text/CompositeView.java
+++ b/javax/swing/text/CompositeView.java
@@ -134,7 +134,7 @@ public abstract class CompositeView
public void setParent(View parent)
{
super.setParent(parent);
- if (parent != null && ((children == null) || children.length == 0))
+ if (parent != null && numChildren == 0)
loadChildren(getViewFactory());
}
diff --git a/javax/swing/text/FlowView.java b/javax/swing/text/FlowView.java
index cee5bb126..9609f3fc8 100644
--- a/javax/swing/text/FlowView.java
+++ b/javax/swing/text/FlowView.java
@@ -189,7 +189,7 @@ public abstract class FlowView extends BoxView
// Then remove all views from the flow view.
fv.removeAll();
-
+
for (int rowIndex = 0; start < end; rowIndex++)
{
View row = fv.createRow();
@@ -318,8 +318,8 @@ public abstract class FlowView extends BoxView
int rowIndex)
{
View logicalView = getLogicalView(fv);
- // FIXME: Handle the bias thing correctly.
- int index = logicalView.getViewIndex(startOffset, Position.Bias.Forward);
+ int index = logicalView.getViewIndex(startOffset,
+ Position.Bias.Forward);
View retVal = logicalView.getView(index);
if (retVal.getStartOffset() != startOffset)
retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
@@ -603,6 +603,7 @@ public abstract class FlowView extends BoxView
{
super(element, axis);
strategy = sharedStrategy;
+ layoutSpan = Short.MAX_VALUE;
}
/**
@@ -651,7 +652,7 @@ public abstract class FlowView extends BoxView
*/
public int getFlowStart(int index)
{
- return getLeftInset(); // TODO: Is this correct?
+ return 0;
}
/**
@@ -678,8 +679,8 @@ public abstract class FlowView extends BoxView
if (layoutPool == null)
{
layoutPool = new LogicalView(getElement());
- layoutPool.setParent(this);
}
+ layoutPool.setParent(this);
// Initialize the flow strategy.
strategy.insertUpdate(this, null, null);
}
@@ -696,21 +697,17 @@ public abstract class FlowView extends BoxView
protected void layout(int width, int height)
{
int flowAxis = getFlowAxis();
+ int span;
if (flowAxis == X_AXIS)
- {
- if (layoutSpan != width)
- {
- layoutChanged(Y_AXIS);
- layoutSpan = width;
- }
- }
+ span = (int) width;
else
+ span = (int) height;
+
+ if (layoutSpan != span)
{
- if (layoutSpan != height)
- {
- layoutChanged(X_AXIS);
- layoutSpan = height;
- }
+ layoutChanged(flowAxis);
+ layoutChanged(getAxis());
+ layoutSpan = span;
}
if (! isLayoutValid(flowAxis))
diff --git a/javax/swing/text/GlyphView.java b/javax/swing/text/GlyphView.java
index cb7f8f05d..35c8dd5d7 100644
--- a/javax/swing/text/GlyphView.java
+++ b/javax/swing/text/GlyphView.java
@@ -252,6 +252,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
static class DefaultGlyphPainter extends GlyphPainter
{
+ FontMetrics fontMetrics;
+
/**
* Returns the full height of the rendered text.
*
@@ -259,9 +261,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getHeight(GlyphView view)
{
- Font font = view.getFont();
- FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
- float height = metrics.getHeight();
+ updateFontMetrics(view);
+ float height = fontMetrics.getHeight();
return height;
}
@@ -341,16 +342,16 @@ public class GlyphView extends View implements TabableView, Cloneable
Shape a)
throws BadLocationException
{
+ updateFontMetrics(view);
Element el = view.getElement();
- Font font = view.getFont();
- FontMetrics fm = view.getContainer().getFontMetrics(font);
Segment txt = view.getText(el.getStartOffset(), pos);
Rectangle bounds = a instanceof Rectangle ? (Rectangle) a
: a.getBounds();
TabExpander expander = view.getTabExpander();
- int width = Utilities.getTabbedTextWidth(txt, fm, bounds.x, expander,
+ int width = Utilities.getTabbedTextWidth(txt, fontMetrics, bounds.x,
+ expander,
view.getStartOffset());
- int height = fm.getHeight();
+ int height = fontMetrics.getHeight();
Rectangle result = new Rectangle(bounds.x + width, bounds.y,
0, height);
return result;
@@ -375,10 +376,10 @@ public class GlyphView extends View implements TabableView, Cloneable
public float getSpan(GlyphView view, int p0, int p1,
TabExpander te, float x)
{
- Font font = view.getFont();
- FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ updateFontMetrics(view);
Segment txt = view.getText(p0, p1);
- int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
+ int span = Utilities.getTabbedTextWidth(txt, fontMetrics, (int) x, te,
+ p0);
return span;
}
@@ -395,9 +396,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getAscent(GlyphView v)
{
- Font font = v.getFont();
- FontMetrics fm = v.getContainer().getFontMetrics(font);
- return fm.getAscent();
+ updateFontMetrics(v);
+ return fontMetrics.getAscent();
}
/**
@@ -413,9 +413,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getDescent(GlyphView v)
{
- Font font = v.getFont();
- FontMetrics fm = v.getContainer().getFontMetrics(font);
- return fm.getDescent();
+ updateFontMetrics(v);
+ return fontMetrics.getDescent();
}
/**
@@ -430,16 +429,10 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public int getBoundedPosition(GlyphView v, int p0, float x, float len)
{
+ updateFontMetrics(v);
TabExpander te = v.getTabExpander();
Segment txt = v.getText(p0, v.getEndOffset());
- Font font = v.getFont();
- Container c = v.getContainer();
- FontMetrics fm;
- if (c != null)
- fm = c.getFontMetrics(font);
- else
- fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
- int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+ int pos = Utilities.getTabbedTextOffset(txt, fontMetrics, (int) x,
(int) (x + len), te, p0, false);
return pos + p0;
}
@@ -458,9 +451,33 @@ public class GlyphView extends View implements TabableView, Cloneable
public int viewToModel(GlyphView v, float x, float y, Shape a,
Bias[] biasRet)
{
- Rectangle b = a.getBounds();
- int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
- return pos + v.getStartOffset();
+ Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ int p0 = v.getStartOffset();
+ int p1 = v.getEndOffset();
+ TabExpander te = v.getTabExpander();
+ Segment s = v.getText(p0, p1);
+ int offset = Utilities.getTabbedTextOffset(s, fontMetrics, r.x, (int) x,
+ te, p0);
+ int ret = p0 + offset;
+ if (ret == p1)
+ ret--;
+ biasRet[0] = Position.Bias.Forward;
+ return ret;
+ }
+
+ private void updateFontMetrics(GlyphView v)
+ {
+ Font font = v.getFont();
+ if (fontMetrics == null || ! font.equals(fontMetrics.getFont()))
+ {
+ Container c = v.getContainer();
+ FontMetrics fm;
+ if (c != null)
+ fm = c.getFontMetrics(font);
+ else
+ fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ fontMetrics = fm;
+ }
}
}
diff --git a/javax/swing/text/ParagraphView.java b/javax/swing/text/ParagraphView.java
index 6a13b2a3e..fb4ac65d8 100644
--- a/javax/swing/text/ParagraphView.java
+++ b/javax/swing/text/ParagraphView.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package javax.swing.text;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.SizeRequirements;
@@ -104,19 +107,6 @@ public class ParagraphView extends FlowView implements TabExpander
}
/**
- * Allows rows to span the whole parent view.
- */
- public float getMaximumSpan(int axis)
- {
- float max;
- if (axis == X_AXIS)
- max = Float.MAX_VALUE;
- else
- max = super.getMaximumSpan(axis);
- return max;
- }
-
- /**
* Overridden because child views are not necessarily laid out in model
* order.
*/
diff --git a/javax/swing/text/View.java b/javax/swing/text/View.java
index aafd76a4f..dc611fe49 100644
--- a/javax/swing/text/View.java
+++ b/javax/swing/text/View.java
@@ -92,7 +92,14 @@ public abstract class View implements SwingConstants
{
int numChildren = getViewCount();
for (int i = 0; i < numChildren; i++)
- getView(i).setParent(null);
+ {
+ View child = getView(i);
+ // It is important that we only reset the parent on views that
+ // actually belong to us. In FlowView the child may already be
+ // reparented.
+ if (child.getParent() == this)
+ child.setParent(null);
+ }
}
this.parent = parent;
@@ -262,7 +269,7 @@ public abstract class View implements SwingConstants
public void removeAll()
{
- replace(0, getViewCount(), new View[0]);
+ replace(0, getViewCount(), null);
}
public void remove(int index)
@@ -618,10 +625,12 @@ public abstract class View implements SwingConstants
DocumentEvent ev, Shape shape)
{
if (ec != null && shape != null)
- preferenceChanged(null, true, true);
- Container c = getContainer();
- if (c != null)
- c.repaint();
+ {
+ preferenceChanged(null, true, true);
+ Container c = getContainer();
+ if (c != null)
+ c.repaint();
+ }
}
/**
diff --git a/javax/swing/text/html/BlockView.java b/javax/swing/text/html/BlockView.java
index 6274e7b17..d7519ef9a 100644
--- a/javax/swing/text/html/BlockView.java
+++ b/javax/swing/text/html/BlockView.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.Length;
+
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -55,7 +57,24 @@ import javax.swing.text.ViewFactory;
*/
public class BlockView extends BoxView
{
-
+
+ /**
+ * The attributes for this view.
+ */
+ private AttributeSet attributes;
+
+ /**
+ * The box painter for this view.
+ */
+ private StyleSheet.BoxPainter painter;
+
+ /**
+ * The width and height as specified in the stylesheet, null if not
+ * specified. The first value is the X_AXIS, the second the Y_AXIS. You
+ * can index this directly by the X_AXIS and Y_AXIS constants.
+ */
+ private Length[] cssSpans;
+
/**
* Creates a new view that represents an html box.
* This can be used for a number of elements.
@@ -66,8 +85,9 @@ public class BlockView extends BoxView
public BlockView(Element elem, int axis)
{
super(elem, axis);
+ cssSpans = new Length[2];
}
-
+
/**
* Creates the parent view for this. It is called before
* any other methods, if the parent view is working properly.
@@ -99,12 +119,27 @@ public class BlockView extends BoxView
protected SizeRequirements calculateMajorAxisRequirements(int axis,
SizeRequirements r)
{
- SizeRequirements sr = super.calculateMajorAxisRequirements(axis, r);
- // FIXME: adjust it if the CSS width or height attribute is specified
- // and applicable
- return sr;
+ if (r == null)
+ r = new SizeRequirements();
+
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMajorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ constrainSize(axis, r, parent);
+ }
+ else
+ r = super.calculateMajorAxisRequirements(axis, r);
+ return r;
}
-
+
/**
* Calculates the requirements along the minor axis.
* This is implemented to call the superclass and then
@@ -118,12 +153,73 @@ public class BlockView extends BoxView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
- SizeRequirements sr = super.calculateMinorAxisRequirements(axis, r);
- // FIXME: adjust it if the CSS width or height attribute is specified
- // and applicable.
- return sr;
+ if (r == null)
+ r = new SizeRequirements();
+
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ constrainSize(axis, r, parent);
+ }
+ else
+ r = super.calculateMinorAxisRequirements(axis, r);
+ return r;
}
-
+
+ /**
+ * Sets the span on the SizeRequirements object according to the
+ * according CSS span value, when it is set.
+ *
+ * @param r the size requirements
+ * @param axis the axis
+ *
+ * @return <code>true</code> when the CSS span has been set,
+ * <code>false</code> otherwise
+ */
+ private boolean setCSSSpan(SizeRequirements r, int axis)
+ {
+ boolean ret = false;
+ Length span = cssSpans[axis];
+ // We can't set relative CSS spans here because we don't know
+ // yet about the allocated span. Instead we use the view's
+ // normal requirements.
+ if (span != null && ! span.isPercentage())
+ {
+ r.minimum = (int) span.getValue();
+ r.preferred = (int) span.getValue();
+ r.maximum = (int) span.getValue();
+ ret = true;
+ }
+ return ret;
+ }
+
+ /**
+ * Constrains the <code>r</code> requirements according to
+ * <code>min</code>.
+ *
+ * @param axis the axis
+ * @param r the requirements to constrain
+ * @param min the constraining requirements
+ */
+ private void constrainSize(int axis, SizeRequirements r,
+ SizeRequirements min)
+ {
+ if (min.minimum > r.minimum)
+ {
+ r.minimum = min.minimum;
+ r.preferred = min.minimum;
+ r.maximum = Math.max(r.maximum, min.maximum);
+ }
+ }
+
/**
* Lays out the box along the minor axis (the axis that is
* perpendicular to the axis that it represents). The results
@@ -142,10 +238,40 @@ public class BlockView extends BoxView
protected void layoutMinorAxis(int targetSpan, int axis,
int[] offsets, int[] spans)
{
- // FIXME: Not implemented.
- super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+ int viewCount = getViewCount();
+ CSS.Attribute spanAtt = axis == X_AXIS ? CSS.Attribute.WIDTH
+ : CSS.Attribute.HEIGHT;
+ for (int i = 0; i < viewCount; i++)
+ {
+ View view = getView(i);
+ int min = (int) view.getMinimumSpan(axis);
+ int max;
+ // Handle CSS span value of child.
+ AttributeSet atts = view.getAttributes();
+ Length length = (Length) atts.getAttribute(spanAtt);
+ if (length != null)
+ {
+ min = Math.max((int) length.getValue(targetSpan), min);
+ max = min;
+ }
+ else
+ max = (int) view.getMaximumSpan(axis);
+
+ if (max < targetSpan)
+ {
+ // Align child.
+ float align = view.getAlignment(axis);
+ offsets[i] = (int) ((targetSpan - max) * align);
+ spans[i] = max;
+ }
+ else
+ {
+ offsets[i] = 0;
+ spans[i] = Math.max(min, targetSpan);
+ }
+ }
}
-
+
/**
* Paints using the given graphics configuration and shape.
* This delegates to the css box painter to paint the
@@ -156,11 +282,8 @@ public class BlockView extends BoxView
*/
public void paint(Graphics g, Shape a)
{
- Rectangle rect = (Rectangle) a;
- // FIXME: not fully implemented
- getStyleSheet().getBoxPainter(getAttributes()).paint(g, rect.x, rect.y,
- rect.width,
- rect.height, this);
+ Rectangle rect = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ painter.paint(g, rect.x, rect.y, rect.width, rect.height, this);
super.paint(g, a);
}
@@ -171,7 +294,9 @@ public class BlockView extends BoxView
*/
public AttributeSet getAttributes()
{
- return getStyleSheet().getViewAttributes(this);
+ if (attributes == null)
+ attributes = getStyleSheet().getViewAttributes(this);
+ return attributes;
}
/**
@@ -206,8 +331,11 @@ public class BlockView extends BoxView
if (getViewCount() == 0)
return 0.0F;
float prefHeight = getPreferredSpan(Y_AXIS);
- float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
- return (firstRowHeight / 2.F) / prefHeight;
+ View first = getView(0);
+ float firstRowHeight = first.getPreferredSpan(Y_AXIS);
+ return prefHeight != 0 ? (firstRowHeight * first.getAlignment(Y_AXIS))
+ / prefHeight
+ : 0;
}
throw new IllegalArgumentException("Invalid Axis");
}
@@ -227,7 +355,8 @@ public class BlockView extends BoxView
// If more elements were added, then need to set the properties for them
int currPos = ev.getOffset();
- if (currPos <= getStartOffset() && (currPos + ev.getLength()) >= getEndOffset())
+ if (currPos <= getStartOffset()
+ && (currPos + ev.getLength()) >= getEndOffset())
setPropertiesFromAttributes();
}
@@ -284,9 +413,27 @@ public class BlockView extends BoxView
*/
protected void setPropertiesFromAttributes()
{
- // FIXME: Not implemented (need to use StyleSheet).
+ // Fetch attributes.
+ StyleSheet ss = getStyleSheet();
+ attributes = ss.getViewAttributes(this);
+
+ // Fetch painter.
+ painter = ss.getBoxPainter(attributes);
+
+ // Update insets.
+ if (attributes != null)
+ {
+ setInsets((short) painter.getInset(TOP, this),
+ (short) painter.getInset(LEFT, this),
+ (short) painter.getInset(BOTTOM, this),
+ (short) painter.getInset(RIGHT, this));
+ }
+
+ // Fetch width and height.
+ cssSpans[X_AXIS] = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ cssSpans[Y_AXIS] = (Length) attributes.getAttribute(CSS.Attribute.HEIGHT);
}
-
+
/**
* Gets the default style sheet.
*
@@ -294,8 +441,7 @@ public class BlockView extends BoxView
*/
protected StyleSheet getStyleSheet()
{
- StyleSheet styleSheet = new StyleSheet();
- styleSheet.importStyleSheet(getClass().getResource(HTMLEditorKit.DEFAULT_CSS));
- return styleSheet;
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ return doc.getStyleSheet();
}
}
diff --git a/javax/swing/text/html/CSS.java b/javax/swing/text/html/CSS.java
index 20a2debbc..6461dca9a 100644
--- a/javax/swing/text/html/CSS.java
+++ b/javax/swing/text/html/CSS.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.BorderWidth;
import gnu.javax.swing.text.html.css.CSSColor;
import gnu.javax.swing.text.html.css.FontSize;
import gnu.javax.swing.text.html.css.FontStyle;
@@ -45,6 +46,9 @@ import gnu.javax.swing.text.html.css.Length;
import java.io.Serializable;
import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import javax.swing.text.MutableAttributeSet;
/**
* Provides CSS attributes to be used by the HTML view classes. The constants
@@ -394,6 +398,24 @@ public class CSS implements Serializable
public static final Attribute WORD_SPACING =
new Attribute("word-spacing", true, "normal");
+ // Some GNU Classpath specific extensions.
+ static final Attribute BORDER_TOP_STYLE =
+ new Attribute("border-top-style", false, null);
+ static final Attribute BORDER_BOTTOM_STYLE =
+ new Attribute("border-bottom-style", false, null);
+ static final Attribute BORDER_LEFT_STYLE =
+ new Attribute("border-left-style", false, null);
+ static final Attribute BORDER_RIGHT_STYLE =
+ new Attribute("border-right-style", false, null);
+ static final Attribute BORDER_TOP_COLOR =
+ new Attribute("border-top-color", false, null);
+ static final Attribute BORDER_BOTTOM_COLOR =
+ new Attribute("border-bottom-color", false, null);
+ static final Attribute BORDER_LEFT_COLOR =
+ new Attribute("border-left-color", false, null);
+ static final Attribute BORDER_RIGHT_COLOR =
+ new Attribute("border-right-color", false, null);
+
/**
* The attribute string.
*/
@@ -484,14 +506,44 @@ public class CSS implements Serializable
o = new FontWeight(v);
else if (att == Attribute.FONT_STYLE)
o = new FontStyle(v);
- else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR)
+ else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR
+ || att == Attribute.BORDER_COLOR
+ || att == Attribute.BORDER_TOP_COLOR
+ || att == Attribute.BORDER_BOTTOM_COLOR
+ || att == Attribute.BORDER_LEFT_COLOR
+ || att == Attribute.BORDER_RIGHT_COLOR)
o = new CSSColor(v);
else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
|| att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
- || att == Attribute.MARGIN_TOP)
+ || att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
+ || att == Attribute.HEIGHT)
o = new Length(v);
+ else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH
+ || att == Attribute.BORDER_LEFT_WIDTH
+ || att == Attribute.BORDER_RIGHT_WIDTH
+ || att == Attribute.BORDER_BOTTOM_WIDTH)
+ o = new BorderWidth(v);
else
o = v;
return o;
}
+
+ static void addInternal(MutableAttributeSet atts, Attribute a, String v)
+ {
+ if (a == Attribute.BACKGROUND)
+ parseBackgroundShorthand(atts, v);
+ }
+
+ private static void parseBackgroundShorthand(MutableAttributeSet atts,
+ String v)
+ {
+ StringTokenizer tokens = new StringTokenizer(v, " ");
+ while (tokens.hasMoreElements())
+ {
+ String token = tokens.nextToken();
+ if (CSSColor.isValidColor(token))
+ atts.addAttribute(Attribute.BACKGROUND_COLOR,
+ getValue(Attribute.BACKGROUND_COLOR, token));
+ }
+ }
}
diff --git a/javax/swing/text/html/CSSBorder.java b/javax/swing/text/html/CSSBorder.java
new file mode 100644
index 000000000..540955494
--- /dev/null
+++ b/javax/swing/text/html/CSSBorder.java
@@ -0,0 +1,420 @@
+/* CSSBorder.java -- A border for rendering CSS border styles
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath 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, or (at your option)
+any later version.
+
+GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text.html;
+
+import gnu.javax.swing.text.html.css.BorderWidth;
+import gnu.javax.swing.text.html.css.CSSColor;
+import gnu.javax.swing.text.html.css.Length;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+
+import javax.swing.border.Border;
+import javax.swing.text.AttributeSet;
+
+/**
+ * A border implementation to render CSS border styles.
+ */
+class CSSBorder
+ implements Border
+{
+
+ /**
+ * The CSS border styles.
+ */
+
+ private static final int STYLE_NOT_SET = -1;
+ private static final int STYLE_NONE = 0;
+ private static final int STYLE_HIDDEN = 1;
+ private static final int STYLE_DOTTED = 2;
+ private static final int STYLE_DASHED = 3;
+ private static final int STYLE_SOLID = 4;
+ private static final int STYLE_DOUBLE = 5;
+ private static final int STYLE_GROOVE = 6;
+ private static final int STYLE_RIDGE = 7;
+ private static final int STYLE_INSET = 8;
+ private static final int STYLE_OUTSET = 9;
+
+ /**
+ * The left insets.
+ */
+ private int left;
+
+ /**
+ * The right insets.
+ */
+ private int right;
+
+ /**
+ * The top insets.
+ */
+ private int top;
+
+ /**
+ * The bottom insets.
+ */
+ private int bottom;
+
+ /**
+ * The border style on the left.
+ */
+ private int leftStyle;
+
+ /**
+ * The border style on the right.
+ */
+ private int rightStyle;
+
+ /**
+ * The border style on the top.
+ */
+ private int topStyle;
+
+ /**
+ * The color for the top border.
+ */
+ private Color topColor;
+
+ /**
+ * The color for the bottom border.
+ */
+ private Color bottomColor;
+
+ /**
+ * The color for the left border.
+ */
+ private Color leftColor;
+
+ /**
+ * The color for the right border.
+ */
+ private Color rightColor;
+
+ /**
+ * The border style on the bottom.
+ */
+ private int bottomStyle;
+
+ /**
+ * Creates a new CSS border and fetches its attributes from the specified
+ * attribute set.
+ *
+ * @param atts the attribute set that contains the border spec
+ */
+ CSSBorder(AttributeSet atts)
+ {
+ // Determine the border styles.
+ int style = getBorderStyle(atts, CSS.Attribute.BORDER_STYLE);
+ if (style == STYLE_NOT_SET)
+ style = STYLE_NONE; // Default to none.
+ topStyle = bottomStyle = leftStyle = rightStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_TOP_STYLE);
+ if (style != STYLE_NOT_SET)
+ topStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_BOTTOM_STYLE);
+ if (style != STYLE_NOT_SET)
+ bottomStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_LEFT_STYLE);
+ if (style != STYLE_NOT_SET)
+ leftStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_RIGHT_STYLE);
+ if (style != STYLE_NOT_SET)
+ rightStyle = style;
+
+ // Determine the border colors.
+ Color color = getBorderColor(atts, CSS.Attribute.BORDER_COLOR);
+ if (color == null)
+ color = Color.BLACK;
+ topColor = bottomColor = leftColor = rightColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_TOP_COLOR);
+ if (color != null)
+ topColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_BOTTOM_COLOR);
+ if (color != null)
+ bottomColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_LEFT_COLOR);
+ if (color != null)
+ leftColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_RIGHT_COLOR);
+ if (color != null)
+ rightColor = color;
+
+ // Determine the border widths.
+ int width = getBorderWidth(atts, CSS.Attribute.BORDER_WIDTH);
+ if (width == -1)
+ width = 0;
+ top = bottom = left = right = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_TOP_WIDTH);
+ if (width >= 0)
+ top = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_BOTTOM_WIDTH);
+ if (width >= 0)
+ bottom = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_LEFT_WIDTH);
+ if (width >= 0)
+ left = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_RIGHT_WIDTH);
+ if (width >= 0)
+ right = width;
+ }
+
+ /**
+ * Determines the border style for a given CSS attribute.
+ *
+ * @param atts the attribute set
+ * @param key the CSS key
+ *
+ * @return the border style according to the constants defined in this class
+ */
+ private int getBorderStyle(AttributeSet atts, CSS.Attribute key)
+ {
+ int style = STYLE_NOT_SET;
+ Object o = atts.getAttribute(key);
+ if (o != null)
+ {
+ String cssStyle = o.toString();
+ if (cssStyle.equals("none"))
+ style = STYLE_NONE;
+ else if (cssStyle.equals("hidden"))
+ style = STYLE_HIDDEN;
+ else if (cssStyle.equals("dotted"))
+ style = STYLE_DOTTED;
+ else if (cssStyle.equals("dashed"))
+ style = STYLE_DASHED;
+ else if (cssStyle.equals("solid"))
+ style = STYLE_SOLID;
+ else if (cssStyle.equals("double"))
+ style = STYLE_DOUBLE;
+ else if (cssStyle.equals("groove"))
+ style = STYLE_GROOVE;
+ else if (cssStyle.equals("ridge"))
+ style = STYLE_RIDGE;
+ else if (cssStyle.equals("inset"))
+ style = STYLE_INSET;
+ else if (cssStyle.equals("outset"))
+ style = STYLE_OUTSET;
+ }
+ return style;
+ }
+
+ /**
+ * Determines the border color for the specified key.
+ *
+ * @param atts the attribute set from which to fetch the color
+ * @param key the CSS key
+ *
+ * @return the border color
+ */
+ private Color getBorderColor(AttributeSet atts, CSS.Attribute key)
+ {
+ Object o = atts.getAttribute(key);
+ Color color = null;
+ if (o instanceof CSSColor)
+ {
+ CSSColor cssColor = (CSSColor) o;
+ color = cssColor.getValue();
+ }
+ return color;
+ }
+
+ /**
+ * Returns the width for the specified key.
+ *
+ * @param atts the attributes to fetch the width from
+ * @param key the CSS key
+ *
+ * @return the width, or -1 of none has been set
+ */
+ private int getBorderWidth(AttributeSet atts, CSS.Attribute key)
+ {
+ int width = -1;
+ Object o = atts.getAttribute(key);
+ if (o instanceof BorderWidth)
+ {
+ width = (int) ((BorderWidth) o).getValue();
+ }
+ return width;
+ }
+
+ /**
+ * Returns the border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return new Insets(top, left, bottom, right);
+ }
+
+ /**
+ * CSS borders are generally opaque so return true here.
+ */
+ public boolean isBorderOpaque()
+ {
+ return true;
+ }
+
+ public void paintBorder(Component c, Graphics g, int x, int y, int width,
+ int height)
+ {
+ // Top border.
+ paintBorderLine(g, x, y + top / 2, x + width, y + top / 2, topStyle, top,
+ topColor, false);
+ // Left border.
+ paintBorderLine(g, x + left / 2, y, x + left / 2, y + height, leftStyle,
+ left, leftColor, true);
+ // Bottom border.
+ paintBorderLine(g, x, y + height - bottom / 2, x + width,
+ y + height - bottom / 2, topStyle, bottom, bottomColor,
+ false);
+ // Right border.
+ paintBorderLine(g, x + width - right / 2, y, x + width - right / 2,
+ y + height, topStyle, right, rightColor, true);
+
+ }
+
+ private void paintBorderLine(Graphics g, int x1, int y1, int x2, int y2,
+ int style, int width, Color color,
+ boolean vertical)
+ {
+ switch (style)
+ {
+ case STYLE_DOTTED:
+ paintDottedLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_DASHED:
+ paintDashedLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_SOLID:
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_DOUBLE:
+ paintDoubleLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_GROOVE:
+ paintGrooveLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_RIDGE:
+ paintRidgeLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_OUTSET:
+ paintOutsetLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_INSET:
+ paintInsetLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_NONE:
+ case STYLE_HIDDEN:
+ default:
+ // Nothing to do in these cases.
+ }
+ }
+
+ private void paintDottedLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintDashedLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintSolidLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ int x = Math.min(x1, x2);
+ int y = Math.min(y1, y1);
+ int w = Math.abs(x2 - x1);
+ int h = Math.abs(y2 - y1);
+ if (vertical)
+ {
+ w = width;
+ x -= width / 2;
+ }
+ else
+ {
+ h = width;
+ y -= width / 2;
+ }
+ g.setColor(color);
+ g.fillRect(x, y, w, h);
+ }
+
+ private void paintDoubleLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintGrooveLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintRidgeLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintOutsetLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintInsetLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+}
diff --git a/javax/swing/text/html/HTMLDocument.java b/javax/swing/text/html/HTMLDocument.java
index 2e2eb3abc..26e3fb4bc 100644
--- a/javax/swing/text/html/HTMLDocument.java
+++ b/javax/swing/text/html/HTMLDocument.java
@@ -39,10 +39,10 @@ exception statement from your version. */
package javax.swing.text.html;
import gnu.classpath.NotImplementedException;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import java.io.IOException;
import java.io.StringReader;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -571,6 +571,16 @@ public class HTMLDocument extends DefaultStyledDocument
boolean inPreTag = false;
/**
+ * True when we are inside a paragraph (P, H1-H6, P-IMPLIED).
+ */
+ boolean inParagraph = false;
+
+ /**
+ * True when we are currently inside an implied paragraph.
+ */
+ boolean inImpliedParagraph = false;
+
+ /**
* This is true when we are inside a style tag. This will add text
* content inside this style tag beeing parsed as CSS.
*
@@ -600,12 +610,6 @@ public class HTMLDocument extends DefaultStyledDocument
*/
Document textAreaDocument;
- void print (String line)
- {
- if (debug)
- System.out.println (line);
- }
-
public class TagAction
{
/**
@@ -813,6 +817,7 @@ public class HTMLDocument extends DefaultStyledDocument
public void start(HTML.Tag t, MutableAttributeSet a)
{
blockOpen(t, a);
+ inParagraph = true;
}
/**
@@ -822,6 +827,7 @@ public class HTMLDocument extends DefaultStyledDocument
public void end(HTML.Tag t)
{
blockClose(t);
+ inParagraph = false;
}
}
@@ -882,7 +888,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("AreaAction.start not implemented");
}
/**
@@ -893,7 +898,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("AreaAction.end not implemented");
}
}
@@ -942,7 +946,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("BaseAction.start not implemented");
}
/**
@@ -953,7 +956,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("BaseAction.end not implemented");
}
}
@@ -967,7 +969,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("HeadAction.start not implemented: "+t);
super.start(t, a);
}
@@ -992,29 +993,71 @@ public class HTMLDocument extends DefaultStyledDocument
}
}
- class LinkAction extends TagAction
+ class LinkAction extends HiddenAction
{
/**
* This method is called when a start tag is seen for one of the types
* of tags associated with this Action.
*/
public void start(HTML.Tag t, MutableAttributeSet a)
- throws NotImplementedException
{
- // FIXME: Implement.
- print ("LinkAction.start not implemented");
+ super.start(t, a);
+ String type = (String) a.getAttribute(HTML.Attribute.TYPE);
+ if (type == null)
+ type = "text/css";
+ if (type.equals("text/css"))
+ {
+ String rel = (String) a.getAttribute(HTML.Attribute.REL);
+ String media = (String) a.getAttribute(HTML.Attribute.MEDIA);
+ String title = (String) a.getAttribute(HTML.Attribute.TITLE);
+ if (media == null)
+ media = "all";
+ else
+ media = media.toLowerCase();
+ if (rel != null)
+ {
+ rel = rel.toLowerCase();
+ if ((media.indexOf("all") != -1
+ || media.indexOf("screen") != -1)
+ && (rel.equals("stylesheet")))
+ {
+ String href = (String) a.getAttribute(HTML.Attribute.HREF);
+ URL url = null;
+ try
+ {
+ url = new URL(baseURL, href);
+ }
+ catch (MalformedURLException ex)
+ {
+ try
+ {
+ url = new URL(href);
+ }
+ catch (MalformedURLException ex2)
+ {
+ url = null;
+ }
+ }
+ if (url != null)
+ {
+ try
+ {
+ getStyleSheet().importStyleSheet(url);
+ }
+ catch (Exception ex)
+ {
+ // Don't let exceptions and runtime exceptions
+ // in CSS parsing disprupt the HTML parsing
+ // process. But inform the user/developer
+ // on the console about it.
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ }
}
- /**
- * Called when an end tag is seen for one of the types of tags associated
- * with this Action.
- */
- public void end(HTML.Tag t)
- throws NotImplementedException
- {
- // FIXME: Implement.
- print ("LinkAction.end not implemented");
- }
}
class MapAction extends TagAction
@@ -1027,7 +1070,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MapAction.start not implemented");
}
/**
@@ -1038,7 +1080,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MapAction.end not implemented");
}
}
@@ -1052,7 +1093,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MetaAction.start not implemented");
}
/**
@@ -1063,7 +1103,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MetaAction.end not implemented");
}
}
@@ -1098,7 +1137,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("TitleAction.start not implemented");
}
/**
@@ -1109,7 +1147,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("TitleAction.end not implemented");
}
}
@@ -1121,9 +1158,6 @@ public class HTMLDocument extends DefaultStyledDocument
public HTMLReader(int offset, int popDepth, int pushDepth,
HTML.Tag insertTag)
{
- print ("HTMLReader created with pop: "+popDepth
- + " push: "+pushDepth + " offset: "+offset
- + " tag: "+insertTag);
this.insertTag = insertTag;
this.offset = offset;
this.popDepth = popDepth;
@@ -1351,8 +1385,7 @@ public class HTMLDocument extends DefaultStyledDocument
TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
if (action != null)
{
- action.start(HTML.Tag.COMMENT,
- htmlAttributeSet.EMPTY_HTML_ATTRIBUTE_SET);
+ action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
action.end(HTML.Tag.COMMENT);
}
}
@@ -1414,7 +1447,6 @@ public class HTMLDocument extends DefaultStyledDocument
public void handleEndOfLineString(String eol)
{
// FIXME: Implement.
- print ("HTMLReader.handleEndOfLineString not implemented yet");
}
/**
@@ -1475,7 +1507,9 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
{
- printBuffer();
+ if (inImpliedParagraph)
+ blockClose(HTML.Tag.IMPLIED);
+
DefaultStyledDocument.ElementSpec element;
parseStack.push(t);
@@ -1485,7 +1519,6 @@ public class HTMLDocument extends DefaultStyledDocument
element = new DefaultStyledDocument.ElementSpec(copy,
DefaultStyledDocument.ElementSpec.StartTagType);
parseBuffer.addElement(element);
- printBuffer();
}
/**
@@ -1496,9 +1529,16 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void blockClose(HTML.Tag t)
{
- printBuffer();
DefaultStyledDocument.ElementSpec element;
+ if (inImpliedParagraph)
+ {
+ inImpliedParagraph = false;
+ inParagraph = false;
+ if (t != HTML.Tag.IMPLIED)
+ blockClose(HTML.Tag.IMPLIED);
+ }
+
// If the previous tag is a start tag then we insert a synthetic
// content tag.
DefaultStyledDocument.ElementSpec prev;
@@ -1519,7 +1559,6 @@ public class HTMLDocument extends DefaultStyledDocument
element = new DefaultStyledDocument.ElementSpec(null,
DefaultStyledDocument.ElementSpec.EndTagType);
parseBuffer.addElement(element);
- printBuffer();
if (parseStack.size() > 0)
parseStack.pop();
}
@@ -1550,6 +1589,13 @@ public class HTMLDocument extends DefaultStyledDocument
protected void addContent(char[] data, int offs, int length,
boolean generateImpliedPIfNecessary)
{
+ if (generateImpliedPIfNecessary && (! inParagraph) && (! inPreTag))
+ {
+ blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+ inParagraph = true;
+ inImpliedParagraph = true;
+ }
+
AbstractDocument.AttributeContext ctx = getAttributeContext();
DefaultStyledDocument.ElementSpec element;
AttributeSet attributes = null;
@@ -1566,10 +1612,8 @@ public class HTMLDocument extends DefaultStyledDocument
DefaultStyledDocument.ElementSpec.ContentType,
data, offs, length);
- printBuffer();
// Add the element to the buffer
parseBuffer.addElement(element);
- printBuffer();
if (parseBuffer.size() > HTMLDocument.this.getTokenThreshold())
{
@@ -1592,29 +1636,25 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
{
+ if (t != HTML.Tag.FRAME && ! inParagraph && ! inImpliedParagraph)
+ {
+ blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+ inParagraph = true;
+ inImpliedParagraph = true;
+ }
+
a.addAttribute(StyleConstants.NameAttribute, t);
- // Migrate from the rather htmlAttributeSet to the faster, lighter and
- // unchangeable alternative implementation.
- AttributeSet copy = a.copyAttributes();
-
// The two spaces are required because some special elements like HR
// must be broken. At least two characters are needed to break into the
// two parts.
DefaultStyledDocument.ElementSpec spec =
- new DefaultStyledDocument.ElementSpec(copy,
+ new DefaultStyledDocument.ElementSpec(a.copyAttributes(),
DefaultStyledDocument.ElementSpec.ContentType,
new char[] {' ', ' '}, 0, 2 );
parseBuffer.add(spec);
}
- void printBuffer()
- {
- print ("\n*********BUFFER**********");
- for (int i = 0; i < parseBuffer.size(); i ++)
- print (" "+parseBuffer.get(i));
- print ("***************************");
- }
}
/**
diff --git a/javax/swing/text/html/HTMLEditorKit.java b/javax/swing/text/html/HTMLEditorKit.java
index c541a4d34..85d5221d3 100644
--- a/javax/swing/text/html/HTMLEditorKit.java
+++ b/javax/swing/text/html/HTMLEditorKit.java
@@ -82,7 +82,7 @@ import javax.swing.text.html.parser.ParserDelegator;
/* Move these imports here after javax.swing.text.html to make it compile
with jikes. */
import gnu.javax.swing.text.html.parser.GnuParserDelegator;
-import gnu.javax.swing.text.html.parser.HTML_401Swing;
+import gnu.javax.swing.text.html.parser.HTML_401F;
/**
* @author Lillian Angel (langel at redhat dot com)
@@ -646,15 +646,12 @@ public class HTMLEditorKit
else if (tag.equals(HTML.Tag.IMG))
view = new ImageView(element);
- // FIXME: Uncomment when the views have been implemented
else if (tag.equals(HTML.Tag.CONTENT))
view = new InlineView(element);
else if (tag == HTML.Tag.HEAD)
view = new NullView(element);
else if (tag.equals(HTML.Tag.TABLE))
view = new javax.swing.text.html.TableView(element);
- else if (tag.equals(HTML.Tag.TD))
- view = new ParagraphView(element);
else if (tag.equals(HTML.Tag.HR))
view = new HRuleView(element);
else if (tag.equals(HTML.Tag.BR))
@@ -663,10 +660,11 @@ public class HTMLEditorKit
|| tag.equals(HTML.Tag.TEXTAREA))
view = new FormView(element);
- /*
else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR)
|| tag.equals(HTML.Tag.UL) || tag.equals(HTML.Tag.OL))
view = new ListView(element);
+ // FIXME: Uncomment when the views have been implemented
+ /*
else if (tag.equals(HTML.Tag.OBJECT))
view = new ObjectView(element);
else if (tag.equals(HTML.Tag.FRAMESET))
@@ -973,7 +971,7 @@ public class HTMLEditorKit
{
if (parser == null)
{
- parser = new GnuParserDelegator(HTML_401Swing.getInstance());
+ parser = new GnuParserDelegator(HTML_401F.getInstance());
}
return parser;
}
diff --git a/javax/swing/text/html/HTMLWriter.java b/javax/swing/text/html/HTMLWriter.java
index 16e9a7163..44119c732 100644
--- a/javax/swing/text/html/HTMLWriter.java
+++ b/javax/swing/text/html/HTMLWriter.java
@@ -608,28 +608,8 @@ public class HTMLWriter
closeOutUnwantedEmbeddedTags(attrSet);
- // NOTE: 20061030 - fchoong - GNU CP uses a different implimentation of
- // the IMPLIED tag.
- boolean fg_gnu_cp_implied_tag = false;
-
- if (matchNameAttribute(attrSet, HTML.Tag.P))
- {
- //writeAllAttributes(attrSet);
-
- Enumeration attrNameEnum = attrSet.getAttributeNames();
-
- while (attrNameEnum.hasMoreElements())
- {
- Object key = attrNameEnum.nextElement();
- Object value = attrSet.getAttribute(key);
-
- if (key.equals("_implied_") && value.toString().equals("true"))
- fg_gnu_cp_implied_tag = true;
- } // while(attrNameEnum.hasMoreElements())
- } // if(matchNameAttribute(attrSet, HTML.Tag.P))
-
// handle the tag
- if (synthesizedElement(paramElem) || fg_gnu_cp_implied_tag)
+ if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
@@ -640,8 +620,7 @@ public class HTMLWriter
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
- else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED)
- || fg_gnu_cp_implied_tag) // NOTE: GNU CP specific
+ else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
@@ -782,28 +761,8 @@ public class HTMLWriter
if (fg_is_fragment_parent_elem || (fg_pass_start_elem
&& fg_pass_end_elem == false) || fg_is_start_and_end_elem)
{
- // NOTE: 20061030 - fchoong - GNU CP uses a different implimentation of
- // the IMPLIED tag.
- boolean fg_gnu_cp_implied_tag = false;
-
- if (matchNameAttribute(attrSet, HTML.Tag.P))
- {
- //writeAllAttributes(attrSet);
-
- Enumeration attrNameEnum = attrSet.getAttributeNames();
-
- while (attrNameEnum.hasMoreElements())
- {
- Object key = attrNameEnum.nextElement();
- Object value = attrSet.getAttribute(key);
-
- if (key.equals("_implied_") && value.toString().equals("true"))
- fg_gnu_cp_implied_tag = true;
- } // while(attrNameEnum.hasMoreElements())
- } // if(matchNameAttribute(attrSet, HTML.Tag.P))
-
// handle the tag
- if (synthesizedElement(paramElem) || fg_gnu_cp_implied_tag)
+ if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
@@ -862,8 +821,7 @@ public class HTMLWriter
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
- else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED)
- || fg_gnu_cp_implied_tag) // NOTE: GNU CP specific
+ else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
diff --git a/javax/swing/text/html/InlineView.java b/javax/swing/text/html/InlineView.java
index 31eaa129c..6b134ae39 100644
--- a/javax/swing/text/html/InlineView.java
+++ b/javax/swing/text/html/InlineView.java
@@ -38,13 +38,17 @@ exception statement from your version. */
package javax.swing.text.html;
+import java.awt.FontMetrics;
import java.awt.Shape;
+import java.text.BreakIterator;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.LabelView;
+import javax.swing.text.Segment;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
@@ -65,6 +69,18 @@ public class InlineView
private AttributeSet attributes;
/**
+ * The span of the longest word in this view.
+ *
+ * @see #getLongestWord()
+ */
+ private float longestWord;
+
+ /**
+ * Indicates if we may wrap or not.
+ */
+ private boolean nowrap;
+
+ /**
* Creates a new <code>InlineView</code> that renders the specified element.
*
* @param element the element for this view
@@ -144,8 +160,13 @@ public class InlineView
public int getBreakWeight(int axis, float pos, float len)
{
- // FIXME: Implement this.
- return super.getBreakWeight(axis, pos, len);
+ int weight;
+ if (nowrap) { if (getText(getStartOffset(), getEndOffset()).toString().contains("Web"))
+ System.err.println("Web NOWRAP");
+ weight = BadBreakWeight;}
+ else
+ weight = super.getBreakWeight(axis, pos, len);
+ return weight;
}
public View breakView(int axis, int offset, float pos, float len)
@@ -190,7 +211,12 @@ public class InlineView
b = true;
setSuperscript(b);
- // TODO: Handle white-space: nowrap property.
+ // Fetch nowrap setting.
+ o = atts.getAttribute(CSS.Attribute.WHITE_SPACE);
+ if (o != null && o.equals("nowrap"))
+ nowrap = true;
+ else
+ nowrap = false;
}
/**
@@ -207,4 +233,74 @@ public class InlineView
styleSheet = ((HTMLDocument) doc).getStyleSheet();
return styleSheet;
}
+
+ /**
+ * Returns the minimum span for the specified axis. This returns the
+ * width of the longest word for the X axis and the super behaviour for
+ * the Y axis. This is a slight deviation from the reference implementation.
+ * IMO this should improve rendering behaviour so that an InlineView never
+ * gets smaller than the longest word in it.
+ */
+ public float getMinimumSpan(int axis)
+ {
+ float min = super.getMinimumSpan(axis);
+ if (axis == X_AXIS)
+ min = Math.max(getLongestWord(), min);
+ return min;
+ }
+
+ /**
+ * Returns the span of the longest word in this view.
+ *
+ * @return the span of the longest word in this view
+ */
+ private float getLongestWord()
+ {
+ if (longestWord == -1)
+ longestWord = calculateLongestWord();
+ return longestWord;
+ }
+
+ /**
+ * Calculates the span of the longest word in this view.
+ *
+ * @return the span of the longest word in this view
+ */
+ private float calculateLongestWord()
+ {
+ float span = 0;
+ try
+ {
+ Document doc = getDocument();
+ int p0 = getStartOffset();
+ int p1 = getEndOffset();
+ Segment s = new Segment();
+ doc.getText(p0, p1 - p0, s);
+ BreakIterator iter = BreakIterator.getWordInstance();
+ iter.setText(s);
+ int wordStart = p0;
+ int wordEnd = p0;
+ int start = iter.first();
+ for (int end = iter.next(); end != BreakIterator.DONE;
+ start = end, end = iter.next())
+ {
+ if ((end - start) > (wordEnd - wordStart))
+ {
+ wordStart = start;
+ wordEnd = end;
+ }
+ }
+ if (wordEnd - wordStart > 0)
+ {
+ FontMetrics fm = getFontMetrics();
+ int offset = s.offset + wordStart - s.getBeginIndex();
+ span = fm.charsWidth(s.array, offset, wordEnd - wordStart);
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ // Return 0.
+ }
+ return span;
+ }
}
diff --git a/javax/swing/text/html/ListView.java b/javax/swing/text/html/ListView.java
index c07d3598c..3e809bbd2 100644
--- a/javax/swing/text/html/ListView.java
+++ b/javax/swing/text/html/ListView.java
@@ -94,9 +94,6 @@ public class ListView
public void paint(Graphics g, Shape allocation)
{
super.paint(g, allocation);
- // FIXME: Why is this overridden? I think that painting would be done
- // by the superclass and the stylesheet... Maybe find out when this
- // stuff is implemented properly.
}
/**
diff --git a/javax/swing/text/html/ParagraphView.java b/javax/swing/text/html/ParagraphView.java
index 951f70b60..e3f2817be 100644
--- a/javax/swing/text/html/ParagraphView.java
+++ b/javax/swing/text/html/ParagraphView.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.Length;
+
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -71,6 +73,16 @@ public class ParagraphView
private StyleSheet.BoxPainter painter;
/**
+ * The width as specified in the stylesheet or null if not specified.
+ */
+ private Length cssWidth;
+
+ /**
+ * The height as specified in the stylesheet or null if not specified.
+ */
+ private Length cssHeight;
+
+ /**
* Creates a new ParagraphView for the specified element.
*
* @param element the element
@@ -116,29 +128,34 @@ public class ParagraphView
super.setPropertiesFromAttributes();
// Fetch CSS attributes.
- AttributeSet atts = getAttributes();
- Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
- if (o != null)
+ attributes = getAttributes();
+ if (attributes != null)
{
- String align = o.toString();
- if (align.equals("left"))
- setJustification(StyleConstants.ALIGN_LEFT);
- else if (align.equals("right"))
- setJustification(StyleConstants.ALIGN_RIGHT);
- else if (align.equals("center"))
- setJustification(StyleConstants.ALIGN_CENTER);
- else if (align.equals("justify"))
- setJustification(StyleConstants.ALIGN_JUSTIFIED);
- }
+ super.setPropertiesFromAttributes();
+ Object o = attributes.getAttribute(CSS.Attribute.TEXT_ALIGN);
+ if (o != null)
+ {
+ String align = o.toString();
+ if (align.equals("left"))
+ setJustification(StyleConstants.ALIGN_LEFT);
+ else if (align.equals("right"))
+ setJustification(StyleConstants.ALIGN_RIGHT);
+ else if (align.equals("center"))
+ setJustification(StyleConstants.ALIGN_CENTER);
+ else if (align.equals("justify"))
+ setJustification(StyleConstants.ALIGN_JUSTIFIED);
+ }
- // Fetch StyleSheet's box painter.
- painter = getStyleSheet().getBoxPainter(atts);
- setInsets((short) painter.getInset(TOP, this),
- (short) painter.getInset(LEFT, this),
- (short) painter.getInset(BOTTOM, this),
- (short) painter.getInset(RIGHT, this));
+ // Fetch StyleSheet's box painter.
+ painter = getStyleSheet().getBoxPainter(attributes);
+ setInsets((short) painter.getInset(TOP, this),
+ (short) painter.getInset(LEFT, this),
+ (short) painter.getInset(BOTTOM, this),
+ (short) painter.getInset(RIGHT, this));
- // TODO: Handle CSS width and height attributes somehow.
+ cssWidth = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ cssHeight = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ }
}
/**
@@ -169,8 +186,66 @@ public class ParagraphView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
- // FIXME: Implement the above specified behaviour.
- return super.calculateMinorAxisRequirements(axis, r);
+ r = super.calculateMinorAxisRequirements(axis, r);
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ }
+ else
+ {
+ float min = 0;
+ int n = getLayoutViewCount();
+ for (int i = 0; i < n; i++)
+ min = Math.max(getLayoutView(i).getMinimumSpan(axis), min);
+ r.minimum = (int) min;
+ r.preferred = Math.max(r.preferred, r.minimum);
+ r.maximum = Math.max(r.maximum, r.preferred);
+ }
+ return r;
+ }
+
+ /**
+ * Sets the span on the SizeRequirements object according to the
+ * according CSS span value, when it is set.
+ *
+ * @param r the size requirements
+ * @param axis the axis
+ *
+ * @return <code>true</code> when the CSS span has been set,
+ * <code>false</code> otherwise
+ */
+ private boolean setCSSSpan(SizeRequirements r, int axis)
+ {
+ boolean ret = false;
+ if (axis == X_AXIS)
+ {
+ if (cssWidth != null && ! cssWidth.isPercentage())
+ {
+ r.minimum = (int) cssWidth.getValue();
+ r.preferred = (int) cssWidth.getValue();
+ r.maximum = (int) cssWidth.getValue();
+ ret = true;
+ }
+ }
+ else
+ {
+ if (cssHeight != null && ! cssWidth.isPercentage())
+ {
+ r.minimum = (int) cssHeight.getValue();
+ r.preferred = (int) cssHeight.getValue();
+ r.maximum = (int) cssHeight.getValue();
+ ret = true;
+ }
+ }
+ return ret;
}
/**
diff --git a/javax/swing/text/html/StyleSheet.java b/javax/swing/text/html/StyleSheet.java
index 703a3864a..add22e01c 100644
--- a/javax/swing/text/html/StyleSheet.java
+++ b/javax/swing/text/html/StyleSheet.java
@@ -45,21 +45,27 @@ import gnu.javax.swing.text.html.css.FontSize;
import gnu.javax.swing.text.html.css.FontStyle;
import gnu.javax.swing.text.html.css.FontWeight;
import gnu.javax.swing.text.html.css.Length;
+import gnu.javax.swing.text.html.css.Selector;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
-import java.util.StringTokenizer;
+import javax.swing.border.Border;
import javax.swing.event.ChangeListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
@@ -86,7 +92,7 @@ import javax.swing.text.View;
*
* The rules are stored as named styles, and other information is stored to
* translate the context of an element to a rule.
- *
+ *
* @author Lillian Angel (langel@redhat.com)
*/
public class StyleSheet extends StyleContext
@@ -101,21 +107,35 @@ public class StyleSheet extends StyleContext
implements CSSParserCallback
{
/**
- * The selector for which the rules are currently parsed.
+ * The current style.
+ */
+ private CSSStyle style;
+
+ /**
+ * The precedence of the stylesheet to be parsed.
*/
- private String[] selector;
+ private int precedence;
+
+ /**
+ * Creates a new CSS parser. This parser parses a CSS stylesheet with
+ * the specified precedence.
+ *
+ * @param prec the precedence, according to the constants defined in
+ * CSSStyle
+ */
+ CSSStyleSheetParserCallback(int prec)
+ {
+ precedence = prec;
+ }
/**
* Called at the beginning of a statement.
*
* @param sel the selector
*/
- public void startStatement(String sel)
+ public void startStatement(Selector sel)
{
- StringTokenizer tokens = new StringTokenizer(sel);
- selector = new String[tokens.countTokens()];
- for (int index = 0; tokens.hasMoreTokens(); index++)
- selector[index] = tokens.nextToken();
+ style = new CSSStyle(precedence, sel);
}
/**
@@ -123,7 +143,8 @@ public class StyleSheet extends StyleContext
*/
public void endStatement()
{
- selector = null;
+ css.add(style);
+ style = null;
}
/**
@@ -134,23 +155,13 @@ public class StyleSheet extends StyleContext
*/
public void declaration(String property, String value)
{
- for (int i = 0; i < selector.length; i++)
- {
- CSSStyle style = (CSSStyle) css.get(selector[i]);
- if (style == null)
- {
- style = new CSSStyle();
- css.put(selector[i], style);
- }
- CSS.Attribute cssAtt = CSS.getAttribute(property);
- Object val = CSS.getValue(cssAtt, value);
- if (cssAtt != null)
- style.addAttribute(cssAtt, val);
- // else // For debugging only.
- // System.err.println("no mapping for: " + property);
- }
+ CSS.Attribute cssAtt = CSS.getAttribute(property);
+ Object val = CSS.getValue(cssAtt, value);
+ CSS.addInternal(style, cssAtt, value);
+ if (cssAtt != null)
+ style.addAttribute(cssAtt, val);
}
-
+
}
/**
@@ -158,9 +169,33 @@ public class StyleSheet extends StyleContext
*/
private class CSSStyle
extends SimpleAttributeSet
- implements Style
+ implements Style, Comparable
{
+ static final int PREC_UA = 400000;
+ static final int PREC_NORM = 300000;
+ static final int PREC_AUTHOR_NORMAL = 200000;
+ static final int PREC_AUTHOR_IMPORTANT = 100000;
+ static final int PREC_USER_IMPORTANT = 0;
+
+ /**
+ * The priority of this style when matching CSS selectors.
+ */
+ private int precedence;
+
+ /**
+ * The selector for this rule.
+ *
+ * This is package private to avoid accessor methods.
+ */
+ Selector selector;
+
+ CSSStyle(int prec, Selector sel)
+ {
+ precedence = prec;
+ selector = sel;
+ }
+
public String getName()
{
// TODO: Implement this for correctness.
@@ -176,6 +211,17 @@ public class StyleSheet extends StyleContext
{
// TODO: Implement this for correctness.
}
+
+ /**
+ * Sorts the rule according to the style's precedence and the
+ * selectors specificity.
+ */
+ public int compareTo(Object o)
+ {
+ CSSStyle other = (CSSStyle) o;
+ return other.precedence + other.selector.getSpecificity()
+ - precedence - selector.getSpecificity();
+ }
}
@@ -192,7 +238,7 @@ public class StyleSheet extends StyleContext
* Maps element names (selectors) to AttributSet (the corresponding style
* information).
*/
- HashMap css = new HashMap();
+ ArrayList css = new ArrayList();
/**
* Maps selectors to their resolved styles.
@@ -371,14 +417,17 @@ public class StyleSheet extends StyleContext
// the default.css.
int count = tags.length;
ArrayList styles = new ArrayList();
- for (int i = 0; i < count; i++)
+ for (Iterator i = css.iterator(); i.hasNext();)
{
- Style style = (Style) css.get(tags[i]);
- if (style != null)
+ CSSStyle style = (CSSStyle) i.next();
+ if (style.selector.matches(tags, classes, ids))
styles.add(style);
- // FIXME: Handle ID and CLASS attributes.
}
+
+ // Sort selectors.
+ Collections.sort(styles);
Style[] styleArray = new Style[styles.size()];
+ styleArray = (Style[]) styles.toArray(styleArray);
Style resolved = new MultiStyle(selector,
(Style[]) styles.toArray(styleArray));
resolvedStyles.put(selector, resolved);
@@ -395,9 +444,15 @@ public class StyleSheet extends StyleContext
*/
public Style getRule(String selector)
{
- // FIXME: This is a very rudimentary implementation. Should
- // be extended to conform to the CSS spec.
- return (Style) css.get(selector);
+ Selector sel = new Selector(selector);
+ CSSStyle best = null;
+ for (Iterator i = css.iterator(); i.hasNext();)
+ {
+ CSSStyle style = (CSSStyle) i.next();
+ if (style.compareTo(best) < 0)
+ best = style;
+ }
+ return best;
}
/**
@@ -408,7 +463,8 @@ public class StyleSheet extends StyleContext
*/
public void addRule(String rule)
{
- CSSStyleSheetParserCallback cb = new CSSStyleSheetParserCallback();
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_AUTHOR_NORMAL);
// FIXME: Handle ref.
StringReader in = new StringReader(rule);
CSSParser parser = new CSSParser(in, cb);
@@ -419,7 +475,7 @@ public class StyleSheet extends StyleContext
catch (IOException ex)
{
// Shouldn't happen. And if, then we
- assert false;
+ System.err.println("IOException while parsing stylesheet: " + ex.getMessage());
}
}
@@ -451,7 +507,8 @@ public class StyleSheet extends StyleContext
public void loadRules(Reader in, URL ref)
throws IOException
{
- CSSStyleSheetParserCallback cb = new CSSStyleSheetParserCallback();
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_UA);
// FIXME: Handle ref.
CSSParser parser = new CSSParser(in, cb);
parser.parse();
@@ -543,13 +600,26 @@ public class StyleSheet extends StyleContext
/**
* Imports a style sheet from the url. The rules are directly added to the
- * receiver.
+ * receiver. This is usually called when a <link> tag is resolved in an
+ * HTML document.
*
- * @param url - the URL to import the StyleSheet from.
+ * @param url the URL to import the StyleSheet from
*/
public void importStyleSheet(URL url)
{
- // FIXME: Not implemented
+ try
+ {
+ InputStream in = url.openStream();
+ Reader r = new BufferedReader(new InputStreamReader(in));
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_AUTHOR_NORMAL);
+ CSSParser parser = new CSSParser(r, cb);
+ parser.parse();
+ }
+ catch (IOException ex)
+ {
+ // We can't do anything about it I guess.
+ }
}
/**
@@ -585,6 +655,7 @@ public class StyleSheet extends StyleContext
String value)
{
Object val = CSS.getValue(key, value);
+ CSS.addInternal(attr, key, value);
attr.addAttribute(key, val);
}
@@ -615,11 +686,31 @@ public class StyleSheet extends StyleContext
*/
public AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet)
{
- // FIXME: Really convert HTML to CSS here.
AttributeSet cssAttr = htmlAttrSet.copyAttributes();
- MutableAttributeSet cssStyle = addStyle(null, null);
- cssStyle.addAttributes(cssAttr);
- return cssStyle;
+
+ // The HTML align attribute maps directly to the CSS text-align attribute.
+ Object o = htmlAttrSet.getAttribute(HTML.Attribute.ALIGN);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.TEXT_ALIGN, o);
+
+ // The HTML width attribute maps directly to CSS width.
+ o = htmlAttrSet.getAttribute(HTML.Attribute.WIDTH);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.WIDTH,
+ CSS.getValue(CSS.Attribute.WIDTH, o.toString()));
+
+ // The HTML height attribute maps directly to CSS height.
+ o = htmlAttrSet.getAttribute(HTML.Attribute.HEIGHT);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.HEIGHT,
+ CSS.getValue(CSS.Attribute.HEIGHT, o.toString()));
+
+ o = htmlAttrSet.getAttribute(HTML.Attribute.NOWRAP);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.WHITE_SPACE, "nowrap");
+
+ // TODO: Add more mappings.
+ return cssAttr;
}
/**
@@ -802,7 +893,7 @@ public class StyleSheet extends StyleContext
*/
public BoxPainter getBoxPainter(AttributeSet a)
{
- return new BoxPainter(a);
+ return new BoxPainter(a, this);
}
/**
@@ -813,7 +904,7 @@ public class StyleSheet extends StyleContext
*/
public ListPainter getListPainter(AttributeSet a)
{
- return new ListPainter(a);
+ return new ListPainter(a, this);
}
/**
@@ -920,17 +1011,42 @@ public class StyleSheet extends StyleContext
public static class BoxPainter extends Object implements Serializable
{
+ /**
+ * The left inset.
+ */
private float leftInset;
+
+ /**
+ * The right inset.
+ */
private float rightInset;
+
+ /**
+ * The top inset.
+ */
private float topInset;
+
+ /**
+ * The bottom inset.
+ */
private float bottomInset;
/**
+ * The border of the box.
+ */
+ private Border border;
+
+ /**
+ * The background color.
+ */
+ private Color background;
+
+ /**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
- BoxPainter(AttributeSet as)
+ BoxPainter(AttributeSet as, StyleSheet ss)
{
Length l = (Length) as.getAttribute(CSS.Attribute.MARGIN_LEFT);
if (l != null)
@@ -944,6 +1060,13 @@ public class StyleSheet extends StyleContext
l = (Length) as.getAttribute(CSS.Attribute.MARGIN_BOTTOM);
if (l != null)
bottomInset = l.getValue();
+
+ // Determine border.
+ border = new CSSBorder(as);
+
+ // Determine background.
+ background = ss.getBackground(as);
+
}
@@ -965,15 +1088,23 @@ public class StyleSheet extends StyleContext
{
case View.TOP:
inset = topInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).top;
break;
case View.BOTTOM:
inset = bottomInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).bottom;
break;
case View.LEFT:
inset = leftInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).left;
break;
case View.RIGHT:
inset = rightInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).right;
break;
default:
inset = 0.0F;
@@ -994,7 +1125,16 @@ public class StyleSheet extends StyleContext
*/
public void paint(Graphics g, float x, float y, float w, float h, View v)
{
- // FIXME: Not implemented.
+
+ if (background != null)
+ {
+ g.setColor(background);
+ g.fillRect((int) x, (int) y, (int) w, (int) h);
+ }
+ if (border != null)
+ {
+ border.paintBorder(null, g, (int) x, (int) y, (int) w, (int) h);
+ }
}
}
@@ -1005,24 +1145,36 @@ public class StyleSheet extends StyleContext
*
* @author Lillian Angel (langel@redhat.com)
*/
- public static class ListPainter extends Object implements Serializable
+ public static class ListPainter implements Serializable
{
-
+
/**
* Attribute set for painter
*/
- AttributeSet as;
-
+ private AttributeSet attributes;
+
+ /**
+ * The associated style sheet.
+ */
+ private StyleSheet styleSheet;
+
+ /**
+ * The bullet type.
+ */
+ private String type;
+
/**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
- ListPainter(AttributeSet as)
+ ListPainter(AttributeSet as, StyleSheet ss)
{
- this.as = as;
+ attributes = as;
+ styleSheet = ss;
+ type = (String) as.getAttribute(CSS.Attribute.LIST_STYLE_TYPE);
}
-
+
/**
* Paints the CSS list decoration according to the attributes given.
*
@@ -1037,7 +1189,19 @@ public class StyleSheet extends StyleContext
public void paint(Graphics g, float x, float y, float w, float h, View v,
int item)
{
- // FIXME: Not implemented.
+ // FIXME: This is a very simplistic list rendering. We still need
+ // to implement different bullet types (see type field) and custom
+ // bullets via images.
+ View itemView = v.getView(item);
+ AttributeSet viewAtts = itemView.getAttributes();
+ Object tag = viewAtts.getAttribute(StyleConstants.NameAttribute);
+ // Only paint something here when the child view is an LI tag
+ // and the calling view is some of the list tags then).
+ if (tag != null && tag == HTML.Tag.LI)
+ {
+ g.setColor(Color.BLACK);
+ g.fillOval((int) x - 15, (int) (h / 2 - 3 + y), 6, 6);
+ }
}
}
diff --git a/javax/swing/text/html/TableView.java b/javax/swing/text/html/TableView.java
index c2edc8cdd..2bd11ffcf 100644
--- a/javax/swing/text/html/TableView.java
+++ b/javax/swing/text/html/TableView.java
@@ -38,49 +38,185 @@ exception statement from your version. */
package javax.swing.text.html;
-import javax.swing.text.Document;
+import gnu.javax.swing.text.html.css.Length;
+
+import javax.swing.SizeRequirements;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BoxView;
import javax.swing.text.Element;
+import javax.swing.text.StyleConstants;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
/**
- * A conrete implementation of TableView that renders HTML tables.
- *
- * @author Roman Kennke (kennke@aicas.com)
+ * A view implementation that renders HTML tables.
+ *
+ * This is basically a vertical BoxView that contains the rows of the table
+ * and the rows are horizontal BoxViews that contain the actual columns.
*/
class TableView
- extends javax.swing.text.TableView
+ extends BoxView
+ implements ViewFactory
{
+
/**
* Represents a single table row.
*/
- public class RowView extends TableRow
+ class RowView
+ extends BlockView
{
/**
- * Creates a new instance of the <code>RowView</code>.
+ * Creates a new RowView.
*
- * @param el the element for which to create a row view
+ * @param el the element for the row view
+ */
+ RowView(Element el)
+ {
+ super(el, X_AXIS);
+ }
+
+ /**
+ * Overridden to make rows not resizable along the Y axis.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float span;
+ if (axis == Y_AXIS)
+ span = super.getPreferredSpan(axis);
+ else
+ span = super.getMaximumSpan(axis);
+ return span;
+ }
+
+ /**
+ * Calculates the overall size requirements for the row along the
+ * major axis. This will be the sum of the column requirements.
+ */
+ protected SizeRequirements calculateMajorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ if (r == null)
+ r = new SizeRequirements();
+ r.minimum = totalColumnRequirements.minimum;
+ r.preferred = totalColumnRequirements.preferred;
+ r.maximum = totalColumnRequirements.maximum;
+ r.alignment = 0.0F;
+ return r;
+ }
+
+ /**
+ * Lays out the columns in this row.
*/
- public RowView(Element el)
+ protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
+ int spans[])
{
- super(el);
+ int numCols = offsets.length;
+ int realColumn = 0;
+ for (int i = 0; i < numCols; i++)
+ {
+ View v = getView(i);
+ if (v instanceof CellView)
+ {
+ CellView cv = (CellView) v;
+ offsets[i] = columnOffsets[realColumn];
+ spans[i] = 0;
+ for (int j = 0; j < cv.colSpan; j++, realColumn++)
+ {
+ spans[i] += columnSpans[realColumn];
+ }
+ }
+ }
}
-
+ }
+
/**
- * Get the associated style sheet from the document.
- *
- * @return the associated style sheet.
+ * A view that renders HTML table cells (TD and TH tags).
*/
- protected StyleSheet getStyleSheet()
+ class CellView
+ extends BlockView
+ {
+
+ /**
+ * The number of columns that this view spans.
+ */
+ int colSpan;
+
+ /**
+ * Creates a new CellView for the specified element.
+ *
+ * @param el the element for which to create the colspan
+ */
+ CellView(Element el)
{
- Document d = getElement().getDocument();
- if (d instanceof HTMLDocument)
- return ((HTMLDocument) d).getStyleSheet();
- else
- return null;
- }
+ super(el, Y_AXIS);
+ }
+
+ /**
+ * Overridden to fetch the columnSpan attibute.
+ */
+ protected void setPropertiesFromAttributes()
+ {
+ super.setPropertiesFromAttributes();
+ colSpan = 1;
+ AttributeSet atts = getAttributes();
+ Object o = atts.getAttribute(HTML.Attribute.COLSPAN);
+ if (o != null)
+ {
+ try
+ {
+ colSpan = Integer.parseInt(o.toString());
+ }
+ catch (NumberFormatException ex)
+ {
+ // Couldn't parse the colspan, assume 1.
+ colSpan = 1;
+ }
+ }
+ }
}
+
+ /**
+ * The attributes of this view.
+ */
+ private AttributeSet attributes;
+
+ /**
+ * The column requirements.
+ */
+ private SizeRequirements[] columnRequirements;
+
+ /**
+ * The overall requirements across all columns.
+ *
+ * Package private to avoid accessor methods.
+ */
+ SizeRequirements totalColumnRequirements;
+
+ /**
+ * The column layout, offsets.
+ *
+ * Package private to avoid accessor methods.
+ */
+ int[] columnOffsets;
+
+ /**
+ * The column layout, spans.
+ *
+ * Package private to avoid accessor methods.
+ */
+ int[] columnSpans;
+
+ /**
+ * The widths of the columns that have been explicitly specified.
+ */
+ Length[] columnWidths;
+
+ /**
+ * Indicates if the grid setup is ok.
+ */
+ private boolean gridValid;
+
/**
* Creates a new HTML table view for the specified element.
*
@@ -88,50 +224,424 @@ class TableView
*/
public TableView(Element el)
{
- super(el);
+ super(el, Y_AXIS);
+ totalColumnRequirements = new SizeRequirements();
}
-
+
/**
- * Get the associated style sheet from the document.
- *
- * @return the associated style sheet.
+ * Implementation of the ViewFactory interface for creating the
+ * child views correctly.
*/
- protected StyleSheet getStyleSheet()
+ public View create(Element elem)
{
- Document d = getElement().getDocument();
- if (d instanceof HTMLDocument)
- return ((HTMLDocument) d).getStyleSheet();
- else
- return null;
- }
-
+ View view = null;
+ AttributeSet atts = elem.getAttributes();
+ Object name = atts.getAttribute(StyleConstants.NameAttribute);
+ if (name instanceof HTML.Tag)
+ {
+ HTML.Tag tag = (HTML.Tag) name;
+ if (tag == HTML.Tag.TR)
+ view = new RowView(elem);
+ else if (tag == HTML.Tag.TD || tag == HTML.Tag.TH)
+ view = new CellView(elem);
+ else if (tag == HTML.Tag.CAPTION)
+ view = new ParagraphView(elem);
+ }
+
+ // If we haven't mapped the element, then fall back to the standard
+ // view factory.
+ if (view == null)
+ {
+ View parent = getParent();
+ if (parent != null)
+ {
+ ViewFactory vf = parent.getViewFactory();
+ if (vf != null)
+ view = vf.create(elem);
+ }
+ }
+ return view;
+ }
+
/**
- * Creates a view for a table row.
- *
- * @param el the element that represents the table row
- * @return a view for rendering the table row
- * (and instance of {@link RowView}).
+ * Returns this object as view factory so that we get our TR, TD, TH
+ * and CAPTION subelements created correctly.
*/
- protected TableRow createTableRow(Element el)
+ public ViewFactory getViewFactory()
{
- return new RowView(el);
- }
-
+ return this;
+ }
+
/**
- * Loads the children of the Table. This completely bypasses the ViewFactory
- * and creates instances of TableRow instead.
+ * Returns the attributes of this view. This is overridden to provide
+ * the attributes merged with the CSS stuff.
+ */
+ public AttributeSet getAttributes()
+ {
+ if (attributes == null)
+ attributes = getStyleSheet().getViewAttributes(this);
+ return attributes;
+ }
+
+ /**
+ * Returns the stylesheet associated with this view.
*
- * @param vf ignored
+ * @return the stylesheet associated with this view
*/
- protected void loadChildren(ViewFactory vf)
+ private StyleSheet getStyleSheet()
{
- Element el = getElement();
- int numChildren = el.getElementCount();
- View[] rows = new View[numChildren];
- for (int i = 0; i < numChildren; ++i)
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ return doc.getStyleSheet();
+ }
+
+ /**
+ * Overridden to calculate the size requirements according to the
+ * columns distribution.
+ */
+ protected SizeRequirements calculateMinorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ updateGrid();
+ calculateColumnRequirements();
+
+ // Calculate the horizontal requirements according to the superclass.
+ // This will return the maximum of the row's widths.
+ r = super.calculateMinorAxisRequirements(axis, r);
+
+ // Try to set the CSS width if it fits.
+ AttributeSet atts = getAttributes();
+ Length l = (Length) atts.getAttribute(CSS.Attribute.WIDTH);
+ if (l != null)
+ {
+ int width = (int) l.getValue();
+ if (r.minimum < width)
+ r.minimum = width;
+ }
+
+ // Apply the alignment.
+ Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
+ r.alignment = 0.0F;
+ if (o != null)
{
- rows[i] = createTableRow(el.getElement(i));
+ String al = o.toString();
+ if (al.equals("left"))
+ r.alignment = 0.0F;
+ else if (al.equals("center"))
+ r.alignment = 0.5F;
+ else if (al.equals("right"))
+ r.alignment = 1.0F;
}
- replace(0, getViewCount(), rows);
+
+ return r;
+ }
+
+ /**
+ * Overridden to perform the table layout before calling the super
+ * implementation.
+ */
+ protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
+ int[] spans)
+ {
+ updateGrid();
+ layoutColumns(targetSpan);
+ super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+ }
+
+ /**
+ * Calculates the size requirements for the columns.
+ */
+ private void calculateColumnRequirements()
+ {
+ int numRows = getViewCount();
+ totalColumnRequirements.minimum = 0;
+ totalColumnRequirements.preferred = 0;
+ totalColumnRequirements.maximum = 0;
+
+ // In this first pass we find out a suitable total width to fit in
+ // all columns of all rows.
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+
+ // We collect the normal (non-relative) column requirements in the
+ // total variable and the relative requirements in the relTotal
+ // variable. In the end we create the maximum of both to get the
+ // real requirements.
+ SizeRequirements total = new SizeRequirements();
+ SizeRequirements relTotal = new SizeRequirements();
+ float totalPercent = 0.F;
+ for (int c = 0; c < numCols; )
+ {
+ View v = rowView.getView(c);
+ if (v instanceof CellView)
+ {
+ CellView cellView = (CellView) v;
+ int colSpan = cellView.colSpan;
+ if (colSpan > 1)
+ {
+ int cellMin = (int) cellView.getMinimumSpan(X_AXIS);
+ int cellPref = (int) cellView.getPreferredSpan(X_AXIS);
+ int cellMax = (int) cellView.getMaximumSpan(X_AXIS);
+ int currentMin = 0;
+ int currentPref = 0;
+ long currentMax = 0;
+ for (int i = 0; i < colSpan; i++)
+ {
+ SizeRequirements req = columnRequirements[c + i];
+ currentMin += req.minimum;
+ currentPref += req.preferred;
+ currentMax += req.maximum;
+ }
+ int deltaMin = cellMin - currentMin;
+ int deltaPref = cellPref - currentPref;
+ int deltaMax = (int) (cellMax - currentMax);
+ // Distribute delta.
+ for (int i = 0; i < colSpan; i++)
+ {
+ SizeRequirements req = columnRequirements[c + i];
+ if (deltaMin > 0)
+ req.minimum += deltaMin / colSpan;
+ if (deltaPref > 0)
+ req.preferred += deltaPref / colSpan;
+ if (deltaMax > 0)
+ req.maximum += deltaMax / colSpan;
+ if (columnWidths[c + i] == null
+ || ! columnWidths[c + i].isPercentage())
+ {
+ total.minimum += req.minimum;
+ total.preferred += req.preferred;
+ total.maximum += req.maximum;
+ }
+ else
+ {
+ relTotal.minimum =
+ Math.max(relTotal.minimum,
+ (int) (req.minimum
+ * columnWidths[c + i].getValue()));
+ relTotal.preferred =
+ Math.max(relTotal.preferred,
+ (int) (req.preferred
+ * columnWidths[c + i].getValue()));
+ relTotal.maximum =
+ Math.max(relTotal.maximum,
+ (int) (req.maximum
+ * columnWidths[c + i].getValue()));
+ totalPercent += columnWidths[c + i].getValue();
+ }
+ }
+ }
+ else
+ {
+ // Shortcut for colSpan == 1.
+ SizeRequirements req = columnRequirements[c];
+ req.minimum = Math.max(req.minimum,
+ (int) cellView.getMinimumSpan(X_AXIS));
+ req.preferred = Math.max(req.preferred,
+ (int) cellView.getPreferredSpan(X_AXIS));
+ req.maximum = Math.max(req.maximum,
+ (int) cellView.getMaximumSpan(X_AXIS));
+ if (columnWidths[c] == null
+ || ! columnWidths[c].isPercentage())
+ {
+ total.minimum += columnRequirements[c].minimum;
+ total.preferred += columnRequirements[c].preferred;
+ total.maximum += columnRequirements[c].maximum;
+ }
+ else
+ {
+ relTotal.minimum =
+ Math.max(relTotal.minimum,
+ (int) (req.minimum
+ / columnWidths[c].getValue()));
+ relTotal.preferred =
+ Math.max(relTotal.preferred,
+ (int) (req.preferred
+ / columnWidths[c].getValue()));
+ relTotal.maximum =
+ Math.max(relTotal.maximum,
+ (int) (req.maximum
+ / columnWidths[c].getValue()));
+ totalPercent += columnWidths[c].getValue();
+ }
+ }
+ c += colSpan;
+ }
+ else
+ c++;
+ }
+
+ // Update the total requirements as follows:
+ // 1. Multiply the absolute requirements with 1 - totalPercent. This
+ // gives the total requirements based on the wishes of the absolute
+ // cells.
+ // 2. Take the maximum of this value and the total relative
+ // requirements. Now we should have enough space for whatever cell
+ // in this column.
+ // 3. Take the maximum of this value and the previous maximum value.
+ total.minimum *= 1.F / (1.F - totalPercent);
+ total.preferred *= 1.F / (1.F - totalPercent);
+ total.maximum *= 1.F / (1.F - totalPercent);
+
+ int rowTotalMin = Math.max(total.minimum, relTotal.minimum);
+ int rowTotalPref = Math.max(total.preferred, relTotal.preferred);
+ int rowTotalMax = Math.max(total.maximum, relTotal.maximum);
+ totalColumnRequirements.minimum =
+ Math.max(totalColumnRequirements.minimum, rowTotalMin);
+ totalColumnRequirements.preferred =
+ Math.max(totalColumnRequirements.preferred, rowTotalPref);
+ totalColumnRequirements.maximum =
+ Math.max(totalColumnRequirements.maximum, rowTotalMax);
+ }
+
+ // Now we know what we want and can fix up the actual relative
+ // column requirements.
+ int numCols = columnRequirements.length;
+ for (int i = 0; i < numCols; i++)
+ {
+ if (columnWidths[i] != null)
+ {
+ columnRequirements[i].minimum = (int)
+ columnWidths[i].getValue(totalColumnRequirements.minimum);
+ columnRequirements[i].preferred = (int)
+ columnWidths[i].getValue(totalColumnRequirements.preferred);
+ columnRequirements[i].maximum = (int)
+ columnWidths[i].getValue(totalColumnRequirements.maximum);
+ }
+ }
+ }
+
+ /**
+ * Lays out the columns.
+ *
+ * @param targetSpan the target span into which the table is laid out
+ */
+ private void layoutColumns(int targetSpan)
+ {
+ // Set the spans to the preferred sizes. Determine the space
+ // that we have to adjust the sizes afterwards.
+ long sumPref = 0;
+ int n = columnRequirements.length;
+ for (int i = 0; i < n; i++)
+ {
+ SizeRequirements col = columnRequirements[i];
+ if (columnWidths[i] != null)
+ columnSpans[i] = (int) columnWidths[i].getValue(targetSpan);
+ else
+ columnSpans[i] = col.preferred;
+ sumPref += columnSpans[i];
+ }
+
+ // Try to adjust the spans so that we fill the targetSpan.
+ long diff = targetSpan - sumPref;
+ float factor = 0.0F;
+ int[] diffs = null;
+ if (diff != 0)
+ {
+ long total = 0;
+ diffs = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ // Only adjust the width if we haven't set a column width here.
+ if (columnWidths[i] == null)
+ {
+ SizeRequirements col = columnRequirements[i];
+ int span;
+ if (diff < 0)
+ {
+ span = col.minimum;
+ diffs[i] = columnSpans[i] - span;
+ }
+ else
+ {
+ span = col.maximum;
+ diffs[i] = span - columnSpans[i];
+ }
+ total += span;
+ }
+ else
+ total += columnSpans[i];
+ }
+
+ float maxAdjust = Math.abs(total - sumPref);
+ factor = diff / maxAdjust;
+ factor = Math.min(factor, 1.0F);
+ factor = Math.max(factor, -1.0F);
+ }
+
+ // Actually perform adjustments.
+ int totalOffs = 0;
+ for (int i = 0; i < n; i++)
+ {
+ columnOffsets[i] = totalOffs;
+ if (diff != 0)
+ {
+ float adjust = factor * diffs[i];
+ columnSpans[i] += Math.round(adjust);
+ }
+ // Avoid overflow here.
+ totalOffs = (int) Math.min((long) totalOffs + (long) columnSpans[i],
+ Integer.MAX_VALUE);
+ }
+ }
+
+ /**
+ * Updates the arrays that contain the row and column data in response
+ * to a change to the table structure.
+ */
+ private void updateGrid()
+ {
+ if (! gridValid)
+ {
+ int maxColumns = 0;
+ int numRows = getViewCount();
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+ maxColumns = Math.max(numCols, maxColumns);
+ }
+ columnWidths = new Length[maxColumns];
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+ int colIndex = 0;
+ for (int c = 0; c < numCols; c++)
+ {
+ View v = rowView.getView(c);
+ if (v instanceof CellView)
+ {
+ CellView cv = (CellView) v;
+ Object o =
+ cv.getAttributes().getAttribute(CSS.Attribute.WIDTH);
+ if (o != null && columnWidths[colIndex] == null
+ && o instanceof Length)
+ columnWidths[colIndex]= (Length) o;
+ colIndex += cv.colSpan;
+ }
+ }
+ }
+ columnRequirements = new SizeRequirements[maxColumns];
+ for (int i = 0; i < maxColumns; i++)
+ columnRequirements[i] = new SizeRequirements();
+ columnOffsets = new int[maxColumns];
+ columnSpans = new int[maxColumns];
+
+ gridValid = true;
+ }
+ }
+
+ /**
+ * Overridden to restrict the table width to the preferred size.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = super.getPreferredSpan(axis);
+ else
+ span = super.getMaximumSpan(axis);
+ return span;
}
}
diff --git a/javax/swing/text/html/parser/DocumentParser.java b/javax/swing/text/html/parser/DocumentParser.java
index 062606d17..f717d69cb 100644
--- a/javax/swing/text/html/parser/DocumentParser.java
+++ b/javax/swing/text/html/parser/DocumentParser.java
@@ -38,13 +38,13 @@ exception statement from your version. */
package javax.swing.text.html.parser;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import javax.swing.text.html.parser.Parser;
import java.io.IOException;
import java.io.Reader;
import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
/**
@@ -117,7 +117,7 @@ public class DocumentParser
protected final void handleStartTag(TagElement tag)
{
parser.handleStartTag(tag);
- htmlAttributeSet attributes = gnu.getAttributes();
+ SimpleAttributeSet attributes = gnu.getAttributes();
if (tag.fictional())
attributes.addAttribute(HTMLEditorKit.ParserCallback.IMPLIED,
diff --git a/javax/swing/text/html/parser/ParserDelegator.java b/javax/swing/text/html/parser/ParserDelegator.java
index 70636d929..cdd339b8f 100644
--- a/javax/swing/text/html/parser/ParserDelegator.java
+++ b/javax/swing/text/html/parser/ParserDelegator.java
@@ -38,13 +38,13 @@ exception statement from your version. */
package javax.swing.text.html.parser;
import gnu.javax.swing.text.html.parser.HTML_401F;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
@@ -93,7 +93,7 @@ public class ParserDelegator
protected final void handleStartTag(TagElement tag)
{
- htmlAttributeSet attributes = gnu.getAttributes();
+ SimpleAttributeSet attributes = gnu.getAttributes();
if (tag.fictional())
attributes.addAttribute(ParserCallback.IMPLIED, Boolean.TRUE);