Skip to content

Commit

Permalink
add Grid to desktop, buttons in grid with functionality: can be moved…
Browse files Browse the repository at this point in the history
… in grid and opens popup when pressed
  • Loading branch information
peretr committed Apr 15, 2026
1 parent 3eeb661 commit 2325e36
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 41 deletions.
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

0 comments on commit 2325e36

Please sign in to comment.