blob: c419b30801846cb267165250c0e13038cf8381da [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2008 John Krasnay and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* John Krasnay - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xml.vex.core.internal.layout;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.wst.xml.vex.core.internal.core.Caret;
import org.eclipse.wst.xml.vex.core.internal.core.Insets;
import org.eclipse.wst.xml.vex.core.internal.dom.Element;
import org.eclipse.wst.xml.vex.core.internal.provisional.dom.VEXElement;
/**
* Box representing a row in a table.
*/
public class TableRowBox extends AbstractBlockBox {
public TableRowBox(LayoutContext context, TableRowGroupBox parent,
Element element) {
super(context, parent, element);
}
public TableRowBox(LayoutContext context, BlockBox parent, int startOffset,
int endOffset) {
super(context, parent, startOffset, endOffset);
}
protected List createChildren(final LayoutContext context) {
final List children = new ArrayList();
VEXElement element = this.findContainingElement();
final int[] widths = this.getTableBox().getColumnWidths();
LayoutUtils.iterateTableCells(context.getStyleSheet(), element, this
.getStartOffset(), this.getEndOffset(),
new ElementOrRangeCallback() {
private int column = 0;
public void onElement(Element child, String displayStyle) {
children.add(new TableCellBox(context,
TableRowBox.this, child, widths[column++]));
}
public void onRange(VEXElement parent, int startOffset,
int endOffset) {
children.add(new TableCellBox(context,
TableRowBox.this, startOffset, endOffset,
widths[column++]));
}
});
return children;
}
/**
* Override drawBox to do nothing. Table rows have no borders in
* border-collapse:separate mode.
*/
public void drawBox(LayoutContext context, int x, int y,
int containerWidth, boolean drawBorders) {
}
public Caret getCaret(LayoutContext context, int offset) {
int hSpacing = this.getTableBox().getHorizonalSpacing();
Box[] children = this.getChildren();
// If we haven't yet laid out this block, estimate the caret.
if (children == null) {
int relative = offset - this.getStartOffset();
int size = this.getEndOffset() - this.getStartOffset();
int y = 0;
if (size > 0) {
y = this.getHeight() * relative / size;
}
return new HCaret(0, y, this.getWidth());
}
int x = hSpacing / 2;
int[] widths = this.getTableBox().getColumnWidths();
for (int i = 0; i < children.length; i++) {
Box child = children[i];
if (!child.hasContent()) {
continue; // TODO can we really have generated table cells?
}
if (offset < child.getStartOffset()) {
return new TextCaret(x, 0, this.getHeight());
}
if (offset >= child.getStartOffset()
&& offset <= child.getEndOffset()) {
Caret caret = child.getCaret(context, offset);
caret.translate(child.getX(), child.getY());
return caret;
}
x += widths[i] + hSpacing;
}
return new TextCaret(x, 0, this.getHeight());
}
/**
* Override to return zero insets. Table rows have no insets in
* border-collapse:separate mode.
*/
public Insets getInsets(LayoutContext context, int containerWidth) {
return Insets.ZERO_INSETS;
}
public int getMarginBottom() {
return 0;
}
public int getMarginTop() {
return 0;
}
public int getNextLineOffset(LayoutContext context, int offset, int x) {
BlockBox[] children = this.getContentChildren();
int[] widths = this.getTableBox().getColumnWidths();
int leftEdge = 0;
for (int i = 0; i < children.length; i++) {
if (leftEdge + widths[i] > x) {
int newOffset = children[i].getNextLineOffset(context, offset,
x - leftEdge);
if (newOffset == children[i].getEndOffset() + 1) {
return -1;
} else {
return newOffset;
}
}
leftEdge += widths[i];
}
return -1;
}
public int getPreviousLineOffset(LayoutContext context, int offset, int x) {
BlockBox[] children = this.getContentChildren();
int[] widths = this.getTableBox().getColumnWidths();
int leftEdge = 0;
for (int i = 0; i < children.length; i++) {
if (leftEdge + widths[i] > x) {
int newOffset = children[i].getPreviousLineOffset(context,
offset, x - leftEdge);
if (newOffset == children[i].getStartOffset() - 1) {
return -1;
} else {
return newOffset;
}
}
leftEdge += widths[i];
}
return -1;
}
/**
* Returns the TableBox associated with this row.
*/
public TableBox getTableBox() {
return (TableBox) this.getParent().getParent().getParent();
}
protected int positionChildren(LayoutContext context) {
int hSpacing = this.getTableBox().getHorizonalSpacing();
int childX = hSpacing;
int topInset = 0;
int height = 0;
int bottomInset = 0;
for (int i = 0; i < this.getChildren().length; i++) {
Box child = this.getChildren()[i];
Insets insets = child.getInsets(context, this.getWidth());
childX += insets.getLeft();
child.setX(childX);
childX += child.getWidth() + insets.getRight() + hSpacing;
topInset = Math.max(topInset, insets.getTop());
height = Math.max(height, child.getHeight());
bottomInset = Math.max(bottomInset, insets.getBottom());
}
this.setHeight(topInset + height + bottomInset);
for (int i = 0; i < this.getChildren().length; i++) {
Box child = this.getChildren()[i];
child.setY(topInset);
child.setHeight(height);
}
return -1; // TODO revisit
}
public int viewToModel(LayoutContext context, int x, int y) {
Box[] children = this.getChildren();
if (children == null) {
int charCount = this.getEndOffset() - this.getStartOffset() - 1;
if (charCount == 0 || this.getHeight() == 0) {
return this.getEndOffset();
} else {
return this.getStartOffset() + charCount * y / this.getHeight();
}
} else {
for (int i = 0; i < children.length; i++) {
Box child = children[i];
if (!child.hasContent()) {
continue;
}
if (x < child.getX()) {
return child.getStartOffset() - 1;
} else if (x < child.getX() + child.getWidth()) {
return child.viewToModel(context, x - child.getX(), y
- child.getY());
}
}
}
return this.getEndOffset();
}
}