package org.eclipse.iee.pad.text.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.text.CaretInfo;
import org.eclipse.draw2d.text.ParagraphTextLayout;
import org.eclipse.draw2d.text.TextFlow;
import org.eclipse.iee.core.document.text.EventBusSupport;
import org.eclipse.iee.core.document.text.Text;
import org.eclipse.iee.core.document.text.TextStyle;
import org.eclipse.iee.editor.core.container.TextRenderCtx;
import org.eclipse.iee.editor.core.pad.common.text.AbstractVisualTextEditor;
import org.eclipse.iee.editor.core.pad.common.text.IEditorLocation;
import org.eclipse.iee.editor.core.pad.common.text.ITextContainer;
import org.eclipse.iee.editor.core.pad.common.text.OffsetEditorLocation;
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.eventbus.Subscribe;
public class TextEditor extends AbstractVisualTextEditor<Text, TextFlow> implements ITextContainer<Text> {
private TextRenderCtx fRenderCtx;
private PropertyChangeListener fStyleListener;
private TextStyle fStyle;
public TextEditor(TextRenderCtx renderCtx) {
fRenderCtx = renderCtx;
EventBusSupport.getDefault().register(this);
}
protected TextFlow createFigure() {
TextFlow textFlow = new TextFlow();
updateFont(textFlow, getStyle());
updateBgColor(textFlow);
updateFgColor(textFlow);
textFlow.setLayoutManager(new ParagraphTextLayout(textFlow, ParagraphTextLayout.WORD_WRAP_SOFT));
return textFlow;
}
private Optional<TextStyle> getStyle() {
if (getModel() != null) {
return Optional.<TextStyle> of(getModel().getStyle());
} else {
return Optional.<TextStyle> absent();
}
}
private void updateFont(TextFlow textFlow, Optional<TextStyle> textStyle) {
textFlow.setFont(fRenderCtx.getFont(textStyle));
}
private void updateFgColor(TextFlow textFlow) {
Optional<org.eclipse.swt.graphics.Color> foreground = fRenderCtx.getForeground(getStyle());
if (foreground.isPresent()) {
textFlow.setForegroundColor(foreground.get());
}
}
private void updateBgColor(TextFlow textFlow) {
Optional<org.eclipse.swt.graphics.Color> background = fRenderCtx.getBackground(getStyle());
if (background.isPresent()) {
textFlow.setForegroundColor(background.get());
}
}
private String getVisibleText(String s) {
if (!Strings.isNullOrEmpty(s)) {
return s;
} else {
return "\u25a1";
}
}
public void updateCaret(final Caret caret, final int offset) {
CaretInfo caretPlacement = getFigure().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 getFigure().getCaretPlacement(offset, b);
}
public Optional<IEditorLocation> getTextLocation(int x, int y) {
int[] trailing = new int[1];
Point location = new Point(x, y);
final int offset = getFigure().getOffset(location, trailing, null);
return Optional.<IEditorLocation> of(new OffsetEditorLocation(this, offset));
}
/* (non-Javadoc)
* @see org.eclipse.iee.editor.core.pad.common.text.ITextContainer#getLength()
*/
@Override
public int getLength() {
return getFigure().getText().length();
}
public Optional<IEditorLocation> getStart() {
return Optional.<IEditorLocation> of(createLocation(0));
}
private OffsetEditorLocation createLocation(int offset) {
return new OffsetEditorLocation(this, offset);
}
@Override
public Optional<IEditorLocation> getEnd() {
return Optional.<IEditorLocation> of(new OffsetEditorLocation(this, getLength() - 1));
}
@Override
public Optional<IEditorLocation> getLineStart(int x, int y, boolean askParent) {
if (askParent && getParent().isPresent()) {
return getParent().get().getLineStart(x, y, true);
} else {
Optional<IEditorLocation> lineStart = Optional.absent();
Point t = new Point(x, y);
getFigure().translateToRelative(t);
int firstOffsetForLine = getFigure().getFirstOffsetForLine(t.y);
if (firstOffsetForLine >= 0) {
CaretInfo caretPlacement = getFigure().getCaretPlacement(firstOffsetForLine, false);
if (caretPlacement.getX() < x) {
lineStart = Optional.<IEditorLocation> of(new OffsetEditorLocation(this, firstOffsetForLine));
}
}
return lineStart;
}
}
@Override
public Optional<IEditorLocation> getLineEnd(int x, int y, boolean askParent) {
if (askParent && getParent().isPresent()) {
return getParent().get().getLineEnd(x, y, true);
} else {
Optional<IEditorLocation> lineEnd = Optional.absent();
Point t = new Point(x, y);
getFigure().translateToRelative(t);
int lastOffsetForLine = getFigure().getLastOffsetForLine(t.y);
if (lastOffsetForLine >= 0) {
CaretInfo caretPlacement = getFigure().getCaretPlacement(lastOffsetForLine, true);
if (caretPlacement.getX() > x) {
lineEnd = Optional.<IEditorLocation> of(new OffsetEditorLocation(this, lastOffsetForLine + 1));
}
}
return lineEnd;
}
}
@Override
protected void doBindValue(Text value) {
fStyleListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("bold".equals(evt.getPropertyName())
|| "italic".equals(evt.getPropertyName())
|| "font".equals(evt.getPropertyName())
|| "fontSize".equals(evt.getPropertyName())) {
updateFont(getFigure(), getStyle());
}
if ("fgColor".equals(evt.getPropertyName())) {
updateFgColor(getFigure());
}
if ("bgColor".equals(evt.getPropertyName())) {
updateBgColor(getFigure());
}
}
};
fStyle = value.getStyle();
fStyle.addPropertyChangeListener(fStyleListener);
updateValue(value.getText());
}
@Override
protected void doUnbindValue(Text oldValue) {
if (fStyle != null) {
fStyle.removePropertyChangeListener(fStyleListener);
fStyle = null;
}
updateValue("");
}
@Subscribe
public void onPropertyChange(PropertyChangeEvent event) {
if (event.getSource() == getModel() && "text".equals(event.getPropertyName())) {
String value = (String) event.getNewValue();
updateValue(value);
}
}
private void updateValue(String value) {
getFigure().setText(getVisibleText(value));
}
@Override
public void selectBetween(IEditorLocation start, IEditorLocation end) {
int startOffset = getStartOffset(start);
int endOffset = getEndOffset(end);
getFigure().setSelection(startOffset, endOffset);
}
private int getStartOffset(IEditorLocation start) {
if (start.getEditor() == this) {
return start.getOffset();
}
return 0;
}
private int getEndOffset(IEditorLocation end) {
if (end.getEditor() == this) {
return end.getOffset();
}
return getFigure().getText().length();
}
@Override
public void unselectBetween(IEditorLocation start, IEditorLocation end) {
getFigure().setSelection(-1, -1);
}
@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
}
}