package org.eclipse.iee.pad.text.ui; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.TextUtilities; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.text.FlowFigure; import org.eclipse.draw2d.text.FlowPage; import org.eclipse.draw2d.text.TextFlow; import org.eclipse.iee.core.document.text.Document; import org.eclipse.iee.core.document.text.EventBusSupport; import org.eclipse.iee.core.document.text.IDocumentContent; import org.eclipse.iee.core.document.text.INode; import org.eclipse.iee.core.document.text.ISpanContent; import org.eclipse.iee.core.document.text.Span; import org.eclipse.iee.core.document.text.Text; import org.eclipse.iee.editor.core.bindings.DefaultObservableValue; import org.eclipse.iee.editor.core.container.ITextEditor; import org.eclipse.iee.editor.core.container.TextRenderCtx; import org.eclipse.iee.editor.core.pad.common.text.AbstractVisualTextEditor; import com.google.common.base.Optional; import com.google.common.eventbus.Subscribe; public class DocumentEditor extends AbstractVisualTextEditor<Document, FlowPage> { private TextRenderCtx fRenderCtx; public DocumentEditor(TextRenderCtx renderCtx) { fRenderCtx = renderCtx; EventBusSupport.getDefault().register(this); } @Override protected void doBindValue(Document value) { if (value.getChildren().size() == 0) { value.addChild(createEmptySpan()); } for (IDocumentContent documentContent : value.getChildren()) { if (documentContent instanceof Span) { insertEmptyTexts((Span) documentContent); } } updateSpans(value); } protected void insertEmptyTexts(Span span) { for (ISpanContent spanContent : span.getChildren()) { if (spanContent instanceof Span) { if (((Span) spanContent).getChildren().size() == 0) { ((Span) spanContent).addChild(new Span()); } } else if (spanContent instanceof Text) { Text text = (Text) spanContent; TextEditor e = new TextEditor(fRenderCtx); e.setValue(Optional.of(DefaultObservableValue.fromValue(text))); addEditor(e); getFigure().add(e.getView().getWrapped(IFigure.class)); } } } private Span createEmptySpan() { Span span = new Span(); span.addChild(new Text()); return span; } @Subscribe public void onPropertyChange(PropertyChangeEvent event) { if ((event.getSource() == getModel() || isChildren(event.getSource())) && "children".equals(event.getPropertyName())) { updateSpans(getModel()); } } private boolean isChildren(Object source) { if (source instanceof INode) { INode node = (INode) source; while (node != null) { if (node == getModel()) { return true; } node = node.getParent(); } } return false; } protected void updateSpans(Document paragraph) { for (ITextEditor<?> expressionEditor : new ArrayList<>(getChildren())) { removeEditor(expressionEditor); expressionEditor.dispose(); } getFigure().removeAll(); for (IDocumentContent iParagraphContent : paragraph.getChildren()) { if (iParagraphContent instanceof Span) { updateSubSpan((Span) iParagraphContent); } } } protected void updateSubSpan(Span span) { for (ISpanContent spanContent : span.getChildren()) { if (spanContent instanceof Span) { updateSubSpan((Span) spanContent); } else if (spanContent instanceof Text) { Text text = (Text) spanContent; TextEditor e = new TextEditor(fRenderCtx); e.setValue(Optional.of(DefaultObservableValue.fromValue(text))); addEditor(e); getFigure().add(e.getView().getWrapped(IFigure.class)); } } } @Override public boolean isSelectable() { // TODO Auto-generated method stub return false; } @Override public void setSelected(boolean b) { // TODO Auto-generated method stub } @Override public void setActive(boolean b) { // TODO Auto-generated method stub } @Override protected FlowPage createFigure() { return new FlowPage() { @Override public Dimension getPreferredSize(int w, int h) { int width = getWidth(this); return super.getPreferredSize(width, h); } @Override protected void revalidateBidi(IFigure origin) { super.revalidateBidi(origin); getPreferredSize(-1, -1); revalidate(); } private int getWidth(IFigure figure) { List<IFigure> children2 = figure.getChildren(); int width = 0; for (IFigure object : children2) { if (object instanceof TextFlow) { TextFlow textFlow = ((TextFlow) object); String[] parts = textFlow.getText().split("\n"); String text = parts[0]; int iw = TextUtilities.INSTANCE.getTextExtents(text, textFlow.getFont()).width; width += iw; if (parts.length > 1) { break; } } else if (object instanceof FlowFigure) { width += getWidth(object); } } return width; } }; } }