1 package com.melloware.jukes.gui.view.editor;
2
3 import java.awt.Dimension;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.MouseAdapter;
6 import java.awt.event.MouseEvent;
7 import java.awt.event.MouseListener;
8 import java.io.File;
9 import java.io.IOException;
10 import java.text.MessageFormat;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Iterator;
14 import java.util.List;
15
16 import javax.swing.DefaultListModel;
17 import javax.swing.JComboBox;
18 import javax.swing.JComponent;
19 import javax.swing.JFileChooser;
20 import javax.swing.JLabel;
21 import javax.swing.JList;
22 import javax.swing.JPopupMenu;
23 import javax.swing.JTextArea;
24 import javax.swing.JTextField;
25 import javax.swing.JToolBar;
26 import javax.swing.ListSelectionModel;
27 import javax.swing.ProgressMonitor;
28 import javax.swing.Timer;
29 import javax.swing.text.JTextComponent;
30
31 import org.apache.commons.lang.StringEscapeUtils;
32 import org.apache.commons.lang.StringUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36 import com.jgoodies.binding.list.SelectionInList;
37 import com.jgoodies.binding.value.ValueModel;
38 import com.jgoodies.binding.adapter.ComboBoxAdapter;
39 import com.jgoodies.forms.builder.PanelBuilder;
40 import com.jgoodies.forms.layout.CellConstraints;
41 import com.jgoodies.forms.layout.FormLayout;
42 import com.jgoodies.uif.action.ActionManager;
43 import com.jgoodies.uif.application.Application;
44 import com.jgoodies.uif.builder.ToolBarBuilder;
45 import com.jgoodies.uif.component.ToolBarButton;
46 import com.jgoodies.uif.panel.SimpleInternalFrame;
47 import com.jgoodies.uif.util.ResourceUtils;
48 import com.jgoodies.uifextras.util.UIFactory;
49 import com.jgoodies.validation.util.ValidationUtils;
50 import com.jgoodies.validation.view.ValidationComponentUtils;
51 import com.melloware.jukes.db.HibernateDao;
52 import com.melloware.jukes.db.HibernateUtil;
53 import com.melloware.jukes.db.orm.Artist;
54 import com.melloware.jukes.db.orm.Catalog;
55 import com.melloware.jukes.db.orm.Disc;
56 import com.melloware.jukes.db.orm.Track;
57 import com.melloware.jukes.exception.InfrastructureException;
58 import com.melloware.jukes.file.FileUtil;
59 import com.melloware.jukes.file.filter.FilterFactory;
60 import com.melloware.jukes.file.image.ChooserImagePreview;
61 import com.melloware.jukes.file.image.ImageFactory;
62 import com.melloware.jukes.file.image.ImageFileView;
63 import com.melloware.jukes.file.tag.MusicTag;
64 import com.melloware.jukes.file.tag.TagFactory;
65 import com.melloware.jukes.gui.tool.Actions;
66 import com.melloware.jukes.gui.tool.Resources;
67 import com.melloware.jukes.gui.view.MainMenuBuilder;
68 import com.melloware.jukes.gui.view.component.AlbumImage;
69 import com.melloware.jukes.gui.view.component.ComponentFactory;
70 import com.melloware.jukes.gui.view.component.TrackListCellRenderer;
71 import com.melloware.jukes.gui.view.dialogs.WebSearchDialog;
72 import com.melloware.jukes.gui.view.tasks.TimerListener;
73 import com.melloware.jukes.gui.view.tasks.UpdateTagsTask;
74 import com.melloware.jukes.gui.view.validation.DiscValidationModel;
75 import com.melloware.jukes.gui.view.validation.ArtistValidationModel;
76 import com.melloware.jukes.gui.view.validation.IconFeedbackPanel;
77 import com.melloware.jukes.util.JukesValidationMessage;
78 import com.melloware.jukes.util.MessageUtil;
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @SuppressWarnings("unchecked")
93 public final class DiscEditor
94 extends AbstractEditor {
95
96 private static final Log LOG = LogFactory.getLog(DiscEditor.class);
97 private static final List GENRE_LIST = MusicTag.getGenreTypes();
98 private AlbumImage albumImage;
99 private DefaultListModel listModel;
100 private JComboBox genre;
101 private JComponent discPanel;
102 private JComponent genreEditor;
103 private JLabel genreLabel;
104 private JLabel location;
105 private JList trackList;
106 private JTextArea notesField;
107 private JTextComponent nameField;
108 private JTextComponent year;
109 private JTextComponent artistField;
110 private JToolBar headerToolbar;
111 private List tracks;
112 private SimpleInternalFrame listScrollPane;
113
114
115
116
117 public DiscEditor() {
118 super(Resources.DISC_TREE_ICON);
119 }
120
121
122
123
124 public Class getDomainClass() {
125 return Disc.class;
126 }
127
128
129
130
131 public JToolBar getHeaderToolBar() {
132 return headerToolbar;
133 }
134
135
136
137
138 public void build() {
139 initComponents();
140 initComponentAnnotations();
141 initEventHandling();
142
143 discPanel = buildDiscPanel();
144
145 FormLayout layout = new FormLayout("fill:pref:grow", "p, 12px, p, p, 12px, p, 12px, p, 12px, p");
146
147 setLayout(layout);
148 PanelBuilder builder = new PanelBuilder(layout, this);
149 builder.setDefaultDialogBorder();
150 CellConstraints cc = new CellConstraints();
151
152 builder.add(buildMusicPanel(), cc.xy(1, 1));
153 builder.add(buildHintAreaPane(), cc.xy(1, 3));
154 builder.addSeparator(Resources.getString("label.disc"), cc.xy(1, 4));
155 builder.add(discPanel, cc.xy(1, 6));
156 JComponent audit = buildAuditInfoPanel();
157 if (this.getSettings().isAuditInfo()) {
158 builder.addSeparator(Resources.getString("label.auditinfo"), cc.xy(1, 8));
159 builder.add(audit, cc.xy(1, 10));
160 }
161 }
162
163
164
165
166
167
168 public void commit() {
169 commit(this.getSettings().isUpdateTags());
170 }
171
172
173
174
175 public void delete() {
176 super.delete();
177 try {
178 if (!MessageUtil.confirmDelete(this)) {
179 return;
180 }
181
182 setBusyCursor(true);
183 HibernateUtil.beginTransaction();
184 Disc disc = getDisc();
185 final Artist artist = disc.getArtist();
186 HibernateDao.refresh(artist);
187 artist.getDiscs().remove(disc);
188 HibernateDao.refresh(disc);
189 HibernateDao.delete(disc);
190 HibernateUtil.commitTransaction();
191
192
193
194 if (this.getSettings().isCopyImagesToDirectory()) {
195 final String oldImageName = ImageFactory.standardImageFileName(artist.getName(), disc.getName(), disc.getYear());
196 File oldImageFile = new File (oldImageName);
197 if ( oldImageFile.exists() ) {
198 if (!oldImageFile.delete()) {
199 LOG.debug("Error deleting file: " + oldImageFile.getAbsolutePath());
200 }
201 }
202 }
203
204
205 getValidationModel().setDirty(false);
206
207 if (artist.getDiscs().size() == 0) {
208
209 ActionManager.get(Actions.REFRESH_ID).actionPerformed(null);
210 } else {
211
212 this.getMainModule().refreshSelection(disc, Resources.NODE_DELETED);
213 }
214 } catch (Exception ex) {
215 final String errorMessage = ResourceUtils.getString("messages.ErrorDeletingDisc");
216 MessageUtil.showError(this, errorMessage);
217 LOG.error(errorMessage, ex);
218 HibernateUtil.rollbackTransaction();
219 } finally {
220 setBusyCursor(false);
221 }
222 }
223
224
225
226
227 public void findCover() {
228 Disc disc = getDisc();
229 if (disc.isNotValid()) {
230 final String errorMessage = ResourceUtils.getString("messages.discnotexists");
231 LOG.error(errorMessage);
232 MessageUtil.showError(this, errorMessage);
233 return;
234 }
235
236 updateModel();
237
238
239 boolean hasErrors = hasErrors();
240 if (hasErrors) {
241 LOG.error(Resources.MESSAGE_EDITOR_ERRORS);
242 MessageUtil.showError(this, Resources.MESSAGE_EDITOR_ERRORS);
243 return;
244 }
245
246 final File currentDir = new File(getDisc().getLocation());
247 JFileChooser chooser = new JFileChooser();
248 chooser.setApproveButtonText("Select");
249 chooser.setDialogTitle("Find Cover Image");
250 chooser.setCurrentDirectory(currentDir);
251 chooser.addChoosableFileFilter(FilterFactory.imageFileFilter());
252 chooser.setAcceptAllFileFilterUsed(false);
253 chooser.setFileView(new ImageFileView());
254 chooser.setAccessory(new ChooserImagePreview(chooser));
255 chooser.setMultiSelectionEnabled(false);
256 int returnVal = chooser.showOpenDialog(Application.getDefaultParentFrame());
257 if (returnVal != JFileChooser.APPROVE_OPTION) {
258 return;
259 }
260
261 File file = chooser.getSelectedFile();
262
263
264 String imageLocation;
265 try {
266 imageLocation = ImageFactory.saveImageToUserDefinedDirectory(file,
267 disc.getArtist().getName(),
268 disc.getName().toString(),
269 disc.getYear().toString());
270 } catch (IOException e) {
271
272 e.printStackTrace();
273 imageLocation = file.getAbsolutePath();
274 }
275
276 try {
277 setBusyCursor(true);
278 HibernateUtil.beginTransaction();
279 disc.setCoverUrl(imageLocation);
280 HibernateDao.persist(disc);
281 HibernateUtil.commitTransaction();
282
283
284 updateView();
285 } catch (InfrastructureException ex) {
286 final String errorMessage = ResourceUtils.getString("messages.DiscUnique");
287 MessageUtil.showError(this, errorMessage);
288 LOG.error(errorMessage, ex);
289 HibernateUtil.rollbackTransaction();
290 HibernateDao.refresh(disc);
291 } catch (Exception ex) {
292 final String errorMessage = ResourceUtils.getString("messages.ErrorUpdatingCoverImage");
293 MessageUtil.showError(this, errorMessage);
294 LOG.error(errorMessage, ex);
295 HibernateUtil.rollbackTransaction();
296 HibernateDao.refresh(disc);
297 } finally {
298 setBusyCursor(false);
299 }
300 }
301
302
303
304
305 public void renameFiles() {
306 if (getDisc().isNotValid()) {
307 final String errorMessage = ResourceUtils.getString("messages.discnotexists");
308 MessageUtil.showError(this, errorMessage);
309 LOG.error(errorMessage);
310 return;
311 }
312
313 updateModel();
314
315
316 boolean hasErrors = hasErrors();
317 if (hasErrors) {
318 LOG.error(Resources.MESSAGE_EDITOR_ERRORS);
319 MessageUtil.showError(this, Resources.MESSAGE_EDITOR_ERRORS);
320 return;
321 }
322
323 MusicTag musicTag = null;
324 try {
325 setBusyCursor(true);
326 for (Iterator iter = getDisc().getTracks().iterator(); iter.hasNext();) {
327 Track track = (Track)iter.next();
328 final File file = new File(track.getTrackUrl());
329
330 if (file.exists()) {
331 musicTag = TagFactory.getTag(file);
332 if (musicTag.renameFile(this.getSettings().getFileFormatMusic())) {
333 track.setTrackUrl(musicTag.getAbsolutePath());
334 }
335 }
336 }
337 commit(false);
338 } catch (InfrastructureException ex) {
339 LOG.error(ex.getMessage());
340 MessageUtil.showError(this, ex.getMessage());
341 } catch (Exception ex) {
342 final String errorMessage = ResourceUtils.getString("messages.ErrorRenamingFile");
343 MessageUtil.showError(this, errorMessage);
344 LOG.error(errorMessage, ex);
345 } finally {
346 setBusyCursor(false);
347 }
348 }
349
350
351
352
353 public void rollback() {
354 super.rollback();
355 try {
356 setBusyCursor(true);
357
358 Disc disc = getDisc();
359 HibernateDao.refresh(disc);
360 updateView();
361 super.rollback();
362 } catch (Exception ex) {
363 final String errorMessage = ResourceUtils.getString("messages.ErrorRefreshingDisc");
364 MessageUtil.showError(this, errorMessage);
365 LOG.error(errorMessage, ex);
366 } finally {
367 setBusyCursor(false);
368 }
369 }
370
371
372
373
374 public void webSearch() {
375 super.webSearch();
376 final Disc disc = getDisc();
377 if (disc.isNotValid()) {
378 final String errorMessage = ResourceUtils.getString("messages.discnotexists");
379 MessageUtil.showError(this, errorMessage);
380 LOG.error(errorMessage);
381 return;
382 }
383
384 if (hasErrors()) {
385 LOG.error(Resources.MESSAGE_EDITOR_ERRORS);
386 MessageUtil.showError(this, Resources.MESSAGE_EDITOR_ERRORS);
387 return;
388 }
389
390 final WebSearchDialog dialog = new WebSearchDialog(getMainFrame(), getSettings());
391 dialog.setSelectedArtist(disc.getArtist().getName());
392 dialog.setSelectedDisc(disc.getName());
393 dialog.open();
394
395
396 if (dialog.hasBeenCanceled()) {
397 return;
398 }
399
400
401 boolean modified = false;
402
403
404 final String[] checkList = { "- Disc", "-Disc", "- disc" };
405 if (((StringUtils.isNotBlank(dialog.getSelectedDisc()))
406 && (StringUtils.indexOfAny(nameField.getText(), checkList) <= 0))) {
407 disc.setName(dialog.getSelectedDisc());
408 nameField.setText(dialog.getSelectedDisc());
409 modified = true;
410 }
411 if ((StringUtils.isNotBlank(dialog.getSelectedYear()))
412 && (Integer.valueOf(dialog.getSelectedYear()).intValue() < Integer.valueOf(year.getText()).intValue())) {
413 disc.setYear(dialog.getSelectedYear());
414 year.setText(dialog.getSelectedYear());
415 modified = true;
416 }
417 if (dialog.getSelectedImage() != null) {
418 try {
419 if (StringUtils.isNotBlank(disc.getCoverUrl())) {
420 ImageFactory.saveImage(dialog.getSelectedImage(), disc.getCoverUrl());
421 } else {
422 String filename = ImageFactory.saveImageWithFileFormat(dialog.getSelectedImage(),
423 this.getSettings().getFileFormatImage(),
424 disc.getLocation(),
425 disc.getArtist().getName(),
426 disc.getName(),
427 disc.getYear());
428 disc.setCoverUrl(filename);
429 }
430 albumImage.setImage(ImageFactory.getDiscImage(disc.getCoverUrl()).getImage());
431 } catch (IOException ex) {
432 final String errorMessage = ResourceUtils.getString("messages.ErrorSavingCoverImage");
433 MessageUtil.showError(this, errorMessage);
434 LOG.error(errorMessage, ex);
435 }
436 }
437
438
439 commit(modified);
440 }
441
442
443
444
445
446
447 protected String getTitleSuffix() {
448 return getDisc().getDisplayText(getSettings().getDisplayFormatDisc());
449 }
450
451
452
453
454 protected void updateModel() {
455 Disc disc = getDisc();
456 Artist foundArtist = null;
457
458 if (!StringUtils.equals(disc.getName(), nameField.getText())) {
459 disc.setName(nameField.getText());
460 }
461
462 if (!StringUtils.equalsIgnoreCase(disc.getYear(), year.getText())) {
463 disc.setYear(year.getText());
464 }
465 if (!StringUtils.equalsIgnoreCase(disc.getGenre(), (String)genre.getSelectedItem())) {
466 disc.setGenre((String)genre.getSelectedItem());
467 }
468
469 if (!StringUtils.equalsIgnoreCase(disc.getNotes(), notesField.getText())) {
470 disc.setNotes(notesField.getText());
471 }
472
473
474 if ((artistField.getText()== null) || (ValidationUtils.isBlank(artistField.getText()))) {
475 final String errorMessage = ResourceUtils.getString("messages.UpdateModel")+ Resources.MESSAGE_EDITOR_ERRORS
476 + "\n " + ResourceUtils.getString("messages.ArtistNameMandatory");
477 MessageUtil.showError(this, errorMessage);
478 LOG.error(errorMessage);
479 } else if (!StringUtils.equalsIgnoreCase(disc.getArtist().getName() , artistField.getText())) {
480
481 try {
482 setBusyCursor(true);
483
484 final String resource = ResourceUtils.getString("hql.artist.findCaseSensitive");
485 final String hql = MessageFormat.format(resource,
486 new Object[] { StringEscapeUtils.escapeSql(artistField.getText()) });
487 foundArtist = (Artist)HibernateDao.findUniqueByQuery(hql);
488
489 if (foundArtist == null) {
490 final String errorMessage = ResourceUtils.getString("messages.ErrorUpdatingArtistNotFound") + artistField.getText();
491 LOG.error(errorMessage);
492 MessageUtil.showError(this, errorMessage);
493 }
494 if (foundArtist != null) {
495
496 disc.setArtist(foundArtist);
497 }
498 } catch (InfrastructureException ex) {
499 final String errorMessage = ResourceUtils.getString("messages.ArtistNameUnique");
500 LOG.error(errorMessage);
501 MessageUtil.showError(this, errorMessage);
502 } catch (Exception ex) {
503 final String errorMessage = ResourceUtils.getString("messages.ErrorUpdatingArtist");
504 LOG.error(errorMessage, ex);
505 MessageUtil.showError(this, errorMessage);
506 } finally {
507 setBusyCursor(false);
508 }
509
510 }
511 }
512
513
514
515
516 protected void updateView() {
517 Disc disc = getDisc();
518 final String currentCoverUrl;
519
520 genre.setSelectedItem(null);
521
522 nameField.setText(disc.getName());
523 year.setText(disc.getYear());
524 genre.setSelectedItem(disc.getGenre());
525 genreLabel.setText(disc.getGenre());
526 location.setText(disc.getLocation());
527 location.setToolTipText(disc.getLocation());
528 notesField.setText(disc.getNotes());
529 artistField.setText(disc.getArtist().getName());
530 createdDateLabel.setText(DATE_FORMAT.format(disc.getCreatedDate()));
531 createdByLabel.setText(disc.getCreatedUser());
532 modifiedDateLabel.setText(DATE_FORMAT.format(disc.getModifiedDate()));
533 modifiedByLabel.setText(disc.getModifiedUser());
534 listModel.removeAllElements();
535 tracks = new ArrayList();
536 for (Iterator iter = disc.getTracks().iterator(); iter.hasNext();) {
537 final Track track = (Track)iter.next();
538 final String name = track.getDisplayText(getSettings().getDisplayFormatTrack());
539 final JukesValidationMessage message = new JukesValidationMessage(name, null, track);
540 tracks.add(message);
541 }
542 Collections.sort(tracks, TrackListCellRenderer.TRACK_COMPARATOR);
543 for (Iterator iter = tracks.iterator(); iter.hasNext();) {
544 JukesValidationMessage message = (JukesValidationMessage)iter.next();
545 listModel.addElement(message);
546 }
547
548
549 int dimension = this.getSettings().getCoverSizeLarge();
550 albumImage.setDisc(disc);
551 if (this.getSettings().isCopyImagesToDirectory()) {
552 currentCoverUrl = ImageFactory.standardImageFileName(disc.getArtist().getName(), disc.getName(), disc.getYear());
553 }
554 else {
555 currentCoverUrl = disc.getCoverUrl();
556 }
557 albumImage.setImage(ImageFactory.getScaledImage(currentCoverUrl, dimension, dimension).getImage());
558 }
559
560
561
562
563
564
565 private Disc getDisc() {
566 return (Disc)getModel();
567 }
568
569
570
571
572
573
574 private JComponent buildDiscPanel() {
575
576 FormLayout layout = new FormLayout("right:max(14dlu;pref), 4dlu, left:min(80dlu;pref):grow, pref, 4dlu, pref, 25px",
577 "p, 4px, p, 4px, p, 4px, p, 4px, p, 4px, p, 4px");
578
579 layout.setRowGroups(new int[][] {
580 { 1, 3, 5 }
581 });
582 PanelBuilder builder = new PanelBuilder(layout);
583 CellConstraints cc = new CellConstraints();
584
585 builder.addLabel(Resources.getString("label.artist") + ": ", cc.xy(1, 1));
586 builder.add(artistField, cc.xyw(3, 1, 3));
587
588 builder.addLabel(Resources.getString("label.name") + ": ", cc.xy(1, 3));
589 builder.add(nameField, cc.xyw(3, 3, 3));
590 builder.add(ComponentFactory.createTitleCaseButton(nameField), cc.xy(6, 3));
591 builder.addLabel(Resources.getString("label.genre") + ": ", cc.xy(1, 5));
592 builder.add(genreLabel, cc.xyw(2, 5, 2));
593 builder.add(genre, cc.xyw(3, 5, 3));
594 builder.addLabel(Resources.getString("label.year") + ": ", cc.xy(1, 7));
595 builder.add(year, cc.xy(3, 7));
596 builder.addLabel(Resources.getString("label.file") + ": ", cc.xy(1, 9));
597 builder.add(location, cc.xyw(3, 9, 5));
598 builder.addLabel(Resources.getString("label.notes") + ": ", cc.xy(1, 11, "left,top"));
599 builder.add(notesField, cc.xyw(3, 11, 3));
600
601 return new IconFeedbackPanel(getValidationModel().getValidationResultModel(), builder.getPanel());
602 }
603
604
605
606
607
608
609 private JComponent buildMusicPanel() {
610 FormLayout layout = new FormLayout("left:pref, 4dlu, right:pref", "p");
611
612 layout.setRowGroups(new int[][] {
613 { 1 }
614 });
615 PanelBuilder builder = new PanelBuilder(layout);
616 CellConstraints cc = new CellConstraints();
617 builder.add(listScrollPane, cc.xy(1, 1, "left,top"));
618 builder.add(albumImage, cc.xy(3, 1, "left,top"));
619 return builder.getPanel();
620 }
621
622 private JToolBar buildToolBar() {
623 final ToolBarBuilder bar = new ToolBarBuilder("Disc Toolbar");
624 ToolBarButton button = null;
625 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.UNLOCK_ID);
626 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
627 bar.add(button);
628 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.COMMIT_ID);
629 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
630 bar.add(button);
631 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.ROLLBACK_ID);
632 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
633 bar.add(button);
634 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.DELETE_ID);
635 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
636 bar.add(button);
637 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.FILE_RENAME_ID);
638 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
639 bar.add(button);
640 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.DISC_COVER_ID);
641 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
642 bar.add(button);
643 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.DISC_WEB_ID);
644 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
645 bar.add(button);
646 return bar.getToolBar();
647 }
648
649
650
651
652
653
654
655 private void commit(boolean aUpdateTags) {
656 super.commit();
657 final Disc disc = getDisc();
658 final String temporaryDiscName = disc.getName();
659 final String temporaryDiscYear = disc.getYear();
660 final String temporaryDiscGenre = disc.getGenre();
661 final String temporaryDiscNotes = disc.getNotes();
662 final String oldImageName = ImageFactory.standardImageFileName(disc.getArtist().getName(), disc.getName(), disc.getYear());
663 Artist foundArtist = null;
664 Artist artist = null;
665
666 if ((artistField.getText()== null) || (ValidationUtils.isBlank(artistField.getText()))) {
667 final String errorMessage = Resources.MESSAGE_EDITOR_ERRORS + "\n" + ResourceUtils.getString("messages.ArtistNameMandatory");
668 MessageUtil.showError(this, errorMessage);
669 LOG.error(errorMessage);
670 return;
671 }
672
673 if (artistField.getText().length() > 100) {
674 final String errorMessage = Resources.MESSAGE_EDITOR_ERRORS + "\n" + ResourceUtils.getString("messages.ArtistNameLength") + " <= 100";
675 MessageUtil.showError(this, errorMessage);
676 LOG.error(errorMessage);
677 return;
678 }
679 boolean artistChanged = (!StringUtils.equalsIgnoreCase(disc.getArtist().getName() , artistField.getText()));
680
681
682 boolean hasErrors = hasErrors();
683 if (hasErrors) {
684 LOG.error(Resources.MESSAGE_EDITOR_ERRORS);
685 MessageUtil.showError(this, Resources.MESSAGE_EDITOR_ERRORS);
686 return;
687 }
688
689
690 if (artistChanged) {
691 try {
692 setBusyCursor(true);
693
694 final String resource = ResourceUtils.getString("hql.artist.findCaseSensitive");
695 final String hql = MessageFormat.format(resource,
696 new Object[] { StringEscapeUtils.escapeSql(artistField.getText()) });
697 foundArtist = (Artist)HibernateDao.findUniqueByQuery(hql);
698 if (foundArtist == null) {
699
700 artist = new Artist();
701 artist.setName(artistField.getText());
702 artist.setNotes("");
703 HibernateUtil.beginTransaction();
704 HibernateDao.saveOrUpdate(artist);
705 HibernateUtil.commitTransaction();
706 }
707 if (foundArtist != null) {
708
709 LOG.debug("DiscEditor - Change Artist, Artist was found in Database: " + artistField.getText());
710 }
711 } catch (InfrastructureException ex) {
712 final String errorMessage = ResourceUtils.getString("messages.ArtistNameUnique");
713 MessageUtil.showError(this, errorMessage);
714 LOG.error(errorMessage);
715 } catch (Exception ex) {
716 final String errorMessage = ResourceUtils.getString("messages.ErrorUpdatingArtist");
717 MessageUtil.showError(this, errorMessage);
718 LOG.error(errorMessage, ex);
719 } finally {
720 setBusyCursor(false);
721 }
722 }
723
724 updateModel();
725
726
727 try {
728 setBusyCursor(true);
729 HibernateUtil.beginTransaction();
730 HibernateDao.saveOrUpdate(disc);
731 HibernateUtil.commitTransaction();
732
733
734 if (this.getSettings().isCopyImagesToDirectory()) {
735 File oldImageFile = new File (oldImageName);
736 if ( oldImageFile.exists() ) {
737 final String newImageName = ImageFactory.standardImageFileName(artistField.getText(), disc.getName(), disc.getYear());
738 final File newImageFile = new File (newImageName);
739 oldImageFile.renameTo(newImageFile);
740 }
741 }
742
743 updateView();
744 this.getMainModule().refreshSelection(disc, Resources.NODE_CHANGED);
745 if (artistChanged) {
746 this.getMainModule().refreshTree();
747 }
748 } catch (InfrastructureException ex) {
749 final String errorMessage = ResourceUtils.getString("messages.DiscUnique");
750 MessageUtil.showError(this, errorMessage);
751 LOG.error(errorMessage);
752 HibernateUtil.rollbackTransaction();
753
754 disc.setName(temporaryDiscName);
755 disc.setYear(temporaryDiscYear);
756 disc.setGenre(temporaryDiscGenre);
757 disc.setNotes(temporaryDiscNotes);
758 nameField.setText(temporaryDiscName);
759 year.setText(temporaryDiscYear);
760 genre.setSelectedItem(temporaryDiscGenre);
761 notesField.setText(temporaryDiscNotes);
762 HibernateDao.refresh(disc);
763 updateModel();
764
765
766 final Object selectedNode = this.getMainModule().getSelection();
767 this.getMainModule().refreshTree(selectedNode);
768 rollback();
769 hasErrors = true;
770 getValidationModel().setDirty(false);
771 } catch (Exception ex) {
772 final String errorMessage = ResourceUtils.getString("messages.ErrorUpdatingDisc");
773 MessageUtil.showError(this, errorMessage);
774 LOG.error(errorMessage, ex);
775 HibernateUtil.rollbackTransaction();
776 HibernateDao.refresh(disc);
777 hasErrors = true;
778 } finally {
779 setBusyCursor(false);
780 }
781
782 if (!hasErrors) {
783 if (aUpdateTags) {
784
785 task = new UpdateTagsTask(disc);
786 progressMonitor = new ProgressMonitor(getMainFrame(), Resources.getString("messages.updatetracks"), "",
787 0, (int)task.getLengthOfTask());
788 progressMonitor.setProgress(0);
789 progressMonitor.setMillisToDecideToPopup(10);
790 task.go();
791 timer = new Timer(50, null);
792 timer.addActionListener(new TimerListener(progressMonitor, task, timer));
793 timer.start();
794 } else {
795 MessageUtil.showSuccess(this);
796 }
797 super.commit();
798 }
799 }
800
801
802
803
804 private void initComponentAnnotations() {
805 ValidationComponentUtils.setInputHint(nameField, "Name is Mandatory, Length <= 100");
806 ValidationComponentUtils.setMandatory(nameField, true);
807 ValidationComponentUtils.setMessageKey(nameField, "Disc.Name");
808 ValidationComponentUtils.setInputHint(year, "Year is Mandatory, must be exactly 4 digits between 0000-9999");
809 ValidationComponentUtils.setMandatory(year, true);
810 ValidationComponentUtils.setMessageKey(year, "Disc.Year");
811 ValidationComponentUtils.setInputHint(genre, "Genre is Mandatory, Length <= 100, Enter <Genre>, <Genre: Style> or <Genre, Style>");
812 ValidationComponentUtils.setMandatory(genre, true);
813 ValidationComponentUtils.setMessageKey(genre, "Disc.Genre");
814 ValidationComponentUtils.setInputHint(notesField, "Notes Length <= 500");
815 ValidationComponentUtils.setMessageKey(notesField, "Disc.Notes");
816
817 ValidationComponentUtils.setInputHint(artistField, "Artist Name is Mandatory, Length <= 100");
818 ValidationComponentUtils.setMessageKey(artistField, "Artist.Name");
819 ValidationComponentUtils.setMandatory(artistField, true);
820
821 ValidationComponentUtils.setInputHint(genreEditor, "Genre is Mandatory, Length <= 100, Enter <Genre>, <Genre: Style> or <Genre, Style>");
822 }
823
824
825
826
827 private void initComponents() {
828 validationModel = new DiscValidationModel(new Disc());
829 ArtistValidationModel artistValidationModel = new ArtistValidationModel (new Artist());
830
831 headerToolbar = buildToolBar();
832 nameField = ComponentFactory.createTextField(validationModel.getModel(Disc.PROPERTYNAME_NAME), false);
833
834 artistField = ComponentFactory.createTextField(artistValidationModel.getModel(Artist.PROPERTYNAME_NAME), false);
835
836 year = ComponentFactory.createTextField(validationModel.getModel(Disc.PROPERTYNAME_YEAR), false);
837 ((JTextField)year).setColumns(5);
838 final ValueModel genreChoiceModel = validationModel.getModel(Disc.PROPERTYNAME_GENRE);
839 genreLabel = new JLabel();
840 genreLabel.setName("GENRE");
841
842
843 ComboBoxAdapter genreAdapter = new ComboBoxAdapter(GENRE_LIST.toArray(), genreChoiceModel);
844 genre = new JComboBox(genreAdapter);
845 genre.setEditable(true);
846
847 genreEditor = (JComponent)genre.getComponent(2);
848
849 notesField = ComponentFactory.createTextArea(getValidationModel().getModel(Disc.PROPERTYNAME_NOTES), false);
850 notesField.setLineWrap(true);
851 notesField.setWrapStyleWord(true);
852 notesField.setRows(3);
853 location = ComponentFactory.createLabel(getValidationModel().getModel(Disc.PROPERTYNAME_LOCATION));
854 albumImage = new AlbumImage(new Dimension(this.getSettings().getCoverSizeLarge(), this.getSettings().getCoverSizeLarge()));
855 listModel = new DefaultListModel();
856
857 trackList = new JList(listModel);
858 trackList.setFocusable(true);
859 trackList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
860 trackList.setSelectedIndex(0);
861 trackList.setVisibleRowCount(20);
862 trackList.setCellRenderer(new TrackListCellRenderer(this.getSettings()));
863 final JPopupMenu popup = MainMenuBuilder.buildPlayerPopupMenu(trackList);
864 MouseListener popupListener = new ListPopupListener(popup);
865 trackList.addMouseListener(popupListener);
866 trackList.add(popup);
867 listScrollPane = new SimpleInternalFrame(Resources.getString("label.tracks"));
868 listScrollPane.setFrameIcon(Resources.TRACK_TREE_ICON);
869 listScrollPane.setContent(UIFactory.createStrippedScrollPane(trackList));
870 listScrollPane.setSelected(true);
871 }
872
873
874 private static class ListPopupListener
875 extends MouseAdapter {
876
877 final JPopupMenu popup;
878
879 public ListPopupListener(JPopupMenu popup) {
880 this.popup = popup;
881 }
882
883 public void mousePressed(MouseEvent evt) {
884 maybeShowPopup(evt);
885
886
887
888 if ((((evt.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) && (evt.getClickCount() == 2)) ||
889 ((evt.getModifiers() & MouseEvent.BUTTON2_MASK) != 0))
890 {
891 LOG.debug("[List left double clicked or middle clicked].");
892 JComponent source = (JComponent)evt.getSource();
893 final ActionEvent event = new ActionEvent(source, 1, Actions.PLAYER_QUEUE_ID);
894 source.putClientProperty(Resources.EDITOR_COMPONENT, source);
895 ActionManager.get(Actions.PLAYER_QUEUE_ID).actionPerformed(event);
896 }
897 }
898
899 public void mouseReleased(MouseEvent e) {
900 maybeShowPopup(e);
901 }
902
903 private void maybeShowPopup(MouseEvent e) {
904 if (e.isPopupTrigger()) {
905 ActionManager.get(Actions.TRACK_PLAY_IMMEDIATE_ID).setEnabled(true);
906
907
908 popup.show(e.getComponent(), e.getX(), e.getY());
909 }
910 }
911
912 }
913
914 }