001: package tide.sources;
002:
003: import java.awt.datatransfer.*;
004: import java.awt.Color;
005: import java.awt.dnd.*;
006: import tide.editor.bookmarks.SourceBookmark;
007: import tide.project.*;
008: import tide.sources.*;
009: import snow.utils.storage.*;
010: import tide.editor.*;
011: import tide.exttools.findbugs.*;
012: import tide.exttools.JLint.*;
013: import tide.exttools.jad_decompiler.*;
014: import snow.utils.gui.*;
015: import snow.utils.*;
016: import javax.swing.*;
017: import java.awt.BorderLayout;
018: import java.awt.event.*;
019: import javax.swing.border.*;
020: import javax.swing.event.*;
021: import javax.swing.tree.*;
022: import java.util.*;
023: import java.io.*;
024:
025: /** Shows the sources and classes in class path.
026: (also src.jar, but its content is mapped with the corresponding classes in rt.jar)
027: */
028: public class LibrariesPanel extends JPanel {
029: private final JTree tree = new JTree();
030:
031: public LibrariesPanel() {
032: super (new BorderLayout());
033:
034: JScrollPane sp = new JScrollPane(tree);
035: sp.setBorder(null);
036: sp.getViewport().setBorder(null);
037: add(sp, BorderLayout.CENTER);
038: tree.setRootVisible(false);
039:
040: tree.setCellRenderer(new LibTreeRenderer());
041:
042: // selection
043: tree.getSelectionModel().addTreeSelectionListener(
044: new TreeSelectionListener() {
045: public void valueChanged(TreeSelectionEvent tse) {
046: TreePath tp = tse.getNewLeadSelectionPath();
047: if (tp != null) {
048: LibFileItem src = (LibFileItem) tp
049: .getLastPathComponent();
050: if (src != null) {
051: if (src.isJavaFile()
052: || src.isClassFile()) {
053: MainEditorFrame.instance
054: .setSourceOrItemToEditOrView(
055: src, false);
056: }
057: }
058: }
059: }
060: });
061:
062: tree.addMouseListener(new MouseAdapter() {
063: @Override
064: public void mousePressed(MouseEvent me) {
065: if (me.isPopupTrigger()) {
066: showPopup(me);
067: }
068: }
069:
070: @Override
071: public void mouseReleased(MouseEvent me) {
072: if (me.isPopupTrigger()) {
073: showPopup(me);
074: }
075: }
076: });
077:
078: this .registerKeyboardAction(new ActionListener() {
079: public void actionPerformed(ActionEvent ae) {
080: java.util.List<LibFileItem> files = getTreeModel()
081: .getAllFiles();
082: new SearchTool(files, true, "Search in all libraries ("
083: + files.size() + " classes)");
084: }
085: }, "SearchFileNamesLib", Accelerators.search,
086: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
087:
088: allowDropFilesFromOS();
089:
090: } // Constructor
091:
092: public void clearSelection() {
093: tree.getSelectionModel().clearSelection();
094: }
095:
096: /** Must be called when loading a new project
097: */
098: public void setModel(LibrariesTreeModel m) {
099: tree.setModel(m);
100: tree.setVisible(true);
101: }
102:
103: private final void showPopup(MouseEvent me) {
104: int selRow = tree.getRowForLocation(me.getX(), me.getY());
105: if (selRow == -1)
106: return;
107:
108: TreePath selPath = tree
109: .getPathForLocation(me.getX(), me.getY());
110: final LibFileItem sf = (LibFileItem) selPath
111: .getLastPathComponent();
112: if (sf == null)
113: return;
114:
115: // force the selection to the clicked path.
116: tree.setSelectionPath(selPath);
117:
118: final List<LibFileItem> allFiles = new ArrayList<LibFileItem>();
119: this .getTreeModel().getAllFilesRecurse(allFiles, sf, false); // all, even non java ones (?)
120: //System.out.println(""+allFiles.size() + " files in " + selPath);
121:
122: JPopupMenu popup = new JPopupMenu("Libraries tree popup menu");
123:
124: if (sf.isDirectory()) {
125: if (sf.getPackageName().length() == 0) {
126: popup.add(" " + allFiles.size()
127: + " files in the whole library");
128: } else {
129: popup.add(" " + allFiles.size() + " files in "
130: + sf.getPackageName());
131: }
132: } else {
133: popup.add(" " + sf.getJavaName());
134: //popup.add(" "+sf.getPackageName());
135: }
136: popup.addSeparator();
137:
138: JMenuItem search = new JMenuItem("Search in files",
139: Icons.sharedSearch);
140: // Todo: ctr + alt + shift+g
141: popup.add(search);
142: search.addActionListener(new ActionListener() {
143: public void actionPerformed(ActionEvent ae) {
144: // only not ignored files
145: List<LibFileItem> files = new ArrayList<LibFileItem>();
146: for (LibFileItem sf : allFiles) {
147: if (sf.isJavaFile()) {
148: files.add(sf);
149: }
150: }
151:
152: new SearchTool(files, false, "Search in "
153: + files.size() + " library files");
154: }
155: });
156:
157: JMenuItem searchD = new JMenuItem("Search filenames",
158: Icons.sharedSearch);
159: searchD.setAccelerator(Accelerators.search);
160: popup.add(searchD);
161: searchD.addActionListener(new ActionListener() {
162: public void actionPerformed(ActionEvent ae) {
163: // only not ignored files
164: List<LibFileItem> files = new ArrayList<LibFileItem>();
165: for (LibFileItem sf : allFiles) {
166: if (sf.isJavaFile())
167: files.add(sf);
168: }
169: new SearchTool(files, true, "Search in " + files.size()
170: + " library filenames");
171: }
172: });
173:
174: if (sf.isJavaFile()) {
175: popup.addSeparator();
176: JMenuItem exec = new JMenuItem("Execute",
177: new Icons.StartIcon(12, 12, true));
178: popup.add(exec);
179: exec.addActionListener(new ActionListener() {
180: public void actionPerformed(ActionEvent ae) {
181: System.out.println("Executing within ext lib "
182: + sf.getJavaName());
183: MainEditorFrame.instance.execute(sf, false, null,
184: null);
185: }
186: });
187: }
188:
189: if (sf.isClassFile()) {
190: popup.addSeparator();
191: final JMenuItem decomp = new JMenuItem(
192: "Decompile (with JAD)");
193: popup.add(decomp);
194: decomp.addActionListener(new ActionListener() {
195: public void actionPerformed(ActionEvent ae) {
196:
197: // show settings dialog if not configured
198: if (!JADDecompilerSettingsDialog.isConfigured()) {
199: JADDecompilerSettingsDialog fbst = new JADDecompilerSettingsDialog(
200: MainEditorFrame.instance,
201: MainEditorFrame.instance
202: .getActualProject());
203: if (!fbst.dialogWasAccepted
204: || !JADDecompilerSettingsDialog
205: .isConfigured()) {
206: return;
207: }
208: }
209:
210: try {
211: JADLauncher.decompile(sf);
212: //System.out.println(""+sf.decompiledContent);
213:
214: // enforce reselecting !
215: MainEditorFrame.instance.editorPanel
216: .removeTab(sf);
217: MainEditorFrame.instance
218: .setSourceOrItemToEditOrView(sf, false);
219: } catch (Exception e) {
220: e.printStackTrace();
221: //int ltd = MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc.getLength(); // remember position...
222: MainEditorFrame.instance.outputPanels
223: .selectToolsTab(true);
224: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
225: .appendError("\nCannot decompile "
226: + sf.getJavaName() + ":\n"
227: + e.getMessage());
228:
229: //MainEditorFrame.instance.outputPanels.toolsOutputPanel.setCaretPosition(ltd);
230: }
231: }
232: });
233:
234: JMenuItem undecomp = new JMenuItem(
235: "View bytecode (disasembled with javap)");
236: popup.add(undecomp);
237: undecomp.addActionListener(new ActionListener() {
238: public void actionPerformed(ActionEvent ae) {
239: //enforce using javaP
240: sf.decompiledContentOrSource = null;
241: sf.enforceDecompileInsteadOfViewingSource = true;
242:
243: // enforce reselecting !
244: MainEditorFrame.instance.editorPanel.removeTab(sf);
245: MainEditorFrame.instance
246: .setSourceOrItemToEditOrView(sf, true);
247: }
248: });
249:
250: final JMenuItem vs = new JMenuItem(
251: "View source (if available)");
252: popup.add(vs);
253: vs.addActionListener(new ActionListener() {
254: public void actionPerformed(ActionEvent ae) {
255: //enforce using javaP
256: sf.decompiledContentOrSource = null;
257: sf.enforceDecompileInsteadOfViewingSource = false;
258:
259: // enforce reselecting !
260: MainEditorFrame.instance.editorPanel.removeTab(sf);
261: MainEditorFrame.instance
262: .setSourceOrItemToEditOrView(sf, true);
263: }
264: });
265:
266: } //is class
267:
268: popup.addSeparator();
269: SharedUtils.addBookmarksPopup(popup, sf.getJavaName());
270:
271: if (sf.isJavaFile()) {
272: // add bookmark
273: JMenuItem addBookmark = new JMenuItem(
274: "Add a bookmark here", Icons.sharedPlus);
275: popup.add(addBookmark);
276: addBookmark.addActionListener(new ActionListener() {
277: public void actionPerformed(ActionEvent ae) {
278: String tt = JOptionPane.showInputDialog(
279: LibrariesPanel.this ,
280: "Bookmark description (optional)",
281: "Add a bookmark",
282: JOptionPane.QUESTION_MESSAGE);
283: if (tt == null)
284: return;
285: MainEditorFrame.instance
286: .getActualProject()
287: .addBookmark(
288: new SourceBookmark(
289: sf.getJavaName(), 0, 0, tt)); // position 0
290: }
291: });
292: }
293:
294: if (sf.getLevel() == 1) {
295: boolean isIgnored = sf.isIgnored();
296: popup.addSeparator();
297:
298: if (!isIgnored) {
299: JMenuItem ignore = new JMenuItem("Ignore this library",
300: Icons.sharedCross);
301: popup.add(ignore);
302: ignore.addActionListener(new ActionListener() {
303: public void actionPerformed(ActionEvent ae) {
304: if (sf.getName().endsWith("rt.jar")) {
305: if (JOptionPane
306: .showConfirmDialog(
307: LibrariesPanel.this ,
308: "rt.jar contains essential classes like String."
309: + "\nIgnoring it is not a good idea.\nDo you still want to ignore it?",
310: "Ignoring rt.jar",
311: JOptionPane.YES_NO_CANCEL_OPTION) != JOptionPane.YES_OPTION)
312: return;
313: }
314: setIgnored(sf, true);
315: tree.repaint(); // ?
316: }
317: });
318:
319: // TODO: ignore all but rt.jar !
320: if (sf.getName().endsWith("rt.jar")) {
321: JMenuItem ignorea = new JMenuItem(
322: "Ignore all but rt.jar", Icons.sharedCross);
323: popup.add(ignorea);
324: ignorea.addActionListener(new ActionListener() {
325: public void actionPerformed(ActionEvent ae) {
326: for (LibFileItem fi : getTreeModel()
327: .getAllTopLevelLibs()) {
328: setIgnored(fi, fi != sf);
329: }
330: tree.repaint(); // ?
331: }
332: });
333: }
334: }
335:
336: if (isIgnored) {
337: JMenuItem restore = new JMenuItem(
338: "Restore this library");
339: popup.add(restore);
340: restore.addActionListener(new ActionListener() {
341: public void actionPerformed(ActionEvent ae) {
342: setIgnored(sf, false);
343: tree.repaint(); // ?
344: }
345: });
346: }
347:
348: if (!MainEditorFrame.instance.getActualProject().ignoredLibrariesNames
349: .isEmpty()) {
350: JMenuItem restoreA = new JMenuItem(
351: "Restore all ignored libraries");
352: popup.add(restoreA);
353: restoreA.addActionListener(new ActionListener() {
354: public void actionPerformed(ActionEvent ae) {
355: MainEditorFrame.instance.getActualProject().ignoredLibrariesNames
356: .clear();
357: for (LibFileItem fi : getTreeModel()
358: .getAllTopLevelLibs()) {
359: setIgnored(fi, false);
360: }
361: tree.repaint(); // ?
362: }
363: });
364: }
365: }
366:
367: FileIcon dir = new FileIcon(true, 15);
368: dir.setType(FileIcon.IconColor.RedGreen);
369: JMenuItem internalexplore = new JMenuItem(
370: "Internal file explorer", dir);
371: popup.addSeparator();
372: popup.add(internalexplore);
373: internalexplore.addActionListener(new ActionListener() {
374: public void actionPerformed(ActionEvent ae) {
375: new SourcesExplorer(allFiles, MainEditorFrame.instance,
376: "Files in node " + sf.getJavaName());
377: }
378: });
379:
380: FileIcon dir2 = new FileIcon(true, 15);
381: dir2.setType(FileIcon.IconColor.RedGreen);
382: JMenuItem internalexplore2 = new JMenuItem(
383: "Internal package explorer", dir2);
384: //popup.addSeparator();
385: popup.add(internalexplore2);
386: internalexplore2.addActionListener(new ActionListener() {
387: public void actionPerformed(ActionEvent ae) {
388: new PackagesExplorer(allFiles, MainEditorFrame.instance);
389: }
390: });
391:
392: popup.show(tree, me.getX(), me.getY());
393: }
394:
395: private void setIgnored(LibFileItem sf, boolean is) {
396: if (sf instanceof LibFileItem.LibFileRoot) {
397: LibFileItem.LibFileRoot lib = (LibFileItem.LibFileRoot) sf;
398: lib.setIgnored(is);
399: } else if (sf instanceof LibFileItem.LibDirRoot) {
400: LibFileItem.LibDirRoot lib = (LibFileItem.LibDirRoot) sf;
401: lib.setIgnored(is);
402: }
403: tree.repaint(); // ?
404: }
405:
406: /** Set this at loading or when the project settings have changed or at reload.
407: */
408: public void setLibraries(List<File> libraries,
409: List<File> sourcesForLibraries) {
410: LibrariesTreeModel librariesTreeModel = getTreeModel();
411: librariesTreeModel.setRoots(libraries, sourcesForLibraries);
412:
413: if (librariesTreeModel.root.getChildCount() > 0) {
414: TreePath tp = new TreePath(librariesTreeModel.root
415: .getChildItemAt(0).getPath());
416: tree.makeVisible(tp);
417: }
418: }
419:
420: public LibrariesTreeModel getTreeModel() {
421: return MainEditorFrame.instance.getActualProject().librariesTreeModel;
422: }
423:
424: public void setSelectedItem(LibFileItem lit,
425: boolean enforceReselection) {
426: TreePath newSelectionPath = new TreePath(lit.getPath());
427: if (enforceReselection) {
428: tree.setSelectionPath(null);
429: }
430: tree.setSelectionPath(newSelectionPath);
431: tree.makeVisible(newSelectionPath);
432: tree.scrollPathToVisible(newSelectionPath);
433:
434: }
435:
436: public void allowDropFilesFromOS() {
437: new FileDropTarget(this );
438: }
439:
440: class FileDropTarget extends DropTarget {
441: public FileDropTarget(JComponent c) {
442: super (c, DnDConstants.ACTION_COPY,
443: new FileDropTargetListener(c), true);
444: c.setDropTarget(this );
445:
446: }
447: }
448:
449: class FileDropTargetListener implements DropTargetListener {
450: JComponent comp;
451: Border originalBorder = null;
452: Border redBorder = BorderFactory.createLineBorder(Color.red, 1);
453: Border greenBorder = BorderFactory.createLineBorder(
454: Color.green, 1);
455:
456: public FileDropTargetListener(JComponent comp) {
457: this .comp = comp;
458: this .originalBorder = comp.getBorder();
459: }
460:
461: public boolean isValidCandidate(File f) {
462: String n = f.getName().toLowerCase();
463: if (n.endsWith(".jar"))
464: return true;
465: if (n.endsWith(".zip"))
466: return true;
467: return false;
468: }
469:
470: File fileToDrop = null;
471:
472: public void dragEnter(DropTargetDragEvent dte) {
473: //System.out.println("dragEnter");
474:
475: boolean accept = false;
476: fileToDrop = null;
477: for (DataFlavor df : dte.getCurrentDataFlavors()) {
478: if (df.isFlavorJavaFileListType()) {
479: Transferable tr = dte.getTransferable();
480: try {
481: Object data = tr
482: .getTransferData(df.javaFileListFlavor);
483: //System.out.println(""+data);
484: @SuppressWarnings("unchecked")
485: List<File> lf = (List<File>) data;
486: if (lf.size() == 1) {
487: if (isValidCandidate(lf.get(0))) {
488: fileToDrop = lf.get(0);
489: //pathField.setToolTipText("Droping "+lf.get(0));
490: dte
491: .acceptDrag(DnDConstants.ACTION_COPY);
492: accept = true;
493: break;
494: }
495: }
496: } catch (Exception e) {
497: comp.setBorder(redBorder);
498: e.printStackTrace();
499: }
500: } else if (df.isFlavorTextType()) {
501: Transferable tr = dte.getTransferable();
502: try {
503: String data = ""
504: + tr
505: .getTransferData(df.javaFileListFlavor);
506: if (data.toLowerCase().startsWith("file://"))
507: data = data.substring(6);
508:
509: File f = new File(data);
510: if (isValidCandidate(f)) {
511: fileToDrop = f;
512: //pathField.setToolTipText("Droping "+f); // don't work
513: //ToolTipManager.sharedInstance().setDismissDelay(.showTipWindow();
514: dte.acceptDrag(DnDConstants.ACTION_COPY);
515: accept = true;
516: break;
517: }
518:
519: } catch (Exception e) {
520: comp.setBorder(redBorder);
521: e.printStackTrace();
522: }
523: }
524: //System.out.println(""+df);
525: }
526:
527: if (accept) {
528: comp.setBorder(greenBorder);
529: } else {
530: comp.setBorder(redBorder);
531: }
532: }
533:
534: public void dragExit(DropTargetEvent dte) {
535: //System.out.println("dragExit");
536: setToolTipText(null);
537: setBorder(originalBorder);
538: }
539:
540: public void dragOver(DropTargetDragEvent dte) {
541: //System.out.println("dragOver");
542: }
543:
544: public void drop(DropTargetDropEvent dte) {
545: setBorder(originalBorder);
546: setToolTipText(null);
547: System.out.println("drop " + fileToDrop);
548: if (fileToDrop.isFile()) {
549: int rep = JOptionPane.showConfirmDialog(
550: LibrariesPanel.this ,
551: "Do you want to add the library\n\n "
552: + fileToDrop
553: + "\n\nto the class path ?",
554: "Confirmation",
555: JOptionPane.YES_NO_CANCEL_OPTION);
556: if (rep != JOptionPane.OK_OPTION) {
557: return;
558: }
559: try {
560: MainEditorFrame.instance.editorPanel
561: .saveChangedFiles();
562: List<File> cp = MainEditorFrame.instance
563: .getActualProject().getClassPath(false,
564: false);
565: cp.add(fileToDrop);
566: MainEditorFrame.instance.getActualProject()
567: .setExternalJars(cp);
568: MainEditorFrame.instance.reloadProject();
569:
570: /*String cont = FileUtils.getFileStringContent(fileToDrop);
571: addNewSourceDialog("", cont);*/
572: } catch (Exception e) {
573: e.printStackTrace();
574: }
575: }
576: }
577:
578: public void dropActionChanged(DropTargetDragEvent dte) {
579: System.out.println("dropActionChanged");
580: }
581: }
582:
583: }
|