/******************************************************************************* * Copyright (c) 2004, 2005 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.gef.examples.text.edit; import java.beans.PropertyChangeEvent; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.MarginBorder; import org.eclipse.draw2d.text.BlockFlow; import org.eclipse.draw2d.text.CaretInfo; import org.eclipse.draw2d.text.FlowPage; import org.eclipse.draw2d.text.InlineFlow; import org.eclipse.gef.examples.text.TextLocation; import org.eclipse.gef.examples.text.figures.CommentPage; import org.eclipse.gef.examples.text.model.Container; import org.eclipse.gef.examples.text.requests.CaretRequest; import org.eclipse.gef.examples.text.requests.SearchResult; /** * @since 3.1 */ public abstract class CompoundTextPart extends AbstractTextPart { public CompoundTextPart(Object model) { setModel(model); } public boolean acceptsCaret() { for (Iterator iter = getChildren().iterator(); iter.hasNext();) { TextEditPart part = (TextEditPart)iter.next(); if (part.acceptsCaret()) return true; } return false; } public void activate() { super.activate(); getContainer().getStyle().addPropertyChangeListener(this); } protected void createEditPolicies() {} protected IFigure createFigure() { Figure figure = null; switch (getContainer().getType()) { case Container.TYPE_INLINE: figure = new InlineFlow(); break; case Container.TYPE_COMMENT: figure = new CommentPage(); break; case Container.TYPE_PARAGRAPH: figure = new BlockFlow(); figure.setBorder(new MarginBorder(4, 2, 4, 0)); break; case Container.TYPE_ROOT: figure = new FlowPage(); figure.setBorder(new MarginBorder(4)); break; default: throw new RuntimeException("unexpected container"); } return figure; } public void deactivate() { getContainer().getStyle().removePropertyChangeListener(this); super.deactivate(); } public CaretInfo getCaretPlacement(int offset, boolean trailing) { throw new RuntimeException("This part cannot place the caret"); } protected Container getContainer() { return (Container)getModel(); } /** * @see TextEditPart#getLength() */ public int getLength() { return getChildren().size(); } protected List getModelChildren() { return getContainer().getChildren(); } /** * @see TextEditPart#getTextLocation(int, TextLocation) */ public void getTextLocation(CaretRequest search, SearchResult result) { if (search.getType() == CaretRequest.LINE_BOUNDARY) { if (search.isForward) searchLineEnd(search, result); else searchLineBegin(search, result); } else if (search.getType() == CaretRequest.ROW || search.getType() == CaretRequest.LOCATION) { if (search.isForward) searchLineBelow(search, result); else searchLineAbove(search, result); } else if (search.getType() == CaretRequest.COLUMN || search.getType() == CaretRequest.WORD_BOUNDARY) { if (search.isForward) searchForward(search, result); else searchBackward(search, result); } else if (getParent() instanceof TextEditPart) getTextParent().getTextLocation(search, result); } public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("children")) refreshChildren(); } protected void searchBackward(CaretRequest search, SearchResult result) { int childIndex = search.isRecursive ? getChildren().size() - 1 : getChildren().indexOf(search.where.part) - 1; boolean wasRecursive = search.isRecursive; search.setRecursive(true); while (childIndex >= 0) { TextEditPart part = (TextEditPart)getChildren().get(childIndex--); part.getTextLocation(search, result); if (result.location != null) return; } search.setRecursive(wasRecursive); if (!search.isRecursive && getParent() instanceof TextEditPart) { if (this instanceof BlockTextPart) search.isInto = true; search.setReferenceTextLocation(this, 0); getTextParent().getTextLocation(search, result); } } protected void searchForward(CaretRequest search, SearchResult result) { int childIndex = search.isRecursive ? 0 : getChildren().indexOf(search.where.part) + 1; int childCount = getChildren().size(); boolean wasRecursive = search.isRecursive; search.setRecursive(true); while (childIndex < childCount) { TextEditPart part = (TextEditPart)getChildren().get(childIndex++); part.getTextLocation(search, result); if (result.location != null) return; } search.setRecursive(wasRecursive); if (!search.isRecursive && getParent() instanceof TextEditPart) { if (this instanceof BlockTextPart) search.isInto = true; search.setReferenceTextLocation(this, getLength()); getTextParent().getTextLocation(search, result); } } protected void searchLineAbove(CaretRequest search, SearchResult result) { int childIndex; TextEditPart part; if (search.isRecursive) childIndex = getChildren().size() - 1; else { childIndex = getChildren().indexOf(search.where.part); if (search.where.offset == 0) childIndex--; } boolean wasRecursive = search.isRecursive; search.setRecursive(true); while (childIndex >= 0) { part = (TextEditPart)getChildren().get(childIndex--); part.getTextLocation(search, result); if (result.bestMatchFound) return; } search.setRecursive(wasRecursive); if (!search.isRecursive && getParent() instanceof TextEditPart) { search.setReferenceTextLocation(this, 0); getTextParent().getTextLocation(search, result); } } protected void searchLineBegin(CaretRequest search, SearchResult result) { int childIndex = 0; int childCount = getChildren().size(); search.setRecursive(true); while (childIndex < childCount) { TextEditPart newPart = (TextEditPart)getChildren().get(childIndex++); newPart.getTextLocation(search, result); if (result.location != null) return; } } protected void searchLineBelow(CaretRequest search, SearchResult result) { //The top of this figure must be below the bottom of the caret // if (getFigure().getBounds().y < caret.bottom()) //return null; int childIndex; int childCount = getChildren().size(); if (search.isRecursive || (!search.isRecursive && search.where == null)) childIndex = 0; else { childIndex = getChildren().indexOf(search.where.part); if (search.where.offset == search.where.part.getLength()) childIndex++; } boolean wasRecursive = search.isRecursive; search.setRecursive(true); while (childIndex < childCount) { TextEditPart part = (TextEditPart)getChildren().get(childIndex++); part.getTextLocation(search, result); if (result.bestMatchFound) return; } search.setRecursive(wasRecursive); if (!search.isRecursive && getParent() instanceof TextEditPart) { search.setReferenceTextLocation(this, getLength()); getTextParent().getTextLocation(search, result); } } protected void searchLineEnd(CaretRequest search, SearchResult result) { int childIndex = getChildren().size() - 1; TextEditPart child; search.setRecursive(true); while (childIndex >= 0) { child = (TextEditPart)getChildren().get(childIndex--); child.getTextLocation(search, result); if (result.location != null) return; } } }