package gve.calc.formula;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

@author Geert Vernaeve Part is the superclass for all formula components. Part objects don't exist; formulas are built up out of objects that are subclass of Part, such as Fraction, Root, ...
abstract public class Part { Part parent; // null for top part
Set to 0 for production release, 100 for full debug
public static final int debuglevel = 0; public static final int Mouse_RIGHT = 1; // Popup button public abstract Object clone(); public abstract Part evaluate(Evaluator ev); public Part getParent() { return parent; }
NOTE: rather dangerous to make this public ... better solutions???
public void setParent(Part newparent) { parent = newparent; }
Replace a child by another. If this Part has no childs (e.g. Real, Empty), throw an error.
public void replaceChild(Part child,Part byThat) { throw new Error("replace() error"); }
Is ch a child of (a child of (...)) par?
static public boolean isDescendantOf(Part ch,Part par) { while (ch.parent != null) { ch = ch.parent; if (ch == par) return true; } return false; }
Is ch == par or a descendant of par?
static public boolean isDescendantOr(Part ch,Part par) { while (ch != null) { if (ch == par) return true; ch = ch.parent; } return false; }
PENDING: Make this method abstract
public void write(java.io.Writer w) throws java.io.IOException { w.write(getClass().getName()); w.write('\n'); } // Note: every subclass *MUST* have its own read() method, otherwise // the thing recurses horribly. public static Part read(BufferedReader r) throws IOException, ClassNotFoundException,NoSuchMethodException, java.lang.reflect.InvocationTargetException,IllegalAccessException { String line = r.readLine(); // class if (line == null) return new Identifier("ReadError"); if (line.startsWith("formula.")) { // Backwards compatibility stuff if (line.equals("formula.Proof")) line = "gve.calc.logic.Proof"; else if (line.equals("formula.ProofRule")) line = "gve.calc.logic.ProofRule"; else if (line.equals("formula.OperatorModel")) line = "gve.calc.logic.OperatorModel"; else line = "gve.calc." + line; } // Call the read() method of the class Class [] argtypes = { Class.forName("java.io.BufferedReader") }; Object [] args = { r }; if (debuglevel >= 30) System.out.println("Invocating "+line); // try { return (Part)Class.forName(line).getMethod("read",argtypes).invoke(null,args); // } catch (java.lang.reflect.InvocationTargetException targetexc) { // throw new java.lang.reflect.InvocationTargetException(targetexc, // "Error invocating "+line+".read()\n"+targetexc.getMessage()); // } }
Compares two parts to each other. This method should return true if both parts and subtrees match. Brackets of kind BRACKET should not be taken into account; i.e. (a) "is the same" as a. Use the utility method Brackets.unbracket() if necessary. PENDING: should an object with children first call evaluate() on them? PENDING: make abstract
public boolean same(Object o) { System.out.println("***WARNING***No definition for same() in "+this+", returning false"); try { throw new Exception("heh"); } catch (Exception exc) { exc.printStackTrace(); } return false; }
Return children, starting from count=0. If there's no child with that number, return null.
public Part getChild(int count) { return null; } public static Part[] getChildren(Part p) { Part [] result = new Part[10]; int count = 0; while (true) { Part child = p.getChild(count); if (child == null) break; if (count >= result.length) { // grow buffer Part [] newbuff = new Part[result.length * 2]; System.arraycopy(result,0,newbuff,0,count); result = newbuff; } result[count++] = child; } Part [] children = new Part[count]; System.arraycopy(result,0,children,0,count); return children; } public void dump(int indent) { String ind = ""; for (int i = 0; i < indent; i++) ind+=" "; System.out.println(ind + toString()); for (int i = 0; ; i++) { Part ch = getChild(i); if (ch == null) break; if (ch.parent != this) System.out.println("[Warning: next Child's Parent is bad]"); ch.dump(indent+1); } } public void dump() { dump(0); } public static boolean isEmpty(Part p) { if (p instanceof Identifier) { Identifier ident = (Identifier)p; return ident.isEmpty(); } return false; } public static boolean isEmpty(Object obj) { if (obj instanceof Part) return isEmpty((Part)obj); return false; }
Called whenever one of the children of this part has been modified The argument is the (sub,subsub,...)child that has been modified.
public void modified(Part p) {}
PENDING: make this abstract.
public Component createView(FormulaView f) { return new awt.Label("<no view>"); }
PENDING: make this abstract Note that this is not the nicest method to implement save formats, since every Part subclass has to contain save routines for each supported format ...
public void saveLatex(BufferedWriter w) throws IOException { } }