package su.litvak.moviedb.gui;
import org.hibernate.criterion.Order;
import su.litvak.moviedb.Sessions;
import su.litvak.moviedb.entity.Genre;
import su.litvak.moviedb.entity.Movie;
import su.litvak.moviedb.entity.Person;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.*;
import java.util.List;
public class MoviePanel extends JPanel {
Movie movie;
boolean saved;
JLabel lblName = new JLabel("Movie Name");
JTextField fldName = new JTextField();
JLabel lblYear = new JLabel("Year");
JSpinner spYear = new JSpinner(new SpinnerNumberModel(2013, 1900, 2020, 1));
JLabel lblGenres = new JLabel("Genres");
List<GenreComboBox> lstGenrePanels = new ArrayList<GenreComboBox>();
JButton btnAddGenre = new JButton("[+]");
JLabel lblRating = new JLabel("Rating");
JFormattedTextField fldRating;
JLabel lblDirectors = new JLabel("Directors");
List<PersonPanel> lstDirectors = new ArrayList<PersonPanel>();
JButton btnAddDirector = new JButton("[+]");
JLabel lblWriters = new JLabel("Writers");
List<PersonPanel> lstWriters = new ArrayList<PersonPanel>();
JButton btnAddWriter = new JButton("[+]");
JLabel lblProducers = new JLabel("Producers");
List<PersonPanel> lstProducers = new ArrayList<PersonPanel>();
JButton btnAddProducer = new JButton("[+]");
JLabel lblLength = new JLabel("Length");
JSpinner spLength = new JSpinner(new SpinnerNumberModel(120, 1, 5000, 1));
JLabel lblMinute = new JLabel("minute");
JLabel lblCast = new JLabel("<html><body><h1>Cast</h1></body></html>");
List<PersonPanel> lstActors = new ArrayList<PersonPanel>();
JButton btnAddActor = new JButton("[+]");
JLabel lblStory = new JLabel("<html><body><h2>Story</h2></body></html>");
JTextArea taStory = new JTextArea();
JScrollPane spStory = new JScrollPane(taStory);
static class GenreComboBox extends JComboBox {
GenreComboBox() {
Sessions.beginTransaction();
for (Genre genre : (List<Genre>) Sessions.getSession()
.createCriteria(Genre.class)
.addOrder(Order.asc("title")).list()) {
addItem(genre);
}
Sessions.rollbackTransaction();
}
}
static class PersonPanel extends JPanel {
JLabel lbl;
JTextField fld = new JTextField();
PersonPanel(boolean showlabel) {
if (showlabel) {
lbl = new JLabel();
add(lbl);
}
add(fld);
fld.setPreferredSize(new Dimension(150, fld.getPreferredSize().height));
}
}
public MoviePanel() {
movie = new Movie();
performLayout();
}
public MoviePanel(Movie movie) {
this.movie = movie;
performLayout();
}
private void performLayout() {
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
/**
* Set up rating field
*/
NumberFormat ratingFormat = NumberFormat.getInstance();
ratingFormat.setMinimumFractionDigits(0);
ratingFormat.setMaximumFractionDigits(1);
fldRating = new JFormattedTextField(ratingFormat);
fldRating.setColumns(3);
/**
* Set up story text area
*/
taStory.setRows(5);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
final GroupLayout.Group genreHorGroup = layout.createSequentialGroup();
final GroupLayout.Group genreVerGroup = layout.createParallelGroup(GroupLayout.Alignment.CENTER);
final GroupLayout.Group dirHorGroup = layout.createSequentialGroup();
final GroupLayout.Group dirVerGroup = layout.createParallelGroup(GroupLayout.Alignment.CENTER);
final GroupLayout.Group wrHorGroup = layout.createSequentialGroup();
final GroupLayout.Group wrVerGroup = layout.createParallelGroup(GroupLayout.Alignment.CENTER);
final GroupLayout.Group prodHorGroup = layout.createSequentialGroup();
final GroupLayout.Group prodVerGroup = layout.createParallelGroup(GroupLayout.Alignment.CENTER);
final GroupLayout.Group actHorGroup = layout.createParallelGroup();
final GroupLayout.Group actVerGroup = layout.createSequentialGroup();
layout.setHorizontalGroup(layout.createParallelGroup()
.addGroup(layout.createSequentialGroup()
.addComponent(lblName)
.addComponent(fldName)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblYear)
.addComponent(spYear, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblRating)
.addComponent(fldRating, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblGenres)
.addGroup(genreHorGroup)
.addComponent(btnAddGenre)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblDirectors)
.addGroup(dirHorGroup)
.addComponent(btnAddDirector)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblWriters)
.addGroup(wrHorGroup)
.addComponent(btnAddWriter)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblProducers)
.addGroup(prodHorGroup)
.addComponent(btnAddProducer)
)
.addGroup(layout.createSequentialGroup()
.addComponent(lblLength)
.addComponent(spLength, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(lblMinute)
)
.addComponent(lblCast)
.addGroup(actHorGroup)
.addComponent(btnAddActor)
.addComponent(lblStory)
.addComponent(spStory)
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblName)
.addComponent(fldName, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblYear)
.addComponent(spYear, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblRating)
.addComponent(fldRating, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblGenres)
.addGroup(genreVerGroup)
.addComponent(btnAddGenre)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblDirectors)
.addGroup(dirVerGroup)
.addComponent(btnAddDirector)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblWriters)
.addGroup(wrVerGroup)
.addComponent(btnAddWriter)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblProducers)
.addGroup(prodVerGroup)
.addComponent(btnAddProducer)
)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lblLength)
.addComponent(spLength, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(lblMinute)
)
.addComponent(lblCast)
.addGroup(actVerGroup)
.addComponent(btnAddActor)
.addComponent(lblStory)
.addComponent(spStory)
);
/**
* Link label size
*/
layout.linkSize(lblName, lblYear, lblRating, lblGenres, lblDirectors, lblWriters, lblProducers, lblLength);
/**
* Set up text and spinners
*/
fldName.setText(movie.title.trim());
spYear.setValue(movie.year);
spLength.setValue(movie.time);
fldRating.setValue(movie.rating);
taStory.setText(movie.story);
/**
* Set up directors
*/
if (movie.directors == null) {
movie.directors = new HashSet<Person>();
addPersonPanel(lstDirectors, false, dirHorGroup, dirVerGroup);
} else {
for (Person person : movie.directors) {
addPersonPanel(lstDirectors, false, dirHorGroup, dirVerGroup);
lstDirectors.get(lstDirectors.size() - 1).fld.setText(person.name);
}
}
btnAddDirector.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addPersonPanel(lstDirectors, false, dirHorGroup, dirVerGroup);
}
});
/**
* Set up writers
*/
if (movie.writers == null) {
movie.writers = new HashSet<Person>();
addPersonPanel(lstWriters, false, wrHorGroup, wrVerGroup);
} else {
for (Person person : movie.writers) {
addPersonPanel(lstWriters, false, wrHorGroup, wrVerGroup);
lstWriters.get(lstWriters.size() - 1).fld.setText(person.name);
}
}
btnAddWriter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addPersonPanel(lstWriters, false, wrHorGroup, wrVerGroup);
}
});
/**
* Set up producers
*/
if (movie.producers == null) {
movie.producers = new HashSet<Person>();
addPersonPanel(lstProducers, false, prodHorGroup, prodVerGroup);
} else {
for (Person person : movie.producers) {
addPersonPanel(lstProducers, false, prodHorGroup, prodVerGroup);
lstProducers.get(lstProducers.size() - 1).fld.setText(person.name);
}
}
btnAddProducer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addPersonPanel(lstProducers, false, prodHorGroup, prodVerGroup);
}
});
/**
* Set up actors
*/
if (movie.actors == null) {
movie.actors = new HashSet<Person>();
addPersonPanel(lstActors, true, actHorGroup, actVerGroup);
addPersonPanel(lstActors, true, actHorGroup, actVerGroup);
addPersonPanel(lstActors, true, actHorGroup, actVerGroup);
} else {
for (Person person : movie.actors) {
addPersonPanel(lstActors, true, actHorGroup, actVerGroup);
lstActors.get(lstActors.size() - 1).fld.setText(person.name);
}
}
for (int i = 0; i < lstActors.size(); i++) {
lstActors.get(i).lbl.setText("Star " + (i + 1));
}
btnAddActor.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addPersonPanel(lstActors, true, actHorGroup, actVerGroup);
lstActors.get(lstActors.size() - 1).lbl.setText("Star " + lstActors.size());
}
});
/**
* Set up genres
*/
if (movie.genres == null) {
movie.genres = new HashSet<Genre>();
addGenre(genreHorGroup, genreVerGroup);
} else {
for (Genre genre : movie.genres) {
addGenre(genreHorGroup, genreVerGroup);
lstGenrePanels.get(lstGenrePanels.size() - 1).setSelectedItem(genre);
}
}
btnAddGenre.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addGenre(genreHorGroup, genreVerGroup);
}
});
}
/**
* Adds new genre selection component to this panel
*
* @param horGroup
* @param verGroup
*/
private void addGenre(GroupLayout.Group horGroup, GroupLayout.Group verGroup) {
GenreComboBox cmb = new GenreComboBox();
horGroup.addComponent(cmb, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
verGroup.addComponent(cmb, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
revalidate();
lstGenrePanels.add(cmb);
}
/**
* Adds new person panel component to this panel
*
* @param lst
* @param showLabel
* @param horGroup
* @param verGroup
*/
private void addPersonPanel(List<PersonPanel> lst, boolean showLabel, GroupLayout.Group horGroup, GroupLayout.Group verGroup) {
PersonPanel personPanel = new PersonPanel(showLabel);
horGroup.addComponent(personPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
verGroup.addComponent(personPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
revalidate();
lst.add(personPanel);
}
public void save() {
saved = true;
movie.title = fldName.getText().trim();
movie.year = (Integer) spYear.getValue();
movie.time = (Integer) spLength.getValue();
movie.rating = (Double) fldRating.getValue();
movie.story = taStory.getText();
/**
* Process genres
*/
Set<Genre> newGenres = new HashSet<Genre>();
for (GenreComboBox cmb : lstGenrePanels) {
newGenres.add((Genre) cmb.getSelectedItem());
}
for (Iterator<Genre> it = movie.genres.iterator(); it.hasNext(); ) {
if (!newGenres.contains(it.next())) {
it.remove();
}
}
movie.genres.addAll(newGenres);
/**
* Process directors, writers, producers and actors
*/
processPersons(movie.directors, lstDirectors);
processPersons(movie.writers, lstWriters);
processPersons(movie.producers, lstProducers);
processPersons(movie.actors, lstActors);
}
private void processPersons(Set<Person> persons, List<PersonPanel> lstPP) {
Set<Person> newPersons = new HashSet<Person>();
for (PersonPanel pp : lstPP) {
if (pp.fld.getText().trim().isEmpty()) {
continue;
}
Person p = new Person();
p.name = pp.fld.getText().trim();
newPersons.add(p);
}
for (Iterator<Person> it = persons.iterator(); it.hasNext(); ) {
if (!newPersons.contains(it.next())) {
it.remove();
}
}
persons.addAll(newPersons);
}
}