001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019: package org.openharmonise.him.editors.report.swing;
020:
021: import java.awt.*;
022: import java.awt.event.*;
023: import java.util.*;
024: import java.util.List;
025:
026: import javax.swing.*;
027: import javax.swing.event.*;
028: import javax.swing.tree.*;
029:
030: import org.openharmonise.him.*;
031: import org.openharmonise.him.swing.resourcetree.*;
032: import org.openharmonise.him.swing.resourcetree.formresourcetree.*;
033: import org.openharmonise.swing.FontManager;
034: import org.openharmonise.vfs.*;
035: import org.openharmonise.vfs.gui.*;
036: import org.openharmonise.vfs.servers.ServerList;
037:
038: /**
039: * A component, much like the {@link javax.swing.JComboBox}, which displays
040: * a field, button and drop down. However in this case the drop down
041: * contains a resoruce tree from which the value(s) are selected.
042: *
043: * @author Matthew Large
044: * @version $Revision: 1.2 $
045: *
046: */
047: public class JComboTree extends JPanel implements ActionListener,
048: LayoutManager, FormResourceTreeListener, MouseListener,
049: WindowFocusListener, FocusListener {
050:
051: /**
052: * Tree selection mode.
053: *
054: * @see TreeSelectionModel
055: */
056: private int m_nSelectionMode = -1;
057:
058: /**
059: * Label do display value.
060: */
061: protected JLabel m_value = null;
062:
063: /**
064: * Open drop down button.
065: */
066: private JToggleButton m_button = null;
067:
068: /**
069: * Screen X position.
070: */
071: private int m_nScreenPosX = 0;
072:
073: /**
074: * Screen Y position.
075: */
076: private int m_nScreenPosY = 0;
077:
078: /**
079: * Window for drop down.
080: */
081: protected JWindow m_nWindow = null;
082:
083: /**
084: * List of paths which are the roots for the tree.
085: */
086: private ArrayList m_aCollectionPaths = new ArrayList();
087:
088: /**
089: * Action command for component.
090: */
091: private String m_sActionCommand = null;
092:
093: /**
094: * List of {@link ActionListener} objects.
095: */
096: private ArrayList m_aActionListeners = new ArrayList();
097:
098: /**
099: * true if leaf nodes are to be displayed.
100: */
101: private boolean m_bShowLeafNodes = true;
102:
103: /**
104: * true if only leaf nodes can be selected.
105: */
106: private boolean m_bSelectedLeafOnly = false;
107:
108: private boolean m_bShowApprovedOnly = false;
109:
110: /**
111: * Selected highlight colour.
112: */
113: private Color m_selectedColor = new Color(173, 169, 143);
114:
115: /**
116: * List of path values.
117: */
118: private List m_paths = null;
119:
120: /**
121: * true if the user should be able to clear the value(s).
122: */
123: private boolean m_bAllowClear = false;
124:
125: /**
126: * true if the tree is populated.
127: */
128: private boolean m_bIsTreePopulated = false;
129:
130: /**
131: * Resource tree.
132: */
133: private FormResourceTree m_tree;
134:
135: private AbstractResourceFilter m_filter = new BasicResourceFilter();
136:
137: private int m_nWidth = 150;
138: private int m_nHeight = 20;
139:
140: private boolean m_bHideReentrantStop = false;
141:
142: /**
143: * Constructs a new combo tree component.
144: *
145: * @param sPath Path value
146: */
147: public JComboTree(String sPath) {
148: super ();
149: m_paths = new ArrayList();
150:
151: if (sPath != null) {
152: m_paths.add(sPath);
153: }
154: this .setup();
155: }
156:
157: /**
158: *
159: */
160: public JComboTree() {
161: super ();
162: this .setup();
163: }
164:
165: /**
166: * Configures this component.
167: *
168: */
169: protected void setup() {
170: this .setLayout(this );
171: this .setBackground(Color.WHITE);
172:
173: this .m_value = new JLabel();
174: this .m_value.setBackground(Color.WHITE);
175: this .m_value.setBorder(BorderFactory.createEtchedBorder());
176: this .m_value.setFont(FontManager.getInstance().getFont(
177: FontManager.FONT_RESOURCE_TITLE));
178: this .add(m_value);
179:
180: this .m_button = new JToggleButton("V");
181: this .m_button.addActionListener(this );
182: this .add(this .m_button);
183: }
184:
185: /**
186: * Returns the value label.
187: *
188: * @return Value label
189: */
190: public JLabel getLabel() {
191: return m_value;
192: }
193:
194: /**
195: * Returns the path value. If there is more than one then the first
196: * is returned.
197: *
198: * @return Path value, or null if there isn't one
199: */
200: public String getPath() {
201: String sPath = null;
202:
203: if (m_paths != null && m_paths.size() > 0) {
204: sPath = (String) m_paths.get(0);
205: }
206:
207: return sPath;
208: }
209:
210: /**
211: * Returns a list of path values.
212: *
213: * @return List of path values
214: */
215: public List getPaths() {
216: return new ArrayList(m_paths);
217: }
218:
219: /* (non-Javadoc)
220: * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
221: */
222: public void actionPerformed(ActionEvent arg0) {
223: if (this .m_nWindow == null) {
224: Component comp = this .getParent();
225: while (comp != null
226: && !(comp instanceof JDialog || comp instanceof JFrame)) {
227: comp = comp.getParent();
228: }
229: this .m_nWindow = new JWindow(((Window) comp));
230: m_nWindow.addWindowFocusListener(this );
231:
232: JPanel panel = new JPanel();
233: panel.addFocusListener(this );
234: panel
235: .setBorder(BorderFactory
236: .createLineBorder(Color.BLACK));
237: panel.setBackground(Color.WHITE);
238: panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
239:
240: String fontName = "Dialog";
241: int fontSize = 11;
242: Font font = new Font(fontName, Font.PLAIN, fontSize);
243:
244: if (this .m_bAllowClear) {
245: JTextField clearLabel = new JTextField("Clear value");
246: clearLabel.setEditable(false);
247: clearLabel.setBorder(BorderFactory
248: .createLineBorder(Color.BLACK));
249: clearLabel.setFont(font);
250: clearLabel.addMouseListener(this );
251: panel.add(clearLabel);
252: clearLabel.setPreferredSize(new Dimension(220, 15));
253: clearLabel.setSize(new Dimension(220, 15));
254: }
255:
256: List aPaths = new ArrayList();
257: if (m_paths != null && m_paths.size() > 0) {
258: aPaths = new ArrayList(m_paths);
259: }
260: m_tree = new FormResourceTree(aPaths);
261: m_tree.setResourceFilter(getResourceTreeFilter());
262: m_tree.addFocusListener(this );
263: if (m_nSelectionMode >= 0) {
264: m_tree.setSelectionMode(m_nSelectionMode);
265: if (m_nSelectionMode > 1) {
266: m_tree.setIsMultiSelect(true);
267: } else {
268: m_tree.setIsMultiSelect(false);
269: }
270: } else {
271: m_tree.setIsMultiSelect(false);
272: }
273: m_tree.setBorder(BorderFactory
274: .createLineBorder(Color.BLACK));
275: m_tree.setShowLeafNodes(m_bShowLeafNodes);
276: m_tree.addFormResourceTreeListener(this );
277: if (m_bShowApprovedOnly) {
278: m_tree.setShowApprovedOnly(true);
279: }
280: AbstractVirtualFileSystem vfs = ServerList.getInstance()
281: .getHarmoniseServer().getVFS();
282: Iterator itor = this .m_aCollectionPaths.iterator();
283: while (itor.hasNext()) {
284: String sColPath = (String) itor.next();
285: VirtualFile vfDir = vfs.getVirtualFile(sColPath)
286: .getResource();
287: if (vfDir != null) {
288: m_tree.addCollection(vfDir);
289: }
290: }
291:
292: this .m_nWindow.getContentPane().setLayout(
293: new BorderLayout());
294: panel.add(m_tree);
295: this .m_nWindow.getContentPane().add(panel);
296: m_bIsTreePopulated = true;
297:
298: addAncestorListener(new AncestorListener() {
299: public void ancestorAdded(AncestorEvent event) {
300: if (event.getSource() != this
301: && event.getSource() != getButton())
302: hidePopup();
303: }
304:
305: public void ancestorRemoved(AncestorEvent event) {
306: if (event.getSource() != this
307: && event.getSource() != getButton())
308: hidePopup();
309: }
310:
311: public void ancestorMoved(AncestorEvent event) {
312: if (event.getSource() != this
313: && event.getSource() != getButton())
314: hidePopup();
315: }
316: });
317:
318: }
319: if (!this .m_bHideReentrantStop && this .m_button.isSelected()
320: && !this .m_nWindow.isVisible()) {
321: this .m_nWindow.setSize(200, 300);
322: this .m_nScreenPosX = this .getLocationOnScreen().x;
323: this .m_nScreenPosY = this .getLocationOnScreen().y;
324: this .m_nWindow.setLocation(this .m_nScreenPosX,
325: this .m_nScreenPosY + 20);
326: this .m_nWindow.toFront();
327: this .m_nWindow.setVisible(true);
328:
329: } else {
330: this .m_nWindow.setVisible(false);
331: this .m_button.setSelected(false);
332: this .revalidate();
333: this .repaint();
334: }
335: this .m_bHideReentrantStop = false;
336: }
337:
338: protected JToggleButton getButton() {
339: return this .m_button;
340: }
341:
342: /**
343: *
344: */
345: protected void hidePopup() {
346: if (this .m_nWindow != null) {
347: this .m_bHideReentrantStop = true;
348: this .m_nWindow.setVisible(false);
349: this .m_button.setSelected(false);
350: this .invalidate();
351: }
352: }
353:
354: public void setShowApprovedOnly(boolean show) {
355: m_bShowApprovedOnly = show;
356: }
357:
358: /**
359: * Sets whether or not to show leaf nodes.
360: *
361: * @param bShowLeafNodes true if leaf nodes are to be shown.
362: */
363: public void setShowLeafNodes(boolean bShowLeafNodes) {
364: this .m_bShowLeafNodes = bShowLeafNodes;
365: }
366:
367: /**
368: * Sets whether only leaf nodes should be selectable.
369: *
370: * @param bSelectLeafOnly true to set only leaf nodes as selectable
371: */
372: public void setSelectedLeafOnly(boolean bSelectLeafOnly) {
373: this .m_bSelectedLeafOnly = bSelectLeafOnly;
374: }
375:
376: /**
377: * Sets whether or not the user should be able to clear the
378: * value(s).
379: *
380: * @param bAllowClear true to allow the user to clear the value(s)
381: */
382: public void setAllowClear(boolean bAllowClear) {
383: }
384:
385: /* (non-Javadoc)
386: * @see java.awt.Component#paint(java.awt.Graphics)
387: */
388: public void paint(Graphics arg0) {
389: super .paint(arg0);
390: if (this .m_nWindow != null
391: && this .m_nWindow.isVisible()
392: && (this .m_nScreenPosX != this .getLocationOnScreen().x || this .m_nScreenPosY != this
393: .getLocationOnScreen().y)) {
394: this .m_nScreenPosX = this .getLocationOnScreen().x;
395: this .m_nScreenPosY = this .getLocationOnScreen().y;
396: this .m_nWindow.setLocation(this .m_nScreenPosX,
397: this .m_nScreenPosY + 20);
398: this .m_nWindow.toFront();
399: this .m_nWindow.repaint();
400: }
401: }
402:
403: /* (non-Javadoc)
404: * @see java.awt.Component#doLayout()
405: */
406: public void doLayout() {
407: super .doLayout();
408: if (this .m_nWindow != null
409: && this .m_nWindow.isVisible()
410: && (this .m_nScreenPosX != this .getLocationOnScreen().x || this .m_nScreenPosY != this
411: .getLocationOnScreen().y)) {
412: this .m_nScreenPosX = this .getLocationOnScreen().x;
413: this .m_nScreenPosY = this .getLocationOnScreen().y;
414: this .m_nWindow.setLocation(this .m_nScreenPosX,
415: this .m_nScreenPosY + 20);
416: this .m_nWindow.toFront();
417: this .m_nWindow.repaint();
418: }
419: }
420:
421: /* (non-Javadoc)
422: * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
423: */
424: public void layoutContainer(Container arg0) {
425: this .m_value.setSize(m_nWidth - 20, m_nHeight);
426: this .m_value.setLocation(0, 0);
427:
428: this .m_button.setSize(20, m_nHeight);
429: this .m_button.setLocation(m_nWidth - 20, 0);
430: }
431:
432: /* (non-Javadoc)
433: * @see java.awt.Component#setSize(java.awt.Dimension)
434: */
435: public void setSize(Dimension dim) {
436: this .setSize(dim.width, dim.height);
437: }
438:
439: /* (non-Javadoc)
440: * @see java.awt.Component#setSize(int, int)
441: */
442: public void setSize(int nWidth, int nHeight) {
443: super .setSize(nWidth, nHeight);
444: this .m_nWidth = nWidth;
445: this .m_nHeight = nHeight;
446: }
447:
448: /* (non-Javadoc)
449: * @see java.awt.Component#getSize()
450: */
451: public Dimension getSize() {
452: return new Dimension(this .m_nWidth, this .m_nHeight);
453: }
454:
455: /**
456: * Adds a list of root collection paths for the tree.
457: *
458: * @param paths List of full paths
459: */
460: public void addCollectionPaths(List paths) {
461: this .m_aCollectionPaths.addAll(paths);
462: }
463:
464: /**
465: * Adds a root colllection path for the tree.
466: *
467: * @param sPath Full path
468: */
469: public void addCollectionPath(String sPath) {
470: this .m_aCollectionPaths.add(sPath);
471: }
472:
473: /**
474: * Removes a root collection path from the tree.
475: *
476: * @param sPath Full path
477: */
478: public void removeCollectionPath(String sPath) {
479: this .m_aCollectionPaths.remove(sPath);
480: }
481:
482: /**
483: * Returns a list of the root collection paths for the tree.
484: *
485: * @return List of full paths
486: */
487: public List getCollectionPaths() {
488: return (List) this .m_aCollectionPaths.clone();
489: }
490:
491: /* (non-Javadoc)
492: * @see java.awt.Component#getPreferredSize()
493: */
494: public Dimension getPreferredSize() {
495: return new Dimension(170, 20);
496: }
497:
498: /**
499: * @param arg0
500: */
501: private JComboTree(boolean arg0) {
502: super (arg0);
503: }
504:
505: /**
506: * @param arg0
507: */
508: private JComboTree(LayoutManager arg0) {
509: super (arg0);
510: }
511:
512: /**
513: * @param arg0
514: * @param arg1
515: */
516: private JComboTree(LayoutManager arg0, boolean arg1) {
517: super (arg0, arg1);
518: }
519:
520: /* (non-Javadoc)
521: * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
522: */
523: public void removeLayoutComponent(Component arg0) {
524: }
525:
526: /* (non-Javadoc)
527: * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
528: */
529: public void addLayoutComponent(String arg0, Component arg1) {
530: }
531:
532: /* (non-Javadoc)
533: * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
534: */
535: public Dimension minimumLayoutSize(Container arg0) {
536: return this .getPreferredSize();
537: }
538:
539: /* (non-Javadoc)
540: * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
541: */
542: public Dimension preferredLayoutSize(Container arg0) {
543: return this .getPreferredSize();
544: }
545:
546: /**
547: * Adds an action listener.
548: *
549: * @param listener Listener to add
550: */
551: public void addActionListener(ActionListener listener) {
552: this .m_aActionListeners.add(listener);
553: }
554:
555: /**
556: * Removes an action listener.
557: *
558: * @param listener Listener to remove
559: */
560: public void removeActionListener(ActionListener listener) {
561: this .m_aActionListeners.remove(listener);
562: }
563:
564: /**
565: * Fires an action event to all the action listeners.
566: *
567: */
568: private void fireActionEvent() {
569: ActionEvent ae = new ActionEvent(this , 0, this .m_sActionCommand);
570: Iterator itor = this .m_aActionListeners.iterator();
571: while (itor.hasNext()) {
572: ActionListener listener = (ActionListener) itor.next();
573: listener.actionPerformed(ae);
574: }
575: }
576:
577: /**
578: * Sets the action command for this component.
579: *
580: * @param sActionCommand Action command
581: */
582: public void setActionCommand(String sActionCommand) {
583: this .m_sActionCommand = sActionCommand;
584: }
585:
586: /**
587: * Clears the value(s) and hides the drop down.
588: *
589: */
590: public void clear() {
591: if (this .m_paths != null) {
592: this .m_paths.clear();
593: }
594: this .m_value.setIcon(IconManager.getInstance().getIcon(
595: "16-blank.gif"));
596: this .m_value.setText("");
597: this .revalidate();
598: this .m_nWindow.setVisible(false);
599: this .m_tree.clearSelection();
600: }
601:
602: /* (non-Javadoc)
603: * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
604: */
605: public void mouseClicked(MouseEvent me) {
606: clear();
607: }
608:
609: /**
610: * Addsa path value.
611: *
612: * @param vfs Virtual file system
613: * @param sPath Full path
614: */
615: public void addPath(AbstractVirtualFileSystem vfs, String sPath) {
616: if (m_paths == null) {
617: m_paths = new ArrayList();
618: }
619:
620: m_paths.add(sPath);
621:
622: setPaths(vfs, m_paths);
623: }
624:
625: /**
626: * Removes a path value.
627: *
628: * @param vfs Virtual file system
629: * @param sPath Full path
630: */
631: public void removePath(AbstractVirtualFileSystem vfs, String sPath) {
632: if (m_paths != null) {
633: if (m_paths.contains(sPath)) {
634: m_paths.remove(sPath);
635: setPaths(vfs, m_paths);
636: }
637: }
638: }
639:
640: /**
641: * Sets the path value.
642: *
643: * @param vfs Virtual file system
644: * @param sPath full path
645: */
646: public void setPath(AbstractVirtualFileSystem vfs, String sPath) {
647: ArrayList list = new ArrayList();
648: list.add(sPath);
649:
650: setPaths(vfs, list);
651: }
652:
653: /**
654: * Sets a list of paths.
655: *
656: * @param vfs Virtual file system
657: * @param paths List of full paths
658: */
659: public void setPaths(AbstractVirtualFileSystem vfs, List paths) {
660: VirtualFileSystemView vfsView = vfs.getVirtualFileSystemView();
661: Iterator iter = paths.iterator();
662: StringBuffer sbuf = new StringBuffer();
663: Icon icon = null;
664: m_paths = new ArrayList();
665: while (iter.hasNext()) {
666: String sPath = (String) iter.next();
667:
668: VirtualFile vfFile = vfs.getVirtualFile(sPath)
669: .getResource();
670: if (m_value != null
671: && (!this .m_bSelectedLeafOnly || (this .m_bSelectedLeafOnly && !vfFile
672: .isDirectory()))) {
673: m_paths.add(sPath);
674:
675: icon = vfsView.getIcon(vfFile);
676: if (sbuf.length() > 0) {
677: sbuf.append(";");
678: }
679: sbuf.append(vfsView.getDisplayName(vfFile));
680: }
681: }
682: this .m_value.setIcon(icon);
683: this .m_value.setText(sbuf.toString());
684: }
685:
686: /* (non-Javadoc)
687: * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
688: */
689: public void mouseEntered(MouseEvent arg0) {
690:
691: }
692:
693: /* (non-Javadoc)
694: * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
695: */
696: public void mouseExited(MouseEvent arg0) {
697:
698: }
699:
700: /* (non-Javadoc)
701: * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
702: */
703: public void mousePressed(MouseEvent arg0) {
704:
705: }
706:
707: /* (non-Javadoc)
708: * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
709: */
710: public void mouseReleased(MouseEvent arg0) {
711:
712: }
713:
714: /**
715: * Sets the tree selection mode.
716: *
717: * @param nMode Tree selection mode
718: */
719: public void setSelectionMode(int nMode) {
720: m_nSelectionMode = nMode;
721: }
722:
723: /* (non-Javadoc)
724: * @see com.simulacramedia.contentmanager.swing.resourcetree.formresourcetree.FormResourceTreeListener#pathValuesChanged(java.util.List)
725: */
726: public void pathValuesChanged(List pathValues) {
727: if (m_bIsTreePopulated == true) {
728:
729: setPaths(ServerList.getInstance().getHarmoniseServer()
730: .getVFS(), m_tree.getPathValues());
731:
732: this .revalidate();
733: if (this .m_nWindow != null
734: && (m_nSelectionMode == -1 || m_nSelectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION)) {
735: this .m_nWindow.setVisible(false);
736: }
737: this .fireActionEvent();
738: }
739: }
740:
741: /* (non-Javadoc)
742: * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
743: */
744: public void focusGained(FocusEvent arg0) {
745: }
746:
747: /* (non-Javadoc)
748: * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
749: */
750: public void focusLost(FocusEvent arg0) {
751: this .hidePopup();
752: }
753:
754: /* (non-Javadoc)
755: * @see java.awt.event.WindowFocusListener#windowGainedFocus(java.awt.event.WindowEvent)
756: */
757: public void windowGainedFocus(WindowEvent arg0) {
758: }
759:
760: /* (non-Javadoc)
761: * @see java.awt.event.WindowFocusListener#windowLostFocus(java.awt.event.WindowEvent)
762: */
763: public void windowLostFocus(WindowEvent arg0) {
764: this .hidePopup();
765: }
766:
767: public void setResourceTreeFilter(AbstractResourceFilter filter) {
768: m_filter = filter;
769: }
770:
771: protected AbstractResourceFilter getResourceTreeFilter() {
772: return m_filter;
773: }
774:
775: public void setScopeEnabled(boolean isEnabled) {
776: this.m_value.setEnabled(isEnabled);
777: this.m_button.setEnabled(isEnabled);
778: }
779: }
|