Rename year directories to allow natural ordering
38
year3/semester1/CT326: Programming III/assignments/assignment4/assignment4/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
year3/semester1/CT326: Programming III/assignments/assignment4/assignment4/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
7
year3/semester1/CT326: Programming III/assignments/assignment4/assignment4/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
14
year3/semester1/CT326: Programming III/assignments/assignment4/assignment4/.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
After Width: | Height: | Size: 431 KiB |
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>assignment4</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 280 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 150 KiB |
@ -0,0 +1,13 @@
|
||||
1., "Personal Holloway", 3:23
|
||||
2., "Greedy Fly", 4:30
|
||||
3., "Swallowed", 4:51
|
||||
4., "Insect Kin", 4:27
|
||||
5., "Cold Contagious", 6:00
|
||||
6., "A Tendency to Start Fires", 4:04
|
||||
7., "Mouth", 5:45
|
||||
8., "Straight No Chaser", 4:02
|
||||
9., "History", 4:17
|
||||
10., "Synapse", 4:52
|
||||
11., "Communicator", 4:25
|
||||
12., "Bonedriven", 4:32
|
||||
13., "Distant Voices", 6:39
|
@ -0,0 +1,11 @@
|
||||
1., "Negative Vibes", 4:44
|
||||
2., "Ghosts of Overdoses", 4:41
|
||||
3., "It's All Good", 4:21
|
||||
4., "Factories", 5:17
|
||||
5., "Jar Song", 5:03
|
||||
6., "Celtic Tiger", 5:13
|
||||
7., "Apple of My Eye", 3:43
|
||||
8., "Industrial School", 5:27
|
||||
9., "Great Gaels of Ireland", 5:21
|
||||
10., "Marching Season Siege", 3:24
|
||||
11., "Seize the Day" (hidden track), 4:12
|
@ -0,0 +1,11 @@
|
||||
1., "Babooshka", 3:20
|
||||
2., "Delius (Song of Summer)", 2:51
|
||||
3., "Blow Away (For Bill)", 3:33
|
||||
4., "All We Ever Look For", 3:47
|
||||
5., "Egypt", 4:10
|
||||
6., "The Wedding List", 4:15
|
||||
7., "Violin", 3:15
|
||||
8., "The Infant Kiss", 2:50
|
||||
9., "Night Scented Stock", 0:51
|
||||
10., "Army Dreamers", 2:55
|
||||
11., "Breathing", 5:29
|
@ -0,0 +1,10 @@
|
||||
1, Nasty, 4:40
|
||||
2, O.D., 3:22
|
||||
3, Death Note, 3:40
|
||||
4, Bad, 3:55
|
||||
5, Drown, 3:54
|
||||
6, Saucy, 3:04
|
||||
7, Yas, 3:22
|
||||
8, So Strange, 4:00
|
||||
9, Rich Kids, 3:21
|
||||
10, G.O.A.T., 3:35
|
@ -0,0 +1,11 @@
|
||||
1., "Here Comes the Sun", 3:05
|
||||
2., "Because", 2:45
|
||||
3., "You Never Give Me Your Money", 4:03
|
||||
4., "Sun King", 2:26
|
||||
5., "Mean Mr. Mustard", 1:06
|
||||
6., "Polythene Pam", 1:13
|
||||
7., "She Came In Through the Bathroom Window", 1:58
|
||||
8., "Golden Slumbers", 1:31
|
||||
9., "Carry That Weight", 1:36
|
||||
10., "The End", 2:05
|
||||
11., "Her Majesty", 0:23
|
@ -0,0 +1,5 @@
|
||||
Bush, Razorblade Suitcase, covers/Razorblade_suitcase.jpg, library/bush_razorblade_suitcase.txt
|
||||
Kate Bush, Never for Ever, covers/Katebushneverforever.png, library/kate_bush_never_for_ever.txt
|
||||
Damien Dempsey, Seize the Day, covers/Damien_Dempsey_-_Seize_the_Day.jpg, library/damien_dempsey_seize_the_day.txt
|
||||
Beatles, Abbey Road, covers/Beatles_-_Abbey_Road.jpg, library/the_beatles_abbey_road.txt
|
||||
Polyphia, New Levels New Devils, covers/polyphia_new_levels_new_devils.jpeg, library/new_levels_new_devils.txt
|
@ -0,0 +1,120 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* class to represent an Album object and its tracks
|
||||
*/
|
||||
public class Album {
|
||||
private String artist; // the name of the artist
|
||||
private String title; // the title of the album
|
||||
private String pathToCover; // the path to the cover image of the album
|
||||
private String pathToTrackList; // the path to the track list text file for the album
|
||||
private ArrayList<Track> tracks = new ArrayList<>(); // arraylist of all the tracks on the album
|
||||
|
||||
/**
|
||||
* constructor for Album objects
|
||||
* @param artist String of the artist's name
|
||||
* @param title String of the title of the album
|
||||
* @param pathToCover String of the filepath to the cover image
|
||||
* @param pathToTrackList String of the filepath to the list of tracks on the album
|
||||
*/
|
||||
public Album(String artist, String title, String pathToCover, String pathToTrackList) throws IOException {
|
||||
this.artist = artist;
|
||||
this.title = title;
|
||||
this.pathToCover = pathToCover;
|
||||
this.pathToTrackList = pathToTrackList;
|
||||
|
||||
// reading the trackList file and adding a Track object to the ArrayList for each line in the file
|
||||
BufferedReader reader = new BufferedReader(new FileReader(pathToTrackList)); // not catching FileNotFoundException as entire method should fail if the trackList file is not accessible
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] columns = line.split(",");
|
||||
tracks.add(new Track(columns[0].strip(), columns[1].strip(), columns[2].strip())); // trimming whitespace from the ends of each column read in
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for the artist's name
|
||||
* @return String artist
|
||||
*/
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for the artist's name
|
||||
* @param artist String of the artist's name
|
||||
*/
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for the title
|
||||
* @return String title of the album
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for the title
|
||||
* @param title String title of the album
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for pathToCover
|
||||
* @return String path to the cover image
|
||||
*/
|
||||
public String getPathToCover() {
|
||||
return pathToCover;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for pathToCover
|
||||
* @param pathToCover String of the filepath to the cover image
|
||||
*/
|
||||
public void setPathToCover(String pathToCover) {
|
||||
this.pathToCover = pathToCover;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for trackList
|
||||
* @return String of the filepath to the trackList
|
||||
*/
|
||||
public String getPathToTrackList() {
|
||||
return pathToTrackList;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for trackList
|
||||
* @param pathToTrackList String of the filepath to the trackLists
|
||||
*/
|
||||
public void setPathToTrackList(String pathToTrackList) {
|
||||
this.pathToTrackList = pathToTrackList;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for tracks
|
||||
* @return Array of Track objects
|
||||
*/
|
||||
public ArrayList<Track> getTracks() {
|
||||
return tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for tracks
|
||||
* @param tracks array of Track objects
|
||||
*/
|
||||
public void setTracks(ArrayList<Track> tracks) {
|
||||
this.tracks = tracks;
|
||||
}
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Application class for the Music Library application
|
||||
*/
|
||||
public class MusicLibrary extends JFrame {
|
||||
private String libraryDirectory = "resources/"; // directory that the library files are in
|
||||
private String libraryFileName = "music_library.txt"; // name of the music libary file
|
||||
private ArrayList<Album> albums = new ArrayList<>();
|
||||
private ActionListener actionListener; // action listener for the buttons in this application
|
||||
|
||||
/**
|
||||
* constructor for the Music Library application
|
||||
*/
|
||||
public MusicLibrary() {
|
||||
super("Music Library"); // set window title
|
||||
|
||||
// make JFrame fill the screen
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
setSize(screenSize.width, screenSize.height);
|
||||
|
||||
// using border layout to position JPanels easily
|
||||
Container container = getContentPane();
|
||||
container.setLayout(new BorderLayout());
|
||||
|
||||
// panel to show the list of albums
|
||||
JPanel albumPanel = new JPanel();
|
||||
|
||||
// action listener to handle what happens when buttons are clicked
|
||||
actionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
// if the actionCommand was to show the albumPanel (i.e., "back" button was pressed on the trackPanel)
|
||||
if (event.getActionCommand().equals("showAlbumPanel")) {
|
||||
// removing everything from the container
|
||||
container.removeAll();
|
||||
|
||||
// cleaning screen
|
||||
container.revalidate();
|
||||
container.repaint();
|
||||
|
||||
// adding albumPanel to container
|
||||
container.add(albumPanel, BorderLayout.CENTER);
|
||||
}
|
||||
// else if the actionCommand was anything other than showAlbumPanel, i.e. it was an album being clicked, hide it and display the tracklist of the selected album
|
||||
else {
|
||||
// hiding the albumPanel
|
||||
container.remove(albumPanel);
|
||||
|
||||
// cleaning screen
|
||||
container.revalidate();
|
||||
container.repaint();
|
||||
|
||||
// displaying album contents (trackPanel)
|
||||
container.add(generateTrackPanel(albums.get(Integer.parseInt(event.getActionCommand()))), BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// loading the albums into the arraylist
|
||||
try {
|
||||
albums = loadAlbums(libraryDirectory + libraryFileName);
|
||||
}
|
||||
// display error message if the music library file could not be read successfully
|
||||
catch (IOException e) {
|
||||
albumPanel.add(new JLabel("The music library file could not be read successfully!!!"));
|
||||
}
|
||||
|
||||
// iterating over each album and adding it to the GUI interface as a button
|
||||
for (int i = 0; i < albums.size(); i++) { // using iteration instead of for-each so that we can set the actionCommand of the button to the value of i
|
||||
Album album = albums.get(i);
|
||||
|
||||
// attempting to create a button with the album cover as the icon
|
||||
try {
|
||||
// reading in image, scaling it, turning it into an icond, and adding it to the album button
|
||||
Image coverImage = ImageIO.read(new File(libraryDirectory + album.getPathToCover())).getScaledInstance(200, 200, Image.SCALE_SMOOTH);
|
||||
ImageIcon icon = new ImageIcon(coverImage);
|
||||
JButton button = new JButton(album.getTitle(), icon); // including album title in button to make it easier to use
|
||||
// JButton button = new JButton(icon); // would give same appearancec as in assignment spec
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.setActionCommand(String.valueOf(i));
|
||||
button.addActionListener(actionListener);
|
||||
|
||||
albumPanel.add(button);
|
||||
}
|
||||
// if the album cover cannot be found, just put a text button in its place
|
||||
catch (IOException e) {
|
||||
JButton button = new JButton(album.getTitle());
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.setActionCommand(String.valueOf(i));
|
||||
button.addActionListener(actionListener);
|
||||
|
||||
albumPanel.add(button);
|
||||
}
|
||||
}
|
||||
|
||||
// display the album panel
|
||||
container.add(albumPanel, BorderLayout.CENTER);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to load all the Albums into memory as an ArrayList of Albums
|
||||
* @param libraryPath String representing the file path to the music_library.txt file
|
||||
* @throws IOException if reading the albums in from the library file and/or instantiating them fails
|
||||
*/
|
||||
public ArrayList<Album> loadAlbums(String libraryPath) throws IOException {
|
||||
// it's not really necessary that libraryPath be passed to this method from a design perspective, as they are both members of the MusicLibrary object class
|
||||
// however, this makes the method more re-usable if we ever want to load albums from outside of this class
|
||||
|
||||
ArrayList<Album> albums = new ArrayList<>(); // ArrayList of Album objects to be returned
|
||||
|
||||
// instantiating an Album object for each line in the library file
|
||||
BufferedReader reader = new BufferedReader(new FileReader(libraryPath)); // not catching FileNotFoundException as entire method should fail if the library file is not accessible
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] columns = line.split(",");
|
||||
|
||||
// creating the album object and adding it to the ArrayList
|
||||
albums.add(new Album(columns[0].trim(), columns[1].trim(), columns[2].trim(), libraryDirectory + columns[3].trim())); // trimming whitespace from the ends of each column read in
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
/**
|
||||
* method to generate a JPanel containing a JTable of all the tracks for a given Album
|
||||
* @param album the Album for which we are generating a JTable of tracks
|
||||
* @return a JPanel containing a JTable of all the tracks for a given Album
|
||||
*/
|
||||
public JPanel generateTrackPanel(Album album) {
|
||||
JPanel trackPanel = new JPanel(new BorderLayout()); // using border layout so the table can be easily aligned above the "back" button
|
||||
|
||||
ArrayList<Track> tracks = album.getTracks();
|
||||
|
||||
// columns to be displayed in JTable
|
||||
String[][] data = new String[tracks.size()][3];
|
||||
|
||||
// filling up columns to be displayed in JTable
|
||||
for (int i = 0; i < tracks.size(); i++) {
|
||||
// track number, track title, and track duration
|
||||
data[i] = new String[]{tracks.get(i).getTrackNumber(), tracks.get(i).getTitle(), tracks.get(i).getDuration()};
|
||||
}
|
||||
|
||||
// adding the JTable of tracks to the center of the panel
|
||||
String[] columnNames = {"No.", "Track Title", "Length"};
|
||||
JTable table = new JTable(data, columnNames);
|
||||
table.setEnabled(false); // disable user interaction with the table so they can't edit it
|
||||
trackPanel.add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
|
||||
JButton button = new JButton("Back");
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.addActionListener(actionListener);
|
||||
button.setActionCommand("showAlbumPanel");
|
||||
|
||||
// adding the back button to the bottom of the panel, underneath the table
|
||||
trackPanel.add(button, BorderLayout.SOUTH);
|
||||
|
||||
return trackPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* main method
|
||||
* @param args (none)
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
MusicLibrary application = new MusicLibrary();
|
||||
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
/**
|
||||
* class to represent a Track on an Album
|
||||
* not really necessary for this assignmenet, could've just stored tracks as Strings or something, but i feel that this is a more "correct" OOP-like approach
|
||||
*/
|
||||
public class Track {
|
||||
private String trackNumber; // storing as String as we never manipulate it arithmetically, and allows non-integer numberings such as A1 and B1 for A-sides and B-sides
|
||||
private String title; // title of track
|
||||
private String duration; // duration can also be stored as String as we never manipulate it. if manipulation was being done, java.time.Duration would be a better choice
|
||||
|
||||
/**
|
||||
* constructor for Track objects
|
||||
* @param trackNumber the number of the track as a String
|
||||
* @param title the name of the track/song
|
||||
* @param duration the length of the song as a String
|
||||
*/
|
||||
public Track(String trackNumber, String title, String duration) {
|
||||
this.trackNumber = trackNumber;
|
||||
this.title = title;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the number of the track
|
||||
* @return the number of the track as a String
|
||||
*/
|
||||
public String getTrackNumber() {
|
||||
return trackNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the number of the track
|
||||
* @param trackNumber a String representing the number of the track
|
||||
*/
|
||||
public void setTrackNumber(String trackNumber) {
|
||||
this.trackNumber = trackNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the title of the track
|
||||
* @return the name of the track, as a String
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the title of the track
|
||||
* @param title a String object representing the name of the track
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the duration of the track
|
||||
* @return the duration of the track, as a String object
|
||||
*/
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the duration of the track
|
||||
* @param duration a String object representing the duration of the track
|
||||
*/
|
||||
public void setDuration(String duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 17 KiB |