Auf Thema antworten

Also bei OpenOffice/LibreOffice finde ich es einfach sehr unpraktisch, dass man immer diesen Mathe-Editor aufmachen muss und er sich immer schließt, sobald man eine Formel eingegeben hat.

Deswegen würde ich gerne diesen Workflow beschleunigen.


So in etwa dachte ich mir das auch mit dem TextField einbinden nach jeder Space-Taste, aber das Alignment-Management wäre mir dann einfach etwas zu heftig und kompliziert bei dem TextFlow.. Mit CSS kenne ich mich noch nicht so gut aus, vor allem wenn es darum geht Controls stark abzuändern.

Bisher habe ich immer nur Textfarben oder ähnliches verändert aber nie die Form. Denke da kann ich mich aber auch leicht einarbeiten (falls es gut dokumentiert ist).


Falls du wirklich Interesse hast:

Die Syntax von LaTeX ist denkbar einfach und leicht zu merken (zumindest für mathematische Ausdrücke).

Hier ist mal eine schnelle Referenz:

http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference

Prinzipiell benötigt man (zumindest ich in diesem Fall) nur folgende Ausdrücke:

  • Tiefgestelle Ausdrücke: "_" -> x_0 ergibt ein x mit einer tiefgestellten 0. Allgemeine Syntax lautet _{} wobei man in der geschweiften Klammer mehrere Ausdrücke angeben kann
  • Hochgestellte Ausdrücke: ^{} -> x^0 ergibt ein x mit einer hochgestellten 0.
  • Integral: \int_{}^{}: ergibt ein Integral mit einer von (underscore) bis (hochgestellt) Grenze
  • Summe: \sum_{}^{}: ergibt das Summenzeichen mit den Grenzen, Beispiel: \sum_{i=0}^{n}
  • Brüche: \frac{}{}: erster Ausdruck steht für Zähler, zweiter für Nenner, Beispiel: \frac{\cos{\theta}}{\sin{\alpha}}
  • Griechische Buchstaben: einfach ein vorangestelltes "\" und den Namen, Beispiel: \alpha, \beta\, \delta, \Delta, \theta, ...

Da gibt's noch was zu beachten:

Es gibt sogenannte Inline und Display Methoden:

Inline-Methoden werden benutzt, wenn man einen mathematischen Ausdruck innerhalb eines Textes anzeigen will, während der Display-Modus quasi als Bild dargestellt wird, das in eine eigene Zeile geschrieben wird und auch eine ganze Zeile beansprucht.

Für Inline umschließt man den gesamten Ausdruck typischerweise mit: $ausdruck$

Für Display kann man entweder "$$ausdruck$$" oder "\[ausdruck\]" verwenden.


Im Folgenden zeige ich dir mal bisher, was ich so habe:

[SPOILER="MainApp"]

[code=Java]public class MainApp extends Application {


    @Override

    public void start(Stage stage) {

        MainPresenter mainPresenter = initApplication();

        Scene scene = new Scene(mainPresenter.getView(), 600, 400);

        stage.setScene(scene);

        stage.setTitle("Math Editor - Simplyfy");

        stage.show();

    }


    private MainPresenter initApplication() {

        MainPresenter mainPresenter = new MainPresenter();

        MyEditorView mainView = new MyEditorView();

        FormulaModel model = new FormulaModel();


        mainView.setPresenter(mainPresenter);

        mainPresenter.setView(mainView);

        mainPresenter.setFormulaModel(model);

        mainView.init();


        return mainPresenter;

    }


    public static void main(String[] args) {

        launch(args);

    }

}[/code]

[/SPOILER]


[SPOILER="Presenter"]

[code=Java]public class MainPresenter {


    private MyEditorView view;

    private FormulaModel model;


    public void setFormulaModel(FormulaModel mod) {

        this.model = mod;

    }


    public void updateFormulaModel(ImageView imageView, String formula) {

        if ((model.getOriginalStringFromImage(imageView) == null)

                || model.getOriginalStringFromImage(imageView).isEmpty()) {


        } else {

            model.addImageAndFormula(imageView, formula);

        }

    }


    public String getFormulaFromSelectedImageView(ImageView iv) {

        return model.getOriginalStringFromImage(iv);

    }


    public ImageView createImageViewFromFormula(String formula) {


        ImageView iv = null;

        if (TeXUtil.isParsable(formula)) {

            iv = TeXUtil.parseFormula(formula);

            model.addImageAndFormula(iv, formula);

        }


        return iv;

    }


    public void removeFormula(ImageView iv) {

        model.getMap().remove(iv);

    }


    public void setView(MyEditorView mainV) {

        this.view = mainV;

    }


    public MyEditorView getView() {

        return this.view;

    }

}[/code]

[/SPOILER]


[SPOILER="Model"]

[code=Java]

import java.util.LinkedHashMap;


import javafx.scene.image.ImageView;


public class FormulaModel {


    private LinkedHashMap<ImageView, String> imageFormula;


    public FormulaModel() {

        this.imageFormula = new LinkedHashMap<>();


    }


    public LinkedHashMap<ImageView, String> getMap() {

        return this.imageFormula;

    }


    public void addImageAndFormula(ImageView imgView, String formula) {

        this.imageFormula.put(imgView, formula);

    }


    public String getOriginalStringFromImage(ImageView img) {

        if (img == null) {

            return new String();

        }

        return this.imageFormula.get(img);

    }

}

[/code]

[/SPOILER]


[SPOILER="View"]

