├── .classpath ├── .externalToolBuilders └── Ant_Builder.launch ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── README.md ├── Todo, GSoC 2013.txt ├── application ├── Info.plist.tmpl ├── sketch.icns ├── template.app │ └── Contents │ │ ├── MacOS │ │ └── JavaApplicationStub │ │ ├── PkgInfo │ │ └── Resources │ │ └── sketch.icns ├── template.exe └── template.plist ├── build.properties ├── build.xml ├── data └── icons │ ├── class_obj.png │ ├── field_default_obj.png │ ├── field_icon.png │ ├── field_private_obj.png │ ├── field_protected_obj.png │ ├── field_public_obj.png │ ├── info_icon.png │ ├── innerclass_private_obj.png │ ├── innerclass_protected_obj.png │ ├── methdef_obj.png │ ├── methpri_obj.png │ ├── methpro_obj.png │ ├── methpub_obj.png │ ├── refresh_icon.png │ └── sort_icon.png ├── keywords.txt ├── mode.properties ├── mode ├── .gitignore ├── CompilationChecker.jar ├── classpath-explorer-1.0.jar ├── com.ibm.icu_4.4.2.v20110823.jar ├── jdi-src.zip ├── jdi.jar ├── jdimodel-src.zip ├── jdimodel.jar ├── jsoup-1.7.1-javadoc.jar ├── jsoup-1.7.1.jar ├── org.eclipse.core.contenttype_3.4.200.v20120523-2004.jar ├── org.eclipse.core.jobs_3.5.300.v20120622-204750.jar ├── org.eclipse.core.resources_3.8.1.v20120802-154922.jar ├── org.eclipse.core.runtime_3.8.0.v20120521-2346.jar ├── org.eclipse.equinox.common_3.6.100.v20120522-1841.jar ├── org.eclipse.equinox.preferences_3.5.0.v20120522-1841.jar ├── org.eclipse.jdt.core_3.8.2.v20120814-155456.jar ├── org.eclipse.jdt.debug_3.7.101.v20120725-115645.jar ├── org.eclipse.osgi_3.8.1.v20120830-144521.jar ├── org.eclipse.text_3.5.200.v20120523-1310.jar └── readme.txt ├── pdeX.txt ├── revisions.txt ├── src └── processing │ └── mode │ └── experimental │ ├── ASTGenerator.java │ ├── ASTNodeWrapper.java │ ├── ArrayFieldNode.java │ ├── AutoSaveUtil.java │ ├── ClassLoadListener.java │ ├── Compiler.java │ ├── CompletionCandidate.java │ ├── CompletionPanel.java │ ├── DebugBuild.java │ ├── DebugEditor.java │ ├── DebugRunner.java │ ├── DebugToolbar.java │ ├── Debugger.java │ ├── ErrorBar.java │ ├── ErrorCheckerService.java │ ├── ErrorMarker.java │ ├── ErrorMessageSimplifier.java │ ├── ErrorWindow.java │ ├── ExperimentalMode.java │ ├── FieldNode.java │ ├── ImportStatement.java │ ├── JavadocHelper.java │ ├── LineBreakpoint.java │ ├── LineHighlight.java │ ├── LineID.java │ ├── LineListener.java │ ├── LocalVariableNode.java │ ├── OffsetMatcher.java │ ├── Problem.java │ ├── SketchOutline.java │ ├── TextArea.java │ ├── TextAreaPainter.java │ ├── Utils.java │ ├── VMEventListener.java │ ├── VMEventReader.java │ ├── VariableInspector.form │ ├── VariableInspector.java │ ├── VariableNode.java │ ├── XQConsoleToggle.java │ ├── XQErrorTable.java │ └── XQPreprocessor.java ├── theme ├── buttons-2x.png ├── buttons-debug-2x.png ├── buttons-debug.png ├── buttons.png ├── mode-2x.png ├── mode.png ├── theme.txt └── var-icons.gif └── todo.txt /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.externalToolBuilders/Ant_Builder.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .AppleDouble 3 | ._* 4 | *~ 5 | bin 6 | mode/ExperimentalMode.jar 7 | dist 8 | build.properties -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | processing-experimental 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.ui.externaltools.ExternalToolBuilder 15 | 16 | 17 | LaunchConfigHandle 18 | <project>/.externalToolBuilders/Ant_Builder.launch 19 | 20 | 21 | 22 | 23 | 24 | org.eclipse.jdt.core.javanature 25 | 26 | 27 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Update**: This repo is no longer active. PDE X codebase was merged into the [main processing repo](https://github.com/processing/processing/) starting with the 3.0 alpha releases (July 2014), further development continues in the main repo. So please report any issues in the main Processing repo. 2 | 3 | PDE X 4 | ===== 5 | 6 | PDE X is a [Processing](http://processing.org/) Mode that brings powerful new features to the Processing Development Environment: 7 | 8 | * Intelligent Code Completion 9 | * Quick Renaming(Refactoring) 10 | * Quick Navigation 11 | * Import Suggestions 12 | * Live Error Checker 13 | * Integrated Debugger 14 | 15 | Find out more at [Getting Started](https://github.com/processing/processing-experimental/wiki/Getting-Started). Or checkout the [FAQ](https://github.com/processing/processing-experimental/wiki/FAQ) 16 | 17 | ####How to Install 18 | 19 | ![Mode Button](http://i.imgur.com/cag1y10.png) 20 | 21 | Click on the down arrow besides the mode switch button, and select Add Mode. In the Mode Manager window, select PDE X and click 'Install'. You'll need Processing 2.0.2 or higher. 22 | 23 | For installing it manually, download the latest version from [here](http://download.processing.org/pdeX.zip). Extract the zip contents into `/modes` folder. Restart Processing. 24 | 25 | Manindra Moharana 26 | 27 | 21 October 2013 28 | 29 | -- 30 | PDE X is supported by [Google Summer of Code 2013](http://www.google-melange.com/gsoc/homepage/google/gsoc2013) -------------------------------------------------------------------------------- /Todo, GSoC 2013.txt: -------------------------------------------------------------------------------- 1 | TODO List for Experimental Mode Plus- GSOC 2013 2 | 3 | This would also be a break down of my thought process and ideas as I tackle various tasks. Also lines are fairly long. Make sure you turn on word wrap. ;) 4 | 5 | Manindra Moharana (me@mkmoharana.com) 6 | 7 | [ ]: Todo, [x] : Done, ? : Undecided Todo, ! : Critical, + : Minor Todo 8 | 9 | Code Completion 10 | =============== 11 | 12 | The big stuff: 13 | 14 | *! May be I should just implement recursive find for compiled code first, see how it goes and hopefully it would give me some ideas about how to integrating the two. 15 | - Making very good progress here. The elegance of recurion - Hats off! 16 | - Many of the cases seem to have been covered, and I'm achieving more and more code unification as I'm working through the problem step by step 17 | - Looks almost complete now, nearly all cases covered(July 13th) 18 | x After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location. Fixed. 19 | [ ]Keyboard Shortcut for completion popup - Ctrl + Space 20 | [ ]Scope handling? Static/non static scope? 21 | [ ]Disable completions on comment line 22 | [ ]Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. 23 | 24 | [x]Ensure that a compilation unit is created at startup! 25 | x! Code competition for local code is working with recursive look up. 26 | [x]Completion doesn't seem to show up for fields of a type defined locally. But works for methods with return type defined locally. Take ideas. Some case missing most probably. Fixed 27 | [x]Discovered another major issue due to offset differences -> While looking for predictions, if the parsed string contains pde enhancements, predictions FAIL! Zomg. 28 | Ex - "s.substring(int(13.4))." fails. Thinking to just do the substitutions before sending it to updatePredictions(), coz offsets aren't really a concern here, right? Yup, fixed it! 29 | x! Code completion with library code, non-nested seems to be broken, fix it. Fixed. 30 | [x]Completion for external classes - ArrayList, HashMap, etc. 31 | x! Recursive lookup for compiled(library) code! 32 | x! Library CC for nested would be tricky. Need to jump from local->compiled code while searching recursively. Recursive find's current implementation is based on ASTNode return type. Afaik, no way to instantiate orphaned ASTNode objects(or did I miss it?). ASTNode objects have to be created only from the main ast instance. But I need to find a way to switch to compiled instances from local class instance. 33 | x! Should I implement wrapper for ASTNode? - possibly needed for code completion with compiled and non-compiled code. Done. 34 | [x]Differentiating between multiple statements on the same line. How to? Done with offset handling. 35 | [x]- Cache predictions if current 'word' is increasing in length. If already showing predictions beginning with 's', for 'sa', remove extra completions, rather than recalculating predictions. Performance increase. 36 | [x]Parameterized type support is broken. 37 | [x]Array types, all all other types support broken. :\ 38 | [x]Completion for array access, strings[0]. 39 | 40 | Finer details 41 | 42 | [ ]findDeclarations should support 3rd party classes too. It's about time. ;) 43 | [ ]printStuff(int,float,String) - completion endings have to be appropriate. Right now it's just printStuff(,,). Cursor positioning also needs to be taken care of(done). Argument list as tooltip if possible? 44 | *! p5 enhanced stuff in java, how does it fit in with everything else, and edge cases. Possibly add support for them. Offset handling improvements should help here. 45 | [ ]Diamond operator isn't supported for now. Bummer. 46 | 47 | [x]Completion popup height is now dynamic, decreases to fit. 48 | [ ]Completion width can be dynamic, if really needed.. 49 | [x]Icons for completions? Or overkill right now? 50 | [x]'Show Usage' menu item added 51 | [x]Show declaring class for completions 52 | x! Ignore String case while finding completion candidates 53 | [x]Multiple 3rd party classes found in various packages. Not a chance no more. 54 | [x]Obj a1; a1.-> completion doesn't work before it is instantiated. Look into that. Began working again by itself. Yay! 55 | [x]Cursor positioning should be after the first ( if arguments present, else after () 56 | [x]Display the type of Completion(method return type, variable type) in the popup. 57 | - facing some issues for local types. Fixed. 58 | [x]Sorted list of completion candidates - fields, then methods. It's unsorted presently. 59 | [x]Reflection API - getMethods vs getDeclaredMethods. declared. 60 | [x]Need to add offset correction to ASTGenerator and its lookup methods. Or leave it for later? All set to implement 61 | [x]Completion List should get hidden on hitting esc key 62 | 63 | Offset Mapping 64 | ============== 65 | 66 | First major hurdle is offset mapping 67 | *! pde<->java code offset : precise conversion needed 68 | [ ]W.r.t PDE specific enhancements, things are almost working. There are some offset issues when multiple pde statements are in the same line, but I guess it's good enough for now to proceed ahead. Will keep a close watch for potential bugs. 69 | [x]for the above, I've decide to first implement a sketch outline like feature, which would highlight an AST element precisely in the pde code. This would ensure I've got the mapping working properly. And may lead to a future feature. 70 | [x]This is precise upto a certain line. Once on a line, pde stuff have to be taken into consideration. 71 | [x]Edge case - multiple statements in a single line 72 | [x]PDE specific enhancements will also have to be tackled like int(), # literals. The length of the node returned needs to be modified to make up for extra chars added like PApplet.parseFloat, etc. Also the 2nd or futher pde enhancements in the same line means even the beginning offset would need adjustment. Meh. 73 | 74 | Refactoring 75 | =========== 76 | 77 | [ ]Undo misbehaves here, handle carefully. 78 | [ ]Fails to rename the first defined global variable, if a javadoc comment precedes it. But owrds for single/multiline comments. Wth! 79 | [x]New Name is validated. 80 | [x]Ordered list in 'Show Usage' window 81 | [x]Add support for word select on right click and rename, mouse co-ordinates need to obtained carefully 82 | 83 | Refactoring would work only when code is compiler error free. I plan to do a find replace type op on the compile ready code. 84 | 1. First identify the declaration of the variable in the AST. We'll then make a list of all its occurrences. 85 | 2. DFS through the AST, for each (SimpleName)instance of the word in code, find if the matched word is the same one whose declaration we found. 86 | [x]Edge Case: For renaming a TypeDeclaration, the declaration of SimpleName instance of the TD and it's constructor(s) aren't added to the list generated by DFS. So for renaming TD, will have to manually add the TD SimpleName and it's constructors' SimpleNames to the a list of declaration nodes that can be positively matched against. 87 | [x]Renaming any constructor is equivalent to renaming the TD 88 | 3. Find corresponding PDE offsets of the SimpleNames, rename in each line. 89 | [x]Edge Case: Need to take displaced offsets on a line, due to pde enhancements, into consideration. 90 | 4. All the changes in code would be made in a separate copy of the code(?). After all the renaming is done, allow it only if the new code compiles. Basically an undo should be possible in case of conflicts. 91 | [x]Refactoring ui 92 | [x]For now, user needs to highlight the name of the var, and then right-click -> Rename.. 93 | [x]Handle saving. If sketch closed after renaming w/o saving find bugs. Done, marking the sketch as modified after renaming. 94 | 95 | Quick Navigation 96 | ================ 97 | 98 | *+ A silly bug where the name of the first field declaration isn't highlighted correctly. Seems to be happening if there's a javadoc or multiline comment near about the top. 99 | 100 | [x]On OS X, Ctrl + Click is right mouse click, so implement Cmd + Click instead. isMetaDown()? 101 | [x]Ctrl + Click on an element to scroll to its definition in code 102 | [x]Local Vars 103 | [x]Local Methods 104 | [x]Local Classes 105 | [x]Recursive lookup, a.b().c() 106 | [x]Now highlihgting the declaration name, rather than the whole declaration. 107 | 108 | Sketch Outline 109 | ============== 110 | 111 | [x]Show Sketch Outline Tree 112 | [x]Filter stuff in text field 113 | [x]Add icons - custom cell renderer 114 | 115 | Suggestion for missing imports 116 | ============================== 117 | 118 | [ ]Find a more subtle way to suggest for imports. The current method is too troublesome. Randomly pops up offering suggestions. May intimidate beginners. 119 | 120 | 1. In compileCheck() in ECS, check if error message is of the type "__" cannot be resolved to a type. 121 | 2. Find the class name via astGen, and suggest import as a popup. 122 | [x]Barebones functionality done. 123 | [x]Add imports only to beginning of first tab. 124 | [x]Search within contributed libraries folder 125 | [x]Hide suggestion list before showing import suggestions 126 | [x]Search within code folder of sketch 127 | 128 | Labels for Java elements 129 | ======================== 130 | 131 | [x]Working for local code 132 | [ ]Need to modify getASTNodeAt to also fetch the type for predefined classes. 133 | [ ]Labels for predefined class objects 134 | [ ]Chaining support for labels 135 | 136 | Synchronization 137 | =============== 138 | 139 | Gotta do it carefully between main thread, ECS Thread, and SwingWorker threads 140 | Fields that are concurrently accessed: 141 | 142 | ECS members: 143 | [x]ArrayList problems - updated in ECS, accessed by ErrorBar.update() 144 | [x]ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() 145 | [x]hasErrors, syntaxErrors - Atomic Boolean 146 | [x]boolean warningsEnabled - made it volatile 147 | [ ]CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( 148 | 149 | 150 | General Stuff 151 | ============= 152 | 153 | [ ][Critical] PermGen out of memory bug. Manually triggering GC after making the classloader null ensures permgen memory is reclaimed on editor exit. Max open window still limited by max permgen size. Also, added a classloadcounter in ECS to trigger GC periodically. 154 | https://github.com/processing/processing-experimental/issues/1 155 | See: http://stackoverflow.com/questions/2095974/how-to-unload-a-already-loaded-class-in-java 156 | I'm making the classLoader null, but what about the classes loaded by ASTGen? Investigate. 157 | [x]Disabling Error Checking disables predictions as well! Fixed. 158 | [x]Added doc listener for text area updates 159 | [x]Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file 160 | [x]Save preferences to main preference.txt 161 | [x]Hide breakpoint markers when Debugger isn't active 162 | [x]Ensure gutter mouse handler is taken care of when hiding Debugger breakpoint bar. 163 | [x]Ensure all editor windows are closed when editor is closed. 164 | [x]Add a red marker near Errors label in console toggle, to indicate errors present in sketch. 165 | [x]Add option for toggling debug output 166 | [x]On Run/Debug Console is visible(ProblemsList hidden) 167 | [ ]Update wiki for Ctrl + H instead of Ctrl + J shortcuts 168 | [x]update build.xml to produce dists 169 | [x]Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc 170 | [x]Add GitHub link to PDE X Menu 171 | -------------------------------------------------------------------------------- /application/Info.plist.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | @@sketch@@ 9 | CFBundleIconFile 10 | sketch.icns 11 | CFBundleIdentifier 12 | @@sketch@@ 13 | CFBundleDisplayName 14 | @@sketch@@ 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | @@sketch@@ 19 | CFBundlePackageType 20 | APPL 21 | 22 | 23 | CFBundleShortVersionString 24 | 1 25 | CFBundleVersion 26 | 1 27 | CFBundleSignature 28 | ???? 29 | NSHumanReadableCopyright 30 | Your copyright here 31 | CFBundleGetInfoString 32 | Created with Processing 33 | 34 | 35 | @@jvm_runtime@@ 36 | 37 | JVMMainClassName 38 | @@sketch@@ 39 | 40 | LSMinimumSystemVersion 41 | 10.7.3 42 | 43 | NSHighResolutionCapable 44 | 45 | 46 | LSArchitecturePriority 47 | 48 | x86_64 49 | 50 | 51 | LSEnvironment 52 | 53 | LC_CTYPE 54 | UTF-8 55 | 56 | 57 | LSUIPresentationMode 58 | @@lsuipresentationmode@@ 59 | 60 | JVMOptions 61 | 62 | @@jvm_options_list@@ 63 | -Xdock:icon=Contents/Resources/sketch.icns 64 | -Dapple.laf.useScreenMenuBar=true 65 | -Dcom.apple.macos.use-file-dialog-packages=true 66 | -Dcom.apple.macos.useScreenMenuBar=true 67 | -Dcom.apple.mrj.application.apple.menu.about.name=@@sketch@@ 68 | -Dcom.apple.smallTabs=true 69 | 70 | JVMArguments 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /application/sketch.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/application/sketch.icns -------------------------------------------------------------------------------- /application/template.app/Contents/MacOS/JavaApplicationStub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/application/template.app/Contents/MacOS/JavaApplicationStub -------------------------------------------------------------------------------- /application/template.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /application/template.app/Contents/Resources/sketch.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/application/template.app/Contents/Resources/sketch.icns -------------------------------------------------------------------------------- /application/template.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/application/template.exe -------------------------------------------------------------------------------- /application/template.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | @@sketch@@ 7 | CFBundleVersion 8 | 1.0 9 | CFBundleAllowMixedLocalizations 10 | true 11 | CFBundleExecutable 12 | JavaApplicationStub 13 | CFBundleDevelopmentRegion 14 | English 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | ???? 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleIconFile 22 | sketch.icns 23 | CFBundleIdentifier 24 | @@sketch@@ 25 | 26 | 27 | LSUIPresentationMode 28 | @@lsuipresentationmode@@ 29 | 30 | LSArchitecturePriority 31 | 32 | @@lsarchitecturepriority@@ 33 | 34 | 35 | Java 36 | 37 | VMOptions 38 | @@vmoptions@@ 39 | 40 | MainClass 41 | @@sketch@@ 42 | 43 | 45 | JVMVersion 46 | 1.6* 47 | 48 | ClassPath 49 | @@classpath@@ 50 | 51 | 52 | Properties 53 | 54 | apple.laf.useScreenMenuBar 55 | true 56 | apple.awt.showGrowBox 57 | false 58 | com.apple.smallTabs 59 | true 60 | apple.awt.Antialiasing 61 | false 62 | apple.awt.TextAntialiasing 63 | true 64 | com.apple.hwaccel 65 | true 66 | 72 | apple.awt.use-file-dialog-packages 73 | true 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | sketchbook.location=${user.home}/Documents/Processing 2 | classpath.local.location=${user.home}/Documents/workspace/libs 3 | core.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/core/library 4 | app.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/ 5 | java.target.version=1.7 6 | lib.name=ExperimentalMode 7 | prettyName=PDE X 8 | dist=dist 9 | release=7 10 | prettyVersion=1.0.4b 11 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /data/icons/class_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/class_obj.png -------------------------------------------------------------------------------- /data/icons/field_default_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/field_default_obj.png -------------------------------------------------------------------------------- /data/icons/field_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/field_icon.png -------------------------------------------------------------------------------- /data/icons/field_private_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/field_private_obj.png -------------------------------------------------------------------------------- /data/icons/field_protected_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/field_protected_obj.png -------------------------------------------------------------------------------- /data/icons/field_public_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/field_public_obj.png -------------------------------------------------------------------------------- /data/icons/info_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/info_icon.png -------------------------------------------------------------------------------- /data/icons/innerclass_private_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/innerclass_private_obj.png -------------------------------------------------------------------------------- /data/icons/innerclass_protected_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/innerclass_protected_obj.png -------------------------------------------------------------------------------- /data/icons/methdef_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/methdef_obj.png -------------------------------------------------------------------------------- /data/icons/methpri_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/methpri_obj.png -------------------------------------------------------------------------------- /data/icons/methpro_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/methpro_obj.png -------------------------------------------------------------------------------- /data/icons/methpub_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/methpub_obj.png -------------------------------------------------------------------------------- /data/icons/refresh_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/refresh_icon.png -------------------------------------------------------------------------------- /data/icons/sort_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/data/icons/sort_icon.png -------------------------------------------------------------------------------- /mode.properties: -------------------------------------------------------------------------------- 1 | name=PDE X 2 | authorList=[The Processing Foundation](http://processing.org) 3 | url=https://github.com/processing/processing-experimental 4 | sentence=The next generation of PDE 5 | paragraph=Intelligent Code Completion, Quick Navigation, Refactoring, Live Error Checker, Debugger, etc. 6 | version=@@version@@ 7 | prettyVersion=@@pretty-version@@ 8 | -------------------------------------------------------------------------------- /mode/.gitignore: -------------------------------------------------------------------------------- 1 | experimental.jar 2 | -------------------------------------------------------------------------------- /mode/CompilationChecker.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/CompilationChecker.jar -------------------------------------------------------------------------------- /mode/classpath-explorer-1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/classpath-explorer-1.0.jar -------------------------------------------------------------------------------- /mode/com.ibm.icu_4.4.2.v20110823.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/com.ibm.icu_4.4.2.v20110823.jar -------------------------------------------------------------------------------- /mode/jdi-src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jdi-src.zip -------------------------------------------------------------------------------- /mode/jdi.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jdi.jar -------------------------------------------------------------------------------- /mode/jdimodel-src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jdimodel-src.zip -------------------------------------------------------------------------------- /mode/jdimodel.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jdimodel.jar -------------------------------------------------------------------------------- /mode/jsoup-1.7.1-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jsoup-1.7.1-javadoc.jar -------------------------------------------------------------------------------- /mode/jsoup-1.7.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/jsoup-1.7.1.jar -------------------------------------------------------------------------------- /mode/org.eclipse.core.contenttype_3.4.200.v20120523-2004.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.core.contenttype_3.4.200.v20120523-2004.jar -------------------------------------------------------------------------------- /mode/org.eclipse.core.jobs_3.5.300.v20120622-204750.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.core.jobs_3.5.300.v20120622-204750.jar -------------------------------------------------------------------------------- /mode/org.eclipse.core.resources_3.8.1.v20120802-154922.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.core.resources_3.8.1.v20120802-154922.jar -------------------------------------------------------------------------------- /mode/org.eclipse.core.runtime_3.8.0.v20120521-2346.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.core.runtime_3.8.0.v20120521-2346.jar -------------------------------------------------------------------------------- /mode/org.eclipse.equinox.common_3.6.100.v20120522-1841.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.equinox.common_3.6.100.v20120522-1841.jar -------------------------------------------------------------------------------- /mode/org.eclipse.equinox.preferences_3.5.0.v20120522-1841.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.equinox.preferences_3.5.0.v20120522-1841.jar -------------------------------------------------------------------------------- /mode/org.eclipse.jdt.core_3.8.2.v20120814-155456.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.jdt.core_3.8.2.v20120814-155456.jar -------------------------------------------------------------------------------- /mode/org.eclipse.jdt.debug_3.7.101.v20120725-115645.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.jdt.debug_3.7.101.v20120725-115645.jar -------------------------------------------------------------------------------- /mode/org.eclipse.osgi_3.8.1.v20120830-144521.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.osgi_3.8.1.v20120830-144521.jar -------------------------------------------------------------------------------- /mode/org.eclipse.text_3.5.200.v20120523-1310.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/mode/org.eclipse.text_3.5.200.v20120523-1310.jar -------------------------------------------------------------------------------- /mode/readme.txt: -------------------------------------------------------------------------------- 1 | Packages from Eclipse 4.2.1: 2 | http://download.eclipse.org/eclipse/downloads/ 3 | 4 | The jdi.jar and jdimodel.jar files are unpacked 5 | from the org.eclipse.jdt.debug JAR file. 6 | -------------------------------------------------------------------------------- /pdeX.txt: -------------------------------------------------------------------------------- 1 | name=PDE X 2 | authorList=[The Processing Foundation](http://processing.org) 3 | url=https://github.com/processing/processing-experimental 4 | sentence=The next generation of PDE 5 | paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. 6 | version=7 7 | prettyVersion=1.0.4b 8 | -------------------------------------------------------------------------------- /revisions.txt: -------------------------------------------------------------------------------- 1 | 2 | PDE X v1.0.4b - May 9, 2014 3 | 4 | Requires Processing 2.1.2 or above. 5 | 6 | Bug fixes 7 | 8 | + Disabled auto-save. My sincere apologies to those who lost data due 9 | to this bug. It was wrong of me to release an untested feature without 10 | adding an option to enable/disable it. I've learnt a lesson and I shall 11 | ensure this sort of thing doesn't happen again in the future. 12 | 13 | + Autocompletion bug, column is sometimes off by 1 14 | https://github.com/processing/processing-experimental/issues/38 15 | 16 | + Persistent completion dialog on OS X 17 | https://github.com/processing/processing-experimental/issues/32 18 | 19 | + Status bar update bug 20 | https://github.com/processing/processing-experimental/issues/29 21 | 22 | + Export application broken 23 | https://github.com/processing/processing-experimental/issues/45 24 | 25 | + Status Bar - New Tab prompt bug 26 | https://github.com/processing/processing-experimental/issues/53 27 | 28 | + Show usage fails for methods which have javadoc comment 29 | https://github.com/processing/processing-experimental/issues/51 30 | 31 | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 | 33 | PDE X v1.0.3b - January 21, 2014 34 | 35 | New Feature 36 | 37 | + PDE X now saves a backup of your sketch every 3 minutes(configurable in preferences.txt). 38 | In case of an unexpected crash, this should save the day! 39 | https://github.com/processing/processing-experimental/issues/36 40 | 41 | Bug fixes 42 | 43 | + Outline Window width is now fixed 44 | https://github.com/processing/processing-experimental/issues/31 45 | 46 | + Export Application works again on OS X 47 | https://github.com/processing/processing-experimental/issues/33 48 | 49 | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 | 51 | PDE X v1.0.2b - October 21, 2013 52 | 53 | Bug fixes 54 | 55 | + Code completion window gets stuck when Processing loses focus 56 | https://github.com/processing/processing-experimental/issues/21 57 | 58 | + Live-error checker is more efficient with memory now. 59 | You can have upto 7 editor windows open at a time with PDE X. 60 | https://github.com/processing/processing-experimental/issues/1 61 | 62 | + Cmd + Left Click should be working again in OS X with Processing 2.1 63 | https://github.com/processing/processing-experimental/issues/11 64 | 65 | + TextAreaPainter updated for Processing 2.1 66 | 67 | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 | 69 | PDE X v1.0.1b - 25 September, 2013 70 | 71 | Bug fix 72 | 73 | + Fixed a major issue where completion list was going blank. 74 | https://github.com/processing/processing-experimental/issues/19 75 | 76 | Changes 77 | 78 | - Removed the tiny markers shown at the start of error lines. Too. Much. Red. 79 | 80 | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 | 82 | PDE X v1.0.0b - 22 September, 2013 83 | 84 | Boom! First Public Beta Release! 85 | 86 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ArrayFieldNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.ArrayReference; 21 | import com.sun.jdi.ClassNotLoadedException; 22 | import com.sun.jdi.InvalidTypeException; 23 | import com.sun.jdi.Value; 24 | import java.util.logging.Level; 25 | import java.util.logging.Logger; 26 | 27 | /** 28 | * Specialized {@link VariableNode} for representing single fields in an array. 29 | * Overrides {@link #setValue} to properly change the value of the encapsulated 30 | * array field. 31 | * 32 | * @author Martin Leopold 33 | */ 34 | public class ArrayFieldNode extends VariableNode { 35 | 36 | protected ArrayReference array; 37 | protected int index; 38 | 39 | /** 40 | * Construct an {@link ArrayFieldNode}. 41 | * 42 | * @param name the name 43 | * @param type the type 44 | * @param value the value 45 | * @param array a reference to the array 46 | * @param index the index inside the array 47 | */ 48 | public ArrayFieldNode(String name, String type, Value value, ArrayReference array, int index) { 49 | super(name, type, value); 50 | this.array = array; 51 | this.index = index; 52 | } 53 | 54 | @Override 55 | public void setValue(Value value) { 56 | try { 57 | array.setValue(index, value); 58 | } catch (InvalidTypeException ex) { 59 | Logger.getLogger(ArrayFieldNode.class.getName()).log(Level.SEVERE, null, ex); 60 | } catch (ClassNotLoadedException ex) { 61 | Logger.getLogger(ArrayFieldNode.class.getName()).log(Level.SEVERE, null, ex); 62 | } 63 | this.value = value; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/AutoSaveUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-14 Manindra Moharana 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | 19 | package processing.mode.experimental; 20 | 21 | import java.io.File; 22 | import java.io.FileFilter; 23 | import java.io.IOException; 24 | import java.util.Timer; 25 | import java.util.TimerTask; 26 | 27 | import processing.app.Base; 28 | import processing.app.Sketch; 29 | 30 | import static processing.mode.experimental.ExperimentalMode.log; 31 | 32 | /** 33 | * Autosave utility for saving sketch backups in the background after 34 | * certain intervals 35 | * 36 | * @author Manindra Moharana 37 | * 38 | */ 39 | public class AutoSaveUtil { 40 | 41 | private DebugEditor editor; 42 | 43 | private Timer timer; 44 | 45 | private int saveTime; 46 | 47 | private File autosaveDir, pastSave; 48 | 49 | private boolean isSaving; 50 | 51 | private boolean isAutoSaveBackup; 52 | 53 | private File sketchFolder, sketchBackupFolder; 54 | 55 | private static final String AUTOSAVEFOLDER = "__autosave__"; 56 | 57 | /** 58 | * 59 | * @param dedit 60 | * @param timeOut - in minutes, how frequently should saves occur 61 | */ 62 | public AutoSaveUtil(DebugEditor dedit, int timeOut){ 63 | /* 64 | editor = dedit; 65 | if (timeOut < 1) { // less than 1 minute not allowed! 66 | saveTime = -1; 67 | throw new IllegalArgumentException(""); 68 | } 69 | else{ 70 | saveTime = timeOut * 60 * 1000; 71 | log("AutoSaver Interval(mins): " + timeOut); 72 | } 73 | checkIfBackup(); 74 | if(isAutoSaveBackup){ 75 | sketchBackupFolder = sketchFolder; 76 | } 77 | else{ 78 | autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + AUTOSAVEFOLDER); 79 | sketchFolder = editor.getSketch().getFolder(); 80 | sketchBackupFolder = autosaveDir; 81 | }*/ 82 | } 83 | 84 | /** 85 | * If the sketch path looks like ../__autosave__/../FooSketch 86 | * then assume this is a backup sketch 87 | */ 88 | private void checkIfBackup(){ 89 | File parent = sketchFolder.getParentFile().getParentFile(); 90 | if(parent.isDirectory() && parent.getName().equals(AUTOSAVEFOLDER)){ 91 | isAutoSaveBackup = true; 92 | log("IS AUTOSAVE " + sketchFolder.getAbsolutePath()); 93 | } 94 | } 95 | 96 | public File getActualSketchFolder(){ 97 | if(isAutoSaveBackup) 98 | return sketchFolder.getParentFile().getParentFile().getParentFile(); 99 | else 100 | return sketchFolder; 101 | } 102 | 103 | public boolean isAutoSaveBackup() { 104 | return isAutoSaveBackup; 105 | } 106 | 107 | /** 108 | * Check if any previous autosave exists 109 | * @return 110 | */ 111 | public boolean checkForPastSave(){ 112 | if(autosaveDir.exists()){ 113 | String prevSaves[] = Base.listFiles(autosaveDir, false); 114 | if(prevSaves.length > 0){ 115 | File t = new File(Base.listFiles(new File(prevSaves[0]), false)[0]); 116 | sketchBackupFolder = t; 117 | pastSave = new File(t.getAbsolutePath() + File.separator + t.getName() + ".pde"); 118 | if(pastSave.exists()) 119 | return true; 120 | } 121 | } 122 | return false; 123 | } 124 | 125 | /** 126 | * Refresh autosave directory if current sketch location in the editor changes 127 | */ 128 | public void reloadAutosaveDir(){ 129 | while(isSaving); 130 | autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + AUTOSAVEFOLDER); 131 | } 132 | 133 | public File getAutoSaveDir(){ 134 | return autosaveDir; 135 | } 136 | 137 | /** 138 | * The folder of the original sketch 139 | * @return 140 | */ 141 | public File getSketchFolder(){ 142 | return sketchFolder; 143 | } 144 | 145 | public File getSketchBackupFolder(){ 146 | return sketchBackupFolder; 147 | } 148 | 149 | public File getPastSave(){ 150 | return pastSave; 151 | } 152 | 153 | /** 154 | * Start the auto save service 155 | */ 156 | public void init(){ 157 | /* 158 | if(isAutoSaveBackup) { 159 | log("AutoSaver not started"); 160 | return; 161 | } 162 | if(saveTime < 10000) saveTime = 10 * 1000; 163 | saveTime = 5 * 1000; //TODO: remove 164 | timer = new Timer(); 165 | timer.schedule(new SaveTask(), saveTime, saveTime); 166 | isSaving = false; 167 | log("AutoSaver started"); 168 | */ 169 | } 170 | 171 | /** 172 | * Stop the autosave service 173 | */ 174 | public void stop(){ 175 | while(isSaving); // save operation mustn't be interrupted 176 | if(timer != null) timer.cancel(); 177 | Base.removeDir(autosaveDir); 178 | ExperimentalMode.log("Stopping autosaver and deleting backup dir"); 179 | } 180 | 181 | /** 182 | * Main function that performs the save operation 183 | * Code reused from processing.app.Sketch.saveAs() 184 | * @return 185 | * @throws IOException 186 | */ 187 | private boolean saveSketch() throws IOException{ 188 | if(!editor.getSketch().isModified()) return false; 189 | isSaving = true; 190 | Sketch sc = editor.getSketch(); 191 | 192 | boolean deleteOldSave = false; 193 | String oldSave = null; 194 | if(!autosaveDir.exists()){ 195 | autosaveDir = new File(sc.getFolder().getAbsolutePath(), AUTOSAVEFOLDER); 196 | autosaveDir.mkdir(); 197 | } 198 | else 199 | { 200 | // delete the previous backup after saving current one. 201 | String prevSaves[] = Base.listFiles(autosaveDir, false); 202 | if(prevSaves.length > 0){ 203 | deleteOldSave = true; 204 | oldSave = prevSaves[0]; 205 | } 206 | } 207 | String newParentDir = autosaveDir + File.separator + System.currentTimeMillis(); 208 | String newName = sc.getName(); 209 | 210 | 211 | // check on the sanity of the name 212 | String sanitaryName = Sketch.checkName(newName); 213 | File newFolder = new File(newParentDir, sanitaryName); 214 | if (!sanitaryName.equals(newName) && newFolder.exists()) { 215 | Base.showMessage("Cannot Save", 216 | "A sketch with the cleaned name\n" + 217 | "“" + sanitaryName + "” already exists."); 218 | isSaving = false; 219 | return false; 220 | } 221 | newName = sanitaryName; 222 | 223 | // String newPath = newFolder.getAbsolutePath(); 224 | // String oldPath = folder.getAbsolutePath(); 225 | 226 | // if (newPath.equals(oldPath)) { 227 | // return false; // Can't save a sketch over itself 228 | // } 229 | 230 | // make sure there doesn't exist a tab with that name already 231 | // but ignore this situation for the first tab, since it's probably being 232 | // resaved (with the same name) to another location/folder. 233 | for (int i = 1; i < sc.getCodeCount(); i++) { 234 | if (newName.equalsIgnoreCase(sc.getCode()[i].getPrettyName())) { 235 | Base.showMessage("Nope", 236 | "You can't save the sketch as \"" + newName + "\"\n" + 237 | "because the sketch already has a tab with that name."); 238 | isSaving = false; 239 | return false; 240 | } 241 | } 242 | 243 | 244 | 245 | // if the new folder already exists, then first remove its contents before 246 | // copying everything over (user will have already been warned). 247 | if (newFolder.exists()) { 248 | Base.removeDir(newFolder); 249 | } 250 | // in fact, you can't do this on Windows because the file dialog 251 | // will instead put you inside the folder, but it happens on OS X a lot. 252 | 253 | // now make a fresh copy of the folder 254 | newFolder.mkdirs(); 255 | 256 | // grab the contents of the current tab before saving 257 | // first get the contents of the editor text area 258 | if (sc.getCurrentCode().isModified()) { 259 | sc.getCurrentCode().setProgram(editor.getText()); 260 | } 261 | 262 | File[] copyItems = sc.getFolder().listFiles(new FileFilter() { 263 | public boolean accept(File file) { 264 | String name = file.getName(); 265 | // just in case the OS likes to return these as if they're legit 266 | if (name.equals(".") || name.equals("..")) { 267 | return false; 268 | } 269 | // list of files/folders to be ignored during "save as" 270 | for (String ignorable : editor.getMode().getIgnorable()) { 271 | if (name.equals(ignorable)) { 272 | return false; 273 | } 274 | } 275 | // ignore the extensions for code, since that'll be copied below 276 | for (String ext : editor.getMode().getExtensions()) { 277 | if (name.endsWith(ext)) { 278 | return false; 279 | } 280 | } 281 | // don't do screen captures, since there might be thousands. kind of 282 | // a hack, but seems harmless. hm, where have i heard that before... 283 | if (name.startsWith("screen-")) { 284 | return false; 285 | } 286 | return true; 287 | } 288 | }); 289 | // now copy over the items that make sense 290 | for (File copyable : copyItems) { 291 | if (copyable.isDirectory()) { 292 | Base.copyDir(copyable, new File(newFolder, copyable.getName())); 293 | } else { 294 | Base.copyFile(copyable, new File(newFolder, copyable.getName())); 295 | } 296 | } 297 | 298 | // save the other tabs to their new location 299 | for (int i = 1; i < sc.getCodeCount(); i++) { 300 | File newFile = new File(newFolder, sc.getCode()[i].getFileName()); 301 | sc.getCode()[i].saveAs(newFile); 302 | } 303 | 304 | // While the old path to the main .pde is still set, remove the entry from 305 | // the Recent menu so that it's not sticking around after the rename. 306 | // If untitled, it won't be in the menu, so there's no point. 307 | // if (!isUntitled()) { 308 | // editor.removeRecent(); 309 | // } 310 | 311 | // save the main tab with its new name 312 | File newFile = new File(newFolder, newName + ".pde"); 313 | sc.getCode()[0].saveAs(newFile); 314 | 315 | // updateInternal(newName, newFolder); 316 | // 317 | // // Make sure that it's not an untitled sketch 318 | // setUntitled(false); 319 | // 320 | // // Add this sketch back using the new name 321 | // editor.addRecent(); 322 | 323 | // let Editor know that the save was successful 324 | 325 | if(deleteOldSave){ 326 | Base.removeDir(new File(oldSave)); 327 | } 328 | isSaving = false; 329 | return true; 330 | } 331 | 332 | /** 333 | * Timertask used to perform the save operation every X minutes 334 | * @author quarkninja 335 | * 336 | */ 337 | private class SaveTask extends TimerTask{ 338 | 339 | @Override 340 | public void run() { 341 | try { 342 | if(saveSketch()) 343 | ExperimentalMode.log("Backup Saved " + editor.getSketch().getMainFilePath()); 344 | } catch (IOException e) { 345 | e.printStackTrace(); 346 | } 347 | 348 | } 349 | 350 | } 351 | 352 | } 353 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ClassLoadListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.ReferenceType; 21 | 22 | /** 23 | * Listener to be notified when a class is loaded in the debugger. Used by 24 | * {@link LineBreakpoint}s to activate themselves as soon as the respective 25 | * class is loaded. 26 | * 27 | * @author Martin Leopold 28 | */ 29 | public interface ClassLoadListener { 30 | 31 | /** 32 | * Event handler called when a class is loaded. 33 | * 34 | * @param theClass the class 35 | */ 36 | public void classLoaded(ReferenceType theClass); 37 | } 38 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/CompletionCandidate.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | import static processing.mode.experimental.ExperimentalMode.log; 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.List; 6 | 7 | import org.eclipse.jdt.core.dom.ASTNode; 8 | import org.eclipse.jdt.core.dom.FieldDeclaration; 9 | import org.eclipse.jdt.core.dom.MethodDeclaration; 10 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 11 | import org.eclipse.jdt.core.dom.TypeDeclaration; 12 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 13 | 14 | public class CompletionCandidate implements Comparable{ 15 | 16 | private String elementName; // 17 | 18 | private String label; // the toString value 19 | 20 | private String completionString; 21 | 22 | private Object wrappedObject; 23 | 24 | private int type; 25 | 26 | public static final int PREDEF_CLASS = 0, PREDEF_FIELD = 1, 27 | PREDEF_METHOD = 2, LOCAL_CLASS = 3, LOCAL_METHOD = 4, LOCAL_FIELD = 5, 28 | LOCAL_VAR = 6; 29 | 30 | public CompletionCandidate(Method method) { 31 | method.getDeclaringClass().getName(); 32 | elementName = method.getName(); 33 | StringBuffer label = new StringBuffer(method.getName() + "("); 34 | StringBuffer cstr = new StringBuffer(method.getName() + "("); 35 | for (int i = 0; i < method.getParameterTypes().length; i++) { 36 | label.append(method.getParameterTypes()[i].getSimpleName()); 37 | if (i < method.getParameterTypes().length - 1) { 38 | label.append(","); 39 | cstr.append(","); 40 | } 41 | } 42 | if(method.getParameterTypes().length == 1) { 43 | cstr.append(' '); 44 | } 45 | label.append(")"); 46 | if(method.getReturnType() != null) 47 | label.append(" : " + method.getReturnType().getSimpleName()); 48 | label.append(" - " + method.getDeclaringClass().getSimpleName()); 49 | cstr.append(")"); 50 | this.label = label.toString(); 51 | this.completionString = cstr.toString(); 52 | type = PREDEF_METHOD; 53 | wrappedObject = method; 54 | } 55 | 56 | public Object getWrappedObject() { 57 | return wrappedObject; 58 | } 59 | 60 | public CompletionCandidate(SingleVariableDeclaration svd) { 61 | completionString = svd.getName().toString(); 62 | elementName = svd.getName().toString(); 63 | if(svd.getParent() instanceof FieldDeclaration) 64 | type = LOCAL_FIELD; 65 | else 66 | type = LOCAL_VAR; 67 | label = svd.getName() + " : " + svd.getType(); 68 | } 69 | 70 | public CompletionCandidate(VariableDeclarationFragment vdf) { 71 | completionString = vdf.getName().toString(); 72 | elementName = vdf.getName().toString(); 73 | if(vdf.getParent() instanceof FieldDeclaration) 74 | type = LOCAL_FIELD; 75 | else 76 | type = LOCAL_VAR; 77 | label = vdf.getName() + " : " + ASTGenerator.extracTypeInfo2(vdf); 78 | } 79 | 80 | public CompletionCandidate(MethodDeclaration method) { 81 | // log("ComCan " + method.getName()); 82 | elementName = method.getName().toString(); 83 | type = LOCAL_METHOD; 84 | List params = (List) method 85 | .getStructuralProperty(MethodDeclaration.PARAMETERS_PROPERTY); 86 | StringBuffer label = new StringBuffer(elementName + "("); 87 | StringBuffer cstr = new StringBuffer(method.getName() + "("); 88 | for (int i = 0; i < params.size(); i++) { 89 | label.append(params.get(i).toString()); 90 | if (i < params.size() - 1) { 91 | label.append(","); 92 | cstr.append(","); 93 | } 94 | } 95 | if (params.size() == 1) { 96 | cstr.append(' '); 97 | } 98 | label.append(")"); 99 | if (method.getReturnType2() != null) 100 | label.append(" : " + method.getReturnType2()); 101 | cstr.append(")"); 102 | this.label = label.toString(); 103 | this.completionString = cstr.toString(); 104 | } 105 | 106 | public CompletionCandidate(TypeDeclaration td){ 107 | type = LOCAL_CLASS; 108 | elementName = td.getName().toString(); 109 | label = elementName; 110 | completionString = elementName; 111 | } 112 | 113 | public CompletionCandidate(Field f) { 114 | f.getDeclaringClass().getName(); 115 | elementName = f.getName(); 116 | type = PREDEF_FIELD; 117 | label = f.getName() + " : " + f.getType().getSimpleName() 118 | + " - " + f.getDeclaringClass().getSimpleName(); 119 | completionString = elementName; 120 | wrappedObject = f; 121 | } 122 | 123 | public CompletionCandidate(String name, String labelStr, String completionStr, int type) { 124 | elementName = name; 125 | label = labelStr; 126 | completionString = completionStr; 127 | this.type = type; 128 | } 129 | 130 | public CompletionCandidate(String name, int type) { 131 | elementName = name; 132 | label = name; 133 | completionString = name; 134 | this.type = type; 135 | } 136 | 137 | public String getElementName() { 138 | return elementName; 139 | } 140 | 141 | public String getCompletionString() { 142 | return completionString; 143 | } 144 | 145 | public String toString() { 146 | return label; 147 | } 148 | 149 | public int getType() { 150 | return type; 151 | } 152 | 153 | public int compareTo(CompletionCandidate cc) { 154 | if(type != cc.getType()){ 155 | return cc.getType() - type; 156 | } 157 | return (elementName.compareTo(cc.getElementName())); 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/DebugBuild.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import java.io.File; 21 | import processing.app.Sketch; 22 | import processing.app.SketchException; 23 | import processing.mode.java.JavaBuild; 24 | 25 | /** 26 | * Copied from processing.mode.java.JavaBuild, just changed compiler. 27 | * 28 | * @author Martin Leopold 29 | */ 30 | public class DebugBuild extends JavaBuild { 31 | 32 | public DebugBuild(Sketch sketch) { 33 | super(sketch); 34 | } 35 | 36 | /** 37 | * Preprocess and compile sketch. Copied from 38 | * processing.mode.java.JavaBuild, just changed compiler. 39 | * 40 | * @param srcFolder 41 | * @param binFolder 42 | * @param sizeWarning 43 | * @return main class name or null on compile failure 44 | * @throws SketchException 45 | */ 46 | @Override 47 | public String build(File srcFolder, File binFolder, boolean sizeWarning) throws SketchException { 48 | this.srcFolder = srcFolder; 49 | this.binFolder = binFolder; 50 | 51 | // Base.openFolder(srcFolder); 52 | // Base.openFolder(binFolder); 53 | 54 | // run the preprocessor 55 | String classNameFound = preprocess(srcFolder, sizeWarning); 56 | 57 | // compile the program. errors will happen as a RunnerException 58 | // that will bubble up to whomever called build(). 59 | // Compiler compiler = new Compiler(this); 60 | // String bootClasses = System.getProperty("sun.boot.class.path"); 61 | // if (compiler.compile(this, srcFolder, binFolder, primaryClassName, getClassPath(), bootClasses)) { 62 | 63 | if (Compiler.compile(this)) { // use compiler with debug info enabled (-g switch flicked) 64 | sketchClassName = classNameFound; 65 | return classNameFound; 66 | } 67 | return null; 68 | } 69 | 70 | public ExperimentalMode getMode() { 71 | return (ExperimentalMode)mode; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/DebugRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.VirtualMachine; 21 | import processing.app.RunnerListener; 22 | import processing.app.SketchException; 23 | import processing.app.exec.StreamRedirectThread; 24 | import processing.mode.java.JavaBuild; 25 | import processing.mode.java.runner.MessageSiphon; 26 | 27 | /** 28 | * Runs a {@link JavaBuild}. Launches the build in a new debuggee VM. 29 | * 30 | * @author Martin Leopold 31 | */ 32 | public class DebugRunner extends processing.mode.java.runner.Runner { 33 | 34 | // important inherited fields 35 | // protected VirtualMachine vm; 36 | public DebugRunner(JavaBuild build, RunnerListener listener) throws SketchException { 37 | super(build, listener); 38 | } 39 | 40 | /** 41 | * Launch the virtual machine. Simple non-blocking launch. VM starts 42 | * suspended. 43 | * 44 | * @return debuggee VM or null on failure 45 | */ 46 | public VirtualMachine launch() { 47 | // String[] machineParamList = getMachineParams(); 48 | // String[] sketchParamList = getSketchParams(false); 49 | // /* 50 | // * System.out.println("vm launch sketch params:"); for (int i=0; 51 | // * i 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import java.awt.Graphics; 21 | import java.awt.Image; 22 | import java.awt.event.MouseEvent; 23 | import java.awt.image.BufferedImage; 24 | import java.util.logging.Level; 25 | import java.util.logging.Logger; 26 | import processing.app.Base; 27 | import processing.app.Editor; 28 | import processing.app.Preferences; 29 | import processing.app.Toolkit; 30 | import processing.mode.java.JavaToolbar; 31 | 32 | /** 33 | * Custom toolbar for the editor window. Preserves original button numbers 34 | * ({@link JavaToolbar#RUN}, {@link JavaToolbar#STOP}, {@link JavaToolbar#NEW}, 35 | * {@link JavaToolbar#OPEN}, {@link JavaToolbar#SAVE}, {@link JavaToolbar#EXPORT}) 36 | * which can be used e.g. in {@link #activate} and 37 | * {@link #deactivate}. 38 | * 39 | * @author Martin Leopold 40 | */ 41 | public class DebugToolbar extends JavaToolbar { 42 | // preserve original button id's, but re-define so they are accessible 43 | // (they are used by DebugEditor, so they want to be public) 44 | 45 | static protected final int RUN = 100; // change this, to be able to get it's name via getTitle() 46 | static protected final int DEBUG = JavaToolbar.RUN; 47 | 48 | static protected final int CONTINUE = 101; 49 | static protected final int STEP = 102; 50 | static protected final int TOGGLE_BREAKPOINT = 103; 51 | static protected final int TOGGLE_VAR_INSPECTOR = 104; 52 | 53 | static protected final int STOP = JavaToolbar.STOP; 54 | 55 | static protected final int NEW = JavaToolbar.NEW; 56 | static protected final int OPEN = JavaToolbar.OPEN; 57 | static protected final int SAVE = JavaToolbar.SAVE; 58 | static protected final int EXPORT = JavaToolbar.EXPORT; 59 | 60 | 61 | // the sequence of button ids. (this maps button position = index to button ids) 62 | static protected final int[] buttonSequence = { 63 | DEBUG, CONTINUE, STEP, STOP, TOGGLE_BREAKPOINT, TOGGLE_VAR_INSPECTOR, 64 | NEW, OPEN, SAVE, EXPORT 65 | }; 66 | 67 | 68 | public DebugToolbar(Editor editor, Base base) { 69 | super(editor, base); 70 | } 71 | public Image[][] loadDebugImages() { 72 | int res = Toolkit.highResDisplay() ? 2 : 1; 73 | 74 | String suffix = null; 75 | Image allButtons = null; 76 | // Some modes may not have a 2x version. If a mode doesn't have a 1x 77 | // version, this will cause an error... they should always have 1x. 78 | if (res == 2) { 79 | suffix = "-2x.png"; 80 | allButtons = mode.loadImage("theme/buttons-debug" + suffix); 81 | if (allButtons == null) { 82 | res = 1; // take him down a notch 83 | } 84 | } 85 | if (res == 1) { 86 | suffix = ".png"; 87 | allButtons = mode.loadImage("theme/buttons-debug" + suffix); 88 | if (allButtons == null) { 89 | // use the old (pre-2.0b9) file name 90 | suffix = ".gif"; 91 | allButtons = mode.loadImage("theme/buttons-debug" + suffix); 92 | } 93 | } 94 | 95 | // The following three final fields were not accessible, so just copied the values here 96 | // for the time being. TODO: inform Ben, make these fields public 97 | /** Width of each toolbar button. */ 98 | final int BUTTON_WIDTH = 27; 99 | /** Size (both width and height) of the buttons in the source image. */ 100 | final int BUTTON_IMAGE_SIZE = 33; 101 | int count = allButtons.getWidth(this) / BUTTON_WIDTH*res; 102 | final int GRID_SIZE = 32; 103 | 104 | Image[][] buttonImages = new Image[count][3]; 105 | 106 | for (int i = 0; i < count; i++) { 107 | for (int state = 0; state < 3; state++) { 108 | Image image = new BufferedImage(BUTTON_WIDTH*res, GRID_SIZE*res, BufferedImage.TYPE_INT_ARGB); 109 | Graphics g = image.getGraphics(); 110 | g.drawImage(allButtons, 111 | -(i*BUTTON_IMAGE_SIZE*res) - 3, 112 | (state-2)*BUTTON_IMAGE_SIZE*res, null); 113 | g.dispose(); 114 | buttonImages[i][state] = image; 115 | } 116 | } 117 | 118 | return buttonImages; 119 | } 120 | 121 | /** 122 | * Initialize buttons. Loads images and adds the buttons to the toolbar. 123 | */ 124 | @Override 125 | public void init() { 126 | Image[][] images = loadDebugImages(); 127 | for (int idx = 0; idx < buttonSequence.length; idx++) { 128 | int id = buttonId(idx); 129 | addButton(getTitle(id, false), getTitle(id, true), images[idx], id == NEW || id == TOGGLE_BREAKPOINT); 130 | } 131 | } 132 | 133 | 134 | /** 135 | * Get the title for a toolbar button. Displayed in the toolbar when 136 | * hovering over a button. 137 | * @param id id of the toolbar button 138 | * @param shift true if shift is pressed 139 | * @return the title 140 | */ 141 | public static String getTitle(int id, boolean shift) { 142 | switch (id) { 143 | case DebugToolbar.RUN: 144 | return JavaToolbar.getTitle(JavaToolbar.RUN, shift); 145 | case STOP: 146 | return JavaToolbar.getTitle(JavaToolbar.STOP, shift); 147 | case NEW: 148 | return JavaToolbar.getTitle(JavaToolbar.NEW, shift); 149 | case OPEN: 150 | return JavaToolbar.getTitle(JavaToolbar.OPEN, shift); 151 | case SAVE: 152 | return JavaToolbar.getTitle(JavaToolbar.SAVE, shift); 153 | case EXPORT: 154 | return JavaToolbar.getTitle(JavaToolbar.EXPORT, shift); 155 | case DEBUG: 156 | if (shift) { 157 | return "Run"; 158 | } else { 159 | return "Debug"; 160 | } 161 | case CONTINUE: 162 | return "Continue"; 163 | case TOGGLE_BREAKPOINT: 164 | return "Toggle Breakpoint"; 165 | case STEP: 166 | if (shift) { 167 | return "Step Into"; 168 | } else { 169 | return "Step"; 170 | } 171 | case TOGGLE_VAR_INSPECTOR: 172 | return "Variable Inspector"; 173 | } 174 | return null; 175 | } 176 | 177 | 178 | /** 179 | * Event handler called when a toolbar button is clicked. 180 | * @param e the mouse event 181 | * @param idx index (i.e. position) of the toolbar button clicked 182 | */ 183 | @Override 184 | public void handlePressed(MouseEvent e, int idx) { 185 | boolean shift = e.isShiftDown(); 186 | DebugEditor deditor = (DebugEditor) editor; 187 | int id = buttonId(idx); // convert index/position to button id 188 | 189 | switch (id) { 190 | // case DebugToolbar.RUN: 191 | // super.handlePressed(e, JavaToolbar.RUN); 192 | // break; 193 | case STOP: 194 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Stop' toolbar button"); 195 | super.handlePressed(e, JavaToolbar.STOP); 196 | break; 197 | case NEW: 198 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'New' toolbar button"); 199 | super.handlePressed(e, JavaToolbar.NEW); 200 | break; 201 | case OPEN: 202 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Open' toolbar button"); 203 | super.handlePressed(e, JavaToolbar.OPEN); 204 | break; 205 | case SAVE: 206 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Save' toolbar button"); 207 | super.handlePressed(e, JavaToolbar.SAVE); 208 | break; 209 | case EXPORT: 210 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Export' toolbar button"); 211 | super.handlePressed(e, JavaToolbar.EXPORT); 212 | break; 213 | case DEBUG: 214 | deditor.handleStop(); // Close any running sketches 215 | deditor.showProblemListView(XQConsoleToggle.CONSOLE); 216 | if (shift) { 217 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Run' toolbar button"); 218 | deditor.handleRun(); 219 | } else { 220 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Debug' toolbar button"); 221 | deditor.dbg.startDebug(); 222 | } 223 | break; 224 | case CONTINUE: 225 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Continue' toolbar button"); 226 | deditor.dbg.continueDebug(); 227 | break; 228 | case TOGGLE_BREAKPOINT: 229 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Toggle Breakpoint' toolbar button"); 230 | deditor.dbg.toggleBreakpoint(); 231 | break; 232 | case STEP: 233 | if (shift) { 234 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Step Into' toolbar button"); 235 | deditor.dbg.stepInto(); 236 | } else { 237 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Step' toolbar button"); 238 | deditor.dbg.stepOver(); 239 | } 240 | break; 241 | // case STEP_INTO: 242 | // deditor.dbg.stepInto(); 243 | // break; 244 | // case STEP_OUT: 245 | // deditor.dbg.stepOut(); 246 | // break; 247 | case TOGGLE_VAR_INSPECTOR: 248 | Logger.getLogger(DebugToolbar.class.getName()).log(Level.INFO, "Invoked 'Variable Inspector' toolbar button"); 249 | deditor.toggleVariableInspector(); 250 | break; 251 | } 252 | } 253 | 254 | 255 | /** 256 | * Activate (light up) a button. 257 | * @param id the button id 258 | */ 259 | @Override 260 | public void activate(int id) { 261 | //System.out.println("activate button idx: " + buttonIndex(id)); 262 | super.activate(buttonIndex(id)); 263 | } 264 | 265 | 266 | /** 267 | * Set a button to be inactive. 268 | * @param id the button id 269 | */ 270 | @Override 271 | public void deactivate(int id) { 272 | //System.out.println("deactivate button idx: " + buttonIndex(id)); 273 | super.deactivate(buttonIndex(id)); 274 | } 275 | 276 | 277 | /** 278 | * Get button position (index) from it's id. 279 | * @param buttonId the button id 280 | * ({@link #RUN}, {@link #DEBUG}, {@link #CONTINUE}), {@link #STEP}, ...) 281 | * @return the button index 282 | */ 283 | protected int buttonIndex(int buttonId) { 284 | for (int i = 0; i < buttonSequence.length; i++) { 285 | if (buttonSequence[i] == buttonId) { 286 | return i; 287 | } 288 | } 289 | return -1; 290 | } 291 | 292 | 293 | /** 294 | * Get the button id from its position (index). 295 | * @param buttonIdx the button index 296 | * @return the button id 297 | * ({@link #RUN}, {@link #DEBUG}, {@link #CONTINUE}), {@link #STEP}, ...) 298 | */ 299 | protected int buttonId(int buttonIdx) { 300 | return buttonSequence[buttonIdx]; 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ErrorBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the XQMode project - https://github.com/Manindra29/XQMode 3 | 4 | Under Google Summer of Code 2012 - 5 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 6 | 7 | Copyright (C) 2012 Manindra Moharana 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License version 2 11 | as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.mode.experimental; 24 | 25 | import java.awt.Color; 26 | import java.awt.Cursor; 27 | import java.awt.Dimension; 28 | import java.awt.Graphics; 29 | import java.awt.Graphics2D; 30 | import java.awt.RenderingHints; 31 | import java.awt.event.MouseAdapter; 32 | import java.awt.event.MouseEvent; 33 | import java.awt.event.MouseMotionListener; 34 | import java.util.ArrayList; 35 | 36 | import javax.swing.JPanel; 37 | import javax.swing.SwingWorker; 38 | import javax.swing.text.BadLocationException; 39 | 40 | import processing.app.Base; 41 | import processing.app.SketchCode; 42 | 43 | /** 44 | * The bar on the left of the text area which displays all errors as rectangles.
45 | *
46 | * All errors and warnings of a sketch are drawn on the bar, clicking on one, 47 | * scrolls to the tab and location. Error messages displayed on hover. Markers 48 | * are not in sync with the error line. Similar to eclipse's right error bar 49 | * which displays the overall errors in a document 50 | * 51 | * @author Manindra Moharana <me@mkmoharana.com> 52 | * 53 | */ 54 | public class ErrorBar extends JPanel { 55 | /** 56 | * Preferred height of the component 57 | */ 58 | protected int preferredHeight; 59 | 60 | /** 61 | * Preferred height of the component 62 | */ 63 | protected int preferredWidth = 12; 64 | 65 | /** 66 | * Height of marker 67 | */ 68 | public static final int errorMarkerHeight = 4; 69 | 70 | /** 71 | * Color of Error Marker 72 | */ 73 | public Color errorColor = new Color(0xED2630); 74 | 75 | /** 76 | * Color of Warning Marker 77 | */ 78 | public Color warningColor = new Color(0xFFC30E); 79 | 80 | /** 81 | * Background color of the component 82 | */ 83 | public Color backgroundColor = new Color(0x2C343D); 84 | 85 | /** 86 | * DebugEditor instance 87 | */ 88 | protected DebugEditor editor; 89 | 90 | /** 91 | * ErrorCheckerService instance 92 | */ 93 | protected ErrorCheckerService errorCheckerService; 94 | 95 | /** 96 | * Stores error markers displayed PER TAB along the error bar. 97 | */ 98 | protected ArrayList errorPoints = new ArrayList(); 99 | 100 | /** 101 | * Stores previous list of error markers. 102 | */ 103 | protected ArrayList errorPointsOld = new ArrayList(); 104 | 105 | public void paintComponent(Graphics g) { 106 | Graphics2D g2d = (Graphics2D) g; 107 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 108 | RenderingHints.VALUE_ANTIALIAS_ON); 109 | g.setColor(backgroundColor); 110 | g.fillRect(0, 0, getWidth(), getHeight()); 111 | 112 | for (ErrorMarker emarker : errorPoints) { 113 | if (emarker.getType() == ErrorMarker.Error) { 114 | g.setColor(errorColor); 115 | } else { 116 | g.setColor(warningColor); 117 | } 118 | g.fillRect(2, emarker.getY(), (getWidth() - 3), errorMarkerHeight); 119 | } 120 | } 121 | 122 | public Dimension getPreferredSize() { 123 | return new Dimension(preferredWidth, preferredHeight); 124 | } 125 | 126 | public Dimension getMinimumSize() { 127 | return getPreferredSize(); 128 | } 129 | 130 | public ErrorBar(DebugEditor editor, int height, ExperimentalMode mode) { 131 | this.editor = editor; 132 | this.preferredHeight = height; 133 | this.errorCheckerService = editor.errorCheckerService; 134 | errorColor = mode.getThemeColor("errorbar.errorcolor", errorColor); 135 | warningColor = mode 136 | .getThemeColor("errorbar.warningcolor", warningColor); 137 | backgroundColor = mode.getThemeColor("errorbar.backgroundcolor", 138 | backgroundColor); 139 | addListeners(); 140 | } 141 | 142 | /** 143 | * Update error markers in the error bar. 144 | * 145 | * @param problems 146 | * - List of problems. 147 | */ 148 | synchronized public void updateErrorPoints(final ArrayList problems) { 149 | 150 | // NOTE TO SELF: ErrorMarkers are calculated for the present tab only 151 | // Error Marker index in the arraylist is LOCALIZED for current tab. 152 | // Also, need to do the update in the UI thread to prevent concurrency issues. 153 | final int fheight = this.getHeight(); 154 | SwingWorker worker = new SwingWorker() { 155 | 156 | protected Object doInBackground() throws Exception { 157 | SketchCode sc = editor.getSketch().getCurrentCode(); 158 | int totalLines = 0, currentTab = editor.getSketch() 159 | .getCurrentCodeIndex(); 160 | try { 161 | totalLines = Base.countLines(sc.getDocument() 162 | .getText(0, sc.getDocument().getLength())) + 1; 163 | } catch (BadLocationException e) { 164 | e.printStackTrace(); 165 | } 166 | // System.out.println("Total lines: " + totalLines); 167 | synchronized (errorPoints) { 168 | errorPointsOld.clear(); 169 | for (ErrorMarker marker : errorPoints) { 170 | errorPointsOld.add(marker); 171 | } 172 | errorPoints.clear(); 173 | 174 | // Each problem.getSourceLine() will have an extra line added 175 | // because of 176 | // class declaration in the beginning as well as default imports 177 | synchronized (problems) { 178 | for (Problem problem : problems) { 179 | if (problem.getTabIndex() == currentTab) { 180 | // Ratio of error line to total lines 181 | float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) 182 | / ((float) totalLines); 183 | // Ratio multiplied by height of the error bar 184 | y *= fheight - 15; // -15 is just a vertical offset 185 | errorPoints 186 | .add(new ErrorMarker(problem, (int) y, 187 | problem.isError() ? ErrorMarker.Error 188 | : ErrorMarker.Warning)); 189 | // System.out.println("Y: " + y); 190 | } 191 | } 192 | } 193 | } 194 | return null; 195 | } 196 | 197 | protected void done() { 198 | repaint(); 199 | } 200 | }; 201 | 202 | try { 203 | worker.execute(); // I eat concurrency bugs for breakfast. 204 | } catch (Exception exp) { 205 | System.out.println("Errorbar update markers is slacking." 206 | + exp.getMessage()); 207 | // e.printStackTrace(); 208 | } 209 | } 210 | 211 | /** 212 | * Check if new errors have popped up in the sketch since the last check 213 | * 214 | * @return true - if errors have changed 215 | */ 216 | public boolean errorPointsChanged() { 217 | if (errorPointsOld.size() != errorPoints.size()) { 218 | editor.getTextArea().repaint(); 219 | // System.out.println("2 Repaint " + System.currentTimeMillis()); 220 | return true; 221 | } 222 | 223 | else { 224 | for (int i = 0; i < errorPoints.size(); i++) { 225 | if (errorPoints.get(i).getY() != errorPointsOld.get(i).getY()) { 226 | editor.getTextArea().repaint(); 227 | // System.out.println("3 Repaint " + 228 | // System.currentTimeMillis()); 229 | return true; 230 | } 231 | } 232 | } 233 | return false; 234 | } 235 | 236 | /** 237 | * Add various mouse listeners. 238 | */ 239 | protected void addListeners() { 240 | 241 | this.addMouseListener(new MouseAdapter() { 242 | 243 | // Find out which error/warning the user has clicked 244 | // and then scroll to that 245 | @SuppressWarnings("rawtypes") 246 | @Override 247 | public void mouseClicked(final MouseEvent e) { 248 | SwingWorker worker = new SwingWorker() { 249 | 250 | protected Object doInBackground() throws Exception { 251 | for (ErrorMarker eMarker : errorPoints) { 252 | // -2 and +2 are extra allowance, clicks in the 253 | // vicinity of the markers register that way 254 | if (e.getY() >= eMarker.getY() - 2 255 | && e.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { 256 | errorCheckerService.scrollToErrorLine(eMarker.getProblem()); 257 | return null; 258 | } 259 | } 260 | return null; 261 | } 262 | }; 263 | 264 | try { 265 | worker.execute(); 266 | } catch (Exception exp) { 267 | System.out.println("Errorbar mouseClicked is slacking." 268 | + exp.getMessage()); 269 | // e.printStackTrace(); 270 | } 271 | 272 | } 273 | }); 274 | 275 | // Tooltip on hover 276 | this.addMouseMotionListener(new MouseMotionListener() { 277 | 278 | @SuppressWarnings("rawtypes") 279 | @Override 280 | public void mouseMoved(final MouseEvent evt) { 281 | // System.out.println(e); 282 | SwingWorker worker = new SwingWorker() { 283 | 284 | protected Object doInBackground() throws Exception { 285 | for (ErrorMarker eMarker : errorPoints) { 286 | if (evt.getY() >= eMarker.getY() - 2 287 | && evt.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { 288 | Problem p = eMarker.getProblem(); 289 | String msg = (p.isError() ? "Error: " : "Warning: ") 290 | + p.getMessage(); 291 | setToolTipText(msg); 292 | setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 293 | break; 294 | } 295 | } 296 | return null; 297 | } 298 | }; 299 | 300 | try { 301 | worker.execute(); 302 | } catch (Exception exp) { 303 | System.out 304 | .println("Errorbar mousemoved Worker is slacking." 305 | + exp.getMessage()); 306 | // e.printStackTrace(); 307 | } 308 | } 309 | 310 | @Override 311 | public void mouseDragged(MouseEvent arg0) { 312 | 313 | } 314 | }); 315 | 316 | } 317 | 318 | } 319 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ErrorMarker.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | /** 3 | * Error markers displayed on the Error Bar. 4 | * 5 | * @author Manindra Moharana <me@mkmoharana.com> 6 | * 7 | */ 8 | public class ErrorMarker { 9 | /** 10 | * y co-ordinate of the marker 11 | */ 12 | private int y; 13 | /** 14 | * Type of marker: Error or Warning? 15 | */ 16 | private int type = -1; 17 | /** 18 | * Error Type constant 19 | */ 20 | public static final int Error = 1; 21 | /** 22 | * Warning Type constant 23 | */ 24 | public static final int Warning = 2; 25 | /** 26 | * Problem that the error marker represents 27 | * @see Problem 28 | */ 29 | private Problem problem; 30 | 31 | public ErrorMarker(Problem problem, int y, int type) { 32 | this.problem = problem; 33 | this.y = y; 34 | this.type = type; 35 | } 36 | 37 | /** 38 | * y co-ordinate of the marker 39 | */ 40 | public int getY() { 41 | return y; 42 | } 43 | 44 | /** 45 | * Type of marker: ErrorMarker.Error or ErrorMarker.Warning? 46 | */ 47 | public int getType() { 48 | return type; 49 | } 50 | 51 | /** 52 | * Problem that the error marker represents 53 | * @see Problem 54 | */ 55 | public Problem getProblem() { 56 | return problem; 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/processing/mode/experimental/ErrorMessageSimplifier.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.util.TreeMap; 6 | 7 | import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; 8 | 9 | public class ErrorMessageSimplifier { 10 | 11 | // private ErrorCheckerService errorCheckerService; 12 | 13 | /** 14 | * Mapping between ProblemID constant and the constant name. Holds about 650 15 | * of them. Also, this is just temporary, will be used to find the common 16 | * error types, cos you know, identifying String names is easier than 17 | * identifying 8 digit int constants! 18 | * TODO: this is temporary 19 | */ 20 | private TreeMap constantsMap; 21 | 22 | public ErrorMessageSimplifier() { 23 | 24 | new Thread() { 25 | public void run() { 26 | prepareConstantsList(); 27 | } 28 | }.start(); 29 | } 30 | 31 | private void prepareConstantsList() { 32 | constantsMap = new TreeMap(); 33 | Class probClass = DefaultProblem.class; 34 | Field f[] = probClass.getFields(); 35 | for (Field field : f) { 36 | if (Modifier.isStatic(field.getModifiers())) 37 | try { 38 | //System.out.println(field.getName() + " :" + field.get(null)); 39 | Object val = field.get(null); 40 | if (val instanceof Integer) { 41 | constantsMap.put((Integer) (val), field.getName()); 42 | } 43 | } catch (Exception e) { 44 | System.out.println("Here"); 45 | e.printStackTrace(); 46 | break; 47 | } 48 | } 49 | //System.out.println("Total items: " + constantsMap.size()); 50 | } 51 | 52 | public String getIDName(int id) { 53 | if (constantsMap == null) 54 | return null; 55 | return constantsMap.get(id); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ErrorWindow.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the XQMode project - https://github.com/Manindra29/XQMode 3 | 4 | Under Google Summer of Code 2012 - 5 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 6 | 7 | Copyright (C) 2012 Manindra Moharana 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License version 2 11 | as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.mode.experimental; 24 | 25 | import java.awt.BorderLayout; 26 | import java.awt.Frame; 27 | import java.awt.Point; 28 | import java.awt.event.ComponentEvent; 29 | import java.awt.event.ComponentListener; 30 | import java.awt.event.WindowAdapter; 31 | import java.awt.event.WindowEvent; 32 | 33 | import javax.swing.JFrame; 34 | import javax.swing.JPanel; 35 | import javax.swing.JScrollPane; 36 | import javax.swing.WindowConstants; 37 | import javax.swing.border.EmptyBorder; 38 | import javax.swing.table.TableModel; 39 | 40 | import processing.app.Editor; 41 | import processing.app.Toolkit; 42 | 43 | /** 44 | * Error Window that displays a tablular list of errors. Clicking on an error 45 | * scrolls to its location in the code. 46 | * 47 | * @author Manindra Moharana <me@mkmoharana.com> 48 | * 49 | */ 50 | public class ErrorWindow extends JFrame { 51 | 52 | private JPanel contentPane; 53 | /** 54 | * The table displaying the errors 55 | */ 56 | protected XQErrorTable errorTable; 57 | /** 58 | * Scroll pane that contains the Error Table 59 | */ 60 | protected JScrollPane scrollPane; 61 | 62 | protected DebugEditor thisEditor; 63 | private JFrame thisErrorWindow; 64 | 65 | /** 66 | * Handles the sticky Problem window 67 | */ 68 | private DockTool2Base Docker; 69 | 70 | protected ErrorCheckerService errorCheckerService; 71 | 72 | /** 73 | * Preps up ErrorWindow 74 | * 75 | * @param editor 76 | * - Editor 77 | * @param ecs - ErrorCheckerService 78 | */ 79 | public ErrorWindow(DebugEditor editor, ErrorCheckerService ecs) { 80 | thisErrorWindow = this; 81 | errorCheckerService = ecs; 82 | thisEditor = editor; 83 | setTitle("Problems"); 84 | prepareFrame(); 85 | } 86 | 87 | /** 88 | * Sets up ErrorWindow 89 | */ 90 | protected void prepareFrame() { 91 | Toolkit.setIcon(this); 92 | setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); 93 | // Default size: setBounds(100, 100, 458, 160); 94 | setBounds(100, 100, 458, 160); // Yeah, I hardcode such things sometimes. Hate me. 95 | 96 | contentPane = new JPanel(); 97 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 98 | setContentPane(contentPane); 99 | contentPane.setLayout(new BorderLayout(0, 0)); 100 | 101 | scrollPane = new JScrollPane(); 102 | contentPane.add(scrollPane); 103 | 104 | errorTable = new XQErrorTable(errorCheckerService); 105 | scrollPane.setViewportView(errorTable); 106 | 107 | try { 108 | Docker = new DockTool2Base(); 109 | addListeners(); 110 | } catch (Exception e) { 111 | System.out.println("addListeners() acted silly."); 112 | e.printStackTrace(); 113 | } 114 | 115 | if (thisEditor != null) { 116 | setLocation(new Point(thisEditor.getLocation().x 117 | + thisEditor.getWidth(), thisEditor.getLocation().y)); 118 | } 119 | 120 | } 121 | 122 | /** 123 | * Updates the error table with new data(Table Model). Called from Error 124 | * Checker Service. 125 | * 126 | * @param tableModel 127 | * - Table Model 128 | * @return True - If error table was updated successfully. 129 | */ 130 | synchronized public boolean updateTable(final TableModel tableModel) { 131 | // XQErrorTable handles evrything now 132 | return errorTable.updateTable(tableModel); 133 | } 134 | 135 | /** 136 | * Adds various listeners to components of EditorWindow and to the Editor 137 | * window 138 | */ 139 | protected void addListeners() { 140 | 141 | if (thisErrorWindow == null) 142 | System.out.println("ERW null"); 143 | 144 | thisErrorWindow.addComponentListener(new ComponentListener() { 145 | 146 | @Override 147 | public void componentShown(ComponentEvent e) { 148 | 149 | } 150 | 151 | @Override 152 | public void componentResized(ComponentEvent e) { 153 | Docker.tryDocking(); 154 | } 155 | 156 | @Override 157 | public void componentMoved(ComponentEvent e) { 158 | Docker.tryDocking(); 159 | } 160 | 161 | @Override 162 | public void componentHidden(ComponentEvent e) { 163 | 164 | } 165 | }); 166 | 167 | thisErrorWindow.addWindowListener(new WindowAdapter() { 168 | 169 | @Override 170 | public void windowClosing(WindowEvent e) { 171 | thisEditor.problemWindowMenuCB.setSelected(false); 172 | } 173 | 174 | @Override 175 | public void windowDeiconified(WindowEvent e) { 176 | thisEditor.setExtendedState(Frame.NORMAL); 177 | } 178 | 179 | }); 180 | 181 | if (thisEditor == null) { 182 | System.out.println("Editor null"); 183 | return; 184 | } 185 | 186 | /*thisEditor.addWindowListener(new WindowAdapter() { 187 | 188 | @Override 189 | public void windowClosing(WindowEvent e) { 190 | 191 | } 192 | 193 | @Override 194 | public void windowClosed(WindowEvent e) { 195 | errorCheckerService.pauseThread(); 196 | errorCheckerService.stopThread(); // Bye bye thread. 197 | thisErrorWindow.dispose(); 198 | } 199 | 200 | @Override 201 | public void windowIconified(WindowEvent e) { 202 | thisErrorWindow.setExtendedState(Frame.ICONIFIED); 203 | } 204 | 205 | @Override 206 | public void windowDeiconified(WindowEvent e) { 207 | thisErrorWindow.setExtendedState(Frame.NORMAL); 208 | } 209 | 210 | });*/ 211 | 212 | thisEditor.addComponentListener(new ComponentListener() { 213 | 214 | @Override 215 | public void componentShown(ComponentEvent e) { 216 | 217 | } 218 | 219 | @Override 220 | public void componentResized(ComponentEvent e) { 221 | if (Docker.isDocked()) { 222 | Docker.dock(); 223 | } else { 224 | Docker.tryDocking(); 225 | } 226 | } 227 | 228 | @Override 229 | public void componentMoved(ComponentEvent e) { 230 | 231 | if (Docker.isDocked()) { 232 | Docker.dock(); 233 | } else { 234 | Docker.tryDocking(); 235 | } 236 | 237 | } 238 | 239 | @Override 240 | public void componentHidden(ComponentEvent e) { 241 | // System.out.println("ed hidden"); 242 | } 243 | }); 244 | 245 | } 246 | 247 | 248 | /** 249 | * Implements the docking feature of the tool - The frame sticks to the 250 | * editor and once docked, moves along with it as the editor is resized, 251 | * moved, or closed. 252 | * 253 | * This class has been borrowed from Tab Manager tool by Thomas Diewald. It 254 | * has been slightly modified and used here. 255 | * 256 | * @author Thomas Diewald , http://thomasdiewald.com 257 | */ 258 | private class DockTool2Base { 259 | 260 | private int docking_border = 0; 261 | private int dock_on_editor_y_offset_ = 0; 262 | private int dock_on_editor_x_offset_ = 0; 263 | 264 | // /////////////////////////////// 265 | // ____2____ 266 | // | | 267 | // | | 268 | // 0 | editor | 1 269 | // | | 270 | // |_________| 271 | // 3 272 | // /////////////////////////////// 273 | 274 | // public void reset() { 275 | // dock_on_editor_y_offset_ = 0; 276 | // dock_on_editor_x_offset_ = 0; 277 | // docking_border = 0; 278 | // } 279 | 280 | public boolean isDocked() { 281 | return (docking_border >= 0); 282 | } 283 | 284 | private final int MAX_GAP_ = 20; 285 | 286 | // 287 | public void tryDocking() { 288 | if (thisEditor == null) 289 | return; 290 | Editor editor = thisEditor; 291 | Frame frame = thisErrorWindow; 292 | 293 | int ex = editor.getX(); 294 | int ey = editor.getY(); 295 | int ew = editor.getWidth(); 296 | int eh = editor.getHeight(); 297 | 298 | int fx = frame.getX(); 299 | int fy = frame.getY(); 300 | int fw = frame.getWidth(); 301 | int fh = frame.getHeight(); 302 | 303 | if (((fy > ey) && (fy < ey + eh)) 304 | || ((fy + fh > ey) && (fy + fh < ey + eh))) { 305 | int dis_border_left = Math.abs(ex - (fx + fw)); 306 | int dis_border_right = Math.abs((ex + ew) - (fx)); 307 | 308 | if (dis_border_left < MAX_GAP_ || dis_border_right < MAX_GAP_) { 309 | docking_border = (dis_border_left < dis_border_right) ? 0 310 | : 1; 311 | dock_on_editor_y_offset_ = fy - ey; 312 | dock(); 313 | return; 314 | } 315 | } 316 | 317 | if (((fx > ex) && (fx < ex + ew)) 318 | || ((fx + fw > ey) && (fx + fw < ex + ew))) { 319 | int dis_border_top = Math.abs(ey - (fy + fh)); 320 | int dis_border_bot = Math.abs((ey + eh) - (fy)); 321 | 322 | if (dis_border_top < MAX_GAP_ || dis_border_bot < MAX_GAP_) { 323 | docking_border = (dis_border_top < dis_border_bot) ? 2 : 3; 324 | dock_on_editor_x_offset_ = fx - ex; 325 | dock(); 326 | return; 327 | } 328 | } 329 | docking_border = -1; 330 | } 331 | 332 | public void dock() { 333 | if (thisEditor == null) 334 | return; 335 | Editor editor = thisEditor; 336 | Frame frame = thisErrorWindow; 337 | 338 | int ex = editor.getX(); 339 | int ey = editor.getY(); 340 | int ew = editor.getWidth(); 341 | int eh = editor.getHeight(); 342 | 343 | // int fx = frame.getX(); 344 | // int fy = frame.getY(); 345 | int fw = frame.getWidth(); 346 | int fh = frame.getHeight(); 347 | 348 | int x = 0, y = 0; 349 | if (docking_border == -1) { 350 | return; 351 | } 352 | 353 | if (docking_border == 0) { 354 | x = ex - fw; 355 | y = ey + dock_on_editor_y_offset_; 356 | } 357 | if (docking_border == 1) { 358 | x = ex + ew; 359 | y = ey + dock_on_editor_y_offset_; 360 | } 361 | 362 | if (docking_border == 2) { 363 | x = ex + dock_on_editor_x_offset_; 364 | y = ey - fh; 365 | } 366 | if (docking_border == 3) { 367 | x = ex + dock_on_editor_x_offset_; 368 | y = ey + eh; 369 | } 370 | frame.setLocation(x, y); 371 | } 372 | 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/FieldNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.ClassNotLoadedException; 21 | import com.sun.jdi.Field; 22 | import com.sun.jdi.InvalidTypeException; 23 | import com.sun.jdi.ObjectReference; 24 | import com.sun.jdi.Value; 25 | import java.util.logging.Level; 26 | import java.util.logging.Logger; 27 | 28 | /** 29 | * Specialized {@link VariableNode} for representing fields. Overrides 30 | * {@link #setValue} to properly change the value of the encapsulated field. 31 | * 32 | * @author Martin Leopold 33 | */ 34 | public class FieldNode extends VariableNode { 35 | 36 | protected Field field; 37 | protected ObjectReference obj; 38 | 39 | /** 40 | * Construct a {@link FieldNode}. 41 | * 42 | * @param name the name 43 | * @param type the type 44 | * @param value the value 45 | * @param field the field 46 | * @param obj a reference to the object containing the field 47 | */ 48 | public FieldNode(String name, String type, Value value, Field field, ObjectReference obj) { 49 | super(name, type, value); 50 | this.field = field; 51 | this.obj = obj; 52 | } 53 | 54 | @Override 55 | public void setValue(Value value) { 56 | try { 57 | obj.setValue(field, value); 58 | } catch (InvalidTypeException ex) { 59 | Logger.getLogger(FieldNode.class.getName()).log(Level.SEVERE, null, ex); 60 | } catch (ClassNotLoadedException ex) { 61 | Logger.getLogger(FieldNode.class.getName()).log(Level.SEVERE, null, ex); 62 | } 63 | this.value = value; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/ImportStatement.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the XQMode project - https://github.com/Manindra29/XQMode 3 | 4 | Under Google Summer of Code 2012 - 5 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 6 | 7 | Copyright (C) 2012 Manindra Moharana 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License version 2 11 | as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.mode.experimental; 24 | 25 | /** 26 | * Wrapper for import statements 27 | * 28 | * @author Manindra Moharana <me@mkmoharana.com> 29 | * 30 | */ 31 | public class ImportStatement { 32 | /** 33 | * Ex: processing.opengl.*, java.util.* 34 | */ 35 | private String importName; 36 | 37 | /** 38 | * Which tab does it belong to? 39 | */ 40 | private int tab; 41 | 42 | /** 43 | * Line number(pde code) of the import 44 | */ 45 | private int lineNumber; 46 | 47 | /** 48 | * 49 | * @param importName - Ex: processing.opengl.*, java.util.* 50 | * @param tab - Which tab does it belong to? 51 | * @param lineNumber - Line number(pde code) of the import 52 | */ 53 | public ImportStatement(String importName, int tab, int lineNumber) { 54 | this.importName = importName; 55 | this.tab = tab; 56 | this.lineNumber = lineNumber; 57 | } 58 | 59 | public String getImportName() { 60 | return importName; 61 | } 62 | 63 | public String getPackageName(){ 64 | String ret = new String(importName.trim()); 65 | if(ret.startsWith("import ")) 66 | ret = ret.substring(7); 67 | if(ret.endsWith(";")) 68 | ret = ret.substring(0, ret.length() - 1); 69 | return ret; 70 | } 71 | 72 | public int getTab() { 73 | return tab; 74 | } 75 | 76 | public int getLineNumber() { 77 | return lineNumber; 78 | } 79 | } -------------------------------------------------------------------------------- /src/processing/mode/experimental/JavadocHelper.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | import java.util.Iterator; 6 | import java.util.TreeMap; 7 | 8 | import org.jsoup.Jsoup; 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.nodes.Element; 11 | import org.jsoup.select.Elements; 12 | 13 | public class JavadocHelper { 14 | 15 | public static void loadJavaDoc(TreeMap jdocMap, File p5Ref){ 16 | Document doc; 17 | 18 | //Pattern pat = Pattern.compile("\\w+"); 19 | try { 20 | if (p5Ref == null) { 21 | System.out.println("P5 Ref location null"); 22 | p5Ref = new File( 23 | "/home/quarkninja/Workspaces/processing-workspace/processing/build/linux/work/modes/java/reference"); 24 | } 25 | 26 | FileFilter fileFilter = new FileFilter() { 27 | public boolean accept(File file) { 28 | if(!file.getName().endsWith("_.html")) 29 | return false; 30 | int k = 0; 31 | for (int i = 0; i < file.getName().length(); i++) { 32 | if(file.getName().charAt(i)== '_') 33 | k++; 34 | if(k > 1) 35 | return false; 36 | } 37 | return true; 38 | } 39 | }; 40 | 41 | for (File docFile : p5Ref.listFiles(fileFilter)) { 42 | 43 | doc = Jsoup.parse(docFile, null); 44 | Elements elm = doc.getElementsByClass("ref-item"); 45 | String msg = ""; 46 | String methodName = docFile.getName().substring(0, docFile.getName().indexOf('_')); 47 | //System.out.println(methodName); 48 | for (Iterator it = elm.iterator(); it.hasNext();) { 49 | Element ele = (Element) it.next(); 50 | msg = "
" 51 | + ele.html() + "
"; 52 | //mat.replaceAll(""); 53 | msg = msg.replaceAll("img src=\"", "img src=\"" 54 | + p5Ref.toURI().toURL().toString() + "/"); 55 | //System.out.println(ele.text()); 56 | } 57 | jdocMap.put(methodName, msg); 58 | } 59 | System.out.println("JDoc loaded "+jdocMap.size()); 60 | /* File javaDocFile = new File( 61 | "/home/quarkninja/Workspaces/processing-workspace/processing/build/javadoc/core/processing/core/PApplet.html"); 62 | //SimpleOpenNI.SimpleOpenNI 63 | doc = Jsoup.parse(javaDocFile, null); 64 | 65 | String msg = ""; 66 | Elements elm = doc.getElementsByTag("pre"); 67 | // Elements desc = doc.getElementsByTag("dl"); 68 | //System.out.println(elm.toString()); 69 | 70 | for (Iterator iterator = elm.iterator(); iterator.hasNext();) { 71 | Element element = (Element) iterator.next(); 72 | 73 | //System.out.println(element.text()); 74 | // if (element.nextElementSibling() != null) 75 | // System.out.println(element.nextElementSibling().text()); 76 | //System.out.println("-------------------"); 77 | msg = "
" 78 | + element.html() 79 | + element.nextElementSibling() 80 | + "
"; 81 | int k = 0; 82 | Matcher matcher = pat.matcher(element.text()); 83 | ArrayList parts = new ArrayList(); 84 | while (matcher.find()) { 85 | // System.out.print("Start index: " + matcher.start()); 86 | // System.out.print(" End index: " + matcher.end() + " "); 87 | if (k == 0 && !matcher.group().equals("public")) { 88 | k = -1; 89 | break; 90 | } 91 | // System.out.print(matcher.group() + " "); 92 | parts.add(matcher.group()); 93 | k++; 94 | } 95 | if (k <= 0 || parts.size() < 3) 96 | continue; 97 | int i = 0; 98 | if (parts.get(i).equals("public")) 99 | i++; 100 | if (parts.get(i).equals("static") || parts.get(i).equals("final") 101 | || parts.get(i).equals("class")) 102 | i++; 103 | if (parts.get(i).equals("static") || parts.get(i).equals("final")) 104 | i++; 105 | // System.out.println("Ret Type " + parts.get(i)); 106 | 107 | i++; // return type 108 | 109 | //System.out.println("Name " + parts.get(i)); 110 | jdocMap.put(parts.get(i), msg); 111 | } 112 | 113 | // for (String key : jdocMap.keySet()) { 114 | // System.out.println("Method: " + key); 115 | // System.out.println("Method: " + jdocMap.get(key)); 116 | // } 117 | * 118 | */ 119 | } catch (Exception e) { 120 | e.printStackTrace(); 121 | } 122 | 123 | 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/LineBreakpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.AbsentInformationException; 21 | import com.sun.jdi.Location; 22 | import com.sun.jdi.ReferenceType; 23 | import com.sun.jdi.request.BreakpointRequest; 24 | import java.util.List; 25 | import java.util.logging.Level; 26 | import java.util.logging.Logger; 27 | 28 | import static processing.mode.experimental.ExperimentalMode.log; 29 | import static processing.mode.experimental.ExperimentalMode.logE; 30 | import static processing.mode.experimental.ExperimentalMode.log2; 31 | 32 | /** 33 | * Model/Controller of a line breakpoint. Can be set before or while debugging. 34 | * Adds a highlight using the debuggers view ({@link DebugEditor}). 35 | * 36 | * @author Martin Leopold 37 | */ 38 | public class LineBreakpoint implements ClassLoadListener { 39 | 40 | protected Debugger dbg; // the debugger 41 | protected LineID line; // the line this breakpoint is set on 42 | protected BreakpointRequest bpr; // the request on the VM's event request manager 43 | protected ReferenceType theClass; // the class containing this breakpoint, null when not yet loaded 44 | 45 | /** 46 | * Create a {@link LineBreakpoint}. If in a debug session, will try to 47 | * immediately set the breakpoint. If not in a debug session or the 48 | * corresponding class is not yet loaded the breakpoint will activate on 49 | * class load. 50 | * 51 | * @param line the line id to create the breakpoint on 52 | * @param dbg the {@link Debugger} 53 | */ 54 | public LineBreakpoint(LineID line, Debugger dbg) { 55 | this.line = line; 56 | line.startTracking(dbg.editor().getTab(line.fileName()).getDocument()); 57 | this.dbg = dbg; 58 | theClass = dbg.getClass(className()); // try to get the class immediately, may return null if not yet loaded 59 | set(); // activate the breakpoint (show highlight, attach if debugger is running) 60 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.INFO, "LBP Created " +toString() + " class: " + className(), new Object[]{}); 61 | } 62 | 63 | /** 64 | * Create a {@link LineBreakpoint} on a line in the current tab. 65 | * 66 | * @param lineIdx the line index of the current tab to create the breakpoint 67 | * on 68 | * @param dbg the {@link Debugger} 69 | */ 70 | // TODO: remove and replace by {@link #LineBreakpoint(LineID line, Debugger dbg)} 71 | public LineBreakpoint(int lineIdx, Debugger dbg) { 72 | this(dbg.editor().getLineIDInCurrentTab(lineIdx), dbg); 73 | } 74 | 75 | /** 76 | * Get the line id this breakpoint is on. 77 | * 78 | * @return the line id 79 | */ 80 | public LineID lineID() { 81 | return line; 82 | } 83 | 84 | /** 85 | * Test if this breakpoint is on a certain line. 86 | * 87 | * @param testLine the line id to test 88 | * @return true if this breakpoint is on the given line 89 | */ 90 | public boolean isOnLine(LineID testLine) { 91 | return line.equals(testLine); 92 | } 93 | 94 | /** 95 | * Attach this breakpoint to the VM. Creates and enables a 96 | * {@link BreakpointRequest}. VM needs to be paused. 97 | */ 98 | protected void attach() { 99 | if (!dbg.isPaused()) { 100 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "can't attach breakpoint, debugger not paused"); 101 | return; 102 | } 103 | 104 | if (theClass == null) { 105 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "can't attach breakpoint, class not loaded: {0}", className()); 106 | return; 107 | } 108 | 109 | // find line in java space 110 | LineID javaLine = dbg.sketchToJavaLine(line); 111 | if (javaLine == null) { 112 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "couldn't find line {0} in the java code", line); 113 | return; 114 | } 115 | try { 116 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "BPs of class: {0} , line " + (javaLine.lineIdx() + 1), new Object[]{theClass}); 117 | List locations = theClass.locationsOfLine(javaLine.lineIdx() + 1); 118 | if (locations.isEmpty()) { 119 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "no location found for line {0} -> {1}", new Object[]{line, javaLine}); 120 | return; 121 | } 122 | // use first found location 123 | bpr = dbg.vm().eventRequestManager().createBreakpointRequest(locations.get(0)); 124 | bpr.enable(); 125 | Logger.getLogger(LineBreakpoint.class.getName()).log(Level.INFO, "attached breakpoint to {0} -> {1}", new Object[]{line, javaLine}); 126 | } catch (AbsentInformationException ex) { 127 | Logger.getLogger(Debugger.class.getName()).log(Level.SEVERE, null, ex); 128 | } 129 | } 130 | 131 | /** 132 | * Detach this breakpoint from the VM. Deletes the 133 | * {@link BreakpointRequest}. 134 | */ 135 | protected void detach() { 136 | if (bpr != null) { 137 | dbg.vm().eventRequestManager().deleteEventRequest(bpr); 138 | bpr = null; 139 | } 140 | } 141 | 142 | /** 143 | * Set this breakpoint. Adds the line highlight. If Debugger is paused also 144 | * attaches the breakpoint by calling {@link #attach()}. 145 | */ 146 | protected void set() { 147 | dbg.addClassLoadListener(this); // class may not yet be loaded 148 | dbg.editor().addBreakpointedLine(line); 149 | if (theClass != null && dbg.isPaused()) { // class is loaded 150 | // immediately activate the breakpoint 151 | attach(); 152 | } 153 | if (dbg.editor().isInCurrentTab(line)) { 154 | dbg.editor().getSketch().setModified(true); 155 | } 156 | } 157 | 158 | /** 159 | * Remove this breakpoint. Clears the highlight and detaches the breakpoint 160 | * if the debugger is paused. 161 | */ 162 | public void remove() { 163 | dbg.removeClassLoadListener(this); 164 | //System.out.println("removing " + line.lineIdx()); 165 | dbg.editor().removeBreakpointedLine(line.lineIdx()); 166 | if (dbg.isPaused()) { 167 | // immediately remove the breakpoint 168 | detach(); 169 | } 170 | line.stopTracking(); 171 | if (dbg.editor().isInCurrentTab(line)) { 172 | dbg.editor().getSketch().setModified(true); 173 | } 174 | } 175 | 176 | // public void enable() { 177 | // } 178 | // 179 | // public void disable() { 180 | // } 181 | @Override 182 | public String toString() { 183 | return line.toString(); 184 | } 185 | 186 | /** 187 | * Get the name of the class this breakpoint belongs to. Needed for fetching 188 | * the right location to create a breakpoint request. 189 | * 190 | * @return the class name 191 | */ 192 | protected String className() { 193 | if (line.fileName().endsWith(".pde")) { 194 | // standard tab 195 | ReferenceType mainClass = dbg.getMainClass(); 196 | //System.out.println(dbg.getMainClass().name()); 197 | if (mainClass == null) { 198 | return null; 199 | } 200 | return dbg.getMainClass().name(); 201 | } 202 | 203 | if (line.fileName().endsWith(".java")) { 204 | // pure java tab 205 | return line.fileName().substring(0, line.fileName().lastIndexOf(".java")); 206 | } 207 | 208 | return null; 209 | } 210 | 211 | /** 212 | * Event handler called when a class is loaded in the debugger. Causes the 213 | * breakpoint to be attached, if its class was loaded. 214 | * 215 | * @param theClass the class that was just loaded. 216 | */ 217 | @Override 218 | public void classLoaded(ReferenceType theClass) { 219 | // check if our class is being loaded 220 | log("Class Loaded: " + theClass.name()); 221 | if (theClass.name().equals(className())) { 222 | this.theClass = theClass; 223 | attach(); 224 | } 225 | for (ReferenceType ct : theClass.nestedTypes()) { 226 | log("Nested " + ct.name()); 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/LineHighlight.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import java.awt.Color; 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | 24 | /** 25 | * Model/Controller for a highlighted source code line. Implements a custom 26 | * background color and a text based marker placed in the left-hand gutter area. 27 | * 28 | * @author Martin Leopold 29 | */ 30 | public class LineHighlight implements LineListener { 31 | 32 | protected DebugEditor editor; // the view, used for highlighting lines by setting a background color 33 | protected Color bgColor; // the background color for highlighting lines 34 | protected LineID lineID; // the id of the line 35 | protected String marker; // 36 | protected Color markerColor; 37 | protected int priority = 0; 38 | protected static Set allHighlights = new HashSet(); 39 | 40 | protected static boolean isHighestPriority(LineHighlight hl) { 41 | for (LineHighlight check : allHighlights) { 42 | if (check.lineID().equals(hl.lineID()) && check.priority() > hl.priority()) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | /** 50 | * Create a {@link LineHighlight}. 51 | * 52 | * @param lineID the line id to highlight 53 | * @param bgColor the background color used for highlighting 54 | * @param editor the {@link DebugEditor} 55 | */ 56 | public LineHighlight(LineID lineID, Color bgColor, DebugEditor editor) { 57 | this.lineID = lineID; 58 | this.bgColor = bgColor; 59 | this.editor = editor; 60 | lineID.addListener(this); 61 | lineID.startTracking(editor.getTab(lineID.fileName()).getDocument()); // TODO: overwrite a previous doc? 62 | paint(); // already checks if on current tab 63 | allHighlights.add(this); 64 | } 65 | 66 | public void setPriority(int p) { 67 | this.priority = p; 68 | } 69 | 70 | public int priority() { 71 | return priority; 72 | } 73 | 74 | /** 75 | * Create a {@link LineHighlight} on the current tab. 76 | * 77 | * @param lineIdx the line index on the current tab to highlight 78 | * @param bgColor the background color used for highlighting 79 | * @param editor the {@link DebugEditor} 80 | */ 81 | // TODO: Remove and replace by {@link #LineHighlight(LineID lineID, Color bgColor, DebugEditor editor)} 82 | public LineHighlight(int lineIdx, Color bgColor, DebugEditor editor) { 83 | this(editor.getLineIDInCurrentTab(lineIdx), bgColor, editor); 84 | } 85 | 86 | /** 87 | * Set a text based marker displayed in the left hand gutter area of this 88 | * highlighted line. 89 | * 90 | * @param marker the marker text 91 | */ 92 | public void setMarker(String marker) { 93 | this.marker = marker; 94 | paint(); 95 | } 96 | 97 | /** 98 | * Set a text based marker displayed in the left hand gutter area of this 99 | * highlighted line. Also use a custom text color. 100 | * 101 | * @param marker the marker text 102 | * @param markerColor the text color 103 | */ 104 | public void setMarker(String marker, Color markerColor) { 105 | this.markerColor = markerColor; 106 | setMarker(marker); 107 | } 108 | 109 | /** 110 | * Retrieve the line id of this {@link LineHighlight}. 111 | * 112 | * @return the line id 113 | */ 114 | public LineID lineID() { 115 | return lineID; 116 | } 117 | 118 | /** 119 | * Retrieve the color for highlighting this line. 120 | * 121 | * @return the highlight color. 122 | */ 123 | public Color getColor() { 124 | return bgColor; 125 | } 126 | 127 | /** 128 | * Test if this highlight is on a certain line. 129 | * 130 | * @param testLine the line to test 131 | * @return true if this highlight is on the given line 132 | */ 133 | public boolean isOnLine(LineID testLine) { 134 | return lineID.equals(testLine); 135 | } 136 | 137 | /** 138 | * Event handler for line number changes (due to editing). Will remove the 139 | * highlight from the old line number and repaint it at the new location. 140 | * 141 | * @param line the line that has changed 142 | * @param oldLineIdx the old line index (0-based) 143 | * @param newLineIdx the new line index (0-based) 144 | */ 145 | @Override 146 | public void lineChanged(LineID line, int oldLineIdx, int newLineIdx) { 147 | // clear old line 148 | if (editor.isInCurrentTab(new LineID(line.fileName(), oldLineIdx))) { 149 | editor.textArea().clearLineBgColor(oldLineIdx); 150 | editor.textArea().clearGutterText(oldLineIdx); 151 | } 152 | 153 | // paint new line 154 | // but only if it's on top -> fixes current line being hidden by breakpoint moving it down. 155 | // lineChanged events seem to come in inverse order of startTracking the LineID. (and bp is created first...) 156 | if (LineHighlight.isHighestPriority(this)) { 157 | paint(); 158 | } 159 | } 160 | 161 | /** 162 | * Notify this line highlight that it is no longer used. Call this for 163 | * cleanup before the {@link LineHighlight} is discarded. 164 | */ 165 | public void dispose() { 166 | lineID.removeListener(this); 167 | lineID.stopTracking(); 168 | allHighlights.remove(this); 169 | } 170 | 171 | /** 172 | * (Re-)paint this line highlight. 173 | */ 174 | public void paint() { 175 | if (editor.isInCurrentTab(lineID)) { 176 | editor.textArea().setLineBgColor(lineID.lineIdx(), bgColor); 177 | if (marker != null) { 178 | if (markerColor != null) { 179 | editor.textArea().setGutterText(lineID.lineIdx(), marker, markerColor); 180 | } else { 181 | editor.textArea().setGutterText(lineID.lineIdx(), marker); 182 | } 183 | } 184 | } 185 | } 186 | 187 | /** 188 | * Clear this line highlight. 189 | */ 190 | public void clear() { 191 | if (editor.isInCurrentTab(lineID)) { 192 | editor.textArea().clearLineBgColor(lineID.lineIdx()); 193 | editor.textArea().clearGutterText(lineID.lineIdx()); 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/LineID.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | import java.util.logging.Level; 23 | import java.util.logging.Logger; 24 | import javax.swing.event.DocumentEvent; 25 | import javax.swing.event.DocumentListener; 26 | import javax.swing.text.BadLocationException; 27 | import javax.swing.text.Document; 28 | import javax.swing.text.Element; 29 | import javax.swing.text.Position; 30 | 31 | /** 32 | * Describes an ID for a code line. Comprised of a file name and a (0-based) 33 | * line number. Can track changes to the line number due to text editing by 34 | * attaching a {@link Document}. Registered {@link LineListener}s are notified 35 | * of changes to the line number. 36 | * 37 | * @author Martin Leopold 38 | */ 39 | public class LineID implements DocumentListener { 40 | 41 | protected String fileName; // the filename 42 | protected int lineIdx; // the line number, 0-based 43 | protected Document doc; // the Document to use for line number tracking 44 | protected Position pos; // the Position acquired during line number tracking 45 | protected Set listeners = new HashSet(); // listeners for line number changes 46 | 47 | public LineID(String fileName, int lineIdx) { 48 | this.fileName = fileName; 49 | this.lineIdx = lineIdx; 50 | } 51 | 52 | /** 53 | * Get the file name of this line. 54 | * 55 | * @return the file name 56 | */ 57 | public String fileName() { 58 | return fileName; 59 | } 60 | 61 | /** 62 | * Get the (0-based) line number of this line. 63 | * 64 | * @return the line index (i.e. line number, starting at 0) 65 | */ 66 | public synchronized int lineIdx() { 67 | return lineIdx; 68 | } 69 | 70 | @Override 71 | public int hashCode() { 72 | return toString().hashCode(); 73 | } 74 | 75 | /** 76 | * Test whether this {@link LineID} is equal to another object. Two 77 | * {@link LineID}'s are equal when both their fileName and lineNo are equal. 78 | * 79 | * @param obj the object to test for equality 80 | * @return {@code true} if equal 81 | */ 82 | @Override 83 | public boolean equals(Object obj) { 84 | if (obj == null) { 85 | return false; 86 | } 87 | if (getClass() != obj.getClass()) { 88 | return false; 89 | } 90 | final LineID other = (LineID) obj; 91 | if ((this.fileName == null) ? (other.fileName != null) : !this.fileName.equals(other.fileName)) { 92 | return false; 93 | } 94 | if (this.lineIdx != other.lineIdx) { 95 | return false; 96 | } 97 | return true; 98 | } 99 | 100 | /** 101 | * Output a string representation in the form fileName:lineIdx+1. Note this 102 | * uses a 1-based line number as is customary for human-readable line 103 | * numbers. 104 | * 105 | * @return the string representation of this line ID 106 | */ 107 | @Override 108 | public String toString() { 109 | return fileName + ":" + (lineIdx + 1); 110 | } 111 | 112 | // /** 113 | // * Retrieve a copy of this line ID. 114 | // * 115 | // * @return the copy 116 | // */ 117 | // @Override 118 | // public LineID clone() { 119 | // return new LineID(fileName, lineIdx); 120 | // } 121 | 122 | /** 123 | * Attach a {@link Document} to enable line number tracking when editing. 124 | * The position to track is before the first non-whitespace character on the 125 | * line. Edits happening before that position will cause the line number to 126 | * update accordingly. Multiple {@link #startTracking} calls will replace 127 | * the tracked document. Whoever wants a tracked line should track it and 128 | * add itself as listener if necessary. 129 | * ({@link LineHighlight}, {@link LineBreakpoint}) 130 | * 131 | * @param doc the {@link Document} to use for line number tracking 132 | */ 133 | public synchronized void startTracking(Document doc) { 134 | //System.out.println("tracking: " + this); 135 | if (doc == null) { 136 | return; // null arg 137 | } 138 | if (doc == this.doc) { 139 | return; // already tracking that doc 140 | } 141 | try { 142 | Element line = doc.getDefaultRootElement().getElement(lineIdx); 143 | if (line == null) { 144 | return; // line doesn't exist 145 | } 146 | String lineText = doc.getText(line.getStartOffset(), line.getEndOffset() - line.getStartOffset()); 147 | // set tracking position at (=before) first non-white space character on line 148 | pos = doc.createPosition(line.getStartOffset() + nonWhiteSpaceOffset(lineText)); 149 | this.doc = doc; 150 | doc.addDocumentListener(this); 151 | } catch (BadLocationException ex) { 152 | Logger.getLogger(LineID.class.getName()).log(Level.SEVERE, null, ex); 153 | pos = null; 154 | this.doc = null; 155 | } 156 | } 157 | 158 | /** 159 | * Notify this {@link LineID} that it is no longer in use. Will stop 160 | * position tracking. Call this when this {@link LineID} is no longer 161 | * needed. 162 | */ 163 | public synchronized void stopTracking() { 164 | if (doc != null) { 165 | doc.removeDocumentListener(this); 166 | doc = null; 167 | } 168 | } 169 | 170 | /** 171 | * Update the tracked position. Will notify listeners if line number has 172 | * changed. 173 | */ 174 | protected synchronized void updatePosition() { 175 | if (doc != null && pos != null) { 176 | // track position 177 | int offset = pos.getOffset(); 178 | int oldLineIdx = lineIdx; 179 | lineIdx = doc.getDefaultRootElement().getElementIndex(offset); // offset to lineNo 180 | if (lineIdx != oldLineIdx) { 181 | for (LineListener l : listeners) { 182 | if (l != null) { 183 | l.lineChanged(this, oldLineIdx, lineIdx); 184 | } else { 185 | listeners.remove(l); // remove null listener 186 | } 187 | } 188 | } 189 | } 190 | } 191 | 192 | /** 193 | * Add listener to be notified when the line number changes. 194 | * 195 | * @param l the listener to add 196 | */ 197 | public void addListener(LineListener l) { 198 | listeners.add(l); 199 | } 200 | 201 | /** 202 | * Remove a listener for line number changes. 203 | * 204 | * @param l the listener to remove 205 | */ 206 | public void removeListener(LineListener l) { 207 | listeners.remove(l); 208 | } 209 | 210 | /** 211 | * Calculate the offset of the first non-whitespace character in a string. 212 | * 213 | * @param str the string to examine 214 | * @return offset of first non-whitespace character in str 215 | */ 216 | protected static int nonWhiteSpaceOffset(String str) { 217 | for (int i = 0; i < str.length(); i++) { 218 | if (!Character.isWhitespace(str.charAt(i))) { 219 | return i; 220 | } 221 | } 222 | return str.length(); 223 | } 224 | 225 | /** 226 | * Called when the {@link Document} registered using {@link #startTracking} 227 | * is edited. This happens when text is inserted or removed. 228 | * 229 | * @param de 230 | */ 231 | protected void editEvent(DocumentEvent de) { 232 | //System.out.println("document edit @ " + de.getOffset()); 233 | if (de.getOffset() <= pos.getOffset()) { 234 | updatePosition(); 235 | //System.out.println("updating, new line no: " + lineNo); 236 | } 237 | } 238 | 239 | /** 240 | * {@link DocumentListener} callback. Called when text is inserted. 241 | * 242 | * @param de 243 | */ 244 | @Override 245 | public void insertUpdate(DocumentEvent de) { 246 | editEvent(de); 247 | } 248 | 249 | /** 250 | * {@link DocumentListener} callback. Called when text is removed. 251 | * 252 | * @param de 253 | */ 254 | @Override 255 | public void removeUpdate(DocumentEvent de) { 256 | editEvent(de); 257 | } 258 | 259 | /** 260 | * {@link DocumentListener} callback. Called when attributes are changed. 261 | * Not used. 262 | * 263 | * @param de 264 | */ 265 | @Override 266 | public void changedUpdate(DocumentEvent de) { 267 | // not needed. 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/LineListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | /** 21 | * A Listener for line number changes. 22 | * 23 | * @author Martin Leopold 24 | */ 25 | public interface LineListener { 26 | 27 | /** 28 | * Event handler for line number changes (due to editing). 29 | * 30 | * @param line the line that has changed 31 | * @param oldLineIdx the old line index (0-based) 32 | * @param newLineIdx the new line index (0-based) 33 | */ 34 | void lineChanged(LineID line, int oldLineIdx, int newLineIdx); 35 | } 36 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/LocalVariableNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.ClassNotLoadedException; 21 | import com.sun.jdi.InvalidTypeException; 22 | import com.sun.jdi.LocalVariable; 23 | import com.sun.jdi.StackFrame; 24 | import com.sun.jdi.Value; 25 | import java.util.logging.Level; 26 | import java.util.logging.Logger; 27 | 28 | /** 29 | * Specialized {@link VariableNode} for representing local variables. Overrides 30 | * {@link #setValue} to properly change the value of the encapsulated local 31 | * variable. 32 | * 33 | * @author Martin Leopold 34 | */ 35 | public class LocalVariableNode extends VariableNode { 36 | 37 | protected LocalVariable var; 38 | protected StackFrame frame; 39 | 40 | /** 41 | * Construct a {@link LocalVariableNode}. 42 | * 43 | * @param name the name 44 | * @param type the type 45 | * @param value the value 46 | * @param var the local variable 47 | * @param frame the stack frame containing the local variable 48 | */ 49 | public LocalVariableNode(String name, String type, Value value, LocalVariable var, StackFrame frame) { 50 | super(name, type, value); 51 | this.var = var; 52 | this.frame = frame; 53 | } 54 | 55 | @Override 56 | public void setValue(Value value) { 57 | try { 58 | frame.setValue(var, value); 59 | } catch (InvalidTypeException ex) { 60 | Logger.getLogger(LocalVariableNode.class.getName()).log(Level.SEVERE, null, ex); 61 | } catch (ClassNotLoadedException ex) { 62 | Logger.getLogger(LocalVariableNode.class.getName()).log(Level.SEVERE, null, ex); 63 | } 64 | this.value = value; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/OffsetMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-14 Manindra Moharana 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | 19 | package processing.mode.experimental; 20 | 21 | import java.util.ArrayList; 22 | import static processing.mode.experimental.ExperimentalMode.log; 23 | 24 | /** 25 | * Performs offset matching between PDE and Java code (one line of code only) 26 | * 27 | * @author Manindra Moharana 28 | * 29 | */ 30 | 31 | public class OffsetMatcher { 32 | 33 | public ArrayList offsetMatch; 34 | 35 | String pdeCodeLine, javaCodeLine; 36 | 37 | boolean matchingNeeded = false; 38 | 39 | public OffsetMatcher(String pdeCode, String javaCode) { 40 | this.pdeCodeLine = pdeCode; 41 | this.javaCodeLine = javaCode; 42 | if(pdeCodeLine.trim().equals(javaCodeLine.trim())){ //TODO: trim() needed here? 43 | matchingNeeded = false; 44 | offsetMatch = new ArrayList(); 45 | log("Offset Matching not needed"); 46 | } 47 | else 48 | { 49 | matchingNeeded = true; 50 | minDistance(); 51 | } 52 | 53 | // log("PDE <-> Java"); 54 | for (int i = 0; i < offsetMatch.size(); i++) { 55 | // log(offsetMatch.get(i).pdeOffset + " <-> " 56 | // + offsetMatch.get(i).javaOffset + 57 | // ", " + word1.charAt(offsetMatch.get(i).pdeOffset) 58 | // + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); 59 | } 60 | // log("Length " + offsetMatch.size()); 61 | } 62 | 63 | public int getPdeOffForJavaOff(int start, int length) { 64 | log("PDE :" + pdeCodeLine + "\nJAVA:" + javaCodeLine); 65 | if(!matchingNeeded) return start; 66 | int ans = getPdeOffForJavaOff(start), end = getPdeOffForJavaOff(start + length - 1); 67 | log(start + " java start off, pde start off " 68 | + ans); 69 | log((start + length - 1) + " java end off, pde end off " 70 | + end); 71 | log("J: " + javaCodeLine.substring(start, start + length) + "\nP: " 72 | + pdeCodeLine.substring(ans, end + 1)); 73 | return ans; 74 | } 75 | 76 | public int getJavaOffForPdeOff(int start, int length) { 77 | if(!matchingNeeded) return start; 78 | int ans = getJavaOffForPdeOff(start); 79 | log(start + " pde start off, java start off " 80 | + getJavaOffForPdeOff(start)); 81 | log((start + length - 1) + " pde end off, java end off " 82 | + getJavaOffForPdeOff(start + length - 1)); 83 | return ans; 84 | } 85 | 86 | public int getPdeOffForJavaOff(int javaOff) { 87 | if(!matchingNeeded) return javaOff; 88 | for (int i = offsetMatch.size() - 1; i >= 0; i--) { 89 | if (offsetMatch.get(i).javaOffset < javaOff) { 90 | continue; 91 | } else if (offsetMatch.get(i).javaOffset == javaOff) { 92 | // int j = i; 93 | while (offsetMatch.get(--i).javaOffset == javaOff) { 94 | log("MP " + offsetMatch.get(i).javaOffset + " " 95 | + offsetMatch.get(i).pdeOffset); 96 | } 97 | int pdeOff = offsetMatch.get(++i).pdeOffset; 98 | while (offsetMatch.get(--i).pdeOffset == pdeOff) 99 | ; 100 | int j = i + 1; 101 | if (j > -1 && j < offsetMatch.size()) 102 | return offsetMatch.get(j).pdeOffset; 103 | } 104 | 105 | } 106 | return -1; 107 | } 108 | 109 | public int getJavaOffForPdeOff(int pdeOff) { 110 | if(!matchingNeeded) return pdeOff; 111 | for (int i = offsetMatch.size() - 1; i >= 0; i--) { 112 | if (offsetMatch.get(i).pdeOffset < pdeOff) { 113 | continue; 114 | } else if (offsetMatch.get(i).pdeOffset == pdeOff) { 115 | // int j = i; 116 | while (offsetMatch.get(--i).pdeOffset == pdeOff) { 117 | // log("MP " + offsetMatch.get(i).javaOffset + " " 118 | // + offsetMatch.get(i).pdeOffset); 119 | } 120 | int javaOff = offsetMatch.get(++i).javaOffset; 121 | while (offsetMatch.get(--i).javaOffset == javaOff) 122 | ; 123 | int j = i + 1; 124 | if (j > -1 && j < offsetMatch.size()) 125 | return offsetMatch.get(j).javaOffset; 126 | } 127 | 128 | } 129 | return -1; 130 | } 131 | 132 | /** 133 | * Finds 'distance' between two Strings. 134 | * See Edit Distance Problem 135 | * https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/styles/pages/editdistance.html 136 | * http://www.stanford.edu/class/cs124/lec/med.pdf 137 | * 138 | */ 139 | private int minDistance() { 140 | 141 | // word1 = reverse(word1); 142 | // word2 = reverse(word2); 143 | int len1 = pdeCodeLine.length(); 144 | int len2 = javaCodeLine.length(); 145 | log(pdeCodeLine + " len: " + len1); 146 | log(javaCodeLine + " len: " + len2); 147 | // len1+1, len2+1, because finally return dp[len1][len2] 148 | int[][] dp = new int[len1 + 1][len2 + 1]; 149 | 150 | for (int i = 0; i <= len1; i++) { 151 | dp[i][0] = i; 152 | } 153 | 154 | for (int j = 0; j <= len2; j++) { 155 | dp[0][j] = j; 156 | } 157 | 158 | //iterate though, and check last char 159 | for (int i = 0; i < len1; i++) { 160 | char c1 = pdeCodeLine.charAt(i); 161 | for (int j = 0; j < len2; j++) { 162 | char c2 = javaCodeLine.charAt(j); 163 | //System.out.print(c1 + "<->" + c2); 164 | //if last two chars equal 165 | if (c1 == c2) { 166 | //update dp value for +1 length 167 | dp[i + 1][j + 1] = dp[i][j]; 168 | // log(); 169 | } else { 170 | int replace = dp[i][j] + 1; 171 | int insert = dp[i][j + 1] + 1; 172 | int delete = dp[i + 1][j] + 1; 173 | // if (replace < delete) { 174 | // log(" --- D"); 175 | // } else 176 | // log(" --- R"); 177 | int min = replace > insert ? insert : replace; 178 | min = delete > min ? min : delete; 179 | dp[i + 1][j + 1] = min; 180 | } 181 | } 182 | } 183 | 184 | ArrayList alist = new ArrayList(); 185 | offsetMatch = alist; 186 | minDistInGrid(dp, len1, len2, 0, 0, pdeCodeLine.toCharArray(), 187 | javaCodeLine.toCharArray(), alist); 188 | return dp[len1][len2]; 189 | } 190 | 191 | private void minDistInGrid(int g[][], int i, int j, int fi, int fj, 192 | char s1[], char s2[], ArrayList set) { 193 | // if(i < s1.length)System.out.print(s1[i] + " <->"); 194 | // if(j < s2.length)System.out.print(s2[j]); 195 | if (i < s1.length && j < s2.length) { 196 | // pdeCodeMap[k] = i; 197 | // javaCodeMap[k] = j; 198 | //System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); 199 | set.add(new OffsetPair(i, j)); 200 | // if (s1[i] != s2[j]) 201 | // System.out.println("--"); 202 | } 203 | //System.out.println(); 204 | if (i == fi && j == fj) { 205 | //System.out.println("Reached end."); 206 | } else { 207 | int a = Integer.MAX_VALUE, b = a, c = a; 208 | if (i > 0) 209 | a = g[i - 1][j]; 210 | if (j > 0) 211 | b = g[i][j - 1]; 212 | if (i > 0 && j > 0) 213 | c = g[i - 1][j - 1]; 214 | int mini = Math.min(a, Math.min(b, c)); 215 | if (mini == a) { 216 | //System.out.println(s1[i + 1] + " " + s2[j]); 217 | minDistInGrid(g, i - 1, j, fi, fj, s1, s2, set); 218 | } else if (mini == b) { 219 | //System.out.println(s1[i] + " " + s2[j + 1]); 220 | minDistInGrid(g, i, j - 1, fi, fj, s1, s2, set); 221 | } else if (mini == c) { 222 | //System.out.println(s1[i + 1] + " " + s2[j + 1]); 223 | minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, set); 224 | } 225 | } 226 | } 227 | 228 | private class OffsetPair { 229 | public final int pdeOffset, javaOffset; 230 | 231 | public OffsetPair(int pde, int java) { 232 | pdeOffset = pde; 233 | javaOffset = java; 234 | } 235 | } 236 | 237 | public static void main(String[] args) { 238 | // minDistance("c = #qwerty;", "c = 0xffqwerty;"); 239 | OffsetMatcher a; 240 | 241 | // a = new OffsetMatcher("int a = int(can); int ball;", 242 | // "int a = PApplet.parseInt(can); int ball;"); 243 | // a.getPdeOffForJavaOff(25, 3); 244 | // a.getJavaOffForPdeOff(12, 3); 245 | // minDistance("static void main(){;", "public static void main(){;"); 246 | // minDistance("#bb00aa", "0xffbb00aa"); 247 | a = new OffsetMatcher("void test(ArrayList boids){", 248 | "public void test(ArrayList boids){"); 249 | a.getJavaOffForPdeOff(20,4); 250 | log("--"); 251 | // a = new OffsetMatcher("color abc = #qwerty;", "int abc = 0xffqwerty;"); 252 | // a.getPdeOffForJavaOff(4, 3); 253 | // a.getJavaOffForPdeOff(6, 3); 254 | // distance("c = #bb00aa;", "c = 0xffbb00aa;"); 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/Problem.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the XQMode project - https://github.com/Manindra29/XQMode 3 | 4 | Under Google Summer of Code 2012 - 5 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 6 | 7 | Copyright (C) 2012 Manindra Moharana 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License version 2 11 | as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.mode.experimental; 24 | 25 | import java.util.regex.Matcher; 26 | import java.util.regex.Pattern; 27 | 28 | import org.eclipse.jdt.core.compiler.IProblem; 29 | 30 | /** 31 | * Wrapper class for IProblem. 32 | * 33 | * Stores the tabIndex and line number according to its tab, including the 34 | * original IProblem object 35 | * 36 | * @author Manindra Moharana <me@mkmoharana.com> 37 | * 38 | */ 39 | public class Problem { 40 | /** 41 | * The IProblem which is being wrapped 42 | */ 43 | private IProblem iProblem; 44 | /** 45 | * The tab number to which the error belongs to 46 | */ 47 | private int tabIndex; 48 | /** 49 | * Line number(pde code) of the error 50 | */ 51 | private int lineNumber; 52 | 53 | private int lineStartOffset; 54 | 55 | private int lineStopOffset; 56 | 57 | /** 58 | * Error Message. Processed form of IProblem.getMessage() 59 | */ 60 | private String message; 61 | 62 | /** 63 | * The type of error - WARNING or ERROR. 64 | */ 65 | private int type; 66 | 67 | public static final int ERROR = 1, WARNING = 2; 68 | 69 | /** 70 | * 71 | * @param iProblem - The IProblem which is being wrapped 72 | * @param tabIndex - The tab number to which the error belongs to 73 | * @param lineNumber - Line number(pde code) of the error 74 | */ 75 | public Problem(IProblem iProblem, int tabIndex, int lineNumber) { 76 | this.iProblem = iProblem; 77 | if(iProblem.isError()) { 78 | type = ERROR; 79 | } 80 | else if(iProblem.isWarning()) { 81 | type = WARNING; 82 | } 83 | this.tabIndex = tabIndex; 84 | this.lineNumber = lineNumber; 85 | this.message = process(iProblem); 86 | } 87 | 88 | public void setPDEOffsets(int startOffset, int stopOffset){ 89 | lineStartOffset = startOffset; 90 | lineStopOffset = stopOffset; 91 | } 92 | 93 | public int getPDELineStartOffset(){ 94 | return lineStartOffset; 95 | } 96 | 97 | public int getPDELineStopOffset(){ 98 | return lineStopOffset; 99 | } 100 | 101 | public String toString() { 102 | return new String("TAB " + tabIndex + ",LN " + lineNumber + "LN START OFF: " 103 | + lineStartOffset + ",LN STOP OFF: " + lineStopOffset + ",PROB: " 104 | + message); 105 | } 106 | 107 | public boolean isError(){ 108 | return type == ERROR; 109 | } 110 | 111 | public boolean isWarning(){ 112 | return type == WARNING; 113 | } 114 | 115 | public String getMessage(){ 116 | return message; 117 | } 118 | 119 | public IProblem getIProblem(){ 120 | return iProblem; 121 | } 122 | 123 | public int getTabIndex(){ 124 | return tabIndex; 125 | } 126 | 127 | public int getLineNumber(){ 128 | return lineNumber; 129 | } 130 | 131 | public void setType(int ProblemType){ 132 | if(ProblemType == ERROR) 133 | type = ERROR; 134 | else if(ProblemType == WARNING) 135 | type = WARNING; 136 | else throw new IllegalArgumentException("Illegal Problem type passed to Problem.setType(int)"); 137 | } 138 | 139 | private static Pattern pattern; 140 | private static Matcher matcher; 141 | 142 | private static final String tokenRegExp = "\\b token\\b"; 143 | 144 | public static String process(IProblem problem) { 145 | return process(problem.getMessage()); 146 | } 147 | 148 | /** 149 | * Processes error messages and attempts to make them a bit more english like. 150 | * Currently performs: 151 | *
  • Remove all instances of token. "Syntax error on token 'blah', delete this token" 152 | * becomes "Syntax error on 'blah', delete this" 153 | * @param message - The message to be processed 154 | * @return String - The processed message 155 | */ 156 | public static String process(String message) { 157 | // Remove all instances of token 158 | // "Syntax error on token 'blah', delete this token" 159 | if(message == null) return null; 160 | pattern = Pattern.compile(tokenRegExp); 161 | matcher = pattern.matcher(message); 162 | message = matcher.replaceAll(""); 163 | 164 | return message; 165 | } 166 | 167 | // Split camel case words into separate words. 168 | // "VaraibleDeclaration" becomes "Variable Declaration" 169 | // But sadly "PApplet" become "P Applet" and so on. 170 | public static String splitCamelCaseWord(String word) { 171 | String newWord = ""; 172 | for (int i = 1; i < word.length(); i++) { 173 | if (Character.isUpperCase(word.charAt(i))) { 174 | // System.out.println(word.substring(0, i) + " " 175 | // + word.substring(i)); 176 | newWord += word.substring(0, i) + " "; 177 | word = word.substring(i); 178 | i = 1; 179 | } 180 | } 181 | newWord += word; 182 | // System.out.println(newWord); 183 | return newWord.trim(); 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-14 Manindra Moharana 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | 19 | package processing.mode.experimental; 20 | 21 | import java.util.ArrayList; 22 | 23 | /** 24 | * A class containing multiple utility methods 25 | * 26 | * @author Manindra Moharana 27 | * 28 | */ 29 | 30 | public class Utils { 31 | 32 | public ArrayList offsetMatch; 33 | String word1, word2; 34 | public static String reverse(String s) { 35 | char w[] = s.toCharArray(); 36 | for (int i = 0; i < w.length / 2; i++) { 37 | char t = w[i]; 38 | w[i] = w[w.length - 1 - i]; 39 | w[w.length - 1 - i] = t; 40 | } 41 | return new String(w); 42 | } 43 | 44 | public void getPdeOffForJavaOff(int start, int length){ 45 | System.out.println("PDE <-> Java" ); 46 | for (int i = 0; i < offsetMatch.size(); i++) { 47 | System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); 48 | System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " 49 | + word2.charAt(offsetMatch.get(i).javaOffset)); 50 | } 51 | System.out.println("Length " + offsetMatch.size()); 52 | System.out.println(start + " java start off, pde start off " 53 | + getPdeOffForJavaOff(start)); 54 | System.out.println((start + length - 1) + " java end off, pde end off " 55 | + getPdeOffForJavaOff(start + length - 1)); 56 | } 57 | 58 | public void getJavaOffForPdeOff(int start, int length){ 59 | // System.out.println("PDE <-> Java" ); 60 | // for (int i = 0; i < offsetMatch.size(); i++) { 61 | // System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); 62 | // System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " 63 | // + word2.charAt(offsetMatch.get(i).javaOffset)); 64 | // } 65 | // System.out.println("Length " + offsetMatch.size()); 66 | System.out.println(start + " pde start off, java start off " 67 | + getJavaOffForPdeOff(start)); 68 | System.out.println((start + length - 1) + " pde end off, java end off " 69 | + getJavaOffForPdeOff(start + length - 1)); 70 | } 71 | 72 | public int getPdeOffForJavaOff(int javaOff){ 73 | for (int i = offsetMatch.size() - 1; i >= 0;i--) { 74 | if(offsetMatch.get(i).javaOffset < javaOff){ 75 | continue; 76 | } 77 | else 78 | if(offsetMatch.get(i).javaOffset == javaOff){ 79 | // int j = i; 80 | while(offsetMatch.get(--i).javaOffset == javaOff){ 81 | System.out.println("MP " + offsetMatch.get(i).javaOffset + " " 82 | + offsetMatch.get(i).pdeOffset); 83 | } 84 | int pdeOff = offsetMatch.get(++i).pdeOffset; 85 | while(offsetMatch.get(--i).pdeOffset == pdeOff); 86 | int j = i + 1; 87 | if (j > -1 && j < offsetMatch.size()) 88 | return offsetMatch.get(j).pdeOffset; 89 | } 90 | 91 | } 92 | return -1; 93 | } 94 | 95 | public int getJavaOffForPdeOff(int pdeOff){ 96 | for (int i = offsetMatch.size() - 1; i >= 0;i--) { 97 | if(offsetMatch.get(i).pdeOffset < pdeOff){ 98 | continue; 99 | } 100 | else 101 | if(offsetMatch.get(i).pdeOffset == pdeOff){ 102 | // int j = i; 103 | while(offsetMatch.get(--i).pdeOffset == pdeOff){ 104 | // System.out.println("MP " + offsetMatch.get(i).javaOffset + " " 105 | // + offsetMatch.get(i).pdeOffset); 106 | } 107 | int javaOff = offsetMatch.get(++i).javaOffset; 108 | while(offsetMatch.get(--i).javaOffset == javaOff); 109 | int j = i + 1; 110 | if (j > -1 && j < offsetMatch.size()) 111 | return offsetMatch.get(j).javaOffset; 112 | } 113 | 114 | } 115 | return -1; 116 | } 117 | 118 | public int minDistance(String word1, String word2) { 119 | this.word1 = word1; 120 | this.word2 = word2; 121 | // word1 = reverse(word1); 122 | // word2 = reverse(word2); 123 | int len1 = word1.length(); 124 | int len2 = word2.length(); 125 | System.out.println(word1 + " len: " + len1); 126 | System.out.println(word2 + " len: " + len2); 127 | // len1+1, len2+1, because finally return dp[len1][len2] 128 | int[][] dp = new int[len1 + 1][len2 + 1]; 129 | 130 | for (int i = 0; i <= len1; i++) { 131 | dp[i][0] = i; 132 | } 133 | 134 | for (int j = 0; j <= len2; j++) { 135 | dp[0][j] = j; 136 | } 137 | 138 | //iterate though, and check last char 139 | for (int i = 0; i < len1; i++) { 140 | char c1 = word1.charAt(i); 141 | for (int j = 0; j < len2; j++) { 142 | char c2 = word2.charAt(j); 143 | //System.out.print(c1 + "<->" + c2); 144 | //if last two chars equal 145 | if (c1 == c2) { 146 | //update dp value for +1 length 147 | dp[i + 1][j + 1] = dp[i][j]; 148 | // System.out.println(); 149 | } else { 150 | int replace = dp[i][j] + 1; 151 | int insert = dp[i][j + 1] + 1; 152 | int delete = dp[i + 1][j] + 1; 153 | // if (replace < delete) { 154 | // System.out.println(" --- D"); 155 | // } else 156 | // System.out.println(" --- R"); 157 | int min = replace > insert ? insert : replace; 158 | min = delete > min ? min : delete; 159 | dp[i + 1][j + 1] = min; 160 | } 161 | } 162 | } 163 | 164 | // for (int i = 0; i < dp.length; i++) { 165 | // for (int j = 0; j < dp[0].length; j++) { 166 | // System.out.print(dp[i][j] + " "); 167 | // } 168 | // System.out.println(); 169 | // } 170 | // int maxLen = Math.max(len1, len2)+2; 171 | // int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; 172 | // System.out.println("Edit distance1: " + dp[len1][len2]); 173 | ArrayList alist = new ArrayList(); 174 | offsetMatch = alist; 175 | minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), 176 | word2.toCharArray(), alist); 177 | // System.out.println("PDE-to-Java"); 178 | // for (int i = 0; i < maxLen; i++) { 179 | // System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); 180 | // System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " 181 | // + word2.charAt(javaCodeMap[i])); 182 | // } 183 | // for (int i = 0; i < alist.size(); i++) { 184 | // System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); 185 | // System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " 186 | // + word2.charAt(alist.get(i).javaOffset)); 187 | // } 188 | // System.out.println("Length " + alist.size()); 189 | return dp[len1][len2]; 190 | } 191 | 192 | public static int distance(String a, String b) { 193 | // a = a.toLowerCase(); 194 | // b = b.toLowerCase(); 195 | 196 | // i == 0 197 | int[] costs = new int[b.length() + 1]; 198 | for (int j = 0; j < costs.length; j++) 199 | costs[j] = j; 200 | for (int i = 1; i <= a.length(); i++) { 201 | // j == 0; nw = lev(i - 1, j) 202 | costs[0] = i; 203 | int nw = i - 1; 204 | for (int j = 1; j <= b.length(); j++) { 205 | int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), 206 | a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1); 207 | nw = costs[j]; 208 | costs[j] = cj; 209 | } 210 | } 211 | System.out.println("Edit distance2: " + costs[b.length()]); 212 | return costs[b.length()]; 213 | } 214 | 215 | public void minDistInGrid(int g[][], int i, int j, int fi, int fj, 216 | char s1[], char s2[], ArrayList set) { 217 | // if(i < s1.length)System.out.print(s1[i] + " <->"); 218 | // if(j < s2.length)System.out.print(s2[j]); 219 | if (i < s1.length && j < s2.length) { 220 | // pdeCodeMap[k] = i; 221 | // javaCodeMap[k] = j; 222 | //System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); 223 | set.add(new OfsSetTemp(i, j)); 224 | // if (s1[i] != s2[j]) 225 | // System.out.println("--"); 226 | } 227 | //System.out.println(); 228 | if (i == fi && j == fj) { 229 | //System.out.println("Reached end."); 230 | } else { 231 | int a = Integer.MAX_VALUE, b = a, c = a; 232 | if (i > 0) 233 | a = g[i - 1][j]; 234 | if (j > 0) 235 | b = g[i][j - 1]; 236 | if (i > 0 && j > 0) 237 | c = g[i - 1][j - 1]; 238 | int mini = Math.min(a, Math.min(b, c)); 239 | if (mini == a) { 240 | //System.out.println(s1[i + 1] + " " + s2[j]); 241 | minDistInGrid(g, i - 1, j, fi, fj, s1, s2,set); 242 | } else if (mini == b) { 243 | //System.out.println(s1[i] + " " + s2[j + 1]); 244 | minDistInGrid(g, i, j - 1, fi, fj, s1, s2, set); 245 | } else if (mini == c) { 246 | //System.out.println(s1[i + 1] + " " + s2[j + 1]); 247 | minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, set); 248 | } 249 | } 250 | } 251 | 252 | public class OfsSetTemp { 253 | public final int pdeOffset, javaOffset; 254 | public OfsSetTemp(int pde, int java){ 255 | pdeOffset = pde; 256 | javaOffset = java; 257 | } 258 | } 259 | 260 | // public class OffsetMatch{ 261 | // public final ArrayList pdeOffset, javaOffset; 262 | // 263 | // public OffsetMatch(){ 264 | // pdeOffset = new ArrayList(); 265 | // javaOffset = new ArrayList(); 266 | // } 267 | // } 268 | 269 | public static void main(String[] args) { 270 | // minDistance("c = #qwerty;", "c = 0xffqwerty;"); 271 | Utils a = new Utils(); 272 | 273 | a.minDistance("int a = int(can); int ball;", "int a = PApplet.parseInt(can); int ball;"); 274 | a.getPdeOffForJavaOff(25, 3); 275 | a.getJavaOffForPdeOff(12,3); 276 | // minDistance("static void main(){;", "public static void main(){;"); 277 | // minDistance("#bb00aa", "0xffbb00aa"); 278 | //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); 279 | System.out.println("--"); 280 | a.minDistance("color abc = #qwerty;", "int abc = 0xffqwerty;"); 281 | a.getPdeOffForJavaOff(4, 3); 282 | a.getJavaOffForPdeOff(6,3); 283 | // distance("c = #bb00aa;", "c = 0xffbb00aa;"); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/VMEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.event.EventSet; 21 | 22 | /** 23 | * Interface for VM callbacks. 24 | * 25 | * @author Martin Leopold 26 | */ 27 | public interface VMEventListener { 28 | 29 | /** 30 | * Receive an event from the VM. Events are sent in batches. See 31 | * documentation of EventSet for more information. 32 | * 33 | * @param es Set of events 34 | */ 35 | void vmEvent(EventSet es); 36 | } 37 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/VMEventReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.VMDisconnectedException; 21 | import com.sun.jdi.event.EventQueue; 22 | import com.sun.jdi.event.EventSet; 23 | import java.util.logging.Level; 24 | import java.util.logging.Logger; 25 | 26 | /** 27 | * Reader Thread for VM Events. Constantly monitors a VMs EventQueue for new 28 | * events and forwards them to an VMEventListener. 29 | * 30 | * @author Martin Leopold 31 | */ 32 | public class VMEventReader extends Thread { 33 | 34 | EventQueue eventQueue; 35 | VMEventListener listener; 36 | 37 | /** 38 | * Construct a VMEventReader. Needs to be kicked off with start() once 39 | * constructed. 40 | * 41 | * @param eventQueue The queue to read events from. Can be obtained from a 42 | * VirtualMachine via eventQueue(). 43 | * @param listener the listener to forward events to. 44 | */ 45 | public VMEventReader(EventQueue eventQueue, VMEventListener listener) { 46 | super("VM Event Thread"); 47 | this.eventQueue = eventQueue; 48 | this.listener = listener; 49 | } 50 | 51 | @Override 52 | public void run() { 53 | try { 54 | while (true) { 55 | EventSet eventSet = eventQueue.remove(); 56 | listener.vmEvent(eventSet); 57 | /* 58 | * for (Event e : eventSet) { System.out.println("VM Event: " + 59 | * e.toString()); } 60 | */ 61 | } 62 | } catch (VMDisconnectedException e) { 63 | Logger.getLogger(VMEventReader.class.getName()).log(Level.INFO, "VMEventReader quit on VM disconnect"); 64 | } catch (Exception e) { 65 | Logger.getLogger(VMEventReader.class.getName()).log(Level.SEVERE, "VMEventReader quit", e); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/VariableInspector.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
    54 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/VariableNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Martin Leopold 3 | * 4 | * This program is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation; either version 2 of the License, or (at your option) any later 7 | * version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 12 | * details. 13 | * 14 | * You should have received a copy of the GNU General Public License along with 15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 | * Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | package processing.mode.experimental; 19 | 20 | import com.sun.jdi.ArrayReference; 21 | import com.sun.jdi.ObjectReference; 22 | import com.sun.jdi.StringReference; 23 | import com.sun.jdi.Value; 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.Enumeration; 27 | import java.util.List; 28 | import javax.swing.tree.MutableTreeNode; 29 | import javax.swing.tree.TreeNode; 30 | 31 | /** 32 | * Model for a variable in the variable inspector. Has a type and name and 33 | * optionally a value. Can have sub-variables (as is the case for objects, and 34 | * arrays). 35 | * 36 | * @author Martin Leopold 37 | */ 38 | public class VariableNode implements MutableTreeNode { 39 | 40 | public static final int TYPE_UNKNOWN = -1; 41 | public static final int TYPE_OBJECT = 0; 42 | public static final int TYPE_ARRAY = 1; 43 | public static final int TYPE_INTEGER = 2; 44 | public static final int TYPE_FLOAT = 3; 45 | public static final int TYPE_BOOLEAN = 4; 46 | public static final int TYPE_CHAR = 5; 47 | public static final int TYPE_STRING = 6; 48 | public static final int TYPE_LONG = 7; 49 | public static final int TYPE_DOUBLE = 8; 50 | public static final int TYPE_BYTE = 9; 51 | public static final int TYPE_SHORT = 10; 52 | public static final int TYPE_VOID = 11; 53 | protected String type; 54 | protected String name; 55 | protected Value value; 56 | protected List children = new ArrayList(); 57 | protected MutableTreeNode parent; 58 | 59 | /** 60 | * Construct a {@link VariableNode}. 61 | * @param name the name 62 | * @param type the type 63 | * @param value the value 64 | */ 65 | public VariableNode(String name, String type, Value value) { 66 | this.name = name; 67 | this.type = type; 68 | this.value = value; 69 | } 70 | 71 | public void setValue(Value value) { 72 | this.value = value; 73 | } 74 | 75 | public Value getValue() { 76 | return value; 77 | } 78 | 79 | /** 80 | * Get a String representation of this variable nodes value. 81 | * 82 | * @return a String representing the value. 83 | */ 84 | public String getStringValue() { 85 | String str; 86 | if (value != null) { 87 | if (getType() == TYPE_OBJECT) { 88 | str = "instance of " + type; 89 | } else if (getType() == TYPE_ARRAY) { 90 | //instance of int[5] (id=998) --> instance of int[5] 91 | str = value.toString().substring(0, value.toString().lastIndexOf(" ")); 92 | } else if (getType() == TYPE_STRING) { 93 | str = ((StringReference) value).value(); // use original string value (without quotes) 94 | } else { 95 | str = value.toString(); 96 | } 97 | } else { 98 | str = "null"; 99 | } 100 | return str; 101 | } 102 | 103 | public String getTypeName() { 104 | return type; 105 | } 106 | 107 | public int getType() { 108 | if (type == null) { 109 | return TYPE_UNKNOWN; 110 | } 111 | if (type.endsWith("[]")) { 112 | return TYPE_ARRAY; 113 | } 114 | if (type.equals("int")) { 115 | return TYPE_INTEGER; 116 | } 117 | if (type.equals("long")) { 118 | return TYPE_LONG; 119 | } 120 | if (type.equals("byte")) { 121 | return TYPE_BYTE; 122 | } 123 | if (type.equals("short")) { 124 | return TYPE_SHORT; 125 | } 126 | if (type.equals("float")) { 127 | return TYPE_FLOAT; 128 | } 129 | if (type.equals("double")) { 130 | return TYPE_DOUBLE; 131 | } 132 | if (type.equals("char")) { 133 | return TYPE_CHAR; 134 | } 135 | if (type.equals("java.lang.String")) { 136 | return TYPE_STRING; 137 | } 138 | if (type.equals("boolean")) { 139 | return TYPE_BOOLEAN; 140 | } 141 | if (type.equals("void")) { 142 | return TYPE_VOID; //TODO: check if this is correct 143 | } 144 | return TYPE_OBJECT; 145 | } 146 | 147 | public String getName() { 148 | return name; 149 | } 150 | 151 | public void setName(String name) { 152 | this.name = name; 153 | } 154 | 155 | /** 156 | * Add a {@link VariableNode} as child. 157 | * 158 | * @param c the {@link VariableNode} to add. 159 | */ 160 | public void addChild(VariableNode c) { 161 | children.add(c); 162 | c.setParent(this); 163 | } 164 | 165 | /** 166 | * Add multiple {@link VariableNode}s as children. 167 | * 168 | * @param children the list of {@link VariableNode}s to add. 169 | */ 170 | public void addChildren(List children) { 171 | for (VariableNode child : children) { 172 | addChild(child); 173 | } 174 | } 175 | 176 | @Override 177 | public TreeNode getChildAt(int i) { 178 | return children.get(i); 179 | } 180 | 181 | @Override 182 | public int getChildCount() { 183 | return children.size(); 184 | } 185 | 186 | @Override 187 | public TreeNode getParent() { 188 | return parent; 189 | } 190 | 191 | @Override 192 | public int getIndex(TreeNode tn) { 193 | return children.indexOf(tn); 194 | } 195 | 196 | @Override 197 | public boolean getAllowsChildren() { 198 | if (value == null) { 199 | return false; 200 | } 201 | 202 | // handle strings 203 | if (getType() == TYPE_STRING) { 204 | return false; 205 | } 206 | 207 | // handle arrays 208 | if (getType() == TYPE_ARRAY) { 209 | ArrayReference array = (ArrayReference) value; 210 | return array.length() > 0; 211 | } 212 | // handle objects 213 | if (getType() == TYPE_OBJECT) { // this also rules out null 214 | // check if this object has any fields 215 | ObjectReference obj = (ObjectReference) value; 216 | return !obj.referenceType().visibleFields().isEmpty(); 217 | } 218 | 219 | return false; 220 | } 221 | 222 | /** 223 | * This controls the default icon and disclosure triangle. 224 | * 225 | * @return true, will show "folder" icon and disclosure triangle. 226 | */ 227 | @Override 228 | public boolean isLeaf() { 229 | //return children.size() == 0; 230 | return !getAllowsChildren(); 231 | } 232 | 233 | @Override 234 | public Enumeration children() { 235 | return Collections.enumeration(children); 236 | } 237 | 238 | /** 239 | * Get a String representation of this {@link VariableNode}. 240 | * 241 | * @return the name of the variable (for sorting to work). 242 | */ 243 | @Override 244 | public String toString() { 245 | return getName(); // for sorting 246 | } 247 | 248 | /** 249 | * Get a String description of this {@link VariableNode}. Contains the type, 250 | * name and value. 251 | * 252 | * @return the description 253 | */ 254 | public String getDescription() { 255 | String str = ""; 256 | if (type != null) { 257 | str += type + " "; 258 | } 259 | str += name; 260 | str += " = " + getStringValue(); 261 | return str; 262 | } 263 | 264 | @Override 265 | public void insert(MutableTreeNode mtn, int i) { 266 | children.add(i, this); 267 | } 268 | 269 | @Override 270 | public void remove(int i) { 271 | MutableTreeNode mtn = children.remove(i); 272 | if (mtn != null) { 273 | mtn.setParent(null); 274 | } 275 | } 276 | 277 | @Override 278 | public void remove(MutableTreeNode mtn) { 279 | children.remove(mtn); 280 | mtn.setParent(null); 281 | } 282 | 283 | /** 284 | * Remove all children from this {@link VariableNode}. 285 | */ 286 | public void removeAllChildren() { 287 | for (MutableTreeNode mtn : children) { 288 | mtn.setParent(null); 289 | } 290 | children.clear(); 291 | } 292 | 293 | @Override 294 | public void setUserObject(Object o) { 295 | if (o instanceof Value) { 296 | value = (Value) o; 297 | } 298 | } 299 | 300 | @Override 301 | public void removeFromParent() { 302 | parent.remove(this); 303 | this.parent = null; 304 | } 305 | 306 | @Override 307 | public void setParent(MutableTreeNode mtn) { 308 | parent = mtn; 309 | } 310 | 311 | /** 312 | * Test for equality. To be equal, two {@link VariableNode}s need to have 313 | * equal type, name and value. 314 | * 315 | * @param obj the object to test for equality with this {@link VariableNode} 316 | * @return true if the given object is equal to this {@link VariableNode} 317 | */ 318 | @Override 319 | public boolean equals(Object obj) { 320 | if (obj == null) { 321 | return false; 322 | } 323 | if (getClass() != obj.getClass()) { 324 | return false; 325 | } 326 | final VariableNode other = (VariableNode) obj; 327 | if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) { 328 | //System.out.println("type not equal"); 329 | return false; 330 | } 331 | if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { 332 | //System.out.println("name not equal"); 333 | return false; 334 | } 335 | if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) { 336 | //System.out.println("value not equal"); 337 | return false; 338 | } 339 | // if (this.parent != other.parent && (this.parent == null || !this.parent.equals(other.parent))) { 340 | // System.out.println("parent not equal: " + this.parent + "/" + other.parent); 341 | // return false; 342 | // } 343 | return true; 344 | } 345 | 346 | /** 347 | * Returns a hash code based on type, name and value. 348 | */ 349 | @Override 350 | public int hashCode() { 351 | int hash = 3; 352 | hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0); 353 | hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0); 354 | hash = 97 * hash + (this.value != null ? this.value.hashCode() : 0); 355 | // hash = 97 * hash + (this.parent != null ? this.parent.hashCode() : 0); 356 | return hash; 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/XQConsoleToggle.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | 3 | /* 4 | Part of the XQMode project - https://github.com/Manindra29/XQMode 5 | 6 | Under Google Summer of Code 2012 - 7 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 8 | 9 | Copyright (C) 2012 Manindra Moharana 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License version 2 13 | as published by the Free Software Foundation. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software Foundation, 22 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | import java.awt.Color; 26 | import java.awt.Dimension; 27 | import java.awt.Graphics; 28 | import java.awt.Graphics2D; 29 | import java.awt.RenderingHints; 30 | import java.awt.event.MouseEvent; 31 | import java.awt.event.MouseListener; 32 | 33 | import javax.swing.JPanel; 34 | 35 | /** 36 | * Toggle Button displayed in the editor line status panel for toggling bewtween 37 | * console and problems list. Glorified JPanel. 38 | * 39 | * @author Manindra Moharana <me@mkmoharana.com> 40 | * 41 | */ 42 | 43 | public class XQConsoleToggle extends JPanel implements MouseListener { 44 | public static final String CONSOLE = "Console", ERRORSLIST = "Errors" ; 45 | 46 | private boolean toggleText = true; 47 | private boolean toggleBG = true; 48 | 49 | /** 50 | * Height of the component 51 | */ 52 | protected int height; 53 | protected DebugEditor editor; 54 | protected String buttonName; 55 | 56 | public XQConsoleToggle(DebugEditor editor, String buttonName, int height) { 57 | this.editor = editor; 58 | this.height = height; 59 | this.buttonName = buttonName; 60 | } 61 | 62 | public Dimension getPreferredSize() { 63 | return new Dimension(70, height); 64 | } 65 | 66 | public Dimension getMinimumSize() { 67 | return getPreferredSize(); 68 | } 69 | 70 | public Dimension getMaximumSize() { 71 | return getPreferredSize(); 72 | } 73 | 74 | public void paintComponent(Graphics g) { 75 | Graphics2D g2d = (Graphics2D) g; 76 | g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 77 | RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 78 | 79 | // On mouse hover, text and background color are changed. 80 | if (toggleBG) { 81 | g.setColor(new Color(0xff9DA7B0)); 82 | g.fillRect(0, 0, this.getWidth(), this.getHeight()); 83 | g.setColor(new Color(0xff29333D)); 84 | g.fillRect(0, 0, 4, this.getHeight()); 85 | g.setColor(Color.BLACK); 86 | } else { 87 | g.setColor(Color.DARK_GRAY); 88 | g.fillRect(0, 0, this.getWidth(), this.getHeight()); 89 | g.setColor(new Color(0xff29333D)); 90 | g.fillRect(0, 0, 4, this.getHeight()); 91 | g.setColor(Color.WHITE); 92 | } 93 | 94 | g.drawString(buttonName, getWidth() / 2 + 2 // + 2 is a offset 95 | - getFontMetrics(getFont()).stringWidth(buttonName) / 2, 96 | this.getHeight() - 6); 97 | if(drawMarker){ 98 | g.setColor(markerColor); 99 | g.fillRect(4, 0, 2, this.getHeight()); 100 | } 101 | } 102 | 103 | boolean drawMarker = false; 104 | protected Color markerColor; 105 | public void updateMarker(boolean value, Color color){ 106 | drawMarker = value; 107 | markerColor = color; 108 | repaint(); 109 | } 110 | 111 | @Override 112 | public void mouseClicked(MouseEvent arg0) { 113 | 114 | this.repaint(); 115 | try { 116 | editor.showProblemListView(buttonName); 117 | } catch (Exception e) { 118 | System.out.println(e); 119 | // e.printStackTrace(); 120 | } 121 | toggleText = !toggleText; 122 | } 123 | 124 | @Override 125 | public void mouseEntered(MouseEvent arg0) { 126 | toggleBG = !toggleBG; 127 | this.repaint(); 128 | } 129 | 130 | @Override 131 | public void mouseExited(MouseEvent arg0) { 132 | toggleBG = !toggleBG; 133 | this.repaint(); 134 | } 135 | 136 | @Override 137 | public void mousePressed(MouseEvent arg0) { 138 | } 139 | 140 | @Override 141 | public void mouseReleased(MouseEvent arg0) { 142 | } 143 | } -------------------------------------------------------------------------------- /src/processing/mode/experimental/XQErrorTable.java: -------------------------------------------------------------------------------- 1 | package processing.mode.experimental; 2 | 3 | /* 4 | Part of the XQMode project - https://github.com/Manindra29/XQMode 5 | 6 | Under Google Summer of Code 2012 - 7 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 8 | 9 | Copyright (C) 2012 Manindra Moharana 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License version 2 13 | as published by the Free Software Foundation. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software Foundation, 22 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | import java.awt.event.MouseAdapter; 26 | import java.awt.event.MouseEvent; 27 | 28 | import javax.swing.JTable; 29 | import javax.swing.SwingWorker; 30 | import javax.swing.table.JTableHeader; 31 | import javax.swing.table.TableModel; 32 | 33 | /** 34 | * Custom JTable implementation for XQMode. Minor tweaks and addtions. 35 | * 36 | * @author Manindra Moharana <me@mkmoharana.com> 37 | * 38 | */ 39 | public class XQErrorTable extends JTable { 40 | 41 | /** 42 | * Column Names of JTable 43 | */ 44 | public static final String[] columnNames = { "Problem", "Tab", "Line" }; 45 | 46 | /** 47 | * Column Widths of JTable. 48 | */ 49 | public int[] columnWidths = { 600, 100, 50 }; // Default Values 50 | 51 | /** 52 | * Is the column being resized? 53 | */ 54 | private boolean columnResizing = false; 55 | 56 | /** 57 | * ErrorCheckerService instance 58 | */ 59 | protected ErrorCheckerService errorCheckerService; 60 | 61 | @Override 62 | public boolean isCellEditable(int rowIndex, int colIndex) { 63 | return false; // Disallow the editing of any cell 64 | } 65 | 66 | public XQErrorTable(final ErrorCheckerService errorCheckerService) { 67 | this.errorCheckerService = errorCheckerService; 68 | for (int i = 0; i < this.getColumnModel().getColumnCount(); i++) { 69 | this.getColumnModel().getColumn(i) 70 | .setPreferredWidth(columnWidths[i]); 71 | } 72 | 73 | this.getTableHeader().setReorderingAllowed(false); 74 | 75 | this.addMouseListener(new MouseAdapter() { 76 | @Override 77 | synchronized public void mouseReleased(MouseEvent e) { 78 | try { 79 | errorCheckerService.scrollToErrorLine(((XQErrorTable) e 80 | .getSource()).getSelectedRow()); 81 | // System.out.print("Row clicked: " 82 | // + ((XQErrorTable) e.getSource()).getSelectedRow()); 83 | } catch (Exception e1) { 84 | System.out.println("Exception XQErrorTable mouseReleased " 85 | + e); 86 | } 87 | } 88 | }); 89 | 90 | // Handles the resizing of columns. When mouse press is detected on 91 | // table header, Stop updating the table, store new values of column 92 | // widths,and resume updating. Updating is disabled as long as 93 | // columnResizing is true 94 | this.getTableHeader().addMouseListener(new MouseAdapter() { 95 | 96 | @Override 97 | public void mousePressed(MouseEvent e) { 98 | columnResizing = true; 99 | } 100 | 101 | @Override 102 | public void mouseReleased(MouseEvent e) { 103 | columnResizing = false; 104 | for (int i = 0; i < ((JTableHeader) e.getSource()) 105 | .getColumnModel().getColumnCount(); i++) { 106 | columnWidths[i] = ((JTableHeader) e.getSource()) 107 | .getColumnModel().getColumn(i).getWidth(); 108 | // System.out.println("nw " + columnWidths[i]); 109 | } 110 | } 111 | }); 112 | } 113 | 114 | 115 | /** 116 | * Updates table contents with new data 117 | * @param tableModel - TableModel 118 | * @return boolean - If table data was updated 119 | */ 120 | @SuppressWarnings("rawtypes") 121 | synchronized public boolean updateTable(final TableModel tableModel) { 122 | 123 | // If problems list is not visible, no need to update 124 | if (!this.isVisible()) { 125 | return false; 126 | } 127 | 128 | SwingWorker worker = new SwingWorker() { 129 | 130 | protected Object doInBackground() throws Exception { 131 | return null; 132 | } 133 | 134 | protected void done() { 135 | 136 | try { 137 | setModel(tableModel); 138 | 139 | // Set column widths to user defined widths 140 | for (int i = 0; i < getColumnModel().getColumnCount(); i++) { 141 | getColumnModel().getColumn(i).setPreferredWidth( 142 | columnWidths[i]); 143 | } 144 | getTableHeader().setReorderingAllowed(false); 145 | validate(); 146 | repaint(); 147 | } catch (Exception e) { 148 | System.out.println("Exception at XQErrorTable.updateTable " + e); 149 | // e.printStackTrace(); 150 | } 151 | } 152 | }; 153 | 154 | try { 155 | if (!columnResizing) { 156 | worker.execute(); 157 | } 158 | } catch (Exception e) { 159 | System.out.println("ErrorTable updateTable Worker's slacking." 160 | + e.getMessage()); 161 | // e.printStackTrace(); 162 | } 163 | return true; 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/processing/mode/experimental/XQPreprocessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the XQMode project - https://github.com/Manindra29/XQMode 3 | 4 | Under Google Summer of Code 2012 - 5 | http://www.google-melange.com/gsoc/homepage/google/gsoc2012 6 | 7 | Copyright (C) 2012 Manindra Moharana 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License version 2 11 | as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.mode.experimental; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import org.eclipse.jdt.core.JavaCore; 30 | import org.eclipse.jdt.core.dom.AST; 31 | import org.eclipse.jdt.core.dom.ASTParser; 32 | import org.eclipse.jdt.core.dom.ASTVisitor; 33 | import org.eclipse.jdt.core.dom.CompilationUnit; 34 | import org.eclipse.jdt.core.dom.MethodDeclaration; 35 | import org.eclipse.jdt.core.dom.Modifier; 36 | import org.eclipse.jdt.core.dom.NumberLiteral; 37 | import org.eclipse.jdt.core.dom.SimpleType; 38 | import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 39 | import org.eclipse.jface.text.BadLocationException; 40 | import org.eclipse.jface.text.Document; 41 | import org.eclipse.text.edits.MalformedTreeException; 42 | import org.eclipse.text.edits.TextEdit; 43 | 44 | import processing.mode.java.preproc.PdePreprocessor; 45 | 46 | /** 47 | * My implementation of P5 preprocessor. Uses Eclipse JDT features instead of 48 | * ANTLR. Performance gains mostly and full control over debug output. But needs 49 | * lots and lots of testing. There will always an option to switch back to PDE 50 | * preproc. 51 | * 52 | * @author Manindra Moharana <me@mkmoharana.com> 53 | * 54 | */ 55 | public class XQPreprocessor { 56 | 57 | private ASTRewrite rewrite = null; 58 | private ArrayList imports; 59 | private ArrayList extraImports; 60 | 61 | private String[] coreImports, defaultImports; 62 | 63 | public XQPreprocessor() { 64 | PdePreprocessor p = new PdePreprocessor(null); 65 | defaultImports = p.getDefaultImports(); 66 | coreImports = p.getCoreImports(); 67 | } 68 | 69 | /** 70 | * The main method that performs preprocessing. Converts code into compilable java. 71 | * @param source - String 72 | * @param programImports - List of import statements 73 | * @return String - Compile ready java code 74 | */ 75 | public String doYourThing(String source, 76 | ArrayList programImports) { 77 | this.extraImports = programImports; 78 | //source = prepareImports() + source; 79 | Document doc = new Document(source); 80 | 81 | ASTParser parser = ASTParser.newParser(AST.JLS4); 82 | parser.setSource(doc.get().toCharArray()); 83 | parser.setKind(ASTParser.K_COMPILATION_UNIT); 84 | 85 | @SuppressWarnings("unchecked") 86 | Map options = JavaCore.getOptions(); 87 | 88 | // Ben has decided to move on to 1.6. Yay! 89 | JavaCore.setComplianceOptions(JavaCore.VERSION_1_6, options); 90 | options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); 91 | parser.setCompilerOptions(options); 92 | CompilationUnit cu = (CompilationUnit) parser.createAST(null); 93 | cu.recordModifications(); 94 | rewrite = ASTRewrite.create(cu.getAST()); 95 | cu.accept(new XQASTVisitor()); 96 | 97 | TextEdit edits = cu.rewrite(doc, null); 98 | try { 99 | edits.apply(doc); 100 | } catch (MalformedTreeException e) { 101 | e.printStackTrace(); 102 | } catch (BadLocationException e) { 103 | e.printStackTrace(); 104 | } 105 | // System.out.println("------------XQPreProc-----------------"); 106 | // System.out.println(doc.get()); 107 | // System.out.println("------------XQPreProc End-----------------"); 108 | 109 | // Calculate main class offset 110 | int position = doc.get().indexOf("{") + 1; 111 | int lines = 0; 112 | for (int i = 0; i < position; i++) { 113 | if (doc.get().charAt(i) == '\n') { 114 | lines++; 115 | } 116 | } 117 | lines += 2; 118 | // System.out.println("Lines: " + lines); 119 | 120 | return doc.get(); 121 | } 122 | 123 | /** 124 | * Returns all import statements as lines of code 125 | * 126 | * @return String - All import statements combined. Each import in a separate line. 127 | */ 128 | public String prepareImports() { 129 | imports = new ArrayList(); 130 | for (int i = 0; i < extraImports.size(); i++) { 131 | imports.add(new String(extraImports.get(i).getImportName())); 132 | } 133 | imports.add(new String("// Default Imports")); 134 | for (int i = 0; i < coreImports.length; i++) { 135 | imports.add(new String("import " + coreImports[i] + ";")); 136 | } 137 | for (int i = 0; i < defaultImports.length; i++) { 138 | imports.add(new String("import " + defaultImports[i] + ";")); 139 | } 140 | String totalImports = ""; 141 | for (int i = 0; i < imports.size(); i++) { 142 | totalImports += imports.get(i) + "\n"; 143 | } 144 | totalImports += "\n"; 145 | return totalImports; 146 | } 147 | 148 | public String prepareImports(ArrayList programImports) { 149 | this.extraImports = programImports; 150 | return prepareImports(); 151 | } 152 | 153 | /** 154 | * Visitor implementation that does all the substitution dirty work.
    155 | *
  • Any function not specified as being protected or private will be made 156 | * 'public'. This means that void setup() becomes 157 | * public void setup(). 158 | * 159 | *
  • Converts doubles into floats, i.e. 12.3 becomes 12.3f so that people 160 | * don't have to add f after their numbers all the time since it's confusing 161 | * for beginners. Also, most functions of p5 core deal with floats only. 162 | * 163 | * @author Manindra Moharana 164 | * 165 | */ 166 | private class XQASTVisitor extends ASTVisitor { 167 | @SuppressWarnings({ "unchecked", "rawtypes" }) 168 | public boolean visit(MethodDeclaration node) { 169 | if (node.getReturnType2() != null) { 170 | // if return type is color, make it int 171 | // if (node.getReturnType2().toString().equals("color")) { 172 | // System.err.println("color type detected!"); 173 | // node.setReturnType2(rewrite.getAST().newPrimitiveType( 174 | // PrimitiveType.INT)); 175 | // } 176 | 177 | // The return type is not void, no need to make it public 178 | // if (!node.getReturnType2().toString().equals("void")) 179 | // return true; 180 | } 181 | 182 | // Simple method, make it public 183 | if (node.modifiers().size() == 0 && !node.isConstructor()) { 184 | // rewrite.set(node, node.getModifiersProperty(), 185 | // Modifier.PUBLIC, 186 | // null); 187 | // rewrite.getListRewrite(node, 188 | // node.getModifiersProperty()).insertLast(Modifier., null) 189 | List newMod = rewrite.getAST().newModifiers(Modifier.PUBLIC); 190 | node.modifiers().add(newMod.get(0)); 191 | } 192 | 193 | return true; 194 | } 195 | 196 | public boolean visit(NumberLiteral node) { 197 | if (!node.getToken().endsWith("f") 198 | && !node.getToken().endsWith("d")) { 199 | for (int i = 0; i < node.getToken().length(); i++) { 200 | if (node.getToken().charAt(i) == '.') { 201 | 202 | String s = node.getToken() + "f"; 203 | node.setToken(s); 204 | break; 205 | } 206 | } 207 | } 208 | return true; 209 | } 210 | 211 | // public boolean visit(FieldDeclaration node) { 212 | // if (node.getType().toString().equals("color")){ 213 | // System.err.println("color type detected!"); 214 | // node.setType(rewrite.getAST().newPrimitiveType( 215 | // PrimitiveType.INT)); 216 | // } 217 | // return true; 218 | // } 219 | // 220 | // public boolean visit(VariableDeclarationStatement node) { 221 | // if (node.getType().toString().equals("color")){ 222 | // System.err.println("color type detected!"); 223 | // node.setType(rewrite.getAST().newPrimitiveType( 224 | // PrimitiveType.INT)); 225 | // } 226 | // return true; 227 | // } 228 | 229 | /** 230 | * This is added just for debugging purposes - to make sure that all 231 | * instances of color type have been substituded as in by the regex 232 | * search in ErrorCheckerService.preprocessCode(). 233 | */ 234 | public boolean visit(SimpleType node) { 235 | if (node.toString().equals("color")) { 236 | System.err 237 | .println("color type detected! \nThis shouldn't be happening! Please report this as an issue."); 238 | } 239 | return true; 240 | 241 | } 242 | 243 | } 244 | 245 | } 246 | -------------------------------------------------------------------------------- /theme/buttons-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/buttons-2x.png -------------------------------------------------------------------------------- /theme/buttons-debug-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/buttons-debug-2x.png -------------------------------------------------------------------------------- /theme/buttons-debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/buttons-debug.png -------------------------------------------------------------------------------- /theme/buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/buttons.png -------------------------------------------------------------------------------- /theme/mode-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/mode-2x.png -------------------------------------------------------------------------------- /theme/mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/mode.png -------------------------------------------------------------------------------- /theme/theme.txt: -------------------------------------------------------------------------------- 1 | # DEBUGGER 2 | 3 | # breakpointed line background color 4 | breakpoint.bgcolor = #f0f0f0 5 | # marker for breakpointed lines in left hand gutter (2 ascii characters) 6 | breakpoint.marker = <> 7 | breakpoint.marker.color = #4a545e 8 | 9 | # current line background color 10 | currentline.bgcolor = #ffff96 11 | # marker for the current line in left hand gutter (2 ascii characters) 12 | currentline.marker = -> 13 | currentline.marker.color = #e27500 14 | 15 | # left hand gutter background color 16 | gutter.bgcolor = #fcfcfc 17 | # color of vertical separation line 18 | gutter.linecolor = #e9e9e9 19 | # space (in px) added to left and right of gutter markers 20 | gutter.padding = 3 21 | 22 | 23 | # XQMODE 24 | 25 | # underline colors 26 | editor.errorcolor = #ed2630 27 | editor.warningcolor = #ffc30e 28 | editor.errormarkercolor = #ed2630 29 | editor.warningmarkercolor = #ffc30e 30 | 31 | # ERROR BAR - error bar on the right that shows the markers 32 | errorbar.errorcolor = #ed2630 33 | errorbar.warningcolor = #ffc30e 34 | errorbar.backgroundcolor = #2c343d 35 | -------------------------------------------------------------------------------- /theme/var-icons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processing/processing-experimental/2efe9b256724e1b13baf0f6e1b1074305d79ec47/theme/var-icons.gif -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | TODO List for PDE X 2 | =================== 3 | 4 | This would also be a break down of my thought process and ideas as I tackle 5 | various tasks. Previously, a different todo file was used for GSoC 2013. 6 | 7 | Manindra Moharana (me@mkmoharana.com) 8 | 9 | [ ]: Todo, [x] : Done, ? : Undecided Todo, ! : Critical, + : Minor Todo 10 | 11 | 12 | Critical Bugs 13 | ------------- 14 | 15 | -[ ] Better memory management. #1 16 | 17 | -[ ] Breakpoints in classes. #47 18 | 19 | 20 | Normal Bugs 21 | ----------- 22 | -[x] Sketch NOC 6_09: steer PVector, doesn't show completion. #68 23 | 24 | -[x] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is 25 | happening due certain post processing offsets not being accounted for - "public void" 26 | 27 | -[x] New offset matching now used by Show Usage 28 | 29 | -[x] New offset matching now used by Refactoring 30 | 31 | Enhancements/New Features 32 | ------------------------- 33 | 34 | -[x] Precise error highlighting(PEH). Now working for one error per line. Hell yeah! 35 | 36 | -[ ] Gotta fix PEH for multiple errors per line. Will be slightly meticulous. 37 | 38 | -[ ] When viewing Outline View, instead of showing the beginning of the list, 39 | it should select the current node element within which the cursor is presently 40 | positioned. 41 | 42 | -[ ] Begin work on code snippets. 43 | 44 | -[ ] JUnit Testing? 45 | 46 | -[ ] Preferences panel 47 | 48 | -[ ] Line Numbers 49 | 50 | 51 | --------------------------------------------------------------------------------