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); } }