Skip to content

Commit 4759e22

Browse files
committed
Added comments
1 parent 1dee24d commit 4759e22

2 files changed

Lines changed: 263 additions & 56 deletions

File tree

src/main/java/org/example/ItunesPlayList.java

Lines changed: 149 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,97 @@
1616
import java.util.List;
1717
import java.util.Map;
1818

19+
/**
20+
* Huvudklass för GUI:t. Hanterar visning av bibliotek, spellistor och sökning.
21+
*/
1922
public class ItunesPlayList {
2023

24+
// --- DATAMODELLER ---
25+
26+
// En Map som lagrar alla spellistor. Nyckeln är namnet (t.ex. "Musik") och värdet är listan med låtar.
2127
private Map<String, ObservableList<DisplaySong>> allPlaylists = new HashMap<>();
28+
29+
// Listan med namn på spellistor som visas i vänstermenyn (Sidebar).
30+
// "ObservableList" gör att GUI:t uppdateras automatiskt om vi lägger till/tar bort namn här.
2231
private ObservableList<String> playlistNames = FXCollections.observableArrayList();
32+
33+
// --- GUI KOMPONENTER ---
34+
35+
// Tabellen i mitten som visar låtarna
2336
private TableView<DisplaySong> songTable = new TableView<>();
37+
38+
// Listan till vänster där man väljer spellista
2439
private ListView<String> sourceList = new ListView<>();
25-
private Text lcdTitle = new Text("iTunes");
40+
41+
// Textfält för den "digitala displayen" högst upp
42+
private Text lcdTitle = new Text("myTunes");
2643
private Text lcdArtist = new Text("Välj bibliotek eller spellista");
2744

45+
/**
46+
* Bygger upp hela gränssnittet och visar fönstret.
47+
* @param dbSongs En lista med låtar hämtade från databasen/backend.
48+
*/
2849
public void showLibrary(List<org.example.entity.Song> dbSongs) {
2950
Stage stage = new Stage();
51+
52+
// Konvertera databas-objekten till vår interna DisplaySong-klass och skapa grundlistorna
3053
initData(dbSongs);
54+
55+
// BorderPane är huvudlayouten: Top, Left, Center, Bottom
3156
BorderPane root = new BorderPane();
3257

33-
// --- TOPPEN ---
34-
HBox topPanel = new HBox(15);
35-
topPanel.getStyleClass().add("top-panel");
58+
// ---------------------------------------------------------
59+
// 1. TOPPEN (Knappar, LCD-display, Sökfält)
60+
// ---------------------------------------------------------
61+
HBox topPanel = new HBox(15); // HBox lägger saker på rad horisontellt
62+
topPanel.getStyleClass().add("top-panel"); // CSS-klass för styling
3663
topPanel.setPadding(new Insets(10, 15, 10, 15));
3764
topPanel.setAlignment(Pos.CENTER_LEFT);
3865

66+
// Skapa LCD-displayen (den blå rutan med text)
3967
StackPane lcdDisplay = createLCDDisplay();
68+
// Säg åt displayen att växa och ta upp ledig plats i bredd
4069
HBox.setHgrow(lcdDisplay, Priority.ALWAYS);
4170

71+
// Sökfältet
4272
TextField searchField = new TextField();
4373
searchField.setPromptText("Sök...");
4474
searchField.getStyleClass().add("itunes-search");
75+
76+
// Lyssnare: När texten ändras i sökfältet, kör metoden filterSongs()
4577
searchField.textProperty().addListener((obs, old, newVal) -> filterSongs(newVal));
4678

79+
// Lägg till allt i toppen
4780
topPanel.getChildren().addAll(
4881
createRoundButton("⏮"), createRoundButton("▶"), createRoundButton("⏭"),
4982
lcdDisplay, searchField
5083
);
5184

52-
// --- VÄNSTER ---
53-
sourceList.setItems(playlistNames);
85+
// ---------------------------------------------------------
86+
// 2. VÄNSTER (Spellistorna)
87+
// ---------------------------------------------------------
88+
sourceList.setItems(playlistNames); // Koppla data till listan
5489
sourceList.getStyleClass().add("source-list");
5590
sourceList.setPrefWidth(200);
91+
92+
// Lyssnare: Vad händer när man klickar på en spellista i menyn?
5693
sourceList.getSelectionModel().selectedItemProperty().addListener((obs, old, newVal) -> {
5794
if (newVal != null) {
58-
searchField.clear();
95+
searchField.clear(); // Rensa gammal sökning
96+
// Hämta låtlistan från vår Map baserat på namnet och visa i tabellen
5997
songTable.setItems(allPlaylists.get(newVal));
6098
}
6199
});
62-
sourceList.getSelectionModel().selectFirst();
100+
sourceList.getSelectionModel().selectFirst(); // Välj första listan ("Musik") som startvärde
63101

64-
// --- MITTEN ---
65-
setupTable();
102+
// ---------------------------------------------------------
103+
// 3. MITTEN (Låttabellen)
104+
// ---------------------------------------------------------
105+
setupTable(); // Konfigurerar kolumner och beteende för tabellen
66106

67-
// --- BOTTEN ---
107+
// ---------------------------------------------------------
108+
// 4. BOTTEN (Knappar för att hantera listor)
109+
// ---------------------------------------------------------
68110
HBox bottomPanel = new HBox(10);
69111
bottomPanel.setPadding(new Insets(10));
70112
bottomPanel.getStyleClass().add("bottom-panel");
@@ -76,28 +118,38 @@ public void showLibrary(List<org.example.entity.Song> dbSongs) {
76118
Button btnMoveToPlaylist = new Button("Lägg till Låt i spellista");
77119
Button btnRemoveSong = new Button("Ta bort låt från lista");
78120

121+
// Koppla knapparna till metoder
79122
btnAddList.setOnAction(e -> createNewPlaylist());
80123
btnDeleteList.setOnAction(e -> deleteSelectedPlaylist());
81124
btnRemoveSong.setOnAction(e -> removeSelectedSong());
82-
btnMoveToPlaylist.setOnAction(e -> showMoveToMenu(btnMoveToPlaylist));
125+
btnMoveToPlaylist.setOnAction(e -> addSelectedSong(btnMoveToPlaylist));
83126

84127
bottomPanel.getChildren().addAll(btnAddList, btnDeleteList, new Separator(), btnMoveToPlaylist, btnRemoveSong);
85128

129+
// ---------------------------------------------------------
130+
// SLUTMONTERING
131+
// ---------------------------------------------------------
132+
133+
// SplitPane gör att användaren kan dra i gränsen mellan vänstermeny och tabell
86134
SplitPane splitPane = new SplitPane(sourceList, songTable);
87-
splitPane.setDividerPositions(0.25);
135+
splitPane.setDividerPositions(0.25); // Sätt startposition för avdelaren
88136

89137
root.setTop(topPanel);
90138
root.setCenter(splitPane);
91139
root.setBottom(bottomPanel);
92140

93141
Scene scene = new Scene(root, 950, 600);
142+
// Ladda CSS-filen (måste ligga i resources-mappen)
94143
scene.getStylesheets().add(getClass().getResource("/ipod_style.css").toExternalForm());
95144

96145
stage.setScene(scene);
97146
stage.setTitle("myTunes");
98147
stage.show();
99148
}
100149

150+
/**
151+
* Hjälpmetod för att skapa LCD-displayen (bakgrund + text).
152+
*/
101153
private StackPane createLCDDisplay() {
102154
StackPane stack = new StackPane();
103155
Rectangle bg = new Rectangle(350, 45);
@@ -113,25 +165,40 @@ private StackPane createLCDDisplay() {
113165
return stack;
114166
}
115167

168+
/**
169+
* Hjälpmetod för att skapa en standardiserad knapp.
170+
*/
116171
private Button createRoundButton(String icon) {
117172
Button b = new Button(icon);
118173
b.getStyleClass().add("itunes-button");
119174
return b;
120175
}
121176

177+
/**
178+
* Konfigurerar kolumnerna i tabellen och hur data ska visas.
179+
*/
122180
private void setupTable() {
181+
// Skapa kolumner
123182
TableColumn<DisplaySong, String> titleCol = new TableColumn<>("Namn");
183+
// Berätta för kolumnen vilket fält i DisplaySong den ska läsa från (name)
124184
titleCol.setCellValueFactory(d -> new SimpleStringProperty(d.getValue().name));
185+
125186
TableColumn<DisplaySong, String> artistCol = new TableColumn<>("Artist");
126187
artistCol.setCellValueFactory(d -> new SimpleStringProperty(d.getValue().artist));
188+
127189
TableColumn<DisplaySong, String> albumCol = new TableColumn<>("Album");
128190
albumCol.setCellValueFactory(d -> new SimpleStringProperty(d.getValue().album));
191+
129192
TableColumn<DisplaySong, String> timeCol = new TableColumn<>("Längd");
130193
timeCol.setCellValueFactory(d -> new SimpleStringProperty(d.getValue().time));
131194

132195
songTable.getColumns().setAll(titleCol, artistCol, albumCol, timeCol);
133196
songTable.getStyleClass().add("song-table");
197+
198+
// Gör så att kolumnerna fyller ut hela bredden
134199
songTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
200+
201+
// Lyssnare: När man klickar på en rad i tabellen -> Uppdatera LCD-displayen
135202
songTable.getSelectionModel().selectedItemProperty().addListener((obs, old, newVal) -> {
136203
if (newVal != null) {
137204
lcdTitle.setText(newVal.name);
@@ -140,46 +207,84 @@ private void setupTable() {
140207
});
141208
}
142209

210+
/**
211+
* Filtrerar låtarna i den aktiva listan baserat på söktexten.
212+
*/
143213
private void filterSongs(String searchText) {
144214
String currentList = sourceList.getSelectionModel().getSelectedItem();
145215
if (currentList == null) return;
216+
217+
// Hämta originaldatan för den valda spellistan
146218
ObservableList<DisplaySong> masterData = allPlaylists.get(currentList);
219+
220+
// Om sökfältet är tomt, visa allt
147221
if (searchText == null || searchText.isEmpty()) {
148222
songTable.setItems(masterData);
149223
return;
150224
}
225+
226+
// Skapa en filtrerad lista som omsluter masterData
151227
FilteredList<DisplaySong> filteredData = new FilteredList<>(masterData, song -> {
152228
String filter = searchText.toLowerCase();
153-
return song.name.toLowerCase().contains(filter) || song.artist.toLowerCase().contains(filter) || song.album.toLowerCase().contains(filter);
229+
// Returnera true om sökordet finns i namn, artist eller album
230+
return song.name.toLowerCase().contains(filter) ||
231+
song.artist.toLowerCase().contains(filter) ||
232+
song.album.toLowerCase().contains(filter);
154233
});
234+
155235
songTable.setItems(filteredData);
156236
}
157237

238+
/**
239+
* Omvandlar databas-objekten till GUI-objekt och skapar standardlistor.
240+
*/
158241
private void initData(List<org.example.entity.Song> dbSongs) {
159242
ObservableList<DisplaySong> library = FXCollections.observableArrayList();
243+
244+
// Loopa igenom datan från databasen
160245
if (dbSongs != null) {
161246
for (org.example.entity.Song s : dbSongs) {
247+
// Hantera null-värden snyggt (om artist eller album saknas)
162248
String art = (s.getAlbum() != null && s.getAlbum().getArtist() != null) ? s.getAlbum().getArtist().getName() : "Okänd";
163249
String alb = (s.getAlbum() != null) ? s.getAlbum().getName() : "Okänt";
250+
251+
// Skapa ett nytt DisplaySong-objekt
164252
library.add(new DisplaySong(s.getTitle(), art, alb, s.getLength()));
165253
}
166254
}
255+
256+
// Lägg in huvudbiblioteket "Musik"
167257
allPlaylists.put("Musik", library);
168258
playlistNames.add("Musik");
259+
260+
// Skapa en tom lista för "Favoriter"
169261
allPlaylists.put("Favoriter", FXCollections.observableArrayList());
170262
playlistNames.add("Favoriter");
171263
}
172264

265+
/**
266+
* Visar en dialogruta för att skapa en ny spellista.
267+
*/
173268
private void createNewPlaylist() {
174269
TextInputDialog d = new TextInputDialog("Ny lista");
270+
271+
// Här ändrar du fönstrets titel och text
272+
d.setTitle("Skapa ny spellista"); // Ersätter "Bekräftelse"
273+
d.setHeaderText("Ange namn på din nya lista"); // Rubriken inuti rutan
274+
d.setContentText("Namn:"); // Texten bredvid inmatningsfältet
275+
175276
d.showAndWait().ifPresent(name -> {
277+
// Kontrollera att namnet inte är tomt och inte redan finns
176278
if (!name.trim().isEmpty() && !allPlaylists.containsKey(name)) {
177279
allPlaylists.put(name, FXCollections.observableArrayList());
178280
playlistNames.add(name);
179281
}
180282
});
181283
}
182284

285+
/**
286+
* Tar bort vald spellista (men tillåter inte att man tar bort "Musik").
287+
*/
183288
private void deleteSelectedPlaylist() {
184289
String sel = sourceList.getSelectionModel().getSelectedItem();
185290
if (sel != null && !sel.equals("Musik")) {
@@ -188,29 +293,53 @@ private void deleteSelectedPlaylist() {
188293
}
189294
}
190295

296+
/**
297+
* Tar bort vald låt från den aktiva spellistan (ej från huvudbiblioteket "Musik").
298+
*/
191299
private void removeSelectedSong() {
192300
DisplaySong sel = songTable.getSelectionModel().getSelectedItem();
193301
String list = sourceList.getSelectionModel().getSelectedItem();
194-
if (sel != null && list != null && !list.equals("Musik")) allPlaylists.get(list).remove(sel);
302+
// Skydd: Man får inte ta bort låtar direkt från "Musik"-biblioteket i denna vy
303+
if (sel != null && list != null && !list.equals("Musik")) {
304+
allPlaylists.get(list).remove(sel);
305+
}
195306
}
196307

197-
private void showMoveToMenu(Button anchor) {
308+
/**
309+
* Visar en popup-meny för att lägga till vald låt i en annan spellista.
310+
*/
311+
private void addSelectedSong(Button anchor) {
198312
DisplaySong sel = songTable.getSelectionModel().getSelectedItem();
199-
if (sel == null) return;
313+
if (sel == null) return; // Ingen låt vald
314+
200315
ContextMenu menu = new ContextMenu();
201316
for (String n : playlistNames) {
202-
if (n.equals("Musik")) continue;
317+
if (n.equals("Musik")) continue; // Man kan inte lägga till i "Musik" (det är källan)
318+
203319
MenuItem itm = new MenuItem(n);
204-
itm.setOnAction(e -> { if (!allPlaylists.get(n).contains(sel)) allPlaylists.get(n).add(sel); });
320+
itm.setOnAction(e -> {
321+
// Om låten inte redan finns i listan, lägg till den
322+
if (!allPlaylists.get(n).contains(sel)) {
323+
allPlaylists.get(n).add(sel);
324+
}
325+
});
205326
menu.getItems().add(itm);
206327
}
328+
// Visa menyn vid knappen
207329
menu.show(anchor, anchor.getScene().getWindow().getX() + anchor.getLayoutX(), anchor.getScene().getWindow().getY() + anchor.getLayoutY());
208330
}
209331

332+
/**
333+
* En inre klass (DTO - Data Transfer Object) enbart för visning i tabellen.
334+
* Detta skiljer GUI-logiken från databas-entiteterna.
335+
*/
210336
public static class DisplaySong {
211337
String name, artist, album, time;
212338
public DisplaySong(String n, String a, String al, Long t) {
213-
this.name = n; this.artist = a; this.album = al; this.time = String.valueOf(t);
339+
this.name = n;
340+
this.artist = a;
341+
this.album = al;
342+
this.time = String.valueOf(t);
214343
}
215344
}
216345
}

0 commit comments

Comments
 (0)