/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tgfx.render;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.binding.BooleanExpression;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import tgfx.Main;
import tgfx.tinyg.CommandManager;
import tgfx.tinyg.TinygDriver;
import tgfx.ui.gcode.GcodeTabController;
/**
*
* @author rileyporter
*/
public class CNCMachine extends Pane {
public static StackPane gcodePane = new StackPane(); //Holds CNCMachine
private BooleanExpression cursorVisibleBinding;
private DecimalFormat df = new DecimalFormat("#.##");
private final Circle cursorPoint = new Circle(2, javafx.scene.paint.Color.RED);
private static double xPrevious;
private static double yPrevious;
private boolean _msgSent = false;
private double magnification = 1;
private SimpleDoubleProperty cncHeight = new SimpleDoubleProperty();
private SimpleDoubleProperty cncWidth = new SimpleDoubleProperty();
private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(CNCMachine.class);
public CNCMachine() {
//Cursor point indicator
cursorPoint.setRadius(1);
this.setMaxSize(0, 0); //hide this element until we connect
//Set our machine size from tinyg travel max
this.setVisible(false);
this.setPadding(new Insets(10));
this.setFocusTraversable(true);
this.setFocused(true);
/*####################################
*CSS
#################################### */
this.setStyle("-fx-background-color: black; -fx-border-color: orange; -fx-border-width: .5;");
/*####################################
*PositionCursor Set
#################################### */
final Circle c = new Circle(2, Color.RED);
final Text cursorText = new Text("None");
cursorText.setFill(Color.YELLOW);
cursorText.setFont(Font.font("Arial", 6));
setupLayout(); //initial layout setup in constructor
/*####################################
*Event / Change Listeners
*#################################### */
//ugh...
//
//
// ChangeListener posChangeListener = new ChangeListener() {
// @Override
// public void changed(ObservableValue ov, Object t, Object t1) {
// if (TinygDriver.getInstance().m.getAxisByName("y").getMachinePosition() > heightProperty().get()
// || TinygDriver.getInstance().m.getAxisByName("x").getMachinePosition() > widthProperty().get()) {
// hideOrShowCursor(false);
// } else {
// hideOrShowCursor(true);
// }
//
// }
// };
this.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent me) {
// gcodePane.getChildren().remove(c);
getChildren().remove(cursorText);
unFocusForJogging();
}
});
this.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent me) {
setFocusForJogging();
requestFocus();
}
});
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(final MouseEvent me) {
//This is so we can set our machine position when a machine does not have homing switches
if (me.getButton().equals(MouseButton.SECONDARY)) {
//Right Clicked
ContextMenu cm = new ContextMenu();
MenuItem menuItem1 = new MenuItem("Set Machine Position");
menuItem1.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
Draw2d.setFirstDraw(true); //We do not want to draw a line from our previous position
TinygDriver.getInstance().cmdManager.setMachinePosition(getNormalizedX(me.getX()), getNormalizedY(me.getY()));
Draw2d.setFirstDraw(true); //This allows us to move our drawing to a new place without drawing a line from the old.
try {
TinygDriver.getInstance().write(CommandManager.CMD_APPLY_SYSTEM_ZERO_ALL_AXES);
TinygDriver.getInstance().write(CommandManager.CMD_QUERY_STATUS_REPORT);
} catch (Exception ex) {
Logger.getLogger(CNCMachine.class.getName()).log(Level.SEVERE, null, ex);
}
//G92 does not invoke a status report... So we need to generate one to have
//Our GUI update the coordinates to zero
}
});
cm.getItems().add(menuItem1);
cm.show((Node) me.getSource(), me.getScreenX(), me.getScreenY());
}
}
});
/*####################################
*Bindings
*#################################### */
maxHeightProperty().bind(TinygDriver.getInstance().machine.getAxisByName("y").getTravelMaxSimple().multiply(TinygDriver.getInstance().machine.gcodeUnitDivision));
maxWidthProperty().bind(TinygDriver.getInstance().machine.getAxisByName("x").getTravelMaxSimple().multiply(TinygDriver.getInstance().machine.gcodeUnitDivision));
cursorPoint.translateYProperty().bind(this.heightProperty().subtract(TinygDriver.getInstance().machine.getAxisByName("y").getMachinePositionSimple()));
cursorPoint.layoutXProperty().bind(TinygDriver.getInstance().machine.getAxisByName("x").getMachinePositionSimple());
// cncHeight.bind(this.heightProperty());
// cncWidth.bind(this.widthProperty());
// cursorPoint.layoutXProperty().addListener(posChangeListener); //When the x or y pos changes we see if we want to show or hide the cursor
// cursorPoint.layoutYProperty().addListener(posChangeListener);
}
private void hideOrShowCursor(boolean choice) {
this.visibleProperty().set(choice);
}
private void unFocusForJogging() {
this.setFocused(true);
// Main.postConsoleMessage("UnFocused");
GcodeTabController.hideGcodeText();
}
private void setFocusForJogging() {
this.setFocused(true);
// Main.postConsoleMessage("Focused");
GcodeTabController.setGcodeText("Jogging Enabled");
}
public double getNormalizedX(double x) {
return (Double.valueOf((x / TinygDriver.getInstance().machine.gcodeUnitDivision.get())));
}
public double getNormalizedY(double y) {
return (Double.valueOf((getHeight() - y) / TinygDriver.getInstance().machine.gcodeUnitDivision.get()));
}
public String getNormalizedYasString(double y) {
return (df.format(getNormalizedY(y)));
}
public String getNormalizedXasString(double x) {
return (df.format(getNormalizedX(x)));
}
public boolean checkBoundsY(Line l) {
if ((this.getHeight() - l.getEndY()) >=0 && (this.getHeight() - l.getEndY()) <= this.getHeight() + 1) {
return true;
} else {
return false;
}
}
public boolean checkBoundsX(Line l) {
if (l.getEndX() >= 0 && l.getEndX() <= this.getWidth()) {
return true;
} else {
return false;
}
}
public void clearScreen() {
this.getChildren().clear();
Draw2d.setFirstDraw(true); //We don't want to draw a line from where the previous point was when a clear screen is called.
setupLayout(); //re-draw the needed elements.
}
/**
*
* @param moveType
* @param vel
*/
public void drawLine(String moveType, double vel) {
Line l;
l = new Line();
l.setSmooth(true);
//Code to make mm's look the same size as inches
double scale = 1;
double unitMagnication = 1;
// if (TinygDriver.getInstance().m.getGcodeUnitMode().get().equals(Gcode_unit_modes.inches.toString())) {
// unitMagnication = 5; //INCHES
// } else {
// unitMagnication = 2; //MM
// }
// double newX = unitMagnication * (Double.valueOf(TinygDriver.getInstance().m.getAxisByName("X").getWork_position().get()) + 80);// + magnification;
// double newY = unitMagnication * (Double.valueOf(TinygDriver.getInstance().m.getAxisByName("Y").getWork_position().get()) + 80);// + magnification;
// if (newX > gcodePane.getWidth() || newX > gcodePane.getWidth()) {
// scale = scale / 2;
// Line line = new Line();
// Iterator ii = gcodePane.getChildren().iterator();
// gcodePane.getChildren().clear(); //remove them after we have the iterator
// while (ii.hasNext()) {
// if (ii.next().getClass().toString().contains("Line")) {
// //This is a line.
// line = (Line) ii.next();
// line.setStartX(line.getStartX() / 2);
// line.setStartY(line.getStartY() / 2);
// line.setEndX(line.getEndX() / 2);
// line.setEndY(line.getEndY() / 2);
// gcodePane.getChildren().add(line);
//
// }
// }
// console.appendText("[+]Finished Drawing Prevew Scale Change.\n");
// gcodeWindow.setScaleX(scale);
// gcodeWindow.setScaleY(scale);
// }
// Main.print(gcodePane.getHeight() - TinygDriver.getInstance().m.getAxisByName("y").getWork_position().get());
double newX = TinygDriver.getInstance().machine.getAxisByName("x").getMachinePositionSimple().get();// + magnification;
double newY = this.getHeight() - TinygDriver.getInstance().machine.getAxisByName("y").getMachinePositionSimple().get();//(gcodePane.getHeight() - (Double.valueOf(TinygDriver.getInstance().m.getAxisByName("y").getWork_position().get())));// + magnification;
if (Draw2d.isFirstDraw()) {
//This is to not have us draw a line on the first connect.
l = new Line(newX, this.getHeight(), newX, this.getHeight());
Draw2d.setFirstDraw(false);
} else {
l = new Line(xPrevious, yPrevious, newX, newY);
l.setStrokeWidth(.5);
}
xPrevious = newX;
yPrevious = newY; //TODO Pull these out to CNC machine or Draw2d these are out of place
if (TinygDriver.getInstance().machine.getMotionMode().get().equals("traverse")) {
//G0 Moves
l.getStrokeDashArray().addAll(1d, 5d);
l.setStroke(Draw2d.TRAVERSE);
} else {
// l.setStroke(Draw2d.getLineColorFromVelocity(vel));
l.setStroke(Draw2d.FAST);
}
if (l != null) {
if (this.checkBoundsX(l) && this.checkBoundsY(l)) {
//Line is within the travel max gcode preview box. So we will draw it.
this.getChildren().add(l); //Add the line to the Pane
// cursorPoint.visibleProperty().set(true);
_msgSent = false;
if (!getChildren().contains(cursorPoint)) { //If the cursorPoint is not in the Group and we are in bounds
this.getChildren().add(cursorPoint); //Adding the cursorPoint back
}
} else {
Logger.getLogger("Main").info("Outside of Bounds X");
if (getWidth() != 21 && getHeight() != 21) { //This is a bug fix to avoid the cursor being hidden on the initial connect.
//This should be fairly harmless as it will always show the cursor if its the inital connect size 21,21
//its a bit of a hack but it works for now.
// cursorPoint.visibleProperty().set(false);
// Draw2d.setFirstDraw(true);
if (getChildren().contains(cursorPoint)) { //If cursor is in the group we are going to remove it util above is true
getChildren().remove(this.getChildren().indexOf(cursorPoint)); //Remove it.
if (!_msgSent) {
Main.postConsoleMessage("You are out of your TinyG machine working envelope. You need to either move back in by jogging, homing"
+ "\n or you can right click on the Gcode Preview and click set position to set your estimated position.\n");
_msgSent = true; //We do this as to not continue to spam the user with out of bound errors.
}
}
}else{
}
}
}
}
public void zeroSystem() {
if (TinygDriver.getInstance().isConnected().get()) {
try {
Draw2d.setFirstDraw(true); //This allows us to move our drawing to a new place without drawing a line from the old.
TinygDriver.getInstance().write(CommandManager.CMD_APPLY_SYSTEM_ZERO_ALL_AXES);
//G92 does not invoke a status report... So we need to generate one to have
//Our GUI update the coordinates to zero
TinygDriver.getInstance().write(CommandManager.CMD_QUERY_STATUS_REPORT);
//We need to set these to 0 so we do not draw a line from the last place we were to 0,0
resetDrawingCoords();
} catch (Exception ex) {
}
}
}
public static void resetDrawingCoords() {
//After a reset has occured we call this ot reset the previous coords.
xPrevious = 0;
yPrevious = 0;
}
private void setupLayout() {
//This draws the x axis text as well as grid etc
Text xText = new Text("X Axis");
Text yText = new Text("Y Axis");
xText.setY(-10);
xText.xProperty().bind(this.heightProperty().divide(2));
xText.setRotate(0);
xText.setFill(Color.YELLOW);
xText.setFont(Font.font("Arial", 10));
yText.setX(-25);
yText.yProperty().bind(this.widthProperty().divide(2));
yText.setRotate(-90);
yText.setFill(Color.YELLOW);
yText.setFont(Font.font("Arial", 10));
this.getChildren().add(xText);
this.getChildren().add(yText);
this.setCursor(Cursor.CROSSHAIR);
this.getChildren().add(cursorPoint);
}
public void autoScaleWorkTravelSpace(double scaleAmount) {
//Get the axis with the smallest available space. Think aspect ratio really
double stroke = 2 / scaleAmount;
this.setScaleX(scaleAmount);
this.setScaleY(scaleAmount);
Iterator ii = this.getChildren().iterator();
while (ii.hasNext()) {
if (ii.next().getClass().getName().endsWith("Line")) {
Line l = (Line) ii.next();
l.setStrokeWidth(stroke);
}
}
}
}