/******************************************************************************* * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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: * IBM Corporation - initial API and implementation * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.draw2d.text; import java.util.List; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.swt.SWT; /** * The layout for {@link BlockFlow} figures. * * <P> * WARNING: This class is not intended to be subclassed by clients. * * @author hudsonr * @since 2.1 */ public class BlockFlowLayout extends FlowContainerLayout { BlockBox blockBox; boolean blockInvalid = false; private boolean continueOnSameLine = false; private CompositeBox previousLine = null; /** * Creates a new BlockFlowLayout with the given BlockFlow. * * @param blockFlow * the BlockFlow */ public BlockFlowLayout(BlockFlow blockFlow) { super(blockFlow); } private void addBelowPreviousLine(CompositeBox line) { if (previousLine == null) line.setLineTop(line.getTopMargin()); else line.setLineTop(previousLine.getBaseline() + previousLine.getDescent() + Math.max(previousLine.getBottomMargin(), line.getTopMargin())); int alignment = getBlockFlow().getHorizontalAligment(); if (alignment == PositionConstants.LEFT || alignment == PositionConstants.RIGHT) { int orientation = getBlockFlow().getOrientation(); if (alignment == PositionConstants.LEFT) alignment = orientation == SWT.LEFT_TO_RIGHT ? PositionConstants.ALWAYS_LEFT : PositionConstants.ALWAYS_RIGHT; else alignment = orientation == SWT.LEFT_TO_RIGHT ? PositionConstants.ALWAYS_RIGHT : PositionConstants.ALWAYS_LEFT; } if (alignment != PositionConstants.CENTER && getBlockFlow().isMirrored()) alignment = (PositionConstants.ALWAYS_LEFT | PositionConstants.ALWAYS_RIGHT) & ~alignment; switch (alignment) { case PositionConstants.ALWAYS_RIGHT: line.setX(blockBox.getRecommendedWidth() - line.getWidth()); break; case PositionConstants.CENTER: line.setX((blockBox.getRecommendedWidth() - line.getWidth()) / 2); break; case PositionConstants.ALWAYS_LEFT: line.setX(0); break; default: throw new RuntimeException("Unexpected state"); //$NON-NLS-1$ } blockBox.add(line); previousLine = line; } /** * Align the line horizontally and then commit it. */ protected void addCurrentLine() { addBelowPreviousLine(currentLine); ((LineRoot) currentLine).commit(); } /** * @see FlowContext#addLine(CompositeBox) */ public void addLine(CompositeBox box) { endLine(); addBelowPreviousLine(box); } /** * Marks the blocks contents as changed. This means that children will be * invalidated during validation. * * @since 3.1 */ public void blockContentsChanged() { blockInvalid = true; } /** * @see FlowContainerLayout#cleanup() */ protected void cleanup() { super.cleanup(); previousLine = null; } /** * @see FlowContainerLayout#createNewLine() */ protected void createNewLine() { currentLine = new LineRoot(getBlockFlow().isMirrored()); currentLine.setRecommendedWidth(blockBox.getRecommendedWidth()); } /** * Called by flush(), adds the BlockBox associated with this BlockFlowLayout * to the current line and then ends the line. */ protected void endBlock() { if (blockInvalid) { Insets insets = getBlockFlow().getInsets(); blockBox.height += insets.getHeight(); blockBox.width += insets.getWidth(); } if (getContext() != null) getContext().addLine(blockBox); if (blockInvalid) { blockInvalid = false; List v = getFlowFigure().getChildren(); for (int i = 0; i < v.size(); i++) ((FlowFigure) v.get(i)).postValidate(); } } /** * @see FlowContext#endLine() */ public void endLine() { if (currentLine == null || !currentLine.isOccupied()) return; addCurrentLine(); currentLine = null; } /** * @see FlowContainerLayout#flush() */ protected void flush() { endLine(); endBlock(); } boolean forceChildInvalidation(Figure f) { return blockInvalid; } /** * Returns the BlockFlow associated with this BlockFlowLayout * * @return the BlockFlow */ protected final BlockFlow getBlockFlow() { return (BlockFlow) getFlowFigure(); } int getContextWidth() { return getContext().getRemainingLineWidth(); } /** * @see FlowContext#getContinueOnSameLine() */ public boolean getContinueOnSameLine() { return continueOnSameLine; } /** * @see FlowContext#getWidthLookahead(FlowFigure, int[]) */ public void getWidthLookahead(FlowFigure child, int result[]) { List children = getFlowFigure().getChildren(); int index = -1; if (child != null) index = children.indexOf(child); for (int i = index + 1; i < children.size(); i++) if (((FlowFigure) children.get(i)) .addLeadingWordRequirements(result)) return; } /** * @see FlowContainerLayout#preLayout() */ protected void preLayout() { setContinueOnSameLine(false); blockBox = getBlockFlow().getBlockBox(); setupBlock(); // Probably could setup current and previous line here, or just previous } /** * @see org.eclipse.draw2d.text.FlowContext#setContinueOnSameLine(boolean) */ public void setContinueOnSameLine(boolean value) { continueOnSameLine = value; } /** * sets up the single block that contains all of the lines. */ protected void setupBlock() { int recommended = getContextWidth(); if (recommended == Integer.MAX_VALUE) recommended = -1; BlockFlow bf = getBlockFlow(); if (recommended > 0) { int borderCorrection = bf.getInsets().getWidth() + bf.getLeftMargin() + bf.getRightMargin(); recommended = Math.max(0, recommended - borderCorrection); } if (recommended != blockBox.recommendedWidth) { blockInvalid = true; blockBox.setRecommendedWidth(recommended); } if (blockInvalid) { blockBox.height = 0; blockBox.setWidth(Math.max(0, recommended)); } } }