/**
* This program (working title: MAS Prover) is an automated tableaux prover
* for epistemic logic (S5n).
* Copyright (C) 2007 Elske van der Vaart and Gert van Valkenhoef
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
* 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package nl.rug.ai.mas.oops.render;
import nl.rug.ai.mas.oops.formula.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collection;
import java.text.AttributedString;
import java.awt.Font;
import java.awt.font.TextAttribute;
/**
* Visit a Formula in order to generate an AttributedString from it.
* @see java.text.AttributedString
*/
public class FormulaAttrString implements FormulaVisitor {
protected Stack<List<AttrChar>> d_stack;
private Font d_normal;
private Font d_subscript;
/**
* Constructor.
* @param font The font this formula should be rendered in.
*/
public FormulaAttrString(Font font) {
d_stack = new Stack<List<AttrChar>>();
d_normal = font;
HashMap<TextAttribute, Object> atmap =
new HashMap<TextAttribute, Object>();
atmap.put(TextAttribute.SUPERSCRIPT,
TextAttribute.SUPERSCRIPT_SUB);
d_subscript = font.deriveFont(atmap);
}
/**
* Generate an AttributedString from the top of the stack.
*/
public AttributedString getAttributedString() {
List<AttrChar> l = d_stack.pop();
// construct string, find subscript ranges
List<Range> subList = new ArrayList<Range>();
int i = 0;
String str = new String();
boolean sub = false;
int start = 0;
for (AttrChar ac : l) {
str += String.valueOf(ac.getCharacter());
if (ac.getSubscript()) {
if (!sub) {
start = i;
}
} else {
if (sub) {
subList.add(new Range(start, i));
}
}
sub = ac.getSubscript();
++i;
}
AttributedString atstr = new AttributedString(str);
atstr.addAttribute(TextAttribute.FONT, d_normal);
for (Range r : subList) {
atstr.addAttribute(TextAttribute.FONT, d_subscript,
r.getBegin(), r.getEnd());
}
return atstr;
}
public void visitBiImplication(BiImplication f) {
visitBinary(Constants.BIIM);
}
public void visitConjunction(Conjunction f) {
visitBinary(Constants.CONJ);
}
public void visitDisjunction(Disjunction f) {
visitBinary(Constants.DISJ);
}
public void visitImplication(Implication f) {
visitBinary(Constants.IMPL);
}
public void visitMultiBox(MultiBox f) {
visitMulti(Constants.SQUARE, f.getAgent());
}
public void visitMultiDiamond(MultiDiamond f) {
visitMulti(Constants.LOZENGE, f.getAgent());
}
public void visitNegation(Negation f) {
visitUnary(Constants.NEG);
}
public void visitProposition(Proposition f) {
visitString(f.toString());
}
public void visitUniBox(UniBox f) {
visitUnary(Constants.SQUARE);
}
public void visitUniDiamond(UniDiamond f) {
visitUnary(Constants.LOZENGE);
}
public void visitFormulaReference(FormulaReference f) {
visitString(f.toString());
}
private void visitBinary(char op) {
List<AttrChar> right = d_stack.pop();
List<AttrChar> left = d_stack.pop();
left.add(0, new AttrChar('('));
left.add(new AttrChar(op));
left.addAll(right);
left.add(new AttrChar(')'));
d_stack.push(left);
}
private void visitUnary(Collection<AttrChar> op) {
List<AttrChar> right = d_stack.pop();
right.addAll(0, op);
d_stack.push(right);
}
private void visitUnary(char op) {
List<AttrChar> l = new ArrayList<AttrChar>();
l.add(new AttrChar(op));
visitUnary(l);
}
private void visitMulti(char op, Agent a) {
List<AttrChar> l = new ArrayList<AttrChar>();
l.add(new AttrChar(op));
l.addAll(codeAgent(a));
visitUnary(l);
}
protected void visitString(String str) {
visitString(str, false);
}
protected void visitString(String str, boolean sub) {
d_stack.push(codeString(str, sub));
}
protected List<AttrChar> codeString(String str, boolean sub) {
List<AttrChar> l = new ArrayList<AttrChar>();
for (char c : str.toCharArray()) {
l.add(new AttrChar(c, sub));
}
return l;
}
protected List<AttrChar> codeAgent(Agent a) {
List<AttrChar> l = new ArrayList<AttrChar>();
if (a instanceof NullAgent) {
l.add(new AttrChar(Constants.EMPTY, true));
} else {
l = codeString(a.toString(), true);
}
return l;
}
/**
* Represents a char and the relevant attributes it should receive.
*/
protected class AttrChar {
private char d_c;
private boolean d_sub;
public AttrChar(char c) {
this(c, false);
}
public AttrChar(char c, boolean sub) {
d_c = c;
d_sub = sub;
}
public char getCharacter() {
return d_c;
}
public boolean getSubscript() {
return d_sub;
}
}
/**
* Represent a range [begin, end]
*/
private class Range {
private int d_begin;
private int d_end;
public Range(int begin, int end) {
d_begin = begin;
d_end = end;
}
public int getBegin() {
return d_begin;
}
public int getEnd() {
return d_end;
}
}
}