[code=Java]public class MyEditorView extends VBox {


    private MainPresenter presenter;

    private ImageView selectedImageView;


    public MyEditorView() {

    }


    public void init() {


        MyTextFlow textFlow = new MyTextFlow();

        textFlow.setLineSpacing(10);

        textFlow.setPadding(new Insets(10));


        TextField textField = new TextField();

        Button button = new Button("Send");

        button.setPrefWidth(70);


        getChildren().addAll(textFlow, new HBox(textField, button));

        setVgrow(textFlow, Priority.ALWAYS);


        // Textfield re-sizes according to VBox

        textField.prefWidthProperty().bind(this.widthProperty().subtract(button.prefWidthProperty()));


        // On Enter press

        textField.setOnKeyPressed(e -> {

            if (e.getCode() == KeyCode.ENTER) {

                button.fire();

            }

        });


        button.setOnAction(e -> {

            if (selectedImageView == null) {

                String frml = textField.getText();

                ImageView iv = presenter.createImageViewFromFormula(frml);

                if (iv != null) {

                    textFlow.getChildren().add(iv);

                    selectedImageView = iv;

                } else {

                    textField.setText(textField.getText() + " could not be parsed!");

                }

            } else {

                if (textField.getText().isEmpty()) {

                    presenter.removeFormula(selectedImageView);

                } else {

                    presenter.updateFormulaModel(selectedImageView, textField.getText());

                    ImageView tmpIv = presenter.createImageViewFromFormula(textField.getText());

                    if (tmpIv != null) {

                        Image img = tmpIv.getImage();

                        selectedImageView.setImage(img);

                    } else {

                    }

                }

            }


        });


        String formula = "\\sum_{i=0}^n i^2 = \\frac{(n^2+n)(2n+1)}{6}";


        ImageView iv = presenter.createImageViewFromFormula(formula);

        textFlow.getChildren().add(iv);

        presenter.updateFormulaModel(iv, formula);


        iv.setOnMouseClicked(e -> {

            String frml = presenter.getFormulaFromSelectedImageView(iv);

            if ((frml != null) && !frml.isEmpty()) {

                textField.setText(frml);

                selectedImageView = iv;

            }

        });

    }


    public void setPresenter(MainPresenter present) {

        this.presenter = present;

    }

}[/code]

[/SPOILER]


[SPOILER="TeXUtil"]

[code=Java]import java.awt.image.BufferedImage;


import org.scilab.forge.jlatexmath.TeXConstants;

import org.scilab.forge.jlatexmath.TeXFormula;


import javafx.embed.swing.SwingFXUtils;

import javafx.scene.image.Image;

import javafx.scene.image.ImageView;


public class TeXUtil {


    public static boolean isParsable(String formula) {


        try {

            TeXFormula tex = new TeXFormula(formula);


            java.awt.Image awtImage = tex.createBufferedImage(TeXConstants.STYLE_DISPLAY, 12, java.awt.Color.BLACK,

                    null);

            SwingFXUtils.toFXImage((BufferedImage) awtImage, null);

        } catch (Exception e) {

            System.out.println("Could not create TeXFormula: " + e);

            return false;

        }

        return true;

    }


    public static ImageView parseFormula(String formula) {

        ImageView iv = null;

        try {

            TeXFormula tex = new TeXFormula(formula);


            java.awt.Image awtImage = tex.createBufferedImage(TeXConstants.STYLE_DISPLAY, 12, java.awt.Color.BLACK,

                    null);

            Image fxImage = SwingFXUtils.toFXImage((BufferedImage) awtImage, null);

            iv = new ImageView(fxImage);

            // As we create a new object which doesn't exist before, we need to

            // add

            // it directly to call it afterwards.

        } catch (Exception e) {

            System.out.println("Could not create TeXFormula: " + e);

        }


        return iv;

    }

}[/code]

[/SPOILER]


[SPOILER="ModifiedTextFlow"]

[code=Java]import home.TextForms.util.TeXUtil;

import javafx.scene.text.Text;

import javafx.scene.text.TextFlow;


public class MyTextFlow extends TextFlow {


    public MyTextFlow() {

        super();

    }


    public void setText(String text) {

        String[] split = text.split("\\s+");

        getChildren().clear();

        Text t = new Text();

        StringBuilder sb = new StringBuilder();

        for (String str : split) {

            if (TeXUtil.isParsable(str)) {

                t.setText(sb.toString());

                getChildren().add(t);

                t = new Text();

                // reset StringBuilder

                sb.setLength(0); // set length of buffer to 0

                sb.trimToSize();


            } else {


                sb.append(str);

                sb.append(" ");

            }

        }

    }

}

[/code]

[/SPOILER]


Das Projekt ist ein Maven Projekt und meine POM.XML hat folgende Dependencies für die LaTeX-Lib:

[code]        <!-- https://mvnrepository.com/artifact/org.scilab.forge/jlatexmath -->

        <dependency>

            <groupId>org.scilab.forge</groupId>

            <artifactId>jlatexmath</artifactId>

            <version>1.0.4</version>

        </dependency>[/code]

Genutzt wird Java 8.

Die eigene TextFlow ist unfertig. Hier wollte ich die Idee mit dem "splitten" des Textes realisieren, aber hab nicht viel gemacht, weil mir relativ früh klar wurde, dass mein Vorhaben so nicht funktioniert.

Du kannst dir gerne nehmen was du brauchst.

Falls du alle Klassen importiert und das Programm startest, kannst du mal auf die Gleichung linksklicken, dann erscheint im TextFeld die LaTeX-Formel dafür und kannst etwas damit rumspielen, wird automatisch nach einem Enter-Klick oder Button-Klick aktualisiert.


Hoffe ich hab an alles gedacht :)


Edit: Das Projekt ist mit Absicht nach dem MVP-Prinzip gestaltet, damit ich für die kommende Klausur besser vorbereitet bin (unser Dozent gibt das MVP-Prinzip vor). Normalerweise arbeite ich mit FXML und nach dem MVC-Prinzip. Hoffe dir macht das nichts aus.



Oben