import SGGUI.*;
import InterpolatedVar.*;
import SGPlanarCam.*;
import SGShape.*;
import SGImplify.*;
import Tuple.*;
import SGVectorGraphic.*;
 
import java.awt.geom.Path2D;
import java.awt.geom.*;
import javax.swing.*;
 
 
SGSlider strokeThick;
SGSlider tolerance;
SGSlider worldSize;
SGSlider r,g,b,fr,fg,fb,fa;
 
SGLabel zoom;
 
SGButton openFile, saveFile, draw,fillDraw, enterText,zoomButton,move,undo, snapLink, makeLink,newFile,rot,settingsButton;
ColorBox strok, fil;
 
Vector txEnter;
 
SGGUI controller;
VerticalLayout settings;
VerticalLayout controls;
 
VectorGraphic vg;
 
 
boolean lp;
 
Vector currentStroke = null;
 
Pen pen = new Pen();
 
SGPlanarCam cam;
 
int modKey;
PFont fnt;
 
float dof = 50;
 
float currentScale = 1;
int pts = 0;
 
 
static final int DRAW_LINE = 0;
static final int FILL_LINE = 4;
static final int DRAW_LINK = 1;
static final int TEXT_ENTRY = 2;
static final int ZOOM = 5;
static final int TRANSLATE = 6;
static final int ROTATE = 7;
static final int NONE = 3;
 
int mode = TRANSLATE;
 
StringBuffer txt;
 
 
TextHandler txtHandle;
CamHandler camHandle;
LinkHandler linkHandle;
CameraState clipBoard = null;
 
 
boolean picking = false;
 
int penColor = 0;
int fillColor = 0;
 
 
String scriptQ = null;
 
CameraState baseCam;
 
void setup() {
size(550, 550);
smooth();
frameRate(30);
 
fnt = loadFont("writing.vlw");
textFont(fnt);
controller = new SGGUI(this,fnt);
controller.GUI_HIGHLIGHT = color(220,220,240);
settings = new VerticalLayout(controller,200,10,150);
settings.title = "Settings";
controls = new VerticalLayout(controller,10,10,32);
 
 
tolerance = new SGSlider( "Tolerance",3,.2,.1,10);
worldSize = new SGSlider( "World Size",200,1,5,300);
strokeThick = new SGSlider( "Thickness",4,1,1,20);
zoom = new SGLabel("Zoom", 1);
openFile = new SGButton(loadImage("stock_open-options-24.png"),"open", this);
saveFile = new SGButton(loadImage("stock_save-options-24.png"),"save",this);
move = new SGButton(loadImage("stock-tool-button-move.png"),"move",this);
zoomButton = new SGButton(loadImage("stock-tool-button-zoom.png"),"zoom",this);
draw = new SGButton(loadImage("stock_draw-freeform-line.png"),"draw",this);
fillDraw = new SGButton(loadImage("stock_draw-freeform-line-filled.png"),"fillDraw",this);
undo = new SGButton(loadImage("stock_undo-history-alt-24.png"),"undo",this);
enterText = new SGButton(loadImage("stock_draw-text.png"),"text",this);
snapLink = new SGButton(loadImage("stock_link.png"),"snapLink",this);
makeLink = new SGButton(loadImage("stock_form-pattern-field.png"),"makeLink",this);
newFile = new SGButton(loadImage("stock_new-html.png"),"new",this);
rot = new SGButton(loadImage("stock-tool-button-rotate.png"),"rotate",this);
settingsButton = new SGButton(loadImage("stock_form-properties.png"),"settings",this);
strok = new ColorBox();
fil = new ColorBox();
r = new SGSlider( "Stroke Red",0,5,0,255);
g = new SGSlider( "Stroke Green",0,5,0,255);
b = new SGSlider( "Stroke Blue",0,5,0,255);
 
fr = new SGSlider( "Fill Red",128,5,0,255);
fg = new SGSlider( "Fill Green",128,5,0,255);
fb = new SGSlider( "Fill Blue",200,5,0,255);
fa = new SGSlider( "Fill Alpha",255,5,0,255);
 
settings.add(strokeThick);
settings.add(tolerance);
settings.add(strok);
settings.add(r);
settings.add(g);
settings.add(b);
settings.add(fil);
settings.add(fr);
settings.add(fg);
settings.add(fb);
settings.add(fa);
settings.setVisible(0);
controls.add(newFile);
controls.add(openFile);
controls.add(saveFile);
if (online) {
openFile.enabled = false;
saveFile.enabled = false;
}
controls.add(zoomButton);
controls.add(move);
controls.add(rot);
controls.add(draw);
controls.add(fillDraw);
controls.add(enterText);
controls.add(snapLink);
controls.add(makeLink);
makeLink.enabled = false;
controls.add(settingsButton);
controls.add(undo);
 
controller.add(settings);
controller.add(controls);
cam = new SGPlanarCam(this,new FOLagInterpolatedVar(this,0,4),new FOLagInterpolatedVar(this,0,4),new FOLagInterpolatedVar(this,1,2),new FOLagInterpolatedVar(this,0,4));
cam.setMouseMode(RIGHT,SGPlanarCam.ZOOM);
fillColor = color(fr.getVal(),fg.getVal(),fb.getVal(),fa.getVal());
clear();
baseCam = cam.getState();
 
if (online) readIn("hello.gz");
 
}
 
