001: package com.xoetrope.carousel.visualizer;
002:
003: import java.awt.BorderLayout;
004: import java.awt.datatransfer.DataFlavor;
005: import java.awt.datatransfer.Transferable;
006: import java.awt.datatransfer.UnsupportedFlavorException;
007: import java.awt.event.MouseEvent;
008: import java.awt.event.MouseListener;
009: import java.awt.event.MouseMotionListener;
010: import java.io.File;
011: import java.io.IOException;
012: import java.net.URL;
013: import java.net.URLClassLoader;
014: import java.sql.Connection;
015: import java.util.Hashtable;
016: import java.util.StringTokenizer;
017: import java.util.Vector;
018: import java.util.concurrent.Semaphore;
019:
020: import javax.swing.JComponent;
021: import javax.swing.JFileChooser;
022: import javax.swing.JOptionPane;
023: import javax.swing.JPanel;
024: import javax.swing.JScrollPane;
025: import javax.swing.JTree;
026: import javax.swing.SwingUtilities;
027: import javax.swing.TransferHandler;
028: import javax.swing.border.EmptyBorder;
029: import javax.swing.event.TreeExpansionEvent;
030: import javax.swing.event.TreeSelectionEvent;
031: import javax.swing.event.TreeSelectionListener;
032: import javax.swing.event.TreeWillExpandListener;
033: import javax.swing.filechooser.FileFilter;
034: import javax.swing.tree.DefaultMutableTreeNode;
035: import javax.swing.tree.DefaultTreeModel;
036: import javax.swing.tree.ExpandVetoException;
037: import javax.swing.tree.TreeNode;
038: import javax.swing.tree.TreePath;
039:
040: import net.xoetrope.editor.project.XEditorProject;
041: import net.xoetrope.editor.project.XEditorProjectManager;
042: import net.xoetrope.editor.project.pages.BindingTransferHandler;
043: import net.xoetrope.editor.project.pages.IEditorUtility;
044: import net.xoetrope.editor.project.pages.events.ModelListener;
045: import net.xoetrope.xui.data.XBaseModel;
046: import net.xoetrope.xui.data.XModel;
047:
048: import com.xoetrope.data.pojo.XPojoModelVis;
049:
050: /**
051: * Panel which contains the JTree representation of the XModel. The JTree is
052: * contained within a scrollpane. The model is updated as data items are added
053: * from the XLib editor. Whenever a component is seleted the setActiveComponents
054: * fuction is called with a Vector of type XComponentSizer so that the data node
055: * for the component can be selected. Double clicking a node will cause the
056: * currently selected components data property to be set.
057: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
058: * the GNU Public License (GPL), please see license.txt for more details. If
059: * you make commercial use of this software you must purchase a commercial
060: * license from Xoetrope.</p>
061: * <p> $Revision: 1.14 $</p>
062: */
063: public class ModelVisualiserTree extends JPanel implements
064: TreeSelectionListener, MouseListener, TreeWillExpandListener,
065: ModelListener {
066: private DefaultMutableTreeNode topNode;
067: private JTree jTreeComp;
068: private JScrollPane scroller;
069: private boolean listenerChanging = false;
070: private ModelTreeListener modelTreeListener;
071: private XModel rootModel;
072: private XEditorProject currentProject;
073: private ModelVisualiserPanel modelVisualiserPanel;
074: private Hashtable modelNodes;
075: private TreeExpanderT treeExpander;
076: private JFileChooser dbDriverChooser;
077:
078: /**
079: * Setup a BorderLayout manager. Call the function to create the tree with no
080: * selection.
081: */
082: public ModelVisualiserTree(ModelVisualiserPanel mvp) {
083: treeExpander = new TreeExpanderT();
084: modelNodes = new Hashtable();
085: modelVisualiserPanel = mvp;
086: currentProject = (XEditorProject) XEditorProjectManager
087: .getCurrentProject();
088: setLayout(new BorderLayout());
089: createTreeComp("");
090: }
091:
092: public String getModelPath(XModel model) {
093: if (model == null)
094: return null;
095: if (model instanceof XPojoModelVis) {
096: String path = "";
097: for (; model != null; model = model.getParent()) {
098: String modelId = "";
099: if (model instanceof XPojoModelVis) {
100: modelId = ((XPojoModelVis) model).getCaption();
101: int idx = modelId.lastIndexOf(": ");
102: if (idx >= 0)
103: modelId = modelId.substring(0, idx);
104: } else {
105: modelId = model.getId();
106: }
107: if (modelId != null) {
108: path = ("/" + modelId + path);
109: }
110: }
111: if (path.charAt(0) == '/')
112: path = path.substring(1);
113: if (path.startsWith("base/")) // tmp
114: path = path.substring(5);
115: return path;
116: } else {
117: return model.getId();
118: }
119: }
120:
121: public void addTreeSelectionListener(TreeSelectionListener l) {
122: jTreeComp.addTreeSelectionListener(l);
123: }
124:
125: public void removeTreeSelectionListener(TreeSelectionListener l) {
126: jTreeComp.removeTreeSelectionListener(l);
127: }
128:
129: // public void removeTreeSelectionListener( TreeSelectionListener l ) {
130: // jTreeComp.removeTreeSelectionListener( l );
131: // }
132:
133: public void addMouseListener(MouseListener l) {
134: jTreeComp.addMouseListener(l);
135: }
136:
137: public void removeMouseListener(MouseListener l) {
138: jTreeComp.removeMouseListener(l);
139: }
140:
141: public TreePath getSelectionPath() {
142: return jTreeComp.getSelectionPath();
143: }
144:
145: /**
146: * Set the root mode node displayed by this visualizer
147: * @param root the root of the node hierarchy
148: */
149: public void setRootModel(XModel root) {
150: rootModel = root;
151: }
152:
153: public void addMessageNode(String message) {
154: topNode.removeAllChildren();
155: DefaultMutableTreeNode root = new DefaultMutableTreeNode(
156: message);
157: topNode.add(root);
158: expandRoot();
159: }
160:
161: /**
162: * Reconstruct the tree. This is called when the model has been updated.
163: */
164: public void refresh() {
165: createTreeComp("");
166: }
167:
168: /**
169: * This is called when the model has beed updated from the KalIDEoscope
170: * editor.
171: */
172: public void modelChanged() {
173: refresh();
174: }
175:
176: /**
177: * If the tree already exists remove it from the panel. Get a reference to the
178: * XModel base node. Contruct a new JTree and call the createTree function
179: * with the selected parameter.
180: * @param selected the path to the seleted XModel node
181: */
182: public void createTreeComp(String selected) {
183: if (scroller != null)
184: remove(scroller);
185:
186: topNode = new DefaultMutableTreeNode("Data");
187: jTreeComp = new JTree(topNode);
188:
189: jTreeComp.setDragEnabled(true);
190: jTreeComp.setTransferHandler(new TreeNodeTransferHandler());
191:
192: TreeNodeMouseListener mouseListener = new TreeNodeMouseListener();
193: jTreeComp.addMouseListener(mouseListener);
194: jTreeComp.addMouseMotionListener(mouseListener);
195:
196: jTreeComp.setCellRenderer(new ModelVisualiserTreeCellRenderer(
197: ModelVisualiserTreeCellRenderer.AMEND_SELECT));
198: //jTreeComp.setFont( XEditorDefaults.defaultFont );
199: jTreeComp.setScrollsOnExpand(true);
200: createTree(selected);
201: jTreeComp.addTreeSelectionListener(this );
202: jTreeComp.addMouseListener(this );
203:
204: scroller = new JScrollPane(jTreeComp);
205: scroller.setBorder(new EmptyBorder(0, 0, 0, 0));
206: jTreeComp.setBorder(new EmptyBorder(0, 0, 0, 0));
207: jTreeComp.setRowHeight(20);
208: add(scroller, BorderLayout.CENTER);
209:
210: doLayout();
211: repaint();
212:
213: scroller.doLayout();
214: scroller.repaint();
215: }
216:
217: public void setModelTreeListner(ModelTreeListener mtl) {
218: modelTreeListener = mtl;
219: }
220:
221: /**
222: * Remove all chidren from the topNode variable. Call createTreeNodes with the
223: * base XModel and the parent node. This in turn calls the addNode function
224: * recursively until all XModel children have been processed. Expand the root
225: * node by default.
226: * @param selected
227: * @return
228: */
229: private DefaultMutableTreeNode createTree(String selected) {
230: topNode.removeAllChildren();
231: createTreeNodes(rootModel, topNode);
232: expandRoot();
233: return topNode;
234: }
235:
236: /**
237: * Loop all of the topNode children calling addNode.
238: * @param model the base XModel
239: * @param topNode the parent node of the JTree
240: */
241: void createTreeNodes(XModel model, DefaultMutableTreeNode topNode) {
242: if (model != null) {
243: int numChildren = model.getNumChildren();
244: for (int i = 0; i < numChildren; i++)
245: addNode(model.get(i), topNode);
246: }
247: }
248:
249: /**
250: * Create a new child node to be added to the parentNode parameter.
251: * @param model the XModel whose name will appear in the new treenode. This
252: * XModel's children is in turn passed to this function recursively building
253: * up the tree.
254: * @param parentNode the parent tree node.
255: */
256: void addNode(XModel model, DefaultMutableTreeNode parentNode) {
257: String text = "err: ";
258: if (XModelVisualizerFactory.isDbTableModel(model)) {
259: text = model.getId() + ": ";
260: } else if (XModelVisualizerFactory.isDbRowModel(model)) {
261: text = model.getId() + ": ";
262: } else if (XModelVisualizerFactory.isDbFieldModel(model)) {
263: Object val = model.get();
264: if (val == null)
265: val = "NULL";
266: text = val.toString() + ": ";
267: } else if (XModelVisualizerFactory.isPojoModel(model)) {
268: text = ((TreeNodeCaption) model).getCaption();
269: } else if (model instanceof VisualiserDebuggerModel) {
270: String id = model.getId();
271: Object value = ((VisualiserDebuggerModel) model)
272: .getAttribValueAsString(XBaseModel.VALUE_ATTRIBUTE);
273: text = stripQuotes(id) + ": ";
274: if ((value != null) && (!value.equals("null")))
275: text += value.toString();
276: } else if (model != null) {
277: String id = model.getId();
278: Object value = model.get();
279: text = stripQuotes(id) + ": ";
280: if ((value != null) && (!value.equals("null")))
281: text += value.toString();
282: }
283:
284: DefaultMutableTreeNode root = new XDefaultMutableTreeNode(text,
285: model);
286: parentNode.add(root);
287: }
288:
289: /**
290: * Invoked whenever a node in the tree is about to be expanded.
291: */
292: public void treeWillExpand(TreeExpansionEvent event)
293: throws ExpandVetoException {
294: }
295:
296: /**
297: * Invoked whenever a node in the tree is about to be collapsed.
298: */
299: public void treeWillCollapse(TreeExpansionEvent event)
300: throws ExpandVetoException {
301: }
302:
303: public void valueChanged(TreeSelectionEvent evt) {
304: }
305:
306: /**
307: * Get the path of the selected treenode by looping the selected path array
308: * and placing a '/' between each item
309: * @return the path to the selected XModel
310: */
311: String getTreePath() {
312: TreePath selectedPath = jTreeComp.getSelectionPath();
313: return pathToString(selectedPath);
314: }
315:
316: String pathToString(TreePath treePath) {
317: String modelName = null;
318: if (treePath != null) {
319: Object path[] = treePath.getPath();
320: modelName = "";
321: for (int i = 1; i < path.length; i++) {
322: modelName += "/" + path[i].toString();
323: }
324: }
325: if (modelName == null)
326: return "";
327: else if (modelName.trim().compareTo("") != 0)
328: return modelName.substring(1);
329: else
330: return "";
331: }
332:
333: /**
334: * Strips the path of the value text
335: * @return the stripped path
336: */
337: public String getStrippedPath() {
338: String modelName = null;
339: if (jTreeComp.getSelectionPath() != null) {
340: Object path[] = jTreeComp.getSelectionPath().getPath();
341:
342: modelName = "";
343: for (int i = 1; i < path.length; i++) {
344: String nodeText = path[i].toString();
345: int separatorPos = nodeText.indexOf(": ");
346: String pathEle = nodeText.substring(0, separatorPos);
347: String value = nodeText.substring(separatorPos + 2,
348: nodeText.length());
349: modelName += "/" + pathEle;
350: }
351: }
352: if (modelName == null)
353: return "";
354: else if (modelName.trim().compareTo("") != 0)
355: return modelName.substring(1);
356: else
357: return "";
358: }
359:
360: public String getStrippedPath(TreePath treePath) {
361: String modelName = null;
362: if (treePath != null) {
363: Object path[] = treePath.getPath();
364:
365: modelName = "";
366: for (int i = 1; i < path.length; i++) {
367: String nodeText = path[i].toString();
368: int separatorPos = nodeText.indexOf(": ");
369: String pathEle = nodeText.substring(0, separatorPos);
370: String value = nodeText.substring(separatorPos + 2,
371: nodeText.length());
372: modelName += "/" + pathEle;
373: }
374: }
375:
376: if (modelName == null)
377: return "";
378: else if (modelName.trim().compareTo("") != 0)
379: return modelName.substring(1);
380: else
381: return "";
382: }
383:
384: public String stripQuotes(String str) {
385: if ((str != null) && (str.length() > 0)) {
386: int p = (str.charAt(0) == '"' ? 1 : 0);
387: return str.substring(p, str.length() - p);
388: } else {
389: return str;
390: }
391: }
392:
393: public void setSelectedPath(String path) {
394: Vector nodes = new Vector();
395: nodes.add(topNode);
396: if ((path != null) && (path.length() > 0))
397: addNodes(nodes, topNode, path);
398:
399: Object nodeArray[] = nodes.toArray();
400: TreePath treepath = new TreePath(nodeArray);
401: jTreeComp.setSelectionPath(treepath);
402: jTreeComp.scrollPathToVisible(treepath);
403: }
404:
405: public void expandSelectedPath(String path) {
406: Vector nodes = new Vector();
407: nodes.add(topNode);
408: if ((path != null) && (path.length() > 0))
409: addNodes(nodes, topNode, path);
410:
411: Object nodeArray[] = nodes.toArray();
412: TreePath treepath = new TreePath(nodeArray);
413: jTreeComp.expandPath(treepath);
414: jTreeComp.scrollPathToVisible(treepath);
415: }
416:
417: private void addNodes(Vector nodes, TreeNode node, String path) {
418: if (node instanceof XDefaultMutableTreeNode)
419: ((XDefaultMutableTreeNode) node).defineChildren();
420:
421: int pathSeparatorPos = path.indexOf('/');
422: String subStyle = (pathSeparatorPos > 0 ? path.substring(0,
423: pathSeparatorPos) : path);
424: int numChildren = node.getChildCount();
425: for (int i = 0; i < numChildren; i++) {
426: TreeNode childNode = node.getChildAt(i);
427: String pathEle = childNode.toString();
428: int separatorPos = pathEle.indexOf(":");
429: if (separatorPos > -1)
430: pathEle = pathEle.substring(0, separatorPos);
431: if (pathEle.compareTo(subStyle) == 0) {
432: nodes.add(childNode);
433: if ((pathSeparatorPos > 0)
434: && (pathSeparatorPos < path.length()))
435: addNodes(nodes, childNode, path
436: .substring(pathSeparatorPos + 1));
437:
438: break;
439: }
440: }
441: }
442:
443: private Object[] parsePath(String path) {
444: StringTokenizer token = new StringTokenizer(path, "/");
445: Vector items = new Vector();
446: while (token.hasMoreElements()) {
447: items.add(token.nextElement());
448: }
449: return items.toArray();
450: }
451:
452: public void mouseClicked(MouseEvent me) {
453: if (me.getClickCount() > 1) {
454: if (!listenerChanging) {
455: listenerChanging = true;
456: modelTreeListener.nodeInvoked(getStrippedPath());
457: listenerChanging = false;
458: }
459: }
460: }
461:
462: public void mousePressed(MouseEvent me) {
463: }
464:
465: public void mouseReleased(MouseEvent me) {
466: }
467:
468: public void mouseExited(MouseEvent me) {
469: }
470:
471: public void mouseEntered(MouseEvent me) {
472: }
473:
474: /**
475: * expand the root node.
476: */
477: public void expandRoot() {
478: final TreePath path = new TreePath(topNode);
479: SwingUtilities.invokeLater(new Runnable() {
480: public void run() {
481: jTreeComp.expandPath(path);
482: jTreeComp.repaint();
483: }
484: });
485: }
486:
487: public JTree getTreeComponent() {
488: return jTreeComp;
489: }
490:
491: /****/
492: class TreeExpanderT extends Thread {
493: private final Semaphore canExpand = new Semaphore(1);
494: private boolean working = true;
495: private XModel model;
496: private XDefaultMutableTreeNode treeNode;
497: private XModel[] modelChildren;
498:
499: public void run() {
500: try {
501:
502: while (working) {
503:
504: canExpand.acquire();
505:
506: // define children
507: if (model != null) {
508: int numChildren = model.getNumChildren();
509: modelChildren = new XModel[numChildren];
510: for (int i = 0; i < numChildren; i++)
511: modelChildren[i] = (XModel) model.get(i);
512: }
513: String modelKey = getModelPath(model);
514: modelNodes.put(modelKey, modelChildren);
515:
516: // add the created nodes to the tree
517: treeNode.setNodeChildrenDefined(true);
518: treeNode.removeAllChildren();
519: for (int i = 0; i < modelChildren.length; i++) {
520: addNode(modelChildren[i], treeNode);
521: }
522:
523: // refresh the tree in the java dispatch thread
524: SwingUtilities.invokeLater(new Runnable() {
525: public void run() {
526: expandSelectedNode(treeNode);
527: }
528: });
529:
530: }
531:
532: } catch (Exception ex) {
533: ex.printStackTrace();
534: }
535: }
536:
537: public TreeExpanderT() {
538: working = true;
539: try {
540: canExpand.acquire();
541: } catch (InterruptedException ex) {
542: ex.printStackTrace();
543: }
544: start();
545: }
546:
547: public void defineChildren(XModel aModel) {
548: model = aModel;
549: canExpand.release();
550: }
551:
552: public void defineChildren(XDefaultMutableTreeNode aTreeNode) {
553: treeNode = aTreeNode;
554: model = treeNode.getModel();
555: // start expanding
556: canExpand.release();
557: }
558:
559: }
560:
561: protected class XDefaultMutableTreeNode extends
562: DefaultMutableTreeNode {
563: XModel model;
564: boolean nodeChildrenDefined;
565:
566: public XDefaultMutableTreeNode(String text, XModel aModel) {
567: super (text);
568: model = aModel;
569: nodeChildrenDefined = false;
570: }
571:
572: public void setNodeChildrenDefined(boolean state) {
573: nodeChildrenDefined = state;
574: }
575:
576: private int getModelChildrenCount() {
577: int numChildren = 0;
578: try {
579: if (model == null)
580: return 0;
581:
582: numChildren = model.getNumChildren();
583:
584: } catch (Exception ex) {
585: numChildren = 0;
586: }
587:
588: return numChildren;
589: }
590:
591: public boolean areNodeChildrenDefined() {
592: return nodeChildrenDefined;
593: }
594:
595: public XModel getModel() {
596: return model;
597: }
598:
599: public boolean isLeaf() {
600: return (getModelChildrenCount() == 0);
601: }
602:
603: private boolean modelChildrenDefined() {
604: if (model instanceof XPojoModelVis) {
605: String modelKey = getModelPath(model);
606: return (modelNodes.containsKey(modelKey));
607: } else {
608: return true;
609: }
610: }
611:
612: public int getChildCount() {
613: int numChildren = 0;
614: if (!nodeChildrenDefined) {
615: numChildren = (modelChildrenDefined() ? getModelChildrenCount()
616: : 1);
617: } else {
618: numChildren = super .getChildCount();
619: }
620: return numChildren;
621: }
622:
623: public TreeNode getChildAt(int i) {
624: if (!nodeChildrenDefined)
625: defineChildren();
626: return (super .getChildAt(i));
627: }
628:
629: public void defineChildren() {
630: if (!(model instanceof XPojoModelVis)) {
631: nodeChildrenDefined = true;
632: int numChildren = getModelChildrenCount();
633: for (int i = 0; i < numChildren; i++)
634: addNode(model.get(i), this );
635: } else {
636: definePojoChildren();
637: }
638: }
639:
640: protected void definePojoChildren() {
641: final DefaultMutableTreeNode infoNode = new XDefaultMutableTreeNode(
642: "getting property...: ", null);
643:
644: if ((model instanceof XPojoModelVis)
645: && ((XPojoModelVis) model).isDirty()) {
646:
647: String modelKey = getModelPath(model);
648: modelNodes.remove(modelKey);
649: ((XPojoModelVis) model).setDirty(false);
650: }
651:
652: nodeChildrenDefined = true;
653: if (!modelChildrenDefined()) {
654: XDefaultMutableTreeNode.this .add(infoNode);
655: treeExpander.defineChildren(this );
656: } else {
657: String modelKey = getModelPath(model);
658: XModel[] modelChildren = (XModel[]) modelNodes
659: .get(modelKey);
660: for (int i = 0; i < modelChildren.length; i++)
661: addNode(modelChildren[i],
662: XDefaultMutableTreeNode.this );
663: }
664:
665: }
666:
667: }
668:
669: /**
670: * Refresh tree model representation
671: */
672: protected void refreshTree() {
673: String path = getStrippedPath();
674: removeTreeSelectionListener(modelVisualiserPanel);
675: removeMouseListener(modelVisualiserPanel);
676: createTreeComp(null);
677: if (path != null)
678: setSelectedPath(path);
679: addTreeSelectionListener(modelVisualiserPanel);
680: addMouseListener(modelVisualiserPanel);
681: }
682:
683: public void expandSelectedNode(XDefaultMutableTreeNode treeNode) {
684: ((DefaultTreeModel) jTreeComp.getModel())
685: .nodeStructureChanged(treeNode);
686: XModel model = treeNode.getModel();
687: String path = getModelPath(model);
688: if (path != null)
689: expandSelectedPath(path);
690: jTreeComp.repaint();
691: }
692:
693: private JFileChooser createDbDriverChooser() {
694: JFileChooser chooser = new JFileChooser();
695: chooser.setDialogTitle("Choose the database driver file");
696:
697: FileFilter fileFilter = (new FileFilter() {
698: public boolean accept(File f) {
699: String name = f.getName();
700: return (f.isDirectory() || name.endsWith(".jar") || name
701: .endsWith(".zip"));
702: }
703:
704: public String getDescription() {
705: return "database driver file";
706: }
707: });
708: chooser.setFileFilter(fileFilter);
709: return chooser;
710: }
711:
712: /**
713: * Shows the dialog to choose database driver file.
714: */
715: private File chooseDriverFile() {
716: File driFile = null;
717:
718: if (dbDriverChooser == null) {
719: dbDriverChooser = new JFileChooser();
720: dbDriverChooser
721: .setDialogTitle("Choose the database driver file");
722: FileFilter fileFilter = (new FileFilter() {
723: public boolean accept(File f) {
724: String name = f.getName();
725: return (f.isDirectory() || name.endsWith(".jar") || name
726: .endsWith(".zip"));
727: }
728:
729: public String getDescription() {
730: return "database driver file";
731: }
732: });
733: dbDriverChooser.setFileFilter(fileFilter);
734: }
735:
736: // show the dialog
737: int returnVal = dbDriverChooser.showOpenDialog(this );
738: if (returnVal == JFileChooser.APPROVE_OPTION)
739: driFile = dbDriverChooser.getSelectedFile();
740:
741: return driFile;
742: }
743:
744: private boolean popupYesNoDialog(String msg) {
745: Object[] options = { "Yes", "No" };
746: int n = JOptionPane
747: .showOptionDialog(this , msg, "",
748: JOptionPane.YES_NO_OPTION,
749: JOptionPane.QUESTION_MESSAGE, null, options,
750: options[0]);
751: return (n == 0);
752: }
753:
754: /**
755: * Tests whether the the specified tabase driver is in the project's
756: * class path.
757: * @driverName the name of the driver
758: */
759: private boolean driverFound(String driverName) {
760: IEditorUtility editorUtility = XEditorProjectManager
761: .getEditorUtility();
762: URL[] urls = editorUtility.getProjectURLs(currentProject);
763: ClassLoader classLoader = new URLClassLoader(urls);
764: boolean driverFound = true;
765: try {
766: Class.forName(driverName, false, classLoader);
767: } catch (ClassNotFoundException ex) {
768: driverFound = false;
769: }
770: return driverFound;
771: }
772:
773: /**
774: * Mouse listener for visualiser tree. Invokes exportAdDrag
775: * method
776: */
777: private class TreeNodeMouseListener implements MouseListener,
778: MouseMotionListener {
779: private MouseEvent firstMouseEvent = null;
780:
781: public void mousePressed(MouseEvent e) {
782: firstMouseEvent = e;
783: }
784:
785: public void mouseDragged(MouseEvent e) {
786: if (firstMouseEvent != null) {
787: e.consume();
788: JComponent c = (JComponent) e.getSource();
789: TransferHandler handler = c.getTransferHandler();
790: handler.exportAsDrag(c, firstMouseEvent,
791: TransferHandler.COPY);
792: firstMouseEvent = null;
793: }
794: }
795:
796: public void mouseReleased(MouseEvent e) {
797: firstMouseEvent = null;
798: }
799:
800: public void mouseClicked(MouseEvent e) {
801: }
802:
803: public void mouseEntered(MouseEvent e) {
804: }
805:
806: public void mouseExited(MouseEvent e) {
807: }
808:
809: public void mouseMoved(MouseEvent e) {
810: }
811: }
812:
813: /**
814: * Model visualiser tree drag'n drop handler
815: */
816: private class TreeNodeTransferHandler extends TransferHandler {
817: private DataFlavor dataFlavor;
818:
819: /**
820: * Indicates whether any of the given data type can be imported into
821: * the model.
822: */
823: public boolean canImport(JComponent comp,
824: DataFlavor[] transferFlavors) {
825: // if there are no transferFlavors specified assume the
826: // sql explorer eclipse plugin (as it doesn't provide any flavors)
827: // and allow to import (probably very fragile)
828: dataFlavor = null;
829: if (transferFlavors.length == 0)
830: return true;
831:
832: IEditorUtility editorUtility = XEditorProjectManager
833: .getEditorUtility();
834: for (int i = 0; (dataFlavor == null)
835: && (i < transferFlavors.length); i++) {
836: if (editorUtility.canImportDbTable(transferFlavors[i]))
837: dataFlavor = transferFlavors[i];
838: }
839: return (dataFlavor != null);
840: }
841:
842: /**
843: * Appends database table to the root model node in the
844: * visualiser tree.
845: */
846: private boolean importDbTable(Transferable t) {
847: try {
848: Object tableObject = (dataFlavor != null ? t
849: .getTransferData(dataFlavor) : null);
850: IEditorUtility editorUtility = currentProject
851: .getEditorUtility();
852:
853: // if there is no driver available pop up the file chooser dialog
854: String driverFileName = null;
855: String dri = editorUtility.getDbDriver(tableObject);
856: if (!BindingTransferHandler.driverFound(currentProject,
857: dri)) {
858: driverFileName = editorUtility
859: .getDbDriverFile(tableObject);
860: if (driverFileName == null) {
861: File driverFile = chooseDriverFile();
862: if (driverFile != null)
863: driverFileName = driverFile
864: .getAbsolutePath();
865: else
866: return false; // "cancel" button pressed
867: }
868: }
869:
870: Connection connection = editorUtility
871: .getDbConnection(tableObject);
872: if (connection == null)
873: return false;
874: if ("".equals(getStrippedPath())) {
875: BindingTransferHandler
876: .registerDbTable(currentProject,
877: tableObject, driverFileName);
878: refreshTree();
879: }
880: // database tables can be appended only to the root node
881: else {
882: JOptionPane
883: .showMessageDialog(
884: ModelVisualiserTree.this ,
885: "Database table can be appended only to the root node");
886: return false;
887: }
888: } catch (Exception ex) {
889: JOptionPane.showMessageDialog(ModelVisualiserTree.this ,
890: ex.getMessage());
891: return false;
892: }
893: return true;
894: }
895:
896: /**
897: * Returns the type of transfer actions supported by the source
898: */
899: public int getSourceActions(JComponent c) {
900: return COPY;
901: }
902:
903: /**
904: * Inserts passed data to the given component
905: */
906: public boolean importData(JComponent comp, Transferable t) {
907: return importDbTable(t);
908: }
909:
910: /**
911: * Creates <code>Transferable</code> as the source for the data
912: * transfer
913: */
914: protected Transferable createTransferable(JComponent c) {
915: Transferable t = new Transferable() {
916: private final DataFlavor[] dataFlavors = { BindingTransferHandler.XModelFlavor };
917:
918: /**
919: * Returns the table of available data flavors
920: */
921: public DataFlavor[] getTransferDataFlavors() {
922: return dataFlavors;
923: }
924:
925: /**
926: * Returns whether or not the given data flavor is supported
927: * for this object
928: */
929: public boolean isDataFlavorSupported(DataFlavor flavor) {
930: boolean ret = false;
931: for (int i = 0; (i < dataFlavors.length) && !ret; i++)
932: ret = dataFlavors[i].equals(flavor);
933: return ret;
934: }
935:
936: /**
937: * Resturns the XModel object to be transfered from the
938: * visualiser's tree
939: */
940: public Object getTransferData(DataFlavor flavor)
941: throws UnsupportedFlavorException, IOException {
942: String path = getStrippedPath();
943: return (path != null ? rootModel.get(path) : null);
944: }
945: };
946:
947: return t;
948: }
949:
950: }
951:
952: }
|