hw3: prototype completed
This commit is contained in:
parent
81abdd064d
commit
31302dd0d5
2
hw3/.idea/misc.xml
generated
2
hw3/.idea/misc.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="23" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
@ -1,10 +0,0 @@
|
||||
import java.util.Date;
|
||||
|
||||
public class Photo {
|
||||
private String name;
|
||||
private String filePath;
|
||||
private Date dateAdded;
|
||||
private long fileSize;
|
||||
|
||||
// Constructor, getters, and setters
|
||||
}
|
18
hw3/src/PhotoAlbumApp.java
Normal file
18
hw3/src/PhotoAlbumApp.java
Normal file
@ -0,0 +1,18 @@
|
||||
import controller.PhotoAlbumController;
|
||||
import model.PhotoAlbumModel;
|
||||
import view.PhotoAlbumView;
|
||||
|
||||
public class PhotoAlbumApp {
|
||||
public static void main(String[] args) {
|
||||
// Create MVC components
|
||||
PhotoAlbumModel model = new PhotoAlbumModel();
|
||||
PhotoAlbumView view = new PhotoAlbumView();
|
||||
PhotoAlbumController controller = new PhotoAlbumController(model, view);
|
||||
|
||||
// Initialize view with the controller
|
||||
view.setController(controller);
|
||||
|
||||
// Display the main window
|
||||
javax.swing.SwingUtilities.invokeLater(() -> view.setVisible(true));
|
||||
}
|
||||
}
|
100
hw3/src/controller/PhotoAlbumController.java
Normal file
100
hw3/src/controller/PhotoAlbumController.java
Normal file
@ -0,0 +1,100 @@
|
||||
package controller;
|
||||
|
||||
import model.Photo;
|
||||
import model.PhotoAlbumModel;
|
||||
import strategy.SortByDate;
|
||||
import strategy.SortByName;
|
||||
import strategy.SortBySize;
|
||||
import view.PhotoAlbumView;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class PhotoAlbumController {
|
||||
private PhotoAlbumModel model;
|
||||
private PhotoAlbumView view;
|
||||
|
||||
public PhotoAlbumController(PhotoAlbumModel model, PhotoAlbumView view) {
|
||||
this.model = model;
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public PhotoAlbumModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void handleAddPhoto() {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Image files", "jpg", "jpeg", "png", "gif"));
|
||||
|
||||
if (fileChooser.showOpenDialog(view) == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fileChooser.getSelectedFile();
|
||||
String name = JOptionPane.showInputDialog(view, "Enter photo name:");
|
||||
|
||||
if (name != null && !name.trim().isEmpty()) {
|
||||
Photo photo = new Photo(
|
||||
name,
|
||||
file.getAbsolutePath(),
|
||||
new Date(),
|
||||
file.length()
|
||||
);
|
||||
model.addPhoto(photo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleDeletePhoto() {
|
||||
String name = JOptionPane.showInputDialog(view, "Enter photo name to delete:");
|
||||
if (name != null && !name.trim().isEmpty()) {
|
||||
model.deletePhoto(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleNext() {
|
||||
List<Photo> photos = model.getPhotos();
|
||||
if (photos.isEmpty()) return;
|
||||
|
||||
Photo current = model.getCurrentPhoto();
|
||||
int index = photos.indexOf(current);
|
||||
|
||||
if (index < photos.size() - 1) {
|
||||
model.setCurrentPhoto(photos.get(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePrevious() {
|
||||
List<Photo> photos = model.getPhotos();
|
||||
if (photos.isEmpty()) return;
|
||||
|
||||
Photo current = model.getCurrentPhoto();
|
||||
int index = photos.indexOf(current);
|
||||
|
||||
if (index > 0) {
|
||||
model.setCurrentPhoto(photos.get(index - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public void handleSort(int strategy) {
|
||||
switch (strategy) {
|
||||
case 0:
|
||||
model.setSortingStrategy(new SortByName());
|
||||
break;
|
||||
case 1:
|
||||
model.setSortingStrategy(new SortByDate());
|
||||
break;
|
||||
case 2:
|
||||
model.setSortingStrategy(new SortBySize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePhotoSelection(int index) {
|
||||
List<Photo> photos = model.getPhotos();
|
||||
if (index >= 0 && index < photos.size()) {
|
||||
model.setCurrentPhoto(photos.get(index));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
public interface AlbumIterator {
|
||||
package iterator;
|
||||
|
||||
import model.Photo;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface AlbumIterator extends Iterator<Photo> {
|
||||
boolean hasNext(); // to check if there is a next element
|
||||
boolean hasPrevious(); // to check if there is a previous element
|
||||
Photo current(); // to get the photo at the current position
|
49
hw3/src/iterator/PhotoIterator.java
Normal file
49
hw3/src/iterator/PhotoIterator.java
Normal file
@ -0,0 +1,49 @@
|
||||
package iterator;
|
||||
|
||||
import model.Photo;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class PhotoIterator implements AlbumIterator {
|
||||
private List<Photo> photos;
|
||||
private int currentPosition;
|
||||
|
||||
public PhotoIterator(List<Photo> photos) {
|
||||
this.photos = photos;
|
||||
this.currentPosition = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentPosition < photos.size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return currentPosition > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Photo current() {
|
||||
if (photos.isEmpty()) {
|
||||
throw new NoSuchElementException("The photo album is empty.");
|
||||
}
|
||||
return photos.get(currentPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Photo next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException("No next photo in the album.");
|
||||
}
|
||||
return photos.get(++currentPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Photo previous() {
|
||||
if (!hasPrevious()) {
|
||||
throw new NoSuchElementException("No previous photo in the album.");
|
||||
}
|
||||
return photos.get(--currentPosition);
|
||||
}
|
||||
}
|
49
hw3/src/model/Photo.java
Normal file
49
hw3/src/model/Photo.java
Normal file
@ -0,0 +1,49 @@
|
||||
package model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Photo {
|
||||
private String name;
|
||||
private String filePath;
|
||||
private Date dateAdded;
|
||||
private long fileSize;
|
||||
|
||||
public Photo(String name, String filePath, Date dateAdded, long fileSize) {
|
||||
this.name = name;
|
||||
this.filePath = filePath;
|
||||
this.dateAdded = dateAdded;
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public Date getDateAdded() {
|
||||
return dateAdded;
|
||||
}
|
||||
|
||||
public void setDateAdded(Date dateAdded) {
|
||||
this.dateAdded = dateAdded;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(long fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
}
|
75
hw3/src/model/PhotoAlbumModel.java
Normal file
75
hw3/src/model/PhotoAlbumModel.java
Normal file
@ -0,0 +1,75 @@
|
||||
package model;
|
||||
|
||||
import strategy.SortingStrategy;
|
||||
import iterator.AlbumIterator;
|
||||
import java.util.*;
|
||||
|
||||
public class PhotoAlbumModel {
|
||||
private List<Photo> photos;
|
||||
private SortingStrategy<Photo> sortingStrategy;
|
||||
private List<ModelChangeListener> listeners;
|
||||
private Photo currentPhoto;
|
||||
|
||||
public interface ModelChangeListener {
|
||||
void onModelChanged();
|
||||
}
|
||||
|
||||
public PhotoAlbumModel() {
|
||||
photos = new ArrayList<>();
|
||||
listeners = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addPhoto(Photo photo) {
|
||||
photos.add(photo);
|
||||
if (photos.size() == 1) {
|
||||
currentPhoto = photo;
|
||||
}
|
||||
sortPhotos();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public void deletePhoto(String name) {
|
||||
photos.removeIf(photo -> photo.getName().equals(name));
|
||||
if (currentPhoto != null && currentPhoto.getName().equals(name)) {
|
||||
currentPhoto = photos.isEmpty() ? null : photos.get(0);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public void setSortingStrategy(SortingStrategy<Photo> strategy) {
|
||||
this.sortingStrategy = strategy;
|
||||
sortPhotos();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
private void sortPhotos() {
|
||||
if (sortingStrategy != null) {
|
||||
photos = sortingStrategy.sort(photos);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(ModelChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (ModelChangeListener listener : listeners) {
|
||||
listener.onModelChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Photo> getPhotos() {
|
||||
return new ArrayList<>(photos);
|
||||
}
|
||||
|
||||
public Photo getCurrentPhoto() {
|
||||
return currentPhoto;
|
||||
}
|
||||
|
||||
public void setCurrentPhoto(Photo photo) {
|
||||
if (photos.contains(photo)) {
|
||||
currentPhoto = photo;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
14
hw3/src/strategy/SortByDate.java
Normal file
14
hw3/src/strategy/SortByDate.java
Normal file
@ -0,0 +1,14 @@
|
||||
package strategy;
|
||||
|
||||
import model.Photo;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class SortByDate implements SortingStrategy<Photo> {
|
||||
@Override
|
||||
public List<Photo> sort(List<Photo> photos) {
|
||||
photos.sort(Comparator.comparing(Photo::getDateAdded));
|
||||
return photos;
|
||||
}
|
||||
}
|
14
hw3/src/strategy/SortByName.java
Normal file
14
hw3/src/strategy/SortByName.java
Normal file
@ -0,0 +1,14 @@
|
||||
package strategy;
|
||||
|
||||
import model.Photo;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class SortByName implements SortingStrategy<Photo> {
|
||||
@Override
|
||||
public List<Photo> sort(List<Photo> photos) {
|
||||
photos.sort(Comparator.comparing(Photo::getName));
|
||||
return photos;
|
||||
}
|
||||
}
|
14
hw3/src/strategy/SortBySize.java
Normal file
14
hw3/src/strategy/SortBySize.java
Normal file
@ -0,0 +1,14 @@
|
||||
package strategy;
|
||||
|
||||
import model.Photo;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class SortBySize implements SortingStrategy<Photo> {
|
||||
@Override
|
||||
public List<Photo> sort(List<Photo> photos) {
|
||||
photos.sort(Comparator.comparing(Photo::getFileSize));
|
||||
return photos;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package strategy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SortingStrategy<T> {
|
||||
List<T> sort(List<T> photos);
|
||||
|
||||
}
|
131
hw3/src/view/PhotoAlbumView.java
Normal file
131
hw3/src/view/PhotoAlbumView.java
Normal file
@ -0,0 +1,131 @@
|
||||
package view;
|
||||
|
||||
import controller.PhotoAlbumController;
|
||||
import model.Photo;
|
||||
import model.PhotoAlbumModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class PhotoAlbumView extends JFrame implements PhotoAlbumModel.ModelChangeListener {
|
||||
private PhotoAlbumController controller;
|
||||
private PhotoAlbumModel model;
|
||||
|
||||
private JList<String> photoList;
|
||||
private DefaultListModel<String> listModel;
|
||||
private JLabel currentPhotoLabel;
|
||||
private JButton addButton;
|
||||
private JButton deleteButton;
|
||||
private JButton previousButton;
|
||||
private JButton nextButton;
|
||||
private JComboBox<String> sortingCombo;
|
||||
|
||||
public PhotoAlbumView() {
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setTitle("Photo Album Manager");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(800, 600);
|
||||
|
||||
listModel = new DefaultListModel<>();
|
||||
photoList = new JList<>(listModel);
|
||||
currentPhotoLabel = new JLabel("No photo selected", SwingConstants.CENTER);
|
||||
|
||||
addButton = new JButton("Add Photo");
|
||||
deleteButton = new JButton("Delete Photo");
|
||||
previousButton = new JButton("Previous");
|
||||
nextButton = new JButton("Next");
|
||||
|
||||
String[] sortOptions = {"Sort by Name", "Sort by Date", "Sort by Size"};
|
||||
sortingCombo = new JComboBox<>(sortOptions);
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Left panel with photo list
|
||||
JScrollPane listScrollPane = new JScrollPane(photoList);
|
||||
listScrollPane.setPreferredSize(new Dimension(200, 0));
|
||||
add(listScrollPane, BorderLayout.WEST);
|
||||
|
||||
// Center panel with current photo
|
||||
JPanel centerPanel = new JPanel(new BorderLayout());
|
||||
centerPanel.add(currentPhotoLabel, BorderLayout.CENTER);
|
||||
add(centerPanel, BorderLayout.CENTER);
|
||||
|
||||
// Bottom panel with controls
|
||||
JPanel controlPanel = new JPanel();
|
||||
controlPanel.add(previousButton);
|
||||
controlPanel.add(nextButton);
|
||||
controlPanel.add(addButton);
|
||||
controlPanel.add(deleteButton);
|
||||
controlPanel.add(sortingCombo);
|
||||
add(controlPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public void setController(PhotoAlbumController controller) {
|
||||
this.controller = controller;
|
||||
this.model = controller.getModel();
|
||||
model.addListener(this);
|
||||
|
||||
addButton.addActionListener(e -> controller.handleAddPhoto());
|
||||
deleteButton.addActionListener(e -> controller.handleDeletePhoto());
|
||||
nextButton.addActionListener(e -> controller.handleNext());
|
||||
previousButton.addActionListener(e -> controller.handlePrevious());
|
||||
sortingCombo.addActionListener(e -> controller.handleSort(sortingCombo.getSelectedIndex()));
|
||||
photoList.addListSelectionListener(e -> {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
int index = photoList.getSelectedIndex();
|
||||
if (index >= 0) {
|
||||
controller.handlePhotoSelection(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChanged() {
|
||||
updatePhotoList();
|
||||
updateCurrentPhoto();
|
||||
}
|
||||
|
||||
private void updatePhotoList() {
|
||||
listModel.clear();
|
||||
List<Photo> photos = model.getPhotos();
|
||||
for (Photo photo : photos) {
|
||||
listModel.addElement(photo.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCurrentPhoto() {
|
||||
Photo current = model.getCurrentPhoto();
|
||||
if (current != null) {
|
||||
ImageIcon icon = loadImage(current.getFilePath());
|
||||
if (icon != null) {
|
||||
currentPhotoLabel.setIcon(icon);
|
||||
currentPhotoLabel.setText("");
|
||||
} else {
|
||||
currentPhotoLabel.setIcon(null);
|
||||
currentPhotoLabel.setText("Unable to load image");
|
||||
}
|
||||
} else {
|
||||
currentPhotoLabel.setIcon(null);
|
||||
currentPhotoLabel.setText("No photo selected");
|
||||
}
|
||||
}
|
||||
|
||||
private ImageIcon loadImage(String path) {
|
||||
try {
|
||||
ImageIcon icon = new ImageIcon(path);
|
||||
Image img = icon.getImage();
|
||||
Image scaledImg = img.getScaledInstance(400, 300, Image.SCALE_SMOOTH);
|
||||
return new ImageIcon(scaledImg);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user