blob: 44c43c8b04df8f9e28226d0b74ef4601f7bf411f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. 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:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.css2.value.Length;
/**
* When doing absolute positioning, we need to create a block. But that block
* don't have a corresponding figure. So we need a block without corresponding
* figure.
*
* @author mengbo
* @version 1.5
*/
public class BlockFlowContext implements FlowContext {
private LineBox _currentLine;
private LineBox _previousLine = null;
BlockBox _blockBox;
private final FlowContext _originalContext;
private final ICSSStyle _style;
/**
* @param originalContext
* @param style
*/
public BlockFlowContext(FlowContext originalContext, ICSSStyle style) {
this._originalContext = originalContext;
this._style = style;
setup();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getContainerWidth()
*/
public int getContainerWidth() {
return _originalContext.getContainerWidth();
}
/**
* Initialize the object
*/
private void setup() {
_blockBox = new BlockBox();
_blockBox.setRecommendedWidth(getRecommendedWidth());
_currentLine = this.getCurrentLine();
_previousLine = null;
}
private int getRecommendedWidth() {
int containerWidth = getContainerWidth();
Object leftObj = _style.getStyleProperty(ICSSPropertyID.ATTR_LEFT);
if (leftObj != null && leftObj instanceof Length) {
Length left = (Length) leftObj;
int intLeft = left.getValue();
if (left.isPercentage()) {
intLeft = containerWidth * intLeft / 100;
}
if (intLeft < containerWidth) {
return containerWidth - intLeft;
}
}
return containerWidth;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#addToCurrentLine(org.eclipse.jst.pagedesigner.css2.layout.FlowBox)
*/
public void addToCurrentLine(FlowBox block) {
getCurrentLine().add(block);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#endLine()
*/
public void endLine() {
// this is called from child layouts.
// If there is no current line, state is equivalent to new line
if (_currentLine == null)
return;
if (_currentLine.isOccupied())
layoutLine(); // finalize the current line layout
else
return;
LineBox box = _currentLine;
// _currentLine = _previousLine; //XXX: ???? why (yang)
_previousLine = box;
_currentLine = null;
// setupLine(getCurrentLine());
}
/**
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentLine()
*/
public LineBox getCurrentLine() {
if (_currentLine == null)
createNewLine();
return _currentLine;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentLine(int)
*/
public LineBox getCurrentLine(int topMargin) {
if (_currentLine == null)
createNewLine(topMargin);
return _currentLine;
}
/**
* @param topMargin
*/
private void createNewLine(int topMargin) {
createNewLine();
}
private void createNewLine() {
_currentLine = new LineBox();
setupLine(_currentLine, Integer.MIN_VALUE);
}
/**
* Override to setup the line's x, remaining, and available width.
*
* @param line
* the LineBox to set up
* @param topMargin
*/
protected void setupLine(LineBox line, int topMargin) {
line.clear();
// the caller of getCurrentLine() may add leftMargin and leftPadding and
// leftBorder to line.x
line._x = _blockBox.getBorderInsets().left + _blockBox.getPaddingInsets().left;
// FIXME: here should check the floating boxes, and minus the width of
// them from
// current line.
// XXX: the RecommendedContentWidth is related with the RecommendedWidth
// of container that
// usually larger than it needed.here we do not set the RecommendedWidth
// for the sake of
// layouting right absolute position.
// /shortcoming:the box will break into multi-line after every white
// space.
// line.setRecommendedWidth(_blockBox.getRecommendedContentWidth());
if (_previousLine == null) {
line._y = _blockBox.getBorderInsets().top
+ _blockBox.getPaddingInsets().top;
if (topMargin != Integer.MIN_VALUE)
line._y += topMargin;
} else {
if (topMargin == Integer.MIN_VALUE)
line._y = _previousLine._y + _previousLine.getHeight()
+ getLinePadding() + _previousLine.getMarginInsets().bottom; // XXX:
// should
// add
// previous
// margin
// bottom?
else
line._y = _previousLine._y
+ _previousLine.getHeight()
+ Math.max(topMargin,
_previousLine.getMarginInsets().bottom);
}
// line.validate();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentY()
*/
public int getCurrentY() {
return getCurrentLine()._y; // FIXME: margin of previous block?
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#isCurrentLineOccupied()
*/
public boolean isCurrentLineOccupied() {
return _currentLine != null && _currentLine.isOccupied();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getLastMarginRight()
*/
public int getLastMarginRight() {
if (_currentLine == null || !_currentLine.isOccupied()) {
return 0;
}
FlowBox box = (FlowBox) _currentLine.getFragments().get(
_currentLine.getFragments().size() - 1);
if (box != null) {
return box.getMarginInsets().right;
}
return 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#isCalculatingMaxWidth()
*/
public boolean isCalculatingMaxWidth() {
return false;
}
/**
* Adjust all fragments in the current line to have the same baseline. Do
* any additional adjustments, such as horizontal alignment.
*/
protected void layoutLine() {
// currentLine.x = 0; //XXX: comment out, don't understand why set to 0,
// because it has already
// been set when setupLine(). And if do need, should
// set to getBorderPaddingInsets().left
// if (!isInlineBlock() && shouldExpand())
// {
// // FIXME: currently we are using getRecommendedContentWidth,
// // what happen if after adding the new line, the new width is bigger
// than
// // recommendedContentWidth? should we use getWidth() instead of
// // recommendedcontentWidth?
//
// Object textalign =
// (getCSSStyle().getStyleProperty(ICSSPropertyID.ATTR_TEXTALIGN));
// if (textalign == ICSSPropertyID.VAL_RIGHT)
// {
// _currentLine._x = _blockBox.getRecommendedContentWidth() +
// _blockBox.getBorderPaddingInsets().left - _currentLine.getWidth();
// }
// else if (textalign == ICSSPropertyID.VAL_CENTER)
// {
//
// _currentLine._x = _blockBox.getBorderPaddingInsets().left +
// (_blockBox.getRecommendedContentWidth() - _currentLine.getWidth()) /
// 2;
// }
// if (_currentLine._x < 0)
// _currentLine._x = 0;
// }
// FIXME: should check vertical alignment here?
_currentLine.commit();
_blockBox.add(_currentLine);
}
void endBlock() {
endLine();
}
int getLinePadding() {
return 0;
}
}