99import javafx .scene .Scene ;
1010import javafx .scene .control .*;
1111import javafx .scene .layout .*;
12- import javafx .scene .paint .Color ;
1312import javafx .scene .shape .Rectangle ;
14- import javafx .scene .text .Font ;
15- import javafx .scene .text .FontWeight ;
1613import javafx .scene .text .Text ;
1714import javafx .stage .Stage ;
18-
1915import java .util .HashMap ;
2016import java .util .List ;
2117import java .util .Map ;
@@ -24,7 +20,6 @@ public class ItunesPlayList {
2420
2521 private Map <String , ObservableList <DisplaySong >> allPlaylists = new HashMap <>();
2622 private ObservableList <String > playlistNames = FXCollections .observableArrayList ();
27-
2823 private TableView <DisplaySong > songTable = new TableView <>();
2924 private ListView <String > sourceList = new ListView <>();
3025 private Text lcdTitle = new Text ("iTunes" );
@@ -33,61 +28,51 @@ public class ItunesPlayList {
3328 public void showLibrary (List <org .example .entity .Song > dbSongs ) {
3429 Stage stage = new Stage ();
3530 initData (dbSongs );
36-
3731 BorderPane root = new BorderPane ();
3832
39- // --- TOPPEN (LCD, Kontroller & Sök) ---
33+ // --- TOPPEN ---
4034 HBox topPanel = new HBox (15 );
35+ topPanel .getStyleClass ().add ("top-panel" );
4136 topPanel .setPadding (new Insets (10 , 15 , 10 , 15 ));
4237 topPanel .setAlignment (Pos .CENTER_LEFT );
43- topPanel .setStyle ("-fx-background-color: linear-gradient(to bottom, #dcdcdc, #bebebe); -fx-border-color: #999; -fx-border-width: 0 0 1 0;" );
4438
45- // Skapa LCD
4639 StackPane lcdDisplay = createLCDDisplay ();
4740 HBox .setHgrow (lcdDisplay , Priority .ALWAYS );
4841
49- // Skapa Sökfält
5042 TextField searchField = new TextField ();
5143 searchField .setPromptText ("Sök..." );
52- searchField .setPrefWidth (200 );
53- // iTunes-look med runda hörn
54- searchField .setStyle ("-fx-background-radius: 15; -fx-border-radius: 15; -fx-border-color: #aaa; -fx-background-color: white;" );
55-
56- // Koppla Söklogik
57- searchField .textProperty ().addListener ((observable , oldValue , newValue ) -> {
58- filterSongs (newValue );
59- });
44+ searchField .getStyleClass ().add ("itunes-search" );
45+ searchField .textProperty ().addListener ((obs , old , newVal ) -> filterSongs (newVal ));
6046
6147 topPanel .getChildren ().addAll (
62- createRoundButton ("⏮" ),
63- createRoundButton ("▶" ),
64- createRoundButton ("⏭" ),
65- lcdDisplay ,
66- searchField
48+ createRoundButton ("⏮" ), createRoundButton ("▶" ), createRoundButton ("⏭" ),
49+ lcdDisplay , searchField
6750 );
6851
69- // --- VÄNSTER (Källor) ---
52+ // --- VÄNSTER ---
7053 sourceList .setItems (playlistNames );
54+ sourceList .getStyleClass ().add ("source-list" );
7155 sourceList .setPrefWidth (200 );
72- sourceList .setStyle ("-fx-background-color: #ebf1f7; -fx-control-inner-background: #ebf1f7; -fx-font-family:'Lucida Console'" );
73- sourceList .getSelectionModel ().selectedItemProperty ().addListener ((obs , oldVal , newVal ) -> {
56+ sourceList .getSelectionModel ().selectedItemProperty ().addListener ((obs , old , newVal ) -> {
7457 if (newVal != null ) {
75- searchField .clear (); // Rensa sökning vid byte av lista
58+ searchField .clear ();
7659 songTable .setItems (allPlaylists .get (newVal ));
7760 }
7861 });
7962 sourceList .getSelectionModel ().selectFirst ();
8063
81- // --- MITTEN (Låtlista) ---
64+ // --- MITTEN ---
8265 setupTable ();
8366
84- // --- BOTTEN (Knappar) ---
67+ // --- BOTTEN ---
8568 HBox bottomPanel = new HBox (10 );
8669 bottomPanel .setPadding (new Insets (10 ));
87- bottomPanel .setStyle ( "-fx-background-color: #dcdcdc; -fx-border-color: #999; -fx-border-width: 1 0 0 0; " );
70+ bottomPanel .getStyleClass (). add ( "bottom-panel " );
8871
8972 Button btnAddList = new Button ("+" );
73+ btnAddList .getStyleClass ().add ("list-control-button" );
9074 Button btnDeleteList = new Button ("-" );
75+ btnDeleteList .getStyleClass ().add ("list-control-button" );
9176 Button btnMoveToPlaylist = new Button ("Lägg till Låt i spellista" );
9277 Button btnRemoveSong = new Button ("Ta bort låt från lista" );
9378
@@ -105,159 +90,127 @@ public void showLibrary(List<org.example.entity.Song> dbSongs) {
10590 root .setCenter (splitPane );
10691 root .setBottom (bottomPanel );
10792
108- stage .setScene (new Scene (root , 950 , 600 ));
109- stage .setTitle ("iTunes" );
93+ Scene scene = new Scene (root , 950 , 600 );
94+ scene .getStylesheets ().add (getClass ().getResource ("/ipod_style.css" ).toExternalForm ());
95+
96+ stage .setScene (scene );
97+ stage .setTitle ("myTunes" );
11098 stage .show ();
11199 }
112100
113- private void filterSongs (String searchText ) {
114- String currentList = sourceList .getSelectionModel ().getSelectedItem ();
115- if (currentList == null ) return ;
116-
117- ObservableList <DisplaySong > masterData = allPlaylists .get (currentList );
118- if (searchText == null || searchText .isEmpty ()) {
119- songTable .setItems (masterData );
120- return ;
121- }
101+ private StackPane createLCDDisplay () {
102+ StackPane stack = new StackPane ();
103+ Rectangle bg = new Rectangle (350 , 45 );
104+ bg .getStyleClass ().add ("lcd-background" );
122105
123- FilteredList <DisplaySong > filteredData = new FilteredList <>(masterData , song -> {
124- String filter = searchText .toLowerCase ();
125- return song .name .toLowerCase ().contains (filter ) ||
126- song .artist .toLowerCase ().contains (filter ) ||
127- song .album .toLowerCase ().contains (filter );
128- });
106+ VBox textStack = new VBox (2 );
107+ textStack .setAlignment (Pos .CENTER );
108+ lcdTitle .getStyleClass ().add ("lcd-title" );
109+ lcdArtist .getStyleClass ().add ("lcd-artist" );
129110
130- songTable .setItems (filteredData );
111+ textStack .getChildren ().addAll (lcdTitle , lcdArtist );
112+ stack .getChildren ().addAll (bg , textStack );
113+ return stack ;
131114 }
132115
133- private void initData (List <org .example .entity .Song > dbSongs ) {
134- ObservableList <DisplaySong > library = FXCollections .observableArrayList ();
135-
136- if (dbSongs != null ) {
137- for (org .example .entity .Song s : dbSongs ) {
138- String artistName = "Okänd Artist" ;
139- String albumName = "Okänt Album" ;
140-
141- if (s .getAlbum () != null ) {
142- albumName = s .getAlbum ().getName ();
143- // Gå via albumet för att hitta artisten
144- if (s .getAlbum ().getArtist () != null ) {
145- artistName = s .getAlbum ().getArtist ().getName ();
146- }
147- }
148- library .add (new DisplaySong (s .getTitle (), artistName , albumName , s .getLength ()));
149- }
150- }
151-
152- allPlaylists .put ("Musik" , library );
153- playlistNames .add ("Musik" );
154- allPlaylists .put ("Favoriter" , FXCollections .observableArrayList ());
155- playlistNames .add ("Favoriter" );
116+ private Button createRoundButton (String icon ) {
117+ Button b = new Button (icon );
118+ b .getStyleClass ().add ("itunes-button" );
119+ return b ;
156120 }
157121
158122 private void setupTable () {
159123 TableColumn <DisplaySong , String > titleCol = new TableColumn <>("Namn" );
160124 titleCol .setCellValueFactory (d -> new SimpleStringProperty (d .getValue ().name ));
161-
162125 TableColumn <DisplaySong , String > artistCol = new TableColumn <>("Artist" );
163126 artistCol .setCellValueFactory (d -> new SimpleStringProperty (d .getValue ().artist ));
164-
165127 TableColumn <DisplaySong , String > albumCol = new TableColumn <>("Album" );
166128 albumCol .setCellValueFactory (d -> new SimpleStringProperty (d .getValue ().album ));
167-
168129 TableColumn <DisplaySong , String > timeCol = new TableColumn <>("Längd" );
169130 timeCol .setCellValueFactory (d -> new SimpleStringProperty (d .getValue ().time ));
170131
171- songTable .getColumns ().clear ( );
172- songTable .getColumns ().addAll ( titleCol , artistCol , albumCol , timeCol );
132+ songTable .getColumns ().setAll ( titleCol , artistCol , albumCol , timeCol );
133+ songTable .getStyleClass ().add ( "song-table" );
173134 songTable .setColumnResizePolicy (TableView .CONSTRAINED_RESIZE_POLICY );
174-
175- songTable .setStyle ("-fx-font-family: 'Lucida Console'" );
176-
177- songTable .getSelectionModel ().selectedItemProperty ().addListener ((obs , oldVal , newVal ) -> {
135+ songTable .getSelectionModel ().selectedItemProperty ().addListener ((obs , old , newVal ) -> {
178136 if (newVal != null ) {
179137 lcdTitle .setText (newVal .name );
180138 lcdArtist .setText (newVal .artist );
181139 }
182140 });
183141 }
184142
185- private StackPane createLCDDisplay () {
186- StackPane stack = new StackPane ();
187- Rectangle bg = new Rectangle (350 , 45 , Color .WHITE );
188- bg .setArcWidth (10 ); bg .setArcHeight (10 );
189- bg .setStroke (Color .GRAY );
190- VBox textStack = new VBox (2 );
191- textStack .setAlignment (Pos .CENTER );
192- lcdTitle .setFont (Font .font ("Lucida Console" , FontWeight .BOLD , 12 ));
193- lcdArtist .setFill (Color .DARKSLATEGRAY );
194- textStack .getChildren ().addAll (lcdTitle , lcdArtist );
195- stack .getChildren ().addAll (bg , textStack );
196- return stack ;
143+ private void filterSongs (String searchText ) {
144+ String currentList = sourceList .getSelectionModel ().getSelectedItem ();
145+ if (currentList == null ) return ;
146+ ObservableList <DisplaySong > masterData = allPlaylists .get (currentList );
147+ if (searchText == null || searchText .isEmpty ()) {
148+ songTable .setItems (masterData );
149+ return ;
150+ }
151+ FilteredList <DisplaySong > filteredData = new FilteredList <>(masterData , song -> {
152+ String filter = searchText .toLowerCase ();
153+ return song .name .toLowerCase ().contains (filter ) || song .artist .toLowerCase ().contains (filter ) || song .album .toLowerCase ().contains (filter );
154+ });
155+ songTable .setItems (filteredData );
197156 }
198157
199- private Button createRoundButton (String icon ) {
200- Button b = new Button (icon );
201- b .setStyle ("-fx-background-radius: 50; -fx-min-width: 35; -fx-min-height: 35;" );
202- return b ;
158+ private void initData (List <org .example .entity .Song > dbSongs ) {
159+ ObservableList <DisplaySong > library = FXCollections .observableArrayList ();
160+ if (dbSongs != null ) {
161+ for (org .example .entity .Song s : dbSongs ) {
162+ String art = (s .getAlbum () != null && s .getAlbum ().getArtist () != null ) ? s .getAlbum ().getArtist ().getName () : "Okänd" ;
163+ String alb = (s .getAlbum () != null ) ? s .getAlbum ().getName () : "Okänt" ;
164+ library .add (new DisplaySong (s .getTitle (), art , alb , s .getLength ()));
165+ }
166+ }
167+ allPlaylists .put ("Musik" , library );
168+ playlistNames .add ("Musik" );
169+ allPlaylists .put ("Favoriter" , FXCollections .observableArrayList ());
170+ playlistNames .add ("Favoriter" );
203171 }
204172
205173 private void createNewPlaylist () {
206- TextInputDialog dialog = new TextInputDialog ("Ny lista" );
207- dialog .setTitle ("Skapa spellista" );
208- dialog .setHeaderText ("Ange namn på spellistan" );
209- dialog .showAndWait ().ifPresent (name -> {
174+ TextInputDialog d = new TextInputDialog ("Ny lista" );
175+ d .showAndWait ().ifPresent (name -> {
210176 if (!name .trim ().isEmpty () && !allPlaylists .containsKey (name )) {
211177 allPlaylists .put (name , FXCollections .observableArrayList ());
212178 playlistNames .add (name );
213- sourceList .getSelectionModel ().select (name );
214179 }
215180 });
216181 }
217182
218183 private void deleteSelectedPlaylist () {
219- String selectedName = sourceList .getSelectionModel ().getSelectedItem ();
220- if (selectedName == null || selectedName .equals ("Musik" )) return ;
221-
222- allPlaylists .remove (selectedName );
223- playlistNames .remove (selectedName );
224- sourceList .getSelectionModel ().select ("Musik" );
184+ String sel = sourceList .getSelectionModel ().getSelectedItem ();
185+ if (sel != null && !sel .equals ("Musik" )) {
186+ allPlaylists .remove (sel );
187+ playlistNames .remove (sel );
188+ }
225189 }
226190
227191 private void removeSelectedSong () {
228- DisplaySong selected = songTable .getSelectionModel ().getSelectedItem ();
229- String currentList = sourceList .getSelectionModel ().getSelectedItem ();
230- if (selected != null && currentList != null && !currentList .equals ("Musik" )) {
231- allPlaylists .get (currentList ).remove (selected );
232- }
192+ DisplaySong sel = songTable .getSelectionModel ().getSelectedItem ();
193+ String list = sourceList .getSelectionModel ().getSelectedItem ();
194+ if (sel != null && list != null && !list .equals ("Musik" )) allPlaylists .get (list ).remove (sel );
233195 }
234196
235197 private void showMoveToMenu (Button anchor ) {
236- DisplaySong selectedSong = songTable .getSelectionModel ().getSelectedItem ();
237- if (selectedSong == null ) return ;
238-
239- ContextMenu moveMenu = new ContextMenu ();
240- for (String name : playlistNames ) {
241- if (name .equals ("Musik" )) continue ;
242- MenuItem item = new MenuItem (name );
243- item .setOnAction (e -> {
244- if (!allPlaylists .get (name ).contains (selectedSong )) {
245- allPlaylists .get (name ).add (selectedSong );
246- }
247- });
248- moveMenu .getItems ().add (item );
198+ DisplaySong sel = songTable .getSelectionModel ().getSelectedItem ();
199+ if (sel == null ) return ;
200+ ContextMenu menu = new ContextMenu ();
201+ for (String n : playlistNames ) {
202+ if (n .equals ("Musik" )) continue ;
203+ MenuItem itm = new MenuItem (n );
204+ itm .setOnAction (e -> { if (!allPlaylists .get (n ).contains (sel )) allPlaylists .get (n ).add (sel ); });
205+ menu .getItems ().add (itm );
249206 }
250- moveMenu .show (anchor , anchor .getScene ().getWindow ().getX () + anchor .getLayoutX (),
251- anchor .getScene ().getWindow ().getY () + anchor .getLayoutY ());
207+ menu .show (anchor , anchor .getScene ().getWindow ().getX () + anchor .getLayoutX (), anchor .getScene ().getWindow ().getY () + anchor .getLayoutY ());
252208 }
253209
254210 public static class DisplaySong {
255211 String name , artist , album , time ;
256212 public DisplaySong (String n , String a , String al , Long t ) {
257- this .name = n ;
258- this .artist = a ;
259- this .album = al ;
260- this .time = String .valueOf (t );
213+ this .name = n ; this .artist = a ; this .album = al ; this .time = String .valueOf (t );
261214 }
262215 }
263216}
0 commit comments