blob: b61a37a948c81106d5d508d9de0e87cf02648c15 [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.List;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.swt.graphics.Font;
/**
* @author mengbo
*/
// NOTE: CSSTextLayout does not extends CSSFlowLayout. Since text is a little
// special,
// we don't want to do things like "preLayout()" as in CSSFlowLayout.
public class CSSTextLayout extends FlowFigureLayout {
/**
* Wrapping will ONLY occur at valid line breaks
*/
public static final int WORD_WRAP_HARD = 0;
/**
* Wrapping will always occur at the end of the available space, breaking in
* the middle of a word.
*/
public static final int WORD_WRAP_SOFT = 1;
/**
* Wrapping will always occur at the end of available space, truncating a
* word if it doesn't fit.
*/
// don't support this flag
// public static final int WORD_WRAP_TRUNCATE = 2;
private int _wrappingStyle = WORD_WRAP_HARD;
public CSSTextLayout(CSSTextFigure textfigure) {
super(textfigure);
}
// --------------------------------------------------------------------------------------------------
FlowBox findLastNonLineBox(LineBox box) {
List fragments = box.getFragments();
for (int i = fragments.size() - 1; i >= 0; i--) {
FlowBox item = (FlowBox) fragments.get(i);
if (item instanceof LineBox) {
FlowBox found = findLastNonLineBox((LineBox) item);
if (found != null) {
return found;
}
} else {
return item;
}
}
return null;
}
// boolean isElementContentWhitespaceEnding()
// {
// if (!this._context.isCurrentLineOccupied())
// return true;
// LineBox line = this._context.getCurrentLine();
// FlowBox lastNoneLinebox = findLastNonLineBox(line);
// if (lastNoneLinebox instanceof TextFragmentBox)
// return ((TextFragmentBox) lastNoneLinebox)._isLastCharWhitespace;
// else
// return true;
// }
//
// String normalize(String text)
// {
// text = EntityMap.translateAndCompact(text);
// if (text.length() > 0 &&
// Character.isElementContentWhitespace(text.charAt(0)) &&
// isElementContentWhitespaceEnding())
// return text.substring(1);
// else
// return text;
// }
private void layoutEmptyString(List fragments, Font font) {
// empty node! we want to create a fake fragment, so things can be
// consistent
// that all the CSSTextFigure will have something inside, also in this
// way, even
// empty text node will have a position, thus we can support showing
// caret associated
// with this text figure.
fragments.clear();
TextFragmentBox box = TextLayoutSupport.getFragment(0, fragments);
box._length = 0;
box._offset = 0;
box._height = 0;
box._width = 0;
box.setTextData("");
// {following comments deprecated XXX: If is empty string, we only want
// to this figure to have a size, but don't
// want to it to be added into current line. Otherwise, a line with only
// a empty string
// will also take a line's space.}
// please reference LineBox.isOccupied()
// now we treat a line with only an empty text as not occupied.
getFlowContext().getCurrentLine().add(box);
}
/**
* @see org.eclipse.jst.pagedesigner.css2.layout.FlowFigureLayout#layout()
*/
protected void layout() {
CSSTextFigure flowFigure = (CSSTextFigure) getFlowFigure();
List fragments = flowFigure.getFragments();// Reuse the previous List
// of fragments
String text = flowFigure.getText();
Font font = flowFigure.getCSSStyle().getCSSFont().getSwtFont();
Object whitespace = flowFigure.getCSSStyle().getStyleProperty(
ICSSPropertyID.ATTR_WHITESPACE);
if (whitespace == ICSSPropertyID.VAL_PRE) {
if (text == null || text.length() == 0)
layoutEmptyString(fragments, font);
else
TextLayoutSupport.layoutNoWrap(getFlowContext(), text,
fragments, font);
} else if (whitespace == ICSSPropertyID.VAL_NOWRAP) {
if (text == null || text.length() == 0)
layoutEmptyString(fragments, font);
else
TextLayoutSupport.layoutNoWrap(getFlowContext(), text,
fragments, font);
} else {
if (text == null || text.length() == 0)
layoutEmptyString(fragments, font);
else {
boolean trimLeadingChar = (text.charAt(0) == ' ' && shouldTrimLeadingWhitespace(getFlowContext()));
TextLayoutSupport.layoutNormal(getFlowContext(), text,
fragments, font, _wrappingStyle, trimLeadingChar);
}
}
}
// XXX: maybe should move to TextSupport later.
public boolean shouldTrimLeadingWhitespace(FlowContext context) {
if (!context.isCurrentLineOccupied()) {
return true;
}
while (context instanceof CSSInlineFlowLayout) {
context = ((CSSInlineFlowLayout) context).getFlowContext();
}
LineBox line = context.getCurrentLine();
if (line == null || !line.isOccupied()) {
return true;
}
FlowBox lastNoneLinebox = findLastNonLineBox(line);
if (lastNoneLinebox == null || lastNoneLinebox.getWidth() == 0) {
return true;
} else if (lastNoneLinebox instanceof TextFragmentBox) {
return ((TextFragmentBox) lastNoneLinebox)._isLastCharWhitespace;
} else {
return false;
}
}
public void dispose() {
}
}