/******************************************************************************* * 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 java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.jst.pagedesigner.css2.ICSSStyle; import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID; import org.eclipse.jst.pagedesigner.css2.style.ITagEditInfo; /** * The layout manager for {@link CSSFigure}figures. This class is based on * InlineFlowLayout of draw2d. * * @author mengbo */ public class CSSInlineFlowLayout extends CSSLayout { List _fragments = new ArrayList(); /** * Creates a new InlineFlowLayout with the given FlowFigure. * * @param flow * The FlowFigure */ public CSSInlineFlowLayout(CSSFigure flow) { super(flow); } /** * Clears out all fragments prior to the call to layoutChildren(). */ public void preLayout() { super.preLayout(); _fragments.clear(); // force creating of the first line. avoid empty element don't have // fragments. // createFirstLine(); } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContainerLayout#layoutChildren() */ protected void layoutChildren() { // For designer, to make it to have some size. otherwise can't // be found on screen. // List children = getCSSFigure().getChildren(); // if (children.size() == 0) // { // FlowBox box = new FlowBox(); // box._height = getCSSStyle().getCSSFont().getFontSize(); // box._width = 2; // addToCurrentLine(box); // // } super.layoutChildren(); } /** * Adds the given FlowBox to the current line of this InlineFlowLayout. * * @param block * the FlowBox to add to the current line */ public void addToCurrentLine(FlowBox block) { getCurrentLine().add(block); // XXX: ???: will currentLine be added multiple times to fragments? // (yang) // _fragments.add(_currentLine); } private void createFirstLine() { _currentLine = new LineBox(); setupLine(_currentLine, true); _fragments.add(_currentLine); } /** * @see FlowContainerLayout#createNewLine() */ protected void createNewLine() { _currentLine = new LineBox(); setupLine(_currentLine, false); _fragments.add(_currentLine); } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContainerLayout#createNewLine(int) */ protected void createNewLine(int topMargin) { // inline flow don't support vertical margin. createNewLine(); } /** * @see FlowContainerLayout#cleanup() */ protected void cleanup() { _currentLine = null; } /** * @see FlowContainerLayout#flush() */ protected void flush() { if (_fragments.isEmpty()) { createFirstLine(); } else if (_fragments.size() == 1) { ICSSStyle style = getCSSStyle(); int minWidth = 0, minHeight = 0; // try to see whether there is any designer specified min size ITagEditInfo info = (ITagEditInfo) style .getAdapter(ITagEditInfo.class); if (info != null) { minWidth = info.getMinWidth(); minHeight = info.getMinHeight(); } FlowBox box = (FlowBox) _fragments.get(0); if (minWidth > box._width) { box._width = minWidth; } if (minHeight > box._height) { box._height = minHeight; } } if (_currentLine != null /* && _currentLine.isOccupied() */) { _currentLine.getMarginInsets().right = getCSSStyle().getMarginInsets().right; getFlowContext().addToCurrentLine(_currentLine); } } /** * @see FlowContext#endLine() */ public void endLine() { if (_currentLine == null) { getFlowContext().endLine(); return; } // If nothing was ever placed in the line, ignore it. and if the line is // the first line, just remove it. if (_currentLine.isOccupied()) { getFlowContext().addToCurrentLine(_currentLine); } else if (_fragments.size() == 1) { _fragments.remove(0); } getFlowContext().endLine(); _currentLine = null; } /** * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentY() */ public int getCurrentY() { return getCurrentLine()._y; } /** * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContainerLayout#isCurrentLineOccupied() */ public boolean isCurrentLineOccupied() { if (_currentLine == null) { return getFlowContext().isCurrentLineOccupied(); } else if (_currentLine.getFragments().isEmpty()) { return getFlowContext().isCurrentLineOccupied(); } else { return true; } } /** * Initializes the given LineBox. Called by createNewLine(). * * @param line * The LineBox to initialize. * @param firstline */ protected void setupLine(LineBox line, boolean firstline) { LineBox parent = getFlowContext().getCurrentLine(); line._x = 0; line._y = getFlowContext().getCurrentY(); line.setRecommendedWidth(parent.getAvailableWidth()); setLineVerticalAlign(line); setFontinfoForLine(line); if (firstline && getCSSStyle() != null) { ICSSStyle style = getCSSStyle(); int minWidth = 0, minHeight = 0; // try to see whether there is any designer specified min size ITagEditInfo info = (ITagEditInfo) style .getAdapter(ITagEditInfo.class); if (info != null) { minWidth = info.getMinWidth(); minHeight = info.getMinHeight(); } // // CSS also has the min-width/min-height property. We should also // get that, // // and using the max of the "min-width" css property and the // designer specified min size. // int height = // getLengthValue(style,ICSSPropertyID.ATTR_MIN_HEIGHT); // if(height > minHeight) // { // minHeight = height; // } // int width = getLengthValue(style,ICSSPropertyID.ATTR_MIN_WIDTH); // if(width > minWidth) // { // minWidth = width; // } if (minWidth > 0) { line.setWidth(minWidth); } int fontHeight = this.getCSSStyle().getCSSFont().getXHeight(); if (minHeight > 0 && minHeight > fontHeight) { line.setHeight(minHeight); } else { line.setHeight(fontHeight); } } } private void setLineVerticalAlign(LineBox box) { ICSSStyle style = getCSSStyle(); if (style != null) { box.setVerticalAlignData(style .getStyleProperty(ICSSPropertyID.ATTR_VERTICAL_ALIGN)); } } private void setFontinfoForLine(LineBox line) { ICSSStyle style = getCSSStyle(); if (style != null) { line.setFontMetrics(FigureUtilities.getFontMetrics(style .getCSSFont().getSwtFont())); } } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.FlowFigureLayout#dispose() */ public void dispose() { // } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSLayout#getFragmentsForRead() */ public List getFragmentsForRead() { return _fragments; } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSLayout#postValidate() */ public void postValidate() { List list = _fragments; FlowBox box; int left = Integer.MAX_VALUE, top = left; int right = Integer.MIN_VALUE, bottom = right; for (int i = 0; i < list.size(); i++) { box = (FlowBox) list.get(i); // if (box instanceof LineBox && !((LineBox) box).isOccupied()) // { // continue; // skip unoccupied line // } left = Math.min(left, box._x); right = Math.max(right, box._x + box._width); top = Math.min(top, box._y); bottom = Math.max(bottom, box._y + box._height); } getCSSFigure().setBounds( new Rectangle(left, top, right - left, bottom - top)); list = getCSSFigure().getChildren(); for (int i = 0; i < list.size(); i++) { ((FlowFigure) list.get(i)).postValidate(); } } /* * (non-Javadoc) * * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getContainerWidth() */ public int getContainerWidth() { // FIXME: don't really understand what means for inline return this.getFlowContext().getContainerWidth(); } }