package main;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import tikzmodel.TikzPictureType;
import tikzparser.SyntaxTikzPicture;
import tikzparser.TikzParser;
import tikzparser.Util;
/**
* Represents a file that contains Tikz picture code.
*
* @author Florian Noack
*
*/
public class TikzFile extends File {
private TikzParser parser;
protected ArrayList<Object> parts;
/**
* Create a TikzFile object using the specified filename.
*
* @param filename
* Filename of the TikzFile.
*/
public TikzFile(String filename) {
super(filename);
parser = new TikzParser();
parts = new ArrayList<Object>();
readPictures();
}
/**
* Reads and returns all TikzPictures found in the specified file.
*/
public void readPictures() {
char[] data = null;
char[] dataFile = new char[(int) length()];
try {
FileReader f = new FileReader(this);
int size = f.read(dataFile);
data = new char[size];
for(int i=0; i<data.length; i++) {
data[i] = dataFile[i];
}
f.close();
} catch (IOException e) {
e.printStackTrace();
}
/*
* TODO BE ABLE TO IGNORE \...{tikzpicture} IN COMMENTS
*/
// Find pictures.
String strData = new String(data);
int pos;
ArrayList<EnvironmentPosition> envs = new ArrayList<EnvironmentPosition>();
// Search opening tags
pos = 0;
while(pos < strData.length()) {
pos = strData.indexOf(TikzPictureType.PREFIX_LATEX, pos);
if(pos >= 0) {
envs.add(new EnvironmentPosition(pos, true));
pos += TikzPictureType.PREFIX_LATEX.length();
} else {
pos = strData.length(); // breaks loop
}
}
// Search closing tags
pos = 0;
while(pos < strData.length()) {
pos = strData.indexOf(TikzPictureType.SUFFIX_LATEX, pos);
if(pos >= 0) {
envs.add(new EnvironmentPosition(pos+TikzPictureType.SUFFIX_LATEX.length()-1, false));
pos += TikzPictureType.SUFFIX_LATEX.length();
} else {
pos = strData.length(); // breaks loop
}
}
// Generate environment
java.util.Collections.sort(envs);
boolean isOpen = false;
int lastPos = 0;
for(EnvironmentPosition ep : envs) {
/*
* Environment is open.
*/
if(isOpen) {
// Umgebung wird geschlossen
if(!ep.opening) {
SyntaxTikzPicture p
= parser.parseCode(Util.substring(data, lastPos, ep.pos));
addPart(p);
lastPos = ep.pos+1;
isOpen = false;
/*
* Environment is already open but another opening tag is discovered.
* Make the detected opening tag the current opening tag and go
* ahead.
*/
} else {
String part = Util.substring(data, lastPos, ep.pos-1);
addPart(part);
lastPos = ep.pos;
}
/*
* Environment is closed.
*/
} else {
if(ep.opening) {
String part = Util.substring(data, lastPos, ep.pos-1);
addPart(part);
lastPos = ep.pos;
isOpen = true;
}
}
}
// Add String behind last closing tag
if(lastPos < data.length) {
String part = strData.substring(lastPos);
addPart(part);
}
}
/**
* Writes this TikzFile to disk.
*
* @param file
* TikzFile to be written.
*/
public void save() {
try {
BufferedWriter out = new BufferedWriter(new FileWriter(this));
int debugCnt = 0;
for(Object o : parts) {
debugCnt += o.toString().length();
out.write(o.toString());
}
System.out.println(debugCnt + " characters written");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the TikzPictures stored in this TikzFile.
*
* @return
*
*/
public SyntaxTikzPicture[] getPictures() {
ArrayList<SyntaxTikzPicture> pictures = new ArrayList<SyntaxTikzPicture>();
for(Object o : parts) {
if(o instanceof SyntaxTikzPicture) {
pictures.add((SyntaxTikzPicture) o);
}
}
return pictures.toArray(new SyntaxTikzPicture[pictures.size()]);
}
/**
* Replaces a given SyntaxTikzPicture with another picture.
*
* @param oldPic
* Replaced picture
*
* @param newPic
* Replacing picture
*
* @return
* true, if the picture could be replaced,
* false, otherwise
*/
public boolean replacePicture(SyntaxTikzPicture oldPic, SyntaxTikzPicture newPic) {
boolean ret = false;
int index = parts.indexOf(oldPic);
ret = parts.remove(oldPic);
if(ret) {
parts.add(index, newPic);
}
return ret;
}
/**
* Adds a part to this TikzFile.
*
* @param part
* String representation of this part to be added.
*/
private void addPart(String part) {
parts.add(part);
}
/**
* Adds a part to this TikzFile.
*
* @param p
* TikzPicture to be added.
*/
private void addPart(SyntaxTikzPicture p) {
parts.add(p);
}
private class EnvironmentPosition implements Comparable<EnvironmentPosition> {
boolean opening;
/**
* For a PREFIX: position of the first letter
* For a SUFFIX: position of the last letter
*/
int pos;
public EnvironmentPosition(int pos, boolean opening) {
this.pos = pos;
this.opening = opening;
}
@Override
public int compareTo(EnvironmentPosition ep) {
return new Integer(pos).compareTo(new Integer(ep.pos));
}
}
}