| /******************************************************************************* |
| * 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.draw2d.PositionConstants; |
| import org.eclipse.draw2d.geometry.Insets; |
| |
| /** |
| * The layout for {@link BlockFlow}figures. |
| * <P> |
| * WARNING: This class is not intended to be subclassed by clients. |
| * |
| * @author mengbo |
| * @since 2.1 |
| */ |
| public class BlockFlowLayout extends FlowContainerLayout { |
| private LineBox _previousLine = null; |
| |
| BlockBox _blockBox; |
| |
| /** |
| * Creates a new BlockFlowLayout with the given BlockFlow. |
| * |
| * @param blockFlow |
| * the BlockFlow |
| */ |
| public BlockFlowLayout(BlockFlow blockFlow) { |
| super(blockFlow); |
| } |
| |
| /** |
| * @see FlowContainerLayout#cleanup() |
| */ |
| protected void cleanup() { |
| _currentLine = _previousLine = null; |
| } |
| |
| /** |
| * @see FlowContainerLayout#createNewLine() |
| */ |
| protected void createNewLine() { |
| _currentLine = new LineBox(); |
| setupLine(_currentLine, Integer.MIN_VALUE); |
| } |
| |
| protected void createNewLine(int topmargin) { |
| _currentLine = new LineBox(); |
| setupLine(_currentLine, topmargin); |
| } |
| |
| /** |
| * 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 = 0; |
| |
| // FIXME: here should check the floating boxes, and minus the width of |
| // them from |
| // current line. |
| line.setRecommendedWidth(_blockBox.getRecommendedContentWidth()); |
| if (_previousLine == null) { |
| line._y = 0; |
| 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(); |
| } |
| |
| /** |
| * Called by flush(), adds the BlockBox associated with this BlockFlowLayout |
| * to the current line and then ends the line. |
| */ |
| protected void endBlock() { |
| getFlowContext().addToCurrentLine(_blockBox); |
| |
| // FIXME: here should tell the context the bottom margin. |
| getFlowContext().endLine(); |
| } |
| |
| /** |
| * @see 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 { |
| _currentLine = null; |
| return; |
| } |
| LineBox box = _currentLine; |
| _previousLine = box; |
| _currentLine = null;// _previousLine; //XXX: ???? why (yang) |
| |
| // setupLine(getCurrentLine()); |
| } |
| |
| /** |
| * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentY() |
| */ |
| public int getCurrentY() { |
| return getCurrentLine()._y; // FIXME: margin of previous block? |
| } |
| |
| /** |
| * Returns the BlockFlow associated with this BlockFlowLayout |
| * |
| * @return the BlockFlow |
| */ |
| protected final BlockFlow getBlockFlow() { |
| return (BlockFlow) getFlowFigure(); |
| } |
| |
| /** |
| * 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 |
| switch (getBlockFlow().getHorizontalAligment()) { |
| case PositionConstants.RIGHT: |
| _currentLine._x = _blockBox.getContentWidth() |
| - getBorderPaddingInsets().right - _currentLine.getWidth(); |
| break; |
| case PositionConstants.CENTER: |
| _currentLine._x = (_blockBox.getContentWidth() |
| + getBorderPaddingInsets().left |
| - getBorderPaddingInsets().right - _currentLine.getWidth()) / 2; |
| break; |
| } |
| // FIXME: should check vertical alignment here? |
| _currentLine.commit(); |
| _blockBox.add(_currentLine); |
| } |
| |
| /** |
| * @see FlowContainerLayout#flush() |
| */ |
| protected void flush() { |
| if (_currentLine != null) |
| layoutLine(); |
| endBlock(); |
| } |
| |
| /** |
| * @see FlowContainerLayout#preLayout() |
| */ |
| protected void preLayout() { |
| _blockBox = getBlockFlow().getBlockBox(); |
| setupBlock(); |
| // Probably could setup current and previous line here, or just previous |
| } |
| |
| /** |
| * sets up the single block that contains all of the lines. |
| */ |
| protected void setupBlock() { |
| // Ask for a new line, in case we are in the middle of a line |
| |
| // FIXME: the endLine() should tell context the top margin of this |
| // block. |
| getFlowContext().endLine(); |
| |
| LineBox line = getFlowContext().getCurrentLine(); |
| // int recommended = line.getAvailableWidth(); |
| // if (recommended != previousRecommendedWidth) |
| // Remove all current Fragments |
| _blockBox.clear(); |
| |
| // Setup the one fragment for this Block with the correct X and |
| // available width |
| |
| // FIXME: here should check whether the CSS already set recommended |
| // width for this |
| // block. |
| _blockBox.setRecommendedWidth(line.getAvailableWidth()); |
| |
| _blockBox._y = getFlowContext().getCurrentY(); |
| |
| // FIXME: blockBox.x should be context.getBorderPaddingInsets().left |
| // or just line.x ? |
| _blockBox._x = 0; |
| } |
| |
| Insets getBorderPaddingInsets() { |
| // FIXME: |
| return new Insets(); |
| } |
| |
| int getLinePadding() { |
| return 0; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.css2.layout.FlowFigureLayout#dispose() |
| */ |
| public void dispose() { |
| // TODO: anything to dispose? |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getContainerWidth() |
| */ |
| public int getContainerWidth() { |
| int width = Math.max(0, Math.max(_blockBox.getWidth(), _blockBox |
| .getRecommendedWidth())); |
| return width; |
| } |
| } |