import Tuple.*;
import InterpolatedVar.*;
import SGPlanarCam.*;
import java.util.Hashtable;
import java.util.List;
import SGImplify.*;
import javax.swing.*;
 
static final int DRAW_LINE = 0;
static final int TRANSLATE = 1;
 
int mouseMode = 1;
 
SGPlanarCam cam;
 
Vector pages = new Vector();
 
Vector lines = new Vector();
Vector lineTokens = new Vector();
 
PFont font;
 
int leftMargin = 10;
int topMargin = 10;
int fontHeight = 13;
int fontWidth = 7;
 
int offSet = 0;
int carX,carY = 5;
 
Vector currentStroke = null;
 
Hashtable colorings = new Hashtable();
 
 
String scriptFile = null;
String workingFile;
 
void setup(){
 
populateHash();
 
size(550,550);
frameRate(60);
font = loadFont("mono12.vlw");
 
 
if (online){
 
URL base = getDocumentBase();
URL root = getCodeBase();
StringTokenizer st = new StringTokenizer(base.toString(),"#");
if (st.countTokens() > 1){
st.nextToken();
scriptFile = root + "
println("opening" + scriptFile);
}
}
 
 
cam = new SGPlanarCam(this,new FOLagInterpolatedVar(this,0,2),new FOLagInterpolatedVar(this,0,2),new FOLagInterpolatedVar(this,1,2),new FOLagInterpolatedVar(this,0,4));
cam.cx.setVal(width/2);
cam.cy.setVal(height/2);
cam.setMouseMode(RIGHT,SGPlanarCam.TRANSLATE);
smooth();
 
}
 
 
void draw(){
 
if (scriptFile != null){
parseFile(scriptFile);
 
}
 
background(255);
cam.feed();
 
textFont(font);
 
 
 
Tuple2f bottom = cam.screenToWorld(0,height);
Tuple2f top = cam.screenToWorld(0,0);
int bottomLine = (int)bottom.y/fontHeight + 1;
int topLine = (int)top.y/fontHeight;
 
 
for (int i =0; i < constrain(bottomLine,0,lines.size()); i++){
lineRender((Vector)lineTokens.elementAt(i),i);
}
 
 
if (currentStroke != null) renderSketch(currentStroke);
}
 
