public class GLOBAL {

	public static boolean useMaskedUpdating = false;

	static SketchProperties sketchProperties = new SketchProperties();
	
	public static double CAM_OFFSET_X = 300;
	public static double CAM_OFFSET_Y = -900;
	public static int windowWidth;
	public static int windowHeight;
	public static PFont font;
	public PImage clickToStart;
	public String version = "0.9.0.1";
	public static boolean forceReset = false;
	public static boolean cropExportToScreen = false;
	public static SketchGlobals SketchGlobals;
	public static boolean dxfCapture = false;
	public static String dxfLocation = "./designOutput.dxf";
	//public static MovieMaker mm;
	public static boolean captureScreen = false;
	static int designDisplayList;


	//contains the title img
	static PImage tittleImg;

	static Object myMovie = null;
	static int tittleImageNum = 0;

	static public SketchChairs sketchChairs;

	//static public VerletPhysics physics;
	static public jBullet jBullet;
	static public UITools uiTools;
	//static public RagDoll ragDoll = null;
	public static ModalGUI gui;
	static public Environments environments;

	/*
	 * What mode are we in? 0 - sketch seat 1 - view in 3d
	 */
	static public int mode = 0;
	static public float rotateModelsX;

	static public float rotateModelsY;
	static public PGraphics g;

	public static PApplet applet;
	public static boolean savePDF = false;
	public static int sketch_id;
	static double ZOOM = 1.5f;
	public static Ray3D debugRay = null;

	public static Vec3D debugRayIntersection = null;
	public static ergoDoll person = null;

	public static spShapePack shapePack;
	static public Undo undo = new Undo();

	static public Long tick = 0l;
	static public WidgetPlanes planesWidget;

	static public WidgetSlices slicesWidget;
	static public WidgetLoad loadWidget;
	static public WidgetMaterials widgetMaterials;
	static public WidgetToolSettings widgetToolSettings;
	public static boolean performanceMode = true;

	static JFileChooser fc;

	public static String pdfSaveLocation = null;
	public static MeasureTool measuretTool;
	public static String LAST_SAVED_LOCATION = null;
	public static int timeoutCounter = 1200000 * 1000; //seconds of inactivity untill timeout. 

	public static int inativeCounter = 0; //seconds of inactivity untill timeout. 
	public static boolean personTranslate = true;
	public static boolean autoRotate = false;
	public static boolean modeChanged = false;
	public static float rememberLasty;
	public static boolean resetting = false;
	static CloudHook cloudHook = new CloudHook(
			"http://sketchchair.cc/framework/CloudHook.php");
	public static boolean autoOpenPDF = true;
	public static String lastLoadLocation = null;
	public static boolean screenshot = false;
	public static int renderChairColour = 255;
	public static WidgetLoad widgetLoad;
	public static String dxfSaveLocation;
	public static boolean saveDXF;
	public static SketchChair copyOfChair;
	public static GUIComponentSet toggleSetSlices;
	public static String pngPreviewSaveLocation;
	public static boolean exportPreviewPNG = false;
	static SkchAutamata skchAutomatic = new SkchAutamata();
	public static boolean floorOn = true;
	public static boolean saveChairToFile =false;
	public static boolean saveChairToFileAuto = false;
	public static boolean displayIntroPanel = true;
	public static boolean forceResize = false;
	public static boolean deleteAllChairsFlag =false;

	
	public static String username = null;
	public static String password = null;
	public static boolean authenticated = false;
	public static String sessionID = null;

	public static float prevRotateModelsX = 0;
	public static float prevRotateModelsY = -(float)Math.PI/4;

	public static GUIPanelTabbed designToolbarAdvanced = null;
	public static GUIPanelTabbed  designToolbarBasic = null;

	public static GUIPanel slicePanel;

	public static WidgetPreviewPanel previewWidget;

	public static Frame frame;

	public static int planeID = 0;

	protected static String loadChairLocation = null;
	public static String saveChairLocation = null;
	public static String savePatternLocation = null;

	protected static String saveDXFLocation = null;

	protected static String importSVGLocation = null;



	// create and load default properties
	Properties properties = new Properties();

	public static boolean debugPickBuffer =false;

	public static GUIPanelTabbed designToolbarPattern = null;

	public static GUIPanel cameraPanel;

	public static GUIPanel patternCameraPanel;


	
	public final static int color(int x, int y, int z) {

		if (x > 255)
			x = 255;
		else if (x < 0)
			x = 0;
		if (y > 255)
			y = 255;
		else if (y < 0)
			y = 0;
		if (z > 255)
			z = 255;
		else if (z < 0)
			z = 0;

		return 0xff000000 | (x << 16) | (y << 8) | z;

	}

	public final static int color(int x, int y, int z, int a) {

		if (a > 255)
			a = 255;
		else if (a < 0)
			a = 0;
		if (x > 255)
			x = 255;
		else if (x < 0)
			x = 0;
		if (y > 255)
			y = 255;
		else if (y < 0)
			y = 0;
		if (z > 255)
			z = 255;
		else if (z < 0)
			z = 0;

		return (a << 24) | (x << 16) | (y << 8) | z;

	}

	/**
	 * @return the zOOM
	 */
	public static double getZOOM() {
		return ZOOM;
	}

	public static boolean isMacOSX() {
		String osName = System.getProperty("os.name");
		return osName.startsWith("Mac OS X");
	}

	/**
	* @param zOOM the zOOM to set
	*/
	public static void setZOOM(float zOOM) {
		ZOOM = zOOM;
	}

	GLOBAL(PApplet applet) {
		
		LOGGER.info("Making GLOBAL");
			

		GLOBAL.applet = applet;
		gui = new ModalGUI();
		gui.applet = applet;
		gui.appletStatic = applet;
		
		
		ZOOM = 1f;
		CAM_OFFSET_X = -600;
		CAM_OFFSET_Y = -900;
		

		this.font = applet.loadFont("SegoeUI-12.vlw");
		//this.font = applet.createFont("Helvetica", 12);

		gui.myFontMedium = this.font;
		/*
		URL url = findResource("TrebuchetMS-12.vlw");
		try {
		    InputStream input = createInput(filename);
		    this.font =  new PFont(input);

		  } catch (Exception e) {
		    die("Could not load font " + filename + ". " +
		        "Make sure that the font has been copied " +
		        "to the data folder of your sketch.", e);
		  }
		  */

		sketchChairs = new SketchChairs();
		//physics = new VerletPhysics(
		//new Vec3D(0, 2f, 0), 300, 90f, .090f);
		jBullet = new jBullet();
		uiTools = new UITools(applet);
		//ragDoll = null;

		environments = new Environments();
		/*
		 * What mode are we in? 0 - sketch seat 1 - view in 3d
		 */
		mode = 0;

		rotateModelsX = 0;
		rotateModelsY = 0;

		savePDF = false;
		//	psketch_id;
		setZOOM(1f);

		debugRay = null;
		debugRayIntersection = null;

		person = null;
		shapePack = new spShapePack();
		undo = new Undo();
		tick = 0l;

		planesWidget = new WidgetPlanes(0, 0, 0, 0, gui);

		loadWidget = new WidgetLoad();
		widgetMaterials = new WidgetMaterials(0, 0, 0, 0, gui);

		performanceMode = false;

		fc = null;
		pdfSaveLocation = null;
		measuretTool = new MeasureTool();
		LAST_SAVED_LOCATION = null;

		SketchGlobals = new SketchGlobals();
		SketchGlobals.undo = this.undo;

	}

