/*
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
C.a.R. 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, see .
*/
package rene.zirkel.macro;
/**
* This is an ObjectConstructor, which can run a macro.
*/
// with addons by Dibs for 3D
import eric.JSelectPopup;
import eric.GUI.palette.PaletteManager;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.ConstructionException;
import rene.zirkel.construction.DepList;
import rene.zirkel.construction.Selector;
import rene.zirkel.constructors.ObjectConstructor;
import rene.zirkel.objects.AngleObject;
import rene.zirkel.objects.AreaObject;
import rene.zirkel.objects.CircleObject;
import rene.zirkel.objects.ConstructionObject;
import rene.zirkel.objects.ExpressionObject;
import rene.zirkel.objects.FixedAngleObject;
import rene.zirkel.objects.FixedCircleObject;
import rene.zirkel.objects.FunctionObject;
import rene.zirkel.objects.JLocusTrackObject;
import rene.zirkel.objects.LineObject;
import rene.zirkel.objects.PointObject;
import rene.zirkel.objects.PointonObject;
import rene.zirkel.objects.PrimitiveCircleObject;
import rene.zirkel.objects.PrimitiveLineObject;
import rene.zirkel.objects.QuadricObject;
import rene.zirkel.objects.RayObject;
import rene.zirkel.objects.SegmentObject;
import rene.zirkel.objects.TextObject;
import rene.zirkel.objects.TwoPointLineObject;
import rene.zirkel.objects.UserFunctionObject;
import rene.zirkel.objects.VectorObject;
public class MacroRunner extends ObjectConstructor implements Selector {
String S[];
int Param;
Macro M;
ArrayList OCs=new ArrayList();
ArrayList PROMPTs=new ArrayList();
ZirkelCanvas ZC;
ConstructionObject Params[]; // array of parameters.
boolean NewPoint[]; // are the parameters new points?
boolean Fixed[];
double LastX=0, LastY=0;
boolean ShiftDown=false;
static ConstructionObject previewPoint=null;
static boolean keepLine=true;
static boolean keepCircle=true;
/**
* Must be called, when this constructor is started.
*
* @param m
* The macro to be run
*/
public void setMacro(final Macro m, final ZirkelCanvas zc) {
S=m.getPrompts();
Param=0;
M=m;
Params=new ConstructionObject[S.length];
Fixed=new boolean[S.length];
NewPoint=new boolean[S.length];
for (int i=0; i=S.length) {
doMacro(zc);
reset(zc);
} else {
getFixed(zc);
}
}
}
@Override
public boolean isAdmissible(final ZirkelCanvas zc,
final ConstructionObject o) {
final ConstructionObject p[]=M.getParams();
if (p[Param] instanceof PointObject) {
return (o instanceof PointObject);
} else if (p[Param] instanceof FixedAngleObject) {
return (o instanceof FixedAngleObject);
} else if (p[Param] instanceof RayObject) {
return (o instanceof RayObject);
} else if (p[Param] instanceof TwoPointLineObject) {
return (o instanceof TwoPointLineObject);
} else if (p[Param] instanceof SegmentObject) {
return (p[Param] instanceof SegmentObject);
} else if (p[Param] instanceof PrimitiveLineObject) {
return (o instanceof PrimitiveLineObject);
} else if (p[Param] instanceof PrimitiveCircleObject) {
return (o instanceof PrimitiveCircleObject);
} else if (p[Param] instanceof FunctionObject) {
return (o instanceof FunctionObject);
} else if (p[Param] instanceof UserFunctionObject) {
return (o instanceof UserFunctionObject);
} else if (p[Param] instanceof AngleObject) {
return (o instanceof AngleObject);
} else if (p[Param] instanceof QuadricObject) {
return (o instanceof QuadricObject);
} else if (p[Param] instanceof ExpressionObject) {
return (o instanceof ExpressionObject||o instanceof AngleObject
||o instanceof FixedAngleObject||o instanceof AreaObject);
} else if (p[Param] instanceof AreaObject) {
return (o instanceof AreaObject);
} else {
return false;
}
}
private void checkIfKeepLine(final ZirkelCanvas zc) {
final Construction c=zc.getConstruction();
PointObject P1org=new PointObject(c, -3, 4);
PointObject P2org=new PointObject(c, -1, 1);
PointObject P3org=new PointObject(c, 1, -2);
P1org.setSuperHidden(true);
P2org.setSuperHidden(true);
P3org.setSuperHidden(true);
Params[Params.length-1]=P1org;
c.add(P1org);
runMacroPreview(zc, false);
final PointObject p1=(PointObject) previewPoint;
Params[Params.length-1]=P2org;
c.add(P2org);
runMacroPreview(zc, false);
final PointObject p2=(PointObject) previewPoint;
Params[Params.length-1]=P3org;
c.add(P3org);
runMacroPreview(zc, false);
final PointObject p3=(PointObject) previewPoint;
final double x1=p2.getX()-p1.getX();
final double y1=p2.getY()-p1.getY();
final double x2=p3.getX()-p1.getX();
final double y2=p3.getY()-p1.getY();
keepLine=(Math.abs(x1*y2-x2*y1)<1e-11);
}
private void checkIfKeepCircle(final ZirkelCanvas zc) {
final Construction c=zc.getConstruction();
PointObject P0org=new PointObject(c, 1, 1);
PointObject P1org=new PointObject(c, 2, -1);
PointObject P2org=new PointObject(c, 3, 2);
PointObject P3org=new PointObject(c, 0, 3);
PointObject P4org=new PointObject(c, -1, 2);
P0org.setSuperHidden(true);
P1org.setSuperHidden(true);
P2org.setSuperHidden(true);
P3org.setSuperHidden(true);
P4org.setSuperHidden(true);
Params[Params.length-1]=P0org;
c.add(P0org);
runMacroPreview(zc, false);
final PointObject p0=(PointObject) previewPoint;
Params[Params.length-1]=P1org;
c.add(P1org);
runMacroPreview(zc, false);
final PointObject p1=(PointObject) previewPoint;
Params[Params.length-1]=P2org;
c.add(P2org);
runMacroPreview(zc, false);
final PointObject p2=(PointObject) previewPoint;
Params[Params.length-1]=P3org;
c.add(P3org);
runMacroPreview(zc, false);
final PointObject p3=(PointObject) previewPoint;
Params[Params.length-1]=P4org;
c.add(P4org);
runMacroPreview(zc, false);
final PointObject p4=(PointObject) previewPoint;
final double x1=Math.sqrt((p1.getX()-p0.getX())
*(p1.getX()-p0.getX())+(p1.getY()-p0.getY())
*(p1.getY()-p0.getY()));
final double x2=Math.sqrt((p2.getX()-p0.getX())
*(p2.getX()-p0.getX())+(p2.getY()-p0.getY())
*(p2.getY()-p0.getY()));
final double x3=Math.sqrt((p3.getX()-p0.getX())
*(p3.getX()-p0.getX())+(p3.getY()-p0.getY())
*(p3.getY()-p0.getY()));
final double x4=Math.sqrt((p4.getX()-p0.getX())
*(p4.getX()-p0.getX())+(p4.getY()-p0.getY())
*(p4.getY()-p0.getY()));
boolean b=Math.abs(x1-x2)<1e-11;
b=b&&Math.abs(x1-x3)<1e-11;
b=b&&Math.abs(x1-x4)<1e-11;
keepCircle=b;
}
public boolean isMultipleFinalAccepted() {
final ConstructionObject p[]=M.getParams();
if (Param0) {
return false;
}
final ConstructionObject p[]=M.getParams();
return (p[Param] instanceof PointObject)&&Param==p.length-1;
}
@Override
public void finishConstruction(final MouseEvent e, final ZirkelCanvas zc) {
final ConstructionObject p[]=M.getParams();
ConstructionObject o;
if (p[Param] instanceof PointObject) {
o=zc.selectCreatePoint(e.getX(), e.getY(), e.isAltDown());
} else {
return;
}
NewPoint[Param]=true;
Params[Param]=o;
runMacroPreview(zc, true);
}
public void finishConstruction(int x, int y, final MouseEvent e, final ZirkelCanvas zc) {
final ConstructionObject p[]=M.getParams();
ConstructionObject o;
if (p[Param] instanceof PointObject) {
o=zc.selectCreatePoint(x, y, e.isAltDown());
} else {
return;
}
NewPoint[Param]=true;
Params[Param]=o;
runMacroPreview(zc, true);
}
@Override
public void reset(final ZirkelCanvas zc) {
if (zc.Visual) {
super.reset(zc);
Param=0;
if (M!=null&&M.hasFixed()) {
getFixed(zc);
}
showStatus(zc);
} else if (M!=null) // show the input pattern
{
final StringBuffer b=new StringBuffer();
b.append('=');
final String name=M.getName();
if (name.indexOf("(")>0) {
b.append("\""+M.getName()+"\"");
} else {
b.append(M.getName());
}
b.append('(');
for (int i=0; i=S.length) {
doMacro(zc);
reset(zc);
break;
}
}
showStatus(zc);
}
public void returnPressed(final ZirkelCanvas zc) {
if (M==null||!zc.Visual) {
return;
}
final String name=M.getLast(Param);
if (name.equals("")) {
return;
}
final ConstructionObject o=zc.getConstruction().find(name);
if (!setNextParameter(o, zc, false)) {
return;
}
if (Param>=S.length) {
doMacro(zc);
reset(zc);
} else {
getFixed(zc);
}
}
public boolean setNextParameter(final ConstructionObject o,
final ZirkelCanvas zc, final boolean fix) {
if (!isAdmissible(zc, o)) {
return false;
}
Params[Param]=o;
o.setSelected(true);
if (fix) {
Fixed[Param]=true;
}
zc.getConstruction().addParameter(o);
zc.repaint();
Param++;
return true;
}
public void doMacro(final ZirkelCanvas zc) {
final String value[]=new String[0];
runMacro(zc, value);
}
static DepList DL=new DepList();
@Override
public void showStatus(final ZirkelCanvas zc) {
if (M!=null) {
final ConstructionObject p[]=M.getParams();
String type="???";
// Determine the expected type and display in status line
if (p[Param] instanceof FunctionObject) {
type=Global.name("name.Function");
} else if (p[Param] instanceof PointObject) {
type=Global.name("name.Point");
} else if (p[Param] instanceof FixedAngleObject) {
type=Global.name("name.FixedAngle");
} else if(p[Param] instanceof VectorObject) {
type=Global.name("name.Vector");
} else if (p[Param] instanceof SegmentObject) {
type=Global.name("name.Segment");
} else if (p[Param] instanceof LineObject) {
type=Global.name("name.TwoPointLine");
} else if (p[Param] instanceof RayObject) {
type=Global.name("name.Ray");
} else if (p[Param] instanceof PrimitiveLineObject) {
type=Global.name("name.Line");
} else if (p[Param] instanceof PrimitiveCircleObject) {
type=Global.name("name.Circle");
} else if (p[Param] instanceof ExpressionObject) {
type=Global.name("name.Expression");
} else if (p[Param] instanceof AreaObject) {
type=Global.name("name.Polygon");
} else if (p[Param] instanceof AngleObject) {
type=Global.name("name.Angle");
} else if (p[Param] instanceof QuadricObject) {
type=Global.name("name.Quadric");
}
final String s=M.getLast(Param);
String prompt;
int inc=zc.isDP()?0:1;
if (s.equals("")) {
prompt=ConstructionObject.text4(Global.name("message.runmacro"), M.getName(), ""
+(Param+inc), type, S[Param]);
} else {
prompt=ConstructionObject.text4(Global.name("message.runmacro"), M.getName(), ""
+(Param+inc), type, S[Param])
+" ";
}
zc.showStatus(prompt);
}
}
//Only for JSFunctions/ExecuteMacro
public static ArrayList TargetsNameList = new ArrayList();
public static ArrayList TargetsIndexList = new ArrayList();
/**
* Run a macro. The macro parameters have already been determined. This is a
* rather complicated function.
*/
public void runMacro(final ZirkelCanvas zc, final Construction c,
final String value[]) {
TargetsNameList.clear();
TargetsIndexList.clear();
OCs.clear();
PROMPTs.clear();
M.setTranslation(c);
final ConstructionObject LastBefore=c.lastButN(0);
final int N=Params.length;
// First clear all parameter flags. This makes it possible to
// check for proper translation of secondary parameters later.
// Secondary parameters without a translation will be
// constructed.
Enumeration e=M.elements();
while (e.hasMoreElements()) {
final ConstructionObject o=(ConstructionObject) e.nextElement();
o.clearParameter();
o.setTranslation(null);
}
M.clearTranslations();
c.clearTranslators();
final ConstructionObject p[]=M.getParams();
// For all macro parameters, determine the translation to the
// real construction, and do the same for the secondary
// parameters, which belong to the parameter. The secondary
// parameters are stored in the macro at its definition, as
// the primary ones. Also the parameters in the macros are marked
// as such to make sure and prevent construction.
M.initLast(); // Macros remember the parameters for next call
for (int i=0; i=value.length||value[index].equals("")) {
OCs.add(oc);
PROMPTs.add(M.getPromptName(o.getName()));
}
}
}
}
}
// Now fix the objects, which depend on later objects
e=M.elements();
while (e.hasMoreElements()) {
final ConstructionObject o=(ConstructionObject) e.nextElement();
if (!o.isParameter()) {
o.laterTranslate(M);
}
}
c.updateCircleDep();
c.runTranslators(M);
c.dovalidate();
zc.repaint();
int fixed=0;
for (final boolean element : Fixed) {
if (element) {
fixed++;
}
}
if (fixed>0&&fixed