This fixes the line breaking hints for styled text and HTML.
2006-10-12 Roman Kennke <[EMAIL PROTECTED]>
PR 28696
* javax/swing/text/FlowView.java
(FlowStrategy.layout): Preserve logical views from getting lost.
(FlowStrategy.layoutRow): Fix line breaking.
(FlowStrategy.adjustRow): Fix line breaking.
(FlowStrategy.changedUpdate): Mark layout invalid, or repaint.
(FlowStrategy.insertUpdate): Mark layout invalid, or repaint.
(FlowStrategy.removeUpdate): Mark layout invalid, or repaint.
(createView): Don't check index.
(contains): New helper method.
(reparent): New helper method.
(layoutDirty): Removed unneeded field.
(FlowView): Removed layoutDirty field init.
(changedUpdate): Removed layoutDirty handling.
(insertUpdate): Removed layoutDirty handling.
(removeUpdate): Removed layoutDirty handling.
(layout): Use isLayoutValid() rather than the layoutDirty field.
* javax/swing/text/GlyphView.java
(startOffset): Removed.
(endOffset): Removed.
(offset): New field.
(length): New field.
(GlyphView): Initialize new fields. Removed old fields.
(createFragment): Create fragment with new relative offsets.
(getEndOffset): Work with new relative offsets.
(getStartOffset): Work with new relative offsets.
* javax/swing/text/ParagraphView.java
(Row.getStartOffset): Overidden to determine the minimum start
offset from the children.
(Row.getEndOffset): Overidden to determine the maximum end
offset from the children.
* javax/swing/text/html/BRView.java
Make subclass of InlineView.
(getBreakWeight): Fall back to super for Y_AXIS.
/Roman
Index: javax/swing/text/FlowView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/FlowView.java,v
retrieving revision 1.16
diff -u -1 -5 -r1.16 FlowView.java
--- javax/swing/text/FlowView.java 24 Aug 2006 16:17:09 -0000 1.16
+++ javax/swing/text/FlowView.java 12 Oct 2006 15:12:21 -0000
@@ -26,30 +26,31 @@
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;
+import java.awt.Component;
import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.SizeRequirements;
import javax.swing.event.DocumentEvent;
/**
* A <code>View</code> that can flows it's children into it's layout space.
*
* The <code>FlowView</code> manages a set of logical views (that are
* the children of the [EMAIL PROTECTED] #layoutPool} field). These are translated
* at layout time into a set of physical views. These are the views that
* are managed as the real child views. Each of these child views represents
* a row and are laid out within a box using the superclasses behaviour.
* The concrete implementation of the rows must be provided by subclasses.
@@ -73,255 +74,366 @@
}
/**
* Receives notification from a <code>FlowView</code> that some content
* has been inserted into the document at a location that the
* <code>FlowView</code> is responsible for.
*
* The default implementation simply calls [EMAIL PROTECTED] #layout}.
*
* @param fv the flow view that sends the notification
* @param e the document event describing the change
* @param alloc the current allocation of the flow view
*/
public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
{
- // The default implementation does nothing.
+ if (alloc != null)
+ {
+ fv.layoutChanged(X_AXIS);
+ fv.layoutChanged(Y_AXIS);
+ }
+ else
+ {
+ Component host = fv.getContainer();
+ if (host != null)
+ host.repaint();
+ }
}
/**
* Receives notification from a <code>FlowView</code> that some content
* has been removed from the document at a location that the
* <code>FlowView</code> is responsible for.
*
* The default implementation simply calls [EMAIL PROTECTED] #layout}.
*
* @param fv the flow view that sends the notification
* @param e the document event describing the change
* @param alloc the current allocation of the flow view
*/
public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
{
- // The default implementation does nothing.
+ if (alloc != null)
+ {
+ fv.layoutChanged(X_AXIS);
+ fv.layoutChanged(Y_AXIS);
+ }
+ else
+ {
+ Component host = fv.getContainer();
+ if (host != null)
+ host.repaint();
+ }
}
/**
* Receives notification from a <code>FlowView</code> that some attributes
* have changed in the document at a location that the
* <code>FlowView</code> is responsible for.
*
* The default implementation simply calls [EMAIL PROTECTED] #layout}.
*
* @param fv the flow view that sends the notification
* @param e the document event describing the change
* @param alloc the current allocation of the flow view
*/
public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
{
- // The default implementation does nothing.
+ if (alloc != null)
+ {
+ fv.layoutChanged(X_AXIS);
+ fv.layoutChanged(Y_AXIS);
+ }
+ else
+ {
+ Component host = fv.getContainer();
+ if (host != null)
+ host.repaint();
+ }
}
/**
* Returns the logical view of the managed <code>FlowView</code>.
*
* @param fv the flow view for which to return the logical view
*
* @return the logical view of the managed <code>FlowView</code>
*/
protected View getLogicalView(FlowView fv)
{
return fv.layoutPool;
}
/**
* Performs the layout for the whole view. By default this rebuilds
* all the physical views from the logical views of the managed FlowView.
*
* This is called by [EMAIL PROTECTED] FlowView#layout} to update the layout of
* the view.
*
* @param fv the flow view for which we perform the layout
*/
public void layout(FlowView fv)
{
- fv.removeAll();
- Element el = fv.getElement();
+ int start = fv.getStartOffset();
+ int end = fv.getEndOffset();
+
+ // Preserve the views from the logical view from beeing removed.
+ View lv = getLogicalView(fv);
+ int viewCount = lv.getViewCount();
+ for (int i = 0; i < viewCount; i++)
+ {
+ View v = lv.getView(i);
+ v.setParent(lv);
+ }
- int rowStart = el.getStartOffset();
- int end = el.getEndOffset();
- int rowIndex = 0;
- while (rowStart >= 0 && rowStart < end)
+ // Then remove all views from the flow view.
+ fv.removeAll();
+
+ for (int rowIndex = 0; start < end; rowIndex++)
{
View row = fv.createRow();
fv.append(row);
- rowStart = layoutRow(fv, rowIndex, rowStart);
- rowIndex++;
+ int next = layoutRow(fv, rowIndex, start);
+ if (row.getViewCount() == 0)
+ {
+ row.append(createView(fv, start, Integer.MAX_VALUE, rowIndex));
+ next = row.getEndOffset();
+ }
+ if (start < next)
+ start = next;
+ else
+ assert false: "May not happen";
}
}
/**
* Lays out one row of the flow view. This is called by [EMAIL PROTECTED] #layout} to
* fill one row with child views until the available span is exhausted. The
* default implementation fills the row by calling
* [EMAIL PROTECTED] #createView(FlowView, int, int, int)} until the available space is
* exhausted, a forced break is encountered or there are no more views in
* the logical view. If the available space is exhausted,
* [EMAIL PROTECTED] #adjustRow(FlowView, int, int, int)} is called to fit the row into
* the available span.
*
* @param fv the flow view for which we perform the layout
* @param rowIndex the index of the row
* @param pos the model position for the beginning of the row
* @return the start position of the next row
*/
protected int layoutRow(FlowView fv, int rowIndex, int pos)
{
View row = fv.getView(rowIndex);
int axis = fv.getFlowAxis();
int span = fv.getFlowSpan(rowIndex);
int x = fv.getFlowStart(rowIndex);
- int offset = pos;
- View logicalView = getLogicalView(fv);
- // Special case when span == 0. We need to layout the row as if it had
- // a span of Integer.MAX_VALUE.
- if (span == 0)
- span = Integer.MAX_VALUE;
+ int end = fv.getEndOffset();
+
+ // Needed for adjusting indentation in adjustRow().
+ int preX = x;
+ int availableSpan = span;
- Row: while (span > 0)
+ TabExpander tabExp = fv instanceof TabExpander ? (TabExpander) fv : null;
+
+ boolean forcedBreak = false;
+ while (pos < end && span >= 0)
{
- if (logicalView.getViewIndex(offset, Position.Bias.Forward) == - 1)
- break;
- View view = createView(fv, offset, span, rowIndex);
- if (view == null)
+ View view = createView(fv, pos, span, rowIndex);
+ if (view == null
+ || (span == 0 && view.getPreferredSpan(axis) > 0))
break;
- int viewSpan = (int) view.getPreferredSpan(axis);
- int breakWeight = view.getBreakWeight(axis, x, span);
-
- row.append(view);
- offset += (view.getEndOffset() - view.getStartOffset());
- x += viewSpan;
- span -= viewSpan;
+ int viewSpan;
+ if (axis == X_AXIS && view instanceof TabableView)
+ viewSpan = (int) ((TabableView) view).getTabbedSpan(x, tabExp);
+ else
+ viewSpan = (int) view.getPreferredSpan(axis);
// Break if the line if the view does not fit in this row or the
// line just must be broken.
- if (span < 0 || breakWeight >= View.ForcedBreakWeight)
+ int breakWeight = view.getBreakWeight(axis, pos, span);
+ if (breakWeight >= ForcedBreakWeight)
{
- int flowStart = fv.getFlowStart(axis);
- int flowSpan = fv.getFlowSpan(axis);
- adjustRow(fv, rowIndex, flowSpan, flowStart);
int rowViewCount = row.getViewCount();
if (rowViewCount > 0)
- offset = row.getView(rowViewCount - 1).getEndOffset();
- else
- offset = - 1;
- break Row;
+ {
+ view = view.breakView(axis, pos, x, span);
+ if (view != null)
+ {
+ if (axis == X_AXIS && view instanceof TabableView)
+ viewSpan =
+ (int) ((TabableView) view).getTabbedSpan(x, tabExp);
+ else
+ viewSpan = (int) view.getPreferredSpan(axis);
+ }
+ else
+ viewSpan = 0;
+ }
+ forcedBreak = true;
}
+ span -= viewSpan;
+ x += viewSpan;
+ if (view != null)
+ {
+ row.append(view);
+ pos = view.getEndOffset();
+ }
+ if (forcedBreak)
+ break;
}
- return offset != pos ? offset : - 1;
+ if (span < 0)
+ adjustRow(fv, rowIndex, availableSpan, preX);
+ else if (row.getViewCount() == 0)
+ {
+ View view = createView(fv, pos, Integer.MAX_VALUE, rowIndex);
+ row.append(view);
+ }
+ return row.getEndOffset();
}
/**
* Creates physical views that form the rows of the flow view. This
* can be an entire view from the logical view (if it fits within the
* available span), a fragment of such a view (if it doesn't fit in the
* available span and can be broken down) or <code>null</code> (if it does
* not fit in the available span and also cannot be broken down).
*
* The default implementation fetches the logical view at the specified
* <code>startOffset</code>. If that view has a different startOffset than
* specified in the argument, a fragment is created using
* [EMAIL PROTECTED] View#createFragment(int, int)} that has the correct startOffset
* and the logical view's endOffset.
*
* @param fv the flow view
* @param startOffset the start offset for the view to be created
* @param spanLeft the available span
* @param rowIndex the index of the row
*
* @return a view to fill the row with, or <code>null</code> if there
* is no view or view fragment that fits in the available span
*/
protected View createView(FlowView fv, int startOffset, int spanLeft,
int rowIndex)
{
View logicalView = getLogicalView(fv);
// FIXME: Handle the bias thing correctly.
int index = logicalView.getViewIndex(startOffset, Position.Bias.Forward);
- View retVal = null;
- if (index >= 0)
- {
- retVal = logicalView.getView(index);
- if (retVal.getStartOffset() != startOffset)
- retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
- }
+ View retVal = logicalView.getView(index);
+ if (retVal.getStartOffset() != startOffset)
+ retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
return retVal;
}
/**
* Tries to adjust the specified row to fit within the desired span. The
* default implementation iterates through the children of the specified
* row to find the view that has the highest break weight and - if there
* is more than one view with such a break weight - which is nearest to
* the end of the row. If there is such a view that has a break weight >
* [EMAIL PROTECTED] View#BadBreakWeight}, this view is broken using the
* [EMAIL PROTECTED] View#breakView(int, int, float, float)} method and this view and
* all views after the now broken view are replaced by the broken view.
*
* @param fv the flow view
* @param rowIndex the index of the row to be adjusted
* @param desiredSpan the layout span
* @param x the X location at which the row starts
*/
protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) {
// Determine the last view that has the highest break weight.
int axis = fv.getFlowAxis();
View row = fv.getView(rowIndex);
int count = row.getViewCount();
int breakIndex = -1;
- int maxBreakWeight = View.BadBreakWeight;
- int breakX = x;
- int breakSpan = desiredSpan;
- int currentX = x;
- int currentSpan = desiredSpan;
+ int breakWeight = BadBreakWeight;
+ int breakSpan = 0;
+ int currentSpan = 0;
for (int i = 0; i < count; ++i)
{
View view = row.getView(i);
- int weight = view.getBreakWeight(axis, currentX, currentSpan);
- if (weight >= maxBreakWeight)
+ int spanLeft = desiredSpan - currentSpan;
+ int weight = view.getBreakWeight(axis, x + currentSpan, spanLeft);
+ if (weight >= breakWeight && weight > BadBreakWeight)
{
breakIndex = i;
- breakX = currentX;
breakSpan = currentSpan;
- maxBreakWeight = weight;
+ breakWeight = weight;
+ if (weight >= ForcedBreakWeight)
+ // Don't search further.
+ break;
}
- int size = (int) view.getPreferredSpan(axis);
- currentX += size;
- currentSpan -= size;
+ currentSpan += view.getPreferredSpan(axis);
}
// If there is a potential break location found, break the row at
// this location.
- if (breakIndex > -1)
+ if (breakIndex >= 0)
{
+ int spanLeft = desiredSpan - breakSpan;
View toBeBroken = row.getView(breakIndex);
View brokenView = toBeBroken.breakView(axis,
toBeBroken.getStartOffset(),
- breakX, breakSpan);
+ x + breakSpan, spanLeft);
+ View lv = getLogicalView(fv);
+ for (int i = breakIndex; i < count; i++)
+ {
+ View tmp = row.getView(i);
+ if (contains(lv, tmp))
+ tmp.setParent(lv);
+ else if (tmp.getViewCount() > 0)
+ reparent(tmp, lv);
+ }
row.replace(breakIndex, count - breakIndex,
- new View[]{brokenView});
+ new View[]{ brokenView });
+ }
+
+ }
+
+ /**
+ * Helper method to determine if one view contains another as child.
+ */
+ private boolean contains(View view, View child)
+ {
+ boolean ret = false;
+ int n = view.getViewCount();
+ for (int i = 0; i < n && ret == false; i++)
+ {
+ if (view.getView(i) == child)
+ ret = true;
+ }
+ return ret;
+ }
+
+ /**
+ * Helper method that reparents the <code>view</code> and all of its
+ * decendents to the <code>parent</code> (the logical view).
+ *
+ * @param view the view to reparent
+ * @param parent the new parent
+ */
+ private void reparent(View view, View parent)
+ {
+ int n = view.getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View tmp = view.getView(i);
+ if (contains(parent, tmp))
+ tmp.setParent(parent);
+ else
+ reparent(tmp, parent);
}
}
}
/**
* This special subclass of <code>View</code> is used to represent
* the logical representation of this view. It does not support any
* visual representation, this is handled by the physical view implemented
* in the <code>FlowView</code>.
*/
class LogicalView extends BoxView
{
/**
* Creates a new LogicalView instance.
*/
@@ -355,48 +467,42 @@
* Represents the logical child elements of this view, encapsulated within
* one parent view (an instance of a package private <code>LogicalView</code>
* class). These will be translated to a set of real views that are then
* displayed on screen. This translation is performed by the inner class
* [EMAIL PROTECTED] FlowStrategy}.
*/
protected View layoutPool;
/**
* The <code>FlowStrategy</code> to use for translating between the
* logical and physical view.
*/
protected FlowStrategy strategy;
/**
- * Indicates if the flow should be rebuild during the next layout.
- */
- private boolean layoutDirty;
-
- /**
* Creates a new <code>FlowView</code> for the given
* <code>Element</code> and <code>axis</code>.
*
* @param element the element that is rendered by this FlowView
* @param axis the axis along which the view is tiled, either
* <code>View.X_AXIS</code> or <code>View.Y_AXIS</code>, the flow
* axis is orthogonal to this one
*/
public FlowView(Element element, int axis)
{
super(element, axis);
strategy = sharedStrategy;
- layoutDirty = true;
}
/**
* Returns the axis along which the view should be flowed. This is
* orthogonal to the axis along which the boxes are tiled.
*
* @return the axis along which the view should be flowed
*/
public int getFlowAxis()
{
int axis = getAxis();
int flowAxis;
if (axis == X_AXIS)
flowAxis = Y_AXIS;
@@ -481,90 +587,92 @@
if (layoutSpan != width)
{
layoutChanged(Y_AXIS);
layoutSpan = width;
}
}
else
{
if (layoutSpan != height)
{
layoutChanged(X_AXIS);
layoutSpan = height;
}
}
- if (layoutDirty)
+ if (! isLayoutValid(flowAxis))
{
+ int axis = getAxis();
+ int oldSpan = axis == X_AXIS ? getWidth() : getHeight();
strategy.layout(this);
- layoutDirty = false;
+ int newSpan = (int) getPreferredSpan(axis);
+ if (oldSpan != newSpan)
+ {
+ View parent = getParent();
+ if (parent != null)
+ parent.preferenceChanged(this, axis == X_AXIS, axis == Y_AXIS);
+ }
}
- if (getPreferredSpan(getAxis()) != height)
- preferenceChanged(this, false, true);
-
super.layout(width, height);
}
/**
* Receice notification that some content has been inserted in the region
* that this view is responsible for. This calls
* [EMAIL PROTECTED] FlowStrategy#insertUpdate}.
*
* @param changes the document event describing the changes
* @param a the current allocation of the view
* @param vf the view factory that is used for creating new child views
*/
public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
{
// First we must send the insertUpdate to the logical view so it can
// be updated accordingly.
layoutPool.insertUpdate(changes, a, vf);
strategy.insertUpdate(this, changes, getInsideAllocation(a));
- layoutDirty = true;
}
/**
* Receice notification that some content has been removed from the region
* that this view is responsible for. This calls
* [EMAIL PROTECTED] FlowStrategy#removeUpdate}.
*
* @param changes the document event describing the changes
* @param a the current allocation of the view
* @param vf the view factory that is used for creating new child views
*/
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
{
layoutPool.removeUpdate(changes, a, vf);
strategy.removeUpdate(this, changes, getInsideAllocation(a));
- layoutDirty = true;
}
/**
* Receice notification that some attributes changed in the region
* that this view is responsible for. This calls
* [EMAIL PROTECTED] FlowStrategy#changedUpdate}.
*
* @param changes the document event describing the changes
* @param a the current allocation of the view
* @param vf the view factory that is used for creating new child views
*/
public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
{
layoutPool.changedUpdate(changes, a, vf);
strategy.changedUpdate(this, changes, getInsideAllocation(a));
- layoutDirty = true;
}
/**
* Returns the index of the child <code>View</code> for the given model
* position.
*
* This is implemented to iterate over the children of this
* view (the rows) and return the index of the first view that contains
* the given position.
*
* @param pos the model position for whicht the child <code>View</code> is
* queried
*
* @return the index of the child <code>View</code> for the given model
* position
Index: javax/swing/text/GlyphView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/GlyphView.java,v
retrieving revision 1.21
diff -u -1 -5 -r1.21 GlyphView.java
--- javax/swing/text/GlyphView.java 31 Aug 2006 21:07:05 -0000 1.21
+++ javax/swing/text/GlyphView.java 12 Oct 2006 15:12:21 -0000
@@ -455,47 +455,47 @@
{
Rectangle b = a.getBounds();
int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
return pos + v.getStartOffset();
}
}
/**
* The GlyphPainer used for painting the glyphs.
*/
GlyphPainter glyphPainter;
/**
* The start offset within the document for this view.
*/
- private int startOffset;
+ private int offset;
/**
* The end offset within the document for this view.
*/
- private int endOffset;
+ private int length;
/**
* Creates a new <code>GlyphView</code> for the given <code>Element</code>.
*
* @param element the element that is rendered by this GlyphView
*/
public GlyphView(Element element)
{
super(element);
- startOffset = -1;
- endOffset = -1;
+ offset = 0;
+ length = 0;
}
/**
* Returns the <code>GlyphPainter</code> that is used by this
* <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
* <code>null</code> is returned.
*
* @return the glyph painter that is used by this
* glyph view or <code>null</code> if no glyph painter has been
* installed
*/
public GlyphPainter getGlyphPainter()
{
return glyphPainter;
}
@@ -687,49 +687,53 @@
throw ae;
}
FontMetrics fm = null; // Fetch font metrics somewhere.
return Utilities.getTabbedTextWidth(seg, fm, 0, null, p0);
}
/**
* Returns the start offset in the document model of the portion
* of text that this view is responsible for.
*
* @return the start offset in the document model of the portion
* of text that this view is responsible for
*/
public int getStartOffset()
{
- int start = startOffset;
- if (start < 0)
- start = super.getStartOffset();
- return start;
+ Element el = getElement();
+ int offs = el.getStartOffset();
+ if (length > 0)
+ offs += offset;
+ return offs;
}
/**
* Returns the end offset in the document model of the portion
* of text that this view is responsible for.
*
* @return the end offset in the document model of the portion
* of text that this view is responsible for
*/
public int getEndOffset()
{
- int end = endOffset;
- if (end < 0)
- end = super.getEndOffset();
- return end;
+ Element el = getElement();
+ int offs;
+ if (length > 0)
+ offs = el.getStartOffset() + offset + length;
+ else
+ offs = el.getEndOffset();
+ return offs;
}
/**
* Returns the text segment that this view is responsible for.
*
* @param p0 the start index in the document model
* @param p1 the end index in the document model
*
* @return the text segment that this view is responsible for
*/
public Segment getText(int p0, int p1)
{
Segment txt = new Segment();
try
{
@@ -1017,35 +1021,36 @@
{
preferenceChanged(this, true, false);
}
/**
* Creates a fragment view of this view that starts at <code>p0</code> and
* ends at <code>p1</code>.
*
* @param p0 the start location for the fragment view
* @param p1 the end location for the fragment view
*
* @return the fragment view
*/
public View createFragment(int p0, int p1)
{
+ checkPainter();
+ Element el = getElement();
GlyphView fragment = (GlyphView) clone();
- if (p0 != getStartOffset())
- fragment.startOffset = p0;
- if (p1 != getEndOffset())
- fragment.endOffset = p1;
+ fragment.offset = p0 - el.getStartOffset();
+ fragment.length = p1 - p0;
+ fragment.glyphPainter = glyphPainter.getPainter(fragment, p0, p1);
return fragment;
}
/**
* Returns the alignment of this view along the specified axis. For the Y
* axis this is <code>(height - descent) / height</code> for the used font,
* so that it is aligned along the baseline.
* For the X axis the superclass is called.
*/
public float getAlignment(int axis)
{
checkPainter();
float align;
if (axis == Y_AXIS)
{
Index: javax/swing/text/ParagraphView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/ParagraphView.java,v
retrieving revision 1.12
diff -u -1 -5 -r1.12 ParagraphView.java
--- javax/swing/text/ParagraphView.java 31 Aug 2006 21:07:05 -0000 1.12
+++ javax/swing/text/ParagraphView.java 12 Oct 2006 15:12:21 -0000
@@ -149,30 +149,62 @@
/**
* Overridden to perform a baseline layout. The normal BoxView layout
* isn't completely suitable for rows.
*/
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
return baselineRequirements(axis, r);
}
protected void loadChildren(ViewFactory vf)
{
// Do nothing here. The children are added while layouting.
}
+
+ /**
+ * Overridden to determine the minimum start offset of the row's children.
+ */
+ public int getStartOffset()
+ {
+ // Determine minimum start offset of the children.
+ int offset = Integer.MAX_VALUE;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View v = getView(i);
+ offset = Math.min(offset, v.getStartOffset());
+ }
+ return offset;
+ }
+
+ /**
+ * Overridden to determine the maximum end offset of the row's children.
+ */
+ public int getEndOffset()
+ {
+ // Determine minimum start offset of the children.
+ int offset = 0;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View v = getView(i);
+ offset = Math.max(offset, v.getEndOffset());
+ }
+ return offset;
+ }
}
/**
* The indentation of the first line of the paragraph.
*/
protected int firstLineIndent;
/**
* The justification of the paragraph.
*/
private int justification;
/**
* The line spacing of this paragraph.
*/
Index: javax/swing/text/html/BRView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/BRView.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 BRView.java
--- javax/swing/text/html/BRView.java 6 Jul 2006 09:04:38 -0000 1.1
+++ javax/swing/text/html/BRView.java 12 Oct 2006 15:12:21 -0000
@@ -32,40 +32,39 @@
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 javax.swing.text.Element;
/**
* Handled the HTML BR tag.
*/
class BRView
- extends NullView
-
+ extends InlineView
{
/**
* Creates the new BR view.
*
* @param elem the HTML element, representing the view.
*/
public BRView(Element elem)
{
super(elem);
}
/**
* Always return ForcedBreakWeight for the X_AXIS, BadBreakWeight for the
* Y_AXIS.
*/
public int getBreakWeight(int axis, float pos, float len)
{
if (axis == X_AXIS)
return ForcedBreakWeight;
else
- return BadBreakWeight;
+ return super.getBreakWeight(axis, pos, len);
}
}