	public final int color(float x, float y, float z) {

		if (x > 255)
			x = 255;
		else if (x < 0)
			x = 0;
		if (y > 255)
			y = 255;
		else if (y < 0)
			y = 0;
		if (z > 255)
			z = 255;
		else if (z < 0)
			z = 0;

		return 0xff000000 | ((int) x << 16) | ((int) y << 8) | (int) z;

	}

} public class LOGGER {

	public static void debug(String message) {
	//System.out.println(message);
	}

	public static void debug(String message, Object obj) {	
	//System.out.println(obj.getClass().getName()+": "+message);
	}

	public static void error(String message) {
		System.out.println(message);
	}

	public static void error(String message, Object obj) {
		System.out.println(obj.getClass().getName() + ": " + message);
	}

	//log levels ERROR > WARNING > INFO > DEBUG
	public static void info(String message) {
		System.out.println(message);
	}

	public static void info(String message, Object obj) {System.out.println(obj.getClass().getName()+": "+message);
	}

	public static void warn(String message) {
		System.out.println(message);
	}

	public static void warn(String message, Object obj) {
		System.out.println(obj.getClass().getName() + ": " + message);
	}

	public static void warning(String message) {
		System.out.println(message);
	}

	public static void warning(String message, Object obj) {
		System.out.println(obj.getClass().getName() + ": " + message);
	}

} public class SETTINGS {

	public static boolean DEVELOPER_MODE = false; //if on print to console etc

	
	public static final int UNDO_LEVELS = 20;
	public static final boolean build_collision_mesh_detailed = true;
	public static final float MIN_SPACING = 20f;
	public static final int THUMBNAIL_HEIGHT = 300;
	public static final int THUMBNAIL_WIDTH = 300;

	public static boolean REC = false;
	public static boolean draw_collision_mesh = false;
	
	//public static float slat_width = 50;// drawing tool width
	//public static float leg_width = 25;
	public static float person_friction = 1f;
	public static float chair_damping_linear = .0001f;
	public static float chair_damping_ang = .001f;

	public static int sphere_res = 6;
	public static double optimize_outline_min_angle = 3;

	//Quality settings
	public static int cylinder_res = 15;

	public static float scale = .1f;
	//public static float pixels_per_mm_base = 5.6689342403628117913832199546485f;
	public static float pixels_per_mm_base = 0.35289342403628117913832199546485f;

	public static float pixels_per_mm_screen = 5.6689342403628117913832199546485f;
	public static float pixels_per_mm = pixels_per_mm_base * scale;

	public static float chair_width = 300;
	public static float slat_num = 5;

	public static float slot_tollerance = .03f * pixels_per_mm;
	public static float materialThickness = 0.25f;

	public static float spline_point_every = 30;

	//Colours

	public static int GRID_MAJOR_LINE = GLOBAL.applet.color(0, 0, 0, 255);
	public static float GRID_MAJOR_LINE_WEIGHT = 1f;

	public static int GRID_MINOR_LINE = GLOBAL.applet.color(0, 0, 0, 55);
	public static float GRID_MINOR_LINE_WEIGHT = 1f;

	//public static int SKETCHSHAPE_FILL_UNSELECTED_COLOUR = GLOBAL.applet.color(240, 240, 240);
	public static final float DEFAULT_MATERIAL_WIDTH = .37f;
	public static final float DEFAULT_SLAT_SPACING = 85;

	public static int person_fill_colour = GLOBAL.applet.color(250, 250, 250);

	public static final boolean WEB_MODE = false;
	public static final boolean APPLET_MODE = false;
	public static final float DEFAULT_SLATSLICE_HEIGHT = 100;
	public static final float MIN_RENDER_WIDTH = .3f;
	public static final float MIN_LEG_LEN = 2.0f;
	public static final int MOUSE_CLICKED_MIN_TIME = 1000;
	public static final int MOUSE_PRESSED_MIN_TIME = 1300;

	public static final boolean ENABLE_SELECT_MODEL_PLANES = true;
	
	
	public static final float MIN_ZOOM = 0.2f;
	public static final float MAX_ZOOM = 5;
	
	public static final float MIN_CAM_X_OFFSET = -4000f;
	public static final float MAX_CAM_X_OFFSET = 4000;
	
	public static final float MIN_CAM_Y_OFFSET = -2000f;
	public static final float MAX_CAM_Y_OFFSET = 2000;
	public static final float panelWidth = 900;
	public static final float panelHeight = 110;

	
	
	public static boolean DEBUG = false;
	public static String LANGUAGE = "ENG";
	public static boolean EXHIBITION_MODE = true; // deptreciated 
	public static boolean EXPERT_MODE = true;
	public static boolean TOUCH_SCREEN_MODE = false; 

	
	
	//PERSON COLOURS
	public static int ERGODOLL_FILL_COLOUR = GLOBAL.applet.color(225, 225, 225);
	public static int ERGODOLL_FILL_COLOUR_PERFORMANCE = GLOBAL.applet.color(
			245, 245, 245);
	public static int person_height_text_fill_colour = GLOBAL.applet.color(10,
			10, 10);

	//ENVIRONMENT COLOURS
	public int world_ground_colour = GLOBAL.applet.color(190, 190, 190);
	public int world_ground_side_colour = GLOBAL.applet.color(50, 50, 50);
	public int world_ground_under_colour = GLOBAL.applet.color(50, 50, 50);
	
	public int background_colour = GLOBAL.applet.color(250, 250, 250);

	public static float gravity = 60f;

	public static boolean show_framerate = false;

	public int autoSaveInterval = 600;
	public float bezierDetail = 1;
	public static int renderWidth = 1500;
	public static int renderHeight = 1500;
	
	public static boolean autoSave = false;
	public static int chairSaveNum = 0;
	public static float chair_friction = 1;
	public static boolean seperate_slots = false;

	public static boolean auto_seat = true;
	public static boolean hybernate = true;
	public static boolean render_chairs = true;
	public static boolean auto_build = true;
	public static float version = .90f;
	public static float chair_slat_end_size = 45;
	public static float chair_slatslot_end_size = 25;
	public static boolean RENDER_CENTRE_MASS = false;
	
	//guide windows
	public static int GUIDE_WINDOW_WIDTH = 800;
	public static int GUIDE_WINDOW_HEIGHT = 500;
	public static boolean displayIntroPanel = false;
	public static boolean useSliceCollisionDetection = false;
	public static float simplifyAmount = 1f;
	public static boolean autoSaveMakePattern = false;
	public static String autoSaveMakeLocation = "/";
	public static boolean addLegSlices = true;
	public static boolean autoRefreshTextures = false;
	public static float mouseMoveClamp = 10;
	public static boolean autoReset = false;
	public static int autoResetSeconds = 60;


	
	

} public class UITools {

	public static final int DRAW_TOOL = 1;
	public static final int SELECT_TOOL = 2;
	public static final int SELECT_BEZIER_TOOL = 9;
	public static int LEG_TOOL = 7;

	public static final int MOVE_CAM_TOOL = 3;

	public static final int ZOOM_CAM_TOOL = 4;

	public static final int ROTATE_CAM_TOOL = 5;

	public static final int ADD_DOLL_TOOL = 6;
	public static final int SCALE_PERSON_TOOL = 8;
	public static final int VIEW_SHAPE_PACK = 1;
	public static final int VIEW_CHAIR_EDIT = 2;
	public static final int VIEW_SAVE_CHAIR = 3;
	public static final int DRAW_PATH_TOOL = 12;
	public static final int MOVE_OBJECT = 16;

	public static final int SCALE_TOOL = 19;
	public static final int MOVE_2D_TOOL = 20;
	public static final int SLICES_SINGLE_SLICE = 23;
	public static final int SLICES_GROUP_SLICES = 24;
	public static final int SLICES_SINGLE_SLAT = 28;
	public static final int SLICES_SLATSLICE_GROUP = 29;
	public static final int SLICES_EDIT = 30;

	
	GUIComponentSet toggleSet = new GUIComponentSet();

	static void doLoad() {
		load("chair.cha");

	}

	static void doSave() {

		save("chair.cha");

	}

	static void load(Document doc) {

		LOGGER.debug("UITools: about to load Document");

		//return fd.getFile();
		//FileInputStream fileIn = new FileInputStream(name);
		//ObjectInputStream in = new ObjectInputStream(fileIn);
		Element e = (Element) doc.getChild(0);

		//check to make sure that it's a sketch chair doc. 
		if (!e.getQualifiedName().equals("SketchChairDoc"))
			return;

		e = (Element) e.getChild(0);

		SketchChair loadedChair = null;
		LOGGER.debug("UITools: about to load chair structure");

		//loading a chair
		if (e.getQualifiedName().equals("SketchChair")) {
			loadedChair = new SketchChair(e);
		}
		LOGGER.debug("UITools: loaded chair object");

		if (loadedChair != null) {

			//	loadedChair.justLoaded();

			GLOBAL.sketchChairs.add(loadedChair);
			//GLOBAL.sketchChairs.setCurChair(loadedChair);

			if (GLOBAL.planesWidget != null
					&& GLOBAL.planesWidget.slider != null) {
				GLOBAL.planesWidget.slider.setVal(loadedChair.getWidth());
				//GLOBAL.planesWidget.SlatSliderStart.setVal(loadedChair.startCoverPercent);
				// GLOBAL.planesWidget.SlatSliderEnd.setVal(loadedChair.endCoverPercent);
				// GLOBAL.planesWidget.SlatSliderSpacing.setVal(loadedChair.slatSpacingX);
				GLOBAL.slicesWidget.rebuild(loadedChair.crossSliceSelections);
			}

			GLOBAL.sketchChairs.getCurChair().localSavelocation = GLOBAL.lastLoadLocation;

		} else {
			LOGGER.error("Could not load chair from XML.");
		}

	}

	static void load(InputStream inputStream) {

		Builder builder = new Builder();

		Document doc = null;

		try {
			doc = builder.build(inputStream);
			load(doc);
		} catch (ValidityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParsingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void load(String name) {

		Builder builder = new Builder();
		InputStream input = null;

		GLOBAL.lastLoadLocation = name;
		LOGGER.debug("loading about to open file pointer.");
		try {
			input = new FileInputStream(name);
		} catch (FileNotFoundException e1) {
			LOGGER.debug("UITolls: FileNotFoundException");
			e1.printStackTrace();
		}
		LOGGER.debug("loading file pointer open.");

		Document doc = null;

		if (input == null)
			LOGGER.debug("UITools: File input is null.");

		try {
			if (builder == null)
				LOGGER.debug("UITools: XOM builder is null.");

			LOGGER.debug("UITools: about to build XML from input.");

			doc = builder.build(input);

			if (doc == null)
				LOGGER.debug("UITools: doc XOM obj is null.");

			load(doc);
		} catch (ValidityException e) {
			// TODO Auto-generated catch block
			LOGGER.error("UITools: Could not make XML document: ValidityException");
			e.printStackTrace();
		} catch (ParsingException e) {
			// TODO Auto-generated catch block
			LOGGER.error("UITools: Could not make XML document: ParsingException");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			LOGGER.error("UITools: Could not make XML document: IOException");
			e.printStackTrace();
		}

	}

	static void save(OutputStream stream, String name) {

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			PGraphics saveImg = GLOBAL.sketchChairs.getCurChair()
					.renderToFile();

			if (saveImg.width > 0 && saveImg.height > 0)
				saveImg.save(name + ".png");

		}

	}

	static void save(String name) {

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			try {
				Element root = new Element("SketchChairDoc");
				root.addAttribute(new Attribute("version", String
						.valueOf(SETTINGS.version)));
				
				root.appendChild(GLOBAL.sketchChairs.getCurChair().toXML());

				Document doc = new Document(root);
				OutputStream outXML = new FileOutputStream(name);
				outXML = new BufferedOutputStream(outXML);
				Serializer serializer = new Serializer(outXML, "ISO-8859-1");
				serializer.write(doc);

				GLOBAL.sketchChairs.getCurChair().localSavelocation = name;

			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			float rememberThis = GLOBAL.rotateModelsX;
			GLOBAL.rotateModelsX = .01f;
			
			/*
			PImage saveImg = GLOBAL.sketchChairs.getCurChair().renderDiagram(
					SETTINGS.THUMBNAIL_HEIGHT, SETTINGS.THUMBNAIL_HEIGHT,
					(float) -(Math.PI / 8), (float) -(Math.PI / 4), false);

			GLOBAL.rotateModelsX = rememberThis;
			if (saveImg.width > 0 && saveImg.height > 0)
				saveImg.save(name + ".png");
				*/

		}
	}
	
	
	static void savePattern(String name) {
		GLOBAL.shapePack.makeSVG(GLOBAL.applet, name);
/*
		if (GLOBAL.sketchChairs.getCurChair() != null) {
			try {
				Element root = new Element("SketchChairDoc");
				root.addAttribute(new Attribute("version", String
						.valueOf(SETTINGS.version)));

				root.appendChild(GLOBAL.sketchChairs.getCurChair().toXML());

				Document doc = new Document(root);
				OutputStream outXML = new FileOutputStream(name);
				outXML = new BufferedOutputStream(outXML);
				Serializer serializer = new Serializer(outXML, "ISO-8859-1");
				serializer.write(doc);

				GLOBAL.sketchChairs.getCurChair().localSavelocation = name;

			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			float rememberThis = GLOBAL.rotateModelsX;
			GLOBAL.rotateModelsX = .01f;
			PImage saveImg = GLOBAL.sketchChairs.getCurChair().renderDiagram(
					SETTINGS.THUMBNAIL_HEIGHT, SETTINGS.THUMBNAIL_HEIGHT,
					(float) -(Math.PI / 8), (float) -(Math.PI / 4), false);

			GLOBAL.rotateModelsX = rememberThis;
			if (saveImg.width > 0 && saveImg.height > 0)
				saveImg.save(name + ".png");

		}
		*/
	}

	
	
	

	private int currentTool = 1;
	public int currentView = 2;
	public static int MEASURE_TOOL = 21;

	public static int CROSSSLICE_EDIT = 22;
	public static  PImage DRAW_TOOL_CURSOR = null;
	public static  PImage SELECT_TOOL_CURSOR = null;
	public static  PImage ADD_DOLL_TOOL_CURSOR = null;
	public static  PImage MOVE_OBJECT_CURSOR = null;
	
	
	
	public static  PImage ROTATE_CAM_TOOL_CURSOR =null;
	public static  PImage ZOOM_CAM_TOOL_CURSOR = null;
	public static  PImage MOVE_CAM_TOOL_CURSOR = null;

	public static  PImage CURSOR_ADD_SLICE = null;

	public static  PImage LINE_TOOL_CURSOR;
	public static  PImage SCALE_TOOL_CURSOR;
	private PGraphics pickBuffer;
	private SketchPoint selectedVec = new SketchPoint(0, 0);
	public boolean render3dPreview = false;
	private SlicePlane selectedVecPlane = null;

	public SlicePlane curSliceplane = null;

	private SketchShape selectedShape = null;
	private boolean isSelectedVecOnOutline = false;
	public static int MOUSE_RIGHT = 39;
	public static int MOUSE_MIDDLE = 3;
	public static final int MOUSE_LEFT = 37;
	static final int LANGUAGE_ENG = 1;
	static final int LANGUAGE_JP = 2;
	private static final int NONE = -1;
	public static final int SLICE_EDIT_MODE_ADD = 0;
	public static final int SLICE_EDIT_MODE_POS = 1;
	public static final int SLICE_EDIT_MODE_SPACING = 2;
	private int editing = 1;
	public int preview = 2;

	public int editingMode = isEditing();
	public int pmouseX;
	public int pmouseY;
	public int mouseX;
	public int mouseY;
	public float mouseXworld;
	public float mouseYworld;
	public float pmouseXworld;
	public float pmouseYworld;
	public boolean mouseDown = false;

	public int mouseButton;
	public boolean renderNodesFlag = false;
	boolean useGrid = false;
	float gridWidth = 50f;
	float gridHeight = 50f;
	float minorGridnumber = 10;
	public RigidBody selectedBody;
	public boolean keyPressed;

	public char key;
	public int keyCode;
	private int selectCooldown;
	public MeasureTool measureTool = new MeasureTool();

	private PImage MEASURE_TOOL_CURSOR;

	private ArrayList<Clickable> clickables = new ArrayList<Clickable>();
	public boolean patternView = false;
	public float brush_dia = 40;
	public boolean mousePressed = false;
	private int mousePressedTime = 0;
	private int mouseSingleClickTime;
	public int loadedCursor;
	private boolean waitingForSingleClick;
	public boolean hasCursorControl = false;
	private PImage CURSOR_EDIT_SLICE_POS;
	private PImage CURSOR_EDIT_SLICE_SPACING;
	public int sliceToolMode = 0;
	private boolean prevMouseWasMove = false;
	public static SketchTools SketchTools;

	UITools(PApplet applet) {
		SketchTools = new SketchTools(applet);
	}

	public void addListener(Clickable clickable) {
		this.clickables.add(clickable);
	}

	public void addPlane(GUIEvent e) {
		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addLayer();

	}

	public void autoLoad() {
		load("autoSave.cha");
	}

	public void autoRotate(GUIEvent e) {

		GLOBAL.autoRotate = !GLOBAL.autoRotate;

		setCurrentTool(ROTATE_CAM_TOOL);
		if (!GLOBAL.autoRotate)
			GLOBAL.rotateModelsY = 0;
		
		GLOBAL.slicesWidget.unselectAll();
		GLOBAL.planesWidget.unselectAll();
		
	}

	public void autoSave() {

		save("autoSave.cha");
	}

	void build(PApplet applet) {
		DRAW_TOOL_CURSOR = applet.loadImage("gui/GUI_DRAW_TOOL_CURSOR.png");
		SELECT_TOOL_CURSOR = applet.loadImage("gui/cursors/CURSOR_SELECT.png");
		ADD_DOLL_TOOL_CURSOR = applet
				.loadImage("gui/cursors/CURSOR_HAND_UP.png");
		MOVE_CAM_TOOL_CURSOR = applet
				.loadImage("gui/cursors/CURSOR_CAM_MOVE.png");
		ROTATE_CAM_TOOL_CURSOR = applet
				.loadImage("gui/cursors/CURSOR_CAM_ROTATE.png");
		ZOOM_CAM_TOOL_CURSOR = applet.loadImage("gui/cursors/CURSOR_CAM_ZOOM.png");
		LINE_TOOL_CURSOR = applet.loadImage("gui/GUI_LINE_TOOL_UP.png");
		SCALE_TOOL_CURSOR = applet.loadImage("gui/GUI_SCALE_TOOL_CURSOR.png");
		MEASURE_TOOL_CURSOR = applet
				.loadImage("gui/GUI_MEASURE_TOOL_CURSOR.png");
		MOVE_OBJECT_CURSOR = applet
				.loadImage("gui/cursors/CURSOR_HAND_UP.png");
		CURSOR_ADD_SLICE = applet
				.loadImage("gui/cursors/CURSOR_SLAT_ADD.png");
		this.SketchTools.build(GLOBAL.applet);
		
		CURSOR_EDIT_SLICE_POS = applet
				.loadImage("gui/cursors/CURSOR_SLAT_EDIT.png");
		this.SketchTools.build(GLOBAL.applet);
		
		CURSOR_EDIT_SLICE_SPACING = applet
				.loadImage("gui/cursors/CURSOR_SLAT_EDIT_SPACING.png");
		this.SketchTools.build(GLOBAL.applet);
		
		//GLOBAL.applet.cursor(UITools.SELECT_TOOL_CURSOR, 1,1);
		// buffer is created using applet dimensions
		//this.pickBuffer = applet.createGraphics(applet.width, applet.height,
		//	PConstants.P3D);
		//this.pickBuffer.ortho(-(applet.width / 2), (applet.width / 2),
		//-(applet.height / 2), (applet.height / 2), -1000, 10000);
	}

	public void camJumpFront(GUIEvent e) {
		GLOBAL.rotateModelsX = 0;
		GLOBAL.rotateModelsY = 0;

	}

	public void camJumpSide(GUIEvent e) {
		GLOBAL.rotateModelsX = 0;
		GLOBAL.rotateModelsY = (float) -(Math.PI / 2);

	}

	public void camJumpTop(GUIEvent e) {
		GLOBAL.rotateModelsX = (float) -(Math.PI / 2);
		GLOBAL.rotateModelsY = 0;

	}

	public void camJumpIso(GUIEvent e) {
		GLOBAL.rotateModelsX = (float) -(Math.PI / 8);
		GLOBAL.rotateModelsY = (float) -(Math.PI / 4);

		//g.rotateY(rotateRend);

	}

	public void captureScreen(GUIEvent e) {
		GLOBAL.captureScreen = true;

	}

	public void changeModeBasic(GUIEvent e) {
		SETTINGS.EXPERT_MODE = false;

		UI.setupGUITabsBasic(GLOBAL.applet, GLOBAL.gui);

		GLOBAL.modeChanged = true;
	}

	public void changeModeExpert(GUIEvent e) {
		SETTINGS.EXPERT_MODE = true;
		UI.setupGUITabsExpert(GLOBAL.applet, GLOBAL.gui);


		GLOBAL.modeChanged = true;
	}

	public void changeView(GUIEvent e) {

		this.toggleView(e);

		//	GLOBAL.sketchChairs.curChair.slicePlanesY.update();
		//GLOBAL.sketchChairs.curChair.addToShapePack();

		//	this.currentView = (int) e.val;

	}

	public void copyChair() {
		GLOBAL.copyOfChair = GLOBAL.sketchChairs.getCurChair().copy();
	}

	public void deleteAllChairsFlag(GUIEvent e) {
		GLOBAL.deleteAllChairsFlag = true;
	}

	public void deleteAllChairs(GUIEvent e) {
		//this.saveChairToFileAuto(null);
		//this.captureScreen(null);
		//GLOBAL.applet.draw();

		GLOBAL.sketchChairs.killAll();

	}

	public void deleteLastChair(GUIEvent e) {
		this.saveChairToFileAuto(null);
		this.captureScreen(null);
		GLOBAL.applet.draw();
		GLOBAL.sketchChairs.killLast();

	}

	public void flipChair(GUIEvent e) {
		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().flipDesign();
	}

	/**
	 * @return the currentTool
	 */
	public int getCurrentTool() {
		return currentTool;
	}

	/**
	 * @return the pickBuffer
	 */
	public PGraphics getPickBuffer() {
		return pickBuffer;
	}

	public Vec2D getPointOnPlane(Vec2D mousePoint, Plane planeIn) {

		Plane plane = new Plane(planeIn.copy(), planeIn.normal.copy());

		Vec3D mouseRayPos = new Vec3D(mousePoint.x, mousePoint.y, planeIn.z); // this only works for planes perpendicular to the screen
		Vec3D mouseRayDir = new Vec3D(0, 0, -1);

		Vec3D focusCentre = new Vec3D(
				((GLOBAL.windowWidth / 2) - (float)GLOBAL.CAM_OFFSET_X),
				((GLOBAL.windowHeight / 2) - (float)GLOBAL.CAM_OFFSET_Y), 0);

		//now mouse pos is refereced from the centre of the screen
		mouseRayPos.x -= (GLOBAL.windowWidth / 2);
		mouseRayPos.y -= (GLOBAL.windowHeight / 2);
		mouseRayPos.scaleSelf((float) (1 / GLOBAL.getZOOM()));

		mouseRayPos.addSelf(focusCentre);

		Ray3D ray;

		Vec3D mousePos = null;
		Vec3D intersect;
		mouseRayDir = new Vec3D(0, 0, -1);

		plane.z = 0;
		//we need to rotate the plane so that it matches the one on the draw view
		plane.normal.rotateY(GLOBAL.rotateModelsY);
		plane.normal.rotateX(GLOBAL.rotateModelsX);

		plane.addSelf(plane.normal.scale(planeIn.z));
		//mouseRayDir.rotateY(GLOBAL.rotateModelsY);
		//mouseRayDir.rotateX(GLOBAL.rotateModelsX);

		mouseRayPos.subSelf(focusCentre);
		ray = new Ray3D(mouseRayPos, mouseRayDir); // this should be the world position of the mouse poiner on the 0,0,-1 plane

		intersect = plane.getIntersectionWithRay(ray);

		if (intersect == null) {
			ray = new Ray3D(mouseRayPos, mouseRayDir.invert());
			intersect = plane.getIntersectionWithRay(ray);
		}

		ray = new Ray3D(mouseRayPos, mouseRayDir);
		ray.addSelf(focusCentre);

		//if(this.mouseDown)
		//	GLOBAL.debugRay = ray;

		if (intersect != null) {

			//  System.out.println(plane.getProjectedPoint(intersect));
			//	intersect.z -= plane.z*2;
			//intersect.x += 70;	
			//	System.out.println("before rotate " +intersect);
			//	intersect.subSelf(focusCentre.scale(GLOBAL.getZOOM()));

			// 	intersect.
			intersect.rotateX(-GLOBAL.rotateModelsX);
			intersect.rotateY(-GLOBAL.rotateModelsY);

			intersect.addSelf(focusCentre);

			//intersect.x += (GLOBAL.CAM_OFFSET_X*GLOBAL.getZOOM());
			//intersect.y += GLOBAL.CAM_OFFSET_Y;

			//intersect.rotateAroundAxis(axis, theta)
			mousePos = intersect;
			//mousePos.x += intersect.z;
			//System.out.println("after rotate " +intersect);
		}

		//get the chair matrix
		Matrix4f chairMatrix = new Matrix4f();
		Vec3D chairCentreOfMass = new Vec3D();
		if (GLOBAL.sketchChairs.getCurChair() != null
				&& GLOBAL.sketchChairs.getCurChair().rigidBody != null) {
			Transform transform = new Transform();
			GLOBAL.sketchChairs.getCurChair().rigidBody
					.getWorldTransform(transform);
			transform.getMatrix(chairMatrix);
			chairCentreOfMass = GLOBAL.sketchChairs.getCurChair().centreOfMass;
		}

		if (GLOBAL.sketchChairs.getCurChair() != null
				&& GLOBAL.sketchChairs.getCurChair().rigidBody != null
				&& chairMatrix != null && mousePos != null) {
			float centreMouseDeltaX = mousePos.x
					- ((chairMatrix.m03) / GLOBAL.jBullet.scale);
			float centreMouseDeltaY = mousePos.y
					- ((chairMatrix.m13) / GLOBAL.jBullet.scale);
			float centreMouseDeltaZ = mousePos.z
					- ((chairMatrix.m23) / GLOBAL.jBullet.scale);
			centreMouseDeltaZ = 0;

			float newX = ((chairMatrix.m00) * centreMouseDeltaX)
					+ ((chairMatrix.m01) * centreMouseDeltaY)
					+ ((chairMatrix.m02) * centreMouseDeltaZ);
			float newY = (((chairMatrix.m10) * centreMouseDeltaX)
					+ ((chairMatrix.m11) * centreMouseDeltaY) +
					((chairMatrix.m12) * centreMouseDeltaZ));
			float newZ = ((chairMatrix.m20) * centreMouseDeltaX)
					+ ((chairMatrix.m21) * centreMouseDeltaY)
					+ ((chairMatrix.m22) * centreMouseDeltaZ);

			newY = newY * -1;

			mousePos.x = newX + ((chairCentreOfMass.x) / GLOBAL.jBullet.scale);
			mousePos.y = newY + ((chairCentreOfMass.y) / GLOBAL.jBullet.scale);
			//mousePos.z = centreMouseDeltaZ + chairCentreOfMass.Z;
		}

		Vec2D intersect2D = null;
		if (mousePos != null) {
			intersect2D = new Vec2D(mousePos.x, mousePos.y);
			//intersect2D = new Vec2D(mousePoint.x, mousePoint.y);

		} else {
			intersect2D = new Vec2D(mousePoint.x, mousePoint.y);
		}
		if (intersect2D == null)
			intersect2D = new Vec2D(mousePoint.x, mousePoint.y);

		return intersect2D;

	}

	public Vec2D getPointOnPlaneOld(Vec2D mousePoint, Plane planeIn) {
		//get the chair matrix
		Matrix4f chairMatrix = new Matrix4f();
		Vec3D chairCentreOfMass = new Vec3D();
		if (GLOBAL.sketchChairs.getCurChair() != null
				&& GLOBAL.sketchChairs.getCurChair().rigidBody != null) {
			Transform transform = new Transform();
			GLOBAL.sketchChairs.getCurChair().rigidBody
					.getWorldTransform(transform);
			transform.getMatrix(chairMatrix);
			chairCentreOfMass = GLOBAL.sketchChairs.getCurChair().centreOfMass;
		}

		Plane plane = new Plane(planeIn.copy(), planeIn.normal.copy());

		Vec3D mouseRayPos = new Vec3D(mousePoint.x, mousePoint.y, plane.z); // this only works for planes perpendicular to the screen
		Vec3D mouseRayDir = new Vec3D(0, 0, -1);

		Vec3D focusCentre = new Vec3D(
				((GLOBAL.windowWidth / 2) - (float)GLOBAL.CAM_OFFSET_X),
				((GLOBAL.windowHeight / 2) - (float)GLOBAL.CAM_OFFSET_Y), 0);

		//now mouse pos is refereced from the centre of the screen
		mouseRayPos.x -= (GLOBAL.windowWidth / 2);
		mouseRayPos.y -= (GLOBAL.windowHeight / 2);
		mouseRayPos.scaleSelf((float) (1 / GLOBAL.getZOOM()));

		//mouseRayPos.addSelf(-screenCentre.x,-screenCentre.y, 0);
		mouseRayPos.rotateX((GLOBAL.rotateModelsX));
		mouseRayPos.rotateY((GLOBAL.rotateModelsY));

		mouseRayPos.addSelf(focusCentre);

		mouseRayDir.x = mouseRayDir.x - mouseRayPos.x;
		mouseRayDir.y = mouseRayDir.y - mouseRayPos.y;
		mouseRayDir.z = mouseRayDir.z - mouseRayPos.z;

		mouseRayDir.rotateX((GLOBAL.rotateModelsX));
		mouseRayDir.rotateY((GLOBAL.rotateModelsY));

		Ray3D ray = new Ray3D(mouseRayPos, mouseRayDir);

		Vec3D mousePos = null;

		if (GLOBAL.rotateModelsX == 0 && GLOBAL.rotateModelsY == 0
				&& plane.normal.x == 0 && plane.normal.y == 0)
			mousePos = new Vec3D(ray.x, ray.y, ray.z);

		//put these back in for 3d
		//	if(mousePos == null)	
		//		mousePos = plane.getIntersectionWithRay(ray);

		if (mousePos == null) {

			mouseRayDir = new Vec3D(0, 0, 1);
			mouseRayDir.x = mouseRayDir.x - mouseRayPos.x;
			mouseRayDir.y = mouseRayDir.y - mouseRayPos.y;
			mouseRayDir.z = mouseRayDir.z - mouseRayPos.z;

			mouseRayDir.rotateX((GLOBAL.rotateModelsX));
			mouseRayDir.rotateY((GLOBAL.rotateModelsY));

			ray = new Ray3D(mouseRayPos, mouseRayDir);
			plane.normal.z *= -1;
			//put these back in for 3d
			//	mousePos = plane.getIntersectionWithRay(ray);
		}

		if (GLOBAL.sketchChairs.getCurChair() != null
				&& GLOBAL.sketchChairs.getCurChair().rigidBody != null
				&& chairMatrix != null && mousePos != null) {
			float centreMouseDeltaX = mousePos.x
					- ((chairMatrix.m03) / GLOBAL.jBullet.scale);
			float centreMouseDeltaY = mousePos.y
					- ((chairMatrix.m13) / GLOBAL.jBullet.scale);
			float centreMouseDeltaZ = mousePos.z
					- ((chairMatrix.m23) / GLOBAL.jBullet.scale);
			centreMouseDeltaZ = 0;

			float newX = ((chairMatrix.m00) * centreMouseDeltaX)
					+ ((chairMatrix.m01) * centreMouseDeltaY)
					+ ((chairMatrix.m02) * centreMouseDeltaZ);
			float newY = (((chairMatrix.m10) * centreMouseDeltaX)
					+ ((chairMatrix.m11) * centreMouseDeltaY) + ((chairMatrix.m12) * centreMouseDeltaZ));
			float newZ = ((chairMatrix.m20) * centreMouseDeltaX)
					+ ((chairMatrix.m21) * centreMouseDeltaY)
					+ ((chairMatrix.m22) * centreMouseDeltaZ);

			newY = newY * -1;

			mousePos.x = newX + ((chairCentreOfMass.x) / GLOBAL.jBullet.scale);
			mousePos.y = newY + ((chairCentreOfMass.y) / GLOBAL.jBullet.scale);
			//mousePos.z = centreMouseDeltaZ + chairCentreOfMass.Z;
		}

		Vec2D intersect2D = null;
		if (mousePos != null) {
			intersect2D = new Vec2D(mousePos.x, mousePos.y);
			//intersect2D = new Vec2D(mousePoint.x, mousePoint.y);

		} else {
			intersect2D = new Vec2D(mousePoint.x, mousePoint.y);
		}
		if (intersect2D == null)
			intersect2D = new Vec2D(mousePoint.x, mousePoint.y);

		return intersect2D;

	}

	public Vec2D getPointTranslated(Vec2D mousePoint) {

		Vec2D mouseRayPos = new Vec2D(mousePoint.x, mousePoint.y); // this only works for planes perpendicular to the screen

		Vec2D focusCentre = new Vec2D(
				((GLOBAL.windowWidth / 2) - (float)GLOBAL.CAM_OFFSET_X),
				((GLOBAL.windowHeight / 2) - (float)GLOBAL.CAM_OFFSET_Y));

		mouseRayPos.x -= (GLOBAL.windowWidth / 2);
		mouseRayPos.y -= (GLOBAL.windowHeight / 2);
		mouseRayPos.scaleSelf((float) (1 / GLOBAL.getZOOM()));

		mouseRayPos.addSelf(focusCentre);
		return mouseRayPos;

	}

	Vec2D getPointTranslatedFromWorld(Vec2D mousePoint) {

		Vec2D mouseRayPos = new Vec2D(mousePoint.x, mousePoint.y); // this only works for planes perpendicular to the screen

		Vec2D focusCentre = new Vec2D(
				((GLOBAL.windowWidth / 2) - (float)GLOBAL.CAM_OFFSET_X),
				((GLOBAL.windowHeight / 2) - (float)GLOBAL.CAM_OFFSET_Y));

		mouseRayPos.subSelf(focusCentre);

		mouseRayPos.scaleSelf((float) GLOBAL.getZOOM());

		mouseRayPos.x += (GLOBAL.windowWidth / 2);
		mouseRayPos.y += (GLOBAL.windowHeight / 2);

		return mouseRayPos;

	}

	public void gotoWebsite(GUIEvent e) {
		/*
		String url = "http://www.sketchChair.com"; 
		try {
			// not compatible in JRE 1.5
			//java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
		} catch (IOException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		*/

	}

	public void hybernateChairToFileAuto(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

		String computername = functions.getComputerName();
		String currentDir = new File(".").getAbsolutePath();
		currentDir = currentDir.substring(0, currentDir.length() - 1);

		int id = 0;
		boolean nameFound = false;
		String location = "";

		while (!nameFound && id < 10000) {
			location = currentDir + "savedChairs\\hybernate\\" + computername
					+ "_chair-" + id + ".cha";
			File f = new File(location);

			if (!f.exists())
				nameFound = true;

			id++;
		}

		save(location);
		//System.out.println("saving to " + location);
		SETTINGS.chairSaveNum = id;
		GLOBAL.LAST_SAVED_LOCATION = location;

	}

	/**
	 * @return the editing
	 */
	public int isEditing() {
		return editing;
	}

	boolean isEditingTool(int TOOL) {

		if (TOOL == DRAW_TOOL || TOOL == SELECT_TOOL || TOOL == LEG_TOOL
				|| TOOL == SELECT_BEZIER_TOOL || TOOL == DRAW_PATH_TOOL
				|| TOOL == SCALE_TOOL || TOOL == MOVE_2D_TOOL)
			return true;
		else
			return false;

	}

	public void runAutomatedActions(GUIEvent e) {

		GLOBAL.skchAutomatic.start();

	}

	public void loadTemplateChair(GUIEvent e) {

		//if(GLOBAL.widgetLoad  == null){
		GLOBAL.widgetLoad = new WidgetLoad();
		GLOBAL.widgetLoad.setupGUI(GLOBAL.applet, GLOBAL.gui);
		//	}
		GLOBAL.widgetLoad.show();
	}

	public void mouseDown() {

		
		if (GLOBAL.gui.overComponent())
			GLOBAL.planesWidget.mousePressed(mouseX, mouseY);
		
		//let the gui handle any mouse down events
		if (GLOBAL.gui.overComponent() && GLOBAL.gui.hasFocus()) 
		return;
		
	
//Jump to front if we're in?
		
			if (mouseButton == UITools.MOUSE_LEFT
					&& isEditingTool(this.getCurrentTool()))
				this.camJumpFront(null);
			
			
			

			for (Clickable obj : this.clickables) {
				obj.mousePressed();
			}

			
			
			
			
			
			
			//model manip!
			if (this.getCurrentTool() == UITools.MOVE_OBJECT
					|| this.SketchTools.getCurrentTool() == SketchTools.LEG_TOOL
					|| this.SketchTools.getCurrentTool() == SketchTools.DRAW_TOOL
					|| this.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL
					&& !GLOBAL.gui.overComponent()
					&& !GLOBAL.sketchChairs.getCurChair().overSelectPoint(
							GLOBAL.uiTools.mouseX, GLOBAL.uiTools.mouseY)) {
				Vec2D mousePos = this.getPointTranslated(new Vec2D(this.mouseX,
						this.mouseY));
				GLOBAL.jBullet.mouseDragged(mousePos.x, mousePos.y);
			}

			if ((GLOBAL.uiTools.getCurrentTool() == UITools.SCALE_TOOL)
					&& !GLOBAL.gui.overComponent()) {
				//GLOBAL.person.dragScale(mouseX,mouseX);	
			}

			// middle click
			if (mouseButton == UITools.MOUSE_RIGHT
					|| this.getCurrentTool() == UITools.MOVE_CAM_TOOL) {

				if (SETTINGS.render_chairs
						&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT) {
					
					if(this.prevMouseWasMove){
						
					moveView((UI.mouseX - UI.pmouseX)
							* (float)(1 / GLOBAL.ZOOM),
							(UI.mouseY - UI.pmouseY)
							* (float)(1 / GLOBAL.ZOOM));			
					}else{
						this.prevMouseWasMove = true;
					}
					
					
					}

				
				
				if (GLOBAL.uiTools.currentView == UITools.VIEW_SHAPE_PACK) {
					GLOBAL.shapePack.CAM_OFFSET_X += (UI.mouseX - UI.pmouseX)
							* (1 / GLOBAL.shapePack.ZOOM);
					GLOBAL.shapePack.CAM_OFFSET_Y += (UI.mouseY - UI.pmouseY)
							* (1 / GLOBAL.shapePack.ZOOM);

				}
				
				
				
			}

			if (!GLOBAL.gui.overComponent()) {
				if (this.getCurrentTool() == UITools.ZOOM_CAM_TOOL) {

					if (SETTINGS.render_chairs
							&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT){
						
						this.zoomView(((UI.mouseY - UI.pmouseY) * .01f));
						
						
					}

					if (SETTINGS.render_chairs
							&& GLOBAL.uiTools.currentView == UITools.VIEW_SHAPE_PACK) {
						GLOBAL.shapePack.zoomView((UI.mouseY - UI.pmouseY) * .01f, this.mouseX, this.mouseY) ;

					}

				}

				if (this.getCurrentTool() == UITools.ROTATE_CAM_TOOL
						|| mouseButton == UITools.MOUSE_MIDDLE) {
					if (SETTINGS.render_chairs
							&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT) {
						GLOBAL.rotateModelsY -= (UI.pmouseX - UI.mouseX) / 90f;
						GLOBAL.rotateModelsX += (UI.pmouseY - UI.mouseY) / 90f;
					}
				}

				if (this.getCurrentTool() == UITools.SELECT_TOOL
						&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT) {
					updateVecMove();
				}

			}

			if (this.getCurrentTool() != UITools.ROTATE_CAM_TOOL && GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT)
				GLOBAL.person.mouseDown(mouseX, mouseY);

			Vec2D mousePos = this.getPointTranslated(new Vec2D(this.mouseX,
					this.mouseY));

			GLOBAL.measuretTool.mousePressed(mousePos.x, mousePos.y);

		

	}

	public void mouseDragged() {
		
		
	
		
		
		if (!GLOBAL.gui.overComponent() && !GLOBAL.gui.hasFocus() && !GLOBAL.gui.clickStartedOn()&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT) {

			for (Clickable obj : this.clickables) {
				obj.mouseDragged();
			}
			
			
			
			GLOBAL.sketchChairs.mouseDragged(mouseX, mouseY);

			Vec2D MousePos = this.getPointTranslated(new Vec2D(this.mouseX,this.mouseY));

			GLOBAL.environments.mouseDragged(MousePos.x, MousePos.y);
		}

		if (GLOBAL.gui.overComponent())
			GLOBAL.planesWidget.mouseDragged(mouseX, mouseY);

	}

	void mousePressed() {


		//see if this is a fast press
		this.mousePressedTime = GLOBAL.applet.millis();

		if (!GLOBAL.gui.overComponent() && !SETTINGS.EXPERT_MODE
				&& GLOBAL.uiTools.currentView == GLOBAL.uiTools.VIEW_SHAPE_PACK)
			this.toggleView(null);
		

		//unselect auto rotate
		if (GLOBAL.autoRotate && !GLOBAL.gui.overComponent()) {
			GLOBAL.autoRotate = false;
			GLOBAL.rotateModelsY = 0;

		}

		
		//NOT OVER GUI 
		//IF a press starts over GUI and drags outside it's included as still over GUI
		if (!GLOBAL.gui.overComponent() && !GLOBAL.gui.hasFocus() && !GLOBAL.gui.clickStartedOn()&& GLOBAL.uiTools.currentView == UITools.VIEW_CHAIR_EDIT) {
			GLOBAL.undo.addChair(GLOBAL.sketchChairs.getCurChair().copy());

			for (Clickable obj : this.clickables) {
				obj.mouseClicked();
			}

			Vec2D MousePosPerson = this.getPointTranslated(new Vec2D(
					this.mouseX, this.mouseY));
			GLOBAL.person.mouseClicked(MousePosPerson.x, MousePosPerson.y);

			if (this.getCurrentTool() == UITools.SCALE_TOOL
					&& GLOBAL.sketchChairs.getCurChair() != null) {
				GLOBAL.sketchChairs.getCurChair().mousePressed(
						MousePosPerson.x, MousePosPerson.y);
			}

			if (this.getCurrentTool() == UITools.MOVE_2D_TOOL
					&& GLOBAL.sketchChairs.getCurChair() != null) {
				GLOBAL.sketchChairs.getCurChair().mousePressed(
						MousePosPerson.x, MousePosPerson.y);
			}

			if (this.getCurrentTool() == UITools.SELECT_TOOL
					|| this.SketchTools.getCurrentTool() == SketchTools.SELECT_BEZIER_TOOL
					&& !GLOBAL.person.clickedOnPerson) {
				//getVecOver();
				if (GLOBAL.sketchChairs.getCurChair() != null) {
					GLOBAL.sketchChairs.getCurChair().mousePressed(
							MousePosPerson.x, MousePosPerson.y);
				}
			}

			if (this.getCurrentTool() == UITools.MOVE_OBJECT
					|| GLOBAL.person.clickedOnPerson) {
				Vec2D mousePos = this.getPointTranslated(new Vec2D(this.mouseX,
						this.mouseY));
				GLOBAL.jBullet.mouseDown(mousePos.x, mousePos.y);
			}

			if (this.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL
					&& GLOBAL.sketchChairs.getCurChair() != null
					&& GLOBAL.sketchChairs.getCurChair().countSelectedNodes() <= 0) {
				Vec2D mousePos = this.getPointTranslated(new Vec2D(this.mouseX,
						this.mouseY));

				if (GLOBAL.jBullet.physics_on)
					GLOBAL.jBullet.mouseDown(mousePos.x, mousePos.y);
			}

			if (this.getCurrentTool() == UITools.SELECT_TOOL
					&& GLOBAL.sketchChairs.getCurChair() == null) {
				Vec2D mousePos = this.getPointTranslated(new Vec2D(this.mouseX,
						this.mouseY));
				GLOBAL.jBullet.mouseDown(mousePos.x, mousePos.y);
			}

			if (this.getCurrentTool() == UITools.ADD_DOLL_TOOL) {
				/*new SittingDoll(GLOBAL.jBullet.myWorld, new Vector3f(
						GLOBAL.applet.mouseX, GLOBAL.applet.mouseY, 0), 1);
				selectedVec = null;
				selectedVecPlane = null;
				*/
			}

			Vec2D MousePos = this.getPointTranslated(new Vec2D(this.mouseX,
					this.mouseY));

			if (!GLOBAL.sketchChairs.getCurChair().mouseOver(MousePos.x,
					MousePos.y))
				GLOBAL.environments.mousePressed(MousePos.x, MousePos.y);

			GLOBAL.sketchChairs.mousePressed(this.mouseX, this.mouseY);

			//	if(	this.currentView == UITools.VIEW_SHAPE_PACK && this.mouseButton  == this.MOUSE_LEFT)
			//		this.changeView(null);

		}

		if (GLOBAL.gui.overComponent())
			GLOBAL.planesWidget.mouseClicked(mouseX, mouseY);
		
		
		//GLOBAL.undo.setMouseUpChair(GLOBAL.sketchChairs.getCurChair().copy());
		//if(GLOBAL.undo.getMouseUpChair() != null)GLOBAL.undo.getMouseUpChair().build();
		

	}

	void mouseReleased() {
		
		
		if(GLOBAL.uiTools.currentView != UITools.VIEW_CHAIR_EDIT)
			return;
		
		//
		this.prevMouseWasMove = false;
		
		
		if(!waitingForSingleClick && GLOBAL.applet.millis() - this.mousePressedTime < SETTINGS.MOUSE_PRESSED_MIN_TIME)
		this.waitingForSingleClick = true;
		else
			waitingForSingleClick = false;
		
		this.mouseSingleClickTime = GLOBAL.applet.millis();
		/*
		//see if this is a fast press
		if (GLOBAL.applet.millis() - this.mousePressedTime < SETTINGS.MOUSE_CLICKED_MIN_TIME) {

			if (GLOBAL.applet.millis() - this.mouseSingleClickTime < SETTINGS.MOUSE_CLICKED_MIN_TIME*2)
				this.mouseDoubleClick();
			else
				this.mouseSingleClick();

			this.mouseSingleClickTime = GLOBAL.applet.millis();
		*/

		if (GLOBAL.resetting)
			return;

		GLOBAL.person.mouseReleased(mouseX, mouseY);

		GLOBAL.measuretTool.mouseReleased(mouseX, mouseY);

		if (this.getCurrentTool() == UITools.ROTATE_CAM_TOOL
				&& !SETTINGS.EXPERT_MODE)
			this.camJumpFront(null);

		if (SETTINGS.EXPERT_MODE && GLOBAL.gui.overComponent())
			GLOBAL.planesWidget.mouseReleased(mouseX, mouseY);

		if (!GLOBAL.gui.overComponent())
			GLOBAL.sketchChairs.mouseReleased(mouseX, mouseY);

		if (!GLOBAL.gui.overComponent())
			GLOBAL.environments.mouseReleased(mouseX, mouseY);

		

		if (!GLOBAL.gui.overComponent()) {
			
			
			
			
			for (Clickable obj : this.clickables) {
			//	obj.mouseReleased();
			}
			
			
		}

		if (selectedVec != null && selectedVecPlane != null) {
			GLOBAL.sketchChairs.getCurChair().selectedPlanes
					.buildCurrentSketch();
			selectedVecPlane.getSketch().buildOutline();
			selectedVecPlane.getSketch().getSketchShapes().sketchOutlines
					.optimize();
			selectedVec = null;
			this.selectedVecPlane.getSketch().getSketchShapes().renderShapes = false;
			this.selectedShape.offset();
		}

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			//	GLOBAL.sketchChairs.curChair.updateCollisionShape();
		}

		if (!SETTINGS.EXPERT_MODE) {
			GLOBAL.rotateModelsX = 0;
			GLOBAL.rotateModelsY = 0;
			//BASIC MODE EXHIBITION MODE
			if (this.SketchTools.getCurrentTool() != SketchTools.LEG_TOOL)
				GLOBAL.sketchChairs.getCurChair().selectedPlanes
						.add(GLOBAL.sketchChairs.getCurChair()
								.getSlicePlanesY());
		}

		//rebuild cross selections widget every click
		if (SETTINGS.EXPERT_MODE)
			GLOBAL.slicesWidget
					.rebuild(GLOBAL.sketchChairs.getCurChair().crossSliceSelections);

		
		GLOBAL.undo.setMouseUpChair(GLOBAL.sketchChairs.getCurChair());


		
	}

	void mouseSingleClick() {


		if(GLOBAL.uiTools.currentView != UITools.VIEW_CHAIR_EDIT)
			return;
		

		//Select planes with the select tool
		if ((!GLOBAL.gui.overComponent() && 
				this.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL)
				|| GLOBAL.previewWidget.isMouseOver()) {
			
			
			if(GLOBAL.uiTools.isSideView() && !GLOBAL.previewWidget.isMouseOver()){
				GLOBAL.planesWidget.selectAllPlanes(null);
				GLOBAL.gui.reRender();
			return;	
			}
			

			Object obj = PickBuffer.getInstance().getObject(mouseX, mouseY);
			if (obj instanceof SlicePlane) {
				SlicePlane splane = (SlicePlane) obj;

				
				if (splane.getCrossSliceSelection() == null) {
					GLOBAL.planesWidget.planeClickedOn(splane);
				} else {
					if (GLOBAL.designToolbarAdvanced != null)
						GLOBAL.designToolbarAdvanced.selectTab("slices");

					GLOBAL.slicesWidget.selectSlice(splane
							.getCrossSliceSelection());

				}
				
				GLOBAL.previewWidget.rebuildPatternPreview();
			} else {
				if(!GLOBAL.previewWidget.isMouseOver()){
				GLOBAL.slicesWidget.unselectAll();
				GLOBAL.planesWidget.unselectAll();
				}
			}
		}
		
		
		//IF no planes are selected we can select one with the slat tools
		
		if((this.getCurrentTool() == UITools.SLICES_GROUP_SLICES ||
				this.getCurrentTool() == UITools.SLICES_SINGLE_SLAT ||
				this.getCurrentTool() == UITools.SLICES_SINGLE_SLICE ||
				this.getCurrentTool() == UITools.SLICES_SLATSLICE_GROUP) &&
				(GLOBAL.sketchChairs.getCurChair() != null &&
				GLOBAL.sketchChairs.getCurChair().selectedPlanes.size() == 0)
				){
			Object obj = PickBuffer.getInstance().getObject(mouseX, mouseY);
			if (obj instanceof SlicePlane) {
				SlicePlane splane = (SlicePlane) obj;

				
				if (splane.getCrossSliceSelection() == null) {
					GLOBAL.planesWidget.planeClickedOn(splane);
					
				}
			
		}
		}
		
		GLOBAL.undo.setMouseUpChair(GLOBAL.sketchChairs.getCurChair());
		
		//LOGGER.debug("mouseSingleClick()"+GLOBAL.sketchChairs.getCurChair().selectedPlanes.size());
		GLOBAL.gui.reRender();

	}

	void mouseDoubleClick() {
		
		if (!GLOBAL.gui.overComponent())
			GLOBAL.sketchChairs.mouseDoubleClick(mouseX, mouseY);
		
		GLOBAL.undo.setMouseUpChair(GLOBAL.sketchChairs.getCurChair());

	}

	public void newChair(GUIEvent e) {
		this.hybernateChairToFileAuto(e);
	}

	public void openChairFromFile(GUIEvent e) {
	
			GLOBAL.applet.selectInput("select design file.", "openChairFromFileCallback", null, this);
		      	
	}
	
	
	public void openChairFromFileCallback(File file) {

		 GLOBAL.loadChairLocation = file.getAbsolutePath();

	}
	

	public void openChairFromFileAuto(GUIEvent e) {
		// in response to a button click:

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.killAll();

		String computername = functions.getComputerName();
		String currentDir = new File(".").getAbsolutePath();
		currentDir = currentDir.substring(0, currentDir.length() - 1);

		int id = SETTINGS.chairSaveNum;
		boolean nameFound = false;
		String location = null;

		while (!nameFound && id >= 0) {
			location = currentDir + "savedChairs\\" + computername + "_chair-"
					+ id + ".cha";
			File f = new File(location);

			if (f.exists()) {
				nameFound = true;

			} else {
				id--;
			}

		}

		LOGGER.info("Loading chair from: " + location);

		SETTINGS.chairSaveNum = (id - 1);
		if (location != null)
			load(location);
		else
			SETTINGS.chairSaveNum = 2000;
	}

	public void openEnvironmentFromFile(GUIEvent e) {
		GLOBAL.environments.openEnvironmentFromFile(e);
	}

	public void pasteChair() {
		LOGGER.info("paste");

		if (GLOBAL.copyOfChair != null) {
			GLOBAL.sketchChairs.killAll();
			GLOBAL.sketchChairs.add(GLOBAL.copyOfChair);
			GLOBAL.sketchChairs.getCurChair().build();
		}

	}

	public void physicsPause(GUIEvent e) {
		GLOBAL.jBullet.physics_on = !GLOBAL.jBullet.physics_on;
	}

	public void physicsPlay(GUIEvent e) {
		GLOBAL.jBullet.physics_on = !GLOBAL.jBullet.physics_on;
	}
	
	public void physicsPlayPause(GUIEvent e) {

		if (!GLOBAL.jBullet.physics_on) {
			GLOBAL.jBullet.physics_on = true;
		} else {
			GLOBAL.jBullet.physics_on = false;
		
		}
		}

	public void physicsRewind(GUIEvent e) {
		GLOBAL.jBullet.resetCollisons();
		GLOBAL.jBullet.physics_on = false;
		GLOBAL.person.resetPhysics();
		
		if(GLOBAL.sketchChairs.getCurChair() != null)
		GLOBAL.sketchChairs.getCurChair().resetPhysics();
	}

	public void print(GUIEvent e) {
		LOGGER.info("PRINT");

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			//GLOBAL.shapePack.empty();
			//GLOBAL.sketchChairs.getCurChair().addToShapePack();
			//GLOBAL.shapePack.build();

			String currentDir = new File(".").getAbsolutePath();
			currentDir = currentDir.substring(0, currentDir.length() - 1);

			int id = 0;
			boolean nameFound = false;
			String location = "";
			location = currentDir + "print.pdf";

			GLOBAL.pdfSaveLocation = location;
			GLOBAL.savePDF = true;
			GLOBAL.autoOpenPDF = true;
		}
	}

	void printOpen(String fileLoc) {
		// not compatible in JRE 1.5 
		
		 	    Desktop desktop = null;
		 	    // Before more Desktop API is used, first check 
		 	    // whether the API is supported by this particular 
		 	    // virtual machine (VM) on this particular host.
		 	    if (Desktop.isDesktopSupported()) {
		 	        desktop = Desktop.getDesktop();
		 	        File file = new File(fileLoc);
		 	        try {
						desktop.open(file);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		 	    }
		

	}

	public void redo(GUIEvent e) {
		//	GLOBAL.undo.undo();

	}

	

	
	
	public void removeSelectedPlanes(GUIEvent e) {
		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().removeSelectedPlanes();
	}

	void render(PGraphics g) {

		if(GLOBAL.gui.overComponent()){
			ModalGUI.setCursor(GLOBAL.applet,SELECT_TOOL_CURSOR,15,9);
			return;
		}
		
		
		
		//are we rotating? maybe we should set a flag for this instead of testing the buttons?
		if(this.mouseDown && this.mouseButton == UITools.MOUSE_MIDDLE){
			ModalGUI.setCursor(GLOBAL.applet,ROTATE_CAM_TOOL_CURSOR,17,16);
			this.hasCursorControl = true;

			return;
		}
		
		
		if(this.mouseDown && this.mouseButton == UITools.MOUSE_RIGHT){
			ModalGUI.setCursor(GLOBAL.applet,MOVE_CAM_TOOL_CURSOR,16,16);
			this.hasCursorControl = true;

			return;
		}
		
		

		g.fill(255);
		g.ellipseMode(PApplet.CENTER);

		Vec2D physicsMousePos = this.getPointTranslated(new Vec2D(this.mouseX,
				this.mouseY));

		//
		if ((this.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL 
				|| this.SketchTools.getCurrentTool() == SketchTools.DRAW_TOOL)
				&& GLOBAL.person.mouseOver(physicsMousePos.x, physicsMousePos.y)) {
			ModalGUI.setCursor(GLOBAL.applet,MOVE_OBJECT_CURSOR, 16,16);
			return;
		}

		if (this.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL) {
			
			
			
			if (GLOBAL.sketchChairs.getCurChair() != null) {

				if (!GLOBAL.sketchChairs.getCurChair().overSelectPoint(mouseX,
						mouseY)
						&& GLOBAL.sketchChairs.getCurChair().mouseOver(
								physicsMousePos.x, physicsMousePos.y)) {
					
					ModalGUI.setCursor(GLOBAL.applet,MOVE_OBJECT_CURSOR, 16,16);

					this.hasCursorControl = true;
					return;

				}

				

			}
			
		}
		
		
		if (this.getCurrentTool() == UITools.MOVE_CAM_TOOL) {
			
			
			ModalGUI.setCursor(GLOBAL.applet,MOVE_CAM_TOOL_CURSOR,16,16);

			
			this.hasCursorControl = true;
			return;
		} else if (this.getCurrentTool() == UITools.ROTATE_CAM_TOOL) {
			ModalGUI.setCursor(GLOBAL.applet,ROTATE_CAM_TOOL_CURSOR,16,16);
			this.hasCursorControl = true;
			return;
		} else if (this.getCurrentTool() == UITools.ZOOM_CAM_TOOL) {
			ModalGUI.setCursor(GLOBAL.applet,ZOOM_CAM_TOOL_CURSOR,15,14);
			this.hasCursorControl = true;
			return;
		} else if (this.getCurrentTool() == UITools.SLICES_GROUP_SLICES ||
				this.getCurrentTool() == UITools.SLICES_SINGLE_SLAT ||
				this.getCurrentTool() == UITools.SLICES_SINGLE_SLICE ||
				this.getCurrentTool() == UITools.SLICES_SLATSLICE_GROUP ||
						this.getCurrentTool() == UITools.SLICES_EDIT) {
			
			
			if(sliceToolMode ==  UITools.SLICE_EDIT_MODE_ADD){
				ModalGUI.setCursor(GLOBAL.applet,CURSOR_ADD_SLICE,5,7);
			this.hasCursorControl = true;
			return;
			}
			
			if(sliceToolMode ==  UITools.SLICE_EDIT_MODE_POS){
				ModalGUI.setCursor(GLOBAL.applet,CURSOR_EDIT_SLICE_POS,5,7);
				this.hasCursorControl = true;
				return;
				}
			
			if(sliceToolMode ==  UITools.SLICE_EDIT_MODE_SPACING){
				ModalGUI.setCursor(GLOBAL.applet,CURSOR_EDIT_SLICE_SPACING,5,7);
				this.hasCursorControl = true;
				return;
				}
			
			
		} 
		//CURSOR_EDIT_SLICE_POS
		
		

		this.hasCursorControl = false;
		this.SketchTools.render(g);
  
		/*
		if (!GLOBAL.gui.overComponent() || this.selectCooldown > 0) {

			if (this.getCurrentTool() == DRAW_TOOL) {

				g.noFill();
				g.stroke(100, 100, 100);
				//LOGGER.info("SET CURSOR D");

				if(this.loadedCursor != DRAW_TOOL){
				GLOBAL.applet.cursor(UITools.DRAW_TOOL_CURSOR, 1,1);
				this.loadedCursor = DRAW_TOOL;
				}
				return;
				} else if (this.getCurrentTool() == LEG_TOOL) {
				
				if(this.loadedCursor != DRAW_TOOL){
					GLOBAL.applet.cursor(UITools.DRAW_TOOL_CURSOR, 1,1);
				this.loadedCursor = DRAW_TOOL;
				}

			} else if (this.getCurrentTool() == SELECT_TOOL) {
				
				if(this.loadedCursor != SELECT_TOOL){
				GLOBAL.applet.cursor(UITools.SELECT_TOOL_CURSOR, 1,1);
				this.loadedCursor = SELECT_TOOL;
				}
				
				//g.image(UITools.SELECT_TOOL_CURSOR, mouseX - 10, mouseY - 8);
			} else if (this.getCurrentTool() == ADD_DOLL_TOOL) {
				if(this.loadedCursor != ADD_DOLL_TOOL){
				GLOBAL.applet.cursor(ADD_DOLL_TOOL_CURSOR, 1,1);
				this.loadedCursor = ADD_DOLL_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.MOVE_CAM_TOOL) {
				if(this.loadedCursor != MOVE_CAM_TOOL){
				GLOBAL.applet.cursor(MOVE_CAM_TOOL_CURSOR, 1,1);
				this.loadedCursor = MOVE_CAM_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.ROTATE_CAM_TOOL) {
				if(this.loadedCursor != ROTATE_CAM_TOOL){
					GLOBAL.applet.cursor(ROTATE_CAM_TOOL_CURSOR, 1,1);
				this.loadedCursor = ROTATE_CAM_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.ZOOM_CAM_TOOL) {
				if(this.loadedCursor != ZOOM_CAM_TOOL){
					GLOBAL.applet.cursor(ZOOM_CAM_TOOL_CURSOR, 1,1);
				this.loadedCursor = ZOOM_CAM_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.LEG_TOOL) {
				if(this.loadedCursor != LEG_TOOL){
					GLOBAL.applet.cursor(LINE_TOOL_CURSOR, 1,1);
				this.loadedCursor = LEG_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.SCALE_PERSON_TOOL) {
				if(this.loadedCursor != SCALE_PERSON_TOOL){
				GLOBAL.applet.cursor(ADD_DOLL_TOOL_CURSOR, 1,1);
				this.loadedCursor = SCALE_PERSON_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.MOVE_OBJECT) {
				if(this.loadedCursor != MOVE_OBJECT){
					GLOBAL.applet.cursor(ADD_DOLL_TOOL_CURSOR, 1,1);
				this.loadedCursor = MOVE_OBJECT;
				}
			} else if (this.getCurrentTool() == UITools.SCALE_TOOL) {
				if(this.loadedCursor != SCALE_TOOL){
					GLOBAL.applet.cursor(SCALE_TOOL_CURSOR, 1,1);
				this.loadedCursor = SCALE_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.MEASURE_TOOL) {
				if(this.loadedCursor != MEASURE_TOOL){
					GLOBAL.applet.cursor(MEASURE_TOOL_CURSOR, 1,1);
				this.loadedCursor = MEASURE_TOOL;
				}
			} else if (this.getCurrentTool() == UITools.MOVE_2D_TOOL) {
				if(this.loadedCursor != MOVE_2D_TOOL){
					GLOBAL.applet.cursor(MOVE_CAM_TOOL_CURSOR, 1,1);
				this.loadedCursor = MOVE_2D_TOOL;
				}
			} else {
				if(this.loadedCursor != SELECT_TOOL){
					GLOBAL.applet.cursor(UITools.SELECT_TOOL_CURSOR, 1,1);
					this.loadedCursor = SELECT_TOOL;
				}

				//
				// g.fill(255,0,0);
				// g.ellipse(UI.mouseX , UI.mouseY ,2,2);
			}
		} else {


			if(this.loadedCursor != SELECT_TOOL){
			//	GLOBAL.applet.cursor(UITools.SELECT_TOOL_CURSOR, 1,1);
			//	this.loadedCursor = SELECT_TOOL;
			}
			
		}
*/
		// g.image(this.pickBuffer,0,0);
	}

	void renderGrid(PGraphics g) {

		if (this.useGrid && this.gridWidth * GLOBAL.getZOOM() > 2) {

			g.stroke(SETTINGS.GRID_MAJOR_LINE);
			g.strokeWeight(SETTINGS.GRID_MAJOR_LINE_WEIGHT);
			//float offset_x =  GLOBAL.CAM_OFFSET_X % (this.gridWidth);

			//calculate the number of grid squares between the centre of the screen and the edge to  see where our grid should start
			double offset_x = (GLOBAL.windowWidth / 2)
					- (Math.floor((GLOBAL.windowWidth / 2)
							/ (this.gridWidth * GLOBAL.getZOOM()))
							* this.gridWidth * GLOBAL.getZOOM());
			offset_x = (((GLOBAL.CAM_OFFSET_X * GLOBAL.getZOOM()) + offset_x) % (this.gridWidth * GLOBAL
					.getZOOM())) - this.gridWidth * GLOBAL.getZOOM();

			for (float x = (float) offset_x; x < GLOBAL.windowWidth; x += this.gridWidth
					* GLOBAL.getZOOM()) {

				g.stroke(SETTINGS.GRID_MAJOR_LINE);
				g.strokeWeight(SETTINGS.GRID_MAJOR_LINE_WEIGHT);

				g.line(x, 0, x, GLOBAL.windowHeight);

				if (this.gridWidth * GLOBAL.getZOOM() > minorGridnumber * 5) {
					g.stroke(SETTINGS.GRID_MINOR_LINE);
					g.strokeWeight(SETTINGS.GRID_MINOR_LINE_WEIGHT);

					for (float x2 = (float) (x + (this.gridWidth * GLOBAL.getZOOM())
							/ minorGridnumber); x2 < x + this.gridWidth
							* GLOBAL.getZOOM(); x2 += (this.gridWidth * GLOBAL
							.getZOOM()) / minorGridnumber) {
						g.line(x2, 0, x2, GLOBAL.windowHeight);
					}
				}

			}

			double offset_y = (GLOBAL.windowHeight / 2)
					- (Math.floor((GLOBAL.windowHeight / 2)
							/ (this.gridHeight * GLOBAL.getZOOM()))
							* this.gridHeight * GLOBAL.getZOOM());
			offset_y = (((GLOBAL.CAM_OFFSET_Y * GLOBAL.getZOOM()) + offset_y) % (this.gridHeight * GLOBAL
					.getZOOM())) - this.gridHeight * GLOBAL.getZOOM(); // Y offset

			for (float y = (float) offset_y; y < GLOBAL.windowHeight; y += this.gridHeight
					* GLOBAL.getZOOM()) {
				g.stroke(SETTINGS.GRID_MAJOR_LINE);
				g.strokeWeight(SETTINGS.GRID_MAJOR_LINE_WEIGHT);

				g.line(0, y, GLOBAL.windowWidth, y);

				if (this.gridWidth * GLOBAL.getZOOM() > minorGridnumber * 5) {
					g.stroke(SETTINGS.GRID_MINOR_LINE);
					g.strokeWeight(SETTINGS.GRID_MINOR_LINE_WEIGHT);

					for (float y2 = (float) (y + (this.gridHeight * GLOBAL.getZOOM())
							/ minorGridnumber); y2 < y + this.gridWidth
							* GLOBAL.getZOOM(); y2 += (this.gridHeight * GLOBAL
							.getZOOM()) / minorGridnumber) {
						g.line(0, y2, GLOBAL.windowWidth, y2);
					}
				}

			}

		}
	}

	public void reset(GUIEvent e) {

		GLOBAL.forceResize = true;

		GLOBAL.setZOOM(.5f);
		GLOBAL.CAM_OFFSET_X = -400;
		GLOBAL.CAM_OFFSET_Y = (float) -((700 - GLOBAL.windowHeight) + 900);
		GLOBAL.autoRotate = false;
		//GLOBAL.forceResize = true;
		/*
		GLOBAL.resetting = true; 
		
		if(!SETTINGS.APPLET_MODE){
		this.saveChairToFileAuto(null);
		this.captureScreen(null);
		GLOBAL.applet.draw();
		}
		*/
		//GLOBAL.gui.reset();
		//	GLOBAL.applet.removeAll();
		//GLOBAL.person.resetPhysics();
		//GLOBAL.forceReset = true;

		this.currentView = UITools.VIEW_CHAIR_EDIT;
		SETTINGS.EXPERT_MODE = false;
		GLOBAL.displayIntroPanel = true;
		GLOBAL.gui.reload();
		GLOBAL.gui.reset();

		if (SETTINGS.EXPERT_MODE)
			UI.setupGUITabsExpert(GLOBAL.applet, GLOBAL.gui);

		if (!SETTINGS.EXPERT_MODE)
			UI.setupGUITabsBasic(GLOBAL.applet, GLOBAL.gui);

		GLOBAL.sketchChairs.killAll();
		GLOBAL.jBullet = new jBullet();
		GLOBAL.person = new ergoDoll(GLOBAL.jBullet.myWorld, new Vector3f(-80,
				-10, 0), 1f);
		this.physicsRewind(null);
		//GLOBAL.applet.setup();	
		//GLOBAL.resetting = false;
		SETTINGS_SKETCH.plane_thickness = SETTINGS_SKETCH.plane_thickness_default;

	}

	public void saveChairToFile(GUIEvent e) {
		GLOBAL.saveChairToFile = true;
	}

	public void saveChairToFile() {
		if (SETTINGS.APPLET_MODE) {

			try {
				FileSaveService save = (FileSaveService) ServiceManager
						.lookup("javax.jnlp.FileSaveService");

				Element root = new Element("SketchChairDoc");
				root.addAttribute(new Attribute("version", String
						.valueOf(SETTINGS.version)));
				root.appendChild(GLOBAL.sketchChairs.getCurChair().toXML());

				Document doc = new Document(root);
				//   outXML = ;// new FileOutputStream(name+".xml");

				ByteArrayOutputStream outXML = new ByteArrayOutputStream();
				Serializer serializer = new Serializer(outXML, "ISO-8859-1");
				serializer.write(doc);

				FileContents fc = save.saveFileDialog(null,
						new String[] { "chair" }, new ByteArrayInputStream(
								outXML.toByteArray()), null);

			} catch (Exception ex) {
				LOGGER.error("exception: " + ex);
			}

		} else {
			//Create a file chooser
			GLOBAL.applet.selectOutput("select design file.", "saveChairToFileCallback", null, this);
		}
			 
			 

	}
	
	
	public void savePattern(GUIEvent e) {
		this.savePatternToFile();
	}
	
	public void savePatternToFile() {
		if (SETTINGS.APPLET_MODE) {

			try {
				FileSaveService save = (FileSaveService) ServiceManager
						.lookup("javax.jnlp.FileSaveService");

				Element root = new Element("SketchChairDoc");
				root.addAttribute(new Attribute("version", String
						.valueOf(SETTINGS.version)));
				root.appendChild(GLOBAL.sketchChairs.getCurChair().toXML());

				Document doc = new Document(root);
				//   outXML = ;// new FileOutputStream(name+".xml");

				ByteArrayOutputStream outXML = new ByteArrayOutputStream();
				Serializer serializer = new Serializer(outXML, "ISO-8859-1");
				serializer.write(doc);

				FileContents fc = save.saveFileDialog(null,
						new String[] { "chair" }, new ByteArrayInputStream(
								outXML.toByteArray()), null);

			} catch (Exception ex) {
				LOGGER.error("exception: " + ex);
			}

		} else {
			//Create a file chooser

			GLOBAL.applet.selectOutput("select design file.", "savePatternToFileCallback", null, this);
		}
			 
			 

	}
	
	
	
	
	public void saveChairToFileCallback(File file) {
		GLOBAL.saveChairLocation = file.getAbsolutePath();
		
		if(!GLOBAL.saveChairLocation.endsWith(".skchr"))
			GLOBAL.saveChairLocation += ".skchr";
	}
	
	public void savePatternToFileCallback(File file) {
		GLOBAL.savePatternLocation = file.getAbsolutePath();
		
		if(!GLOBAL.savePatternLocation.endsWith(".svg"))
			GLOBAL.savePatternLocation += ".svg";
		
	}
	
	
	public void saveChairToFileAuto(GUIEvent e) {
		GLOBAL.saveChairToFileAuto = true;
		
		
		
	}

	public void saveChairToFileAuto() {

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			
			if(GLOBAL.sketchChairs.getCurChair().localSavelocation == null){
				this.saveChairToFile();
				return;
				
			}
			
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

			String location = "";
			int id = 0;

			if (GLOBAL.sketchChairs.getCurChair().localSavelocation != null) {
				location = GLOBAL.sketchChairs.getCurChair().localSavelocation;
			} else {

				String computername = functions.getComputerName();
				String currentDir = new File(".").getAbsolutePath();
				currentDir = currentDir.substring(0, currentDir.length() - 1);

				boolean nameFound = false;

				while (!nameFound && id < 10000) {
					location = currentDir + "savedChairs\\chair-" + id + ".xml";
					GLOBAL.sketchChairs.getCurChair().localSavelocation = location;
					File f = new File(location);

					if (!f.exists())
						nameFound = true;

					id++;
				}
			}

			save(location);
			//System.out.println("saving to " + location);
			SETTINGS.chairSaveNum = id;
			GLOBAL.LAST_SAVED_LOCATION = location;
		}
	}

	public void saveCraftRobo(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

		//	GLOBAL.shapePack.build();
		GLOBAL.shapePack.printToCraftRobo();

	}

	public void saveModelDxf(GUIEvent e) {

		GLOBAL.dxfCapture = true;

		if (SETTINGS.APPLET_MODE) {

			FileSaveService save;
			try {
				save = (FileSaveService) ServiceManager
						.lookup("javax.jnlp.FileSaveService");
				GLOBAL.shapePack.build();
				FileContents fc = save.saveFileDialog(null,
						new String[] { "pdf" }, new ByteArrayInputStream(
								GLOBAL.shapePack.getPDFBuffered(GLOBAL.applet)
										.toByteArray()), null);

			} catch (UnavailableServiceException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		} else {
			GLOBAL.applet.selectOutput("select design file.", "saveModelDxfCallback", null, this);

		}
	}
	
	public void saveModelDxfCallback(File file) {
		GLOBAL.dxfLocation = file.getAbsolutePath();
		GLOBAL.dxfCapture = true;
	}

	public void savePatternDXF(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

		if (SETTINGS.APPLET_MODE) {

			FileSaveService save;
			try {
				save = (FileSaveService) ServiceManager
						.lookup("javax.jnlp.FileSaveService");
				GLOBAL.shapePack.build();
				FileContents fc = save.saveFileDialog(null,
						new String[] { "dxf" }, new ByteArrayInputStream(
								GLOBAL.shapePack.getDXFBuffered(GLOBAL.applet)
										.toByteArray()), null);

			} catch (UnavailableServiceException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		} else {
			//GLOBAL.shapePack.printToCraftRobo();

			GLOBAL.applet.selectOutput("select design file.", "savePatternDXFCallback", null, this);


		}

	}

	public void savePatternDXFCallback(File file) {

	 GLOBAL.dxfSaveLocation = file.getAbsolutePath();
		GLOBAL.saveDXF = true;
		
		if(!GLOBAL.dxfSaveLocation.endsWith(".dxf"))
			GLOBAL.dxfSaveLocation += ".dxf";
		
		
	}
	public void savePDF(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

		if (SETTINGS.APPLET_MODE) {

			FileSaveService save;
			try {
				save = (FileSaveService) ServiceManager
						.lookup("javax.jnlp.FileSaveService");
				GLOBAL.shapePack.build();
				FileContents fc = save.saveFileDialog(null,
						new String[] { "pdf" }, new ByteArrayInputStream(
								GLOBAL.shapePack.getPDFBuffered(GLOBAL.applet)
										.toByteArray()), null);

			} catch (UnavailableServiceException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		} else {
			//GLOBAL.shapePack.printToCraftRobo();

			//Create a file chooser
			GLOBAL.applet.selectOutput("select design file.", "savePDFCallback", null, this);


		}

	}
	
	public void savePDFCallback(File file) {

		 String filename = file.getAbsolutePath();
		if (!filename.endsWith("pdf"))
			filename += ".pdf";
		
		GLOBAL.pdfSaveLocation = filename;
		GLOBAL.savePDF = true;
		
	}
	public void layersSelectNext(GUIEvent e){
	
		if (GLOBAL.sketchChairs.getCurChair() != null) {
			GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber++;
			
			if(GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber >= GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().size()){
				if(GLOBAL.planesWidget.mirrorSelection && GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().size()>1)
					GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber = 1;
				else
					GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber = 0;

				
			}

			GLOBAL.planesWidget.planeClickedOn(GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().get(GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber));
		}
	}

	public void layersSelectPrev(GUIEvent e){
	
		
		if (GLOBAL.sketchChairs.getCurChair() != null) {
			GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber--;
			
			if(GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber < 0){
				if(GLOBAL.planesWidget.mirrorSelection && GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().size()>1)
					GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber = GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().size()-1;
				else
					GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber = GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().size();

				
			}

			GLOBAL.planesWidget.planeClickedOn(GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().get(GLOBAL.sketchChairs.getCurChair().selectedPlaneNumber));
		}
		
		
	}

	public void exportPreview(GUIEvent e) {

		if (SETTINGS.APPLET_MODE) {

		} else {

			//Create a file chooser
			GLOBAL.applet.selectOutput("select design file.", "exportPreviewCallback", null, this);



		}

	}
	
	public void exportPreviewCallback(File file) {

		String filename = file.getAbsolutePath();
		
	if (!filename.endsWith("png"))
		filename += ".png";
	
	GLOBAL.pngPreviewSaveLocation =  filename;
	GLOBAL.exportPreviewPNG = true;
	}
	public void savePDFauto(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().addToShapePack();

		String computername = functions.getComputerName();
		String currentDir = new File(".").getAbsolutePath();
		currentDir = currentDir.substring(0, currentDir.length() - 1);

		int id = 0;
		boolean nameFound = false;
		String location = "";

		String dropBoxDir = SETTINGS.autoSaveMakeLocation;
		while (!nameFound && id < 10000) {
			location = dropBoxDir + "/" + "_exhibitionChair-" + id + ".pdf";
			File f = new File(location);

			if (!f.exists())
				nameFound = true;

			id++;
		}

		LOGGER.info("Saving PDF to: " + location);
		GLOBAL.pdfSaveLocation = location;
		GLOBAL.savePDF = true;
		SETTINGS.chairSaveNum++;

	}

	public void selectLanguage(GUIEvent e) {

		if (e.val == UITools.LANGUAGE_ENG) {
			SETTINGS.LANGUAGE = "ENG";
			GLOBAL.modeChanged = true;

		}

		if (e.val == UITools.LANGUAGE_JP) {
			SETTINGS.LANGUAGE = "JP";
			GLOBAL.modeChanged = true;

		}

	}

	public void setDisplaypanelAsShown(GUIEvent e) {
		GLOBAL.displayIntroPanel = false;

	}

	public void selectLegPlanes(GUIEvent e) {

		if (GLOBAL.sketchChairs.getCurChair() != null) {
			GLOBAL.sketchChairs.getCurChair().selectedPlanes.clear();
			GLOBAL.sketchChairs.getCurChair().selectedPlanes
					.add(GLOBAL.sketchChairs.getCurChair().getSlicePlanesY()
							.getFirst());
			GLOBAL.sketchChairs.getCurChair().selectedPlanes
					.add(GLOBAL.sketchChairs.getCurChair().getSlicePlanesY()
							.getLast());
		}

	}

	public void selectTool(GUIEvent e) {
		this.selectTool((int) e.val);
		this.selectCooldown = 50;

	}

	public void makeChairWindow(GUIEvent e) {
		float windowWidth = SETTINGS.GUIDE_WINDOW_WIDTH;
		float windowHeight = SETTINGS.GUIDE_WINDOW_HEIGHT;

		GUIWindow window = new GUIWindow(0f, 0f, windowWidth, windowHeight,
				GLOBAL.gui);
		window.setLightboxed(true);
		window.centre();
		GLOBAL.gui.add(window);

		float posX = 100;
		float posY = 100;
		float spacingY = 80;

		GUIImage guiImg;
		guiImg = new GUIImage(0, 50, "gui/WINDOW_TITLE_MAKE.png", GLOBAL.gui);
		window.add(guiImg);

		GUIButton button;
		button = new GUIToggle(400, 50, "gui/WINDOW_MAKE_PREVIEW_PATTERN.png",
				GLOBAL.gui);
		button.addActionListener(GLOBAL.uiTools, "toggleView", UITools.LEG_TOOL);
		button.addActionListener(window, "close", UITools.LEG_TOOL);
		window.add(button);
		posY += spacingY;

		button = new GUIToggle(400, 200, "gui/WINDOW_MAKE_CUT_PATTERN.png",
				GLOBAL.gui);
		button.addActionListener(window, "close", UITools.LEG_TOOL);
		if (SETTINGS.autoSaveMakePattern)
			button.addActionListener(GLOBAL.uiTools, "savePDFauto",
					UITools.LEG_TOOL);
		else
			button.addActionListener(GLOBAL.uiTools, "print", UITools.LEG_TOOL);

		window.add(button);

		posY += spacingY;

	}

	public void selectTool(int toolNum) {
		
		setCurrentTool(toolNum);

		if (this.getCurrentTool() == UITools.SELECT_TOOL
				&& !SETTINGS.EXPERT_MODE) {
			if (GLOBAL.sketchChairs.getCurChair() != null) {
				GLOBAL.sketchChairs.getCurChair().selectedPlanes.clear();
				GLOBAL.sketchChairs.getCurChair().selectedPlanes
						.add(GLOBAL.sketchChairs.getCurChair()
								.getSlicePlanesY());
			}

		}

		//GLOBAL.forceResize = true;
		// System.out.print(toolNum);
	}

	public void setBrushDia(float val) {

		GLOBAL.uiTools.SketchTools.brush_dia = val;

		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().setBrushDia(val);

	}

	public void setChairColour(GUIEvent e) {
		if (GLOBAL.sketchChairs.getCurChair() != null) {
			GLOBAL.sketchChairs.getCurChair().chairColour = (int) e.val;
		}

	}

	/**
	 * @param currentTool the currentTool to set
	 */
	public void setCurrentTool(int currentTool) {
		this.SketchTools.selectTool(SketchTools.NONE);
		this.currentTool = currentTool;

			
	}

	/**
	 * @param editing the editing to set
	 */
	public void setEditing(int editing) {
		this.editing = editing;
	}

	/**
	 * @param pickBuffer the pickBuffer to set
	 */
	public void setPickBuffer(PGraphics pickBuffer) {
		this.pickBuffer = pickBuffer;
	}

	public void showBugsWebpage(GUIEvent e) {

		String url = "http://www.sketchchair.cc/forum/index.php?board=8.0";
		if (java.awt.Desktop.isDesktopSupported()) {
			try {
				// not compatible in JRE 1.5
				java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		}

	}

	public void showForumWebpage(GUIEvent e) {

		String url = "http://www.sketchchair.cc/forum/";
		if (java.awt.Desktop.isDesktopSupported()) {
			try {
				// not compatible in JRE 1.5
				java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		}

	}

	public void showInstructionMovie(GUIEvent e) {
		//GLOBAL.tittleImageNum = 0;
		//GLOBAL.myMovie = new FasterMovie(GLOBAL.applet,"./introVideos/"+GLOBAL.tittleImageNum+".mov");
		//GLOBAL.myMovie.loop();	
	}

	public void showInstructions(GUIEvent e) {
		GLOBAL.tittleImageNum = 0;
		GLOBAL.tittleImg = GLOBAL.applet.loadImage("./tittleImage/"
				+ GLOBAL.tittleImageNum + SETTINGS.LANGUAGE + ".jpg");

	}

	public void showReferenceWebpage(GUIEvent e) {

		String url = "http://www.sketchchair.cc/development/description-of-features/";
		if (java.awt.Desktop.isDesktopSupported()) {
			try {
				// not compatible in JRE 1.5
				java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		}

	}

	


	
	
	public void sitStand(GUIEvent e) {

		if (!GLOBAL.jBullet.physics_on) {
			GLOBAL.jBullet.physics_on = true;
		} else {
			this.physicsRewind(null);
			GLOBAL.jBullet.physics_on = false;
		}
	}

	public void toggleCentreConstraintChair(GUIEvent e) {
		if (GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.sketchChairs.getCurChair().toggleCentreConstraint();

	}

	
	public void figureGrow(GUIEvent e) {
	GLOBAL.person.bigger();
	}
	
	
	public void figureShrink(GUIEvent e) {
	GLOBAL.person.smaller();

		
	}
	public void toggleExpert(GUIEvent e) {

		SETTINGS.EXPERT_MODE = !SETTINGS.EXPERT_MODE;
		
		if(this.currentView == UITools.VIEW_CHAIR_EDIT) {

		if (SETTINGS.EXPERT_MODE) {
			UI.setupGUITabsExpert(GLOBAL.applet, GLOBAL.gui);
		} else {
			UI.setupGUITabsBasic(GLOBAL.applet, GLOBAL.gui);
		}
				}

		
		if (GLOBAL.slicesWidget != null
				&& GLOBAL.sketchChairs.getCurChair() != null)
			GLOBAL.slicesWidget
					.rebuild(GLOBAL.sketchChairs.getCurChair().crossSliceSelections);

		GLOBAL.forceResize = true;
	}

	public void togglePerformance(GUIEvent e) {
		GLOBAL.performanceMode = !GLOBAL.performanceMode;

		GLOBAL.gui.performanceMode = GLOBAL.performanceMode;

		if (GLOBAL.gui.performanceMode) {
			SETTINGS.cylinder_res = 4;
			SETTINGS.sphere_res = 9;
		} else {

			SETTINGS.cylinder_res = 12;
			SETTINGS.sphere_res = 7;

		}

	}

	public void togglePerson(GUIEvent e) {

		GLOBAL.person.toggleON();
	}
	
	public void toggleFloor(GUIEvent e){
		GLOBAL.floorOn = !GLOBAL.floorOn;

	}

	public void toggleReferenceGeom(GUIEvent e) {
		GLOBAL.environments.render = !GLOBAL.environments.render;

	}
	public void toggleGrid(GUIEvent e) {
		LOGGER.info("snap to grid");
		this.useGrid = !this.useGrid;
		this.SketchTools.useGrid = !this.SketchTools.useGrid ;
	}
	
	public void importSVG(GUIEvent e) {

		
		GLOBAL.applet.selectInput("select design file.", "importSVGCallback", null, this);
		

	}
	public void importSVGCallback(File file) {
		 GLOBAL.importSVGLocation = file.getAbsolutePath();

	}
	
	public void applyMaterialSettings(GUIEvent e) {
	if(GLOBAL.sketchChairs.getCurChair() != null)
		GLOBAL.sketchChairs.getCurChair().addToShapePack();
	
	//LOGGER.info("applyMaterialSettings");
	}
	
	public void toggleView(GUIEvent e) {

		System.gc();//clean up before we hit the memory
		
		if (this.currentView == UITools.VIEW_CHAIR_EDIT)
			this.currentView = UITools.VIEW_SHAPE_PACK;
		else
			this.currentView = UITools.VIEW_CHAIR_EDIT;

		if (this.currentView == UITools.VIEW_SHAPE_PACK) {
			UI.setupGUIPattern(GLOBAL.applet, GLOBAL.gui);
			GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().update();
			GLOBAL.sketchChairs.getCurChair().addToShapePack();
			
		
			
		}else{
			
			if(SETTINGS.EXPERT_MODE)
			UI.setupGUITabsExpert(GLOBAL.applet, GLOBAL.gui);
			else
			UI.setupGUITabsBasic(GLOBAL.applet, GLOBAL.gui);

			if(GLOBAL.designToolbarPattern != null)
			GLOBAL.designToolbarPattern.hide();

			
			if(GLOBAL.designToolbarBasic != null)
				GLOBAL.designToolbarBasic.show();
			
			if(GLOBAL.designToolbarAdvanced != null)
				GLOBAL.designToolbarAdvanced.show();
			
			
		}

	}
	
	public void viewPattern(GUIEvent e) {

		GLOBAL.previewWidget.makeItBtn.hide();
		GLOBAL.previewWidget.designItBtn.hide();
		
		GLOBAL.patternCameraPanel.show();
		GLOBAL.cameraPanel.hide();
		
		this.currentView = UITools.VIEW_SHAPE_PACK;

		UI.setupGUIPattern(GLOBAL.applet, GLOBAL.gui);
		GLOBAL.sketchChairs.getCurChair().getSlicePlanesY().update();
		GLOBAL.sketchChairs.getCurChair().addToShapePack();
		
	}
	
	
	public void viewModel(GUIEvent e) {

		GLOBAL.previewWidget.makeItBtn.show();
		GLOBAL.previewWidget.designItBtn.hide();
		
		GLOBAL.patternCameraPanel.hide();
		GLOBAL.cameraPanel.show();
		
		
		this.currentView = UITools.VIEW_CHAIR_EDIT;

		if(SETTINGS.EXPERT_MODE)
			UI.setupGUITabsExpert(GLOBAL.applet, GLOBAL.gui);
			else
			UI.setupGUITabsBasic(GLOBAL.applet, GLOBAL.gui);
}
	
	

	public void undo(GUIEvent e) {
		System.out.print("UNDO");

		GLOBAL.undo.undoChair(GLOBAL.sketchChairs.getCurChair());

	}

	public void ShareChairOnline(GUIEvent e) {
		SketchChairCloudhook.getInstance().ShareChairOnline(null);
	}

	void update() {
		
		updateVecMove();

		if(GLOBAL.autoRotate){
			GLOBAL.slicesWidget.unselectAll();
			GLOBAL.planesWidget.unselectAll();
		}
		
		if (this.SketchTools.getCurrentTool() != SketchTools.NONE)
			this.currentTool = NONE;

		//if(this.waitingForSingleClick)
		//	LOGGER.info("waitingForSingleClick"+(GLOBAL.applet.millis() - this.mousePressedTime));
		
		
		if((GLOBAL.applet.millis() - this.mousePressedTime) > SETTINGS.MOUSE_CLICKED_MIN_TIME )
		this.waitingForSingleClick = false;
		
		if (this.waitingForSingleClick && 
				 (GLOBAL.applet.millis() - this.mousePressedTime) < SETTINGS.MOUSE_CLICKED_MIN_TIME &&
				(mouseX == pmouseX && mouseY == pmouseY)
				
				){
			this.mouseSingleClick();
			waitingForSingleClick = false;
		}


		this.selectCooldown--;
	}

	public void updateMouse(int mouseX2, int mouseY2, int pmouseX2,
			int pmouseY2, boolean mouseDown2, int mouseButton2) {
		GLOBAL.uiTools.pmouseX = GLOBAL.uiTools.mouseX;
		GLOBAL.uiTools.pmouseY = GLOBAL.uiTools.mouseY;

		GLOBAL.uiTools.mouseX = mouseX2;
		GLOBAL.uiTools.mouseY = mouseY2;

		GLOBAL.uiTools.mouseDown = mouseDown2;
		GLOBAL.uiTools.mouseButton = mouseButton2;

		if (this.useGrid ) {

			float m_gridW = this.gridWidth;
			float m_gridH = this.gridHeight;

			if (this.gridWidth * GLOBAL.getZOOM() > minorGridnumber * 5) {
				m_gridW /= minorGridnumber;
				m_gridH /= minorGridnumber;
			}

			//calculate the number of grid squares between the centre of the screen and the edge to  see where our grid should start
			float offset_x = (float) (Math.round((((float)mouseX2 - ((float)GLOBAL.windowWidth / 2.0f)) / (m_gridW * GLOBAL.getZOOM()))) * (m_gridW * GLOBAL.getZOOM()));
			offset_x +=(float)(GLOBAL.windowWidth / 2)+ ((GLOBAL.CAM_OFFSET_X * GLOBAL.getZOOM()) % (m_gridW * GLOBAL.getZOOM()));
			
			
			float offset_y = (float) (Math.round((((float)mouseY2 - ((float)GLOBAL.windowHeight / 2.0f)) / (m_gridH * GLOBAL.getZOOM()))) * (m_gridH * GLOBAL.getZOOM()));
			offset_y += (float)(GLOBAL.windowHeight / 2)+ ((GLOBAL.CAM_OFFSET_Y * GLOBAL.getZOOM()) % (m_gridH * GLOBAL.getZOOM()));

			int newMouseX = (int) offset_x;
			int newMouseY = (int) offset_y;
			GLOBAL.uiTools.mouseX = newMouseX;
			GLOBAL.uiTools.mouseY = newMouseY;

		}
	}

	public void updateMouseWorld() {

		GLOBAL.uiTools.pmouseXworld = GLOBAL.uiTools.mouseXworld;
		GLOBAL.uiTools.pmouseYworld = GLOBAL.uiTools.mouseYworld;

		Vec2D MouseWorld = this.getPointTranslated(new Vec2D(this.mouseX,
				this.mouseY));

		GLOBAL.uiTools.mouseXworld = MouseWorld.x;
		GLOBAL.uiTools.mouseYworld = MouseWorld.y;

	}

	void updateVecMove() {
		/*
			if (selectedVec != null && selectedVecPlane != null) {
				// System.out.println(selectedVec.x);
				if (UI.mouseDown) {
					//Vec2D planePoint = getPointOnPlane(new Vec2D(UI.mouseX,
							UI.mouseY), this.selectedVecPlane, GLOBAL.g);
					// selectedVec.x += (UI.mouseX - UI.pmouseX) / GLOBAL.ZOOM;
					// selectedVec.y += (UI.mouseY - UI.pmouseY) / GLOBAL.ZOOM;

					if (planePoint != null) {
						// selectedVec.x = planePoint.x;
						// / selectedVec.y = planePoint.y;

						if (this.selectedShape != null) {
							this.selectedShape.movePoint(selectedVec, planePoint);

						}
					}
					// 
				}
			}
			*/
	}

	
	boolean isSideView(){
		return(GLOBAL.rotateModelsX == 0 && GLOBAL.rotateModelsY == 0);
	}
	
	
	void zoomView(float _zoomDelta){
		
		
		float deltaMouseXBefore = (float) (((GLOBAL.applet.width/2)-UI.mouseX)/GLOBAL.ZOOM);
		float deltaMouseYBefore = (float) (((GLOBAL.applet.height/2)-UI.mouseY)/GLOBAL.ZOOM);
		
		
		GLOBAL.ZOOM -= _zoomDelta;

		
		if( (_zoomDelta > 0 && GLOBAL.ZOOM < SETTINGS.MIN_ZOOM)){
			GLOBAL.ZOOM = SETTINGS.MIN_ZOOM;
		}
				
		if(_zoomDelta < 0 && GLOBAL.ZOOM > SETTINGS.MAX_ZOOM){
		GLOBAL.ZOOM = SETTINGS.MAX_ZOOM;
		}
		
		 float deltaMouseXAfter = (float) (((GLOBAL.applet.width/2)-UI.mouseX)/GLOBAL.ZOOM);
		 float deltaMouseYAfter = (float) (((GLOBAL.applet.height/2)-UI.mouseY)/GLOBAL.ZOOM);
		
		 
		 float deltaMouseX = deltaMouseXAfter - deltaMouseXBefore; 
		 float deltaMouseY = deltaMouseYAfter - deltaMouseYBefore;
		 
		 moveView(-deltaMouseX,-deltaMouseY);

	}
	
	void centreView(float _x, float _y){
		
		
		float deltaMouseX = (GLOBAL.applet.width/2)-_x;
		float deltaMouseY = (GLOBAL.applet.height/2)-_y;
				
		GLOBAL.CAM_OFFSET_X += ((deltaMouseX/GLOBAL.ZOOM));
		GLOBAL.CAM_OFFSET_Y += ((deltaMouseY/GLOBAL.ZOOM));
		
		
		
	}
	
	void moveView(float _deltaX, float _deltaY){
		
		
		 GLOBAL.CAM_OFFSET_X +=  _deltaX;
		 GLOBAL.CAM_OFFSET_Y +=  _deltaY;
	
		 
		 float leftEdge = (float) (GLOBAL.CAM_OFFSET_X - ((GLOBAL.applet.width/2)/GLOBAL.ZOOM));
			if(leftEdge < SETTINGS.MIN_CAM_X_OFFSET)
				GLOBAL.CAM_OFFSET_X = SETTINGS.MIN_CAM_X_OFFSET + ((GLOBAL.applet.width/2)/GLOBAL.ZOOM);
			
			
			 float rightEdge = (float) (GLOBAL.CAM_OFFSET_X + ((GLOBAL.applet.width/2)/GLOBAL.ZOOM));
			if(rightEdge > SETTINGS.MAX_CAM_X_OFFSET)
				GLOBAL.CAM_OFFSET_X = SETTINGS.MAX_CAM_X_OFFSET - ((GLOBAL.applet.width/2)/GLOBAL.ZOOM);
			
			double topEdge = (double) GLOBAL.CAM_OFFSET_Y + ((GLOBAL.applet.height/2)/GLOBAL.ZOOM);
			if(topEdge > SETTINGS.MAX_CAM_Y_OFFSET)
				GLOBAL.CAM_OFFSET_Y = SETTINGS.MAX_CAM_Y_OFFSET - ((GLOBAL.applet.height/2)/GLOBAL.ZOOM);
			
			float bottomEdge = (float) (GLOBAL.CAM_OFFSET_Y - ((GLOBAL.applet.height/2)/GLOBAL.ZOOM));
			if(bottomEdge < SETTINGS.MIN_CAM_Y_OFFSET)
				GLOBAL.CAM_OFFSET_Y = SETTINGS.MIN_CAM_Y_OFFSET + ((GLOBAL.applet.height/2)/GLOBAL.ZOOM);
			
		 
	}
	
} public class GUIButton extends GUIComponent {

	PImage img_up = null;
	PImage img_down = null;
	PImage img_over = null;
	String img_up_txt = null;
	String img_down_txt = null;
	PImage img_clicked;

	//GUILabel label = null;

	public GUIButton(float x, float y, float w, float h) {
		// TODO Auto-generated constructor stub
	}

	public GUIButton(float x, float y, float w, float h, GUILabel labelButton,
			ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.setSize(w, h);
		this.label = labelButton;
	}

	public GUIButton(float x, float y, float w, float h, String label,
			ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.setSize(w, h);
		this.label = new GUILabel(this, label, this.controller);
		this.label.layout = GUILabel.CENTRE_OF_COMPONENT;

		//System.out.println("HERE"+this.label.labelStr);

	}

	public GUIButton(float x, float y, float w, float h, String img_up_path,
			String img_down_path, ModalGUI c) {
		this.setPos(x, y);
		this.setController(c);
		//this.setSize(w,h);
		//this.setLabel(label);

		if (img_up_path == null)
			return;

		PImage img_src = controller.applet.loadImage(img_up_path);

		if (w == 0 || h == 0) {
			w = img_src.width;
			h = img_src.height;
			img_up = img_src;

		} else {
			img_up = controller.makeImgUp((int) w, (int) h, img_src);

		}

		if (img_down_path != null && img_down_path != "")
			img_down = controller.applet.loadImage(img_down_path);
		else
			img_down = controller.makeImgDown(w, h, img_src);//ModalGUI.applet.loadImage(img_up_path);

		if (img_up != null)
			img_over = controller.makeImgOver((int) w, (int) h, img_src);//ModalGUI.applet.loadImage(img_up_path);

		this.setSize(this.img_up.width, this.img_up.height);
	}

	public GUIButton(float x, float y, PImage img_up_in, PImage img_down_in,
			PApplet applet, ModalGUI c) {
		this.setPos(x, y);
		this.setController(c);
		//this.setSize(w,h);
		//this.setLabel(label);
		this.img_up = img_up_in;
		
		if(img_down_in == null)
		this.img_down = controller.makeImgOver(img_up.width, img_up.height, img_up_in);
		else
		this.img_down = img_down_in;

		// img_up = applet.loadImage(img_up_path);

		//if(img_down != null)

		this.setSize(this.img_up.width, this.img_up.height);

	}

	public GUIButton(float x, float y, String img_up, ModalGUI c) {
		this(x, y, img_up, null, c);
	}

	public GUIButton(float x, float y, String img_up_path,
			String img_down_path, ModalGUI c) {
		this(x, y, 0, 0, img_up_path, img_down_path, c);
	}

	public boolean isMouseOver() {

		
		
		if (super.isMouseOver()) {

			if (!controller.useAlphaMouseOver)
				return true;

			if (this.img_down != null) {
				this.img_up.loadPixels();
				int index = (int) (((controller.applet.mouseY - this.getY()) * this.img_up.width) + (controller.applet.mouseX - this
						.getX()));
				int c = 0;

				if (index < this.img_up.width * this.img_up.height)
					c = this.img_up.pixels[index];

				if (controller.applet.alpha(c) == 255)
					return true;
				else
					return false;
			}
		} else {
			return false;
		}
		return false;
	}

	@Override
	public void keyEvent(KeyEvent theKeyEvent) {
	}

	public void mouseEvent(MouseEvent e) {

		if (!this.visible)
			return ;
		
		if (this.destroy)
			return;

		if (e.getID() == MouseEvent.MOUSE_PRESSED) {
			if (isMouseOver())
				wasClicked = true;
		} else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked
				&& isMouseOver()) {
			fireEventNotification(this, "Clicked");
			wasClicked = false;
		}

	}

	@Override
	public void render(PGraphics g) {
		super.render(g);
		
		
		if(controller.renderOnUpdate && !reRender){
			return;
		}
		
		
		if(controller.renderOnUpdate)
		reRender = false; // only render once

		if (!this.visible)
			return;

		if (this.getFillColour() != -2)
			g.fill(this.getFillColour());
		if (this.getStrokeColour() != -2)
			g.stroke(this.getStrokeColour());

		if (this.isDown) {
			if (this.getFillColourDown() != -2)
				g.fill(this.getFillColourDown());
			if (this.getStrokeColourDown() != -2)
				g.stroke(this.getStrokeColourDown());
		}

		if (isMouseOver() && !this.isDown) {
			if (this.getFillColourOver() != -2)
				g.fill(this.getFillColourOver());
			if (this.getStrokeColourOver() != -2)
				g.stroke(this.getStrokeColourOver());
		}

		if (this.label != null && this.img_up == null) {
			g.noFill();
			if (wasClicked) {
			} else {
				if (isMouseOver()) {
					g.strokeWeight(2);
				} else {
					g.strokeWeight(1);
				}
			}

			g.rectMode(PConstants.CORNER);
			g.rect(this.getX(), this.getY(), this.getWidth(), this.getHeight());

			if (this.img_up == null) {
				//label.align = GUILabel.CENTRE ;
				//label.render(g,this.getX()+(this.getWidth()/2) , this.getY() + (this.getHeight()/2));
			}

		}

		if (wasClicked && this.img_clicked != null) {
			g.image(this.img_clicked, (int)this.getX(), (int)this.getY());

		} else {
			if (isMouseOver() && this.img_down != null) {
				g.image(this.img_down, (int)this.getX(), (int)this.getY());
				reRender();

			} else if (isMouseOver() && this.img_down == null
					&& this.img_up != null) {
				g.image(this.img_up, (int)this.getX(), (int)this.getY());

				g.rect(this.getX(), this.getY(), this.getWidth(),
						this.getHeight());

			} else {

				if (this.img_up != null)
					g.image(this.img_up, (int)this.getX(), (int)this.getY());
				else
					g.rect(this.getX(), this.getY(), this.getWidth(),
							this.getHeight());
			}
		}
		
		renderLabel(g);

	}

	@Override
	public void renderTop(PGraphics g) {
		
		if (isMouseOver() && this.toolTip != null) {
			this.renderToolTip(g, controller.applet.mouseX,
					controller.applet.mouseY);
			if (toolTipAlpha < 255)
				this.toolTipAlpha += 20;
		} else {
			this.toolTipAlpha = -100;
		}

	}

	@Override
	public void setup() {
		// TODO Auto-generated method stub

	}

} public class GUILabel extends GUIComponent {

	public static final int CENTRE = 1;
	public static final int LEFT = 2;
	public static final int RIGHT = 3;

	public static final int RIGHT_OF_COMPONENT = 1;
	public static final int LEFT_OF_COMPONENT = 2;
	public static final int CENTRE_OF_COMPONENT = 3;
	public static final int UNDER_COMPONENT = 4;
	public static final int ABOVE_COMPONENT = 5;

	private static int countLines(String str) {
		String[] lines = str.split("\r\n|\r|\n");
		return lines.length;
	}

	PImage preRenderedLabel = null;
	private String labelStr = null;
	float textSize = 12;
	public int align;

	public int layout = 1;
	boolean preRenderLabels = true;

	public GUILabel(float x, float y, String string, ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.setLabelStr(string);

	}

	public GUILabel(GUIComponent component, int x, float y, String string,
			ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.setLabelStr(string);
		this.setParentComponent(component);
		this.setSize(this.getLabelStr().length(), textSize);
	}

	public GUILabel(GUIComponent component, String string, ModalGUI c) {
		this(component, 0, 0, string, c);
	}

	@Override
	public void keyEvent(KeyEvent keyevent) {
	super.keyEvent(keyevent);
	}

	@Override
	public void mouseEvent(MouseEvent e) {
	super.mouseEvent(e);
	}

	public void preRenderLabel(String str, PGraphics g) {

		
		
		g.textSize(this.textSize);
		int ln = countLines(str);
		float w = (int)g.textWidth(str) + 4;
		float h = (getController().labelSize + g.textDescent()+ g.textAscent()) * ln;
		PGraphics textG = getController().appletStatic.createGraphics((int) w,
				(int) h, PApplet.OPENGL);
		
		this.setSize(w, h);
		textG.beginDraw();
		textG.smooth(2);
		//textG.background(255);
		
		//textG.textMode(PApplet.SCREEN);
		textG.textSize(this.textSize);
		textG.textFont(getController().myFontMedium,this.textSize);
		//textG.textFont(myFont);
		//textG.textMode(PApplet.SCREEN);
		//textG.alpha(1);
		//textG.background(255, 255, 255, 0);
		textG.fill(0);
		
		
		//LOGGER.info("s"+this.textSize);
		/*
		LOGGER.info(this.labelStr);
		g.printMatrix();
		g.printCamera();
		g.printProjection();
		*/	
		
		textG.text(
				str,
				2,
				h
						- (g.textDescent()+g.textAscent() - 1)
						- ((getController().labelSize + g.textDescent() + 1) * (ln - 1)));
		textG.endDraw();
		this.preRenderedLabel = textG.get();
	}

	public void render(PGraphics g) {
		
		if(controller.renderOnUpdate && !reRender){
			return;
		}
		
		if(controller.renderOnUpdate)
		reRender = false; // only render once

		if (!this.visible)
			return;
		
		

		if (parentComponent == null) {
			this.render(g, this.getX(), this.getY());
			return;
		}

		if (this.layout == GUILabel.RIGHT_OF_COMPONENT) {
			this.align = GUILabel.LEFT;
			this.render(g, this.getX() + (parentComponent.getWidth() + 5),
					this.getY());
		}

		if (this.layout == GUILabel.LEFT_OF_COMPONENT) {
			this.align = GUILabel.RIGHT;
			this.render(g, this.getX() - 5, this.getY());
		}

		if (this.layout == GUILabel.CENTRE_OF_COMPONENT) {
			this.align = GUILabel.CENTRE;
			this.render(g, this.getX() + (parentComponent.getWidth() / 2),
					this.getY() + (this.getHeight() / 2));
		}

		if (this.layout == GUILabel.UNDER_COMPONENT) {
			this.align = GUILabel.CENTRE;
			this.render(g, this.getX() + (parentComponent.getWidth() / 2),
					this.getY() - this.getHeight());
		}

		if (this.layout == GUILabel.ABOVE_COMPONENT) {
			this.align = GUILabel.CENTRE;
			this.render(g, this.getX() + (parentComponent.getWidth() / 2),
					this.getY() - this.getHeight());
		}

		//this.render(g,this.getX(),this.getY());
	}

	public void render(PGraphics g, float x, float y) {

		
		
		if (this.controller == null)
			return;

		if (this.getLabelStr() == null)
			return;

		g.pushMatrix();
		
		if (preRenderedLabel == null && preRenderLabels )
			preRenderLabel(this.getLabelStr(), this.controller.appletStatic.g);



		if (align == CENTRE) {
			g.translate(-preRenderedLabel.width / 2,
					-preRenderedLabel.height / 2);
		}

		if (align == LEFT) {
			//nothing?
		}

		if (align == RIGHT) {
			g.translate(-preRenderedLabel.width, 0);
		}

		
		if(preRenderedLabel != null && preRenderLabels)
		g.image(preRenderedLabel, (int)x, (int)y);
		else{
			g.textSize(this.textSize);
			g.textFont(getController().myFontMedium,this.textSize);
			g.fill(0);
			g.text(this.getLabelStr(),(int)x, (int)y);
		}

		g.popMatrix();

	}

	@Override
	public void setup() {
		// TODO Auto-generated method stub

	}
	
	
	public void setText(String string_){
		setLabelStr(string_);
		preRenderedLabel = null;
	}

	/**
	 * @return the labelStr
	 */
	public String getLabelStr() {
		return labelStr;
	}

	/**
	 * @param labelStr the labelStr to set
	 */
	public void setLabelStr(String labelStr) {
		this.labelStr = labelStr;
	}

} public class GUINumberfield extends GUITextfield {

	float val = 0;
	float incriment = .1f;
	String unit = "mm";

	public GUINumberfield(float x, float y, float w, float h, ModalGUI c) {
		super(x, y, w, h, c);
		this.setText("0");

		
	
		
	}

	public float getVal() {

		String text = getText();
		Float f;

		try {
			f = new Float(text);
		} catch (NumberFormatException e) {
			return 0;

		}

		return f.floatValue();
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		if(this.hasFocus()){
			
		float notches = (float)-e.getUnitsToScroll();
		float newVal = this.getVal()+(notches*this.incriment);
		newVal = (float) (Math.round(newVal*100.0) / 100.0);
		
		
		this.setText(newVal +"");
		this.updateField();
		}
	}
	
	@Override
	public void keyEvent(KeyEvent theKeyEvent) {

		if (isTexfieldActive && isActive
				&& theKeyEvent.getID() == KeyEvent.KEY_PRESSED) {
			if (theKeyEvent.getKeyCode() == KeyEvent.VK_UP) {
				float v = getVal();
				v += incriment;
				NumberFormat nf = NumberFormat.getInstance();
				nf.setMaximumFractionDigits(2);
				this.setText(nf.format(v));
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
				float v = getVal();
				v -= incriment;

				NumberFormat nf = NumberFormat.getInstance();
				nf.setMaximumFractionDigits(2);

				this.setText(nf.format(v));
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
				if (myPosition > 0) {
					myPosition--;
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
				if (myPosition < myTextline.length()) {
					myPosition++;
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DELETE
					|| theKeyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
				if (myTextline.length() > 0) {
					if (myPosition > 0) {
						myTextline.deleteCharAt(myPosition - 1);
						myPosition--;
					}
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
				submit();
			} else if (theKeyEvent.getKeyCode() != KeyEvent.VK_SHIFT
					&& theKeyEvent.getKeyCode() != KeyEvent.VK_ALT
					&& theKeyEvent.getKeyCode() != KeyEvent.VK_A
					&& theKeyEvent.getKeyCode() != KeyEvent.VK_CONTROL) {
				if (theKeyEvent.getKeyCode() >= 48
						&& theKeyEvent.getKeyCode() <= 57
						|| theKeyEvent.getKeyCode() == 46) {

					System.out.println(theKeyEvent.getKeyCode());
					myTextline.insert(myPosition, theKeyEvent.getKeyChar());
					myPosition++;
				}
			}
			updateField();
		}
	}

	public void setText(String theValue) {
		myTextline = new StringBuffer(theValue);
		// myPosition = myTextline.length() - 1;
		_myStringValue = theValue;
		myPosition = myTextline.length();
		// _myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition);
	}

	void setUnit(String unit) {

		this.unit = unit;
	}

	@Override
	protected void updateField() {
		this.fireEventNotification(getVal());
	}

} public class GUIPanel extends GUIComponent {

	public GUIComponents components = new GUIComponents();
	protected float currentX = 15;
	float currentY = 20f;

	float minimizedH = 5;
	float minimizedW = 5;
	float maximizedH = 5;
	float maximizedW = 5;

	public float spacingX = 10;
	public float spacingY = 10;
	public boolean minimized = false;

	public boolean isDragging = false;
	public boolean isDraggable = false;

	private float selectBarHeight = 15;
	public boolean autoHide = false;
	private float cornerRad = 7f;
	PGraphics canvas = null;
	PImage bufferedCanvas = null;
	public boolean useCanvas = false;
	float scrollX = 0;
	float scrollY = 0;

	float prevScrollX = 0;
	float prevScrollY = 0;

	float deltaScrollX = 0;
	float deltaScrolY = 0;

	private float bottomScrollY;
	private float rightScrollX;
	private float topScrollY;
	private float leftScrollX;
	public boolean useScroolBarX;
	public boolean useScroolBarY;

	GUIScrollbar sliderX = null;
	GUIScrollbar sliderY = null;
	public boolean hideSelectBar = false;
	public boolean hideMinimize = true;

	GUIPanel dockedPanelTop = null;
	GUIPanel dockedPanelBottom = null;
	int DOC_TOP = 0;
	int DOC_BOTTOM = 0;
	private GUIButton minimize;

	PImage mask = null;
	String tittle = "";
	private boolean invisible = false;
	public boolean renderBorder = true;
	public PImage tabUpImg = null;
	public PImage tabDownImg = null;

	
	
	public GUIPanel(float x, float y, float w, float h, boolean useCanvas,
			PApplet applet, ModalGUI c) {
		this(x, y, w, h, c);
		makeCanvas(w, h, applet);
		
		//this.useCanvas = useCanvas;

	}

	public GUIPanel(float x, float y, float w, float h, ModalGUI c) {
		this.setController(c);
		this.minimizedH = 10;
		this.minimizedW = w;
		this.maximizedH = h;
		this.maximizedW = w;
		this.setPos(x, y);
		this.setSize(w, h);
		this.mask = c.applet.loadImage("mask.png");
	}

	public void add(GUIComponent component) {

		this.components.add(component);

		component.setController(this.controller);

		component.setParentPanel(this);

		//if(component.getY() > currentY && this.useCanvas)
		//	currentY = component.getY();

		//if(component.getX() > currentX && this.useCanvas)
		//	currentX = component.getX();

		if (component.getY() + component.getHeight() > this.getY()
				+ this.getHeight() - 20
				&& useScroolBarY) {
			this.bottomScrollY = (component.getY() + (component.getHeight() * 2))
					- (this.getY() + this.getHeight());
			this.updateYSlider(0, this.bottomScrollY);
		}
		if (component.getX() + component.getWidth() > this.getX()
				+ this.getWidth()
				&& useScroolBarX) {
			this.rightScrollX = component.getX() + component.getWidth();
			this.updateXSlider(0, this.rightScrollX - this.getX());

		}

		if (this.useCanvas)
			this.updateCanvas();

	}

	public void clear() {
		this.currentX = 5;
		this.currentY = 20;
		this.bottomScrollY = 0;
		this.rightScrollX = 0;
		this.sliderX = null;
		this.sliderY = null;

		//this.updateXSlider(0, 0);
		//this.updateYSlider(0, 0);
		this.components.clear();
	}

	public void docTo(GUIPanel panel) {

		//if(DOC_TOP == this.DOC_TOP)
		this.dockedPanelTop = panel;

		//if(DOC_TOP == this.DOC_BOTTOM)
		//	this.dockedPanelBottom = panel;

	}

	@Override
	public boolean hasFocus() {
		if (this.hasFocus || this.components.hasFocus())
			return true;
		else
			return false;

	}

	@Override
	public void hide() {
		this.visible = false;
		this.components.hideAll();
	}

	void hideAll() {
		this.components.hideAll();
	}

	@Override
	public boolean isMouseOver() {
		int mouseX = controller.applet.mouseX;
		int mouseY = controller.applet.mouseY;

		if (mouseX >= this.getX() && mouseY >= this.getY()
				&& mouseX <= this.getX() + this.getWidth()
				&& mouseY <= this.getY() + this.getHeight())
			return true;

		if (this.components.isMouseOver())
			return true;

		return false;

	}

	private boolean isMouseOverMoveBar() {
		int mouseX = controller.applet.mouseX;
		int mouseY = controller.applet.mouseY;

		return mouseX >= this.getX() && mouseY >= this.getY()
				&& mouseX <= this.getX() + this.getWidth()
				&& mouseY <= this.getY() + this.selectBarHeight;

	}

	@Override
	public void keyEvent(KeyEvent theKeyEvent) {
		this.components.keyEvent(theKeyEvent);
	}

	private void makeCanvas(float w, float h, PApplet applet) {
		this.useCanvas = true;
		//this.canvas = applet.createGraphics((int)w, (int) ((int)h-this.selectBarHeight-2), PApplet.P2D);
		//this.bufferedCanvas = this.canvas.get();

		//this.canvas.alpha(0);
		//this.canvas.smooth();
		//this.canvas.alpha(255);
	}

	public void minimizeToggle(GUIEvent e) {

		this.minimized = !this.minimized;

		if (this.minimized) {
			hideAll();
			this.setSize(this.minimizedW, this.minimizedH);
		} else {
			showAll();
			this.setSize(this.maximizedW, this.maximizedH);
		}
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		if (!this.visible)
			return;
		this.components.mouseWheelMoved(e);

	}
	
	
	@Override
	public void mouseEvent(MouseEvent e) {

		if (!this.visible)
			return;

		this.components.mouseEvent(e);

		if (sliderX != null)
			sliderX.mouseEvent(e);
		if (sliderY != null)
			sliderY.mouseEvent(e);

		if (e.getID() == MouseEvent.MOUSE_PRESSED) {
			if (isMouseOver())
				wasClicked = true;

			if (isMouseOverMoveBar() && isDraggable)
				isDragging = true;

		} else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked
				&& isMouseOver()) {
			fireEventNotification(this, "Clicked");
			wasClicked = false;
			isDragging = false;
		}

		if (e.getID() == MouseEvent.MOUSE_RELEASED) {
			isDragging = false;
		}

	}

	public boolean overComponent() {
		return components.overComponent();
	}

	public void placeComponent(GUIComponent component) {

		component.setController(this.controller);

		if (this.components.l.size() > 0) {
			if (this.currentX + (this.spacingX) + (component.getWidth() * 2) > this
					.getWidth()) {
				currentX = this.spacingX;
				currentY += component.getHeight() + this.spacingY;
			} else {
				currentX += this.spacingX + component.getWidth();
				//currentY += component.getHeight() + this.spacingY;
			}
			//currentY += 10;
		}

		if (currentY + component.getHeight() > this.getHeight()) {
			this.bottomScrollY = currentY;
			this.updateYSlider(0, this.bottomScrollY);
		}
		if (currentX + component.getWidth() > this.getWidth()) {
			this.rightScrollX = currentX;
			this.updateXSlider(0, this.rightScrollX - this.getX());
		}

		component.setPos(currentX, currentY);
		component.setParentPanel(this);

		if (this.useCanvas)
			component.ignorePanel();

		this.add(component);

	}

	public void placeComponentLeft(GUIComponent component) {
		component.setController(this.controller);

		if (currentX + component.getWidth() > this.getWidth()) {
			this.rightScrollX = currentX + (component.getWidth() * 2);
			this.updateXSlider(0, this.rightScrollX - this.getX());
		}

		component.setPos(currentX, currentY);
		component.setParentPanel(this);

		if (this.useCanvas)
			component.ignorePanel();

		currentX += this.spacingX + component.getWidth();

		this.add(component);

	}

	@Override
	public void render(PGraphics g) {
		if (controller == null)
			return;
		
		
		if (!this.visible || invisible)
			return;
		
		//Render on update optimization
		if(controller.renderOnUpdate && !reRender){
			this.components.render(g);//we still need to pass on the render command in case other components need refreshing
		return;
		}
		
		if(controller.renderOnUpdate)
		reRender = false; // only render once

		
		
		
		if(this.sliderX!=null|| this.sliderY!=null){
			/*
			GL gl = ((PGraphicsOpenGL) g).gl;
			gl.glEnable(gl.GL_SCISSOR_TEST);
			gl.glScissor((int)this.getX(),(int)this.getY()-100,(int)this.getWidth(),(int)this.getHeight());
*/		
		}
		

		
		controller.performanceMode = true;

		//if(this.useCanvas)
		//	g = this.canvas;

		

		if (!this.minimized) {
			g.stroke(this.getStrokeColour());
			g.strokeWeight(1);
			g.fill(this.getFillColour());

			if(renderBorder ){
			if (this.cornerRad > 0)
				g.rect(this.getX(), this.getY(), this.getWidth(),
						this.getHeight(),this.cornerRad);
			else
				g.rect(this.getX(), this.getY(), this.getWidth(),
						this.getHeight());
		
			}
			g.fill(this.getFillColour());
			g.noStroke();

			if (!hideSelectBar) {
				if (controller.performanceMode)
					g.rect(this.getX() + 1, this.getY() + 1,
							this.getWidth() - 2, selectBarHeight);
				else
					ModalGUI.roundrect(g, this.getX() + 1, this.getY() + 1,
							this.getWidth() - 2, selectBarHeight,
							this.cornerRad);
			}

			g.fill(255, 255, 255);

		} else {
			g.stroke(this.getStrokeColour());
			g.strokeWeight(1);
			g.fill(this.getFillColour());

			if (!hideSelectBar) {
				if (controller.performanceMode)
					g.rect(this.getX(), this.getY(), this.getWidth(),
							this.selectBarHeight + 2);
				else
					controller.roundrect(g, this.getX(), this.getY(),
							this.getWidth(), this.selectBarHeight + 2,
							this.cornerRad);

				g.fill(this.getFillColour());
				g.noStroke();

				if (controller.performanceMode)
					g.rect(this.getX() + 1, this.getY() + 1,
							this.getWidth() - 2, selectBarHeight);
				else
					controller.roundrect(g, this.getX() + 1, this.getY() + 1,
							this.getWidth() - 2, selectBarHeight,
							this.cornerRad);
			}

			g.fill(this.getFillColour());
		}
		if (this.getLabel() != null) {
			g.fill(50, 50, 50);
			g.textSize = 12f;
			g.textAlign = PConstants.LEFT;
			g.textAlignY = PConstants.BOTTOM;
			g.text(this.getLabel().getLabelStr(), this.getX() + 3f,
					this.getY() + 14f);
		}
		

		if (useCanvas) {
			/*
			//this.canvas.beginDraw();
			
			//this.canvas.translate(-this.getX(),-this.getY());
			
			if(this.sliderY != null)
			this.canvas.translate(0, -this.sliderY.getVal());
			
			if(this.sliderX != null)
				this.canvas.translate( -this.sliderX.getVal(),0);    
			
			//this.canvas.noFill();
			this.canvas.background(255,255,255,0);
			this.components.render(this.canvas);
			*/

			//this.canvas.endDraw();

			//if(this.bufferedCanvas != null)
			//g.image(this.bufferedCanvas, this.getX(), this.getY());

			g.pushMatrix();
			//g.translate(0, -this.scrollY);

			//g.translate( -this.scrollX,0);    
			//	
			this.components.translate(this.prevScrollX - this.scrollX,
					this.prevScrollY - this.scrollY);
			this.prevScrollX = this.scrollX;
			this.prevScrollY = this.scrollY;
			

			
			this.components.render(g, this.getX(), this.getY(),
					this.getWidth(), this.getHeight());
			

			g.popMatrix();
		} else{
			this.components.render(g);
		}

		

		if(this.sliderX!=null|| this.sliderY!=null){
			//GL gl = ((PGraphicsOpenGL) g).gl;
			//gl.glDisable(gl.GL_SCISSOR_TEST);
			
		}
		if (this.sliderX != null)
			this.sliderX.render(g);

		if (this.sliderY != null)
			this.sliderY.render(g);

		if (!this.autoHide && !this.hideMinimize && minimize != null)
			minimize.render(g);

		
		
			
			
	}
	
	

	
	@Override 
	public void reRender(){
	super.reRender();
	

	this.components.reRender();
	
	if (this.sliderX != null)
		sliderX.reRender();
	
	if (this.sliderY != null)
		sliderY.reRender();	
	
this.reRender =true;
	
	}
	
	public void setContentPosition(int xOffset, int yOffset) {
		this.currentX = xOffset;
		this.currentY = yOffset;

	}

	void setTittle(String t) {
		tittle = t;
	}

	@Override
	public void setup() {

		minimize = new GUIButton(this.getWidth() - 18, -1,
				"GUI_PLANE_REMOVE_UP.png", "GUI_PLANE_REMOVE_DOWN.png",
				this.controller);
		minimize.addActionListener(this, "minimizeToggle", 0);
		//	minimize.addToolTip(controller.parent,"GUI_PLANE_REMOVE_TOOLTIP", "ENG");
		minimize.setController(controller);
		//controller.add(minimize);
		minimize.setParentPanel(this);

	}

	@Override
	public void show() {
		this.visible = true;
		this.components.showAll();
	}

	void showAll() {
		this.components.showAll();
	}

	public boolean textfieldHasFocus() {
		return components.textfieldHasFocus();
	}

	@Override
	public void update() {
		
		if(sliderX != null && sliderX.wasClicked)
			reRender();
		
		if(sliderY != null && sliderY.wasClicked){
			reRender();
		}
		
		

		
		/*

		if(this.minimized || !this.visible)
			this.components.hideAll();
		
		if(this.visible && !this.minimized)
			this.components.showAll();
		*/

		if (this.visible)
			components.update();

		/*
		if(this.parentPanel != null && (this.parentPanel.minimized || !this.parentPanel.visible)){
			this.components.hideAll();

			this.visible = false;
			this.minimized = true;
		}
		
		if(this.parentPanel != null && ! this.parentPanel.minimized && this.parentPanel.visible){
			this.components.showAll();	
			this.visible = true;
			this.minimized = false;
		}
		*/

		if (this.useCanvas) {
			//if(this.canvas.isModified())
		//	this.updateCanvas();
		}

		if (this.dockedPanelTop != null) {
			this.setPos(this.dockedPanelTop.getX(), this.dockedPanelTop.getY()
					+ this.dockedPanelTop.getHeight() + 5);

		}

		if (isDragging && this.dockedPanelTop == null) {

			float deltaX = controller.applet.mouseX - controller.applet.pmouseX;
			float deltaY = controller.applet.mouseY - controller.applet.pmouseY;
			this.setPos(this.getX() + deltaX, this.getY() + deltaY);

		}
		if (autoHide) {
			if (isMouseOver()) {
				this.showAll();
				this.minimized = false;
				this.setSize(this.maximizedW, this.maximizedH);

			} else {
				this.hideAll();
				this.minimized = true;
				this.setSize(this.minimizedW, this.minimizedH);

			}
		}

		
		if (this.sliderX != null)
			this.sliderX.update();

		if (this.sliderY != null)
			this.sliderY.update();

		if (this.sliderX != null)
			this.scrollX = this.sliderX.getVal();

		if (this.sliderY != null)
			this.scrollY = this.sliderY.getVal();

	}

	private void updateCanvas() {
		/*
		this.canvas.beginDraw();
		this.bufferedCanvas = this.canvas.get();
		//this.bufferedCanvas.
		this.canvas.endDraw();
*/
		if (sliderX != null)
			sliderX.update();
		if (sliderY != null)
			sliderY.update();
	}

	public void updateXSlider(float minVal, float maxVal) {

		if (this.sliderX == null) {
			this.sliderX = new GUIScrollbar(2, this.getHeight() - 16,
					this.getWidth() - 3, minVal, maxVal, GUISlider.HORIZONTAL,
					this.controller);
			this.sliderX.setParentPanel(this);
			this.sliderX.setVal(0f);
			this.useScroolBarX = true;
			this.sliderX.setController(controller);
			
			//controller.add(minimize);    	

		}

		this.sliderX.setMinVal(minVal);
		this.sliderX.setMaxVal(maxVal);

	}

	public void updateYSlider(float minVal, float maxVal) {
		if (this.sliderY == null) {
			this.sliderY = new GUIScrollbar(this.getWidth() - 10,
					selectBarHeight, this.getHeight() - (selectBarHeight+15),
					minVal, maxVal, GUISlider.VERTICAL, this.controller);
			this.sliderY.setParentPanel(this);
			this.sliderY.setVal(0f);
			this.useScroolBarY = true;
			this.sliderY.setController(controller);
			//controller.add(minimize);
		}
		this.sliderY.setMinVal(minVal);
		this.sliderY.setMaxVal(maxVal);

	}

	public void invisible() {
		this.invisible  = true;		
	}
} public class GUISlider extends GUIComponent {
	public static final int HORIZONTAL = 0;
	public static final int VERTICAL = 1;
	float width;
	float maxVal;
	float minVal;
	public float curVal = 0f;
	boolean clickedOn = false;

	float selectArea = 17f;
	float trigSize = 14f;
	public int orientation = 0;
	private float clickOffsetX;
	private float mouseClickDeltaX;
	private float mouseClickDeltaY;
	private float scrollX;
	private float scrollY;
	
	PImage maxImg = null;
	PImage minImg = null;
	
	GUINumberfield currentValField = null;
	
	private boolean showValLabel = false;
	private String formatValLabel = null;
	private GUILabel labelVal ;
	private float labelValMultiplier = 1.0f;

	
	PImage handle;

	public GUISlider(float x, float y, float width, float minVal, float maxVal,
			int orientation, ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.width = width;
		this.minVal = minVal;
		this.maxVal = maxVal;
		this.orientation = orientation;
		this.handle = controller.applet.loadImage("handle.png");
		labelVal = new GUILabel(0, 0, null, c);
		labelVal.preRenderLabels =false;
	}

	public GUISlider(float x, float y, float width, float minVal, float maxVal,
			ModalGUI c) {
		this.setController(c);
		this.setPos(x, y);
		this.width = width;
		this.minVal = minVal;
		this.maxVal = maxVal;
		this.handle = controller.applet.loadImage("handle.png");
		labelVal = new GUILabel(0, 0, null, c);
		labelVal.preRenderLabels =false;

	}
	
	public void addNumberField(){
		
		float maxImgW =0;
		if(this.maxImg!= null)
			maxImgW = this.maxImg.width;
		this.currentValField = new GUINumberfield(this.x+this.width+maxImgW+5,this.y,35,15,this.getController());
		this.currentValField.addActionListener(this, "setVal");
		
		if(this.parentPanel != null)
			this.parentPanel.add(this.currentValField );
		else
			this.getController().add(this.currentValField);

		this.currentValField.setValue(this.getVal());
	}

	private void changeval() {
		
		reRender();
		if (this.orientation == HORIZONTAL) {
			float mouseX = controller.applet.mouseX - mouseClickDeltaX;
			float mouseDelta = ((mouseX - this.getX()) / (this.width - selectArea));

			if (mouseDelta > 1)
				mouseDelta = 1;

			if (mouseDelta < 0)
				mouseDelta = 0;

			this.curVal = (((maxVal - minVal) * mouseDelta))+1;
			//if(this.curVal < minVal)
			//	this.curVal = minVal;
		} else {
			float mouseY = controller.applet.mouseY - mouseClickDeltaY;
			float mouseDelta = ((mouseY - this.getY()) / (this.width - (selectArea / 2)));

			if (mouseDelta > 1)
				mouseDelta = 1;

			if (mouseDelta < 0)
				mouseDelta = 0;

			this.curVal = (((maxVal - minVal) * mouseDelta));

			if (this.curVal < minVal)
				this.curVal = minVal;

		}
		//	listener.val = this.curVal;
		//	this.fireEventNotification(null, "");
		
		if(this.currentValField != null){
			this.currentValField.setValue(Math.round(this.curVal));
		}
		
		this.fireEventNotification(this.curVal);

	}

	public void setEndImgs(PImage _minImg , PImage _maxImg ){
		this.minImg = _minImg;
		this.maxImg = _maxImg;
		
	}
	private void clicked() {

		this.mouseClickDeltaX = controller.applet.mouseX
				- (this.getX() + this.scrollX);
		this.mouseClickDeltaY = controller.applet.mouseY
				- (this.getY() + this.scrollY);

	}

	public float getVal() {
		return curVal;
	}

	public boolean isMouseOver() {

		return isMouseOverDragPoint();
	}

	boolean isMouseOverDragPoint() {

		float mouseX = controller.applet.mouseX;
		float mouseY = controller.applet.mouseY;

		if (this.orientation == HORIZONTAL) {

			float scrollX = (this.width - selectArea)
					* (this.curVal / (maxVal - minVal));

			//scrollX += this.getX();

			return mouseX >= scrollX + this.getX() && mouseY >= this.getY()
					&& mouseX <= scrollX + this.getX() + (selectArea)
					&& mouseY <= this.getY() + (selectArea);
		} else {

			float scrollY = (this.width - selectArea)
					* (this.curVal / (maxVal - minVal));

			//	scrollY += this.getY();

			return mouseY >= scrollY + this.getY()
					&& mouseY <= scrollY + this.getY() + (selectArea)
					&& mouseX >= getX() - (selectArea / 2)
					&& mouseX <= getX() + (selectArea / 2);

		}
	}

	@Override
	public void keyEvent(KeyEvent theKeyEvent) {
	}

	@Override
	public void mouseEvent(MouseEvent e) {

		//
		if (e.getID() == MouseEvent.MOUSE_PRESSED) {

			if (isMouseOverDragPoint()) {

				if (wasClicked == false)
					this.clicked();

				
				LOGGER.info("clicked");
				wasClicked = true;

			}

			//        if(isMouseOverDragPoint() && wasClicked){
			//    		//System.out.println("Moue over click");
			//
			//        	float scrollX  = width * (curVal/(maxVal-minVal));
			//        	
			//        	
			//        	scrollX += this.getX();
			//        	
			//            this.clickOffsetX = controller.parent.mouseX - scrollX;
			//           // System.out.println("clicked");
			//
			//        }

		} else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked) {
			fireEventNotification(this, "Clicked");
			wasClicked = false;
		}

	}

	@Override
	public void render(PGraphics g) {

		if (!this.visible)
			return;

		if (this.orientation == HORIZONTAL) {

			//fill colours
			if (this.getFillColour() != -2)
				g.fill(this.getFillColour());
			if (this.getStrokeColour() != -2)
				g.stroke(this.getStrokeColour());

			//g.rect(this.getX(), this.getY(), this.width,selectArea);
			g.strokeWeight(5);
			g.stroke(g.color(220, 220, 220));
			g.line(this.getX(), this.getY() + (selectArea / 2), this.getX()
					+ this.width, this.getY() + (selectArea / 2));

			g.strokeWeight(2);
			g.stroke(g.color(95, 95, 95));
			g.line(this.getX() + 2, this.getY() + (selectArea / 2), this.getX()
					+ this.width - 2, this.getY() + (selectArea / 2));

			this.scrollX = (this.width - selectArea)
					* (this.curVal / (maxVal - minVal));
			//scrollX += this.getX();
			//g.ellipseMode(0);
			

			g.fill(180, 180, 180);
			if (this.handle != null)
				g.image(this.handle, (int)(scrollX + this.getX()
						- (this.handle.width / 8)), (int)(this.getY()
						- (this.handle.height / 6)));
			else
				g.rect(scrollX + this.getX(), this.getY(), selectArea,
						selectArea);
			
			
			if(this.minImg != null)
				g.image(this.minImg,this.getX()-(this.minImg.width + 2), this.getY()+(this.minImg.height/2));
				
			
			if(this.maxImg != null)
				g.image(this.maxImg,this.getX()+(this.width + 2), this.getY());

		} else {

			g.stroke(200, 200, 200);
			g.noFill();
			g.strokeWeight(1);
			//fill colours
			if (this.getFillColour() != -2)
				g.fill(this.getFillColour());
			if (this.getStrokeColour() != -2)
				g.stroke(this.getStrokeColour());

			g.strokeWeight(5);
			g.stroke(g.color(220, 220, 220));
			g.line(this.getX(), this.getY(), this.getX(), this.getY()
					+ this.width);

			g.strokeWeight(2);
			g.stroke(g.color(95, 95, 95));
			g.line(this.getX(), this.getY(), this.getX(), this.getY()
					+ this.width);

			this.scrollY = (width - selectArea) * (curVal / (maxVal - minVal));
			//scrollY += this.getY();

			g.fill(180, 180, 180);
			if (this.handle != null)
				g.image(this.handle, (int)(this.getX() - (selectArea / 1.8f)), (int)(scrollY
						+ this.getY() - 2));
			else
				g.rect(this.getX() - (selectArea / 2), scrollY + this.getY(),
						selectArea, selectArea);

		}
		renderLabel(g);
	}

	@Override
	public void renderLabel(PGraphics g) {

		if (this.orientation == HORIZONTAL) {

			if (this.label != null) {
				this.label.align = GUILabel.LEFT;
				this.label.render(g, this.getX(), this.getY() - 15);
			}
			if(getShowValLabel()){
				

				float labelOffset = 0;
				if(this.label != null)	
				labelOffset = this.label.getWidth();
				
				if(getFormatValLabel() != null)
					this.labelVal.setText(String.format(getFormatValLabel(),(this.getVal()*getLabelValMultiplier()))+"");	
					else
				 this.labelVal.setText(String.format("%1$.2f",(this.getVal()*getLabelValMultiplier()))+"");	
			    
				this.labelVal.render(g, this.getX() + this.width+ labelOffset + 20, this.getY()+18);
			}
		} else {

			if (this.label != null) {
				this.label.align = GUILabel.LEFT;
				this.label.render(g, this.getX(), this.getY() + 22);
			}
			
			if(getShowValLabel()){
			
			float labelOffset = 0;
			if(this.label != null)	
			labelOffset = this.label.getWidth();
			if(getFormatValLabel() != null)
			this.labelVal.setText(String.format(getFormatValLabel(),(this.getVal()*getLabelValMultiplier()))+"");	
			else
			this.labelVal.setText(String.format("%.2g",(this.getVal()*getLabelValMultiplier()))+"");	
			this.labelVal.render(g, this.getX() + this.width+ labelOffset + 2, this.getY());
			}
			
			
		}

	}

	public void setMaxVal(float val) {
		this.maxVal = val;
	}

	public void setMinVal(float val) {
		this.minVal = val;
	}

	@Override
	public void setup() {
		// TODO Auto-generated method stub

	}

	public void setVal(float val) {
		this.curVal = val;
	}

	@Override
	public void update() {

		if (this.wasClicked)
			this.changeval();
	}

	/**
	 * @return the showValLabel
	 */
	public boolean getShowValLabel() {
		return showValLabel;
	}

	/**
	 * @param showValLabel the showValLabel to set
	 */
	public void setShowValLabel(boolean showValLabel) {
		this.showValLabel = showValLabel;
		}

	/**
	 * @return the labelValMultiplier
	 */
	public float getLabelValMultiplier() {
		return labelValMultiplier;
	}

	/**
	 * @param labelValMultiplier the labelValMultiplier to set
	 */
	public void setLabelValMultiplier(float labelValMultiplier) {
		this.labelValMultiplier = labelValMultiplier;
	}

	/**
	 * @return the formatValLabel
	 */
	public String getFormatValLabel() {
		return formatValLabel;
	}

	/**
	 * @param formatValLabel the formatValLabel to set
	 */
	public void setFormatValLabel(String formatValLabel) {
		this.formatValLabel = formatValLabel;
	}

} public class GUITextfield extends GUIComponent {

	/*
	 * TODO needs a lot of work! has gone through massive amounts of little
	 * changes and adjustments. implement new fonts, current one is too small.
	 * make the text go to the left when cursor goes beyond right border. make
	 * textfield work for controlWindow
	 *
	 */

	protected ArrayList myTextList = new ArrayList();

	int myIndex = 1;

	int myPosition = 0;

	StringBuffer myTextline = new StringBuffer();

	public boolean isTexfieldActive = false;

	private boolean isPasswordMode = false;

	protected boolean isAutoClear = true;

	protected boolean isKeepFocus = false;

	protected String _myStringValue;
	protected String myPasswordTextline = "";

	public boolean isActive = false;

	public GUITextfield(float x, float y, float w, float h, ModalGUI c) {
		//this(x,y,w,h,applet);
		this.setController(c);
		this.setPos(x, y);
		this.setSize(w, h);

	}

	/**
	 * @invisible
	 * @param theControllerProperties
	 *            ControllerProperties
	 * @return 
	 */
	public GUITextfield(String theName, String theDefaultValue, int theX,
			int theY, int theWidth, int theHeight, ModalGUI c) {

	}

	/**
	 * @invisible
	 */
	protected void adjust() {
		myPosition = myTextline.length();
		if (myPosition < 0) {
			myPosition = 0;
		}
	}

	protected void checkClear() {
		if (isAutoClear) {
			myTextline = new StringBuffer();
			myIndex = myTextList.size();
			myPosition = 0;
			updateField();
		}
	}

	/**
	 * clear the current content of the textfield.
	 */
	public void clear() {
		myTextline = new StringBuffer();
		myIndex = myTextList.size();
		myPosition = 0;
		updateField();
	}

	/**
	 * get the current text of the textfield.
	 *
	 * @return String
	 */
	public String getText() {
		return myTextline.toString();
	}

	/**
	 * returns a string array that lists all text lines that have been confirmed
	 * with a return.
	 *
	 * @return
	 */
	public String[] getTextList() {
		String[] s = new String[myTextList.size()];
		myTextList.toArray(s);
		return s;
	}

	/**
	 * @invisible
	 * @param theElement
	 *            ControlP5XMLElement
	 */
	/*
	public void addToXMLElement(
	       // ControlP5XMLElement theElement) {
	       // theElement.setAttribute("type", "textfield");
	       // theElement.setAttribute("value", "" + stringValue());
	}
	*/

	@Override
	public boolean hasFocus() {
		if (this.hasFocus || this.isActive)
			return true;
		else
			return false;
	}

	/**
	 * returns the current state of the autoClear flag.
	 *
	 * @return
	 */
	public boolean isAutoClear() {
		return isAutoClear;
	}

	/**
	 * check if the textfield is active and in focus.
	 *
	 * @return boolean
	 */
	public boolean isFocus() {
		return isTexfieldActive;
	}

	/**
	 * set the textfield's focus to true or false.
	 *
	 * @param theFlag
	 *            boolean
	 */
	/*
	public void setFocus(
	        boolean theFlag) {
		
		this.hasFocus = theFlag;
		
	        if (theFlag == true) {
	                mousePressed();
	        } else {
	                mouseReleasedOutside();
	        }
	}
	*/
	/**
	 * use true as parameter to force the textfield to stay in focus. to go back
	 * to normal focus behavior, use false.
	 *
	 * @param theFlag
	 */
	public void keepFocus(boolean theFlag) {
		isKeepFocus = theFlag;
		if (isKeepFocus) {
			this.setFocus(true);
		}
	}

	/**
	 * flip throught the texfield history with cursor keys UP and DOWN. go back
	 * and forth with cursor keys LEFT and RIGHT.
	 *
	 * @invisible
	 */
	@Override
	public void keyEvent(KeyEvent theKeyEvent) {


		if (isTexfieldActive && isActive
				&& theKeyEvent.getID() == KeyEvent.KEY_PRESSED) {

			if (theKeyEvent.getKeyCode() == KeyEvent.VK_UP) {
				if (myTextList.size() > 0 && myIndex > 0) {
					myIndex--;
					myTextline = new StringBuffer(
							(String) myTextList.get(myIndex));
					adjust();
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
				myIndex++;
				if (myIndex >= myTextList.size()) {
					myIndex = myTextList.size();
					myTextline = new StringBuffer();
				} else {
					myTextline = new StringBuffer(
							(String) myTextList.get(myIndex));
				}
				adjust();
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
				if (myPosition > 0) {
					myPosition--;
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
				if (myPosition < myTextline.length()) {
					myPosition++;
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_DELETE
					|| theKeyEvent.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
				if (myTextline.length() > 0) {
					if (myPosition > 0) {
						myTextline.deleteCharAt(myPosition - 1);
						myPosition--;
					}
				}
			} else if (theKeyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
				submit();
			} else if (theKeyEvent.getKeyCode() != KeyEvent.VK_SHIFT
					&& theKeyEvent.getKeyCode() != KeyEvent.VK_ALT
					&& theKeyEvent.getKeyCode() != KeyEvent.VK_CONTROL) {

				if (theKeyEvent.getKeyCode() >= 31
						&& theKeyEvent.getKeyCode() <= 127) {
					myTextline.insert(myPosition, theKeyEvent.getKeyChar());
					myPosition++;
				}
			}
			updateField();
		}
	}

	/**
	 * @invisible
	 * @param theElement
	 *            ControlP5XMLElement
	 */
	/*
	public void addToXMLElement(
	       // ControlP5XMLElement theElement) {
	       // theElement.setAttribute("type", "textfield");
	       // theElement.setAttribute("value", "" + stringValue());
	}
	*/

	
	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
	}
	@Override
	public void mouseEvent(MouseEvent e) {
		//

		
		if (e.getID() == MouseEvent.MOUSE_PRESSED) {
			if (isMouseOver())
				wasClicked = true;
		} else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked
				&& isMouseOver()) {
			//  fireEventNotification(this, "Clicked");
			this.isActive = true;
			this.isTexfieldActive = true;
			this.setFocus(true);
		}

		if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked
				&& !isMouseOver()) {
			this.isActive = false;
			this.isTexfieldActive = false;
			this.setFocus(false);
		}

	}

	/**
	 * click the texfield to activate.
	 *
	 * @invisible
	 *
	 */
	protected void mousePressed() {
		this.setFocus(true);
		//System.out.println("FOCUS");
		isTexfieldActive = isActive = true;
	}

	/**
	 *
	 */
	protected void mouseReleasedOutside() {

		if (isKeepFocus == false) {
			//System.out.println("UNFOCUS");
			this.setFocus(false);
			isTexfieldActive = isActive = false;
		}
	}

	/**
	 * @invisible
	 * @param theApplet
	 *            PApplet
	 */
	@Override
	public void render(PGraphics g) {

		if (!this.visible)
			return;

		if (isTexfieldActive && isActive) {
			g.stroke(g.color(0, 0, 0));
		} else {
			g.stroke(g.color(100, 100, 100));
		}
		g.strokeWeight(1);
		g.fill(255);
		g.pushMatrix();
		g.translate(this.getX(), this.getY());
		g.rect(0, 1, this.getWidth(), this.getHeight()+1);
		g.fill(0);

		if (this.getText() != null) {
			g.textAlign = PConstants.LEFT;
			g.textAlignY = PConstants.CENTER;

			String activeMark = "";

			if (this.hasFocus() && new Date().getTime() % 800 > 400)
				activeMark = "|";
			if (this.controller.myFontMedium != null){
				g.textFont(this.controller.myFontMedium);

				if(isPasswordMode)
					this.controller.applet.text(myPasswordTextline + activeMark, 5, 8,
							this.getWidth(), this.getHeight());
				else{
				this.controller.applet.text(this.getText() + activeMark, 5, 8);
				//this.controller.applet.text("hi"+this.getText(),0,0);
				}
			}

			g.noStroke();
			//_myValueLabel.draw(theApplet, 4, 7);
			//_myCaptionLabel.draw(theApplet, 0, height + 4);

			//      System.out.println(this.getText());

		}

		g.popMatrix();
		renderLabel(g);
		

	}

	/**
	 * use setAutoClear(false) to not clear the content of the textfield after
	 * confirming with return.
	 *
	 * @param theFlag
	 */
	public void setAutoClear(boolean theFlag) {
		isAutoClear = theFlag;
	}

	/**
	 * set the mode of the textfield to password mode, each character is shown
	 * as a "*" like e.g. in online password forms.
	 *
	 * @param theFlag
	 *            boolean
	 */
	public void setPasswordMode(boolean theFlag) {
		isPasswordMode = theFlag;
	}

	/**
	 * setText does set the text of a textfield, but will not broadcast its
	 * value. use setText to force the textfield to change its text. you can
	 * call setText any time, nevertheless when autoClear is set to true (which
	 * is the default), it will NOT work when called from within controlEvent or
	 * within a method that has been identified by ControlP5 to forward messages
	 * to, when return has been pressed to confirm a textfield.<br /> use
	 * setAutoClear(false) to enable setText to be executed for the above case.
	 * use yourTextfield.isAutoClear() to check if autoClear is true or false.
	 * <br />
	 * setText replaces the current/latest content of a textfield but does NOT
	 * overwrite the content. when scrolling through the list of textlines (use
	 * key up and down), the previous content that has been replaced will be put
	 * back into place again - since it has not been confirmed with return.
	 *
	 * @param theValue
	 */
	public void setText(String theValue) {
		myTextline = new StringBuffer(theValue);
		// myPosition = myTextline.length() - 1;
		_myStringValue = theValue;
		myPosition = myTextline.length();
		// _myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition);
	}

	@Override
	public void setup() {
		// TODO Auto-generated method stub

	}

	/*
	public Textfield(
	        ControlP5 theControlP5,
	        ControllerGroup theParent,
	        String theName,
	        String theDefaultValue,
	        int theX,
	        int theY,
	        int theWidth,
	        int theHeight) {
	        super(theControlP5, theParent, theName, theX, theY, theWidth, theHeight);
	        _myCaptionLabel = new Label(theName.toUpperCase(), color.colorLabel);
	        _myCaptionLabel.setFixedSize(false);
	        myBroadcastType = STRING;
	        _myValueLabel.setWidth(width - 10);
	        _myValueLabel.setHeight(15);
	        _myValueLabel.set(">");
	        _myValueLabel.setColor(color.colorValue);
	        _myValueLabel.toUpperCase(false);
	        _myValueLabel.setFixedSize(true);
	        _myValueLabel.setFont(ControlP5.standard56);

	}
	*/
	@Override
	public
	void hide(){
		this.isActive = false;
		super.hide();
	}
	
	/**
	 * @invisible
	 * @param theValue
	 *            float
	 */
	public void setValue(float theValue) {
		setValue(theValue+"");
	}

	/**
	 * set the value of the textfield and will broadcast the new string value
	 * immediately. what is the difference between setValue and setText?
	 * setValue does broadcast the value that has been set, setText does not
	 * broadcast the value, but only updates the content of a textfield. for
	 * further information about how setText works, see the setText
	 * documentation.
	 *
	 * @param theValue
	 *            String
	 */
	public void setValue(String theValue) {
		myTextline = new StringBuffer(theValue);
		// myPosition = myTextline.length() - 1;
		_myStringValue = theValue;
		myPosition = myTextline.length();
		//_myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition);
		//broadcast(myBroadcastType);
	}

	/**
	 * make the controller execute a return event. submit the current content of
	 * the texfield.
	 *
	 */
	public void submit() {
		if (myTextline.length() > 0) {
			myTextList.add(myTextline.toString());
			update();
			checkClear();
		}
	}

	/**
	 * @invisible
	 */
	public void update() {
		_myStringValue = myTextline.toString();
		setValue(_myStringValue);
	}

	protected void updateField() {
		if (isPasswordMode) {
			 myPasswordTextline = "";
			for (int i = 0; i < myTextline.length(); i++) {
				myPasswordTextline += "*";
			}
			// _myValueLabel.setWithCursorPosition(myPasswordTextline, myPosition);
		} else {
			int offset = 0;
			// int m = _myValueLabel.bitFontRenderer.getWidth(myTextline.toString(), _myValueLabel,myPosition);
			//offset = (m>_myValueLabel.width()) ? _myValueLabel.width() - m:0;                      
			// _myValueLabel.setWithCursorPosition(myTextline.toString(), myPosition,offset);
		}
	}
} public class GUIToggle extends GUIButton {

	PImage img_clicked;

	boolean linkedVal;
	public boolean justMade = true;
	private GUIComponentSet componentSet = null;

	public boolean isTab = false;

	public float cornerRad = 0;

	public GUIToggle(float x, float y, float w, float h) {
		super(x, y, w, h);
		this.setPos(x, y);
		this.setSize(w, h);
	}

	public GUIToggle(float x, float y, float w, float h,
			GUIComponentSet componentSet, ModalGUI c) {
		super(x, y, w, h, "", c);
		this.setComponentSet(componentSet);
		componentSet.add(this);
		this.setPos(x, y);
		this.setSize(w, h);
	}

	public GUIToggle(float x, float y, float w, float h, String label,
			GUIComponentSet componentSet, ModalGUI c) {
		super(x, y, w, h, "", c);
		this.componentSet = componentSet;
		componentSet.add(this);
		this.setPos(x, y);
		this.setSize(w, h);
		this.label = new GUILabel(this, label, c);

	}

	public GUIToggle(float x, float y, float w, float h, String img_up,
			ModalGUI c) {
		this(x, y, w, h, img_up, "", c);
	}

	public GUIToggle(float x, float y, float w, float h, String img_up_path,
			String img_down_path, ModalGUI c) {
		super(x, y, w, h, img_up_path, img_down_path, c);
		//this.setPos(x,y);
		//this.setSize(w,h);
		//this.setLabel(label);
		this.setController(c);

		PImage img_src = controller.applet.loadImage(img_up_path);

		img_up = controller.makeImgUp((int) w, (int) h, img_src);

		if (img_down_path != null && img_down_path != "")
			img_down = controller.makeImgDown((int) w, (int) h, controller.applet.loadImage(img_down_path));
		else
			img_down = controller.makeImgDown((int) w, (int) h, img_src);//ModalGUI.applet.loadImage(img_up_path);

		if (img_up != null)
			img_over = controller.makeImgOver((int) w, (int) h, img_src);//ModalGUI.applet.loadImage(img_up_path);

		this.setSize(this.img_up.width, this.img_up.height);

	}

	public GUIToggle(float x, float y, String img_up, ModalGUI c) {
		this(x, y, img_up, null, c);
	}

	public GUIToggle(float x, float y, String img_up_path,
			String img_down_path, ModalGUI c) {
		super(y, y, null, null, c);
		this.setController(c);
		this.setPos(x, y);
		//this.setSize(w,h);
		//this.setLabel(label);

		img_up = controller.applet.loadImage(img_up_path);

		if (img_down_path != null)
			img_down = controller.applet.loadImage(img_down_path);
		else
			img_down = controller.makeImgDown(img_up);//ModalGUI.applet.loadImage(img_up_path);

		if (img_up != null)
			img_over = controller.makeImgOver(img_up);//ModalGUI.applet.loadImage(img_up_path);

		this.setSize(this.img_up.width, this.img_up.height);

	}

	public void addLinkedVal(boolean link) {
		this.linkedVal = link;
		this.isDown = this.linkedVal;
	}

	void checkLinkedVal() {

		for (int i = 0; i < listeners.size(); i++) {
			GUIListener listener = listeners.get(i);

			if (listener == null || listener.methodName == "")
				return;
			Field field;
			try {

				field = listener.object.getClass()
						.getField(listener.methodName);
				Class classType = field.getType();

				if (classType.toString().equals("boolean"))
					this.isDown = field.getBoolean(listener.object);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}
		}

	}

	@Override
	public void mouseEvent(MouseEvent e) {
		//super.mouseEvent(e);

		if (!this.visible)
			return ;
		
		if(isMouseOver()){
			mouseOver = true;
			reRender();
		}else if(mouseOver){
			reRender();
			mouseOver = false;
		}
			
		
		
		if (this.destroy)
			return;

		if (justMade) {
			justMade = false;
			return;
		}
		//
		if (e.getID() == MouseEvent.MOUSE_PRESSED) {

			if (isMouseOver() && !wasClicked) {
				wasClicked = true;

			}
		} else if (e.getID() == MouseEvent.MOUSE_RELEASED && wasClicked
				&& isMouseOver()) {

			fireEventNotification(this, "Clicked");
			wasClicked = false;
			this.toggle();

		}

	}

	@Override
	public void render(PGraphics g) {
		
		
		
		//Render on update optimization
		if(controller.renderOnUpdate && !reRender){return;}
		if(controller.renderOnUpdate)
		reRender = false; // only render once

		
		
		if (!this.visible)
			return;

		if (this.destroy)
			return;
		

		checkLinkedVal();

		g.strokeWeight(1);
		g.noFill();
		float sw = g.strokeWeight;

		//setup fill colours

		if (this.getFillColour() != -2)
			g.fill(this.getFillColour());
		if (this.getStrokeColour() != -2)
			g.stroke(this.getStrokeColour());

		if (this.isDown) {
			g.strokeWeight(2);

			if (this.getFillColourDown() != -2)
				g.fill(this.getFillColourDown());
			if (this.getStrokeColourDown() != -2)
				g.stroke(this.getStrokeColourDown());
		}

		if (isMouseOver() && !this.isDown) {
			g.strokeWeight(2);

			if (this.getFillColourOver() != -2)
				g.fill(this.getFillColourOver());
			if (this.getStrokeColourOver() != -2)
				g.stroke(this.getStrokeColourOver());
		}

		
		
		//no images set
		if (this.img_clicked == null && this.img_down == null || isTab) {
			
			if (isTab && this.isDown) {
				
				g.stroke(this.getStrokeColour());
				g.strokeWeight(1);
				
				g.rect(this.getX(), this.getY(), this.getWidth(),
						this.getHeight() + 3,cornerRad,cornerRad,0,0);
	
				g.noStroke();
				g.rect(this.getX(), this.getY()+this.getHeight()-2, this.getWidth(),
						8);
				
				if(this.img_down != null)
					g.image(this.img_down ,this.getX()+this.getWidth()-img_up.width-5,this.getY()+3);
						
			} else{
				g.rect(this.getX(), this.getY(), this.getWidth(),
						this.getHeight(),cornerRad,cornerRad,0,0);
				
				if(this.img_up != null)
					g.image(this.img_up ,this.getX()+this.getWidth()-img_up.width-5,this.getY()+3);
				
			}
			//	return ;
		}

		if(!isTab){
		//  boolean hasFocus = controller.getFocusStatusForComponent(this);
		if (wasClicked && this.img_clicked != null) {
			g.image(this.img_clicked, (int)this.getX(), (int)this.getY());
		} else {
			if (isMouseOver() && this.img_over != null && !this.isDown) {
				g.image(this.img_over, (int)this.getX(), (int)this.getY());

			} else {

				if (this.isDown) {
					if (this.img_down != null)
						g.image(this.img_down, (int)this.getX(), (int)this.getY());
					else
						g.rect(this.getX(), this.getY(), this.getWidth(),
								this.getHeight());
				} else {
					if (this.img_up != null)
						g.image(this.img_up, (int)this.getX(), (int)this.getY());
					else
						g.rect(this.getX(), this.getY(), this.getWidth(),
								this.getHeight());

				}

			}
		}
		}
		
		renderLabel(g);
		g.noStroke();
	}

	@Override
	public void renderTop(PGraphics g) {
		if (isMouseOver() && this.toolTip != null) {
			this.renderToolTip(g, controller.applet.mouseX,
					controller.applet.mouseY);
			if (toolTipAlpha < 255)
				this.toolTipAlpha += 20;
		} else {
			this.toolTipAlpha = -100;
		}
		
	
	}

	public void setComponentSet(GUIComponentSet componentSet) {
		this.componentSet = componentSet;
		componentSet.add(this);

	}

	public void setState(boolean newState) {
		this.isDown = newState;
	}

	void toggle() {
		if (this.componentSet != null)
			this.componentSet.setAllUp();

		this.isDown = !this.isDown;

		this.fireEventNotification(this.isDown);
		this.fireEventNotification("");

	}
	
	public void toggleDown() {
		if (this.componentSet != null)
			this.componentSet.setAllUp();

		this.isDown = true;

		this.fireEventNotification(this.isDown);
		this.fireEventNotification("");

	}

} public class ModalGUI implements MouseWheelListener {
	public static PApplet applet;
	public static PApplet appletStatic;
	boolean clickStartedOn = false;
	public boolean renderOnUpdate = true; //only render components when they're updated or mouse is over.
	public boolean rebuildStencilBuffer = true;
	public static PImage makeImgDown(float w, float h, PImage img) {

		PGraphics pg = appletStatic.createGraphics((int) w, (int) h,
				PApplet.JAVA2D);
		pg.smooth();
		pg.beginDraw();
		
		pg.noStroke();
		pg.background(255);
		pg.rect(0,0,w,h);
		
		
		pg.smooth();
		pg.stroke(200, 200, 200);
		pg.fill(194, 217, 216);

		pg.strokeWeight(1);

		roundrect(pg, 0, 0, w + 4, h + 4, 4);

		//pg.strokeWeight(2);
		//pg.stroke(100, 100, 100);

		//roundrectLeft(pg, 2, 2, w - 4, h - 4, 4);

		int offsetX = (int) ((w - img.width) / 2);
		int offsetY = (int) ((h - img.height) / 2);
		pg.image(img, (int)offsetX, (int)offsetY);
		pg.endDraw();
		return pg;

	}

	public static PImage makeImgDown(PImage img) {
		return makeImgDown(img.width, img.height, img);
	}

	public static PImage makeImgOver(int w, int h, PImage img) {

		PGraphics pg = appletStatic.createGraphics(w, h, PApplet.JAVA2D);
		pg.smooth();
		pg.beginDraw();
		
		pg.noStroke();

		pg.smooth();
		pg.strokeWeight(1);
		pg.stroke(200, 200, 200);
		pg.noFill();

		roundrect(pg, 0, 0, w + 4, h + 4, 4); //right bottom border off texture
		int offsetX = (int) ((w - img.width) / 2);
		int offsetY = (int) ((h - img.height) / 2);
		pg.image(img, (int)offsetX, (int)offsetY);
		pg.endDraw();
		return pg;

	}

	public static PImage makeImgOver(PImage img) {
		return makeImgOver(img.width, img.height, img);
	}

	public static PImage makeImgUp(float w, float h, PImage img) {

		PGraphics pg = appletStatic.createGraphics((int) w, (int) h,
				PApplet.JAVA2D );
		pg.smooth();
		pg.beginDraw();
		pg.smooth();
		
		pg.noStroke();

		pg.stroke(200, 200, 200);
		pg.fill(255, 255, 255);

		int offsetX = (int) ((w - img.width) / 2);
		int offsetY = (int) ((h - img.height) / 2);
		pg.image(img, (int)offsetX, (int)offsetY);
		pg.endDraw();
		return pg;

	}

	static void roundrect(PGraphics g, float x, float y, float w, float h,
			float r) {
/*
 *http://quasipartikel.at/2010/01/07/quadratic-bezier-curves-for-processingjs/
		g.beginShape();
		g.vertex(x+r, y);
		g.vertex(x+w-r, y);
		quadraticBezierVertex(g,x+w, y, x+w, y+r,x+w-r,y);
		g.vertex(x+w, y+h-r);
		  quadraticBezierVertex(g,x+w, y+h, x+w-r, y+h,x+w, y+h-r);
		  g.vertex(x+r, y+h);
		  quadraticBezierVertex(g,x, y+h, x, y+h-r,x+r, y+h);
		  g.vertex(x, y+r);
		  quadraticBezierVertex(g,x, y, x+r, y,x, y+r);
		  g.endShape();
		  
		*/
		g.beginShape();
		g.vertex(x + r, y);
		g.vertex(x + w - r, y);
		g.bezierVertex(x + w, y, x + w, y + r, x + w, y + r);

		g.vertex(x + w, y + r);
		g.vertex(x + w, y + h - r);
		g.bezierVertex(x + w, y + h, x + w - r, y + h, x + w - r, y + h);

		g.vertex(x + w - r, y + h);
		g.vertex(x + r, y + h);
		g.bezierVertex(x, y + h, x, y + h - r, x, y + h - r);

		g.vertex(x, y + h - r);
		g.vertex(x, y + r);
		g.bezierVertex(x, y, x + r, y, x + r, y);
		g.endShape();

		/*
		//line 1
		g.vertex(x, y+h-r);
		g.vertex(x, y+r);
		g.bezierVertex(x, y, x+r, y, x+r, y);
		
		
		//line 1
		g.vertex(x+r, y);
		g.vertex(x+w-r, y);
		
		g.bezierVertex(x+w, y,x+w, y+r, x+w, y+r);
		
		
		//line 1
		g.vertex(x+w, y+r);
		g.vertex(x+w, y+h-r);
		
		g.bezierVertex(x+w, y+h, x+w-r, y+h, x+w-r, y+h);
		
		
		//line 1
		g.vertex(x+w-r, y+h);
		g.vertex(x+r, y+h);
		
		
		g.bezierVertex(x, y+h, x, y+h-r, x, y+h-r);
		*/

		g.endShape(g.CLOSE);

	}
	
	static void quadraticBezierVertex(PGraphics g, float cpx, float cpy, float x, float y, float prevX ,float prevY) {
		  float cp1x = (float) (prevX + 2.0/3.0*(cpx - prevX));
		  float cp1y = (float) (prevY + 2.0/3.0*(cpy - prevY));
		  float cp2x = (float) (cp1x + (x - prevX)/3.0);
		  float cp2y = (float) (cp1y + (y - prevY)/3.0);

		  // finally call cubic Bezier curve function
		  g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y);
		};
		
		

	static void roundrectLeft(PGraphics g, float x, float y, float w, float h,
			float r) {

		g.beginShape();

		g.vertex(x + r, y + h);
		g.bezierVertex(x, y + h, x, y + h - r, x, y + h - r);

		g.vertex(x, y + h - r);
		g.vertex(x, y + r);
		g.bezierVertex(x, y, x + r, y, x + r, y);

		g.endShape(g.OPEN);

	}

	public GUIComponents components = new GUIComponents();
	public PFont myFontMedium = null;

	public boolean performanceMode = true;

	public boolean physics_on = false;

	public boolean useAlphaMouseOver = false;

	private boolean registeredEvent = false;

	public float labelSize = 12;

	public ModalGUI() {

	}

	public ModalGUI(PApplet main) {
		this.setup(main);

	}

	public void add(GUIComponent component) {
		component.setController(this);
		components.add(component);
	}

	public boolean hasFocus() {
		return components.hasFocus();

	}

	public void keyEvent(KeyEvent keyevent) {
		this.components.keyEvent(keyevent);

	}

	public void mouseEvent(MouseEvent e) {
		this.components.mouseEvent(e);
		if (e.getID() == 501) {
			
			reRender();

			
			if (overComponent())
				clickStartedOn = true;
			
		} else if (e.getID() == 502) {
			reRender();

				clickStartedOn = false;
		}
		
		
	}
	
	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		this.components.mouseWheelMoved(e);

	}
	
	

	public boolean overComponent() {
		return components.overComponent();
	}

	
	public boolean clickStartedOn() {
		return clickStartedOn;
	}

	public void reload() {
		this.setup(this.applet);
	}

	public void render(PGraphics g) {
		

		components.render(g);
		/*

		if(rebuildStencilBuffer && renderOnUpdate){
			rebuildStencilBuffer= false;
			
			GL gl = (g);
			  GLCapabilities capabilities = new GLCapabilities();
			  int bits = capabilities.getStencilBits();
			  capabilities.setStencilBits(8);
			  bits = capabilities.getStencilBits();
			  IntBuffer i = IntBuffer.allocate(100);

			  
			  gl.glClearStencil(0x0);  
			  gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			  gl.glClear( GL.GL_STENCIL_BUFFER_BIT);
			  gl.glDisable(GL.GL_DEPTH_TEST);

			  gl.glGetIntegerv(GL.GL_STENCIL_BITS, i);
			  gl.glColorMask(false, false, false, false); 

			  
			  	gl.glEnable(GL.GL_STENCIL_TEST);
				gl.glStencilFunc(GL.GL_ALWAYS, 1, 1);                     // Always Passes, 1 Bit Plane, 1 As Mask
				gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_REPLACE); 
				  gl.glDisable(GL.GL_DEPTH_TEST);
				  
				  components.reRender();
				  components.render(g);
				  components.reRender();
				gl.glStencilFunc(GL.GL_EQUAL,1, 0xFFFFFFFF);     // mask  

			
		}
	*/
	}
	
	public void reRender(){

		components.reRender();
	}

	public void reBuildStencilBuffer(){
		rebuildStencilBuffer = true;
	}
	
	public void reset() {
		
		this.components.reset();
	   this.reBuildStencilBuffer();

	}

	public void setup(PApplet main) {
		this.applet = main;
		this.appletStatic = main;

		components = new GUIComponents();
		//	URL res = cl.getResource("data/TrebuchetMS-12.vlw");
		/*
		try {
			//InputStream stream = res.openStream();
			
			//InputStream input = new FileInputStream(res.getPath());
			InputStream input = cl.getResourceAsStream("data/HelveticaNeueLT-Medium-48.vlw");
		     // String cn = input.getClass().getName();
		      //System.out.println(cn);
		      
		      DataInputStream is = new DataInputStream(input);

			this.myFontMedium =  new PFont(input);
			
			//if(stream.available() > 0){
		    //this.myFont =  new PFont(stream);
			//}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/

		//applet.textMode(PApplet.SCREEN);

		if (!registeredEvent) {
			
			applet.registerMouseEvent(this);
			applet.registerKeyEvent(this);
			applet.addMouseWheelListener(this);
			registeredEvent = true;
		

		}
	}

	public boolean textfieldHasFocus() {
		return components.textfieldHasFocus();
	}

	public void update() {
		this.components.update();
	}

	public static String loadedCursor = null;
	public static void setCursor(PApplet applet, PImage _cursorImg){

		if(loadedCursor == null || !loadedCursor.equals(_cursorImg.toString()) ){
			loadedCursor = _cursorImg.toString();
			applet.cursor(_cursorImg,(int)(_cursorImg.width/2),(int)(_cursorImg.height/2));
		}
	}
	
	public static void setCursor(PApplet applet, PImage _cursorImg, int _x, int _y){

		if(loadedCursor == null || !loadedCursor.equals(_cursorImg.toString()) ){
			loadedCursor = _cursorImg.toString();
			applet.cursor(_cursorImg,_x,_y);
		}
	}


}
import ModalGUI.GUIToggle;
import ModalGUI.ModalGUI;
import processing.core.PApplet;
import cc.sketchchair.core.GLOBAL;
import cc.sketchchair.core.LOGGER;
import cc.sketchchair.core.SETTINGS;
import cc.sketchchair.core.UITools;
import ModalGUI.GUIButton;
import ModalGUI.GUILabel;
import ModalGUI.GUINumberfield;
import ModalGUI.GUIPanel;
import ModalGUI.GUISlider;
import ModalGUI.GUITextfield;
/*******************************************************************************
 * This is part of SketchChair, an open-source tool for designing your own furniture.
 *     www.sketchchair.cc
 *     
 *     Copyright (C) 2012, Diatom Studio ltd.  Contact: hello@diatom.cc
 * 
 *     This program is 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, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     This program 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 <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package cc.sketchchair.widgets;



/**
 * GUI widget used for selecting material properties. 
 * @author gregsaul
 *
 */
public class WidgetMaterials extends GUIPanel{

	public GUIPanel panel;

	public GUINumberfield slotSizeTextfield = null;

	private GUISlider scaleSlider;

	private GUINumberfield cuttingBitSize;

	private GUIToggle toggleDogbones;

	public WidgetMaterials(float x, float y, float w, float h, ModalGUI gui) {
		super(x, y, w, h, gui);
		


	float toggleSize = 25;

		

		//GUILabel label = new GUILabel(15, 15, "cutting sheet size", gui);
		//add(label);


		
		
		
		
		
		
		
		
		
		
		
		label = new GUILabel(20, 30, "scale", gui);
		add(label);
		
		
		
		scaleSlider = new GUISlider(70, 30, 85, 1, 25, this.controller);
		scaleSlider.setParentPanel(this);
		scaleSlider.setVal(10);
		scaleSlider.setShowValLabel(true);
		scaleSlider.setFormatValLabel("1:%1$.0f");
		scaleSlider.setLabelValMultiplier(1.0f);
		scaleSlider.setEndImgs(GLOBAL.applet.loadImage("gui/SLIDER_DESIGN_SCALE_MIN.png"),GLOBAL.applet.loadImage("gui/SLIDER_DESIGN_SCALE_MAX.png"));