package com.himamis.retex.editor.share.controller;
import java.util.ArrayList;
import com.google.j2objc.annotations.Weak;
import com.himamis.retex.editor.share.editor.MathField;
import com.himamis.retex.editor.share.model.MathComponent;
import com.himamis.retex.editor.share.model.MathContainer;
import com.himamis.retex.editor.share.model.MathFormula;
import com.himamis.retex.editor.share.model.MathSequence;
import com.himamis.retex.editor.share.serializer.TeXBuilder;
import com.himamis.retex.editor.share.serializer.TeXSerializer;
import com.himamis.retex.renderer.share.Atom;
import com.himamis.retex.renderer.share.Box;
import com.himamis.retex.renderer.share.TeXConstants;
import com.himamis.retex.renderer.share.TeXFormula;
import com.himamis.retex.renderer.share.TeXIcon;
import com.himamis.retex.renderer.share.platform.graphics.Insets;
import com.himamis.retex.renderer.share.platform.graphics.stubs.GraphicsStub;
public class MathFieldController {
@Weak
private MathField mathField;
private TeXSerializer texSerializer;
private double size = 16;
private int type = TeXFormula.SERIF;
private GraphicsStub graphics;
private TeXBuilder texBuilder;
public MathFieldController(MathField mathField,
boolean directFormulaBuilder) {
this.mathField = mathField;
texSerializer = new TeXSerializer(mathField.getMetaModel());
if (directFormulaBuilder) {
texBuilder = new TeXBuilder();
}
graphics = new GraphicsStub();
}
public void setSize(double size) {
this.size = size;
}
public void setType(int type) {
this.type = type;
}
public void update(MathFormula mathFormula, EditorState editorState, boolean focusEvent) {
if (mathField.hasFocus()) {
updateFormula(mathFormula, editorState.getCurrentField(),
editorState.getCurrentOffset(),
editorState.getSelectionStart(),
editorState.getSelectionEnd());
} else {
updateFormula(mathFormula, null, 0, null, null);
}
updateMathField(focusEvent);
}
private void updateMathField(boolean focusEvent) {
if (mathField.hasParent()) {
if (!focusEvent) {
// prevent infinite focusChanged <-> requestLayout event cycle
mathField.requestLayout();
}
mathField.repaint();
}
}
private void updateFormula(MathFormula mathFormula,
MathSequence currentField, int currentOffset,
MathComponent selectionStart, MathComponent selectionEnd) {
String serializedFormula = texSerializer.serialize(mathFormula,
currentField, currentOffset, selectionStart, selectionEnd);
TeXFormula texFormula = null;
if (texBuilder != null) {
texFormula = new TeXFormula();
Atom root = texBuilder.build(mathFormula.getRootComponent(),
currentField, currentOffset, selectionStart, selectionEnd);
texFormula.root = root;
}
try {
if (texFormula == null) {
texFormula = new TeXFormula(serializedFormula);
}
TeXIcon renderer = texFormula.new TeXIconBuilder()
.setStyle(TeXConstants.STYLE_DISPLAY).setSize(size)
.setType(type).build();
renderer.setInsets(new Insets(1, 1, 1, 1));
mathField.setTeXIcon(renderer);
mathField.fireInputChangedEvent();
} catch (Exception e) {
System.out.println(selectionStart);
System.out.println(selectionEnd);
System.out.println(serializedFormula);
}
}
public EditorState getPath(MathFormula mathFormula, int x, int y,
ArrayList<Integer> list) {
if (texBuilder == null) {
return null;
}
Atom root = texBuilder.build(mathFormula.getRootComponent(), null, 0,
null, null);
TeXFormula texFormula = new TeXFormula();
texFormula.root = root;
TeXIcon renderer = texFormula.new TeXIconBuilder()
.setStyle(TeXConstants.STYLE_DISPLAY).setSize(size)
.setType(type).build();
renderer.getBox().getPath(x / size, y / size, list);
Box current = renderer.getBox();
EditorState es = new EditorState(mathFormula.getMetaModel());
for (int i = 0; i < list.size() && current.getCount() > 0
&& list.get(i) >= 0; i++) {
if (list.get(i) == current.getCount()) {
current = current.getChild(list.get(i) - 1);
MathComponent comp = texBuilder.getComponent(current.getAtom());
if (comp != null) {
es.setCurrentField((MathSequence) comp.getParent());
es.setCurrentOffset(comp.getParentIndex() + 1);
}
return es;
}
current = current.getChild(list.get(i));
}
MathComponent comp = texBuilder.getComponent(current.getAtom());
es.setCurrentField((MathSequence) comp.getParent());
es.setCurrentOffset(comp.getParentIndex());
return es;
}
public void getSelectedPath(MathFormula mathFormula,
ArrayList<Integer> list, MathSequence currentField,
int currentOffset) {
String serializedFormula = texSerializer.serialize(mathFormula,
currentField, currentOffset);
TeXFormula texFormula = new TeXFormula(serializedFormula);
TeXIcon renderer = texFormula.new TeXIconBuilder()
.setStyle(TeXConstants.STYLE_DISPLAY).setSize(size)
.setType(type).build();
renderer.getBox().getSelectedPath(list, 0);
drawWithStub(renderer);
}
public void setSelectedPath(MathFormula mathFormula,
ArrayList<Integer> path, EditorState state) {
setSelectedPath(mathFormula.getRootComponent(), path, state, 0);
}
private void setSelectedPath(MathContainer rootComponent,
ArrayList<Integer> path, EditorState state, int depth) {
if (path.size() <= depth) {
return;
}
int idx = path.get(depth) <= 0
? path.get(depth) + rootComponent.size()
: path.get(depth);
if (rootComponent
.getArgument(idx) instanceof MathContainer
&& path.size() > depth) {
setSelectedPath(
(MathContainer) rootComponent.getArgument(idx),
path,
state, depth + 1);
} else if (rootComponent instanceof MathSequence) {
state.setCurrentOffset(idx);
state.setCurrentField((MathSequence) rootComponent);
}
}
public void drawWithStub(TeXIcon icon) {
graphics.reset();
icon.paintIcon(null, graphics, 0, 0);
}
}