package gve.calc.formula;
import awt.*;
import java.awt.*;
import awt.Button;
import java.awt.event.*;
public class OperatorBoolean extends InfixBinaryOp {
private byte kind;
public static final byte AND = 0;
public static final byte XOR = 1;
public static final byte OR = 2;
public static final byte IMPLIES = 3;
public static final byte EQUIV = 4;
private static String [] names = { "&","xor","or","=>","<=>" };
private static int [] pri = { 1200,1100,1000,900,900 };
public OperatorBoolean(String name,Part l,Part r) {
super(l,r);
for (int i = names.length-1; i>=0; i--) {
if (names[i].equals(name)) {
kind = (byte)i;
break;
}
}
}
public OperatorBoolean(byte kind,Part l,Part r) {
super(l,r);
this.kind = kind;
}
public String getName() { return names[kind]; }
public int getPri() { return pri[kind]; }
public int getLeftPri() { return pri[kind] - 10; }
public int getRightPri() { return pri[kind] + 10; }
public byte getKind() { return kind; }
public Part evaluate(Evaluator ev) {
// PENDING: shortcut L->R evaluatie bij sommige operatoren
Object evalL = left.evaluate(ev);
Object evalR = right.evaluate(ev);
if (evalL instanceof Boolean && evalR instanceof Boolean) {
boolean l = ((Boolean)evalL).getBooleanValue();
boolean r = ((Boolean)evalR).getBooleanValue();
switch(kind) {
case AND: return new Boolean(l & r);
case XOR: return new Boolean(l != r);
case OR: return new Boolean(l | r);
case IMPLIES: return new Boolean(!l | r);
case EQUIV: return new Boolean(l == r);
}
}
return new OperatorBoolean(kind,(Part)evalL,(Part)evalR);
}
public boolean same(Object o) {
o = Brackets.unbracket(o);
if (!(o instanceof OperatorBoolean)) return false;
OperatorBoolean b = (OperatorBoolean)o;
return b.left.same(left) && b.right.same(right) && b.kind==kind;
}
public void write(java.io.Writer w) throws java.io.IOException {
super.write(w);
w.write(kind+"\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);
String line = r.readLine();
byte kind = (byte)Integer.parseInt(line);
return new OperatorBoolean(kind,left,right);
}
public Component createView(FormulaView view) {
return new OperatorBooleanView(this,view,new OperatorBooleanSymbolView(kind,getName()));
}
public void saveOperatorLatex(java.io.BufferedWriter w) throws java.io.IOException {
switch (kind) {
case AND: w.write("\\&"); break;
case XOR: w.write("\\oplus"); break;
case OR: w.write("\\vee"); break;
case IMPLIES: w.write("\\Rightarrow"); break;
case EQUIV: w.write("\\Leftrightarrow"); break;
}
}
}
class OperatorBooleanSymbolView extends TextSymbolView {
private byte kind;
public OperatorBooleanSymbolView(byte kind,String str) {
super(str);
this.kind = kind;
}
public Dimension getSymbolSize() {
FontMetrics metrics = getFontMetrics(getFont());
int w = 0;
switch (kind) {
case OperatorBoolean.AND: w = metrics.charWidth('&'); break;
case OperatorBoolean.XOR: w = metrics.charWidth('O'); break;
case OperatorBoolean.OR: w = metrics.charWidth('v'); break;
case OperatorBoolean.IMPLIES:
case OperatorBoolean.EQUIV: w = metrics.stringWidth("=="); break;
}
return new Dimension(w,metrics.getHeight());
}
public void paintSymbol(Graphics g) {
FontMetrics metrics = getFontMetrics(getFont());
int spatwidth = metrics.charWidth(' ');
int ascent = metrics.getAscent();
switch (kind) {
case OperatorBoolean.AND:
g.drawString("&",0,ascent); return;
case OperatorBoolean.XOR:
paintXor(g,0,0,metrics.charWidth('O'),ascent); break;
case OperatorBoolean.OR:
paintOr(g,0,ascent/3,metrics.charWidth('v'),ascent*2/3); break;
case OperatorBoolean.IMPLIES:
paintImplies(g,1,0,metrics.stringWidth("==")-2,ascent); break;
case OperatorBoolean.EQUIV:
paintEquiv(g,1,0,metrics.stringWidth("==")-2,ascent); break;
}
}
private void paintXor(Graphics g,int x,int y,int w,int h) {
g.drawOval(x,y,w,h);
w--; h--;
g.drawLine(x+w/2,y,x+w/2,y+h);
g.drawLine(x,y+h/2,x+w,y+h/2);
}
private void paintOr(Graphics g,int x,int y,int w,int h) {
w--; h--;
g.drawLine(x,y,x+w/2,y+h);
g.drawLine(x+w/2,y+h,x+w,y);
}
private void paintImplies(Graphics g,int x,int y,int w,int h) {
w--; h--;
// right arrow
g.drawLine(x+w*3/4,y,x+w,y+h/2);
g.drawLine(x+w,y+h/2,x+w*3/4,y+h);
// two horizontal lines
g.drawLine(x,y+(h+2)/4,x+w*7/8,y+(h+2)/4);
g.drawLine(x,y+h*3/4,x+w*7/8,y+h*3/4);
}
private void paintEquiv(Graphics g,int x,int y,int w,int h) {
w--; h--;
// right arrow
g.drawLine(x+w*3/4,y,x+w,y+h/2);
g.drawLine(x+w,y+h/2,x+w*3/4,y+h);
// two horizontal lines
g.drawLine(x+w/8,y+(h+2)/4,x+w*7/8,y+(h+2)/4);
g.drawLine(x+w/8,y+h*3/4,x+w*7/8,y+h*3/4);
// left arrow
g.drawLine(x+w/4,y,x,y+h/2);
g.drawLine(x,y+h/2,x+w/4,y+h);
}
}