package gve.calc.formula;
import java.awt.*;
public class OperatorSet extends InfixBinaryOp {
private byte kind;
public static final byte IN = 0;
public static final byte SUBSETEQ = 1;
// Many more to come ...
public String getName() {
switch (kind) {
case IN: return "in";
case SUBSETEQ: return "subseteq";
default: return null;
}
}
public int getPri() { return 1400; }
public OperatorSet(String name,Part l,Part r) {
super(l,r);
switch(name.charAt(0)) {
case 'i': kind = IN; break;
case 's': kind = SUBSETEQ; break;
default: throw new Error("Bad set operator name "+name);
}
}
public OperatorSet(byte kind,Part l,Part r) {
super(l,r);
this.kind = kind;
}
public byte getKind() { return kind; }
public void write(java.io.Writer w) throws java.io.IOException {
super.write(w);
w.write(""+(int)kind);
w.write('\n');
}
public static Part read(java.io.BufferedReader r) throws java.io.IOException,
ClassNotFoundException,NoSuchMethodException,
java.lang.reflect.InvocationTargetException,IllegalAccessException {
Part left = Part.read(r);
Part right = Part.read(r);
int kind = Integer.parseInt(r.readLine());
return new OperatorSet((byte)kind,left,right);
}
public static boolean in(Part p,Part list) {
CommaEnumerator enum = new CommaEnumerator(list);
while (enum.hasMoreElements()) {
if (p.same(enum.nextPart())) return true;
}
return false;
}
public static boolean subseteq(Part small,Part big) {
CommaEnumerator enum = new CommaEnumerator(small);
while (enum.hasMoreElements()) {
if (!in(enum.nextPart(),big)) return false;
}
return true;
}
public Part evaluate(Evaluator ev) {
Part l = left.evaluate(ev), r = right.evaluate(ev);
switch (kind) {
case IN:
if (r instanceof Brackets) {
Brackets set = (Brackets)r;
if (set.getKind() != Brackets.CURLY)
return new Boolean(false);
// Now we know that 'set' is of the form { ... }
return new Boolean(in(l,set.child));
} else return new Boolean(false);
case SUBSETEQ:
if (r instanceof Brackets && l instanceof Brackets) {
Brackets rset = (Brackets)r;
if (rset.getKind() != Brackets.CURLY)
return new Boolean(false);
Brackets lset = (Brackets)l;
if (lset.getKind() != Brackets.CURLY)
return new Boolean(false);
return new Boolean(subseteq(lset.child,rset.child));
} else return new Boolean(false);
default:
return null;
}
}
public boolean same(Object o) {
o = Brackets.unbracket(o);
if (!(o instanceof OperatorSet)) return false;
OperatorSet obj = (OperatorSet)o;
return kind==obj.kind && left.same(obj.left) && right.same(obj.right);
}
public Component createView(FormulaView view) {
return new InfixBinaryOpView(this,view,new OperatorSetSymbolView(kind,getName()));
}
public void saveOperatorLatex(java.io.BufferedWriter w) throws java.io.IOException {
switch (kind) {
case IN: w.write("\\in"); break;
case SUBSETEQ: w.write("\\subseteq"); break;
}
}
}
class OperatorSetSymbolView extends TextSymbolView {
private byte kind;
public OperatorSetSymbolView(byte kind,String str) {
super(str);
this.kind = kind;
}
public Dimension getSymbolSize() {
FontMetrics metrics = getFontMetrics(getFont());
return new Dimension(metrics.charWidth(' ')*2,metrics.getHeight());
}
public void paintSymbol(Graphics g) {
int spatWidth = g.getFontMetrics().charWidth(' ');
int mBase = g.getFontMetrics().getAscent();
int opWidth = spatWidth*2;
switch (kind) {
case OperatorSet.IN: paintIn(g,0,mBase/3,opWidth,(mBase*2+2)/3); break;
case OperatorSet.SUBSETEQ: paintSubseteq(g,0,mBase/3,opWidth,(mBase*2+2)/3); break;
}
}
private void paintIn(Graphics g,int x,int y,int w,int h) {
g.drawArc(x,y,w+1,h,90,180);
g.drawLine(x+w/2,y,x+w-1,y);
g.drawLine(x+w/2,y+h,x+w-1,y+h);
// middelste lijntje
g.drawLine(x,y+h/2,x+w-1,y+h/2);
}
private void paintSubseteq(Graphics g,int x,int y,int w,int h) {
g.drawArc(x,y,w,h-2,90,181);
g.drawLine(x+w/2,y,x+w-1,y);
g.drawLine(x+w/2,y+h-2,x+w-1,y+h-2);
// onderste lijntje
g.drawLine(x,y+h,x+w-1,y+h);
}
}