Skip to content

add Grid to desktop, buttons in grid with functionality: can be moved… #80

Merged
merged 1 commit into from
Apr 15, 2026
Merged
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,130 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller;

import edu.ntnu.idi.idatt2003.gruppe42.Model.Apps;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.AppStorePopup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.BankPopup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.HustlersPopup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.MailPopup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.NewsPopup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.Popup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.StockPopup;
import javafx.beans.binding.Bindings;
import javafx.scene.control.Button;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;

/**
* Controller for the app buttons.
* Handles app button creation, resizing, click events, and drag-and-drop.
*/
public class AppController {
private final PopupController popupController;
private final Pane parent;

/**
* Constructs a new app controller.
*
* @param popupController the popup controller to manage popups.
* @param parent the parent pane to add popups to.
*/
public AppController(PopupController popupController, Pane parent) {
this.popupController = popupController;
this.parent = parent;
}

/**
* Creates an app button with click and drag functionality.
*
* @param type the type of the app.
* @return the app button.
*/
public Button createAppButton(Apps type) {
Button button = new Button(type.toString());
button.setMinSize(0, 0);

// Bind button size to parent dimensions to keep it square and responsive
button.parentProperty().addListener((observable, oldParent, newParent) -> {
if (newParent instanceof Region region) {
button.prefWidthProperty().bind(
Bindings.min(
region.widthProperty().multiply(0.8),
region.heightProperty()).multiply(0.8));
button.prefHeightProperty().bind(button.prefWidthProperty());
} else {
button.prefWidthProperty().unbind();
button.prefHeightProperty().unbind();
}
});

// Print when clicked and open popup
button.setOnAction(event -> {
System.out.println("button pressed: " + type);
openPopup(type);
});

// Handle start of drag: initiate drag-and-drop
button.setOnDragDetected(event -> {
Dragboard dragboard = button.startDragAndDrop(TransferMode.MOVE);
dragboard.setDragView(button.snapshot(null, null));
dragboard.setDragViewOffsetX(event.getX());
dragboard.setDragViewOffsetY(event.getY());
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString("app_button");
dragboard.setContent(clipboardContent);
event.consume();
});

return button;
}

/**
* Opens the correct popup based on the app type.
*
* @param type the app type.
*/
private void openPopup(Apps type) {
Popup popup = switch (type) {
case APPSTORE -> new AppStorePopup(400, 300, 100, 100);
case HUSTLERS -> new HustlersPopup(400, 300, 140, 140);
case STOCK -> new StockPopup(400, 300, 200, 200);
case MAIL -> new MailPopup(400, 300, 160, 160);
case NEWS -> new NewsPopup(400, 300, 180, 180);
case BANK -> new BankPopup(400, 300, 120, 120);
};

if (popupController.add(popup)) {
parent.getChildren().add(popup.getRoot());
}
}

/**
* Configures a cell to be a drop target for app buttons.
*
* @param cell the stack pane cell to configure.
*/
public void configureCellAsDropTarget(StackPane cell) {
// Handle drag over cell: allow drop if cell is empty
cell.setOnDragOver(event -> {
if (event.getGestureSource() instanceof Button && cell.getChildren().isEmpty()) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});

// Handle drop on cell: move the button to this cell
cell.setOnDragDropped(event -> {
boolean success = false;
if (event.getGestureSource() instanceof Button button) {
((StackPane) button.getParent()).getChildren().remove(button);
cell.getChildren().add(button);
success = true;
}
event.setDropCompleted(success);
event.consume();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public boolean add(Popup popup) {
if (popup == null || popups.contains(popup)) {
return false;
}
popup.getCloseButton().setOnAction(e -> remove(popup));
popup.getRoot().setOnMousePressed(e -> bringToFront(popup));
popup.getContent().setOnMousePressed(e -> bringToFront(popup));
popup.getCloseButton().setOnAction(event -> remove(popup));
popup.getRoot().setOnMousePressed(event -> bringToFront(popup));
popup.getContent().setOnMousePressed(event -> bringToFront(popup));
return popups.add(popup);
}

Expand Down Expand Up @@ -64,8 +64,7 @@ public void bringToFront(Popup popup) {
}

/**
* Checks if a popup is out of bounds and moves it back if necessary.
*
* Checks if a popup is out of bounds and moves it back if necessary
* @param popup the popup to check
*/
public void keepInBounds(Popup popup) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller;

import edu.ntnu.idi.idatt2003.gruppe42.Millions;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Player;
import edu.ntnu.idi.idatt2003.gruppe42.View.StartView;
import java.math.BigDecimal;
Expand All @@ -8,9 +9,11 @@ public class StartViewController {

private String username = "";
private final StartView startView;
private final Millions application;

public StartViewController(StartView startView) {
public StartViewController(Millions application, StartView startView) {

this.application = application;
this.startView = startView;

startView.getUsernameField().textProperty().addListener((obs, old, newValue) -> {
Expand All @@ -19,14 +22,15 @@ public StartViewController(StartView startView) {
}
});

startView.getLoginButton().setOnAction(e -> handleStart());
startView.getLoginButton().setOnAction(event -> handleStart());
}

private void handleStart() {
BigDecimal money = getStartingMoney();

Player player = new Player(username, money);
System.out.println(player.getMoney());
application.switchToDesktopView();
}

private boolean isValidName(String value) {
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Millions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ public void start(Stage stage) throws Exception {
this.stage = stage;

StartView startView = new StartView();
new StartViewController(startView);
new StartViewController(this, startView);

scene = new Scene(startView.getRoot(), 900, 700);

stage.setTitle("Millions");
stage.setScene(scene);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.show();

switchToDesktopView();
}

public void switchToStartView() {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Apps.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package edu.ntnu.idi.idatt2003.gruppe42.Model;

public enum Apps {
APPSTORE,
HUSTLERS,
STOCK,
MAIL,
NEWS,
BANK
}
110 changes: 79 additions & 31 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/DesktopView.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,95 @@
package edu.ntnu.idi.idatt2003.gruppe42.View;

import edu.ntnu.idi.idatt2003.gruppe42.Controller.AppController;
import edu.ntnu.idi.idatt2003.gruppe42.Controller.PopupController;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.Popup;
import edu.ntnu.idi.idatt2003.gruppe42.View.Popups.SimplePopup;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Apps;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import java.util.Random;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;

/**
* View for the desktop.
* Displays a 6x4 grid of apps.
*/
public class DesktopView {

private PopupController popupController;
private final PopupController popupController;
private final AppController appController;
private final BorderPane root;
private static final int COLS = 6;
private static final int ROWS = 4;

public DesktopView() {
popupController = new PopupController();
this.popupController = new PopupController();
this.root = new BorderPane();
this.appController = new AppController(popupController, root);
}

/**
* Returns the root of the desktop view.
*
* @return the root of the desktop view.
*/
public BorderPane getRoot() {

BorderPane root = new BorderPane();
Pane center = new Pane();

Button button = new Button("Add");
Random random = new Random();
button.setOnAction(e -> {
int width = random.nextInt(400) + 100;
int height = random.nextInt(400) + 100;
int x = random.nextInt(1000);
int y = random.nextInt(700);
Popup popup = new SimplePopup(width, height, x, y);
center.getChildren().add(popup.getRoot());
popupController.add(popup);
popupController.keepInBounds(popup);

popup.getRoot().setOnMouseDragged(event -> {
popupController.keepInBounds(popup);
});
});

center.getChildren().add(button);
//center.getChildren().addAll(popupController.getPopups().stream().map(Popup::getRoot).toList());
root.setCenter(center);

GridPane grid = createGrid();
root.setCenter(grid);
return root;
}

/**
* Creates the 6x4 grid with app buttons.
*
* @return the grid pane.
*/
private GridPane createGrid() {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(0);
grid.setVgap(0);

// Set constraints to make the grid fit the width and height of the screen
for (int col = 0; col < COLS; col++) {
ColumnConstraints colConstraints = new ColumnConstraints();
colConstraints.setPercentWidth(100.0 / COLS);
colConstraints.setHgrow(Priority.ALWAYS);
grid.getColumnConstraints().add(colConstraints);
}
for (int row = 0; row < ROWS; row++) {
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(100.0 / ROWS);
rowConstraints.setVgrow(Priority.ALWAYS);
grid.getRowConstraints().add(rowConstraints);
}

for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
StackPane cell = createCell();
grid.add(cell, col, row);

// Add initial buttons to the first row based on the Apps enum
if (row == 0 && col < Apps.values().length) {
cell.getChildren().add(appController.createAppButton(Apps.values()[col]));
}
}
}
return grid;
}

/**
* Creates a cell for the grid that acts as a drop target.
*
* @return the stack pane cell.
*/
private StackPane createCell() {
StackPane cell = new StackPane();
cell.setStyle("-fx-border-color: black; -fx-border-width: 1;");
appController.configureCellAsDropTarget(cell);
return cell;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package edu.ntnu.idi.idatt2003.gruppe42.View.Popups;

/**
* A popup for the AppStore app.
*/
public class AppStorePopup extends Popup {

/**
* Constructs a new AppStore popup.
*
* @param width width of the popup
* @param height height of the popup
* @param x x-position of the popup
* @param y y-position of the popup
*/
public AppStorePopup(int width, int height, int x, int y) {
super(width, height, x, y);
// Add AppStore specific content here
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package edu.ntnu.idi.idatt2003.gruppe42.View.Popups;

/**
* A popup for the Bank app.
*/
public class BankPopup extends Popup {

/**
* Constructs a new Bank popup.
*
* @param width width of the popup
* @param height height of the popup
* @param x x-position of the popup
* @param y y-position of the popup
*/
public BankPopup(int width, int height, int x, int y) {
super(width, height, x, y);
// Add Bank specific content here
}
}
Loading