/*
* Copyright (C) 2011 Alasdair C. Hamilton
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package ket.math;
import java.awt.*;
import java.util.*;
import ket.display.*;
import ket.display.box.Box;
import ket.display.box.BoxTools;
import ket.display.box.BoxWord;
import ket.math.Argument;
import ket.math.Symbol;
import ket.math.purpose.SymbolicState;
/**
* Coordinate the conversion of a symbolic function into latex, html or box.
*/
public class SymbolicFunctionForm implements Form {
SymbolicFunction f;
public SymbolicFunctionForm() { //?
this.f = null;
}
public int getArgUpperLimit() { // <--- use individual symbolic function property.
return f!=null ? f.getArgUpperLimit() : -1; // <--- why is a null test needed here but not for getInfix(), toBox() etc?
}
public int getArgLowerLimit(int actualNumberOfArguments) { // <--- use individual symbolic function property.
return f!=null ? f.getArgLowerLimit(actualNumberOfArguments) : 0;
}
public SymbolicFunctionForm(SymbolicFunction f) {
this.f = f;
}
public void setFunction(SymbolicFunction f) {
this.f = f;
}
// helper methods
protected SymbolicState getPrefix() {
return f.getPrefix();
}
protected SymbolicState getInfix() {
return f.getInfix();
}
protected SymbolicState getPostfix() {
return f.getPostfix();
}
protected boolean isPrefix() {
return f.isPrefix();
}
protected boolean isInfix() {
return f.isInfix();
}
protected boolean isPostfix() {
return f.isPostfix();
}
protected boolean isPrefixOnly() {
return f.isPrefixOnly();
}
protected boolean isInfixOnly() {
return f.isInfixOnly();
}
protected boolean isPostfixOnly() {
return f.isPostfixOnly();
}
@Override
public String toString(Vector<Argument> args) {
boolean addBrackets = isPrefixOnly() && f.displayBrackets();
String text = "";
if (isPrefix()) {
text += getPrefix() + " ";
}
if (addBrackets) {
text += " ( ";
}
switch ( args.size() ) {
case 0:
if (isInfixOnly()) {
text += getInfix();
}
break;
case 1:
String prefixString = isInfixOnly() ? getInfix().toString() : "";
text += prefixString + " " + args.firstElement();
break;
default:
String infixString = isInfix() ? getInfix().toString() : ",";
for (int i=0; i<args.size()-1; i++) {
text += args.get(i) + " " + infixString + " ";
}
text += args.lastElement();
break;
}
if (isPostfix()) {
text += " " + getPostfix();
}
if (addBrackets) {
text += " ) ";
}
return TextTools.removeWhitespace(text);
}
@Override
public String toLatex(Vector<Argument> args) {
if (isPrefixOnly() && f.displayBrackets()) {
String latexArgs = getPrefix().toLatex() + " \\! \\left(";
switch (args.size()) {
case 0:
// Do nothing.
break;
case 1:
latexArgs += " " + args.firstElement().toLatex();
break;
default:
for (int i=0; i<args.size()-1; i++) {
latexArgs += args.get(i).toLatex() + ", ";
}
latexArgs += args.lastElement().toLatex();
}
latexArgs += "\\right)";
return latexArgs;
} else {
String latexArgs = "";
if (isPrefix()) {
latexArgs += getPrefix().toLatex() + " ";
}
switch (args.size()) {
case 0:
if (isInfixOnly()) {
latexArgs += getInfix().toLatex();
}
break;
case 1:
String prefixLatex = isInfixOnly() ? getInfix().toLatex() : "";
latexArgs += prefixLatex + " " + args.lastElement().toLatex();
break;
default:
String infixLatex = isInfix() ? getInfix().toLatex() : ",";
for (int i=0; i<args.size()-1; i++) {
latexArgs += args.get(i).toLatex() + " " + infixLatex + " ";
}
latexArgs += args.lastElement().toLatex();
}
if (isPostfix()) {
latexArgs += " " + getPostfix().toLatex();
}
return latexArgs;
}
}
@Override
public String toHTML(Vector<Argument> args) {
if (isPrefixOnly() && f.displayBrackets()) {
String htmlArgs = getPrefix().toHTML() + "(";
switch (args.size()) {
case 0:
// Do nothing.
break;
case 1:
htmlArgs += " " + args.firstElement().toHTML();
break;
default:
for (int i=0; i<args.size()-1; i++) {
htmlArgs += args.get(i).toHTML() + ", ";
}
htmlArgs += args.lastElement().toHTML();
}
htmlArgs += ")";
return htmlArgs;
} else {
String html = "";
if (isPrefix()) {
// TODO: Include brackets.
html += getPrefix().toHTML() + " ";
}
switch ( args.size() ) {
case 0:
if (isInfixOnly()) {
html += getInfix().toHTML();
}
break;
case 1:
String prefixHTML = isInfixOnly() ? getInfix().toHTML() : "";
html += prefixHTML + " " + args.firstElement().toHTML();
break;
default:
String infixString = isInfix() ? getInfix().toHTML() : ",";
for (int i=0; i<args.size()-1; i++) {
html += args.get(i).toHTML() + " " + infixString + " ";
}
html += args.lastElement().toHTML();
}
if (isPostfix()) {
html += " " + getPostfix().toHTML();
}
// TODO: Is this required, and should a equivalent be added?
return TextTools.removeWhitespace(html);
}
}
@Override
public Box toBox(Argument argument, long settings, ColourScheme colourScheme, Vector<Argument> args) { // Extend FunctionForm and avoid duplicating this method.
Vector<Box> boxArgs = BoxTools.padArgs(args, f.getArgLowerLimit(args.size()), colourScheme);
return this.toBox(argument, boxArgs, settings, colourScheme);
}
@Override
public Box toBox(Argument argument, Vector<Box> boxArgs, long settings, ColourScheme colourScheme) {
if (isPrefixOnly() && f.displayBrackets()) {
// Generalization of a simple function, e.g. \alpha:(x,y).
Box boxText = getPrefix().toBox(argument,
Box.PLAIN_FONT|Box.RIGHT_ALIGN|Box.Y_CENTRE_ALIGN,
colourScheme);
Box commaArgs = BoxTools.commaList(argument, boxArgs, settings, colourScheme);
Box brackets = BoxTools.roundBrackets(argument, commaArgs, settings, colourScheme);
brackets.setArgument(argument);
brackets.setProperty(Box.VERTICAL_STRETCH);
boxText.setArgument(argument);
brackets.setArgument(argument);
return BoxTools.centredHorizontalBoxList(argument, settings, boxText, brackets);
} else {
Vector<Box> boxes = new Vector<Box>();
if (isPrefix()) {
Box pre = getPrefix().toBox(argument, Box.PLAIN_FONT, colourScheme);
//- pre.setArgument(argument);
boxes.add(pre);
}
switch ( boxArgs.size() ) {
case 0:
// Infix-only operators act like prefix operators for single arguments.
if (isInfixOnly()) {
Box inf = getInfix().toBox(argument, Box.PLAIN_FONT, colourScheme);
//- inf.setArgument(argument);
boxes.add(inf);
}
break;
case 1:
if (isInfixOnly()) {
Box inf = getInfix().toBox(argument, Box.PLAIN_FONT, colourScheme);
//- inf.setArgument(argument);
boxes.add(inf);
}
boxes.add(boxArgs.lastElement());
break;
default:
SymbolicState infixSymbol = isInfix() ? getInfix() : Symbol.COMMA;
for (int i=0; i<boxArgs.size()-1; i++) {
boxes.add(boxArgs.get(i));
Box inf = infixSymbol.toBox(argument, Box.PLAIN_FONT, colourScheme);
//- inf.setArgument(argument);
boxes.add(inf);
}
boxes.add(boxArgs.lastElement());
}
if (isPostfix()) {
Box post = getPostfix().toBox(argument, Box.PLAIN_FONT, colourScheme);
//- post.setArgument(argument);
boxes.add(post);
}
return BoxTools.centredHorizontalBoxList(argument, settings, boxes);
}
}
}