diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java new file mode 100644 index 0000000..e1e4d84 --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java @@ -0,0 +1,26 @@ +package org.to.telegramfinalproject.UI; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; + +import java.io.IOException; + +public class ChatItemController { + + @FXML private ImageView profileImage; + @FXML private Label chatName; + @FXML private Label lastMessage; + @FXML private Label chatTime; + @FXML private Label unreadCount; + + public void setChatData(String name, String lastMsg, String time, int unread) { + chatName.setText(name); + lastMessage.setText(lastMsg); + chatTime.setText(time); + unreadCount.setVisible(unread > 0); + unreadCount.setText(String.valueOf(unread)); + } +} \ No newline at end of file diff --git a/src/main/java/org/to/telegramfinalproject/UI/MainController.java b/src/main/java/org/to/telegramfinalproject/UI/MainController.java new file mode 100644 index 0000000..d886977 --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/UI/MainController.java @@ -0,0 +1,211 @@ +package org.to.telegramfinalproject.UI; + +import javafx.animation.TranslateTransition; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.SplitPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.util.Duration; + +import java.io.IOException; + +public class MainController { + + @FXML private StackPane mainRoot; + @FXML private VBox chatListContainer; + @FXML private StackPane chatDisplayArea; + @FXML private Pane overlay; + @FXML private ImageView menuIcon; + @FXML private ScrollPane scrollPane; + @FXML private SplitPane mainSplitPane; + @FXML private VBox leftPane; + @FXML private Button menuButton; + @FXML private TextField searchBar; + + private Node sidebarRoot; + private boolean isSidebarOpen = false; + + // Add ThemeManager handle + private final ThemeManager themeManager = ThemeManager.getInstance(); + + @FXML + public void initialize() { + addSampleChats(); + + // Register the scene for automatic CSS updates + Platform.runLater(() -> { + ThemeManager.getInstance().registerScene(mainRoot.getScene()); + }); + + // Listen for theme changes to update icons & labels manually + ThemeManager.getInstance().darkModeProperty().addListener((obs, oldVal, newVal) -> { + if (newVal) { + // Dark mode ON + updateIconsForDarkMode(); + updateLabelsForDarkMode(); + } else { + // Light mode ON + updateIconsForLightMode(); + updateLabelsForLightMode(); + } + }); + + // Smooth scroll feel + scrollPane.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm()); + scrollPane.setPannable(true); + scrollPane.setFitToWidth(true); + scrollPane.setFitToHeight(false); + scrollPane.getContent().setOnScroll(event -> { + double deltaY = event.getDeltaY() * 0.003; // smaller = smoother + scrollPane.setVvalue(scrollPane.getVvalue() - deltaY); + }); + + // ---------- SplitPane limits so panes can't fully collapse ---------- + leftPane.setMinWidth(72); // avatars-only collapse + chatDisplayArea.setMinWidth(360); // chat area never fully collapses + + mainSplitPane.widthProperty().addListener((o, ov, nv) -> clampDivider()); + if (!mainSplitPane.getDividers().isEmpty()) { + mainSplitPane.getDividers().get(0).positionProperty().addListener((o, ov, nv) -> clampDivider()); + } + } + + private void addSampleChats() { + addChat("Archived Chats", "Your archived chats", "10:45", 0); + addChat("Saved Messages", "Keep messages for later", "Yesterday", 0); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + addChat("Alice", "Hey, how are you?", "14:12", 3); + addChat("Bob", "Let's meet tomorrow", "12:08", 1); + } + + private void addChat(String name, String lastMsg, String time, int unread) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml")); + Node chatItem = loader.load(); + ChatItemController controller = loader.getController(); + controller.setChatData(name, lastMsg, time, unread); + + chatItem.setOnMouseClicked(e -> openChat(name)); + chatListContainer.getChildren().add(chatItem); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void openChat(String chatName) { + chatDisplayArea.getChildren().clear(); + chatDisplayArea.getChildren().add(new javafx.scene.control.Label("Chat with " + chatName)); + } + + @FXML + private void toggleSidebar() { + if (isSidebarOpen) { + closeSidebar(); + } else { + openSidebar(); + } + } + + @FXML + private void openSidebar() { + try { + if (sidebarRoot == null) { + sidebarRoot = FXMLLoader.load(getClass().getResource("/org/to/telegramfinalproject/Fxml/Sidebar_menu.fxml")); + StackPane.setAlignment(sidebarRoot, Pos.CENTER_LEFT); + sidebarRoot.setTranslateX(-getSidebarWidth()); + mainRoot.getChildren().add(sidebarRoot); + } + + TranslateTransition slideIn = new TranslateTransition(Duration.millis(250), sidebarRoot); + slideIn.setToX(0); + slideIn.play(); + + overlay.setVisible(true); + overlay.setMouseTransparent(false); + + isSidebarOpen = true; + + } catch (IOException e) { + e.printStackTrace(); + } + } + + @FXML + private void closeSidebar() { + if (sidebarRoot != null && isSidebarOpen) { + TranslateTransition slideOut = new TranslateTransition(Duration.millis(250), sidebarRoot); + slideOut.setToX(-getSidebarWidth()); + slideOut.setOnFinished(e -> { + overlay.setVisible(false); + overlay.setMouseTransparent(true); + isSidebarOpen = false; + }); + slideOut.play(); + } + } + + private double getSidebarWidth() { + return 250; // Sidebar width in px + } + + private void clampDivider() { + if (mainSplitPane.getDividers().isEmpty()) return; + + double totalW = mainSplitPane.getWidth(); + if (totalW <= 0) return; + + double leftMinRatio = leftPane.getMinWidth() / totalW; + double rightMinRatio = chatDisplayArea.getMinWidth() / totalW; + double maxLeftRatio = 1.0 - rightMinRatio; + + SplitPane.Divider d = mainSplitPane.getDividers().get(0); + double p = d.getPosition(); + if (p < leftMinRatio) { + d.setPosition(leftMinRatio); + } else if (p > maxLeftRatio) { + d.setPosition(maxLeftRatio); + } + } + + private void updateIconsForDarkMode() { + // Example: switch images to white versions + menuIcon.setImage(new Image(getClass().getResourceAsStream("/org/to/telegramfinalproject/Icons/menu_light.png"))); + } + + private void updateIconsForLightMode() { + // Example: switch images to black versions + menuIcon.setImage(new Image(getClass().getResourceAsStream("/org/to/telegramfinalproject/Icons/menu_dark.png"))); + } + + private void updateLabelsForDarkMode() { + //myLabel.setStyle("-fx-text-fill: white;"); + } + + private void updateLabelsForLightMode() { + //myLabel.setStyle("-fx-text-fill: black;"); + } +} \ No newline at end of file diff --git a/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java b/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java index e5c709b..2f8167f 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/SidebarMenuController.java @@ -42,7 +42,7 @@ public class SidebarMenuController { @FXML public void initialize() { - // Load default profile image (if present) + // Load default profile image Image profile = loadImage("/org/to/telegramfinalproject/Images/profile.png"); if (profile != null) profileImage.setImage(profile); @@ -55,8 +55,7 @@ public class SidebarMenuController { // 1) Register with ThemeManager so this scene auto-updates on theme changes themeManager.registerScene(newScene); - // 2) Make sure we start in LIGHT mode (if that's what you want) - // (If you already set the initial mode elsewhere, remove the next line) + // 2) Make sure we start in LIGHT mode themeManager.setDarkMode(false); // 3) Sync icons & toggle with current mode @@ -93,6 +92,7 @@ public class SidebarMenuController { // Update the global theme via ThemeManager themeManager.setDarkMode(newDark); + themeManager.applyThemeToAll(); // Animate the thumb to its new position (listener will handle icons & final position sync) syncToggleVisual(newDark, /*animate=*/true); diff --git a/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java b/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java index 204683a..1dfc7dc 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java +++ b/src/main/java/org/to/telegramfinalproject/UI/TelegramApplication.java @@ -11,7 +11,7 @@ import java.io.IOException; public class TelegramApplication extends Application { @Override public void start(Stage stage) throws IOException { - FXMLLoader fxmlLoader = new FXMLLoader(TelegramApplication.class.getResource("/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml")); + FXMLLoader fxmlLoader = new FXMLLoader(TelegramApplication.class.getResource("/org/to/telegramfinalproject/Fxml/main.fxml")); Scene scene = new Scene(fxmlLoader.load(), 1480, 820); scene.getStylesheets().add(getClass().getResource("/org/to/telegramfinalproject/CSS/light_theme.css").toExternalForm()); diff --git a/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java b/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java index c58066c..43b6425 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ThemeManager.java @@ -41,7 +41,7 @@ public class ThemeManager { } } - private void applyThemeToAll() { + public void applyThemeToAll() { for (Scene scene : registeredScenes) { applyTheme(scene); } diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css index 0b92773..11742c5 100644 --- a/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css +++ b/src/main/resources/org/to/telegramfinalproject/CSS/dark_theme.css @@ -50,3 +50,11 @@ .button, .label { -fx-text-fill: white; } + +/* Thin Telegram-like SplitPane divider (dark) */ +.split-pane:horizontal > .split-pane-divider { + -fx-background-color: transparent; /* no big solid block */ + -fx-border-color: #cccccc; /* the visible thin line */ + -fx-border-width: 0 1px 0 1px; /* 1px vertical line */ + -fx-padding: 0 0 0 0.5px; /* big invisible hitbox for the mouse */ +} diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css index 7ef5c23..3f6ffd0 100644 --- a/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css +++ b/src/main/resources/org/to/telegramfinalproject/CSS/light_theme.css @@ -50,3 +50,11 @@ .button, .label { -fx-text-fill: black; } + +/* Thin Telegram-like SplitPane divider (light) */ +.split-pane:horizontal > .split-pane-divider { + -fx-background-color: transparent; /* no big solid block */ + -fx-border-color: #cccccc; /* the visible thin line */ + -fx-border-width: 0 1px 0 1px; /* 1px vertical line */ + -fx-padding: 0 0 0 0.5px; /* big invisible hitbox for the mouse */ +} diff --git a/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css b/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css new file mode 100644 index 0000000..b6f1ffe --- /dev/null +++ b/src/main/resources/org/to/telegramfinalproject/CSS/scrollpane.css @@ -0,0 +1,22 @@ +.scroll-pane > .viewport { + -fx-background-color: transparent; /* No background behind content */ +} + +.scroll-pane .scroll-bar { + -fx-background-color: transparent; /* Remove background bar */ + -fx-opacity: 0; /* Initially hidden */ + -fx-padding: 0; + -fx-pref-width: 6px; /* Thinner scrollbar */ + -fx-background-insets: 0; + -fx-background-radius: 3px; + -fx-transition: opacity 0.3s ease; +} + +.scroll-pane:hover .scroll-bar { + -fx-opacity: 0.6; /* Show on hover */ +} + +.scroll-pane .thumb { + -fx-background-color: rgba(100, 100, 100, 0.5); /* Semi-transparent thumb */ + -fx-background-radius: 3px; +} diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml new file mode 100644 index 0000000..2d94145 --- /dev/null +++ b/src/main/resources/org/to/telegramfinalproject/Fxml/chat_item.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml new file mode 100644 index 0000000..06c0b0c --- /dev/null +++ b/src/main/resources/org/to/telegramfinalproject/Fxml/main.fxml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml index 41153a8..de39bf4 100644 --- a/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml +++ b/src/main/resources/org/to/telegramfinalproject/Fxml/sidebar_menu.fxml @@ -6,56 +6,71 @@ - + + - - - + + - - - - + - - - - - - - - -