void draw() {
if (scriptQ != null){
readIn(scriptQ);
}
background(255);
penColor = color(r.getVal(),g.getVal(),b.getVal());
strok.setFillColor(penColor);
 
fillColor = color(fr.getVal(),fg.getVal(),fb.getVal(),fa.getVal());
fil.setFillColor(fillColor);
float sc = cam.getZoom();
float wrldSize = worldSize.getVal();
float delta = cam.sc.getTargetVal() - cam.sc.getVal();
if (sc > wrldSize){
 
cam.setZoom(-wrldSize);
cam.sc.setCurrVal(cam.sc.getTargetVal());
}
if (sc < -wrldSize){
cam.setZoom(wrldSize);
cam.sc.setCurrVal(cam.sc.getTargetVal());
}
 
stroke(0);
zoom.setVal(cam.getZoom());
 
CameraState state = cam.getState();
float sc2 = cam.sc.getVal();
float sc3 = cam.sc.getTargetVal();
if ((sc - dof) < -wrldSize){
 
cam.setZoom(wrldSize + (sc + wrldSize));
cam.sc.setCurrVal(cam.sc.getTargetVal());
cam.feed();
vg.render(pen, cam);
 
 
cam.setState(state);
}
if ((sc + dof) > wrldSize){
cam.setZoom(-wrldSize - ( wrldSize-sc));
cam.sc.setCurrVal(cam.sc.getTargetVal());
cam.feed();
 
vg.render(pen, cam);
 
cam.setState(state);
}
cam.sc.setCurrVal(sc2);
 
cam.feed();
vg.render(pen, cam);
 
picking = false;
if (clipBoard != null){
stroke(0,0,250);
strokeWeight(2.f/cam.getScale());
line(cam.cx.getVal(),cam.cy.getVal(),clipBoard.cx,clipBoard.cy);
}
}
 
 
 
void clear(){
vg = new VectorGraphic(this);
camHandle = new CamHandler(this);
linkHandle = new LinkHandler(this);
txtHandle = new TextHandler(this);
vg.addTokenHandler(txtHandle);
vg.addTokenHandler(linkHandle);
 
 
Vector settings = new Vector(2);
settings.add("th");
settings.add("" + pen.strokeWeight);
vg.vector.add(settings);
Vector settings2 = new Vector(6);
settings2.add("sc");
settings2.add("" + (cam.getZoom()));
Tuple2f [] bounds = cam.getBoundingBox();
settings2.add(bounds[0]);
settings2.add(bounds[1]);
settings2.add("-1");
settings2.add(cam.cx.getVal() + "");
settings2.add(cam.cy.getVal() + "");
settings2.add("" + (strokeThick.getVal()/cam.getScale()));
settings2.add(0 + "");
vg.vector.add(settings2);
vg.lastScale = settings2;
 
Vector settings3 = new Vector(2);
settings3.add("fo");
settings3.add("" + fillColor);
vg.vector.add(settings3);
 
Vector settings4 = new Vector(2);
settings4.add("co");
settings4.add("" + penColor);
vg.vector.add(settings4);
 
}
void mousePressed(){
 
if (!mouseEvent.isConsumed() && mouseButton == LEFT){
if (currentStroke == null && (mode == DRAW_LINE || mode == FILL_LINE || mode == DRAW_LINK)){
if (pen.strokeWeight != strokeThick.getVal()/cam.getScale()){
Vector settings = new Vector(2);
settings.add("th");
settings.add("" + (strokeThick.getVal()/cam.getScale()));
vg.vector.add(settings);
}
validateCameraBox();
if (pen.strokeColor != penColor){
Vector settings = new Vector(2);
settings.add("co");
settings.add(penColor + "");
vg.vector.add(settings);
}
 
else if (pen.fill != fillColor){
Vector settings = new Vector(2);
settings.add("fo");
settings.add(fillColor + "");
vg.vector.add(settings);
}
 
println("creating current stroke");
currentStroke = new Vector();
if (mode == DRAW_LINE || mode == DRAW_LINK) currentStroke.add("st");
else if (mode == FILL_LINE) currentStroke.add("fs");
vg.vector.add(currentStroke);
}
}
}
 
