/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexey A. Ivanov
*/
package javax.swing.text;
import java.awt.Graphics;
import java.awt.Shape;
import javax.swing.SizeRequirements;
import javax.swing.event.DocumentEvent;
import javax.swing.text.Position.Bias;
import org.apache.harmony.awt.text.TextUtils;
import org.apache.harmony.x.swing.internal.nls.Messages;
public class ParagraphView extends FlowView implements TabExpander {
private static final int DEFAULT_TAB = 72;
private static final int MIN_TEXT_CHUNK = 10;
private static final char[] TABS = new char[] {'\t'};
private static final char[] TABS_DECIMAL = new char[] {'\t', '.'};
private class Row extends BoxView {
private int lineSpace;
public Row(final Element element) {
super(element, X_AXIS);
}
public int getStartOffset() {
if (getViewCount() > 0) {
return getView(0).getStartOffset();
}
return super.getStartOffset();
}
public int getEndOffset() {
if (getViewCount() > 0) {
return getView(getViewCount() - 1).getEndOffset();
}
return super.getEndOffset();
}
public AttributeSet getAttributes() {
final View parent = getParent();
return parent != null ? parent.getAttributes() : null;
}
protected void loadChildren(final ViewFactory factory) {
}
protected SizeRequirements
calculateMajorAxisRequirements(final int axis,
final SizeRequirements r) {
SizeRequirements result =
super.calculateMajorAxisRequirements(axis, r);
result.alignment = getAlignByJustification();
return result;
}
protected SizeRequirements
calculateMinorAxisRequirements(final int axis,
final SizeRequirements r) {
SizeRequirements result = baselineRequirements(axis, r);
lineSpace = (int)(result.preferred * lineSpacing);
return result;
}
protected void layoutMinorAxis(final int targetSpan, final int axis,
final int[] offsets, final int[] spans) {
baselineLayout(targetSpan, axis, offsets, spans);
}
protected short getLeftInset() {
if (ParagraphView.this.isAllocationValid()
&& ParagraphView.this.getViewCount() > 0
&& this == ParagraphView.this.getView(0)) {
return (short)(super.getLeftInset() + firstLineIndent);
}
return super.getLeftInset();
}
protected short getBottomInset() {
return (short)(super.getBottomInset() + lineSpace);
}
private float getAlignByJustification() {
switch (justification) {
case StyleConstants.ALIGN_LEFT:
return ALIGN_LEFT;
case StyleConstants.ALIGN_CENTER:
return ALIGN_CENTER;
case StyleConstants.ALIGN_RIGHT:
return ALIGN_RIGHT;
default:
return ALIGN_CENTER;
}
}
}
protected int firstLineIndent;
private int justification;
private float lineSpacing;
private int tabBase;
public ParagraphView(final Element element) {
super(element, Y_AXIS);
setPropertiesFromAttributes();
}
public int getFlowStart(final int rowIndex) {
int result = super.getFlowStart(rowIndex);
if (rowIndex == 0) {
result += firstLineIndent;
}
View child = getView(rowIndex);
if (child instanceof CompositeView) {
result += ((CompositeView)child).getLeftInset();
}
return result;
}
public int getFlowSpan(final int rowIndex) {
int result = super.getFlowSpan(rowIndex);
if (rowIndex == 0) {
result -= firstLineIndent;
}
View child = getView(rowIndex);
if (child instanceof CompositeView) {
CompositeView cv = (CompositeView)child;
result -= cv.getLeftInset();
result -= cv.getRightInset();
}
return result;
}
public float getAlignment(final int axis) {
if (axis == Y_AXIS && getViewCount() > 0) {
return (getSpan(Y_AXIS, 0) / 2) / getPreferredSpan(Y_AXIS);
}
return super.getAlignment(axis);
}
public void paint(final Graphics g,
final Shape a) {
tabBase = a.getBounds().x + getLeftInset();
super.paint(g, a);
}
public float nextTabStop(final float x,
final int tabOffset) {
final float base = getTabBase();
final float basedX = x > base ? x - base : 0;
final TabSet tabSet = getTabSet();
if (tabSet == null) {
return base + ((int)(basedX / DEFAULT_TAB) + 1) * DEFAULT_TAB;
}
final TabStop tabStop = tabSet.getTabAfter(basedX);
if (tabStop == null) {
return base + ((int)(basedX / DEFAULT_TAB) + 1) * DEFAULT_TAB;
}
final int align = tabStop.getAlignment();
if (align == TabStop.ALIGN_LEFT || align == TabStop.ALIGN_BAR) {
return base + tabStop.getPosition();
}
int nextTab =
findOffsetToCharactersInString(align == TabStop.ALIGN_DECIMAL
? TABS_DECIMAL : TABS,
tabOffset + 1);
if (nextTab == -1) {
nextTab = getEndOffset();
}
float partSpan = getPartialSize(tabOffset + 1, nextTab);
if (align == TabStop.ALIGN_CENTER) {
return base + tabStop.getPosition() - partSpan / 2;
}
return base + tabStop.getPosition() - partSpan;
}
public View breakView(final int axis,
final float len,
final Shape a) {
return this;
}
public int getBreakWeight(final int axis,
final float len) {
return BadBreakWeight;
}
public void changedUpdate(final DocumentEvent changes,
final Shape a,
final ViewFactory f) {
preferenceChanged(null, true, true);
setPropertiesFromAttributes();
super.changedUpdate(changes, a, f);
}
protected View createRow() {
return new Row(getElement());
}
protected void setJustification(final int j) {
justification = j;
}
protected void setLineSpacing(final float ls) {
lineSpacing = ls;
}
protected void setFirstLineIndent(final float fi) {
firstLineIndent = (int)fi;
}
protected void setPropertiesFromAttributes() {
final AttributeSet attrs = getAttributes();
setJustification(StyleConstants.getAlignment(attrs));
setFirstLineIndent(StyleConstants.getFirstLineIndent(attrs));
setLineSpacing(StyleConstants.getLineSpacing(attrs));
setParagraphInsets(attrs);
}
protected int getLayoutViewCount() {
return layoutPool.getViewCount();
}
protected View getLayoutView(final int index) {
return layoutPool.getView(index);
}
/**
* This method does nothing and is not supposed to be called.
* The functionality described for this method in the API Specification
* is equivalent to that of
* @link FlowView.FlowStrategy#adjustRow(FlowView, int, int, int)
*/
protected void adjustRow(final Row r, final int desiredSpan, final int x) {
}
protected int getClosestPositionTo(final int pos,
final Bias b,
final Shape a,
final int direction,
final Bias[] biasRet,
final int rowIndex,
final int x)
throws BadLocationException {
throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
}
protected float getPartialSize(final int startOffset,
final int endOffset) {
float result = 0;
int index = layoutPool.getViewIndex(startOffset, Bias.Forward);
if (index == -1) {
return 0;
}
View child;
int childStart;
int childEnd;
do {
child = getLayoutView(index);
childStart = child.getStartOffset();
childEnd = child.getEndOffset();
if (startOffset <= childStart && childEnd <= endOffset) {
result += child.getPreferredSpan(X_AXIS);
} else if (!(child instanceof TabableView)) {
return 0;
} else {
TabableView tv = (TabableView)child;
result +=
tv.getPartialSpan(childStart > startOffset ? childStart
: startOffset,
childEnd < endOffset ? childEnd
: endOffset);
}
} while (childEnd < endOffset && ++index < getLayoutViewCount());
return result;
}
protected int findOffsetToCharactersInString(final char[] string,
final int start) {
final Segment text = new Segment();
text.setPartialReturn(true);
int offset = start;
final int limit = getEndOffset();
final Document doc = getDocument();
while (offset < limit) {
try {
doc.getText(offset, Math.min(MIN_TEXT_CHUNK,
limit - offset), text);
} catch (BadLocationException e) {
e.printStackTrace();
return -1;
}
char c = text.first();
while (c != Segment.DONE) {
for (int i = 0; i < string.length; i++) {
if (c == string[i]) {
return offset + text.getIndex() - text.getBeginIndex();
}
}
c = text.next();
}
offset += text.count;
}
return -1;
}
protected int getNextNorthSouthVisualPositionFrom(final int pos,
final Bias b,
final Shape a,
final int direction,
final Bias[] biasRet)
throws BadLocationException {
if (true) {
throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
}
return TextUtils.getNextVisualPositionFrom(getTextKit(), this,
pos, b, a,
direction, biasRet);
}
protected boolean flipEastAndWestAtEnds(final int position,
final Bias bias) {
throw new UnsupportedOperationException(Messages.getString("swing.27")); //$NON-NLS-1$
}
protected TabSet getTabSet() {
return StyleConstants.getTabSet(getAttributes());
}
protected float getTabBase() {
return tabBase;
}
}
|