| /******************************************************************************* |
| * 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 { |
| protected LineBox _currentLine; |
| |
| private LineBox _previousLine = null; |
| |
| protected BlockBox _blockBox; |
| |
| protected FlowContext _originalContext; |
| |
| protected ICSSStyle _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(); |
| } |
| |
| public 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(); |
| } |
| |
| protected 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 |
| */ |
| 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._borderInsets.left + _blockBox._paddingInsets.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._borderInsets.top |
| + _blockBox._paddingInsets.top; |
| if (topMargin != Integer.MIN_VALUE) |
| line._y += topMargin; |
| } else { |
| if (topMargin == Integer.MIN_VALUE) |
| line._y = _previousLine._y + _previousLine.getHeight() |
| + getLinePadding() + _previousLine._marginInsets.bottom; // XXX: |
| // should |
| // add |
| // previous |
| // margin |
| // bottom? |
| else |
| line._y = _previousLine._y |
| + _previousLine.getHeight() |
| + Math.max(topMargin, |
| _previousLine._marginInsets.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._marginInsets.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); |
| } |
| |
| public void endBlock() { |
| endLine(); |
| } |
| |
| int getLinePadding() { |
| return 0; |
| } |
| } |