Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.railroadide.core.ui.collage;

/**
* A listener interface for receiving notifications about changes to the canvas.
*/
public interface CanvasChangeListener {
/**
* Invoked when the canvas has changed.
*/
void onCanvasChanged();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package dev.railroadide.core.ui.collage;

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
* A canvas that holds collage elements and manages their state.
* @param <T> the type of collage element
*/
public abstract class CollageCanvas<T extends CollageElement> {
private final List<CanvasChangeListener> listeners = new ArrayList<>();
private List<T> elements;
private T selectedElement;

/**
* Creates a new CollageCanvas with an empty list of elements.
*/
public CollageCanvas() {
this.elements = new ArrayList<>();
}

/**
* Adds an element to the canvas and notifies listeners of the change.
* @param element the element to add
*/
public void addElement(T element) {
this.elements.add(element);
notifyChangeListeners();
}

/**
* Removes an element from the canvas and notifies listeners of the change.
* @param element the element to remove
*/
public void removeElement(T element) {
this.elements.remove(element);
notifyChangeListeners();
}

/**
* Updates an existing element on the canvas and notifies listeners of the change.
* @param oldElement the element to update
* @param newElement the new element to replace the old one
*/
public void updateElement(T oldElement, T newElement) {
int index = elements.indexOf(oldElement);
if (index != -1) {
elements.set(index, newElement);
}
notifyChangeListeners();
}

/**
* Gets an unmodifiable list of elements on the canvas.
* @return the list of elements
*/
public List<T> getElements() {
return Collections.unmodifiableList(elements);
}

/**
* Clears all elements from the canvas and notifies listeners of the change.
*/
public void clear() {
this.elements.clear();
this.selectedElement = null;
notifyChangeListeners();
}

/**
* Adds a listener to be notified when the canvas changes.
* @param listener the listener to add
*/
public void addChangeListener(CanvasChangeListener listener) {
this.listeners.add(listener);
}

/**
* Removes a listener from the canvas.
* @param listener the listener to remove
*/
public void removeChangeListener(CanvasChangeListener listener) {
this.listeners.remove(listener);
}

/**
* Notifies all registered listeners of a change to the canvas.
*/
public void notifyChangeListeners() {
for (CanvasChangeListener listener : listeners) {
listener.onCanvasChanged();
}
}

/**
* Sets the selected element on the canvas and notifies listeners of the change.
* @param element the element to select
*/
public void setSelectedElement(T element) {
this.selectedElement = element;
notifyChangeListeners();
}

/**
* Gets the currently selected element on the canvas.
* @return an Optional containing the selected element, or empty if no element is selected
*/
public Optional<T> getSelectedElement() {
return Optional.ofNullable(this.selectedElement);
}

/**
* Gets the element at the specified coordinates, if any.
* @param x the x coordinate
* @param y the y coordinate
* @return an Optional containing the element at the specified coordinates, or empty if no element is found
*/
public Optional<T> getElementFromPosition(int x, int y) {
for (T element : elements) {
if (x < element.getX() || x > element.getX() + element.getWidth()) continue;
if (y < element.getY() || y > element.getY() + element.getHeight()) continue;
return Optional.of(element);
}

return Optional.empty();
}

/**
* Renders the selection box around the selected element, if any.
* @param gc the GraphicsContext to render with
*/
public void render(GraphicsContext gc) {
if (getSelectedElement().isPresent()) {
T selected = getSelectedElement().get();
var box = new Rectangle(selected.getX(), selected.getY(), selected.getWidth(), selected.getHeight());
renderSelectionBox(gc, box);
}
}

/**
* Renders a selection box around the given rectangle.
* @param gc the GraphicsContext to render with
* @param box the rectangle to draw the selection box around
*/
void renderSelectionBox(GraphicsContext gc, Rectangle box) {
gc.setStroke(Color.color(0.23, 1, 0.34)); // TODO Use theme colour?
gc.setLineWidth(3);
final double x = box.getX() - gc.getLineWidth() + 1;
final double y = box.getY() - gc.getLineWidth() + 1;
final double w = box.getWidth() + gc.getLineWidth();
final double h = box.getHeight() + gc.getLineWidth();
gc.strokeRect(x, y, w, h);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.railroadide.core.ui.collage;

import javafx.scene.canvas.GraphicsContext;

/**
* A collage element that can be rendered on a canvas.
*/
public interface CollageElement {
int getX();
int getY();
int getWidth();
int getHeight();

/**
* Renders the element on the given GraphicsContext.
* @param gc the GraphicsContext to render on
*/
void render(GraphicsContext gc);
}
23 changes: 23 additions & 0 deletions src/main/java/dev/railroadide/railroad/ide/IDESetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
import dev.railroadide.core.settings.keybinds.KeybindContexts;
import dev.railroadide.core.settings.keybinds.KeybindData;
import dev.railroadide.core.ui.*;
import dev.railroadide.railroad.ide.features.gui_generation.GuiCollage;
import dev.railroadide.core.ui.localized.LocalizedCheckMenuItem;
import dev.railroadide.core.ui.localized.LocalizedLabel;
import dev.railroadide.core.ui.localized.LocalizedMenu;
import dev.railroadide.core.ui.localized.LocalizedMenuItem;
import dev.railroadide.railroad.Railroad;
import dev.railroadide.railroad.ide.features.gui_generation.GuiBackgroundGenerator;
import dev.railroadide.railroad.ide.projectexplorer.ProjectExplorerPane;
import dev.railroadide.railroad.ide.ui.ConsolePane;
import dev.railroadide.railroad.ide.ui.IDEWelcomePane;
Expand Down Expand Up @@ -43,6 +45,9 @@
import org.kordamp.ikonli.fontawesome6.FontAwesomeSolid;
import org.kordamp.ikonli.javafx.FontIcon;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Locale;
Expand Down Expand Up @@ -138,6 +143,23 @@ private static MenuBar createMenuBar() {
newFileItem.setGraphic(new FontIcon(FontAwesomeSolid.FILE));
newFileItem.setKeybindData(new KeybindData(KeyCode.N, new KeyCombination.Modifier[]{KeyCombination.SHORTCUT_DOWN}));

var guiTestItem = new MenuItem("Open GUI Test Window");
guiTestItem.setOnAction($ -> {
// TODO move to File -> New -> GUI & take in input for type, size etc
var testStage = new Stage();
testStage.setTitle("GUI Test Window");
BufferedImage refImage = null;
try {
refImage = ImageIO.read(Path.of("D:\\template.png").toFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
var testPane = new GuiCollage(GuiBackgroundGenerator.builder().setHeight(158).setWidth(176).setReferenceImage(refImage).build());
var scene = new Scene(testPane, 800, 600);
testStage.setScene(scene);
testStage.show();
});

var openFileItem = new LocalizedMenuItem("railroad.menu.file.open_file");
openFileItem.setGraphic(new FontIcon(FontAwesomeSolid.FOLDER_OPEN));
openFileItem.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.SHORTCUT_DOWN));
Expand Down Expand Up @@ -255,6 +277,7 @@ private static MenuBar createMenuBar() {
fileMenu.getItems().add(saveAsItem);
fileMenu.getItems().add(separator1);
fileMenu.getItems().add(exitItem);
fileMenu.getItems().add(guiTestItem);
fileMenu.getStyleClass().add("rr-menu");

var editMenu = new LocalizedMenu("railroad.menu.edit");
Expand Down
Loading
Loading