void mouseClicked(){
picking = true;
}
 
void mouseDragged(){
if (!mouseEvent.isConsumed()){
if (mode == TEXT_ENTRY){
 
int lx = Integer.parseInt((String)txEnter.elementAt(2));
lx += (mouseX-pmouseX)/cam.sc.getVal();
int ly = Integer.parseInt((String)txEnter.elementAt(3));
ly += (mouseY-pmouseY)/cam.sc.getVal();
txEnter.set(3,ly + "");
txEnter.set(2,lx + "");
}
else{
if (currentStroke != null) currentStroke.add(cam.screenToWorld(mouseX,mouseY));
}
}
 
}
 
 
 
void mouseReleased(){
 
if (!mouseEvent.isConsumed() && currentStroke != null){
Tuple2f [] tmp = new Tuple2f[currentStroke.size()-1];
for (int i =0; i < currentStroke.size()-1; i++){
tmp[i] = (Tuple2f)currentStroke.elementAt(i+1);
}
vg.vector.removeElementAt(vg.vector.size()-1);
 
Vector toAdd = new Vector();
if (currentStroke.size() != 1){
if (mode == DRAW_LINE || mode == FILL_LINE ){
if (mode == DRAW_LINE) toAdd.add("st");
else if (mode == FILL_LINE) toAdd.add("fs");
toAdd.addAll(Arrays.asList(SGImplify.simplifyLine2D(tolerance.getVal()/cam.getScale(),tmp)));
vg.vector.add(toAdd);
}
else if (mode == DRAW_LINK && clipBoard != null){
toAdd.add("ln");
TokenPath path = new TokenPath();
Tuple2f [] smp = SGImplify.simplifyLine2D(tolerance.getVal()/cam.getScale(),tmp);
path.moveTo(smp[0].x,smp[0].y);
for (int i =1; i < smp.length; i++){
path.lineTo(smp[i].x,smp[i].y);
}
toAdd.add(path);
toAdd.add(clipBoard);
vg.vector.add(toAdd);
clipBoard = null;
draw.enabled = true;
fillDraw.enabled = true;
makeLink.enabled = false;
undo.enabled = true;
enterText.enabled = true;
}
}
}
currentStroke = null;
}
 
void undo(){
vg.vector.removeElementAt(vg.vector.size()-1);
 
}
 
 
 
 
void GUIEventPerformed(GUIEvent e){
 
if (mode == TEXT_ENTRY){
if (mode == TEXT_ENTRY) mode = NONE;
picking = true;
 
}
keyCode = 0;
if (e.title.equals("draw")){
key = 'd';
keyPressed();
}
if (e.title.equals("fillDraw")){
 
key = 'f';
keyPressed();
}
else if (e.title.equals("zoom")){
key = 'y';
keyPressed();
}
else if (e.title.equals("move")){
key = 't';
keyPressed();
}
else if (e.title.equals("open")){
key = 'o';
keyPressed();
}
else if (e.title.equals("save")){
key = 's';
keyPressed();
}
else if (e.title.equals("undo")){
undo();
}
else if (e.title.equals("text")){
key = 'e';
keyPressed();
}
else if (e.title.equals("snapLink")){
key = 'c';
keyPressed();
 
}
else if (e.title.equals("makeLink")){
key = 'l';
keyPressed();
}
else if (e.title.equals("new")){
key = 'n';
keyPressed();
}
else if (e.title.equals("rotate")){
key = 'r';
 
keyPressed();
}
else if (e.title.equals("settings")){
settings.toggleVisible();
}
}
 
