| Method from javax.swing.text.ParagraphView Detail: |
protected void adjustRow(ParagraphView.Row r,
int desiredSpan,
int x) {
}
Adjusts the given row if possible to fit within the
layout span. By default this will try to find the
highest break weight possible nearest the end of
the row. If a forced break is encountered, the
break will be positioned there.
This is meant for internal usage, and should not be used directly. |
public View breakView(int axis,
float len,
Shape a) {
if(axis == View.Y_AXIS) {
if(a != null) {
Rectangle alloc = a.getBounds();
setSize(alloc.width, alloc.height);
}
// Determine what row to break on.
// PENDING(prinz) add break support
return this;
}
return this;
}
Breaks this view on the given axis at the given length.
ParagraphView instances are breakable
along the Y_AXIS only, and only if
len is after the first line. |
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r) {
r = super.calculateMinorAxisRequirements(axis, r);
float min = 0;
float glue = 0;
int n = getLayoutViewCount();
for (int i = 0; i < n; i++) {
View v = getLayoutView(i);
float span = v.getMinimumSpan(axis);
if (v.getBreakWeight(axis, 0, v.getMaximumSpan(axis))
> View.BadBreakWeight) {
// find the longest non-breakable fragments at the view edges
int p0 = v.getStartOffset();
int p1 = v.getEndOffset();
float start = findEdgeSpan(v, axis, p0, p0, p1);
float end = findEdgeSpan(v, axis, p1, p0, p1);
glue += start;
min = Math.max(min, Math.max(span, glue));
glue = end;
} else {
// non-breakable view
glue += span;
min = Math.max(min, glue);
}
}
r.minimum = Math.max(r.minimum, (int) min);
r.preferred = Math.max(r.minimum, r.preferred);
r.maximum = Math.max(r.preferred, r.maximum);
return r;
}
Calculate the needs for the paragraph along the minor axis.
This uses size requirements of the superclass, modified to take into
account the non-breakable areas at the adjacent views edges. The minimal
size requirements for such views should be no less than the sum of all
adjacent fragments.
If the {@code axis} parameter is neither {@code View.X_AXIS} nor
{@code View.Y_AXIS}, IllegalArgumentException is thrown. If the
{@code r} parameter is {@code null,} a new {@code SizeRequirements}
object is created, otherwise the supplied {@code SizeRequirements}
object is returned. |
public void changedUpdate(DocumentEvent changes,
Shape a,
ViewFactory f) {
// update any property settings stored, and layout should be
// recomputed
setPropertiesFromAttributes();
layoutChanged(X_AXIS);
layoutChanged(Y_AXIS);
super.changedUpdate(changes, a, f);
}
Gives notification from the document that attributes were changed
in a location that this view is responsible for. |
protected View createRow() {
return new Row(getElement());
}
Create a View that should be used to hold a
a row's worth of children in a flow. |
protected int findOffsetToCharactersInString(char[] string,
int start) {
int stringLength = string.length;
int end = getEndOffset();
Segment seg = new Segment();
try {
getDocument().getText(start, end - start, seg);
} catch (BadLocationException ble) {
return -1;
}
for(int counter = seg.offset, maxCounter = seg.offset + seg.count;
counter < maxCounter; counter++) {
char currentChar = seg.array[counter];
for(int subCounter = 0; subCounter < stringLength;
subCounter++) {
if(currentChar == string[subCounter])
return counter - seg.offset + start;
}
}
// No match.
return -1;
}
Finds the next character in the document with a character in
string, starting at offset start. If
there are no characters found, -1 will be returned. |
protected boolean flipEastAndWestAtEnds(int position,
Position.Bias bias) {
Document doc = getDocument();
if(doc instanceof AbstractDocument &&
!((AbstractDocument)doc).isLeftToRight(getStartOffset(),
getStartOffset() + 1)) {
return true;
}
return false;
}
Determines in which direction the next view lays.
Consider the View at index n.
Typically the Views are layed out
from left to right, so that the View
to the EAST will be at index n + 1, and the
View to the WEST will be at index n - 1.
In certain situations, such as with bidirectional text,
it is possible that the View to EAST is not
at index n + 1, but rather at index n - 1,
or that the View to the WEST is not at
index n - 1, but index n + 1. In this case this method
would return true, indicating the Views are
layed out in descending order.
This will return true if the text is layed out right
to left at position, otherwise false. |
public float getAlignment(int axis) {
switch (axis) {
case Y_AXIS:
float a = 0.5f;
if (getViewCount() != 0) {
int paragraphSpan = (int) getPreferredSpan(View.Y_AXIS);
View v = getView(0);
int rowSpan = (int) v.getPreferredSpan(View.Y_AXIS);
a = (paragraphSpan != 0) ? ((float)(rowSpan / 2)) / paragraphSpan : 0;
}
return a;
case X_AXIS:
return 0.5f;
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
Determines the desired alignment for this view along an
axis. This is implemented to give the alignment to the
center of the first row along the y axis, and the default
along the x axis. |
public int getBreakWeight(int axis,
float len) {
if(axis == View.Y_AXIS) {
// PENDING(prinz) make this return a reasonable value
// when paragraph breaking support is re-implemented.
// If less than one row, bad weight value should be
// returned.
//return GoodBreakWeight;
return BadBreakWeight;
}
return BadBreakWeight;
}
Gets the break weight for a given location.
ParagraphView instances are breakable
along the Y_AXIS only, and only if
len is after the first row. If the length
is less than one row, a value of BadBreakWeight
is returned. |
protected int getClosestPositionTo(int pos,
Position.Bias b,
Shape a,
int direction,
Position.Bias[] biasRet,
int rowIndex,
int x) throws BadLocationException {
JTextComponent text = (JTextComponent)getContainer();
Document doc = getDocument();
AbstractDocument aDoc = (doc instanceof AbstractDocument) ?
(AbstractDocument)doc : null;
View row = getView(rowIndex);
int lastPos = -1;
// This could be made better to check backward positions too.
biasRet[0] = Position.Bias.Forward;
for(int vc = 0, numViews = row.getViewCount(); vc < numViews; vc++) {
View v = row.getView(vc);
int start = v.getStartOffset();
boolean ltr = (aDoc != null) ? aDoc.isLeftToRight
(start, start + 1) : true;
if(ltr) {
lastPos = start;
for(int end = v.getEndOffset(); lastPos < end; lastPos++) {
float xx = text.modelToView(lastPos).getBounds().x;
if(xx >= x) {
while (++lastPos < end &&
text.modelToView(lastPos).getBounds().x == xx) {
}
return --lastPos;
}
}
lastPos--;
}
else {
for(lastPos = v.getEndOffset() - 1; lastPos >= start;
lastPos--) {
float xx = text.modelToView(lastPos).getBounds().x;
if(xx >= x) {
while (--lastPos >= start &&
text.modelToView(lastPos).getBounds().x == xx) {
}
return ++lastPos;
}
}
lastPos++;
}
}
if(lastPos == -1) {
return getStartOffset();
}
return lastPos;
}
Returns the closest model position to x.
rowIndex gives the index of the view that corresponds
that should be looked in. |
public int getFlowSpan(int index) {
View child = getView(index);
int adjust = 0;
if (child instanceof Row) {
Row row = (Row) child;
adjust = row.getLeftInset() + row.getRightInset();
}
return (layoutSpan == Integer.MAX_VALUE) ? layoutSpan
: (layoutSpan - adjust);
}
Fetches the constraining span to flow against for
the given child index. |
public int getFlowStart(int index) {
View child = getView(index);
int adjust = 0;
if (child instanceof Row) {
Row row = (Row) child;
adjust = row.getLeftInset();
}
return tabBase + adjust;
}
Fetches the location along the flow axis that the
flow span will start at. |
protected View getLayoutView(int index) {
return layoutPool.getView(index);
}
Returns the view at a given index.
The child views of the paragraph are rows which
have been used to arrange pieces of the Views
that represent the child elements. This methods returns
the view responsible for the child element index
(prior to breaking). These are the Views that were
produced from a factory (to represent the child
elements) and used for layout. |
protected int getLayoutViewCount() {
return layoutPool.getViewCount();
}
Returns the number of views that this view is
responsible for.
The child views of the paragraph are rows which
have been used to arrange pieces of the Views
that represent the child elements. This is the number
of views that have been tiled in two dimensions,
and should be equivalent to the number of child elements
to the element this view is responsible for. |
protected int getNextNorthSouthVisualPositionFrom(int pos,
Position.Bias b,
Shape a,
int direction,
Position.Bias[] biasRet) throws BadLocationException {
int vIndex;
if(pos == -1) {
vIndex = (direction == NORTH) ?
getViewCount() - 1 : 0;
}
else {
if(b == Position.Bias.Backward && pos > 0) {
vIndex = getViewIndexAtPosition(pos - 1);
}
else {
vIndex = getViewIndexAtPosition(pos);
}
if(direction == NORTH) {
if(vIndex == 0) {
return -1;
}
vIndex--;
}
else if(++vIndex >= getViewCount()) {
return -1;
}
}
// vIndex gives index of row to look in.
JTextComponent text = (JTextComponent)getContainer();
Caret c = text.getCaret();
Point magicPoint;
magicPoint = (c != null) ? c.getMagicCaretPosition() : null;
int x;
if(magicPoint == null) {
Shape posBounds;
try {
posBounds = text.getUI().modelToView(text, pos, b);
} catch (BadLocationException exc) {
posBounds = null;
}
if(posBounds == null) {
x = 0;
}
else {
x = posBounds.getBounds().x;
}
}
else {
x = magicPoint.x;
}
return getClosestPositionTo(pos, b, a, direction, biasRet, vIndex, x);
}
Returns the next visual position for the cursor, in
either the east or west direction.
Overridden from CompositeView. |
protected float getPartialSize(int startOffset,
int endOffset) {
float size = 0.0f;
int viewIndex;
int numViews = getViewCount();
View view;
int viewEnd;
int tempEnd;
// Have to search layoutPool!
// PENDING: when ParagraphView supports breaking location
// into layoutPool will have to change!
viewIndex = getElement().getElementIndex(startOffset);
numViews = layoutPool.getViewCount();
while(startOffset < endOffset && viewIndex < numViews) {
view = layoutPool.getView(viewIndex++);
viewEnd = view.getEndOffset();
tempEnd = Math.min(endOffset, viewEnd);
if(view instanceof TabableView)
size += ((TabableView)view).getPartialSpan(startOffset, tempEnd);
else if(startOffset == view.getStartOffset() &&
tempEnd == view.getEndOffset())
size += view.getPreferredSpan(View.X_AXIS);
else
// PENDING: should we handle this better?
return 0.0f;
startOffset = viewEnd;
}
return size;
}
Returns the size used by the views between
startOffset and endOffset.
This uses getPartialView to calculate the
size if the child view implements the
TabableView interface. If a
size is needed and a View does not implement
the TabableView interface,
the preferredSpan will be used. |
protected float getTabBase() {
return (float)tabBase;
}
Returns where the tabs are calculated from. |
protected TabSet getTabSet() {
return StyleConstants.getTabSet(getElement().getAttributes());
}
Gets the Tabset to be used in calculating tabs. |
public float nextTabStop(float x,
int tabOffset) {
// If the text isn't left justified, offset by 10 pixels!
if(justification != StyleConstants.ALIGN_LEFT)
return x + 10.0f;
x -= tabBase;
TabSet tabs = getTabSet();
if(tabs == null) {
// a tab every 72 pixels.
return (float)(tabBase + (((int)x / 72 + 1) * 72));
}
TabStop tab = tabs.getTabAfter(x + .01f);
if(tab == null) {
// no tab, do a default of 5 pixels.
// Should this cause a wrapping of the line?
return tabBase + x + 5.0f;
}
int alignment = tab.getAlignment();
int offset;
switch(alignment) {
default:
case TabStop.ALIGN_LEFT:
// Simple case, left tab.
return tabBase + tab.getPosition();
case TabStop.ALIGN_BAR:
// PENDING: what does this mean?
return tabBase + tab.getPosition();
case TabStop.ALIGN_RIGHT:
case TabStop.ALIGN_CENTER:
offset = findOffsetToCharactersInString(tabChars,
tabOffset + 1);
break;
case TabStop.ALIGN_DECIMAL:
offset = findOffsetToCharactersInString(tabDecimalChars,
tabOffset + 1);
break;
}
if (offset == -1) {
offset = getEndOffset();
}
float charsSize = getPartialSize(tabOffset + 1, offset);
switch(alignment) {
case TabStop.ALIGN_RIGHT:
case TabStop.ALIGN_DECIMAL:
// right and decimal are treated the same way, the new
// position will be the location of the tab less the
// partialSize.
return tabBase + Math.max(x, tab.getPosition() - charsSize);
case TabStop.ALIGN_CENTER:
// Similar to right, but half the partialSize.
return tabBase + Math.max(x, tab.getPosition() - charsSize / 2.0f);
}
// will never get here!
return x;
}
Returns the next tab stop position given a reference position.
This view implements the tab coordinate system, and calls
getTabbedSpan on the logical children in the process
of layout to determine the desired span of the children. The
logical children can delegate their tab expansion upward to
the paragraph which knows how to expand tabs.
LabelView is an example of a view that delegates
its tab expansion needs upward to the paragraph.
This is implemented to try and locate a TabSet
in the paragraph element's attribute set. If one can be
found, its settings will be used, otherwise a default expansion
will be provided. The base location for for tab expansion
is the left inset from the paragraphs most recent allocation
(which is what the layout of the children is based upon). |
public void paint(Graphics g,
Shape a) {
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
tabBase = alloc.x + getLeftInset();
super.paint(g, a);
// line with the negative firstLineIndent value needs
// special handling
if (firstLineIndent < 0) {
Shape sh = getChildAllocation(0, a);
if ((sh != null) && sh.intersects(alloc)) {
int x = alloc.x + getLeftInset() + firstLineIndent;
int y = alloc.y + getTopInset();
Rectangle clip = g.getClipBounds();
tempRect.x = x + getOffset(X_AXIS, 0);
tempRect.y = y + getOffset(Y_AXIS, 0);
tempRect.width = getSpan(X_AXIS, 0) - firstLineIndent;
tempRect.height = getSpan(Y_AXIS, 0);
if (tempRect.intersects(clip)) {
tempRect.x = tempRect.x - firstLineIndent;
paintChild(g, tempRect, 0);
}
}
}
}
Renders using the given rendering surface and area on that
surface. This is implemented to delgate to the superclass
after stashing the base coordinate for tab calculations. |
protected void setFirstLineIndent(float fi) {
firstLineIndent = (int) fi;
}
Sets the indent on the first line. |
protected void setJustification(int j) {
justification = j;
}
Sets the type of justification. |
protected void setLineSpacing(float ls) {
lineSpacing = ls;
}
|
protected void setPropertiesFromAttributes() {
AttributeSet attr = getAttributes();
if (attr != null) {
setParagraphInsets(attr);
Integer a = (Integer)attr.getAttribute(StyleConstants.Alignment);
int alignment;
if (a == null) {
Document doc = getElement().getDocument();
Object o = doc.getProperty(TextAttribute.RUN_DIRECTION);
if ((o != null) && o.equals(TextAttribute.RUN_DIRECTION_RTL)) {
alignment = StyleConstants.ALIGN_RIGHT;
} else {
alignment = StyleConstants.ALIGN_LEFT;
}
} else {
alignment = a.intValue();
}
setJustification(alignment);
setLineSpacing(StyleConstants.getLineSpacing(attr));
setFirstLineIndent(StyleConstants.getFirstLineIndent(attr));
}
}
Set the cached properties from the attributes. |