blob: 97f4571c040a0c622d0e4ccf9bb09a0e44dfd4a7 [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 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._marginInsets.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.
*/
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();
}
}