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.ActionListener;
6 import java.text.MessageFormat;
7 import java.util.Collection;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.Random;
11
12 import javax.swing.JComponent;
13 import javax.swing.JTextArea;
14 import javax.swing.JToolBar;
15 import javax.swing.ProgressMonitor;
16 import javax.swing.Timer;
17 import javax.swing.text.JTextComponent;
18
19 import org.apache.commons.lang.StringEscapeUtils;
20 import org.apache.commons.lang.StringUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 import com.jgoodies.forms.builder.PanelBuilder;
25 import com.jgoodies.forms.layout.CellConstraints;
26 import com.jgoodies.forms.layout.FormLayout;
27 import com.jgoodies.uif.builder.ToolBarBuilder;
28 import com.jgoodies.uif.component.ToolBarButton;
29 import com.jgoodies.uif.util.ResourceUtils;
30 import com.jgoodies.validation.view.ValidationComponentUtils;
31 import com.melloware.jukes.db.HibernateDao;
32 import com.melloware.jukes.db.HibernateUtil;
33 import com.melloware.jukes.db.orm.Artist;
34 import com.melloware.jukes.db.orm.Disc;
35 import com.melloware.jukes.exception.InfrastructureException;
36 import com.melloware.jukes.file.image.ImageFactory;
37 import com.melloware.jukes.gui.tool.Actions;
38 import com.melloware.jukes.gui.tool.Resources;
39 import com.melloware.jukes.gui.view.component.AlbumImage;
40 import com.melloware.jukes.gui.view.component.ComponentFactory;
41 import com.melloware.jukes.gui.view.tasks.TimerListener;
42 import com.melloware.jukes.gui.view.tasks.UpdateTagsTask;
43 import com.melloware.jukes.gui.view.validation.ArtistValidationModel;
44 import com.melloware.jukes.gui.view.validation.IconFeedbackPanel;
45 import com.melloware.jukes.util.MessageUtil;
46
47
48
49
50
51
52
53
54
55
56
57
58 @SuppressWarnings("unchecked")
59 public final class ArtistEditor
60 extends AbstractEditor {
61
62 private static final Log LOG = LogFactory.getLog(ArtistEditor.class);
63 private AlbumImage image1;
64 private AlbumImage image2;
65 private AlbumImage image3;
66 private AlbumImage image4;
67 private AlbumImage image5;
68 private AlbumImage image6;
69 private JComponent artistPanel;
70 private JTextArea notesField;
71 private JTextComponent nameField;
72 private JToolBar headerToolbar;
73
74
75
76
77 public ArtistEditor() {
78 super(Resources.ARTIST_TREE_ICON);
79 }
80
81
82
83
84 public Class getDomainClass() {
85 return Artist.class;
86 }
87
88
89
90
91 public JToolBar getHeaderToolBar() {
92 return headerToolbar;
93 }
94
95
96
97
98 public void build() {
99 initComponents();
100 initComponentAnnotations();
101 initEventHandling();
102
103 artistPanel = buildArtistPanel();
104
105 FormLayout layout = new FormLayout("fill:pref:grow",
106 "max(14dlu;pref), 3dlu, p, 4px, p, 4px, p, 4px, p, 4px, p, 4px, p");
107
108 setLayout(layout);
109 PanelBuilder builder = new PanelBuilder(layout, this);
110 builder.setDefaultDialogBorder();
111 CellConstraints cc = new CellConstraints();
112
113 builder.add(buildHintAreaPane(), cc.xy(1, 1));
114 builder.addSeparator(Resources.getString("label.artist"), cc.xy(1, 3));
115 builder.add(artistPanel, cc.xy(1, 5));
116 builder.addSeparator(Resources.getString("label.featured.discs"), cc.xy(1, 7));
117 builder.add(buildThumbnailPanel(), cc.xy(1, 9));
118 JComponent audit = buildAuditInfoPanel();
119 if (this.getSettings().isAuditInfo()) {
120 builder.addSeparator(Resources.getString("label.auditinfo"), cc.xy(1, 11));
121 builder.add(audit, cc.xy(1, 13));
122 }
123
124 }
125
126
127
128
129
130 public void commit() {
131 commit(true);
132 }
133
134
135
136
137 public void delete() {
138 super.delete();
139 try {
140 if (!MessageUtil.confirmDelete(this)) {
141 return;
142 }
143 setBusyCursor(true);
144
145 Artist artist = getArtist();
146 HibernateUtil.beginTransaction();
147 HibernateDao.refresh(artist);
148 HibernateDao.delete(artist);
149 HibernateUtil.commitTransaction();
150
151
152 getValidationModel().setDirty(false);
153
154 this.getMainModule().refreshSelection(null, Resources.NODE_DELETED);
155 } catch (Exception ex) {
156 LOG.error("Error deleting artist.", ex);
157 HibernateUtil.rollbackTransaction();
158 } finally {
159 setBusyCursor(false);
160 }
161 }
162
163
164
165
166 public void rollback() {
167 super.rollback();
168 try {
169 setBusyCursor(true);
170
171 Artist artist = getArtist();
172 HibernateDao.refresh(artist);
173 updateView();
174 super.rollback();
175 } catch (Exception ex) {
176 LOG.error("Error refreshing artist.", ex);
177 } finally {
178 setBusyCursor(false);
179 }
180 }
181
182
183
184
185
186
187 protected String getTitleSuffix() {
188 return getArtist().getName();
189 }
190
191
192
193
194 protected void updateModel() {
195 Artist artist = getArtist();
196
197 if (!StringUtils.equals(artist.getName(), nameField.getText())) {
198 artist.setName(nameField.getText());
199 }
200 if (!StringUtils.equalsIgnoreCase(artist.getNotes(), notesField.getText())) {
201 artist.setNotes(notesField.getText());
202 }
203 }
204
205
206
207
208 protected void updateView() {
209 Artist artist = getArtist();
210 nameField.setText(artist.getName());
211 notesField.setText(artist.getNotes());
212 createdDateLabel.setText(DATE_FORMAT.format(artist.getCreatedDate()));
213 createdByLabel.setText(artist.getCreatedUser());
214 modifiedDateLabel.setText(DATE_FORMAT.format(artist.getModifiedDate()));
215 modifiedByLabel.setText(artist.getModifiedUser());
216
217 image1.setDisc(null);
218 image2.setDisc(null);
219 image3.setDisc(null);
220 image4.setDisc(null);
221 image5.setDisc(null);
222 image6.setDisc(null);
223
224
225 Random random = new Random();
226
227 Collection discs = this.getDiscCollection();
228
229 HashMap map = new HashMap();
230 while ((map.size() < 6) && (map.size() <= (discs.size() - 1))) {
231 Integer rand = Integer.valueOf(random.nextInt(discs.size()));
232 map.put(rand, rand);
233 }
234 int count = 0;
235 Object[] array = discs.toArray();
236 Iterator iterator = map.values().iterator();
237 IMAGE_LOOP:
238 while (iterator.hasNext()) {
239 Integer element = (Integer)iterator.next();
240 Disc disc = (Disc)array[element.intValue()];
241 AlbumImage preview = null;
242 switch (count) {
243 case 0: {
244 preview = image1;
245 break;
246 }
247 case 1: {
248 preview = image2;
249 break;
250 }
251 case 2: {
252 preview = image3;
253 break;
254 }
255 case 3: {
256 preview = image4;
257 break;
258 }
259 case 4: {
260 preview = image5;
261 break;
262 }
263 case 5: {
264 preview = image6;
265 break;
266 }
267 default: {
268 break IMAGE_LOOP;
269 }
270 }
271 int dimension = this.getSettings().getCoverSizeSmall();
272 preview.setImage(ImageFactory.getScaledImage(disc.getCoverUrl(), dimension, dimension).getImage());
273 preview.setDisc(disc);
274 count++;
275 }
276 }
277
278
279
280
281
282
283 private Artist getArtist() {
284 return (Artist)getModel();
285 }
286
287
288
289
290
291
292
293 private Collection getDiscCollection() {
294 Collection results = null;
295 final String filter = this.getSettings().getFilter();
296
297
298 if (StringUtils.isNotBlank(filter)) {
299 final String resource = ResourceUtils.getString("hql.filter.disc");
300 final String hql = MessageFormat.format(resource, new Object[] { getArtist().getId(), filter });
301 LOG.debug(hql);
302 results = HibernateDao.findByQuery(hql);
303 } else {
304
305 results = getArtist().getDiscs();
306 }
307
308 return results;
309 }
310
311
312
313
314
315
316 private JComponent buildArtistPanel() {
317 FormLayout layout = new FormLayout("right:max(14dlu;pref), 4dlu, left:min(80dlu;pref):grow, pref, 4dlu, 25px",
318 "p, 4px, p, 7px");
319
320 PanelBuilder builder = new PanelBuilder(layout);
321 CellConstraints cc = new CellConstraints();
322
323 builder.addLabel(Resources.getString("label.name") + ": ", cc.xy(1, 1));
324 builder.add(nameField, cc.xyw(3, 1, 3));
325 builder.add(ComponentFactory.createTitleCaseButton(nameField), cc.xy(6, 1));
326 builder.addLabel(Resources.getString("label.notes") + ": ", cc.xy(1, 3, "left,top"));
327 builder.add(notesField, cc.xyw(3, 3, 3));
328
329 return new IconFeedbackPanel(getValidationModel().getValidationResultModel(), builder.getPanel());
330 }
331
332
333
334
335
336
337 private JComponent buildThumbnailPanel() {
338 FormLayout layout = new FormLayout("4px, pref, pref, pref, pref, pref, pref, pref, 4px", "p, 7px");
339
340 PanelBuilder builder = new PanelBuilder(layout);
341 CellConstraints cc = new CellConstraints();
342
343 builder.add(image1, cc.xyw(2, 1, 1));
344 builder.add(image2, cc.xyw(3, 1, 1));
345 builder.add(image3, cc.xyw(4, 1, 1));
346 builder.add(image4, cc.xyw(5, 1, 1));
347 builder.add(image5, cc.xyw(6, 1, 1));
348 builder.add(image5, cc.xyw(7, 1, 1));
349 builder.add(image6, cc.xyw(8, 1, 1));
350
351 return builder.getPanel();
352 }
353
354 private JToolBar buildToolBar() {
355 final ToolBarBuilder bar = new ToolBarBuilder("Artist Toolbar");
356 ToolBarButton button = null;
357 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.UNLOCK_ID);
358 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
359 bar.add(button);
360 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.COMMIT_ID);
361 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
362 bar.add(button);
363 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.ROLLBACK_ID);
364 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
365 bar.add(button);
366 button = (ToolBarButton)ComponentFactory.createToolBarButton(Actions.DELETE_ID);
367 button.putClientProperty(Resources.EDITOR_COMPONENT, this);
368 bar.add(button);
369 return bar.getToolBar();
370 }
371
372
373
374
375
376
377
378 private void commit(boolean aUpdateTags) {
379 super.commit();
380 Artist artist = getArtist();
381 Artist foundArtist = null;
382 boolean hasErrors = false;
383 boolean artistChanged = (!StringUtils.equals(artist.getName(), nameField.getText()));
384
385
386 try {
387 setBusyCursor(true);
388
389 final String resource = ResourceUtils.getString("hql.artist.findCaseSensitive");
390 final String hql = MessageFormat.format(resource,
391 new Object[] { StringEscapeUtils.escapeSql(nameField.getText()) });
392 foundArtist = (Artist)HibernateDao.findUniqueByQuery(hql);
393
394 if (foundArtist == null) {
395 updateModel();
396 }
397
398
399 hasErrors = hasErrors();
400 if (hasErrors) {
401 LOG.error(Resources.getString("messages.editorerrors"));
402 return;
403 }
404
405 HibernateUtil.beginTransaction();
406 if (foundArtist != null) {
407
408 for (Iterator iter = artist.getDiscs().iterator(); iter.hasNext();) {
409 Disc disc = (Disc)iter.next();
410 foundArtist.addDisc(disc);
411 }
412 HibernateDao.persist(foundArtist);
413 }
414
415 HibernateDao.saveOrUpdate(artist);
416 HibernateUtil.commitTransaction();
417
418
419 updateView();
420 } catch (InfrastructureException ex) {
421 HibernateUtil.rollbackTransaction();
422 LOG.error("Artist Name must be unique within a catalog.");
423 HibernateDao.refresh(artist);
424 hasErrors = true;
425 } catch (Exception ex) {
426 HibernateUtil.rollbackTransaction();
427 LOG.error("Error updating artist.", ex);
428 HibernateDao.refresh(artist);
429 hasErrors = true;
430 } finally {
431 setBusyCursor(false);
432 }
433
434 if (!hasErrors) {
435 if (aUpdateTags && artistChanged) {
436
437 final Artist whichArtist = (foundArtist == null) ? artist : foundArtist;
438 task = new UpdateTagsTask(whichArtist);
439 progressMonitor = new ProgressMonitor(getMainFrame(), Resources.getString("messages.updatetracks"), "",
440 0, (int)task.getLengthOfTask());
441 progressMonitor.setProgress(0);
442 progressMonitor.setMillisToDecideToPopup(10);
443 task.go();
444 timer = new Timer(50, null);
445 timer.addActionListener(new TimerListener(progressMonitor, task, timer));
446 timer.start();
447 } else {
448 MessageUtil.showSuccess(this);
449 }
450 super.commit();
451 }
452
453 if (foundArtist == null) {
454 this.getMainModule().refreshSelection(artist, Resources.NODE_CHANGED);
455 } else {
456 this.getMainModule().refreshTree();
457 }
458 }
459
460
461
462
463 private void initComponentAnnotations() {
464 ValidationComponentUtils.setInputHint(nameField, "Artist Name is Mandatory, Length <= 100");
465 ValidationComponentUtils.setMandatory(nameField, true);
466 ValidationComponentUtils.setMessageKey(nameField, "Artist.Name");
467 ValidationComponentUtils.setInputHint(notesField, "Notes Length <= 500");
468 ValidationComponentUtils.setMessageKey(notesField, "Artist.Notes");
469 }
470
471
472
473
474 private void initComponents() {
475 validationModel = new ArtistValidationModel(new Artist());
476 headerToolbar = buildToolBar();
477 final Dimension dimension = new Dimension(this.getSettings().getCoverSizeSmall(),
478 this.getSettings().getCoverSizeSmall());
479 image1 = new AlbumImage(dimension);
480 image2 = new AlbumImage(dimension);
481 image3 = new AlbumImage(dimension);
482 image4 = new AlbumImage(dimension);
483 image5 = new AlbumImage(dimension);
484 image6 = new AlbumImage(dimension);
485 nameField = ComponentFactory.createTextField(getValidationModel().getModel(Artist.PROPERTYNAME_NAME), false);
486 notesField = ComponentFactory.createTextArea(getValidationModel().getModel(Artist.PROPERTYNAME_NOTES), false);
487 notesField.setLineWrap(true);
488 notesField.setWrapStyleWord(true);
489 notesField.setRows(3);
490
491 ActionListener actionListener = new ActionListener() {
492 public void actionPerformed(ActionEvent event) {
493 AlbumImage preview = (AlbumImage)event.getSource();
494 if (preview.getDisc() != null) {
495 setBusyCursor(true);
496 getMainModule().selectNodeInTree(preview.getDisc());
497 setBusyCursor(false);
498 }
499 }
500 };
501 image1.addActionListener(actionListener);
502 image2.addActionListener(actionListener);
503 image3.addActionListener(actionListener);
504 image4.addActionListener(actionListener);
505 image5.addActionListener(actionListener);
506 image6.addActionListener(actionListener);
507
508 }
509
510 }