/* * This file is part of LaTeXDraw. * Copyright (c) 2005-2017 Arnaud BLOUIN * LaTeXDraw is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later version. * LaTeXDraw is distributed without any warranty; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ package net.sf.latexdraw.instruments; import com.google.inject.Inject; import java.net.URL; import java.util.Optional; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.fxml.Initializable; import javafx.scene.input.KeyCode; import net.sf.latexdraw.actions.shape.AddShape; import net.sf.latexdraw.actions.shape.ModifyShapeProperty; import net.sf.latexdraw.actions.shape.ShapeProperties; import net.sf.latexdraw.models.ShapeFactory; import net.sf.latexdraw.models.interfaces.shape.IPlot; import net.sf.latexdraw.models.interfaces.shape.IPoint; import net.sf.latexdraw.models.interfaces.shape.IShape; import net.sf.latexdraw.models.interfaces.shape.IText; import net.sf.latexdraw.parsers.ps.PSFunctionParser; import net.sf.latexdraw.ui.TextAreaAutoSize; import org.malai.action.Action; import org.malai.javafx.action.ActivateInactivateInstruments; import org.malai.javafx.binding.JfXWidgetBinding; import org.malai.javafx.interaction.library.KeyTyped; /** * An instrument for adding and modifying texts of the drawing. * @author Arnaud Blouin */ public class TextSetter extends CanvasInstrument implements Initializable { /** The text field. */ private final TextAreaAutoSize textField; /** * The position where texts are added. It may not corresponds with the location * of the text field since the text field position is absolute (does not consider the zoom level). */ private IPoint position; /** The text to modify throw this instrument. If it is not set, a new text will be created. */ private IText text; private IPlot plot; /** The pencil used to create shapes. */ @Inject private Pencil pencil; @Inject private ShapeTextCustomiser custom; @Inject private ShapePlotCustomiser plotCustom; /** * Creates the instrument. */ TextSetter() { super(); textField = new TextAreaAutoSize(); } @Override public void onActionDone(final Action action) { super.onActionDone(action); custom.update(); Platform.runLater(() -> canvas.requestFocus()); } /** * Sets the text to modify throw this instrument. * @param sh The plot to modify. * @since 3.1 */ public void setPlot(final IPlot sh) { plot = sh; if(sh != null) { textField.setText(sh.getPlotEquation()); setPlotMessage(); } } /** * Sets the text to modify throw this instrument. * @param sh The text to modify. * @since 3.0 */ public void setText(final IText sh) { text = sh; if(sh != null) { textField.setText(sh.getText()); setTextMessage(); } } /** * @param pen The pen to set to the text setter. */ public void setPencil(final Pencil pen) { pencil = pen; } @Override protected void configureBindings() throws IllegalAccessException, InstantiationException { addBinding(new Enter2SetText(this)); addBinding(new Enter2SetEquation(this)); addBinding(new Enter2AddText(this)); addBinding(new Enter2CheckPlot(this)); addBinding(new KeyPress2Desactivate(this)); } private void setTextMessage() { textField.getMessageField().setText("Write LaTeX text."); } private void setPlotMessage() { final String eqEx = " 2 x add sin"; //$NON-NLS-1$ textField.getMessageField().setText("Write the equation, e.g.: " + eqEx); } @Override public void setActivated(final boolean act) { super.setActivated(act); if(act && pencil.isActivated()) { switch(pencil.getCurrentChoice()) { case TEXT: setTextMessage(); break; case PLOT: setPlotMessage(); break; } } textField.setValid(true); textField.setVisible(act); if(act) { Platform.runLater(() -> { textField.setLayoutX(position.getX()); textField.setLayoutY(position.getY() - textField.getPrefHeight()); textField.requestFocus(); }); } } /** * @return The text field used to set texts. * @since 3.0 */ public TextAreaAutoSize getTextField() { return textField; } /** * @param rel The point where texts are added. */ public void setPosition(final IPoint rel) { position = rel; } public IPoint getPosition() { return position; } @Override public void initialize(final URL location, final ResourceBundle resources) { setActivated(false); canvas.addToWidgetLayer(textField); canvas.addToWidgetLayer(textField.getMessageField()); } private static class KeyPress2Desactivate extends JfXWidgetBinding<ActivateInactivateInstruments, KeyTyped, TextSetter> { KeyPress2Desactivate(TextSetter setter) throws InstantiationException, IllegalAccessException { super(setter, false, ActivateInactivateInstruments.class, KeyTyped.class, setter.textField); } @Override public void initAction() { action.addInstrumentToInactivate(instrument); } @Override public boolean isConditionRespected() { final Optional<KeyCode> key = interaction.getKeyCode(); return key.isPresent() && (key.get() == KeyCode.ENTER && instrument.textField.isValidText() && !instrument.textField.getText().isEmpty() || key.get() == KeyCode.ESCAPE); } } private static class Enter2SetText extends JfXWidgetBinding<ModifyShapeProperty, KeyTyped, TextSetter> { Enter2SetText(final TextSetter ins) throws InstantiationException, IllegalAccessException { super(ins, false, ModifyShapeProperty.class, KeyTyped.class, ins.textField); } @Override public void initAction() { action.setGroup(ShapeFactory.INST.createGroup(instrument.text)); action.setProperty(ShapeProperties.TEXT); action.setValue(instrument.textField.getText()); } @Override public boolean isConditionRespected() { return instrument.text != null && !instrument.textField.getText().isEmpty() && interaction.getKeyCode().orElse(null) == KeyCode.ENTER; } } private static class Enter2SetEquation extends JfXWidgetBinding<ModifyShapeProperty, KeyTyped, TextSetter> { Enter2SetEquation(final TextSetter ins) throws InstantiationException, IllegalAccessException { super(ins, false, ModifyShapeProperty.class, KeyTyped.class, ins.textField); } @Override public void initAction() { action.setGroup(ShapeFactory.INST.createGroup(instrument.plot)); action.setProperty(ShapeProperties.PLOT_EQ); action.setValue(instrument.textField.getText()); } @Override public boolean isConditionRespected() { return instrument.plot != null && !instrument.textField.getText().isEmpty() && interaction.getKeyCode().orElse(null) == KeyCode.ENTER; } } private static class Enter2AddText extends JfXWidgetBinding<AddShape, KeyTyped, TextSetter> { Enter2AddText(final TextSetter ins) throws InstantiationException, IllegalAccessException { super(ins, false, AddShape.class, KeyTyped.class, ins.textField); } @Override public void initAction() { final IPoint textPosition = ShapeFactory.INST.createPoint(instrument.position.getX(), instrument.position.getY()); final IShape sh = instrument.pencil == null ? null : instrument.pencil.createShapeInstance(); if(sh instanceof IText) { final IText text = (IText) sh; text.setPosition(textPosition.getX(), textPosition.getY()); text.setText(instrument.textField.getText()); action.setShape(text); action.setDrawing(instrument.pencil.canvas.getDrawing()); } } @Override public boolean isConditionRespected() { return instrument.pencil.getCurrentChoice() == EditionChoice.TEXT && instrument.text == null && !instrument.textField.getText().isEmpty() && interaction.getKeyCode().orElse(null) == KeyCode.ENTER; } } private static class Enter2CheckPlot extends JfXWidgetBinding<AddShape, KeyTyped, TextSetter> { Enter2CheckPlot(final TextSetter ins) throws InstantiationException, IllegalAccessException { super(ins, false, AddShape.class, KeyTyped.class, ins.textField); } @Override public void initAction() { instrument.textField.setValid(true); final IPoint textPosition = ShapeFactory.INST.createPoint(instrument.position.getX(), instrument.position.getY() + instrument.textField.getHeight()); final IShape sh = instrument.pencil == null ? null : instrument.pencil.createShapeInstance(); if(sh instanceof IPlot) { final IPlot plot = (IPlot) sh; plot.setPosition(textPosition.getX(), textPosition.getY()); plot.setPlotEquation(instrument.textField.getText()); action.setShape(plot); action.setDrawing(instrument.pencil.canvas.getDrawing()); } } @Override public boolean isConditionRespected() { boolean ok = instrument.pencil.getCurrentChoice() == EditionChoice.PLOT && instrument.plot == null && ! instrument.textField.getText().isEmpty() && interaction.getKeyCode().orElse(null) == KeyCode.ENTER; if(ok) if(!PSFunctionParser.isValidPostFixEquation(instrument.textField.getText(), Double.valueOf(instrument.plotCustom.minXSpinner.getValue().toString()), Double.valueOf(instrument.plotCustom.maxXSpinner.getValue().toString()), Double.valueOf(instrument.plotCustom.nbPtsSpinner.getValue().toString()))) { instrument.textField.setValid(false); ok = false; } return ok; } } }