blob: aa83d2dccd07f8f92bd6355659e6be92d084d44e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation 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
*******************************************************************************/
package org.eclipse.draw2d.text;
import java.util.Iterator;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
/**
* The base implementation for text flow figures. A flow figure is used to
* render a document in which elements are laid out horizontally within a "line"
* until that line is filled. Layout continues on the next line.
*
* <p>
* WARNING: This class is not intended to be subclassed by clients. Future
* versions may contain additional abstract methods.
*
* @author hudsonr
* @since 2.1
*/
public abstract class FlowFigure extends Figure {
/**
* integer indicating whether selection should be displayed.
*/
protected int selectionStart = -1;
/**
* Constructs a new FlowFigure.
*/
public FlowFigure() {
setLayoutManager(createDefaultFlowLayout());
}
/**
* If the child is a <code>FlowFigure</code>, its FlowContext is passed to
* it.
*
* @see org.eclipse.draw2d.IFigure#add(IFigure, Object, int)
*/
public void add(IFigure child, Object constraint, int index) {
super.add(child, constraint, index);
// If this layout manager is a FlowContext, then the child *must* be a
// FlowFigure
if (getLayoutManager() instanceof FlowContext)
((FlowFigure) child)
.setFlowContext((FlowContext) getLayoutManager());
revalidateBidi(this);
}
/**
* Calculates the width of text before the next line-break is encountered.
* <p>
* Default implementation treats each FlowFigure as a line-break. It adds no
* width and returns <code>true</code>. Sub-classes should override as
* needed.
*
* @param width
* the width before the next line-break (if one's found; all the
* width, otherwise) will be added on to the first int in the
* given array
* @return boolean indicating whether or not a line-break was found
* @since 3.1
*/
public boolean addLeadingWordRequirements(int[] width) {
return true;
}
/**
* FlowFigures can contribute text for their block to the given
* {@link BidiProcessor}, which will process the contributions to determine
* Bidi levels and shaping requirements.
* <p>
* This method is invoked as part of validating Bidi.
* <p>
* Sub-classes that cache the BidiInfo and/or the bidi level in ContentBoxes
* should clear the cached values when this method is invoked.
*
* @param proc
* the BidiProcessor to which contributions should be made
* @see BidiProcessor#add(FlowFigure, String)
* @since 3.1
*/
protected void contributeBidi(BidiProcessor proc) {
for (Iterator iter = getChildren().iterator(); iter.hasNext();)
((FlowFigure) iter.next()).contributeBidi(proc);
}
/**
* Creates the default layout manager
*
* @return The default layout
*/
protected abstract FlowFigureLayout createDefaultFlowLayout();
/**
* Called after validate has occurred. This is used to update the bounds of
* the FlowFigure to encompass its new flow boxed created during validate.
*/
public abstract void postValidate();
/**
* Overridden to revalidateBidi when fragments are removed.
*
* @see org.eclipse.draw2d.IFigure#remove(org.eclipse.draw2d.IFigure)
*/
public void remove(IFigure figure) {
super.remove(figure);
revalidateBidi(this);
}
/**
* This method should be invoked whenever a change that can potentially
* affect the Bidi evaluation is made (eg., adding or removing children,
* changing text, etc.).
* <p>
* The default implementation delegates the revalidation task to the parent.
* Only {@link BlockFlow#revalidateBidi(IFigure) blocks} perform the actual
* revalidation.
* <p>
* The given IFigure is the one that triggered the revalidation. This can be
* used to optimize bidi evaluation.
*
* @param origin
* the figure that was revalidated
* @since 3.1
*/
protected void revalidateBidi(IFigure origin) {
if (getParent() != null)
((FlowFigure) getParent()).revalidateBidi(origin);
}
/**
* Sets the bidi information for this figure. A flow figure contributes bidi
* text in {@link #contributeBidi(BidiProcessor)}. If the figure contributes
* text associated with it, this method is called back to indicate the bidi
* properties for that text within its block.
*
* @param info
* the BidiInfo for this figure
* @since 3.1
*/
public void setBidiInfo(BidiInfo info) {
}
/**
* FlowFigures override setBounds() to prevent translation of children.
* "bounds" is a derived property for FlowFigures, calculated from the
* fragments that make up the FlowFigure.
*
* @see Figure#setBounds(Rectangle)
*/
public void setBounds(Rectangle r) {
if (bounds.equals(r))
return;
if (!r.contains(bounds))
erase();
bounds.x = r.x;
bounds.y = r.y;
bounds.width = r.width;
bounds.height = r.height;
fireFigureMoved();
if (isCoordinateSystem())
fireCoordinateSystemChanged();
repaint();
}
/**
* Sets the flow context.
*
* @param flowContext
* the flow context for this flow figure
*/
public void setFlowContext(FlowContext flowContext) {
((FlowFigureLayout) getLayoutManager()).setFlowContext(flowContext);
}
/**
* Sets the selection or a range of selection. A start value of -1 is used
* to indicate no selection. A start value >=0 indicates show selection. A
* start and end value can be used to represent a range of offsets which
* should render selection.
*
* @param start
* the start offset
* @param end
* the end offset
* @since 3.1
*/
public void setSelection(int start, int end) {
if (selectionStart == start)
return;
selectionStart = start;
repaint();
}
}