void keyPressed(){
 
if (key == CODED){
modKey = keyCode;
}
if (modKey == SHIFT){
if (keyCode > 48 && keyCode < 58){
camHandle.savedStates[keyCode-49] = cam.getState();
}
}
 
else if (modKey == CONTROL){
if (keyCode == 90) undo();
}
if (mode == TEXT_ENTRY){
if (keyCode == ENTER){
txt.append("\f");
}
 
else if (keyCode == BACKSPACE){
if (txt.length() > 0) txt.deleteCharAt(txt.length()-1);
}
else if (keyCode == SHIFT){
 
}
 
else{
txt.append(key);
}
}
else{
if (keyCode > 48 && keyCode < 58){
cam.setState(camHandle.savedStates[keyCode-49]);
}
else if (key == 'l'){
cam.setMouseMode(LEFT,SGPlanarCam.UNBOUND);
mode = DRAW_LINK;
}
 
else if (key == 'c'){
clipBoard = cam.getState();
mode = NONE;
makeLink.enabled = true;
draw.enabled = false;
fillDraw.enabled = false;
enterText.enabled = false;
undo.enabled = false;
cam.setMouseMode(LEFT,SGPlanarCam.TRANSLATE);
}
else if (key == 't'){
cam.setMouseMode(LEFT,SGPlanarCam.TRANSLATE);
mode = TRANSLATE;
}
else if (key == 'y'){
cam.setMouseMode(LEFT,SGPlanarCam.ZOOM);
mode = ZOOM;
}
else if (key == 'r'){
cam.setMouseMode(LEFT,SGPlanarCam.ROTATE);
mode = ROTATE;
}
else if (key == 'd'){
cam.setMouseMode(LEFT,SGPlanarCam.UNBOUND);
mode = DRAW_LINE;
}
else if (key == 'f'){
cam.setMouseMode(LEFT,SGPlanarCam.UNBOUND);
mode = FILL_LINE;
}
else if (key == 'n'){
clear();
}
else if (key == 's'){
writeOut();
}
else if (key == 'o'){
readIn();
}
else if (key == 'q'){
loadFile("base.gz");
}
else if (key == 'a'){
cam.zoom(3);
}
else if (key == 'z'){
cam.zoom(-3);
}
else if (key == 'e'){
 
validateCameraBox();
mode = TEXT_ENTRY;
cam.setMouseMode(LEFT,SGPlanarCam.UNBOUND);
txt = new StringBuffer("");
txEnter = new Vector(6);
txEnter.add("tx");
txEnter.add(cam.getScale() + "");
txEnter.add((int)cam.cx.getTargetVal() + "");
txEnter.add((int)cam.cy.getTargetVal() + "");
txEnter.add(cam.rot.getVal() + "");
txEnter.add(txt);
vg.vector.add(txEnter);
}
}
 
}
 
void validateCameraBox(){
 
if (pen.scale != cam.getZoom() || abs(pen.cx - cam.cx.getTargetVal()) > .1 || abs(pen.cy - cam.cy.getTargetVal()) > .1 ){
println("dropping scale");
Vector settings = new Vector(6);
settings.add("sc");
settings.add("" + (cam.getZoom()));
Tuple2f [] bounds = cam.getBoundingBox();
settings.add(bounds[0]);
settings.add(bounds[1]);
settings.add("-1");
settings.add(cam.cx.getVal() + "");
settings.add(cam.cy.getVal() + "");
settings.add("" + (strokeThick.getVal()/cam.getScale()));
settings.add(penColor + "");
settings.add(fillColor + "");
vg.vector.add(settings);
vg.lastScale.setElementAt(vg.vector.size() + "",4);
vg.lastScale = settings;
}
 
}
 
 
void keyReleased(){
if (keyCode == CONTROL || keyCode == SHIFT) modKey = 0;
}
 
 
void writeOut(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = fc.getSelectedFile();
if (selFile != null){
String outName = selFile.getAbsolutePath();
Vector a;
String [] output = new String[vg.vector.size() + 1];
for(int i =0; i < vg.vector.size();i++ ){
a = (Vector)vg.vector.elementAt(i);
output[i] = a.toString();
}
output[vg.vector.size()] = camHandle.tokenize();
if (!outName.endsWith(".gz")) outName = outName + ".gz";
saveStrings(outName, output);
 
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
 
void readIn(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new ZipFilter());
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = fc.getSelectedFile();
if (selFile != null){
String outName = selFile.getAbsolutePath();
readIn(outName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
 
private void readIn(String fileName){
Vector handlers = new Vector();
handlers.add(txtHandle);
handlers.add(linkHandle);
handlers.add(camHandle);
vg = new VectorGraphic(this,fileName, handlers);
vg.addTokenHandler(txtHandle);
vg.addTokenHandler(linkHandle);
scriptQ = null;
cam.setState(baseCam);
}
 
void loadFile(String filename){
 
try{
 
URL base = new URL(getCodeBase(),filename);
scriptQ = base.toString();
}
catch (Exception e){
println("couldn't open file." + e );
}
}