Icon.java
package no.ntnu.idatt1002.demo.view.components;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.FillRule;
import javafx.scene.shape.SVGPath;
import no.ntnu.idatt1002.demo.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
/**
* Icon class for the Application.
*/
public class Icon extends VBox {
// TODO: Fix so that it scales correctly and that it does not move wierd when
// scaled.
// In addition make the icon get all the properties defined within the svg file
// such as strokewidth, fill and so on.
private final String filePath = "/no/ntnu/idatt1002/icons/";
private final SVGPath svgPath;
public static final int DEFAULT_SIZE = 10;
// private static final float DEFAULT_SCALE = 0.1f;
private final double strokeWidth = 1.5;
private final String iconName;
private int x;
private int y;
private int size;
/**
* Constructor for the Icon class.
*
* @param iconName Name of the icon
*/
public Icon(String iconName) {
this(iconName, DEFAULT_SIZE);
}
/**
* Constructor for the Icon class.
*
* @param iconName Name of the icon
* @param size Size of the icon, width and height
*/
public Icon(String iconName, int size) {
this.iconName = iconName;
this.size = size;
// Path to the SVG file
String FilePath = this.filePath + iconName + ".svg";
// Set the content of the SVG path
String svgFileContent = readSvgFromFile(FilePath);
// Split the SVG content and get the data value from the path
String svgPathString = "";
try {
String[] svgContent = svgFileContent.split("\n");
for (String line : svgContent) {
if (line.contains("<path")) {
svgPathString = getSvgPathString(line);
}
if (line.contains("<rect")) {
Rectangle svgRect = getSvgRect(line);
this.getChildren().add(svgRect);
}
if (line.contains("<circle")) {
SVGPath svgCircle = getSvgCircle(line);
svgCircle.getStyleClass().add("centered");
this.getChildren().add(svgCircle);
}
}
} catch (Exception e) {
Logger.debug(e.getMessage());
}
// Create a new SVGPath
svgPath = new SVGPath();
// Set the content of the SVG path
svgPath.setContent(svgPathString);
// You can customize the appearance of the SVG path
svgPath.setStrokeWidth(strokeWidth);
svgPath.setStrokeType(javafx.scene.shape.StrokeType.CENTERED);
svgPath.setStroke(Color.BLACK);
getChildren().add(svgPath);
this.svgPath.getStyleClass().addAll("icon-no-fill", "centered");
this.getStyleClass().add("icon-container");
}
/**
* Set the fill color of the icon.
*
* <p>
* Fills the icon with the given color. Pass null to remove the fill.
* </p>
*
* @param color The color to fill the icon with
*/
public Icon setFillColor(Color color) {
if (color == null) {
this.svgPath.getStyleClass().add("icon-no-fill");
return this;
}
this.svgPath.getStyleClass().remove("icon-no-fill");
svgPath.setFill(color);
return this;
}
/**
* Reads the SVG file and returns the content as a string.
*
* @param filePath Path to the SVG file
* @return Content of the SVG file as a string
*/
private String readSvgFromFile(String filePath) {
try {
return new String(getClass().getResourceAsStream(filePath).readAllBytes());
} catch (Exception e) {
Logger.debug(e.getMessage());
return ""; // Return empty string if there's an error reading the file
}
}
/**
* Splits the SVG content and returns the value of the attribute.
*
* @param svgContent Content of the SVG file
* @return Value of the attribute
*/
private String getSvgPathString(String svgContent) {
return svgContent.split("d" + "=\"")[1].split("\"")[0];
}
/**
* Splits the provided line from the SVG file and returns the Rectangle that the
* SVG is describing.
*
* @param svgContent Content of the SVG file
* @return The Rectangle described in the SVG file
*/
private Rectangle getSvgRect(String svgContent) {
String rectData = svgContent.split("<rect")[1].split("/>")[0];
int width = Integer.parseInt(rectData.split("width=\"")[1].split("\"")[0]);
int height = Integer.parseInt(rectData.split("height=\"")[1].split("\"")[0]);
// int rx = Integer.parseInt(rectData.split("rx=\"")[1].split("\"")[0]);
String fill = rectData.split("fill=\"")[1].split("\"")[0];
Rectangle svgRect = new Rectangle(width, height);
svgRect.setFill(Paint.valueOf(fill));
return svgRect;
}
/**
* Splits the provided line from the SVG file and returns the Circle that the
* SVG is describing.
*
* @param svgContent Content of the SVG file
* @return The Circle described in the SVG file
*/
private SVGPath getSvgCircle(String svgContent) {
String circleData = svgContent.split("<circle")[1].split("/>")[0];
int cx = Integer.parseInt(circleData.split("cx=\"")[1].split("\"")[0]);
int cy = Integer.parseInt(circleData.split("cy=\"")[1].split("\"")[0]);
double r = Double.parseDouble(circleData.split("r=\"")[1].split("\"")[0]);
SVGPath svgCircle = new SVGPath();
svgCircle.setContent("M" + cx + " " + cy + "m" + -r + " 0a" + r + " " + r + " 0 1,0 " + r * 2 + " 0a" + r + " " + r
+ " 0 1,0 " + -r * 2 + " 0");
if (circleData.contains("stroke=\"")) {
String stroke = circleData.split("stroke=\"")[1].split("\"")[0];
int strokeWidth = Integer.parseInt(circleData.split("stroke-width=\"")[1].split("\"")[0]);
svgCircle.setStroke(Color.valueOf(stroke));
svgCircle.setStrokeWidth(strokeWidth);
}
if (circleData.contains("fill=\"")) {
String fill = circleData.split("fill=\"")[1].split("\"")[0];
svgCircle.setFill(Paint.valueOf(fill));
} else {
svgCircle.setFill(Color.TRANSPARENT);
}
return svgCircle;
}
public void setStrokeColor(Color color) {
svgPath.setStroke(color);
}
/**
* Splits the SVG content and returns the value of the attribute.
*
* @param svgContent Content of the SVG file
* @param regex Regex to split the content
* @return Value of the attribute
*/
private String splitSvgContent(String svgContent, String regex) {
return svgContent.split(regex + "=\"")[1].split("\"")[0];
}
/**
* Set the x value of the icon.
*
* @param x X position
*/
public void setX(int x) {
this.x = x;
setTranslateX(x);
}
/**
* Set the y value of the icon.
*
* @param y Y position
*/
public void setY(int y) {
this.y = y;
setTranslateY(y);
}
/**
* Set the position of the icon.
*
* @param x X position
* @param y Y position
*/
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
setTranslateX(x);
setTranslateY(y);
}
/**
* Set the size of the icon.
*
* @param size Size of the icon
*/
public void setSize(int size) {
// TODO: this """works""" but it still requires manual adjustment of the
// position. Fix this
this.size = size;
this.svgPath.setScaleX(size);
this.svgPath.setScaleY(size);
}
/**
* Scales the icon.
*
* @param scale Scale of the icon
*/
public void scale(double scale) {
this.svgPath.setScaleX(scale);
this.svgPath.setScaleY(scale);
}
/**
* Get the x value of the icon.
*
* @return x position
*/
public int getX() {
return x;
}
/**
* Get the y value of the icon.
*
* @return y position
*/
public int getY() {
return y;
}
/**
* Get the size of the icon.
*
* @return size of the icon
*/
public int getSize() {
return size;
}
/**
* Get the name of the icon.
*
* @return name of the icon
*/
public String getIconName() {
return iconName;
}
}