From fc9c3260bcad911c7a5e3cacfa96a75a20d696ba Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Wed, 14 Feb 2024 17:47:42 +0100 Subject: [PATCH] feat:initial src --- .gitignore | 16 ++ pom.xml | 90 ++++++++++ src/main/java/cz/vsb/fei/java2/lab04/App.java | 53 ++++++ .../cz/vsb/fei/java2/lab04/AppController.java | 167 ++++++++++++++++++ .../cz/vsb/fei/java2/lab04/ColorPoint.java | 47 +++++ .../java/cz/vsb/fei/java2/lab04/Point.java | 49 +++++ src/main/java/module-info.java | 8 + .../cz/vsb/fei/java2/lab04/AppWindow.fxml | 141 +++++++++++++++ .../cz/vsb/fei/java2/lab04/application.css | 1 + src/main/resources/log4j2.xml | 13 ++ .../java/cz/vsb/fei/java2/lab04/AppTest.java | 19 ++ 11 files changed, 604 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/App.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/AppController.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java create mode 100644 src/main/java/cz/vsb/fei/java2/lab04/Point.java create mode 100644 src/main/java/module-info.java create mode 100644 src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml create mode 100644 src/main/resources/cz/vsb/fei/java2/lab04/application.css create mode 100644 src/main/resources/log4j2.xml create mode 100644 src/test/java/cz/vsb/fei/java2/lab04/AppTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98b99a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Eclipse +.classpath +.project +.settings/ + +# Intellij +.idea/ +*.iml +*.iws + +# Mac +.DS_Store + +# Maven +log/ +target/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c29b6f3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,90 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>cz.vsb.fei.java2</groupId> + <artifactId>lab04</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <name>lab04</name> + + <packaging>jar</packaging> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.release>21</maven.compiler.release> + <JavaFX.version>22-ea+16</JavaFX.version> + <JUnit.version>5.10.1</JUnit.version> + <log4j.version>2.22.1</log4j.version> + <lombok.version>1.18.30</lombok.version> + </properties> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.junit</groupId> + <artifactId>junit-bom</artifactId> + <version>${JUnit.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-controls</artifactId> + <version>${JavaFX.version}</version> + </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-fxml</artifactId> + <version>${JavaFX.version}</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <version>${log4j.version}</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.12.1</version> + <configuration> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </path> + </annotationProcessorPaths> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.2.1</version> + </plugin> + </plugins> + </build> + +</project> diff --git a/src/main/java/cz/vsb/fei/java2/lab04/App.java b/src/main/java/cz/vsb/fei/java2/lab04/App.java new file mode 100644 index 0000000..d2abb16 --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/App.java @@ -0,0 +1,53 @@ +package cz.vsb.fei.java2.lab04; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.TabPane; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import lombok.extern.log4j.Log4j2; + +/** + * Class <b>App</b> - extends class Application and it is an entry point of the program + * @author Java I + */ +@Log4j2 +public class App extends Application { + + public static void main(String[] args) { + log.info("Launching JavaFX application."); + launch(args); + } + + private AppController controller; + + @Override + public void start(Stage primaryStage) { + try { + //Construct a main window with a canvas. + + FXMLLoader loader = new FXMLLoader(this.getClass().getResource("AppWindow.fxml")); + + TabPane root = loader.load(); + + Scene scene = new Scene(root); + + + primaryStage.setScene(scene); + primaryStage.setTitle("Hello word app"); + primaryStage.show(); + controller = loader.getController(); + + //Exit program when main window is closed + primaryStage.setOnCloseRequest(this::exitProgram); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void exitProgram(WindowEvent evt) { + System.exit(0); + } +} \ No newline at end of file diff --git a/src/main/java/cz/vsb/fei/java2/lab04/AppController.java b/src/main/java/cz/vsb/fei/java2/lab04/AppController.java new file mode 100644 index 0000000..b4c4b94 --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/AppController.java @@ -0,0 +1,167 @@ +package cz.vsb.fei.java2.lab04; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.Stream; + +import javafx.beans.binding.ObjectBinding; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.chart.BarChart; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Data; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; + +public class AppController { + + private static final Random RANDOM = new Random(); + private static final List<Color> COLORS = Arrays.asList(Color.RED, Color.BLUE, Color.YELLOW, Color.BLACK, + Color.ORANGE, Color.PINK, Color.PURPLE); + + @FXML + private TableView<Point> table1; + private ObservableList<Point> points1 = FXCollections.observableArrayList(); + + private Canvas canvas = new Canvas() { + @Override + public boolean isResizable() { + return true; + } + }; + + @FXML + private BorderPane pane; + + @FXML + private BarChart<String, Long> chart; + + @FXML + public void initialize() { + table1.setItems(points1); + + initColumns(table1); + table1.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + table1.getSelectionModel().selectedItemProperty() + .addListener((ObservableValue<? extends Point> observable, Point oldValue, Point newValue) -> draw()); + canvas.setWidth(200); + canvas.setHeight(200); + pane.setCenter(canvas); + pane.widthProperty() + .addListener((observer, oldValue, newValue) -> canvas.setWidth(newValue.doubleValue() * 0.9)); + pane.heightProperty() + .addListener((observer, oldValue, newValue) -> canvas.setHeight(newValue.doubleValue() * 0.9)); + canvas.boundsInLocalProperty().addListener((observable, oldValue, newValue) -> draw()); + draw(); + + } + + private void draw() { + GraphicsContext gc = canvas.getGraphicsContext2D(); + double maxX = canvas.getWidth(); + double maxY = canvas.getHeight(); + double centerX = maxX / 2; + double centerY = maxY / 2; + gc.setFill(Color.WHITE); + gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); + gc.setStroke(Color.BLACK); + gc.strokeLine(centerX, 0, centerX, maxY); + gc.strokeLine(0, centerY, maxX, centerY); + gc.setFill(Color.BLACK); + Point selectedPoint = table1.getSelectionModel().getSelectedItem(); + for (Point point : points1) { + if (point instanceof ColorPoint colorPoint) { + gc.setFill(colorPoint.getColor()); + gc.fillOval(centerX + colorPoint.getX() - 2, centerY + colorPoint.getY() - 2, 4, 4); + } else { + gc.strokeOval(centerX + point.getX() - 2, centerY + point.getY() - 2, 4, 4); + } + if (point.equals(selectedPoint)) { + gc.setStroke(Color.RED); + gc.strokeLine(centerX + point.getX() - 15, centerY + point.getY(), centerX + point.getX() - 6, + centerY + point.getY()); + gc.strokeLine(centerX + point.getX() + 6, centerY + point.getY(), centerX + point.getX() + 15, + centerY + point.getY()); + gc.strokeLine(centerX + point.getX(), centerY + point.getY() - 15, centerX + point.getX(), + centerY + point.getY() - 6); + gc.strokeLine(centerX + point.getX(), centerY + point.getY() + 6, centerX + point.getX(), + centerY + point.getY() + 15); + } + } + } + + private void initColumns(TableView<Point> tab) { + ((TableColumn<Point, Double>) tab.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<>("x")); + ((TableColumn<Point, Double>) tab.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<>("y")); + ((TableColumn<Point, Color>) tab.getColumns().get(2)).setCellValueFactory(param -> { + if (param.getValue() instanceof ColorPoint p) { + return new MyObservableValue<>(p.getColor()); + } + return null; + }); + ((TableColumn<Point, Integer>) tab.getColumns().get(3)) + .setCellValueFactory(param -> new MyObservableValue<>(System.identityHashCode(param.getValue()))); + } + + @FXML + private void generatePressed(ActionEvent event) { + Stream.generate(this::generate).limit(10).forEach(points1::add); + draw(); + } + + @FXML + private void clearPressed(ActionEvent event) { + table1.getSelectionModel().clearSelection(); + points1.clear(); + draw(); + } + + @FXML + private void measure(ActionEvent event) { + XYChart.Series<String, Long> containsSpeed = new XYChart.Series<>(); + containsSpeed.setName("Speed of method contains() for interface Set"); + int i=10; + while(i<=100000) { + containsSpeed.getData().add(new Data<>(Integer.toString(i), RANDOM.nextLong(i*100l))); + i*=2; + } + chart.getData().add(containsSpeed); + } + + private Point generate() { + if (RANDOM.nextBoolean()) { + return new Point(canvas.getWidth() / 2 - RANDOM.nextDouble(canvas.getWidth()), + canvas.getHeight() / 2 - RANDOM.nextDouble(canvas.getHeight())); + } else { + return new ColorPoint(canvas.getWidth() / 2 - RANDOM.nextDouble(canvas.getWidth()), + canvas.getHeight() / 2 - RANDOM.nextDouble(canvas.getHeight()), + COLORS.get(RANDOM.nextInt(COLORS.size()))); + } + } + + public static class MyObservableValue<T> extends ObjectBinding<T> { + + private T value; + + public MyObservableValue(T color) { + this.value = color; + } + + @Override + public T computeValue() { + return value; + } + + } + +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java b/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java new file mode 100644 index 0000000..4dce08c --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/ColorPoint.java @@ -0,0 +1,47 @@ +package cz.vsb.fei.java2.lab04; + +import java.util.Objects; + +import javafx.scene.paint.Color; + +public class ColorPoint extends Point { + + private Color color; + + public ColorPoint(double x, double y, Color color) { + super(x, y); + this.color = color; + } + + public Color getColor() { + return color; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(color); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (!(obj instanceof ColorPoint)) + return false; + ColorPoint other = (ColorPoint) obj; + if (!other.canEqual(this)) { + return false; + } + return Objects.equals(color, other.color); + } + + @Override + public boolean canEqual(Point p) { + return p instanceof ColorPoint; + } +} diff --git a/src/main/java/cz/vsb/fei/java2/lab04/Point.java b/src/main/java/cz/vsb/fei/java2/lab04/Point.java new file mode 100644 index 0000000..d493f9e --- /dev/null +++ b/src/main/java/cz/vsb/fei/java2/lab04/Point.java @@ -0,0 +1,49 @@ +package cz.vsb.fei.java2.lab04; + +import java.util.Objects; + +public class Point { + + private double x; + + private double y; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof Point)) + return false; + Point other = (Point) obj; + if (!other.canEqual(this)) { + return false; + } + return Double.doubleToLongBits(x) == Double.doubleToLongBits(other.x) + && Double.doubleToLongBits(y) == Double.doubleToLongBits(other.y); + } + + public boolean canEqual(Point p) { + return p instanceof Point; + } + +} \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java new file mode 100644 index 0000000..c8f3b6f --- /dev/null +++ b/src/main/java/module-info.java @@ -0,0 +1,8 @@ +module cz.vsb.fei.java2.lab04 { + requires transitive javafx.controls; + requires javafx.fxml; + requires lombok; + requires org.apache.logging.log4j; + opens cz.vsb.fei.java2.lab04 to javafx.fxml; + exports cz.vsb.fei.java2.lab04; +} \ No newline at end of file diff --git a/src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml b/src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml new file mode 100644 index 0000000..edc5e24 --- /dev/null +++ b/src/main/resources/cz/vsb/fei/java2/lab04/AppWindow.fxml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Copyright (c) 2015, 2019, Gluon and/or its affiliates. + All rights reserved. Use is subject to license terms. + + This file is available and licensed under the following license: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + - Neither the name of Oracle Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.canvas.Canvas?> +<?import javafx.scene.chart.BarChart?> +<?import javafx.scene.chart.CategoryAxis?> +<?import javafx.scene.chart.NumberAxis?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Tab?> +<?import javafx.scene.control.TabPane?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> + + +<TabPane xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.vsb.fei.java2.lab04.AppController"> + <tabs> + <Tab text="Points"> + <content> + <BorderPane minHeight="400.0" minWidth="640.0" prefHeight="400.0" prefWidth="715.0"> + <center> + <HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER"> + <children> + <TableView fx:id="table1" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS"> + <columns> + <TableColumn prefWidth="46.0" text="X" /> + <TableColumn prefWidth="52.0" text="Y" /> + <TableColumn prefWidth="75.0" text="Color" /> + <TableColumn prefWidth="163.0" text="System identity HashCode" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </TableView> + <BorderPane fx:id="pane" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS"> + <center> + <Canvas fx:id="canvas" height="163.0" width="174.0" BorderPane.alignment="CENTER"> + <cursor> + <Cursor fx:constant="CROSSHAIR" /> + </cursor> + </Canvas> + </center> + <opaqueInsets> + <Insets /> + </opaqueInsets> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </BorderPane> + </children> + </HBox> + </center> + <top> + <BorderPane BorderPane.alignment="CENTER"> + <center> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button mnemonicParsing="false" onAction="#generatePressed" text="Generate"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button mnemonicParsing="false" onAction="#clearPressed" text="Clear"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </center> + </BorderPane> + </top> + </BorderPane> + </content> + </Tab> + <Tab text="Speed Mesurment"> + <content> + <BorderPane> + <top> + <BorderPane BorderPane.alignment="CENTER"> + <center> + <Button fx:id="mesure" mnemonicParsing="false" onAction="#measure" text="Mesure"> + <BorderPane.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </BorderPane.margin> + </Button> + </center> + </BorderPane> + </top> + <center> + <BarChart fx:id="chart" BorderPane.alignment="CENTER"> + <xAxis> + <CategoryAxis side="BOTTOM" /> + </xAxis> + <yAxis> + <NumberAxis side="LEFT" /> + </yAxis> + </BarChart> + </center> + </BorderPane> + </content> + </Tab> + </tabs> +</TabPane> diff --git a/src/main/resources/cz/vsb/fei/java2/lab04/application.css b/src/main/resources/cz/vsb/fei/java2/lab04/application.css new file mode 100644 index 0000000..83d6f33 --- /dev/null +++ b/src/main/resources/cz/vsb/fei/java2/lab04/application.css @@ -0,0 +1 @@ +/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */ \ No newline at end of file diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..acb3514 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ +<Configuration> + <Appenders> + <Console name="Console"> + <PatternLayout + pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> + </Console> + </Appenders> + <Loggers> + <Root level="info"> + <AppenderRef ref="Console"></AppenderRef> + </Root> + </Loggers> +</Configuration> diff --git a/src/test/java/cz/vsb/fei/java2/lab04/AppTest.java b/src/test/java/cz/vsb/fei/java2/lab04/AppTest.java new file mode 100644 index 0000000..5b38df5 --- /dev/null +++ b/src/test/java/cz/vsb/fei/java2/lab04/AppTest.java @@ -0,0 +1,19 @@ +package cz.vsb.fei.java2.lab04; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +/** + * Unit test for simple App. + */ +class AppTest { + + /** + * Rigorous Test :-) + */ + @Test + void shouldAnswerWithTrue() { + assertTrue(true); + } +} -- GitLab