package org.eclipse.iee.editor.core.pad.common.text; import org.eclipse.draw2d.FocusEvent; import org.eclipse.draw2d.FocusListener; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.text.CaretInfo; import org.eclipse.draw2d.text.FlowPage; import org.eclipse.draw2d.text.ParagraphTextLayout; import org.eclipse.draw2d.text.TextFlow; import org.eclipse.iee.core.document.text.TextStyle; import org.eclipse.iee.editor.core.bindings.IObservableValue; import org.eclipse.iee.editor.core.container.TextRenderCtx; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.swt.widgets.Caret; import org.eclipse.swt.widgets.Display; import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.base.Supplier; import com.google.common.base.Throwables; public class TextPartEditor extends AbstractVisualTextEditor<String, FlowPage> implements ITextContainer<String> { private TextFlow fTextFlow; private Document fText; private FlowPage fFlowPage; private Optional<TextRenderCtx> fRenderCtx = Optional.absent(); public TextPartEditor() { fText = new Document(); } public TextPartEditor(TextRenderCtx renderCtx) { fText = new Document(); } protected FlowPage createFigure() { fFlowPage = new FlowPage() { @Override public Dimension getPreferredSize(int width, int h) { super.getPreferredSize(width, h); TextFlow object = (TextFlow) getChildren().get(0); return object.getPreferredSize(width, h); } }; fTextFlow = new TextFlow(fText.get()); fTextFlow.setFont(getRenderCtx().getFont(Optional.<TextStyle> absent())); fTextFlow.setLayoutManager(new ParagraphTextLayout(fTextFlow, ParagraphTextLayout.WORD_WRAP_SOFT)); fFlowPage.add(fTextFlow); fFlowPage.setRequestFocusEnabled(true); fFlowPage.addFocusListener(new FocusListener() { public void focusGained(FocusEvent fe) { fTextFlow.setText(fText.get()); } public void focusLost(FocusEvent fe) { fText.set(fTextFlow.getText()); }}); fText.addDocumentListener(new IDocumentListener() { @Override public void documentAboutToBeChanged(DocumentEvent event) { } @Override public void documentChanged(DocumentEvent event) { String s = event.getDocument().get(); fTextFlow.setText(getVisibleText(s)); if (getValue().isPresent() && !s.equals(getValue().get().getValue())) { getValue().get().setValue(s); } // fFlowPage.revalidate(); } }); fTextFlow.setText(getVisibleText(getModel())); return fFlowPage; } private TextRenderCtx getRenderCtx() { return fRenderCtx.or(new Supplier<TextRenderCtx>() { @Override public TextRenderCtx get() { return new TextRenderCtx(new TextStyle(), JFaceResources.getResources()); } }); } private String getVisibleText(String s) { if (!Strings.isNullOrEmpty(s)) { return s; } else { return "\u25a1"; } } public void setText(String text) { fText.set(text); } public String getText(String text) { return fText.get(); } public void addDocumentListener(IDocumentListener listener) { fText.addDocumentListener(listener); } public void updateCaret(final Caret caret, final int offset) { Display.getDefault().asyncExec(new Runnable() { public void run() { CaretInfo caretPlacement = fTextFlow.getCaretPlacement(offset, offset == getLength()); caret.setVisible(true); caret.setSize(1, caretPlacement.getHeight()); caret.setLocation(caretPlacement.getX(), caretPlacement.getY()); } }); } public CaretInfo getCaretInfo(final int offset, final boolean b) { return fTextFlow.getCaretPlacement(offset, b); } public Optional<IEditorLocation> getTextLocation(int x, int y) { int[] trailing = new int[1]; Point location = new Point(x, y); fFlowPage.translateFromParent(location); final int offset = fTextFlow.getOffset(location, trailing, null); return Optional.<IEditorLocation> of(new OffsetEditorLocation(this, offset)); } public int getLength() { return fText.getLength(); } public Optional<IEditorLocation> getStart() { return Optional.<IEditorLocation> of(new OffsetEditorLocation(this, 0)); } @Override public Optional<IEditorLocation> getEnd() { return Optional.<IEditorLocation> of(new OffsetEditorLocation(this, getLength() - 1)); } public void replace(int start, int end, String text) { try { fText.replace(start, end - start, text); } catch (BadLocationException e) { throw Throwables.propagate(e); } } @Override public void setSelected(boolean b) { } @Override public void setActive(boolean b) { } @Override public boolean isSelectable() { return false; } public void bindValue(IObservableValue<String> value) { setValue(Optional.of(value)); } @Override protected void onValueChanged(String oldValue, String newValue) { fText.set(newValue); } @Override public void selectBetween(IEditorLocation start, IEditorLocation end) { if (start.getEditor() == this && end.getEditor() == this) { fTextFlow.setSelection(start.getOffset(), end.getOffset()); } else if (start.getEditor() == this) { fTextFlow.setSelection(start.getOffset(), fTextFlow.getText().length()); } else if (end.getEditor() == this) { fTextFlow.setSelection(0, end.getOffset()); } else { fTextFlow.setSelection(0, fTextFlow.getText().length()); } } @Override public void unselectBetween(IEditorLocation start, IEditorLocation end) { fTextFlow.setSelection(-1, -1); } }