001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package test.check;
031:
032: import java.awt.BorderLayout;
033: import java.awt.Component;
034: import java.awt.event.ActionEvent;
035: import java.awt.event.ActionListener;
036: import java.io.File;
037: import java.util.*;
038:
039: import javax.swing.*;
040: import javax.swing.border.EmptyBorder;
041: import javax.swing.filechooser.FileSystemView;
042: import javax.swing.tree.TreeNode;
043:
044: import org.jvnet.lafwidget.animation.FadeConfigurationManager;
045: import org.jvnet.substance.SubstanceDefaultTreeCellRenderer;
046: import org.jvnet.substance.SubstanceLookAndFeel;
047:
048: import com.jgoodies.forms.builder.DefaultFormBuilder;
049: import com.jgoodies.forms.layout.FormLayout;
050:
051: /**
052: * Test application panel for testing {@link JTree} component and
053: * {@link SubstanceLookAndFeel#TREE_SMART_SCROLL_ANIMATION_KIND}.
054: *
055: * @author Kirill Grouchnikov
056: */
057: public class FileTreePanel extends ControllablePanel {
058: /**
059: * File system view.
060: */
061: protected static FileSystemView fsv = FileSystemView
062: .getFileSystemView();
063:
064: /**
065: * Renderer for the file tree.
066: *
067: * @author Kirill Grouchnikov
068: */
069: private static class FileTreeCellRenderer extends
070: SubstanceDefaultTreeCellRenderer {
071: /**
072: * Icon cache to speed the rendering.
073: */
074: private Map<String, Icon> iconCache = new HashMap<String, Icon>();
075:
076: /**
077: * Root name cache to speed the rendering.
078: */
079: private Map<File, String> rootNameCache = new HashMap<File, String>();
080:
081: /*
082: * (non-Javadoc)
083: *
084: * @see org.jvnet.substance.SubstanceDefaultTreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree,
085: * java.lang.Object, boolean, boolean, boolean, int, boolean)
086: */
087: @Override
088: public Component getTreeCellRendererComponent(JTree tree,
089: Object value, boolean sel, boolean expanded,
090: boolean leaf, int row, boolean hasFocus) {
091: FileTreeNode ftn = (FileTreeNode) value;
092: File file = ftn.file;
093: String filename = "";
094: if (file != null) {
095: if (ftn.isFileSystemRoot) {
096: // long start = System.currentTimeMillis();
097: filename = rootNameCache.get(file);
098: if (filename == null) {
099: filename = fsv.getSystemDisplayName(file);
100: rootNameCache.put(file, filename);
101: }
102: // long end = System.currentTimeMillis();
103: // System.out.println(filename + ":" + (end - start));
104: } else {
105: filename = file.getName();
106: }
107: }
108: JLabel result = (JLabel) super
109: .getTreeCellRendererComponent(tree, filename, sel,
110: expanded, leaf, row, hasFocus);
111: if (file != null) {
112: Icon icon = iconCache.get(filename);
113: if (icon == null) {
114: // System.out.println("Getting icon of " + filename);
115: icon = fsv.getSystemIcon(file);
116: iconCache.put(filename, icon);
117: }
118: result.setIcon(icon);
119: }
120: return result;
121: }
122: }
123:
124: /**
125: * A node in the file tree.
126: *
127: * @author Kirill Grouchnikov
128: */
129: private static class FileTreeNode implements TreeNode {
130: /**
131: * Node file.
132: */
133: private File file;
134:
135: /**
136: * Children of the node file.
137: */
138: private File[] children;
139:
140: /**
141: * Parent node.
142: */
143: private TreeNode parent;
144:
145: /**
146: * Indication whether this node corresponds to a file system root.
147: */
148: private boolean isFileSystemRoot;
149:
150: /**
151: * Creates a new file tree node.
152: *
153: * @param file
154: * Node file
155: * @param isFileSystemRoot
156: * Indicates whether the file is a file system root.
157: * @param parent
158: * Parent node.
159: */
160: public FileTreeNode(File file, boolean isFileSystemRoot,
161: TreeNode parent) {
162: this .file = file;
163: this .isFileSystemRoot = isFileSystemRoot;
164: this .parent = parent;
165: this .children = this .file.listFiles();
166: if (this .children == null)
167: this .children = new File[0];
168: }
169:
170: /**
171: * Creates a new file tree node.
172: *
173: * @param children
174: * Children files.
175: */
176: public FileTreeNode(File[] children) {
177: this .file = null;
178: this .parent = null;
179: this .children = children;
180: }
181:
182: /*
183: * (non-Javadoc)
184: *
185: * @see javax.swing.tree.TreeNode#children()
186: */
187: public Enumeration<?> children() {
188: final int elementCount = this .children.length;
189: return new Enumeration<File>() {
190: int count = 0;
191:
192: /*
193: * (non-Javadoc)
194: *
195: * @see java.util.Enumeration#hasMoreElements()
196: */
197: public boolean hasMoreElements() {
198: return count < elementCount;
199: }
200:
201: /*
202: * (non-Javadoc)
203: *
204: * @see java.util.Enumeration#nextElement()
205: */
206: public File nextElement() {
207: if (count < elementCount) {
208: return children[count++];
209: }
210: throw new NoSuchElementException(
211: "Vector Enumeration");
212: }
213: };
214:
215: }
216:
217: /*
218: * (non-Javadoc)
219: *
220: * @see javax.swing.tree.TreeNode#getAllowsChildren()
221: */
222: public boolean getAllowsChildren() {
223: return true;
224: }
225:
226: /*
227: * (non-Javadoc)
228: *
229: * @see javax.swing.tree.TreeNode#getChildAt(int)
230: */
231: public TreeNode getChildAt(int childIndex) {
232: return new FileTreeNode(this .children[childIndex],
233: this .parent == null, this );
234: }
235:
236: /*
237: * (non-Javadoc)
238: *
239: * @see javax.swing.tree.TreeNode#getChildCount()
240: */
241: public int getChildCount() {
242: return this .children.length;
243: }
244:
245: /*
246: * (non-Javadoc)
247: *
248: * @see javax.swing.tree.TreeNode#getIndex(javax.swing.tree.TreeNode)
249: */
250: public int getIndex(TreeNode node) {
251: FileTreeNode ftn = (FileTreeNode) node;
252: for (int i = 0; i < this .children.length; i++) {
253: if (ftn.file.equals(this .children[i]))
254: return i;
255: }
256: return -1;
257: }
258:
259: /*
260: * (non-Javadoc)
261: *
262: * @see javax.swing.tree.TreeNode#getParent()
263: */
264: public TreeNode getParent() {
265: return this .parent;
266: }
267:
268: /*
269: * (non-Javadoc)
270: *
271: * @see javax.swing.tree.TreeNode#isLeaf()
272: */
273: public boolean isLeaf() {
274: return (this .getChildCount() == 0);
275: }
276: }
277:
278: /**
279: * The file tree.
280: */
281: private JTree tree;
282:
283: /**
284: * Creates the file tree panel.
285: */
286: public FileTreePanel() {
287: this .setLayout(new BorderLayout());
288:
289: File[] roots = File.listRoots();
290: FileTreeNode rootTreeNode = new FileTreeNode(roots);
291: this .tree = new JTree(rootTreeNode);
292: this .tree.setCellRenderer(new FileTreeCellRenderer());
293: this .tree.setRootVisible(false);
294: final JScrollPane jsp = new JScrollPane(this .tree);
295: jsp.setBorder(new EmptyBorder(0, 0, 0, 0));
296: this .add(jsp, BorderLayout.CENTER);
297:
298: FormLayout lm = new FormLayout(
299: "right:pref, 4dlu, fill:pref:grow", "");
300: DefaultFormBuilder builder = new DefaultFormBuilder(lm,
301: new ScrollablePanel());
302: builder.appendSeparator("General");
303:
304: final JCheckBox isEnabled = new JCheckBox("is enabled");
305: isEnabled.setSelected(tree.isEnabled());
306: isEnabled.addActionListener(new ActionListener() {
307: public void actionPerformed(ActionEvent e) {
308: tree.setEnabled(isEnabled.isSelected());
309: }
310: });
311: builder.append("Enabled", isEnabled);
312:
313: final JCheckBox watermarkBleed = new JCheckBox("is bleeding");
314: watermarkBleed.addActionListener(new ActionListener() {
315: public void actionPerformed(ActionEvent e) {
316: tree.putClientProperty(
317: SubstanceLookAndFeel.WATERMARK_TO_BLEED,
318: Boolean.valueOf(watermarkBleed.isSelected()));
319: jsp.putClientProperty(
320: SubstanceLookAndFeel.WATERMARK_TO_BLEED,
321: Boolean.valueOf(watermarkBleed.isSelected()));
322: tree.repaint();
323: }
324: });
325: builder.append("Watermark", watermarkBleed);
326:
327: final JCheckBox cbTreeDecorations = new JCheckBox(
328: "animate tree decorations");
329: cbTreeDecorations.addActionListener(new ActionListener() {
330: public void actionPerformed(ActionEvent e) {
331: if (cbTreeDecorations.isSelected()) {
332: FadeConfigurationManager
333: .getInstance()
334: .allowFades(
335: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
336: tree);
337: } else {
338: FadeConfigurationManager
339: .getInstance()
340: .disallowFades(
341: SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
342: tree);
343: }
344: tree.repaint();
345: }
346: });
347: builder.append("Decorations", cbTreeDecorations);
348:
349: final JCheckBox cbTreeSmartScroll = new JCheckBox(
350: "smart tree scroll");
351: cbTreeSmartScroll.addActionListener(new ActionListener() {
352: public void actionPerformed(ActionEvent e) {
353: if (cbTreeSmartScroll.isSelected()) {
354: FadeConfigurationManager
355: .getInstance()
356: .allowFades(
357: SubstanceLookAndFeel.TREE_SMART_SCROLL_ANIMATION_KIND,
358: tree);
359: } else {
360: FadeConfigurationManager
361: .getInstance()
362: .disallowFades(
363: SubstanceLookAndFeel.TREE_SMART_SCROLL_ANIMATION_KIND,
364: tree);
365: }
366: tree.repaint();
367: }
368: });
369: builder.append("Decorations", cbTreeSmartScroll);
370:
371: this.controlPanel = builder.getPanel();
372: }
373: }
|