void lineRender(Vector line, int index){
int uy = index*fontHeight;
 
if (index == carY){
 
noStroke();
fill(240,240,255,255);
rect(0,uy+2,width,fontHeight);
 
stroke(0);
line(carX*fontWidth,uy+2,carX*fontWidth,uy+2 + fontHeight);
 
}
fill(0);
stroke(0);
 
 
int dx = 0;
for (int i =0; i < line.size(); i++){
dx += ((drawable)line.elementAt(i)).render(dx*fontWidth,uy + fontHeight);
}
 
 
}
 
 
 
 
Vector parseLine(String line){
Vector tmp = new Vector(5);
 
if (line.startsWith("
StringTokenizer bn = new StringTokenizer(line," []");
bn.nextToken();
int anchorLine = new Integer(bn.nextToken()).intValue();
Vector sketch = new Vector();
String st;
while (bn.hasMoreTokens()){
st = bn.nextToken();
if (!st.contains(":")){
sketch.add(st);
}
else{
sketch.add(new Tuple2f(st));
}
}
tmp.add(new graphicToken(sketch,anchorLine));
return tmp;
}
else{
String splt [] = (line).split("
 
StringTokenizer bn = new StringTokenizer(splt[0]," ()[].",true);
 
while (bn.hasMoreTokens()){
tmp.add(new lineToken(bn.nextToken(),0));
}
 
 
if (splt.length > 1) tmp.add(new lineToken("
 
return tmp;
}
}
 
 
void mousePressed(){
 
if (currentStroke == null && mouseMode == DRAW_LINE){
currentStroke = new Vector();
currentStroke.add("
currentStroke.add(cam.screenToWorld(mouseX,mouseY));
 
}
 
}
 
void mouseReleased(){
 
if (mouseMode == DRAW_LINE && mouseButton == LEFT) currentStroke.add("break");
 
}
 
void mouseDragged(){
 
if (!mouseEvent.isConsumed()){
if (currentStroke != null) currentStroke.add(cam.screenToWorld(mouseX,mouseY));
}
 
}
 
void renderSketch(Vector cStroke){
 
Tuple2f a,b;
stroke(50);
strokeWeight(2.5);
a = ( Tuple2f)cStroke.elementAt(1);
for(int j = 2; j < cStroke.size();j++ ){
 
if (cStroke.elementAt(j) instanceof Tuple2f){
 
b = ( Tuple2f)cStroke.elementAt(j);
line(b.x,b.y,a.x,a.y);
a = b;
}
else if (cStroke.size() > j+1){
j++;
a = ( Tuple2f)cStroke.elementAt(j);
}
}
 
}
 
 
void keyPressed(){
println(keyCode);
if (keyCode == DOWN){
carY++;
String st = (String)lines.elementAt(carY);
if (carX > st.length()) carX = st.length();
}
else if (keyCode == UP){
if (carY > 0){
carY--;
String st = (String)lines.elementAt(carY);
if (carX > st.length()) carX = st.length();
}
}
else if (keyCode == RIGHT){
carX++;
}
else if (keyCode == LEFT){
carX--;
}
else if (keyCode == SHIFT){
println("shiftkey");
}
 
else if (keyCode == 113){
openFileDialog();
}
else if (keyCode == 114){
saveFileDialog();
}
 
else if (keyCode == 112){
if (mouseMode == TRANSLATE){
mouseMode = DRAW_LINE;
 
}
else{
mouseMode = TRANSLATE;
 
Tuple2f [] artmp = new Tuple2f[currentStroke.size()-1];
int begin = 1, end = 1;
List sub;
Vector path = new Vector();
path.add("
for (int i =1; i < currentStroke.size(); i++){
if (currentStroke.elementAt(i) instanceof String){
end = i;
 
sub = currentStroke.subList(begin,end);
 
Tuple2f [] brg = (Tuple2f [])sub.toArray(new Tuple2f[0]);
path.addAll(Arrays.asList(SGImplify.simplifyLine2D(3,brg)));
begin = i + 1;
path.add(" break ");
}
 
}
Vector tmp = new Vector();
graphicToken gt = new graphicToken(path,carY);
tmp.add(gt);
currentStroke = null;
 
lines.insertElementAt(gt.toString(),carY);
lineTokens.insertElementAt(tmp,carY);
 
}
}
else if (keyCode == ENTER){
lines.insertElementAt("",carY);
lineTokens.insertElementAt(new Vector(),carY);
carY++;
}
else if (keyCode == BACKSPACE){
if (carX == 0){
String modLine = (String)lines.elementAt(carY-1);
carX = modLine.length();
 
modLine = modLine + (String)lines.elementAt(carY);
 
lines.removeElementAt(carY-1);
lines.insertElementAt(modLine,carY-1);
 
lines.removeElementAt(carY);
lineTokens.removeElementAt(carY);
 
lineTokens.removeElementAt(carY-1);
lineTokens.insertElementAt(parseLine(modLine),carY-1);
carY--;
 
}
else{
String modLine = (String)lines.elementAt(carY);
modLine = modLine.substring(0,carX-1) + modLine.substring(carX,modLine.length());
lines.removeElementAt(carY);
lines.insertElementAt(modLine,carY);
 
lineTokens.removeElementAt(carY);
lineTokens.insertElementAt(parseLine(modLine),carY);
carX--;
}
}
 
 
 
else {
String modLine = (String)lines.elementAt(carY);
modLine = modLine.substring(0,carX) + key + modLine.substring(carX,modLine.length());
lines.removeElementAt(carY);
lines.insertElementAt(modLine,carY);
 
lineTokens.removeElementAt(carY);
lineTokens.insertElementAt(parseLine(modLine),carY);
carX++;
 
}
 
carX = constrain(carX,0,1000);
}
 
 
void openFileDialog(){
 
 
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = fc.getSelectedFile();
if (selFile != null){
 
scriptFile = selFile.getPath();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
);
 
 
}
 
void saveFileDialog(){
 
saveStrings(workingFile,(String [])lines.toArray( new String[lines.size()]));
 
 
}
 
void loadFile(String filename){
 
try{
 
URL base = new URL(getCodeBase(),"./src/" + filename);
scriptFile = base.toString();
 
}
catch (Exception e){
println("couldn't open file." + e );
 
}
}
 
void parseFile(String file){
 
lines = new Vector();
if (file.endsWith(".zip")){
 
try{
 
URL url = new URL(file);
InputStream stream = url.openStream();
ZipInputStream in = new ZipInputStream(stream);
ZipEntry entry = in.getNextEntry();
 
while(entry != null){
 
println(entry.getName());
BufferedReader read = new BufferedReader(new InputStreamReader(in));
 
while(read.ready()){
lines.add(read.readLine());
}
entry = in.getNextEntry();
}
}
catch(Exception e){
println(e);
}
}
else{
 
lines = new Vector(Arrays.asList(loadStrings(file)));
 
}
 
lineTokens = new Vector();
for (int i=0; i < lines.size(); i++){
lineTokens.add(parseLine((String)lines.elementAt(i)));
}
workingFile = scriptFile;
scriptFile = null;
}