From b83d03c8689fa7e98aec1a5de528d5fdcd6c478d Mon Sep 17 00:00:00 2001 From: "@plotvichka_2" Date: Fri, 22 Dec 2023 11:03:46 +0300 Subject: [PATCH 1/4] Add .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fee91d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +*.iml +out/ From b026152f303be05ea700c07855b8af04d6c83db7 Mon Sep 17 00:00:00 2001 From: "@plotvichka_2" Date: Sun, 24 Dec 2023 15:15:24 +0300 Subject: [PATCH 2/4] Pinta 1.0 --- .gitignore | 1 + lab-03/CustomColorPicker.java | 147 ++++++ lab-03/Loader.java | 47 ++ lab-03/Pinta.java | 727 ++++++++++++++++++++++++++++++ lab-03/Saver.java | 54 +++ resources/images/Pinta/brush.png | Bin 0 -> 11766 bytes resources/images/Pinta/clear.png | Bin 0 -> 18423 bytes resources/images/Pinta/create.png | Bin 0 -> 3017 bytes resources/images/Pinta/open.png | Bin 0 -> 8738 bytes resources/images/Pinta/oval.png | Bin 0 -> 12053 bytes resources/images/Pinta/paste.png | Bin 0 -> 8867 bytes resources/images/Pinta/pencil.png | Bin 0 -> 7989 bytes resources/images/Pinta/rect.png | Bin 0 -> 2827 bytes resources/images/Pinta/save.png | Bin 0 -> 7376 bytes 14 files changed, 976 insertions(+) create mode 100644 lab-03/CustomColorPicker.java create mode 100644 lab-03/Loader.java create mode 100644 lab-03/Pinta.java create mode 100644 lab-03/Saver.java create mode 100644 resources/images/Pinta/brush.png create mode 100644 resources/images/Pinta/clear.png create mode 100644 resources/images/Pinta/create.png create mode 100644 resources/images/Pinta/open.png create mode 100644 resources/images/Pinta/oval.png create mode 100644 resources/images/Pinta/paste.png create mode 100644 resources/images/Pinta/pencil.png create mode 100644 resources/images/Pinta/rect.png create mode 100644 resources/images/Pinta/save.png diff --git a/.gitignore b/.gitignore index 0fee91d..8fbc9e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea/ *.iml out/ +*.log diff --git a/lab-03/CustomColorPicker.java b/lab-03/CustomColorPicker.java new file mode 100644 index 0000000..e75574e --- /dev/null +++ b/lab-03/CustomColorPicker.java @@ -0,0 +1,147 @@ +import javafx.event.ActionEvent; +import javafx.scene.control.*; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class CustomColorPicker extends HBox { + public Color getMainColor() { + return mainColor; + } + + public Color getExtraColor() { + return extraColor; + } + + private Color mainColor = Color.BLACK; + private Color extraColor = Color.WHITE; + private final Dialog colorDialog; + + CustomColorPicker() { + setSpacing(8); + + colorDialog = new Dialog<>(); + colorDialog.setTitle("Выбор цвета"); + + ButtonType okButton = new ButtonType("OK", ButtonBar.ButtonData.OK_DONE); + ButtonType cancelButton = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); + + colorDialog.getDialogPane().getButtonTypes().addAll(okButton, cancelButton); + + ColorPicker colorPicker = new ColorPicker(); + colorDialog.getDialogPane().setContent(colorPicker); + + colorDialog.setResultConverter(buttonType -> { + if (buttonType == okButton) { + return colorPicker.getValue(); + } + return null; + }); + + Button mainColorButton = new Button(); + Button extraColorButton = new Button(); + + mainColorButton.setOnAction(e -> { + colorDialog.showAndWait().ifPresent(result -> { + mainColor = result; + mainColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: " + colorToHex(result) + ";" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + }); + }); + extraColorButton.setOnAction(e -> { + colorDialog.showAndWait().ifPresent(result -> { + extraColor = result; + extraColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: " + colorToHex(result) + ";" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + }); + }); + + mainColorButton.setPrefSize(30, 30); + extraColorButton.setPrefSize(mainColorButton.getPrefWidth(), mainColorButton.getPrefHeight()); + + mainColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: black;" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + extraColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: white;" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + + AnchorPane.setTopAnchor(mainColorButton, 0.0); + AnchorPane.setLeftAnchor(mainColorButton, 0.0); + AnchorPane.setRightAnchor(extraColorButton, 0.0); + AnchorPane.setBottomAnchor(extraColorButton, 0.0); + + AnchorPane curr_colors = new AnchorPane(); + curr_colors.setPrefSize(50, 50); + curr_colors.getChildren().addAll(extraColorButton, mainColorButton); + + List> rowColors = new ArrayList<>(); + rowColors.add(List.of("#FFFFFF", "#A0A0A0", "#FF0000", "#FF6A00", + "#FFD800", "#4CFF00", "#00FF90", "#00FFFF", + "#0026FF", "#4800FF", "#B200FF")); + rowColors.add(List.of("#000000", "#808080", "#FF7F7F", "#FFB27F", + "#FFE97F", "#A5FF7F", "#7FFFC5", "#7FFFFF", + "#7F92FF", "#A17FFF", "#D67FFF")); + + GridPane colors = new GridPane(); + for (int j = 0, s = rowColors.size(); j < s; ++j) { + var rowColor = rowColors.get(j); + for (int i = 0, size = rowColor.size(); i < size; ++i) { + Button btn = new Button(); + int finalI = i; + btn.setOnMouseClicked(e -> { + var type = e.getButton(); + if (type == MouseButton.PRIMARY) { + mainColor = Color.web(rowColor.get(finalI)); + mainColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: " + rowColor.get(finalI) + ";" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + } else if (type == MouseButton.SECONDARY) { + extraColor = Color.web(rowColor.get(finalI)); + extraColorButton.setStyle( + "-fx-border-color: black;" + // чёрная граница + "-fx-border-width: 1px;" + // толщина границы + "-fx-background-color: " + rowColor.get(finalI) + ";" + // красный фоновый цвет, белая прослойка + "-fx-background-insets: 2;" // отступы для фона (белая прослойка между границей и фоном) + ); + } + }); + colors.add(btn, i, j); + btn.setPrefSize(25, 25); + btn.setBackground(Background.fill(Color.web(rowColor.get(i)))); + } + } + + + getChildren().addAll(curr_colors, colors); + } + + private String colorToHex(Color color) { + int red = (int) (color.getRed() * 255); + int green = (int) (color.getGreen() * 255); + int blue = (int) (color.getBlue() * 255); + + return String.format("rgb(%d, %d, %d)", red, green, blue); + } +} diff --git a/lab-03/Loader.java b/lab-03/Loader.java new file mode 100644 index 0000000..23937ba --- /dev/null +++ b/lab-03/Loader.java @@ -0,0 +1,47 @@ +import javafx.application.Application; +import javafx.embed.swing.SwingFXUtils; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.stage.FileChooser; + +import java.io.File; +import java.io.IOException; + +public class Loader { + + private Canvas canvas; + + Loader(Canvas canvas) { this.canvas = canvas; } + + public void load() { + FileChooser fileChooser = new FileChooser(); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.jpg")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG files (*.jpeg)", "*.jpeg")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("GIF files (*.gif)", "*.gif")); + fileChooser.getExtensionFilters().add( + new FileChooser.ExtensionFilter("Image files (*.png, *.jpeg, *.jpg, *.gif)", "*.png", "*.jpeg", "*.jpg", "*.gif") + ); + File file = fileChooser.showOpenDialog(null); + + if (file != null) { + try { + loadIntoFile(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private void loadIntoFile(File file) throws IOException { + Image image = new Image(file.toURI().toString()); + GraphicsContext gc = canvas.getGraphicsContext2D(); + gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + gc.drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight()); + } +} \ No newline at end of file diff --git a/lab-03/Pinta.java b/lab-03/Pinta.java new file mode 100644 index 0000000..f6ecd91 --- /dev/null +++ b/lab-03/Pinta.java @@ -0,0 +1,727 @@ +import javafx.application.Application; +import javafx.application.Platform; +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.image.PixelReader; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; +import javafx.scene.shape.StrokeLineCap; +import javafx.scene.shape.StrokeLineJoin; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.stage.Stage; + +import java.io.File; +import java.util.List; + +public class Pinta extends Application { + private double lastX, lastY; + private double startX, startY; + private boolean isShapeSelected = false; + private File toFile; + + private final Font font = Font.font("Arial", FontWeight.BOLD, 14); + + private Stage stage; + private VBox root; + private VBox top; + private MenuBar menu; + private Loader loader; + private Saver saver; + private HBox icons; + private HBox infoBar; + private ImageView imageView; + private HBox brushTools; + private HBox shapeTools; + private CheckBox fillCheckBox; + private TextField sizeOfBrush; + private Button incButton; + private Button decButton; + private HBox center; + private VBox tools; + private List indexes; + private StackPane canvasStack; + private Canvas drawCanvas; + private Canvas tempCanvas; + + private GraphicsContext gcDraw; + private GraphicsContext gcTemp; + private HBox bottom; + private CustomColorPicker customColorPicker; + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage stage) throws Exception { + this.stage = stage; + + root = new VBox(8); + + top = new VBox(8); + createIcons(); + createBrushTools(); + createShapeTools(); + createInfoBar(); + + center = new HBox(8); + createTools(); + createCanvas(); + canvasStack = new StackPane(); + canvasStack.getChildren().addAll(drawCanvas, tempCanvas); + center.setPadding(new Insets(8)); + //TODO + // HBox.setHgrow(drawCanvas, Priority.ALWAYS); + center.getChildren().addAll(tools, canvasStack); + + createMenu(); + top.getChildren().addAll(menu, new Separator(), icons, infoBar); + + customColorPicker = new CustomColorPicker(); + bottom = new HBox(); + bottom.setPadding(new Insets(0, 0, 0, 8)); + bottom.getChildren().addAll(customColorPicker); + + root.getChildren().addAll(top, new Separator(), center, bottom); + + + Scene scene = new Scene(root, 800, 620); + + stage.setScene(scene); + stage.setTitle("Unsaved image - Pinta"); + stage.centerOnScreen(); + stage.show(); + } + + private void createInfoBar() { + infoBar = new HBox(8); + infoBar.setPadding(new Insets(0 ,0 ,0, 8)); + + Label label = new Label("Instrument:"); + label.setFont(font); + label.setPrefHeight(sizeOfBrush.getHeight() + 22); + + imageView = new ImageView("images/Pinta/brush.png"); + imageView.setFitWidth(20); + imageView.setFitHeight(20); + + infoBar.getChildren().addAll(label, imageView, brushTools, shapeTools); + } + + private void createBrushTools() { + brushTools = new HBox(); + + sizeOfBrush = new TextField("3"); + sizeOfBrush.setPrefWidth(80); + Label label = new Label("Size of brush: "); + label.setPrefHeight(sizeOfBrush.getHeight() + 22); + label.setFont(font); + incButton = new Button("+"); + decButton = new Button("-"); + incButton.setPrefWidth(30); + decButton.setPrefWidth(incButton.getPrefWidth()); + incButton.setOnAction(e -> { + int size = Integer.parseInt(sizeOfBrush.getText()); + if (size != 1000) { + sizeOfBrush.setText(String.valueOf(size + 1)); + } + }); + decButton.setOnAction(e -> { + int size = Integer.parseInt(sizeOfBrush.getText()); + if (size != 1) { + sizeOfBrush.setText(String.valueOf(size - 1)); + } + }); + sizeOfBrush.textProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + if (!newValue.matches("^[1-9]\\d*$")) { + newValue = newValue.replaceAll("^0+|[^\\d]", ""); + } + if (!newValue.isEmpty()) { + sizeOfBrush.setText(Integer.parseInt(newValue) > 1000 ? oldValue : newValue); + } + } + }); + + brushTools.getChildren().addAll(label, sizeOfBrush, incButton, decButton); + } + + private void createShapeTools() { + shapeTools = new HBox(8); + + Label fillLabel = new Label("Fill figure"); + fillCheckBox = new CheckBox(); + fillLabel.setFont(font); + fillLabel.setPrefHeight(sizeOfBrush.getHeight() + 22); + fillCheckBox.setPrefHeight(sizeOfBrush.getPrefHeight() + 25); + shapeTools.getChildren().addAll(fillLabel, fillCheckBox); + } + private void createMenu() { + menu = new MenuBar(); + loader = new Loader(drawCanvas); + saver = new Saver(drawCanvas); + + Menu file = new Menu("File"); + MenuItem open = new MenuItem("Open..."); + MenuItem save = new MenuItem("Save..."); + MenuItem saveAs = new MenuItem("Save as..."); + MenuItem exit = new MenuItem("Exit"); + file.getItems().addAll(open, new SeparatorMenuItem(), save, saveAs, new SeparatorMenuItem(), exit); + + menu.getMenus().addAll(file); + + open.setOnAction(e -> { + loader.load(); + }); + + saveAs.setOnAction(e -> { + toFile = saver.save(); + if (toFile != null) { + stage.setTitle(toFile.getName() + " - Pinta"); + } + }); + + save.setOnAction(e -> { + try { + if (toFile != null) { + saver.saveIntoFile(toFile); + } else { + toFile = saver.save(); + } + stage.setTitle(toFile.getName() + " - Pinta"); + } catch (Exception exc) { + exc.printStackTrace(); + } + }); + + exit.setOnAction(e -> { + Platform.exit(); + }); + } + private void createCanvas() { + drawCanvas = new Canvas(); + gcDraw = drawCanvas.getGraphicsContext2D(); + gcDraw.setLineCap(StrokeLineCap.ROUND); + gcDraw.setLineJoin(StrokeLineJoin.ROUND); + drawCanvas.setWidth(600); + drawCanvas.setHeight(400); + + tempCanvas = new Canvas(); + gcTemp = tempCanvas.getGraphicsContext2D(); + tempCanvas.setWidth(drawCanvas.getWidth()); + tempCanvas.setHeight(drawCanvas.getHeight()); + + gcDraw.setStroke(Color.BLACK); + gcDraw.setLineWidth(2); + gcDraw.strokeRect(drawCanvas.getLayoutX(), drawCanvas.getLayoutY(), drawCanvas.getWidth(), drawCanvas.getHeight()); + + createCanvasEvents(); + } + + private void createCanvasEvents() { + //TODO + tempCanvas.setOnMouseClicked(e -> { + String id = ""; + for (var elem : tools.getChildren()) { + if (((ToggleButton) elem).isSelected()) { + id = elem.getId(); + break; + } + } + mouseClickedChooser(e, id); + }); + tempCanvas.setOnMousePressed(e -> { + lastX = startX = e.getX(); + lastY = startY = e.getY(); + }); + + tempCanvas.setOnMouseDragged(e -> { + String id = ""; + for (var elem : tools.getChildren()) { + if (((ToggleButton) elem).isSelected()) { + id = elem.getId(); + break; + } + } + mouseDraggedChooser(e, id); + }); + + tempCanvas.setOnMouseReleased(e -> { + if (isShapeSelected) { + var shapes = tools.getChildren(); + for (int ind : indexes) { + if (((ToggleButton) shapes.get(ind)).isSelected()) { + mouseReleasedChooser(e, ((ToggleButton) shapes.get(ind)).getId()); + } + } + } + }); + } + +// private void setTitleModified(boolean isModified) { +// String title = stage.getTitle(); +// int pos = title.lastIndexOf(' ') - 2; +// if (!isModified) { +// stage.setTitle(title.substring(0, title.lastIndexOf('*')) + " - Pinta"); +// } +// if (title.charAt(pos - 1) != '*') { +// stage.setTitle(title.substring(0, title.lastIndexOf(' ') - 2) + "* - Pinta"); +// } +// } + + private void mouseClickedChooser(MouseEvent e, String id) { + switch (id) { + case "brush" -> { +// setTitleModified(hasSomeChanges()); + try { + gcDraw.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + } + gcDraw.strokeOval(e.getX(), e.getY(), gcDraw.getLineWidth(), gcDraw.getLineWidth()); + } + case "pencil" -> { +// setTitleModified(); + gcDraw.setLineWidth(1); + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + } + gcDraw.strokeOval(e.getX(), e.getY(), 1, 1); + } + //TODO + default -> {} + } + } + + private void mouseDraggedChooser(MouseEvent e, String id) { + switch (id) { + case "brush" -> { +// setTitleModified(); + isShapeSelected = false; + try { + gcDraw.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + } + double x = e.getX(); + double y = e.getY(); + gcDraw.strokeLine(lastX, lastY, x, y); + lastX = x; + lastY = y; + } + case "pencil" -> { +// setTitleModified(); + isShapeSelected = false; + gcDraw.setLineWidth(1); + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + } + double x = e.getX(); + double y = e.getY(); + gcDraw.strokeLine(lastX, lastY, x, y); + lastX = x; + lastY = y; + } + case "rect" -> { +// setTitleModified(); + isShapeSelected = true; + gcTemp.clearRect(0 , 0, tempCanvas.getWidth(), tempCanvas.getHeight()); + lastX = e.getX(); + lastY = e.getY(); + try { + gcTemp.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcTemp.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcTemp.setStroke(customColorPicker.getMainColor()); + gcTemp.setFill(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcTemp.setStroke(customColorPicker.getExtraColor()); + gcTemp.setFill(customColorPicker.getExtraColor()); + } + if (fillCheckBox.isSelected()) { + gcTemp.fillRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + gcTemp.strokeRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + case "oval" -> { +// setTitleModified(); + isShapeSelected = true; + gcTemp.clearRect(0 , 0, tempCanvas.getWidth(), tempCanvas.getHeight()); + lastX = e.getX(); + lastY = e.getY(); + try { + gcTemp.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcTemp.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcTemp.setStroke(customColorPicker.getMainColor()); + gcTemp.setFill(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcTemp.setStroke(customColorPicker.getExtraColor()); + gcTemp.setFill(customColorPicker.getExtraColor()); + } + if (fillCheckBox.isSelected()) { + gcTemp.fillOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + gcTemp.strokeOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + //TODO + default -> {} + } + } + + private void mouseReleasedChooser(MouseEvent e, String id) { + switch (id) { + case "rect" -> { + gcTemp.clearRect(0, 0, tempCanvas.getWidth(), tempCanvas.getHeight()); + try { + gcDraw.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + gcDraw.setFill(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + gcDraw.setFill(customColorPicker.getExtraColor()); + } + if (fillCheckBox.isSelected()) { + gcDraw.fillRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + gcDraw.strokeRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + case "oval" -> { + gcTemp.clearRect(0, 0, tempCanvas.getWidth(), tempCanvas.getHeight()); + try { + gcDraw.setLineWidth(Integer.parseInt(sizeOfBrush.getText())); + } catch (Exception exc) { + gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + gcDraw.setStroke(customColorPicker.getMainColor()); + gcDraw.setFill(customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + gcDraw.setStroke(customColorPicker.getExtraColor()); + gcDraw.setFill(customColorPicker.getExtraColor()); + } + if (fillCheckBox.isSelected()) { + gcDraw.fillOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + gcDraw.strokeOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + //TODO + default -> {} + } + } + +// private boolean hasSomeChanges() { +// Image image1 = toFile == null ? +// (new Canvas(drawCanvas.getWidth(), drawCanvas.getHeight())).snapshot(null, null) +// : new Image(toFile.toURI().toString()); +// Image image2 = drawCanvas.snapshot(null, null); +// +// int width = (int) image1.getWidth(); +// int height = (int) image1.getHeight(); +// +// if (width != image2.getWidth() || height != image2.getHeight()) { +// return true; +// } +// +// PixelReader reader1 = image1.getPixelReader(); +// PixelReader reader2 = image2.getPixelReader(); +// +// for (int x = 0; x < width; x++) { +// for (int y = 0; y < height; y++) { +// if (reader1.getArgb(x, y) != reader2.getArgb(x, y)) { +// return true; +// } +// } +// } +// +// return false; +// } + + private void infoSetter(String id) { + switch (id) { + case "brush" -> { + id = "images/Pinta/brush.png"; + var info = infoBar.getChildren(); + if (!info.contains(brushTools)) { + info.add(brushTools); + } + info.remove(shapeTools); + } + case "pencil" -> { + id = "images/Pinta/pencil.png"; + var info = infoBar.getChildren(); + info.remove(brushTools); + info.remove(shapeTools); + } + case "rect" -> { + id = "images/Pinta/rect.png"; + var info = infoBar.getChildren(); + if (!info.contains(brushTools)) { + info.add(brushTools); + } + if (!info.contains(shapeTools)) { + info.add(shapeTools); + } + } + case "oval" -> { + id = "images/Pinta/oval.png"; + var info = infoBar.getChildren(); + if (!info.contains(brushTools)) { + info.add(brushTools); + } + if (!info.contains(shapeTools)) { + info.add(shapeTools); + } + } + case "" -> { + infoBar.getChildren().remove(brushTools); + infoBar.getChildren().remove(shapeTools); + } + //TODO + default -> throw new IllegalStateException("Unexpected value: " + id); + } + imageView.setImage(id.isEmpty() ? null : new Image(id)); + } + private void createIcons() { + icons = new HBox(); + icons.setPadding(new Insets(0, 0, 0, 8)); + + Button create = new Button(); + ImageView createImageView = new ImageView(new Image("/images/Pinta/create.png")); + createImageView.setFitWidth(30); + createImageView.setFitHeight(30); + create.setStyle("-fx-background-color: transparent;"); + create.setGraphic(createImageView); + create.setPrefSize(createImageView.getFitWidth() + 13, createImageView.getFitHeight() + 13); + + Button open = new Button(); + ImageView openImageView = new ImageView(new Image("/images/Pinta/open.png")); + openImageView.setFitWidth(createImageView.getFitWidth() + 4); + openImageView.setFitHeight(createImageView.getFitHeight() + 4); + open.setStyle("-fx-background-color: transparent;"); + open.setGraphic(openImageView); + open.setText(" Open"); + open.setFont(font); + + Button save = new Button(); + ImageView saveImageView = new ImageView(new Image("/images/Pinta/save.png")); + saveImageView.setFitWidth(createImageView.getFitWidth()); + saveImageView.setFitHeight(createImageView.getFitHeight()); + save.setStyle("-fx-background-color: transparent;"); + save.setGraphic(saveImageView); + save.setText(" Save"); + save.setFont(font); + save.setPrefSize(100, openImageView.getFitHeight() + 10); + + Button paste = new Button(); + ImageView pasteImageView = new ImageView(new Image("/images/Pinta/paste.png")); + pasteImageView.setFitWidth(createImageView.getFitWidth() + 4); + pasteImageView.setFitHeight(createImageView.getFitHeight()); + paste.setStyle("-fx-background-color: transparent;"); + paste.setGraphic(pasteImageView); + paste.setText(" Paste"); + paste.setFont(font); + paste.setPrefSize(115, openImageView.getFitHeight() + 10); + + Button clear = new Button(); + ImageView clearImageView = new ImageView("/images/Pinta/clear.png"); + clearImageView.setFitWidth(createImageView.getFitWidth() + 4); + clearImageView.setFitHeight(createImageView.getFitHeight()); + clear.setStyle("-fx-background-color: transparent;"); + clear.setGraphic(clearImageView); + clear.setText(" Clear"); + clear.setFont(font); + clear.setPrefSize(115, openImageView.getFitHeight() + 10); + + create.setOnAction(e -> { + + }); + create.setOnMouseEntered(e -> { + create.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + create.setOnMouseExited(e -> { + create.setStyle("-fx-background-color: transparent;"); + }); + + open.setOnAction(e -> System.out.println("Open...")); + open.setOnMouseEntered(e -> { + open.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + open.setOnMouseExited(e -> { + open.setStyle("-fx-background-color: transparent;"); + }); + + save.setOnAction(e -> System.out.println("Save...")); + save.setOnMouseEntered(e -> { + save.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + save.setOnMouseExited(e -> { + save.setStyle("-fx-background-color: transparent;"); + }); + + paste.setOnAction(e -> System.out.println("Paste...")); + paste.setOnMouseEntered(e -> { + paste.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + paste.setOnMouseExited(e -> { + paste.setStyle("-fx-background-color: transparent;"); + }); + + clear.setOnAction(e -> { +// setTitleModified(); + gcDraw.clearRect(0, 0, drawCanvas.getWidth(), drawCanvas.getHeight()); + gcDraw.setLineWidth(1); + gcDraw.setStroke(Color.BLACK); + gcDraw.strokeRect(0, 0, drawCanvas.getWidth(), drawCanvas.getHeight()); + }); + clear.setOnMouseEntered(e -> { + clear.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + clear.setOnMouseExited(e -> { + clear.setStyle("-fx-background-color: transparent;"); + }); + + icons.getChildren().addAll(create, open, save, new Separator(Orientation.VERTICAL), paste, new Separator(Orientation.VERTICAL), clear); + } + + private void createTools() { + tools = new VBox(10); + + ToggleGroup instrGroup = new ToggleGroup(); + + ToggleButton brush = new ToggleButton(); + brush.setId("brush"); + brush.fire(); + brush.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + ImageView brushImageView = new ImageView(new Image("/images/Pinta/brush.png")); + brushImageView.setFitWidth(28); + brushImageView.setFitHeight(29); + + + brush.setGraphic(brushImageView); + brush.setPrefSize(brushImageView.getFitWidth() + 10, brushImageView.getFitHeight() + 13); + + ToggleButton pencil = new ToggleButton(); + pencil.setId("pencil"); + ImageView pencilImageView = new ImageView(new Image("/images/Pinta/pencil.png")); + pencilImageView.setFitWidth(brushImageView.getFitWidth()); + pencilImageView.setFitHeight(brushImageView.getFitHeight()); + pencil.setStyle("-fx-background-color: transparent;"); + pencil.setGraphic(pencilImageView); + pencil.setPrefSize(brushImageView.getFitWidth() + 10, brushImageView.getFitHeight() + 13); + + ToggleButton rect = new ToggleButton(); + rect.setId("rect"); + ImageView rectImageView = new ImageView(new Image("/images/Pinta/rect.png")); + rectImageView.setFitWidth(brushImageView.getFitWidth()); + rectImageView.setFitHeight(brushImageView.getFitHeight()); + rect.setStyle("-fx-background-color: transparent;"); + rect.setGraphic(rectImageView); + rect.setPrefSize(brushImageView.getFitWidth() + 10, brushImageView.getFitHeight() + 13); + + ToggleButton oval = new ToggleButton(); + oval.setId("oval"); + ImageView ovalImageView = new ImageView(new Image("/images/Pinta/oval.png")); + ovalImageView.setFitWidth(30); + ovalImageView.setFitHeight(30); + oval.setStyle("-fx-background-color: transparent;"); + oval.setGraphic(ovalImageView); + oval.setPrefSize(brushImageView.getFitWidth() + 10, brushImageView.getFitHeight() + 13); + + brush.setOnMouseEntered(e -> { + brush.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + brush.setOnMouseExited(e -> { + if (!brush.isSelected()) { + brush.setStyle("-fx-background-color: transparent;"); + brush.setDisable(false); + }; + }); + + pencil.setOnMouseEntered(e -> { + pencil.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + pencil.setOnMouseExited(e -> { + if (!pencil.isSelected()) { + pencil.setStyle("-fx-background-color: transparent;"); + } + }); + + rect.setOnMouseEntered(e -> { + rect.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + rect.setOnMouseExited(e -> { + if (!rect.isSelected()) { + rect.setStyle("-fx-background-color: transparent;"); + } + }); + + oval.setOnMouseEntered(e -> { + oval.setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + }); + oval.setOnMouseExited(e -> { + if (!oval.isSelected()) { + oval.setStyle("-fx-background-color: transparent;"); + } + }); + + instrGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> { + if (oldValue != null) { + ((ToggleButton) oldValue).setStyle("-fx-background-color: transparent;"); + } + if (newValue != null) { + ((ToggleButton) newValue).setStyle("-fx-background-radius: 10; -fx-border-radius: 10;"); + infoSetter(((ToggleButton) newValue).getId()); + } else { + infoSetter(""); + } + }); + + instrGroup.getToggles().addAll(brush, pencil, rect, oval); + indexes = List.of(2, 3); + tools.getChildren().addAll(brush, pencil, rect, oval); + } +} \ No newline at end of file diff --git a/lab-03/Saver.java b/lab-03/Saver.java new file mode 100644 index 0000000..b5809a0 --- /dev/null +++ b/lab-03/Saver.java @@ -0,0 +1,54 @@ +import javafx.application.Application; +import javafx.embed.swing.SwingFXUtils; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; + +public class Saver { + private Canvas canvas; + Saver(Canvas canvas) { this.canvas = canvas; } + public File save() { + FileChooser fileChooser = new FileChooser(); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.jpg")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG files (*.jpeg)", "*.jpeg")); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("GIF files (*.gif)", "*.gif")); + fileChooser.getExtensionFilters().add( + new FileChooser.ExtensionFilter("Image files (*.png, *.jpeg, *.jpg, *.gif)", "*.png", "*.jpeg", "*.jpg", "*.gif") + ); + + File file = fileChooser.showSaveDialog(null); + + if (file != null) { + try { + saveIntoFile(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return file; + } + + public void saveIntoFile(File file) throws IOException { + String extension = ""; // Получаем расширение файла + int i = file.getName().lastIndexOf('.'); + if (i > 0) { + extension = file.getName().substring(i + 1); + } + Image snapshot = canvas.snapshot(null, null); + ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), + extension.equals("jpeg") || extension.equals("jpg") ? "png" : extension, + file); + } +} \ No newline at end of file diff --git a/resources/images/Pinta/brush.png b/resources/images/Pinta/brush.png new file mode 100644 index 0000000000000000000000000000000000000000..0e1c689161837f9e9a0347a84ad89d10b73d4c64 GIT binary patch literal 11766 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 fTB00+cCinu;eYLULo8x_ByZ(N}VY6o` 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 literal 0 HcmV?d00001 diff --git a/resources/images/Pinta/create.png b/resources/images/Pinta/create.png new file mode 100644 index 0000000000000000000000000000000000000000..efdbfada3f76d0dbdb04f1a9703aabfe3e4eb453 GIT binary patch literal 3017 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 literal 0 HcmV?d00001 diff --git a/resources/images/Pinta/oval.png b/resources/images/Pinta/oval.png new file mode 100644 index 0000000000000000000000000000000000000000..efbc05551c46dea144e49698c5e8804a05a030d6 GIT binary patch literal 12053 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 literal 0 HcmV?d00001 diff --git a/resources/images/Pinta/rect.png b/resources/images/Pinta/rect.png new file mode 100644 index 0000000000000000000000000000000000000000..837c324eda3c489c49fa2bb275d301f2a3ec4086 GIT binary patch literal 2827 zcmeHJUrd@;6h8v9)M+v6TH9*Dhb?q#0()>lSJ2jIs##*2YD53xj5?hYL_q;5h1g`e zhia2O_+Y_qP1D3?Hr4f`78KKMersA~UFV$r0I@85{^yJm08p8B%5c$1rR z?>*-x_uSvf`TagWUUoDsWnT&aq?MKwod95Cc z=tzb3D&_vN`|Vn8=X_;r`ktJJU3XmY*{$rF_ve$-+3}%zR!3%beWCx|_gv6c#IM#o zKG0CS3e40ilWqNGT|Yl>U_g}!=xqa2Qe0g>*4tRxPcbg#=ts<_==laR$)5`Vv zW()aO{j6n%ZSD zPCe(q?LLlXc!GXG9t7)Z+~JPc9mvvbjp- z|55N;S!|;2v<21{SpN~Fsv8dpB`i=n&LzDnudDA;i#Iv}0@F`#$!B^k47ewqL2bW% z@HV!tTzm&i`aiy%#*Y5&>FIWh+1gQxdY!`r*C?Oho--rf#e@P$8YqQhxz5l{pV+w{ zU-4r+tHd6zfN`_VPMJgE{_}D|XK`YNAWAPK^h>Vv) z#NCTT+f`CXhk1B&W2~L%%-E9(_cG@iV+--=ujmIhP;f4MLshB{0mxcO#V_HE-83bV zf-F~=#cPbUa8p?(=@XyZ6`~QTkL3U+p|$v|JeX`6i z6bgv&a6?BSM-Ohm^HfncAR;1~UeKP$nZ)jDCY}J?CjaMzkky9{;4ad8J$mk??`G%a zYYDdnzP`RfuUwrxtu5Vch1}rw89QV zAtf~}JtH$KJ16&JUVcGgQE^FWS$Rce)!(11YijH2zce&9HKSVF+P{A5==|Q*-P8M{ z58Xd7_;cvj$mrPk#N^cU%GQkfr>kJYvydHoIce zSU@XF{C;XubiV1;mIO2HXnw{{Ve49lM9osO47FoOMrU*f&01z_iF9Vd#N*Hv!tcVp zRgapZ)m<>}&seCW=Iqb%uFo>1F0L%Fc?$}K&WN0&VTU+-_=A?X$tGsZ(dybe?!)up zg_ZS?`8Q?~4v|IrHBKtIyi?4{CU0H+xNXyPVQvUCSLR{hVc^%oJ5}|FdD+zU{S&z% zS-h4p3~RG4Ld@p$R#h$H4=ia`U{dzi(stZLXmtj!ESua^2o^uNxUo^Mv3<_-I!-b6 zb%t>FlKcop$W+JK)9xu9MeUsMG6|o{*h}?&u_kOwTprqPU}(1M1fe10=)9ApEdsB5 zLQCR|v7xWG<0u59hOGDmX3VKk-XT#1R;83~SVo=a-qp&daiK)0>#}2!+`|!fXA#Fz zqbTd+E$p72fk9o;&G9PiQkjnSv7Q913ZocnXs%Is;t_m-mD4D3%pPA78cZ(EZ!%dw zk^dAMQ=Io>a;*}%T>Np$WCw=T*Hs=(+!#Aj{BX^m6Cfo-7TqC;pjGRa?w1OgKgi+K z`?%kgkV;ydB>`6+hK5!a>ByA*F)$`S4GAh79;j;EpFKV;|HP}`HFJ;tqYc|GlNhJ% ztFbwLlpf0TAnnSGJ>VID4Fr2z6?CN)Y|Mmp$oW;h`*^BLZklRZ;lacWUo2}(IZnNu zbe+%aice`KBMBD7bJIJ$4_Ai0z;I^yo#tyv}j2;umEuu5y|i{3JynewSC*XV%g7mWgy|-zEp?`w90$h}+9w zvuWe<9#D7JkTTQoDfTbH3vG$t#kLq5qqZ8iHEl35OWJsB8pn=`-U&^qI&EC30y(*( zaEZq2So7^08jbv6r%rdjta zx#tKWKFN`9d*hF|h*Eg}R6r8?d{afEmh9RkF|LRxz9FpvPCdz$&yoGNKGV+;qWw9? zbv<>Wr8v_H+pYs`&B5vD4{M0KlRO@`q3I#kWLJqFUM-IHV_*HX@hAK`- zVRAekJP*VKsyQ`79Qv_XmtC)T`#*{Vh0U0nZv}LrNn}0>Q$#0(N_QuPJhmu8DF+DY z1%kUmSkcSobub@P6}wrqBq1{h2qHpzh^YM;ufAuxyWtk~K_2hw=%#T;g>@`k0v!v! zHMCXL4vg~n2Jr?_`|q1=hPtysP(z<9yII_@Rm#gb z(Jb;26W4{Q))gZca@(6nw$Q3y@Fr1wrn!T{}`o;UycToc@{Kpk<1I( zg{Eh5x(I$TT9e=&meh+2y)HGY>6VI=F)(e0I`j$rEUaa_VrU_sTn9PFX{Wn zEBc0Z-7mJLqZRn9`F%jC6(V@2Bw)Mrn_t<>yqX`ojNTuIl`lpw$Dh+zam{)YsyT=7 zz47)#_wIOILe<6(_0%KKzfpJ$F4?S~B|P^DfFCuuboz2j#YQ|`JE@_vAr!Pn1GUA_ z9nLR?0EnM8dePQJ6)hf|Ulk{G$0)G@}?*klTNB5i?Or!&uK39{1RC*=4lY8993*?d+ zJwEKif?!V$?8K`?M3UFP==;5$Py+@d_T4}rz)?oFf-x{!-9P)3Isf(sPkU$raFmi|5P6%#1F!4fBRAi$=PXr_1r zkN}IygQx6yDdf*@-2}4)?Jw_QL=jwmyf{A#UWAZzU;Hr=%$otUcc_VKZOrMfMv!|O z*@#N`LV2n1n*JYy{z^7DHI5*a4Ddlx(TwLTpAlo$w{ZcG=eavU|5iZx|FT$FyyqQ^ zGPvzP)Q{#xJ`a);_j0D`+I?VQA9zSuVx$f%FQL-tGM)51V0Z9X!QLFK`q8A9@E~nw zd)Ou_uPN+kc}#S{Qd;+TcO|&EPbv=61?;KaQsb3iMU+%rMHjTBb{kt51AH{}SdSVx zXSf2HwI0OGbqEX^Dn5ez6j`BceWeZ1X?h;f2Kaxc`Ma4 znx*R(2qC?<^2?*@jj{P<6Q4|q?jt!)bfb0yCrYsLt*gdd>Xv|2;%Z4Cs#+VHA9dzk zLaciS+?!`EmcI6EKEkdRasGfK4G7}7JPPtAxXcLxY5EK}HD7@io12C&FSKQku%Dmm zJzD=H4oU_AYiFgFksG4>9-Lj#|8}d@TbuRR zY+u_l-6=f}P^+P~niw8jF%djh5ckLFbCdz$Eq?Jo&Grw=$1w5sS`H7nkIfFHFr_Iu(VYTkOY>8UEVBlb;7Nah=DTBPyd^U)Dy1cM@d!BqYs=Sa<3G znBtx3Ul!%`oZQBnQ#S%XtF&0s^~MKp0|%-XC4w0}41lfbW6BG-;4e1dK%ZX1+1JAd zpx7|iAFJk}A0SE(-I;h01Z!hS4ZYweT--piuU7*=*&1+c;*FNDfq~ z+G+wX+cF%~EDa$_kP=%TSA>Zpm}CUH6R)kB>)ZU4Q*{jui9iD4fKs*|t5)6SAz?@Y zD1WC|*ED`@%Df~KEOrDD4+duJ8S%U??R>-=GB+SBd0I6$C)$;Mhng_?-7S3&B8rFq zNRe(-OkZ8Rmf{Xvv1}-XvamUx_SrINab!DdI>>#Dld66Xi|!-` zC7!f+Y}^!nN<;vz;oX@tjvt>_-g~xw0|ao)kIPmPbLuy*N(n;ReVUOUiVueAEolfiDIv5dZ@TWRg>p9=? zx&mMk**=uAY}|4t2QywW0s^VR>=0zi*YDrn%P2yDw0b2it!Do&$elbBprIXL3<2{G zl$+mts*$1wF9$HrbhLw)tze!FaqGh%32@I2->9Hak|O{EzuIO9uIY@!p~yrh>>R0S zK>(Bh3LMy+!d%{ygP22E%lraJ`}R7_k{gU$f%*EaTlGIeK!e0mSidL@ zaBaNd{>v2%)Z-%w{B-fo4MafJpnG!oQy#sZ-*XnPErwjQm5 zD@N58@q9D|xJ5Z6{6>?C0;sCiPF3Q5=YTDbc6FO1H;)EPc+gIqomkjw0oGJd`}6&lyAdrZ1V;rn&-Om3rV$w+oNYLDfTR z4WsO08N43~f4)M8}qfTt+$S`v^ z4S^b}jQ(&Uo@{o&m~yBOl~O5IZsZGpdOT=hd!dbMH{v#2AD*aw9383zH?yuenz^gDlvMT zK@zVf@tg)pO?r5FtjvDWZ)TC8q350!%MoO++#6R!NmB`2Q0eNlNNF2I ztP#0kwTlVn$5Bgs;#PCQBEsc2C@DqUdM8~CKDMrGBb=86O+Ph9r?g4lw1rXNT+rMu zSsZM66sQOG>YYJ+JqYpH>ikVX*r^Z_f(s&MHCN<+i9tpv(g_4War77{7VtkcKMn-u(>?m7MAgkS{x44?c7 z4KHD7<-cyC|l0+4ayK+?NF>X6kd26A{;$CuNFwINU#*G;|fl@xLRRFZ<`)08MVe z*_=$p=u9(!DJlHn4(^K~_cUC&H{I4buy0q!K|312tfdadMtg=Qr_DC;zzY7)Rfgt- zVYkWq1yL;v5JHejgIog5F@~%R_7n^Q%mCR7o-O(ApUAX)zS115$7O{&_J9@mt>f(W9xs~qb{|p9r)WZMPnk?&PE|%p#aPV)N9?9aMF*u zbI4CRfF@`+URm(!PQSzQ$STkbv2_D@_412eJ2?issik#-V`5+-1c+~QgFJzP5?0uI zRqiokj(?zg&C~PN83F9soE9$!benH}enl73RPt`>X@*lOlgw>s5IAC|7yb zjoc@Mwve|kT&!;kZbMo2kOoVoS*`x|8ZqqfpcbKSwjp3X z7(k|%n~bOyg34py4r-V2t!^O2Yd=p9nE zqy~OeN(LXDyT_XE3O~Cro_V^1Yl$EY#urb%2)}7$@@U#Z=GkRuICZABG0JI4fYXE6 zO>FJ%SCOj6O=iOxjAG^iYM=Sh6)Ma7CkF+NfNL+dOzH6EH=kadjxdQGQ}#Z{rzQ6& z(!q92_c9ye?FsBQoH*S>s3imyZ4gK(R(@cHSDO6kDrY$?nUXccYe%iamh^w((TzGd zj5v1nuyQgG(1uw{&_$gqy(=|xJf7QS+ij@5zB4?bB51}(ybzrwAkJCT+@;ZPzcX)H z2Rg+l_{};detXs)^Q1{#g}CG!x8`mew=|f`DHxK1L;4wpkOZ-_Fb$V`i`lNKNsf%> znNNpBCD54tGmhj7=5BeuN#=OBL?12dKn?bWOFtcl{_l@mK0T%RsxU}oScFyH;y=PG z=yGXZ%UfAdyV@ArO!s9IDw^Xp6*##T*u5ixQ)a!iOza41$YsE_?7L=+$SZnm$yf!nd4LM_$4Ur?MU*~wk^|Q zC`Ay7GJB!hqpo!Ywc#@&ay&E7ym!7?3i@3(nOjX%J?3?%R9Yd~E?DVy5^=V4t!uuH z$4vGof4eq7VO8|zR*cER)X6W}I-Xt2%r`vQkqs#58-iYNwd{q2-K>a5)Kg(st1>b| zgo50@&u}xVqjoE^DYf7luAR))g>l==mft#Ov1e0a@NRfXiATV!xA`Kw_JG+w%rZ+$ z^9*gC4IkHsepb`+9zC$5^@JqXJQnJ7K+Qf6oibsiNv|4Z&)gJY z@AOJjr@D`u+C^GPMh%1wmyVk|B~aAI27;eDj!`}IrqNNQ$yQm2RjE86VaSV5S>X9v zGPiWY=3zX<$*gd3F_*0*RpTuO0W+Q>>bg5#nfQl_cYjVfi>Q$P4_yn-qM)eH?_hz< zk7D{W^IKwICtE3Sd|OGU%7U|m{q<`6WJ&vaFV;a0jC7Ps>)p81nQdVVDW9&p=O=im zqQ5Amtd6Ic?UNh+57l*$-T5wva1kae6xPD{z>aF{ zoxez3hE>mW_;*DEHPk%{NTi{guR_HtBB^uVr2=_6A|R8YZ)2esN!m zUo56&YVBJ8=w3P_Gq1(+O<6lv?wE_upefWzqRijN?czVqI$RZwq+mNN(zNQbEN32( zp$Qkeo$RN!7 Date: Sun, 24 Dec 2023 20:32:07 +0300 Subject: [PATCH 3/4] Pinta v1.1 --- lab-03/CustomColorPicker.java | 1 + lab-03/CustomMenuBar.java | 63 +++ lab-03/DataModel.java | 36 ++ lab-03/DrawingArea.java | 43 ++ lab-03/DrawingAreaController.java | 255 +++++++++++ lab-03/Icons.java | 184 ++++++++ lab-03/InfoBar.java | 140 ++++++ lab-03/Loader.java | 16 +- lab-03/Pinta.java | 702 +----------------------------- lab-03/Saver.java | 9 +- lab-03/ToolsBar.java | 123 ++++++ 11 files changed, 884 insertions(+), 688 deletions(-) create mode 100644 lab-03/CustomMenuBar.java create mode 100644 lab-03/DataModel.java create mode 100644 lab-03/DrawingArea.java create mode 100644 lab-03/DrawingAreaController.java create mode 100644 lab-03/Icons.java create mode 100644 lab-03/InfoBar.java create mode 100644 lab-03/ToolsBar.java diff --git a/lab-03/CustomColorPicker.java b/lab-03/CustomColorPicker.java index e75574e..fc5a2c2 100644 --- a/lab-03/CustomColorPicker.java +++ b/lab-03/CustomColorPicker.java @@ -4,6 +4,7 @@ import javafx.scene.layout.*; import javafx.scene.paint.Color; +import javax.xml.crypto.Data; import java.util.ArrayList; import java.util.List; import java.util.Optional; diff --git a/lab-03/CustomMenuBar.java b/lab-03/CustomMenuBar.java new file mode 100644 index 0000000..ce9ee5f --- /dev/null +++ b/lab-03/CustomMenuBar.java @@ -0,0 +1,63 @@ +import javafx.application.Platform; +import javafx.scene.canvas.Canvas; +import javafx.scene.control.*; + +import javax.xml.crypto.Data; +import java.io.File; + +public class CustomMenuBar extends MenuBar { + private final DataModel dataModel; + private final Menu file; + private final MenuItem open; + private final MenuItem save; + private final MenuItem saveAs; + private final MenuItem exit; + + CustomMenuBar(DataModel dataModel) { + this.dataModel = dataModel; + file = new Menu("File"); + open = new MenuItem("Open..."); + save = new MenuItem("Save..."); + saveAs = new MenuItem("Save as..."); + exit = new MenuItem("Exit"); + file.getItems().addAll(open, new SeparatorMenuItem(), save, saveAs, new SeparatorMenuItem(), exit); + createSetOnActionEvents(); + + getMenus().addAll(file); + } + + private void createSetOnActionEvents() { + open.setOnAction(e -> { + File file = dataModel.loader.load(); + if (file != null) { + dataModel.toFile = file; + dataModel.stage.setTitle(file.getName() + " - Pinta"); + } + }); + + saveAs.setOnAction(e -> { + dataModel.toFile = dataModel.saver.save(); + if (dataModel.toFile != null) { + dataModel.stage.setTitle(dataModel.toFile.getName() + " - Pinta"); + } + }); + + save.setOnAction(e -> { + try { + if (dataModel.toFile != null) { + dataModel.saver.saveIntoFile(dataModel.toFile); + } else { + dataModel.toFile = dataModel.saver.save(); + } + dataModel.stage.setTitle(dataModel.toFile.getName() + " - Pinta"); + } catch (Exception exc) { + exc.printStackTrace(); + } + }); + + exit.setOnAction(e -> { + Platform.exit(); + }); + } +} + diff --git a/lab-03/DataModel.java b/lab-03/DataModel.java new file mode 100644 index 0000000..674e27d --- /dev/null +++ b/lab-03/DataModel.java @@ -0,0 +1,36 @@ +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.CheckBox; +import javafx.scene.control.TextField; +import javafx.scene.paint.Color; +import javafx.scene.shape.StrokeLineCap; +import javafx.scene.shape.StrokeLineJoin; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.stage.Stage; + +import java.io.File; +import java.util.List; + +public class DataModel { + Stage stage; + Loader loader; + Saver saver; + Canvas drawCanvas; + GraphicsContext gcDraw; + Canvas tempCanvas; + GraphicsContext gcTemp; + CustomColorPicker customColorPicker; + + CheckBox fillCheckBox; + TextField sizeOfBrush; + + File toFile; + + InfoBar infoBar; + + ToolsBar tools; + List indexes; + + static final Font font = Font.font("Arial", FontWeight.BOLD, 14); +} diff --git a/lab-03/DrawingArea.java b/lab-03/DrawingArea.java new file mode 100644 index 0000000..27e4c0d --- /dev/null +++ b/lab-03/DrawingArea.java @@ -0,0 +1,43 @@ +import javafx.geometry.Insets; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.StrokeLineCap; +import javafx.scene.shape.StrokeLineJoin; + +public class DrawingArea extends StackPane { + private final Canvas drawCanvas; + private final GraphicsContext gcDraw; + private final Canvas tempCanvas; + private final GraphicsContext gcTemp; + DrawingArea(DataModel dataModel) { + drawCanvas = new Canvas(); + gcDraw = drawCanvas.getGraphicsContext2D(); + gcDraw.setLineCap(StrokeLineCap.ROUND); + gcDraw.setLineJoin(StrokeLineJoin.ROUND); + drawCanvas.setWidth(700); + drawCanvas.setHeight(400); +// + tempCanvas = new Canvas(); + gcTemp = tempCanvas.getGraphicsContext2D(); + tempCanvas.setWidth(drawCanvas.getWidth()); + tempCanvas.setHeight(drawCanvas.getHeight()); + + gcDraw.setStroke(Color.BLACK); + gcDraw.setLineWidth(2); + gcDraw.strokeRect(0, 0, drawCanvas.getWidth(), drawCanvas.getHeight()); + + getChildren().addAll(drawCanvas, tempCanvas); + //TODO + Loader loader = new Loader(drawCanvas, dataModel); + Saver saver = new Saver(drawCanvas, dataModel); + + dataModel.loader = loader; + dataModel.saver = saver; + dataModel.drawCanvas = drawCanvas; + dataModel.tempCanvas = tempCanvas; + dataModel.gcDraw = gcDraw; + dataModel.gcTemp = gcTemp; + } +} diff --git a/lab-03/DrawingAreaController.java b/lab-03/DrawingAreaController.java new file mode 100644 index 0000000..80bb7a9 --- /dev/null +++ b/lab-03/DrawingAreaController.java @@ -0,0 +1,255 @@ +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.ToggleButton; +import javafx.scene.image.Image; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.paint.Color; + +public class DrawingAreaController { + DataModel dataModel; + + private double lastX, lastY; + private double startX, startY; + private boolean isShapeSelected = false; + + DrawingAreaController(DataModel dataModel) { + this.dataModel = dataModel; + + createSizeEvents(); + createCanvasEvents(); + } + + private void createSizeEvents() { + dataModel.stage.widthProperty().addListener((obs, oldWidth, newWidth) -> { + dataModel.gcDraw.clearRect(0, 0, dataModel.drawCanvas.getWidth(), dataModel.drawCanvas.getHeight()); + Image image = dataModel.drawCanvas.snapshot(null, null); + dataModel.drawCanvas.setWidth(newWidth.doubleValue() - 100); + dataModel.tempCanvas.setWidth(dataModel.drawCanvas.getWidth()); + dataModel.gcDraw.setStroke(Color.BLACK); + dataModel.gcDraw.setLineWidth(2); + dataModel.gcDraw.drawImage(image, 0, 0); + dataModel.gcDraw.strokeRect(0, 0, dataModel.drawCanvas.getWidth(), dataModel.drawCanvas.getHeight()); + }); + + dataModel.stage.heightProperty().addListener((obs, oldHeight, newHeight) -> { + dataModel.gcDraw.clearRect(0, 0, dataModel.drawCanvas.getWidth(), dataModel.drawCanvas.getHeight()); + Image image = dataModel.drawCanvas.snapshot(null, null); + dataModel.drawCanvas.setHeight(newHeight.doubleValue() - 260); + dataModel.tempCanvas.setHeight(dataModel.drawCanvas.getHeight()); + dataModel.gcDraw.setStroke(Color.BLACK); + dataModel.gcDraw.setLineWidth(2); + dataModel.gcDraw.drawImage(image, 0, 0); + dataModel.gcDraw.strokeRect(0, 0, dataModel.drawCanvas.getWidth(), dataModel.drawCanvas.getHeight()); + + }); + } + + private void createCanvasEvents() { + //TODO + dataModel.tempCanvas.setOnMouseClicked(e -> { + String id = ""; + for (var elem : dataModel.tools.getChildren()) { + if (((ToggleButton) elem).isSelected()) { + id = elem.getId(); + break; + } + } + mouseClickedChooser(e, id); + }); + dataModel.tempCanvas.setOnMousePressed(e -> { + lastX = startX = e.getX(); + lastY = startY = e.getY(); + }); + + dataModel.tempCanvas.setOnMouseDragged(e -> { + String id = ""; + for (var elem : dataModel.tools.getChildren()) { + if (((ToggleButton) elem).isSelected()) { + id = elem.getId(); + break; + } + } + mouseDraggedChooser(e, id); + }); + + dataModel.tempCanvas.setOnMouseReleased(e -> { + if (isShapeSelected) { + var shapes = dataModel.tools.getChildren(); + for (int ind : dataModel.indexes) { + if (((ToggleButton) shapes.get(ind)).isSelected()) { + mouseReleasedChooser(e, ((ToggleButton) shapes.get(ind)).getId()); + } + } + } + }); + } + + private void mouseClickedChooser(MouseEvent e, String id) { + switch (id) { + case "brush" -> { + try { + dataModel.gcDraw.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + } + dataModel.gcDraw.strokeOval(e.getX(), e.getY(), dataModel.gcDraw.getLineWidth(), dataModel.gcDraw.getLineWidth()); + } + case "pencil" -> { + dataModel.gcDraw.setLineWidth(1); + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + } + dataModel.gcDraw.strokeOval(e.getX(), e.getY(), 1, 1); + } + //TODO + default -> {} + } + } + + private void mouseDraggedChooser(MouseEvent e, String id) { + switch (id) { + case "brush" -> { + isShapeSelected = false; + try { + dataModel.gcDraw.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + } + double x = e.getX(); + double y = e.getY(); + dataModel.gcDraw.strokeLine(lastX, lastY, x, y); + lastX = x; + lastY = y; + } + case "pencil" -> { + isShapeSelected = false; + dataModel.gcDraw.setLineWidth(1); + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + } + double x = e.getX(); + double y = e.getY(); + dataModel.gcDraw.strokeLine(lastX, lastY, x, y); + lastX = x; + lastY = y; + } + case "rect" -> { + isShapeSelected = true; + dataModel.gcTemp.clearRect(0 , 0, dataModel.tempCanvas.getWidth(), dataModel.tempCanvas.getHeight()); + lastX = e.getX(); + lastY = e.getY(); + try { + dataModel.gcTemp.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcTemp.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcTemp.setStroke(dataModel.customColorPicker.getMainColor()); + dataModel.gcTemp.setFill(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcTemp.setStroke(dataModel.customColorPicker.getExtraColor()); + dataModel.gcTemp.setFill(dataModel.customColorPicker.getExtraColor()); + } + if (dataModel.fillCheckBox.isSelected()) { + dataModel.gcTemp.fillRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + dataModel.gcTemp.strokeRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + case "oval" -> { + isShapeSelected = true; + dataModel.gcTemp.clearRect(0 , 0, dataModel.tempCanvas.getWidth(), dataModel.tempCanvas.getHeight()); + lastX = e.getX(); + lastY = e.getY(); + try { + dataModel.gcTemp.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcTemp.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcTemp.setStroke(dataModel.customColorPicker.getMainColor()); + dataModel.gcTemp.setFill(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcTemp.setStroke(dataModel.customColorPicker.getExtraColor()); + dataModel.gcTemp.setFill(dataModel.customColorPicker.getExtraColor()); + } + if (dataModel.fillCheckBox.isSelected()) { + dataModel.gcTemp.fillOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + dataModel.gcTemp.strokeOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + //TODO + default -> {} + } + } + + private void mouseReleasedChooser(MouseEvent e, String id) { + switch (id) { + case "rect" -> { + dataModel.gcTemp.clearRect(0, 0, dataModel.tempCanvas.getWidth(), dataModel.tempCanvas.getHeight()); + try { + dataModel.gcDraw.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + dataModel.gcDraw.setFill(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + dataModel.gcDraw.setFill(dataModel.customColorPicker.getExtraColor()); + } + if (dataModel.fillCheckBox.isSelected()) { + dataModel.gcDraw.fillRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + dataModel.gcDraw.strokeRect(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + case "oval" -> { + dataModel.gcTemp.clearRect(0, 0, dataModel.tempCanvas.getWidth(), dataModel.tempCanvas.getHeight()); + try { + dataModel.gcDraw.setLineWidth(Integer.parseInt(dataModel.sizeOfBrush.getText())); + } catch (Exception exc) { + dataModel.gcDraw.setLineWidth(3); + } + if (e.getButton() == MouseButton.PRIMARY) { + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getMainColor()); + dataModel.gcDraw.setFill(dataModel.customColorPicker.getMainColor()); + } else if (e.getButton() == MouseButton.SECONDARY){ + dataModel.gcDraw.setStroke(dataModel.customColorPicker.getExtraColor()); + dataModel.gcDraw.setFill(dataModel.customColorPicker.getExtraColor()); + } + if (dataModel.fillCheckBox.isSelected()) { + dataModel.gcDraw.fillOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } else { + dataModel.gcDraw.strokeOval(Math.min(startX, lastX), Math.min(startY, lastY), + Math.abs(lastX - startX), Math.abs(lastY - startY)); + } + } + //TODO + default -> {} + } + } +} diff --git a/lab-03/Icons.java b/lab-03/Icons.java new file mode 100644 index 0000000..5309a22 --- /dev/null +++ b/lab-03/Icons.java @@ -0,0 +1,184 @@ +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; + +import javax.xml.crypto.Data; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +public class Icons extends HBox { + private final DataModel dataModel; + private final Button create; + private final Button open; + private final Button save; + private final Button paste; + private final Button clear; + Icons(DataModel dataModel) { + this.dataModel = dataModel; + + setPadding(new Insets(0, 0, 0, 8)); + + create = new Button(); + ImageView createImageView = new ImageView(new Image("/images/Pinta/create.png")); + createImageView.setFitWidth(30); + createImageView.setFitHeight(30); + create.setStyle("-fx-background-color: transparent;"); + create.setGraphic(createImageView); + create.setPrefSize(createImageView.getFitWidth() + 13, createImageView.getFitHeight() + 13); + + open = new Button(); + ImageView openImageView = new ImageView(new Image("/images/Pinta/open.png")); + openImageView.setFitWidth(createImageView.getFitWidth() + 4); + openImageView.setFitHeight(createImageView.getFitHeight() + 4); + open.setStyle("-fx-background-color: transparent;"); + open.setGraphic(openImageView); + open.setText(" Open"); + open.setFont(DataModel.font); + + save = new Button(); + ImageView saveImageView = new ImageView(new Image("/images/Pinta/save.png")); + saveImageView.setFitWidth(createImageView.getFitWidth()); + saveImageView.setFitHeight(createImageView.getFitHeight()); + save.setStyle("-fx-background-color: transparent;"); + save.setGraphic(saveImageView); + save.setText(" Save"); + save.setFont(DataModel.font); + save.setPrefSize(100, openImageView.getFitHeight() + 10); + + paste = new Button(); + ImageView pasteImageView = new ImageView(new Image("/images/Pinta/paste.png")); + pasteImageView.setFitWidth(createImageView.getFitWidth() + 4); + pasteImageView.setFitHeight(createImageView.getFitHeight()); + paste.setStyle("-fx-background-color: transparent;"); + paste.setGraphic(pasteImageView); + paste.setText(" Paste"); + paste.setFont(DataModel.font); + paste.setPrefSize(115, openImageView.getFitHeight() + 10); + + clear = new Button(); + ImageView clearImageView = new ImageView("/images/Pinta/clear.png"); + clearImageView.setFitWidth(createImageView.getFitWidth() + 4); + clearImageView.setFitHeight(createImageView.getFitHeight()); + clear.setStyle("-fx-background-color: transparent;"); + clear.setGraphic(clearImageView); + clear.setText(" Clear"); + clear.setFont(DataModel.font); + clear.setPrefSize(115, openImageView.getFitHeight() + 10); + + List