diff --git a/src/main/java/cz/vsb/fei/java2/lab03/AppController.java b/src/main/java/cz/vsb/fei/java2/lab03/AppController.java index 3b613391501a607dc2cbb64f3a24e0062fc16137..0436edfdafa2f7e5d368b1cfd5121debaa823a79 100644 --- a/src/main/java/cz/vsb/fei/java2/lab03/AppController.java +++ b/src/main/java/cz/vsb/fei/java2/lab03/AppController.java @@ -1,20 +1,104 @@ package cz.vsb.fei.java2.lab03; +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.control.Label; -import javafx.scene.control.MenuItem; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +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); + + @FXML + private TableView<Point> table1; + + @FXML + private TableView<Point> table2; + + private ObservableList<Point> points1 = FXCollections.observableArrayList(); + + private ObservableList<Point> points2 = FXCollections.observableArrayList(); + @FXML - private Label infoLabel; + public void initialize() { + table1.setItems(points1); + table2.setItems(points2); + initColumns(table1); + initColumns(table2); + table1.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + table2.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + table1.getSelectionModel().selectedItemProperty() + .addListener((ObservableValue<? extends Point> observable, Point oldValue, Point newValue) -> { + table2.getSelectionModel().clearSelection(); + for (int i = 0; i < points2.size(); i++) { + if (newValue != null && newValue.equals(points2.get(i))) { + table2.getSelectionModel().select(i); + } + } + }); + } + + 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 menuPressed(ActionEvent event) { - if(event.getSource() instanceof MenuItem menuItem) { - infoLabel.setText("Selected menu: " + menuItem.getText()); + private void generatePressed(ActionEvent event) { + Stream.generate(this::generate).limit(10).forEach(points1::add); + Stream.generate(this::generate).limit(6).forEach(points2::add); + Stream.generate(() -> RANDOM.nextInt(points1.size())).limit(4).map(points1::get).forEach(points2::add); + } + + @FXML + private void clearPressed(ActionEvent event) { + table2.getSelectionModel().clearSelection(); + table1.getSelectionModel().clearSelection(); + points1.clear(); + points2.clear(); + } + + private Point generate() { + if (RANDOM.nextBoolean()) { + return new Point(RANDOM.nextInt(2), RANDOM.nextInt(2)); + } else { + return new ColorPoint(RANDOM.nextInt(2), RANDOM.nextInt(2), 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/lab03/ColorPoint.java b/src/main/java/cz/vsb/fei/java2/lab03/ColorPoint.java index 16722be7c127a830ba28d9e80be9ad1a13a2ec1d..9b30cbf540d75a920c54721550e8df6ed1e01248 100644 --- a/src/main/java/cz/vsb/fei/java2/lab03/ColorPoint.java +++ b/src/main/java/cz/vsb/fei/java2/lab03/ColorPoint.java @@ -11,4 +11,8 @@ public class ColorPoint extends Point { this.color = color; } + public Color getColor() { + return color; + } + } diff --git a/src/main/java/cz/vsb/fei/java2/lab03/Point.java b/src/main/java/cz/vsb/fei/java2/lab03/Point.java index cc34fbc39a6d8595ffac0dd749a78ab7ecb26c44..6e67b01bc25a38937c377cff0edf9e3f1d56254f 100644 --- a/src/main/java/cz/vsb/fei/java2/lab03/Point.java +++ b/src/main/java/cz/vsb/fei/java2/lab03/Point.java @@ -11,4 +11,12 @@ public class Point { this.y = y; } + public double getX() { + return x; + } + + public double getY() { + return y; + } + } \ No newline at end of file diff --git a/src/main/resources/cz/vsb/fei/java2/lab03/AppWindow.fxml b/src/main/resources/cz/vsb/fei/java2/lab03/AppWindow.fxml index 6a81cb714392da4f95140ab76f55e0edcfc5e83c..5b0577ff75c941de01c3af5bba4bda9c018a17de 100644 --- a/src/main/resources/cz/vsb/fei/java2/lab03/AppWindow.fxml +++ b/src/main/resources/cz/vsb/fei/java2/lab03/AppWindow.fxml @@ -32,62 +32,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> -<?import javafx.scene.control.Menu?> -<?import javafx.scene.control.MenuBar?> -<?import javafx.scene.control.MenuItem?> -<?import javafx.scene.control.SeparatorMenuItem?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> <?import javafx.scene.layout.BorderPane?> -<?import javafx.scene.text.Font?> +<?import javafx.scene.layout.HBox?> - -<BorderPane minHeight="400.0" minWidth="640.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.vsb.fei.java2.lab03.AppController"> - <top> - <MenuBar BorderPane.alignment="CENTER"> - <menus> - <Menu mnemonicParsing="false" text="File"> - <items> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="New" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Open…" /> - <Menu mnemonicParsing="false" text="Open Recent" /> - <SeparatorMenuItem mnemonicParsing="false" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Close" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Save" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Save As…" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Revert" /> - <SeparatorMenuItem mnemonicParsing="false" onAction="#menuPressed" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Preferences…" /> - <SeparatorMenuItem mnemonicParsing="false" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Quit" /> - </items> - </Menu> - <Menu mnemonicParsing="false" text="Edit"> - <items> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Undo" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Redo" /> - <SeparatorMenuItem mnemonicParsing="false" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Cut" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Copy" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Paste" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Delete" /> - <SeparatorMenuItem mnemonicParsing="false" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Select All" /> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="Unselect All" /> - </items> - </Menu> - <Menu mnemonicParsing="false" text="Help"> - <items> - <MenuItem mnemonicParsing="false" onAction="#menuPressed" text="About MyHelloApp" /> - </items> - </Menu> - </menus> - </MenuBar> - </top> +<BorderPane minHeight="400.0" minWidth="640.0" prefHeight="400.0" prefWidth="715.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.vsb.fei.java2.lab03.AppController"> <center> - <Label fx:id="infoLabel" alignment="CENTER" style=" " text="Drag components from Library here…" textAlignment="CENTER" textFill="#9f9f9f" wrapText="false" BorderPane.alignment="CENTER"> - <font> - <Font size="18.0" /> - </font> - </Label> + <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> + </TableView> + <BorderPane HBox.hgrow="NEVER"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + <center> + <Label text="==" /> + </center> + </BorderPane> + <TableView fx:id="table2" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS"> + <columns> + <TableColumn prefWidth="38.0" text="X" /> + <TableColumn prefWidth="35.0" text="Y" /> + <TableColumn prefWidth="70.0" text="Color" /> + <TableColumn prefWidth="186.0" text="System identity HashCode" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + </TableView> + </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> diff --git a/src/test/java/cz/vsb/fei/java2/lab03/EquivalenceRoutines.java b/src/test/java/cz/vsb/fei/java2/lab03/EquivalenceRoutines.java new file mode 100644 index 0000000000000000000000000000000000000000..159555fb4cec2342670b591e0ef0fcf77b79504f --- /dev/null +++ b/src/test/java/cz/vsb/fei/java2/lab03/EquivalenceRoutines.java @@ -0,0 +1,25 @@ +package cz.vsb.fei.java2.lab03; + +import static org.junit.jupiter.api.Assertions.assertTrue; + + +class EquivalenceRoutines { + static void assertReflexivity(Object obj) { + assertTrue(obj.equals(obj)); + } + + static void assertSymmetry(Object obj1, Object obj2) { + if(obj1.equals(obj2)) { + assertTrue(obj2.equals(obj1)); + } else { + + assertTrue(!obj2.equals(obj1)); + } + } + + static void assertTransitivity(Object obj1, Object obj2, Object obj3) { + if(obj1.equals(obj2) && obj2.equals(obj3)) { + assertTrue(obj1.equals(obj3)); + } + } +} diff --git a/src/test/java/cz/vsb/fei/java2/lab03/TestEquals.java b/src/test/java/cz/vsb/fei/java2/lab03/TestEquals.java new file mode 100644 index 0000000000000000000000000000000000000000..d14a7499ba4c3e76b2f8a3239ff9a074b1f07889 --- /dev/null +++ b/src/test/java/cz/vsb/fei/java2/lab03/TestEquals.java @@ -0,0 +1,95 @@ +package cz.vsb.fei.java2.lab03; + +import static cz.vsb.fei.java2.lab03.EquivalenceRoutines.assertReflexivity; +import static cz.vsb.fei.java2.lab03.EquivalenceRoutines.assertSymmetry; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import javafx.scene.paint.Color; + +/** + * Unit test for simple App. + */ +@TestMethodOrder(OrderAnnotation.class) +class TestEquals { + + @Test + @Order(1) + void testLogicEquality() { + Point p1 = new Point(1, 2); + Point p2 = new Point(1, 2); + assertTrue(p1.equals(p2)); + + Point p3 = new Point(1, 1); + assertTrue(!p1.equals(p3)); + + Point cp1 = new ColorPoint(1, 2, Color.BLACK); + Point cp2 = new ColorPoint(1, 2, Color.BLACK); + assertTrue(cp1.equals(cp2)); + + Point cp3 = new ColorPoint(1, 1, Color.BLACK); + assertTrue(!cp1.equals(cp3)); + + Point cp4 = new ColorPoint(1, 2, Color.WHITE); + assertTrue(!cp1.equals(cp4)); + } + + @Test + @Order(2) + void testRelfexity() { + Point p1 = new Point(1, 2); + assertReflexivity(p1); + } + + @Test + @Order(3) + void testSymmetry() { + Point p1 = new Point(1, 2); + Point p2 = new Point(1, 2); + assertSymmetry(p1, p2); + + Point p3 = new Point(1, 1); + assertSymmetry(p1, p3); + + Point cp1 = new ColorPoint(1, 2, Color.BLACK); + Point cp2 = new ColorPoint(1, 2, Color.BLACK); + assertSymmetry(p1, cp2); + assertSymmetry(cp1, cp2); + + Point cp3 = new ColorPoint(1, 1, Color.BLACK); + assertSymmetry(p1, cp3); + assertSymmetry(cp1, cp3); + + Point cp4 = new ColorPoint(1, 2, Color.WHITE); + assertSymmetry(p1, cp4); + assertSymmetry(cp1, cp4); + } + + @Test + @Order(4) + void testTransitivity() { + + Point p1 = new ColorPoint(1, 2, Color.WHITE); + Point p2 = new Point(1, 2); + Point p3 = new ColorPoint(1, 2, Color.BLACK); + EquivalenceRoutines.assertTransitivity(p1, p2, p3); + } + + @Test + @Order(5) + void testLiskovPrinciple() { + Point p1 = new ColorPoint(1, 2, Color.CYAN); + Point p2 = new ColorPoint(1, 2, Color.CYAN) { + + @Override + public String toString() { + return "Moje barva"; + } + }; + assertTrue(p1.equals(p2)); + } +}