diff --git a/pdex/src/processing/mode/experimental/ASTGenerator.java b/pdex/src/processing/mode/experimental/ASTGenerator.java
index d65c4d900..23d37464e 100644
--- a/pdex/src/processing/mode/experimental/ASTGenerator.java
+++ b/pdex/src/processing/mode/experimental/ASTGenerator.java
@@ -980,18 +980,18 @@ public class ASTGenerator {
String[] resources = classPath.findResources("",
regExpResourceFilter);
for (String matchedClass2 : resources) {
- matchedClass2 = matchedClass2.replace('/', '.');
+ matchedClass2 = matchedClass2.replace('/', '.'); //package name
String matchedClass = matchedClass2.substring(0, matchedClass2
.length() - 6);
int d = matchedClass.lastIndexOf('.');
if (ignorableImport(matchedClass2,matchedClass.substring(d + 1)))
continue;
- matchedClass = matchedClass.substring(d + 1);
- candidates
- .add(new CompletionCandidate(matchedClass, matchedClass
- + " : " + matchedClass2.substring(0, d), matchedClass,
- CompletionCandidate.PREDEF_CLASS));
+ matchedClass = matchedClass.substring(d + 1); //class name
+ candidates.add(new CompletionCandidate(matchedClass, ""
+ + matchedClass + " : " + ""
+ + matchedClass2.substring(0, d) + "", matchedClass
+ + "", CompletionCandidate.PREDEF_CLASS)); // display package name in grey
//log("-> " + className);
}
}
@@ -3307,6 +3307,68 @@ public class ASTGenerator {
}
return null;
}
+
+ public String[] getSuggestImports(final String className){
+ if(ignoredImportSuggestions == null) {
+ ignoredImportSuggestions = new TreeSet();
+ } else {
+ if(ignoredImportSuggestions.contains(className)) {
+ log("Ignoring import suggestions for " + className);
+ return null;
+ }
+ }
+
+ log("Looking for class " + className);
+ RegExpResourceFilter regf = new RegExpResourceFilter(
+ Pattern.compile(".*"),
+ Pattern
+ .compile(className
+ + ".class",
+ Pattern.CASE_INSENSITIVE));
+ String[] resources = classPath
+ .findResources("", regf);
+ ArrayList candidates = new ArrayList();
+ for (String res : resources) {
+ candidates.add(res);
+ }
+
+ // log("Couldn't find import for class " + className);
+
+ for (Library lib : editor.dmode.contribLibraries) {
+ ClassPath cp = factory.createFromPath(lib.getClassPath());
+ resources = cp.findResources("", regf);
+ for (String res : resources) {
+ candidates.add(res);
+ log("Res: " + res);
+ }
+ }
+
+ if (editor.getSketch().hasCodeFolder()) {
+ File codeFolder = editor.getSketch().getCodeFolder();
+ // get a list of .jar files in the "code" folder
+ // (class files in subfolders should also be picked up)
+ ClassPath cp = factory.createFromPath(Base
+ .contentsToClassPath(codeFolder));
+ resources = cp.findResources("", regf);
+ for (String res : resources) {
+ candidates.add(res);
+ log("Res: " + res);
+ }
+ }
+
+ resources = new String[candidates.size()];
+ for (int i = 0; i < resources.length; i++) {
+ resources[i] = candidates.get(i).replace('/', '.')
+ .substring(0, candidates.get(i).length() - 6);
+ }
+
+// ArrayList ans = new ArrayList();
+// for (int i = 0; i < resources.length; i++) {
+// ans.add(resources[i]);
+// }
+
+ return resources;
+ }
protected JFrame frmImportSuggest;
private TreeSet ignoredImportSuggestions;
diff --git a/pdex/src/processing/mode/experimental/ErrorCheckerService.java b/pdex/src/processing/mode/experimental/ErrorCheckerService.java
index 1ab2ddae6..753f8066a 100644
--- a/pdex/src/processing/mode/experimental/ErrorCheckerService.java
+++ b/pdex/src/processing/mode/experimental/ErrorCheckerService.java
@@ -404,7 +404,7 @@ public class ErrorCheckerService implements Runnable{
if (args.length > 0) {
String missingClass = args[0];
log("Will suggest for type:" + missingClass);
- astGenerator.suggestImports(missingClass);
+ //astGenerator.suggestImports(missingClass);
}
}
}
@@ -1006,6 +1006,30 @@ public class ErrorCheckerService implements Runnable{
if (tempErrorLog.size() < 200)
tempErrorLog.put(problemsList.get(i).getMessage(), problemsList
.get(i).getIProblem());
+
+ if(!ExperimentalMode.importSuggestEnabled) continue;
+ Problem p = problemsList.get(i);
+ if(p.getIProblem().getID() == IProblem.UndefinedType) {
+ String args[] = p.getIProblem().getArguments();
+ if (args.length > 0) {
+ String missingClass = args[0];
+// log("Will suggest for type:" + missingClass);
+ //astGenerator.suggestImports(missingClass);
+ String[] si = astGenerator.getSuggestImports(missingClass);
+ if(si != null && si.length > 0){
+// log("Suggested imps");
+// for (int j = 0; j < si.length; j++) {
+// log(si[j]);
+// }
+ p.setImportSuggestions(si);
+ errorData[i][0] = ""
+ + problemsList.get(i).getMessage()
+ + " (Import Suggestions available)";
+ }
+
+ }
+ }
+
}
DefaultTableModel tm = new DefaultTableModel(errorData,
diff --git a/pdex/src/processing/mode/experimental/Problem.java b/pdex/src/processing/mode/experimental/Problem.java
index 6fa029188..2cae43ce7 100644
--- a/pdex/src/processing/mode/experimental/Problem.java
+++ b/pdex/src/processing/mode/experimental/Problem.java
@@ -22,6 +22,7 @@
package processing.mode.experimental;
+import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -63,6 +64,11 @@ public class Problem {
* The type of error - WARNING or ERROR.
*/
private int type;
+
+ /**
+ * If the error is a 'cannot find type' contains the list of suggested imports
+ */
+ private String[] importSuggestions;
public static final int ERROR = 1, WARNING = 2;
@@ -147,6 +153,14 @@ public class Problem {
type = WARNING;
else throw new IllegalArgumentException("Illegal Problem type passed to Problem.setType(int)");
}
+
+ public String[] getImportSuggestions() {
+ return importSuggestions;
+ }
+
+ public void setImportSuggestions(String[] a) {
+ importSuggestions = a;
+ }
private static Pattern pattern;
private static Matcher matcher;
diff --git a/pdex/src/processing/mode/experimental/XQErrorTable.java b/pdex/src/processing/mode/experimental/XQErrorTable.java
index b3609c897..2dd4bd2b6 100755
--- a/pdex/src/processing/mode/experimental/XQErrorTable.java
+++ b/pdex/src/processing/mode/experimental/XQErrorTable.java
@@ -22,15 +22,31 @@ package processing.mode.experimental;
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import javax.swing.BoxLayout;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
+import javax.swing.ToolTipManager;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;
+import javax.swing.text.BadLocationException;
import processing.app.Language;
+import static processing.mode.experimental.ExperimentalMode.log;
/**
* Custom JTable implementation for XQMode. Minor tweaks and addtions.
@@ -76,7 +92,7 @@ public class XQErrorTable extends JTable {
this.addMouseListener(new MouseAdapter() {
@Override
- synchronized public void mouseReleased(MouseEvent e) {
+ synchronized public void mouseClicked(MouseEvent e) {
try {
errorCheckerService.scrollToErrorLine(((XQErrorTable) e
.getSource()).getSelectedRow());
@@ -87,7 +103,60 @@ public class XQErrorTable extends JTable {
+ e);
}
}
+
+// public void mouseMoved(MouseEvent evt) {
+// log(evt);
+//// String tip = null;
+//// java.awt.Point p = evt.getPoint();
+// int rowIndex = rowAtPoint(evt.getPoint());
+// int colIndex = columnAtPoint(evt.getPoint());
+// synchronized (errorCheckerService.problemsList) {
+// if (rowIndex < errorCheckerService.problemsList.size()) {
+// Problem p = errorCheckerService.problemsList.get(rowIndex);
+// if (p.getImportSuggestions() != null
+// && p.getImportSuggestions().length > 0) {
+// log("Import Suggestions available");
+// }
+// }
+// }
+//// return super.getToolTipText(evt);
+// }
});
+
+ final XQErrorTable thisTable = this;
+
+ this.addMouseMotionListener(new MouseMotionListener() {
+
+ @Override
+ public void mouseMoved(MouseEvent evt) {
+// log(evt);
+// String tip = null;
+// java.awt.Point p = evt.getPoint();
+ int rowIndex = rowAtPoint(evt.getPoint());
+ int colIndex = columnAtPoint(evt.getPoint());
+ synchronized (errorCheckerService.problemsList) {
+ if (rowIndex < errorCheckerService.problemsList.size()) {
+ Problem p = errorCheckerService.problemsList.get(rowIndex);
+ if (p.getImportSuggestions() != null
+ && p.getImportSuggestions().length > 0) {
+ String[] list = p.getImportSuggestions();
+ String className = list[0].substring(list[0].lastIndexOf('.') + 1);
+ String[] temp = new String[list.length];
+ for (int i = 0; i < list.length; i++) {
+ temp[i] = "Import '" + className + "' (" + list[i] + ")";
+ }
+ showImportSuggestion(temp, evt.getXOnScreen(), evt.getYOnScreen() - 3 * thisTable.getFont().getSize());
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+
+ }
+ });
// Handles the resizing of columns. When mouse press is detected on
// table header, Stop updating the table, store new values of column
@@ -111,8 +180,9 @@ public class XQErrorTable extends JTable {
}
}
});
+
+ ToolTipManager.sharedInstance().registerComponent(this);
}
-
/**
* Updates table contents with new data
@@ -163,5 +233,79 @@ public class XQErrorTable extends JTable {
}
return true;
}
+ JFrame frmImportSuggest;
+ private void showImportSuggestion(String list[], int x, int y){
+ if(frmImportSuggest != null) {
+// frmImportSuggest.setVisible(false);
+// frmImportSuggest = null;
+ return;
+ }
+ final JList classList = new JList(list);
+ classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ frmImportSuggest = new JFrame();
+
+ frmImportSuggest.setUndecorated(true);
+ frmImportSuggest.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBackground(Color.WHITE);
+ frmImportSuggest.setBackground(Color.WHITE);
+ panel.add(classList);
+ JLabel label = new JLabel("
(Click to insert)
");
+ label.setBackground(Color.WHITE);
+ label.setHorizontalTextPosition(SwingConstants.CENTER);
+ panel.add(label);
+ panel.validate();
+ frmImportSuggest.getContentPane().add(panel);
+ frmImportSuggest.pack();
+
+ final DebugEditor editor = errorCheckerService.getEditor();
+ classList.addListSelectionListener(new ListSelectionListener() {
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (classList.getSelectedValue() != null) {
+ try {
+ String t = classList.getSelectedValue().trim();
+ log(t);
+ int x = t.indexOf('(');
+ String impString = "import " + t.substring(x + 1, t.indexOf(')')) + ";\n";
+ int ct = editor.getSketch().getCurrentCodeIndex();
+ editor.getSketch().setCurrentCode(0);
+ editor.textArea().getDocument().insertString(0, impString, null);
+ editor.getSketch().setCurrentCode(ct);
+ } catch (BadLocationException ble) {
+ log("Failed to insert import");
+ ble.printStackTrace();
+ }
+ }
+ frmImportSuggest.setVisible(false);
+ frmImportSuggest.dispose();
+ frmImportSuggest = null;
+ }
+ });
+
+ frmImportSuggest.addWindowFocusListener(new WindowFocusListener() {
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ if (frmImportSuggest != null) {
+ frmImportSuggest.dispose();
+ frmImportSuggest = null;
+ }
+ }
+
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+
+ }
+ });
+ frmImportSuggest.setLocation(x, y);
+ frmImportSuggest.setBounds(x, y, 250, 100);
+ frmImportSuggest.pack();
+ frmImportSuggest.setVisible(true);
+
+ }
+
}