1 package com.melloware.jukes.gui.view.node;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.util.Collections;
6 import java.util.Comparator;
7 import java.util.Enumeration;
8
9 import javax.swing.Icon;
10 import javax.swing.JList;
11 import javax.swing.UIManager;
12 import javax.swing.tree.DefaultMutableTreeNode;
13 import javax.swing.tree.MutableTreeNode;
14 import javax.swing.tree.TreeNode;
15
16 import org.apache.commons.lang.builder.CompareToBuilder;
17 import org.apache.commons.lang.builder.EqualsBuilder;
18 import org.apache.commons.lang.builder.HashCodeBuilder;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import com.jgoodies.uif.application.Application;
23 import com.melloware.jukes.db.HibernateDao;
24 import com.melloware.jukes.db.HibernateUtil;
25 import com.melloware.jukes.db.orm.AbstractJukesObject;
26 import com.melloware.jukes.db.orm.Artist;
27 import com.melloware.jukes.db.orm.Disc;
28 import com.melloware.jukes.db.orm.Track;
29 import com.melloware.jukes.file.image.ImageBlender;
30 import com.melloware.jukes.gui.tool.MainModule;
31 import com.melloware.jukes.gui.tool.Resources;
32 import com.melloware.jukes.gui.tool.Settings;
33 import com.melloware.jukes.gui.view.MainFrame;
34 import com.melloware.jukes.util.GuiUtil;
35 import com.melloware.jukes.util.MessageUtil;
36
37
38
39
40
41
42
43
44
45
46
47
48 @SuppressWarnings("PMD")
49 abstract public class AbstractTreeNode
50 extends DefaultMutableTreeNode
51 implements NavigationNode {
52
53 private static final Log LOG = LogFactory.getLog(AbstractTreeNode.class);
54
55
56
57
58 private static Comparator nodeComparator = new Comparator() {
59 public int compare(Object aObject1, Object aObject2) {
60 final AbstractTreeNode item1 = (AbstractTreeNode)aObject1;
61 final AbstractTreeNode item2 = (AbstractTreeNode)aObject2;
62 final CompareToBuilder builder = new CompareToBuilder();
63 builder.append(item1.getName().toUpperCase(), item2.getName().toUpperCase());
64 return builder.toComparison();
65 }
66 };
67
68
69
70
71 protected static final Font BASEFONT = new JList().getFont();
72 protected final AbstractJukesObject model;
73 protected boolean childrenLoaded = false;
74 protected boolean loadingChildren = false;
75 protected Color fontColor;
76 protected Font font;
77 protected final NavigationNode parent;
78 protected Settings settings;
79
80
81
82
83
84
85
86 public AbstractTreeNode(NavigationNode aParent, AbstractJukesObject aModel) {
87 super();
88 parent = aParent;
89 model = aModel;
90 loadingChildren = false;
91 childrenLoaded = false;
92 }
93
94
95
96
97
98
99
100 abstract public String getName();
101
102
103
104
105
106 abstract public void loadChildren();
107
108 public TreeNode getChildAt(int index) {
109 loadChildren();
110 return super.getChildAt(index);
111 }
112
113 public int getChildCount() {
114 if (childrenLoaded || loadingChildren) {
115 return super.getChildCount();
116 } else {
117 if (model == null) {
118 return 0;
119 } else {
120 return model.getChildCount();
121 }
122 }
123 }
124
125
126
127
128 public Font getFont() {
129 this.font = null;
130 if (getModel().isNotValid()) {
131 font = BASEFONT.deriveFont(BASEFONT.getStyle() ^ Font.ITALIC);
132 } else if (getModel().isNewFile(this.settings.getNewFileInDays())) {
133 font = BASEFONT.deriveFont(BASEFONT.getStyle() ^ Font.BOLD);
134 }
135 return font;
136 }
137
138
139
140
141
142
143 public Color getFontColor() {
144 this.fontColor = null;
145 if (model.isNotValid()) {
146 this.fontColor = Color.RED;
147 } else if ((model instanceof Track) && (getMainFrame().getPlaylist().containsNext(model))) {
148 this.fontColor = Color.BLUE;
149 }
150 return this.fontColor;
151 }
152
153 public AbstractJukesObject getModel() {
154 return model;
155 }
156
157
158
159
160
161
162
163
164 public Icon getNodeIcon(boolean selected) {
165 Icon icon = this.getIcon(true);
166 if (icon == null) {
167 icon = UIManager.getIcon(selected ? "Tree.openIcon" : "Tree.closedIcon");
168 } else if (getModel().isNewFile(this.settings.getNewFileInDays())) {
169 icon = ImageBlender.blendIcons(Resources.NODE_NEW_OVERLAY_ICON, icon, ImageBlender.BLEND_OPAQUE, null);
170 } else if (!getModel().isValid()) {
171 icon = ImageBlender.blendIcons(Resources.NODE_INVALID_OVERLAY_ICON, icon, ImageBlender.BLEND_OPAQUE, null);
172 }
173 return icon;
174 }
175
176
177
178
179
180
181 public Settings getSettings() {
182 return this.settings;
183 }
184
185 public Object getUserObject() {
186 return model;
187 }
188
189
190
191
192
193
194 public void setFont(Font aFont) {
195 this.font = aFont;
196 }
197
198
199
200
201
202
203 public void setFontColor(Color aFontColor) {
204 this.fontColor = aFontColor;
205 }
206
207
208
209
210
211
212 public void setSettings(Settings aSettings) {
213 this.settings = aSettings;
214 }
215
216
217
218
219 public void add(MutableTreeNode aNewChild) {
220 super.add(aNewChild);
221
222 Collections.sort(this.children, nodeComparator);
223 }
224
225 public Enumeration children() {
226 loadChildren();
227 return super.children();
228 }
229
230
231
232
233 public void delete() {
234 if (LOG.isDebugEnabled()) {
235 LOG.debug("Deleting tree node: " + this.getName());
236 }
237 try {
238 if (!MessageUtil.confirmDelete(this.getMainFrame())) {
239 return;
240 }
241 GuiUtil.setBusyCursor(this.getMainFrame(), true);
242
243 HibernateUtil.beginTransaction();
244
245 if (getModel() instanceof Artist) {
246 LOG.debug("Do nothing with the Artist");
247 } else if (getModel() instanceof Disc) {
248 final Disc disc = (Disc)getModel();
249 final Artist artist = disc.getArtist();
250 artist.getDiscs().remove(disc);
251 } else if (getModel() instanceof Track) {
252 final Track track = (Track)getModel();
253 final Disc disc = track.getDisc();
254 disc.getTracks().remove(track);
255 } else {
256 throw new IllegalArgumentException("Not a valid tree node type.");
257 }
258 HibernateDao.delete(getModel());
259 HibernateUtil.commitTransaction();
260
261
262 this.getMainModule().refreshSelection(null, Resources.NODE_DELETED);
263
264 } catch (Exception ex) {
265 LOG.error("Error deleting artist.", ex);
266 } finally {
267 GuiUtil.setBusyCursor(this.getMainFrame(), false);
268 }
269 }
270
271
272
273
274 public boolean equals(Object obj) {
275 if (!(obj instanceof AbstractTreeNode)) {
276 return false;
277 }
278 if (this == obj) {
279 return true;
280 }
281 final AbstractTreeNode rhs = (AbstractTreeNode)obj;
282 final EqualsBuilder builder = new EqualsBuilder();
283 builder.append(parent, rhs.parent);
284 builder.append(model, rhs.model);
285 return builder.isEquals();
286 }
287
288
289
290
291 public int hashCode() {
292 return new HashCodeBuilder(17, 37).append(parent).append(model).toHashCode();
293 }
294
295
296
297
298 public String toString() {
299 return model.getName();
300 }
301
302
303
304
305
306
307 protected MainFrame getMainFrame() {
308 return (MainFrame)Application.getDefaultParentFrame();
309 }
310
311
312
313
314
315
316 protected MainModule getMainModule() {
317 return getMainFrame().getMainModule();
318 }
319
320 }