diff --git a/editor/org.processing.editor/.classpath b/editor/org.processing.editor/.classpath new file mode 100644 index 000000000..8643519bb --- /dev/null +++ b/editor/org.processing.editor/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/editor/org.processing.editor/.project b/editor/org.processing.editor/.project new file mode 100644 index 000000000..84b6287cf --- /dev/null +++ b/editor/org.processing.editor/.project @@ -0,0 +1,28 @@ + + + org.processing.editor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/editor/org.processing.editor/.settings/org.eclipse.jdt.core.prefs b/editor/org.processing.editor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..9b97d40c2 --- /dev/null +++ b/editor/org.processing.editor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Tue Jun 08 10:20:47 EDT 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/editor/org.processing.editor/META-INF/MANIFEST.MF b/editor/org.processing.editor/META-INF/MANIFEST.MF new file mode 100644 index 000000000..65671eaab --- /dev/null +++ b/editor/org.processing.editor/META-INF/MANIFEST.MF @@ -0,0 +1,24 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: org.processing.editor +Bundle-SymbolicName: org.processing.editor;singleton:=true +Bundle-Version: 0.0.2 +Bundle-Activator: org.processing.editor.ProcessingEditorPlugin +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui, + org.eclipse.jface.text, + org.eclipse.ui.editors, + org.eclipse.core.resources, + org.eclipse.ui.ide +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Import-Package: org.eclipse.ui.views.contentoutline +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: libs/ant-launcher.jar, + libs/ant.jar, + libs/antlr.jar, + libs/core.jar, + libs/ecj.jar, + libs/jna.jar, + libs/pde.jar, + . + diff --git a/editor/org.processing.editor/build.properties b/editor/org.processing.editor/build.properties new file mode 100644 index 000000000..8c4fc98bc --- /dev/null +++ b/editor/org.processing.editor/build.properties @@ -0,0 +1,15 @@ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + icons/,\ + keywords.txt,\ + libs/,\ + .,\ + libs/ant-launcher.jar,\ + libs/ant.jar,\ + libs/antlr.jar,\ + libs/core.jar,\ + libs/ecj.jar,\ + libs/jna.jar,\ + libs/pde.jar +source.. = src/ diff --git a/editor/org.processing.editor/icons/processing.gif b/editor/org.processing.editor/icons/processing.gif new file mode 100644 index 000000000..6745233f1 Binary files /dev/null and b/editor/org.processing.editor/icons/processing.gif differ diff --git a/editor/org.processing.editor/keywords.txt b/editor/org.processing.editor/keywords.txt new file mode 100644 index 000000000..bf0be1ec4 --- /dev/null +++ b/editor/org.processing.editor/keywords.txt @@ -0,0 +1,631 @@ +# LITERAL2 specifies constants + +ADD LITERAL2 +ALIGN_CENTER LITERAL2 +ALIGN_LEFT LITERAL2 +ALIGN_RIGHT LITERAL2 +ALPHA LITERAL2 +ALPHA_MASK LITERAL2 +ALT LITERAL2 +AMBIENT LITERAL2 +ARROW LITERAL2 +ARGB LITERAL2 +BACKSPACE LITERAL2 +BASELINE LITERAL2 +BEVEL LITERAL2 +BLEND LITERAL2 +BLUE_MASK LITERAL2 +BLUR LITERAL2 +BOTTOM LITERAL2 +BURN LITERAL2 +CENTER LITERAL2 +CHATTER LITERAL2 +CODED LITERAL2 +COMPLAINT LITERAL2 +COMPOSITE LITERAL2 +COMPONENT LITERAL2 +CONCAVE_POLYGON LITERAL2 +CONTROL LITERAL2 +CONVEX_POLYGON LITERAL2 +CORNER LITERAL2 +CORNERS LITERAL2 +CLOSE LITERAL2 +CMYK LITERAL2 +CODED LITERAL2 +COMPLAINT LITERAL2 +CONTROL LITERAL2 +CORNER LITERAL2 +CORNERS LITERAL2 +CROSS LITERAL2 +CUSTOM LITERAL2 +DARKEST LITERAL2 +DEGREES LITERAL2 +DEG_TO_RAD LITERAL2 +DELETE LITERAL2 +DIAMETER LITERAL2 +DIFFERENCE LITERAL2 +DIFFUSE LITERAL2 +DILATE LITERAL2 +DIRECTIONAL LITERAL2 +DISABLE_ACCURATE_TEXTURES LITERAL2 +DISABLE_DEPTH_SORT LITERAL2 +DISABLE_NATIVE_FONTS LITERAL2 +DISABLE_OPENGL_ERROR_REPORT LITERAL2 +DISABLE_TEXT_SMOOTH LITERAL2 +DISABLED LITERAL2 +DODGE LITERAL2 +DOWN LITERAL2 +DXF LITERAL2 +ENABLE_ACCURATE_TEXTURES LITERAL2 +ENABLE_DEPTH_SORT LITERAL2 +ENABLE_NATIVE_FONTS LITERAL2 +DISABLE_OPENGL_2X_SMOOTH LITERAL2 +ENABLE_OPENGL_4X_SMOOTH LITERAL2 +ENABLE_OPENGL_ERROR_REPORT LITERAL2 +ENTER LITERAL2 +EPSILON LITERAL2 +ERODE LITERAL2 +ESC LITERAL2 +EXCLUSION LITERAL2 +GIF LITERAL2 +GRAY LITERAL2 +GREEN_MASK LITERAL2 +GROUP LITERAL2 +HALF LITERAL2 +HALF_PI LITERAL2 +HAND LITERAL2 +HARD_LIGHT LITERAL2 +HINT_COUNT LITERAL2 +HSB LITERAL2 +IMAGE LITERAL2 +INVERT LITERAL2 +JAVA2D LITERAL2 +JPEG LITERAL2 +LEFT LITERAL2 +LIGHTEST LITERAL2 +LINES LITERAL2 +LINUX LITERAL2 +MACOSX LITERAL2 +MAX_FLOAT LITERAL2 +MAX_INT LITERAL2 +MITER LITERAL2 +MODEL LITERAL2 +MOVE LITERAL2 +MULTIPLY LITERAL2 +NORMAL LITERAL2 +NO_DEPTH_TEST LITERAL2 +NTSC LITERAL2 +ONE LITERAL2 +OPAQUE LITERAL2 +OPEN LITERAL2 +OPENGL LITERAL2 +ORTHOGRAPHIC LITERAL2 +OVERLAY LITERAL2 +PAL LITERAL2 +P2D LITERAL2 +P3D LITERAL2 +PERSPECTIVE LITERAL2 +PI LITERAL2 +PIXEL_CENTER LITERAL2 +POINT LITERAL2 +POINTS LITERAL2 +POSTERIZE LITERAL2 +PROBLEM LITERAL2 +PROJECT LITERAL2 +QUAD_STRIP LITERAL2 +QUADS LITERAL2 +QUARTER_PI LITERAL2 +RAD_TO_DEG LITERAL2 +RADIUS LITERAL2 +RADIANS LITERAL2 +RED_MASK LITERAL2 +REPLACE LITERAL2 +RETURN LITERAL2 +RGB LITERAL2 +RIGHT LITERAL2 +ROUND LITERAL2 +SCREEN LITERAL2 +SECAM LITERAL2 +SHIFT LITERAL2 +SPECULAR LITERAL2 +SOFT_LIGHT LITERAL2 +SQUARE LITERAL2 +SUBTRACT LITERAL2 +SVIDEO LITERAL2 +TAB LITERAL2 +TARGA LITERAL2 +TEXT LITERAL2 +TFF LITERAL2 +THIRD_PI LITERAL2 +THRESHOLD LITERAL2 +TIFF LITERAL2 +TOP LITERAL2 +TRIANGLE_FAN LITERAL2 +TRIANGLES LITERAL2 +TRIANGLE_STRIP LITERAL2 +TUNER LITERAL2 +TWO LITERAL2 +TWO_PI LITERAL2 +UP LITERAL2 +WAIT LITERAL2 +WHITESPACE LITERAL2 + + +# KEYWORD1 specifies datatypes and keywords + +ArrayList KEYWORD1 +Boolean KEYWORD1 +Byte KEYWORD1 +Character KEYWORD1 +Class KEYWORD1 +Double KEYWORD1 +Float KEYWORD1 +Integer KEYWORD1 +HashMap KEYWORD1 +String KEYWORD1 +StringBuffer KEYWORD1 +Thread KEYWORD1 +abstract KEYWORD1 +assert KEYWORD1 +boolean KEYWORD1 +break KEYWORD1 +byte KEYWORD1 +catch KEYWORD1 +char KEYWORD1 +class KEYWORD1 +continue KEYWORD1 +default KEYWORD1 +do KEYWORD1 +double KEYWORD1 +else KEYWORD1 +enum KEYWORD1 +extends KEYWORD1 +false KEYWORD1 +final KEYWORD1 +finally KEYWORD1 +for KEYWORD1 +float KEYWORD1 +if KEYWORD1 +implements KEYWORD1 +import KEYWORD1 +instanceof KEYWORD1 +int KEYWORD1 +interface KEYWORD1 +long KEYWORD1 +native KEYWORD1 +new KEYWORD1 +null KEYWORD1 +package KEYWORD1 +private KEYWORD1 +protected KEYWORD1 +public KEYWORD1 +return KEYWORD1 +short KEYWORD1 +static KEYWORD1 +strictfp KEYWORD1 +super KEYWORD1 +switch KEYWORD1 +synchronized KEYWORD1 +this KEYWORD1 +throw KEYWORD1 +throws KEYWORD1 +transient KEYWORD1 +true KEYWORD1 +try KEYWORD1 +void KEYWORD1 +volatile KEYWORD1 +while KEYWORD1 + +# Depricated API + +arraycopy KEYWORD2 arraycopy_ +openStream KEYWORD2 openStream_ + + +# KEYWORD2 specifies methods and functions + +cache KEYWORD2 + + +# THE TEXT ABOVE IS HAND-WRITTEN AND FOUND IN THE FILE "keywords_base.txt" +# THE TEXT BELOW IS AUTO-GENERATED + + +abs KEYWORD2 abs_ +acos KEYWORD2 acos_ ++= addassign ++ addition +alpha KEYWORD2 alpha_ +ambient KEYWORD2 ambient_ +ambientLight KEYWORD2 ambientLight_ +append KEYWORD2 append_ +applyMatrix KEYWORD2 applyMatrix_ +arc KEYWORD2 arc_ +Array KEYWORD1 Array +[] arrayaccess +arrayCopy KEYWORD2 arrayCopy_ +ArrayList KEYWORD1 ArrayList +asin KEYWORD2 asin_ += assign +atan KEYWORD2 atan_ +atan2 KEYWORD2 atan2_ +background KEYWORD2 background_ +beginCamera KEYWORD2 beginCamera_ +beginRaw KEYWORD2 beginRaw_ +beginRecord KEYWORD2 beginRecord_ +beginShape KEYWORD2 beginShape_ +bezier KEYWORD2 bezier_ +bezierDetail KEYWORD2 bezierDetail_ +bezierPoint KEYWORD2 bezierPoint_ +bezierTangent KEYWORD2 bezierTangent_ +bezierVertex KEYWORD2 bezierVertex_ +binary KEYWORD2 binary_ +binary KEYWORD2 bitwiseAND_ +| bitwiseOR +blend KEYWORD2 blend_ +blendColor KEYWORD2 blendColor_ +blue KEYWORD2 blue_ +boolean KEYWORD1 boolean +boolean KEYWORD2 boolean_ +box KEYWORD2 box_ +break KEYWORD1 break +brightness KEYWORD2 brightness_ +byte KEYWORD1 byte +byte KEYWORD2 byte_ +camera KEYWORD2 camera_ +case KEYWORD1 case +ceil KEYWORD2 ceil_ +char KEYWORD1 char +char KEYWORD2 char_ +char KEYWORD2 class_ +color KEYWORD2 color_ +color KEYWORD1 color_datatype +colorMode KEYWORD2 colorMode_ +, comma +// comment +concat KEYWORD2 concat_ +?: KEYWORD1 conditional_ +constrain KEYWORD2 constrain_ +continue KEYWORD1 continue +copy KEYWORD2 copy_ +cos KEYWORD2 cos_ +createFont KEYWORD2 createFont_ +createGraphics KEYWORD2 createGraphics_ +createImage KEYWORD2 createImage_ +createInput KEYWORD2 createInput_ +createOutput KEYWORD2 createOutput_ +createReader KEYWORD2 createReader_ +createWriter KEYWORD2 createWriter_ +{} curlybraces +cursor KEYWORD2 cursor_ +curve KEYWORD2 curve_ +curveDetail KEYWORD2 curveDetail_ +curvePoint KEYWORD2 curvePoint_ +curveTangent KEYWORD2 curveTangent_ +curveTightness KEYWORD2 curveTightness_ +curveVertex KEYWORD2 curveVertex_ +day KEYWORD2 day_ +-- decrement +default KEYWORD1 default +degrees KEYWORD2 degrees_ +delay KEYWORD2 delay_ +directionalLight KEYWORD2 directionalLight_ +dist KEYWORD2 dist_ +/ divide +/= divideassign +/** doccomment +. dot +double KEYWORD1 double +draw KEYWORD3 draw_ +ellipse KEYWORD2 ellipse_ +ellipseMode KEYWORD2 ellipseMode_ +else KEYWORD1 else +emissive KEYWORD2 emissive_ +endCamera KEYWORD2 endCamera_ +endRaw KEYWORD2 endRaw_ +endRecord KEYWORD2 endRecord_ +endShape KEYWORD2 endShape_ +== equality +exit KEYWORD2 exit_ +exp KEYWORD2 exp_ +expand KEYWORD2 expand_ +extends KEYWORD1 extends +false KEYWORD1 false +fill KEYWORD2 fill_ +filter KEYWORD2 filter_ +final KEYWORD1 final +float KEYWORD1 float +float KEYWORD2 float_ +floor KEYWORD2 floor_ +focused LITERAL2 focused +for KEYWORD1 for_ +frameCount LITERAL2 frameCount +frameRate KEYWORD2 frameRate_ +frameRate LITERAL2 frameRate +frustum KEYWORD2 frustum_ +get KEYWORD2 get_ +< greaterthan +<= greaterthanorequalto +green KEYWORD2 green_ +HALF_PI LITERAL2 HALF_PI +HashMap KEYWORD1 HashMap +height LITERAL2 height +hex KEYWORD2 hex_ +hint KEYWORD2 hint_ +hour KEYWORD2 hour_ +hue KEYWORD2 hue_ +if KEYWORD1 if_ +image KEYWORD2 image_ +imageMode KEYWORD2 imageMode_ +implements KEYWORD1 implements +import KEYWORD1 import +++ increment +!= inequality +int KEYWORD1 int +int KEYWORD2 int_ +join KEYWORD2 join_ +key LITERAL2 key +keyCode LITERAL2 keyCode +keyPressed KEYWORD2 keyPressed_ +keyPressed LITERAL2 keyPressed +keyReleased KEYWORD2 keyReleased_ +keyTyped KEYWORD2 keyTyped_ +<< leftshift +lerp KEYWORD2 lerp_ +lerpColor KEYWORD2 lerpColor_ +< lessthan +<= lessthanorequalto +lightFalloff KEYWORD2 lightFalloff_ +lights KEYWORD2 lights_ +lightSpecular KEYWORD2 lightSpecular_ +line KEYWORD2 line_ +link KEYWORD2 link_ +loadBytes KEYWORD2 loadBytes_ +loadFont KEYWORD2 loadFont_ +loadImage KEYWORD2 loadImage_ +loadPixels KEYWORD2 loadPixels_ +loadShape KEYWORD2 loadShape_ +loadStrings KEYWORD2 loadStrings_ +log KEYWORD2 log_ +&& logicalAND +! logicalNOT +|| logicalOR +long KEYWORD1 long +loop KEYWORD2 loop_ +mag KEYWORD2 mag_ +map KEYWORD2 map_ +match KEYWORD2 match_ +matchAll KEYWORD2 matchAll_ +max KEYWORD2 max_ +millis KEYWORD2 millis_ +min KEYWORD2 min_ +- minus +minute KEYWORD2 minute_ +modelX KEYWORD2 modelX_ +modelY KEYWORD2 modelY_ +modelZ KEYWORD2 modelZ_ +% modulo +month KEYWORD2 month_ +mouseButton LITERAL2 mouseButton +mouseClicked KEYWORD2 mouseClicked_ +mouseDragged KEYWORD2 mouseDragged_ +mouseMoved KEYWORD2 mouseMoved_ +mousePressed KEYWORD2 mousePressed_ +mousePressed LITERAL2 mousePressed +mouseReleased KEYWORD2 mouseReleased_ +mouseX LITERAL2 mouseX +mouseY LITERAL2 mouseY +/* multilinecomment +* multiply +*= multiplyassign +new KEYWORD1 new +nf KEYWORD2 nf_ +nfc KEYWORD2 nfc_ +nfp KEYWORD2 nfp_ +nfs KEYWORD2 nfs_ +noCursor KEYWORD2 noCursor_ +noFill KEYWORD2 noFill_ +noise KEYWORD2 noise_ +noiseDetail KEYWORD2 noiseDetail_ +noiseSeed KEYWORD2 noiseSeed_ +noLights KEYWORD2 noLights_ +noLoop KEYWORD2 noLoop_ +norm KEYWORD2 norm_ +normal KEYWORD2 normal_ +noSmooth KEYWORD2 noSmooth_ +noStroke KEYWORD2 noStroke_ +noTint KEYWORD2 noTint_ +null KEYWORD1 null +Object KEYWORD1 Object +online LITERAL2 online +open KEYWORD2 open_ +ortho KEYWORD2 ortho_ +param KEYWORD2 param_ +() parentheses +perspective KEYWORD2 perspective_ +PFont KEYWORD1 PFont +list KEYWORD2 PFont_list_ +PGraphics KEYWORD1 PGraphics +beginDraw KEYWORD2 PGraphics_beginDraw_ +endDraw KEYWORD2 PGraphics_endDraw_ +PI LITERAL2 PI +PImage KEYWORD1 PImage +alpha KEYWORD2 PImage_alpha_ +blend KEYWORD2 PImage_blend_ +copy KEYWORD2 PImage_copy_ +filter KEYWORD2 PImage_filter_ +get KEYWORD2 PImage_get_ +height LITERAL2 PImage_height +loadPixels KEYWORD2 PImage_loadPixels_ +mask KEYWORD2 PImage_mask_ +pixels LITERAL2 PImage_pixels +resize KEYWORD2 PImage_resize_ +save KEYWORD2 PImage_save_ +set KEYWORD2 PImage_set_ +updatePixels KEYWORD2 PImage_updatePixels_ +width LITERAL2 PImage_width +pixels LITERAL2 pixels +pmouseX LITERAL2 pmouseX +pmouseY LITERAL2 pmouseY +point KEYWORD2 point_ +point KEYWORD2 pointLight_ +popMatrix KEYWORD2 popMatrix_ +popStyle KEYWORD3 popStyle_ +pow KEYWORD2 pow_ +print KEYWORD2 print_ +printCamera KEYWORD2 printCamera_ +println KEYWORD2 println_ +printMatrix KEYWORD2 printMatrix_ +printProjection KEYWORD2 printProjection_ +PrintWriter KEYWORD1 PrintWriter +close KEYWORD2 PrintWriter_close_ +flush KEYWORD2 PrintWriter_flush_ +print KEYWORD2 PrintWriter_print_ +println KEYWORD2 PrintWriter_println_ +private KEYWORD1 private +PShape KEYWORD1 PShape +disableStyle KEYWORD2 PShape_disableStyle_ +enableStyle KEYWORD2 PShape_enableStyle_ +getChild KEYWORD2 PShape_getChild_ +getHeight KEYWORD2 PShape_getHeight_ +getWidth KEYWORD2 PShape_getWidth_ +isVisible KEYWORD2 PShape_isVisible_ +resetMatrix KEYWORD2 PShape_resetMatrix_ +rotate KEYWORD2 PShape_rotate_ +rotateX KEYWORD2 PShape_rotateX_ +rotateY KEYWORD2 PShape_rotateY_ +rotateZ KEYWORD2 PShape_rotateZ_ +scale KEYWORD2 PShape_scale_ +setVisible KEYWORD2 PShape_setVisible_ +skewX KEYWORD2 PShape_skewX_ +skewY KEYWORD2 PShape_skewY_ +translate KEYWORD2 PShape_translate_ +public KEYWORD1 public +pushMatrix KEYWORD2 pushMatrix_ +pushStyle KEYWORD3 pushStyle_ +PVector KEYWORD1 PVector +add KEYWORD2 PVector_add_ +angleBetween KEYWORD2 PVector_angleBetween_ +array KEYWORD2 PVector_array_ +copy KEYWORD2 PVector_copy_ +cross KEYWORD2 PVector_cross_ +dist KEYWORD2 PVector_dist_ +div KEYWORD2 PVector_div_ +dot KEYWORD2 PVector_dot_ +get KEYWORD2 PVector_get_ +limit KEYWORD2 PVector_limit_ +mag KEYWORD2 PVector_mag_ +mult KEYWORD2 PVector_mult_ +normalize KEYWORD2 PVector_normalize_ +set KEYWORD2 PVector_set_ +sub KEYWORD2 PVector_sub_ +quad KEYWORD2 quad_ +radians KEYWORD2 radians_ +random KEYWORD2 random_ +randomSeed KEYWORD2 randomSeed_ +rect KEYWORD2 rect_ +rectMode KEYWORD2 rectMode_ +red KEYWORD2 red_ +redraw KEYWORD2 redraw_ +requestImage KEYWORD2 requestImage_ +resetMatrix KEYWORD2 resetMatrix_ +return KEYWORD1 return +reverse KEYWORD2 reverse_ +<< rightshift +rotate KEYWORD2 rotate_ +rotateX KEYWORD2 rotateX_ +rotateY KEYWORD2 rotateY_ +rotateZ KEYWORD2 rotateZ_ +round KEYWORD2 round_ +saturation KEYWORD2 saturation_ +save KEYWORD2 save_ +saveBytes KEYWORD2 saveBytes_ +saveFrame KEYWORD2 saveFrame_ +saveStream KEYWORD2 saveStream_ +saveStrings KEYWORD2 saveStrings_ +scale KEYWORD2 scale_ +skewX KEYWORD2 skewX_ +skewY KEYWORD2 skewY_ +screen LITERAL2 screen +screenX KEYWORD2 screenX_ +screenY KEYWORD2 screenY_ +screenZ KEYWORD2 screenZ_ +second KEYWORD2 second_ +selectFolder KEYWORD2 selectFolder_ +selectInput KEYWORD2 selectInput_ +selectOutput KEYWORD2 selectOutput_ +; semicolon +set KEYWORD2 set_ +setup KEYWORD3 setup_ +shape KEYWORD2 shape_ +shapeMode KEYWORD2 shapeMode_ +shininess KEYWORD2 shininess_ +shorten KEYWORD2 shorten_ +sin KEYWORD2 sin_ +size KEYWORD2 size_ +smooth KEYWORD2 smooth_ +sort KEYWORD2 sort_ +specular KEYWORD2 specular_ +sphere KEYWORD2 sphere_ +sphereDetail KEYWORD2 sphereDetail_ +splice KEYWORD2 splice_ +split KEYWORD2 split_ +splitTokens KEYWORD2 splitTokens_ +spotLight KEYWORD2 spotLight_ +sq KEYWORD2 sq_ +sqrt KEYWORD2 sqrt_ +static KEYWORD1 static +status KEYWORD2 status_ +str KEYWORD2 str_ +String KEYWORD1 String +charAt KEYWORD2 String_charAt_ +equals KEYWORD2 String_equals_ +indexOf KEYWORD2 String_indexOf_ +length KEYWORD2 String_length_ +substring KEYWORD2 String_substring_ +toLowerCase KEYWORD2 String_toLowerCase_ +toUpperCase KEYWORD2 String_toUpperCase_ +stroke KEYWORD2 stroke_ +strokeCap KEYWORD2 strokeCap_ +strokeJoin KEYWORD2 strokeJoin_ +strokeWeight KEYWORD2 strokeWeight_ +subset KEYWORD2 subset_ +-= subtractassign +super KEYWORD1 super +switch KEYWORD2 switch_ +tan KEYWORD2 tan_ +text KEYWORD2 text_ +textAlign KEYWORD2 textAlign_ +textAscent KEYWORD2 textAscent_ +textDescent KEYWORD2 textDescent_ +textFont KEYWORD2 textFont_ +textLeading KEYWORD2 textLeading_ +textMode KEYWORD2 textMode_ +textSize KEYWORD2 textSize_ +texture KEYWORD2 texture_ +textureMode KEYWORD2 textureMode_ +textWidth KEYWORD2 textWidth_ +this KEYWORD1 this +tint KEYWORD2 tint_ +translate KEYWORD2 translate_ +triangle KEYWORD2 triangle_ +trim KEYWORD2 trim_ +true KEYWORD1 true +TWO_PI LITERAL2 TWO_PI +unbinary KEYWORD2 unbinary_ +unhex KEYWORD2 unhex_ +updatePixels KEYWORD2 updatePixels_ +vertex KEYWORD2 vertex_ +void KEYWORD1 void +while KEYWORD1 while_ +width LITERAL2 width +XMLElement KEYWORD1 XMLElement +getChild KEYWORD2 XMLElement_getChild_ +getChildCount KEYWORD2 XMLElement_getChildCount_ +getChildren KEYWORD2 XMLElement_getChildren_ +getContent KEYWORD2 XMLElement_getContent_ +getFloatAttribute KEYWORD2 XMLElement_getFloatAttribute_ +getIntAttribute KEYWORD2 XMLElement_getIntAttribute_ +getName KEYWORD2 XMLElement_getName_ +getStringAttribute KEYWORD2 XMLElement_getStringAttribute_ +year KEYWORD2 year_ diff --git a/editor/org.processing.editor/plugin.xml b/editor/org.processing.editor/plugin.xml new file mode 100644 index 000000000..530a33bc3 --- /dev/null +++ b/editor/org.processing.editor/plugin.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editor/org.processing.editor/src/org/processing/actions/RunButton.java b/editor/org.processing.editor/src/org/processing/actions/RunButton.java new file mode 100644 index 000000000..a6633497e --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/actions/RunButton.java @@ -0,0 +1,55 @@ +package org.processing.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorActionDelegate; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.processing.editor.ProcessingLog; + +/** + * Right now this just does some hello world test stuff. + * Soon it will run the preprocessor only. + * Eventually it will function like the run button in the PDE. + * + * @author lonnen + * + */ +public class RunButton implements IEditorActionDelegate { + String editorContents = null; + + /** Main logic for the button */ + public void run(IAction action) { + ProcessingLog.logInfo("Someone hit the toolbar button!"); + } + + /** + * Notifies this action delegate that the selection in the workbench has changed. + * + * We're required to implement this, but right now it does nothing. + */ + public void selectionChanged(IAction action, ISelection selection) { + // ignore. we don't care about the selection, but we have to implement this + } + + /** + * Retrieved the editor contents when a new editor is set. + * This is messy but this is how we get the editor contents from + * the IEditorActionDelegate. When the preprocessor is implemented + * as a proper builder it will be able to retrieve an up-to-date + * copy of the editor contents. + */ + public void setActiveEditor(IAction action, IEditorPart targetEditor) { + if (targetEditor instanceof ITextEditor) { + IDocumentProvider provider= ((ITextEditor) targetEditor).getDocumentProvider(); + IEditorInput input= targetEditor.getEditorInput(); + IDocument document= provider.getDocument(input); + editorContents = document.get(); + } + } + +} diff --git a/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchAuditor.java b/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchAuditor.java new file mode 100644 index 000000000..8453820ca --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchAuditor.java @@ -0,0 +1,490 @@ +package org.processing.builder; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.processing.editor.ProcessingEditorPlugin; +import org.processing.editor.ProcessingLog; + +import processing.app.Preferences; +import processing.app.preproc.PdePreprocessor; +import processing.app.preproc.PreprocessResult; + +/** + * builder for Processing sketches. + *

+ * Preprocesses processing sketch files into java, and then runs the java files + * through the JDT compiler. Errors returned are reflected back on the + * source files. + *

+ * Uses the PDE's sketch folder setup, with an additional /bin/ folder to save the + * build state and intermediate files. + * + * @author lonnen + * + */ +public class ProcessingSketchAuditor extends IncrementalProjectBuilder { + + public static final String BUILDER_ID = ProcessingEditorPlugin.PLUGIN_ID + ".procesingSketchBuilder"; + + /** + * Adds the processing builder to a project + * + * @param project the project whose build spec we are to modify + */ + public static void addBuilderToProject(IProject project){ + + //cannot modify closed projects + if (!project.isOpen()) + return; + + IProjectDescription description; + try{ + description = project.getDescription(); + } catch (Exception e){ + ProcessingLog.logError(e); + return; + } + + // Look for builders already associated with the project + ICommand[] cmds = description.getBuildSpec(); + for (int j = 0; j < cmds.length; j++){ + if (cmds[j].getBuilderName().equals(BUILDER_ID)) + return; + } + + //Associate builder with project. + ICommand newCmd = description.newCommand(); + newCmd.setBuilderName(BUILDER_ID); + List newCmds = new ArrayList(); + newCmds.addAll(Arrays.asList(cmds)); + newCmds.add(newCmd); + description.setBuildSpec( + (ICommand[]) newCmds.toArray(new ICommand[newCmds.size()])); + try{ + project.setDescription(description,null); + } catch (CoreException e){ + ProcessingLog.logError(e); + } + } + + /** + * Remove the processing builder from the project + * + * @param project the project whose build spec we are to modify + */ + public static void removeBuilderFromProject(IProject project){ + + //cannot modify closed projects + if (!project.isOpen()) + return; + + IProjectDescription description; + try{ + description = project.getDescription(); + } catch (Exception e){ + ProcessingLog.logError(e); + return; + } + + // Look for the builder + int index = -1; + ICommand[] cmds = description.getBuildSpec(); + for (int j = 0; j < cmds.length; j++){ + if (cmds[j].getBuilderName().equals(BUILDER_ID)){ + index = j; + break; + } + } + if (index == -1) + return; + + //Remove builder with project. + List newCmds = new ArrayList(); + newCmds.addAll(Arrays.asList(cmds)); + newCmds.remove(index); + description.setBuildSpec( + (ICommand[]) newCmds.toArray(new ICommand[newCmds.size()])); + try{ + project.setDescription(description,null); + } catch (CoreException e){ + ProcessingLog.logError(e); + } + } + + /** + * Triggers a compile of the project. + *

+ * Decides whether a full or incremental build is appropriate. Right now, + * the answer is always a full build. @see incrementalBuild + * + * @param kind the build type + * @param args build arguments + * @param monitor let the user know things are happening + */ + protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { +// if (kind == IncrementalProjectBuilder.FULL_BUILD){ +// fullBuild(monitor); +// } else { +// IResourceDelta delta = getDelta(getProject()); +// if (delta==null){ +// fullBuild(monitor); +// } else { +// incrementalBuild(delta, monitor); +// } +// } + System.out.println("BUILD!"); + + // every build is a full build for now, @see incrementalBuild + fullBuild(monitor); + return null; + } + + /** + * re-compile only the files that have changed + * + * should be much faster than a full build, but because the preprocessor + * mashes together all the source files for a sketch, there is only one + * resource that gets changed every time a sketch is compiled. Until the + * preprocessor is rewritten and can mark up multiple files, every recompile + * request will result in a full build. To save a little time, the build + * method has been modified to reflect this and never call the incremental + * builder, so we avoid the hassle of crawling the resources to try and + * identify which ones will be recomputed -- its safe to assume all of the + * files will be used because even the ones that are unchanged will be + * grabbed eventually. + * + * @param delta an object containing the resource changes + * @param monitor let the user know things are happening + */ + @SuppressWarnings("unused") + private void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) { + System.out.println("Incremental build on "+delta); + try{ + delta.accept(new IResourceDeltaVisitor() { + public boolean visit(IResourceDelta delta){ + System.out.println("changed: "+delta.getResource().getRawLocation()); + return true; // true visits children of the resource + // this is important for folders + } + }); + } catch (CoreException e) { + e.printStackTrace(); // perhaps we should pass this on + //perhaps we should do something with it instead + } + } + + /** + * completely rebuilds the sketch file + * + * this code is essentially a translation of the processing.core sketch + * code to the Eclipse platform. The same code cannot just be reused + * because we need to use the Eclipse virtual file system to access files + * from inside Eclipse. + * + * @param monitor let the user know things are happening + * @throws CoreException if there are problems accessing the files + */ + private void fullBuild(IProgressMonitor monitor) throws CoreException { + + monitor.beginTask("Full Project Build", 4); // no idea how much 'work' to do here + IProject proj = getProject(); // get the project + + if(checkCancel(monitor)) + return; + + if(!deleteProblemMarkers(proj)) + return; + + // IResource.members() doesn't return the files in a consistent order + // so we get the list at the beginning of each build and use folderContents + // whenever we need to get access to the source files during the build. + IResource[] folderContents = proj.members(); //TODO make this location a preference, link to sketchbook + + // 1. concatenate all .pde files to the 'main' pde + + StringBuffer bigCode = new StringBuffer(); // this will hold the program + int bigCount = 0; // how many lines are we talking about here? + + // without a SketchCode object, this field needs to be tracked independently + int[] preprocOffsets = new int[folderContents.length]; + + for(int i = 0; i < folderContents.length; i++){ + IResource file = folderContents[i]; + if(file.getFileExtension() == "pde"){ // filters out only .pde files + String content = readFile((IFile) file); + preprocOffsets[i] = bigCount; + bigCode.append(content); + bigCode.append("\n"); + bigCount += getLineCount(content); + } + } + + monitor.worked(1); + if(checkCancel(monitor)) + return; + + spoof_preferences();// fake the preferences object. + PdePreprocessor preproc = new PdePreprocessor(proj.getName(), 4); //TODO make tab size a preference? + + //final File java = new File(buildPath, name + ".java"); + IFolder outputFolder = proj.getFolder("bin"); // just a handle to the resource //TODO make the derived resources folder a preference + if (!outputFolder.exists()) + outputFolder.create(IResource.NONE, true, null); + + PreprocessResult result = null; + try{ + IFile outputFile = outputFolder.getFile(proj.getName() + ".java"); + + StringWriter outputFileContents = new StringWriter(); + result = preproc.write(outputFileContents, bigCode.toString()); + + // Ugh. It wants an InputStream + ByteArrayInputStream inStream = new ByteArrayInputStream(outputFileContents.toString().getBytes()); + + outputFile.create(inStream, true, monitor); // force flag = true means this should overwrite any existing files + outputFile.setDerived(true); // let the platform know this is a generated file + + }catch(antlr.RecognitionException re){ + //TODO define the RecognitionException problem marker + + // first assume that it's the main file + int errorFile = 0; + int errorLine = re.getLine() - 1; + + // then search through for anyone else whose preprocName is null, + // since they've also been combined into the main pde + for(int i = 1; i < folderContents.length; i++){ + IResource file = folderContents[i]; + if(file.getFileExtension() == "pde" && (preprocOffsets[i] < errorLine)){ + errorFile = i; + } + } + errorLine -= preprocOffsets[errorFile]; + + //DEBUG + System.out.println("error line - error file - offset"); + System.out.println(errorLine + " - " + errorFile + " - " + preprocOffsets[errorFile]); + + String msg = re.getMessage(); + + if (msg.equals("expecting RCURLY, found 'null'")) { + // This can be a problem since the error is sometimes listed as a line + // that's actually past the number of lines. For instance, it might + // report "line 15" of a 14 line program. Added code to highlightLine() + // inside Editor to deal with this situation (since that code is also + // useful for other similar situations). + msg = "Found one too many { characters without a } to match it."; + } + if (msg.indexOf("expecting RBRACK") != -1) { + msg = "Syntax error, maybe a missing right ] character?"; + } + if (msg.indexOf("expecting SEMI") != -1) { + msg = "Syntax error, maybe a missing semicolon?"; + } + if (msg.indexOf("expecting RPAREN") != -1) { + msg = "Syntax error, maybe a missing right parenthesis?"; + } + if (msg.indexOf("preproc.web_colors") != -1) { + msg = "A web color (such as #ffcc00) must be six digits."; + } + + // if there is no friendly translation, just report what you can + reportProblem(msg, (IFile) folderContents[errorFile], errorLine, true); + + } catch (Exception e){ + ProcessingLog.logError(e); + } + + monitor.worked(1); + if(checkCancel(monitor)) + return; + + // copy any .java files to the output directory + for(int i = 0; i < folderContents.length; i++){ + IResource file = folderContents[i]; + if(file.getFileExtension() == "java"){ // copy .java files into the build directory + folderContents[i].copy(outputFolder.getProjectRelativePath(), IResource.DERIVED, monitor); + } else if (file.getFileExtension() == "pde"){ + // The compiler and runner will need this to have a proper offset + preprocOffsets[i] += result.headerOffset; + } + } + + boolean foundMain = preproc.getFoundMain(); // is this still necessary? + + + monitor.worked(1); + if(checkCancel(monitor)) + return; + + //to the java batch compiler! + //org.eclipse.jdt.core.compiler.CompilationProgress progress = null; + +// String baseCommand[] = new String[]{ +// "-Xemacs", +// //"-noExit", // not necessary for ecj +// "-source", "1.5", +// "-target", "1.5", +// "-classpath", sketch.getClassPath(), +// "-nowarn", // we're not currently interested in warnings (works in ecj) +// "-d", buildPath // output the classes in the buildPath +// }; + + //org.eclipse.jdt.core.compiler.batch.BatchCompiler.compile("-verbose", new PrintWriter(System.out), new PrintWriter(System.err), progress); + // do something with it + + // finally, let the monitor know things are done + monitor.done(); + } + + /** + * Try to delete all of the existing problem markers + *

+ * This should also catch all markers that inherit from IMarker.PROBLEM, + * which includes all of the special marker types for Processing. * + * + * @param project the project to be stripped of problem markers + * @return true if all markers were deleted, false if some remain + */ + protected static boolean deleteProblemMarkers(IProject project) { + //TODO change this to remove markers specific to the Processing builder only + // though that requires making Processing specific markers first + try{ + project.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); + return true; + } catch (CoreException e) { + ProcessingLog.logError(e); + return false; + } + } + + /** + * utility method to read in a file and return it as a string + * + * @param file a resource handler for a file + * @return contents of the file + */ + private String readFile(IFile file) { + if (!file.exists()) + return ""; + InputStream stream = null; + try{ + stream = file.getContents(); + Reader reader = new BufferedReader(new InputStreamReader(stream)); + StringBuffer result = new StringBuffer(2048); + char[] buf = new char[2048]; + while (true){ + int count = reader.read(buf); + if (count < 0) + break; + result.append(buf, 0, count); + } + return result.toString(); + } catch (Exception e){ // IOException and CoreException + ProcessingLog.logError(e); + return ""; + } finally { + try{ + if (stream != null) + stream.close(); + } catch (IOException e){ + ProcessingLog.logError(e); + return ""; + } + } + } + + private int getLineCount(String what){ + int count = 1; + for (char c : what.toCharArray()) { + if (c == '\n') count++; + } + return count; + } + + /** + * Generates a problem marker from the preprocessor output + *

+ * The preprocessor only hands back a line and column. This method reports the whole + * line and the message like the PDE. + * + * @param msg error message + * @param file where the problem occurred + * @param line_number what line did the problem occur on + * @param isError is this an error + */ + private void reportProblem( String msg, IFile file, int line_number, boolean isError){ + System.out.println( (isError ? "ERROR: " : "WARNING: ") + msg); + try{ + IMarker marker = file.createMarker(IMarker.PROBLEM); + marker.setAttribute(IMarker.MESSAGE, msg); + marker.setAttribute(IMarker.LINE_NUMBER, line_number); + marker.setAttribute(IMarker.SEVERITY, isError ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING); + } catch(CoreException e){ + ProcessingLog.logError(e); + return; + } + + } + + /** + * Checks the progress monitor for interruption + * + * @param monitor + * @return true if the monitor is interrupted, false otherwise + */ + private boolean checkCancel(IProgressMonitor monitor){ + if (monitor.isCanceled()){ + throw new OperationCanceledException(); + } + if (isInterrupted()){ + return true; + } + return false; + } + + /** + * Sets up the Static processing.app.Preferences class. + */ + private void spoof_preferences(){ + Preferences.set("editor.tabs.size", "4"); + Preferences.set("preproc.substitute_floats","true"); + Preferences.set("preproc.web_colors", "true"); + Preferences.set("preproc.color_datatype", "true"); + Preferences.set("preproc.enhanced_casting", "true"); + Preferences.set("preproc.substitute.unicode", "true"); + Preferences.set("preproc.output_parse.tree", "false"); + Preferences.set("export.application.fullscreen", "false"); + Preferences.set("run.present.bgcolor", "#666666"); + Preferences.set("export.application.stop", "true"); + Preferences.set("run.present.stop.color", "#cccccc"); + Preferences.set("run.window.bgcolor", "#ECE9D8"); + Preferences.set("preproc.imports.list", "java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image,java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.*"); + } + +} diff --git a/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchNature.java b/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchNature.java new file mode 100644 index 000000000..d34b29aa2 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/builder/ProcessingSketchNature.java @@ -0,0 +1,60 @@ +package org.processing.builder; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.processing.editor.ProcessingLog; + +public class ProcessingSketchNature implements IProjectNature { + + private IProject project; + + /** + * Access method for this natures project + */ + public IProject getProject() { + return project; + } + + /** + * Sets the project this nature is managing + */ + public void setProject(IProject project) { + this.project = project; + } + + /** + * associate the processing sketch builder with the project + */ + public void configure() throws CoreException { + ProcessingSketchAuditor.addBuilderToProject(project); + new Job("Processing Sketch Audit"){ + protected IStatus run(IProgressMonitor monitor){ + try{ + project.build( + ProcessingSketchAuditor.FULL_BUILD, + ProcessingSketchAuditor.BUILDER_ID, + null, + monitor); + } catch (CoreException e){ + ProcessingLog.logError(e); + } + return Status.OK_STATUS; + } + }.schedule(); + } + + /** + * dissociate the processing sketch builder from the project + * and remove the markers it generated. + */ + public void deconfigure() throws CoreException { + ProcessingSketchAuditor.removeBuilderFromProject(project); + ProcessingSketchAuditor.deleteProblemMarkers(project); + } + +} diff --git a/editor/org.processing.editor/src/org/processing/editor/PresentationAction.java b/editor/org.processing.editor/src/org/processing/editor/PresentationAction.java new file mode 100644 index 000000000..f5785a5dc --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/PresentationAction.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextEditorAction; + +/** + * A toolbar action which toggles the presentation model of the + * connected text editor. The editor shows either the highlight range + * only or always the whole document. + */ +public class PresentationAction extends TextEditorAction { + + /** + * Constructs and updates the action. + */ + public PresentationAction() { + super(ProcessingEditorMessages.getResourceBundle(), "TogglePresentation.", null); //$NON-NLS-1$ + update(); + } + + /* (non-Javadoc) + * Method declared on IAction + */ + public void run() { + + ITextEditor editor= getTextEditor(); + + editor.resetHighlightRange(); + boolean show= editor.showsHighlightRangeOnly(); + setChecked(!show); + editor.showHighlightRangeOnly(!show); + } + + /* (non-Javadoc) + * Method declared on TextEditorAction + */ + public void update() { + setChecked(getTextEditor() != null && getTextEditor().showsHighlightRangeOnly()); + setEnabled(true); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingActionContributor.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingActionContributor.java new file mode 100644 index 000000000..0e9c8f807 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingActionContributor.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import org.eclipse.jface.action.*; +import org.eclipse.ui.*; +import org.eclipse.ui.editors.text.TextEditorActionContributor; +import org.eclipse.ui.texteditor.*; + +/** + * Contributes interesting Java actions to the desktop's Edit menu and the toolbar. + */ +public class ProcessingActionContributor extends TextEditorActionContributor { + + protected RetargetTextEditorAction fContentAssistProposal; + protected RetargetTextEditorAction fContentAssistTip; + protected TextEditorAction fTogglePresentation; + + /** + * Default constructor. + */ + public ProcessingActionContributor() { + super(); + fContentAssistProposal= new RetargetTextEditorAction(ProcessingEditorMessages.getResourceBundle(), "ContentAssistProposal."); //$NON-NLS-1$ + fContentAssistProposal.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + fContentAssistTip= new RetargetTextEditorAction(ProcessingEditorMessages.getResourceBundle(), "ContentAssistTip."); //$NON-NLS-1$ + fContentAssistTip.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION); + fTogglePresentation= new PresentationAction(); + } + + /* + * @see IEditorActionBarContributor#init(IActionBars) + */ + public void init(IActionBars bars) { + super.init(bars); + + IMenuManager menuManager= bars.getMenuManager(); + IMenuManager editMenu= menuManager.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT); + if (editMenu != null) { + editMenu.add(new Separator()); + editMenu.add(fContentAssistProposal); + editMenu.add(fContentAssistTip); + } + + IToolBarManager toolBarManager= bars.getToolBarManager(); + if (toolBarManager != null) { + toolBarManager.add(new Separator()); + toolBarManager.add(fTogglePresentation); + } + } + + /* + * + */ + private void doSetActiveEditor(IEditorPart part) { + super.setActiveEditor(part); + + ITextEditor editor= null; + if (part instanceof ITextEditor) + editor= (ITextEditor) part; + + fContentAssistProposal.setAction(getAction(editor, "ContentAssistProposal")); //$NON-NLS-1$ + fContentAssistTip.setAction(getAction(editor, "ContentAssistTip")); //$NON-NLS-1$ + + fTogglePresentation.setEditor(editor); + fTogglePresentation.update(); + } + + /* + * @see IEditorActionBarContributor#setActiveEditor(IEditorPart) + */ + public void setActiveEditor(IEditorPart part) { + super.setActiveEditor(part); + doSetActiveEditor(part); + } + + /* + * @see IEditorActionBarContributor#dispose() + */ + public void dispose() { + doSetActiveEditor(null); + super.dispose(); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingAnnotationHover.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingAnnotationHover.java new file mode 100644 index 000000000..33f9d14e3 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingAnnotationHover.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; + +/** + * Provides the information thats displayed in the presentation area of hover popup windows. + * Right now this doesn't provide anything useful. It just hands back the contents of the line + * the mouse is hovering on. + * + * @see org.eclipse.jface.text.source.IAnnotationHover + */ + +public class ProcessingAnnotationHover implements IAnnotationHover { + + /* (non-Javadoc) + * Method declared on IAnnotationHover + */ + public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) { + IDocument document= sourceViewer.getDocument(); + + try { + IRegion info= document.getLineInformation(lineNumber); + return document.get(info.getOffset(), info.getLength()); + } catch (BadLocationException x) { + } + + return null; + } + +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingContentOutlinePage.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingContentOutlinePage.java new file mode 100644 index 000000000..71900ee36 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingContentOutlinePage.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.views.contentoutline.ContentOutlinePage; + +/** + * A content outline page which always represents the content of the + * connected editor in 10 segments. + */ +public class ProcessingContentOutlinePage extends ContentOutlinePage { + + /** + * A segment element. + */ + protected static class Segment { + public String name; + public Position position; + + public Segment(String name, Position position) { + this.name= name; + this.position= position; + } + + public String toString() { + return name; + } + } + + /** + * Divides the editor's document into ten segments and provides elements for them. + */ + protected class ContentProvider implements ITreeContentProvider { + + protected final static String SEGMENTS= "__java_segments"; //$NON-NLS-1$ + protected IPositionUpdater fPositionUpdater= new DefaultPositionUpdater(SEGMENTS); + protected List fContent= new ArrayList(10); + + protected void parse(IDocument document) { + + int lines= document.getNumberOfLines(); + int increment= Math.max(Math.round(lines / 10), 10); + + for (int line= 0; line < lines; line += increment) { + + int length= increment; + if (line + increment > lines) + length= lines - line; + + try { + + int offset= document.getLineOffset(line); + int end= document.getLineOffset(line + length); + length= end - offset; + Position p= new Position(offset, length); + document.addPosition(SEGMENTS, p); + fContent.add(new Segment(MessageFormat.format(ProcessingEditorMessages.getString("OutlinePage.segment.title_pattern"), new Object[] { new Integer(offset) }), p)); //$NON-NLS-1$ + + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + } + } + + /* + * @see IContentProvider#inputChanged(Viewer, Object, Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (oldInput != null) { + IDocument document= fDocumentProvider.getDocument(oldInput); + if (document != null) { + try { + document.removePositionCategory(SEGMENTS); + } catch (BadPositionCategoryException x) { + } + document.removePositionUpdater(fPositionUpdater); + } + } + + fContent.clear(); + + if (newInput != null) { + IDocument document= fDocumentProvider.getDocument(newInput); + if (document != null) { + document.addPositionCategory(SEGMENTS); + document.addPositionUpdater(fPositionUpdater); + + parse(document); + } + } + } + + /* + * @see IContentProvider#dispose + */ + public void dispose() { + if (fContent != null) { + fContent.clear(); + fContent= null; + } + } + + /* + * @see IContentProvider#isDeleted(Object) + */ + public boolean isDeleted(Object element) { + return false; + } + + /* + * @see IStructuredContentProvider#getElements(Object) + */ + public Object[] getElements(Object element) { + return fContent.toArray(); + } + + /* + * @see ITreeContentProvider#hasChildren(Object) + */ + public boolean hasChildren(Object element) { + return element == fInput; + } + + /* + * @see ITreeContentProvider#getParent(Object) + */ + public Object getParent(Object element) { + if (element instanceof Segment) + return fInput; + return null; + } + + /* + * @see ITreeContentProvider#getChildren(Object) + */ + public Object[] getChildren(Object element) { + if (element == fInput) + return fContent.toArray(); + return new Object[0]; + } + } + + protected Object fInput; + protected IDocumentProvider fDocumentProvider; + protected ITextEditor fTextEditor; + + /** + * Creates a content outline page using the given provider and the given editor. + * + * @param provider the document provider + * @param editor the editor + */ + public ProcessingContentOutlinePage(IDocumentProvider provider, ITextEditor editor) { + super(); + fDocumentProvider= provider; + fTextEditor= editor; + } + + /* (non-Javadoc) + * Method declared on ContentOutlinePage + */ + public void createControl(Composite parent) { + + super.createControl(parent); + + TreeViewer viewer= getTreeViewer(); + viewer.setContentProvider(new ContentProvider()); + viewer.setLabelProvider(new LabelProvider()); + viewer.addSelectionChangedListener(this); + + if (fInput != null) + viewer.setInput(fInput); + } + + /* (non-Javadoc) + * Method declared on ContentOutlinePage + */ + public void selectionChanged(SelectionChangedEvent event) { + + super.selectionChanged(event); + + ISelection selection= event.getSelection(); + if (selection.isEmpty()) + fTextEditor.resetHighlightRange(); + else { + Segment segment= (Segment) ((IStructuredSelection) selection).getFirstElement(); + int start= segment.position.getOffset(); + int length= segment.position.getLength(); + try { + fTextEditor.setHighlightRange(start, length, true); + } catch (IllegalArgumentException x) { + fTextEditor.resetHighlightRange(); + } + } + } + + /** + * Sets the input of the outline page + * + * @param input the input of this outline page + */ + public void setInput(Object input) { + fInput= input; + update(); + } + + /** + * Updates the outline page. + */ + public void update() { + TreeViewer viewer= getTreeViewer(); + + if (viewer != null) { + Control control= viewer.getControl(); + if (control != null && !control.isDisposed()) { + control.setRedraw(false); + viewer.setInput(fInput); + viewer.expandAll(); + control.setRedraw(true); + } + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingDocumentSetupParticipant.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingDocumentSetupParticipant.java new file mode 100644 index 000000000..bad95c6af --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingDocumentSetupParticipant.java @@ -0,0 +1,35 @@ +package org.processing.editor; + +import org.eclipse.core.filebuffers.IDocumentSetupParticipant; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; + +/** + * Participates in the setup of a text file buffer document. + *

+ * Requires the "org.eclipse.core.filebuffers.documentSetup" extension point. + * + * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant + */ +public class ProcessingDocumentSetupParticipant implements IDocumentSetupParticipant { + + /** + * Doesn't do much. + */ + public ProcessingDocumentSetupParticipant() { + } + + /** + * Sets up the document. + */ + public void setup(IDocument document) { + if (document instanceof IDocumentExtension3) { + IDocumentExtension3 extension3= (IDocumentExtension3) document; + IDocumentPartitioner partitioner= new FastPartitioner(ProcessingEditorPlugin.getDefault().getProcessingPartitionScanner(), ProcessingPartitionScanner.JAVA_PARTITION_TYPES); + extension3.setDocumentPartitioner(ProcessingEditorPlugin.PROCESSING_PARTITIONING, partitioner); + partitioner.connect(document); + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingEditor.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditor.java new file mode 100644 index 000000000..d6c871906 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditor.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.text.ITextViewerExtension5; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.projection.ProjectionSupport; +import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; +import org.eclipse.ui.texteditor.TextOperationAction; + +/** + * Sets up a Processing specific text editor. + * + * @see org.eclipse.ui.editors.text.TextEditor + */ +public class ProcessingEditor extends TextEditor { + + /** The outline page */ + private ProcessingContentOutlinePage fOutlinePage; + /** The projection support */ + private ProjectionSupport fProjectionSupport; + + /** + * Default + */ + public ProcessingEditor() { + super(); + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method extend the + * actions to add those specific to the receiver + */ + protected void createActions() { + super.createActions(); + + IAction a= new TextOperationAction(ProcessingEditorMessages.getResourceBundle(), "ContentAssistProposal.", this, ISourceViewer.CONTENTASSIST_PROPOSALS); //$NON-NLS-1$ + a.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + setAction("ContentAssistProposal", a); //$NON-NLS-1$ + + a= new TextOperationAction(ProcessingEditorMessages.getResourceBundle(), "ContentAssistTip.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$ + a.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION); + setAction("ContentAssistTip", a); //$NON-NLS-1$ + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method performs any extra + * disposal actions required by the java editor. + */ + public void dispose() { + if (fOutlinePage != null) + fOutlinePage.setInput(null); + super.dispose(); + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method performs any extra + * revert behavior required by the java editor. + */ + public void doRevertToSaved() { + super.doRevertToSaved(); + if (fOutlinePage != null) + fOutlinePage.update(); + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method performs any extra + * save behavior required by the java editor. + * + * @param monitor the progress monitor + */ + public void doSave(IProgressMonitor monitor) { + super.doSave(monitor); + if (fOutlinePage != null) + fOutlinePage.update(); + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method performs any extra + * save as behavior required by the java editor. + */ + public void doSaveAs() { + super.doSaveAs(); + if (fOutlinePage != null) + fOutlinePage.update(); + } + + /** The ProcessingEditor implementation of this + * AbstractTextEditor method performs sets the + * input of the outline page after AbstractTextEditor has set input. + * + * @param input the editor input + * @throws CoreException in case the input can not be set + */ + public void doSetInput(IEditorInput input) throws CoreException { + super.doSetInput(input); + if (fOutlinePage != null) + fOutlinePage.setInput(input); + } + + /** + * {@inheritDoc} + */ + protected void editorContextMenuAboutToShow(IMenuManager menu) { + super.editorContextMenuAboutToShow(menu); + //These menu items are linked to non-functional things. Disabling [lonnen] june 18, 2010 + //addAction(menu, "ContentAssistProposal"); //$NON-NLS-1$ + //addAction(menu, "ContentAssistTip"); //$NON-NLS-1$ + } + +//TODO Write a useful outline +// The outline wasn't doing anything useful. Until it does, leave this commented +// out to keep the outline from showing up at all. +// +// /** The ProcessingEditor implementation of this +// * AbstractTextEditor method gets the outline page +// * when it is requested. +// * +// * @param required the required type +// * @return an adapter for the required type or null +// */ +// public Object getAdapter(Class required) { +// +// if (IContentOutlinePage.class.equals(required)) { +// if (fOutlinePage == null) { +// fOutlinePage= new ProcessingContentOutlinePage(getDocumentProvider(), this); +// if (getEditorInput() != null) +// fOutlinePage.setInput(getEditorInput()); +// } +// return fOutlinePage; +// } +// +// if (fProjectionSupport != null) { +// Object adapter= fProjectionSupport.getAdapter(getSourceViewer(), required); +// if (adapter != null) +// return adapter; +// } +// +// return super.getAdapter(required); +// } + + /** + * Initializes this editor and provides a SourceViewerConfiguration + * + * @see org.eclipse.jface.text.source.SourceViewerConfiguration + */ + protected void initializeEditor() { + super.initializeEditor(); + setSourceViewerConfiguration(new ProcessingSourceViewerConfiguration()); + } + + /** + * {@inheritDoc} + */ + protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + + fAnnotationAccess= createAnnotationAccess(); + fOverviewRuler= createOverviewRuler(getSharedColors()); + + ISourceViewer viewer= new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles); + + // ensure decoration support has been created and configured. + // preferred over SourceViewerDecorationSupport due to impending API changes [lonnen] june 11, 2010 + fSourceViewerDecorationSupport = getSourceViewerDecorationSupport(viewer); + + return viewer; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.ui.texteditor.ExtendedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite) + */ + public void createPartControl(Composite parent) { + super.createPartControl(parent); + ProjectionViewer viewer= (ProjectionViewer) getSourceViewer(); + fProjectionSupport= new ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors()); + fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$ + fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$ + fProjectionSupport.install(); + viewer.doOperation(ProjectionViewer.TOGGLE); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.ui.texteditor.AbstractTextEditor#adjustHighlightRange(int, int) + */ + protected void adjustHighlightRange(int offset, int length) { + ISourceViewer viewer= getSourceViewer(); + if (viewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension= (ITextViewerExtension5) viewer; + extension.exposeModelRange(new Region(offset, length)); + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.java new file mode 100644 index 000000000..a2ff97029 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Processing Editor Messages object handles localization stuff + * using the ProcessingEditorMessages.preferences file. This class + * is never instantiated, and all of its variables and methods are + * static. + * + * @author lonnen + */ +public class ProcessingEditorMessages { + + private static final String RESOURCE_BUNDLE= "org.processing.editor.ProcessingEditorMessages";//$NON-NLS-1$ + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private ProcessingEditorMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + } + + public static ResourceBundle getResourceBundle() { + return fgResourceBundle; + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.properties b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.properties new file mode 100644 index 000000000..840497670 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorMessages.properties @@ -0,0 +1,46 @@ +############################################################################### +# Copyright (c) 2000, 2005 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### + +# Essentially the same as JavaEditorMessage.properties from the Java example [lonnen] June 10 2010 + +## Actions ## + +ContentAssistProposal.label=Content Assist@Ctrl+SPACE +ContentAssistProposal.tooltip=Content Assist +ContentAssistProposal.image= +ContentAssistProposal.description=Content Assist + +ContentAssistTip.label=Content Tip@Ctrl+SHIFT+SPACE +ContentAssistTip.tooltip=Content Tip +ContentAssistTip.image= +ContentAssistTip.description=Content Tip + +DefineFoldingRegion.label=Define Folding Region +DefineFoldingRegion.tooltip=Define Folding Region +DefineFoldingRegion.image= +DefineFoldingRegion.description=Define Folding Region + +TogglePresentation.label=Change Presentation +TogglePresentation.tooltip=Enable/Disable Segmented Source Viewer +TogglePresentation.image=togglepresentation.gif +TogglePresentation.description=Enable/Disable Segmented Source Viewer + +OutlinePage.segment.title_pattern=position {0} + +AutoIndent.error.bad_location_1=JavaAutoIndentStrategy.getAutoIndentString: BadLocationException +AutoIndent.error.bad_location_2=JavaAutoIndentStrategy.calcShiftBackReplace: BadLocationException + +CompletionProcessor.ContextInfo.display.pattern=proposal {0} at position {1} +CompletionProcessor.ContextInfo.value.pattern=proposal {0} valid from {1} to {2} +CompletionProcessor.Proposal.ContextInfo.pattern={0} valid 5 characters around insertion point +CompletionProcessor.Proposal.hoverinfo.pattern=Java keyword: {0} + +JavaTextHover.emptySelection=empty selection diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorPlugin.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorPlugin.java new file mode 100644 index 000000000..45fa8dc55 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingEditorPlugin.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.net.URL; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.processing.editor.javadoc.JavaDocScanner; +import org.processing.editor.language.ProcessingCodeScanner; +import org.processing.editor.util.ProcessingColorProvider; + +/** + * Processing editor plug-in class. + * Uses a singleton pattern to controls access to a few objects that need to be shared + * across the plugin. Access these options with ProcessingEditorPlugin.getDefault().method() + * @since 3.0 + */ +public class ProcessingEditorPlugin extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "org.processing.ProcessingEditor"; + //public static final String JAVA_PARTITIONING= "__java_example_partitioning"; //$NON-NLS-1$ + public static final String PROCESSING_PARTITIONING= "__processing_partitioning"; //$NON-NLS-1$ + + // The shared instance + private static ProcessingEditorPlugin fgInstance; + + // Supporting objects that are managed by the singleton + private ProcessingPartitionScanner fPartitionScanner; + private ProcessingColorProvider fColorProvider; + private ProcessingCodeScanner fCodeScanner; + private JavaDocScanner fDocScanner; + + /** + * Creates a new plug-in instance. + */ + public ProcessingEditorPlugin() { + //any init code should go in start() + } + + /** + * Called when the plugin is loaded. + * + * All initialization stuff goes here. Make sure to de-initialize it in stop() + * Also, try to keep these methods lean. If it takes too long the platform will + * cancel loading the plug-in. + */ + public void start(BundleContext context) throws Exception { + super.start(context); + fgInstance = this; + } + + /** + * Called when the plugin is unloaded. + * + * Make sure to remove anything here that was initialized to prevent memory + * leaks. Keep this lean, or the platform will cancel the operation. + */ + public void stop(BundleContext context) throws Exception { + fgInstance = null; + super.stop(context); + } + + + /** + * Returns the default plug-in instance. + * + * @return the default plug-in instance + */ + public static ProcessingEditorPlugin getDefault() { return fgInstance; } + + /** + * Return a scanner for creating Processing partitions. + * Processing uses Java's commenting scheme, so our partitioner is almost identical. Unlike + * the Java partitioner, however, this Processing one currently treats the JavaDoc style + * comments as simple multiline comments. + * + * @return a scanner for creating Processing partitions + */ + public ProcessingPartitionScanner getProcessingPartitionScanner() { + if (fPartitionScanner == null) + fPartitionScanner= new ProcessingPartitionScanner(); + return fPartitionScanner; + } + + /** + * Returns the singleton Processing code scanner. + * + * @return the singleton Processing code scanner + */ + public RuleBasedScanner getProcessingCodeScanner() { + if (fCodeScanner == null) + fCodeScanner= new ProcessingCodeScanner(getProcessingColorProvider()); + return fCodeScanner; + } + + /** + * Returns the singleton Processing color provider. + * + * @return the singleton Processing color provider + */ + public ProcessingColorProvider getProcessingColorProvider() { + if (fColorProvider == null) + fColorProvider= new ProcessingColorProvider(); + return fColorProvider; + } + + /** + * Returns the singleton Processingdoc scanner. + * + * @return the singleton Processingdoc scanner + */ + public RuleBasedScanner getProcessingDocScanner() { + if (fDocScanner == null) + fDocScanner= new JavaDocScanner(fColorProvider); + return fDocScanner; + } + + /** + * Returns a buffered input stream for a file in the plug-in directory. + * + * @param filename the file to be loaded + * @return BufferedInputStream to read the file with + */ + public BufferedInputStream getFileInputStream(String filename) { + Bundle bundle = getDefault().getBundle(); + URL fileLocation; + try { + fileLocation = FileLocator.toFileURL(bundle.getEntry(filename)); + BufferedInputStream file = new BufferedInputStream(fileLocation.openStream()); + return file; + } catch (IOException e) { + e.printStackTrace(); + } + return null; // this should be more explicit than a null pointer from a caught exception, right? [lonnen] June 15, 2010 + } + + +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingLog.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingLog.java new file mode 100644 index 000000000..315ed625a --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingLog.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +// This is actually all original code, but it is part of an EPL project, so maybe I still need this? +// If I wanted to worry about licensing I would have applied to law school. Back to code. [lonnen] June 18 2010 +package org.processing.editor; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Container class for all the methods related to logging exceptions and other such + * information that is useful to have written to a log file somewhere. + * + * @author lonnen + */ +public class ProcessingLog { + + // Who needs a constructor? + + /** + * Convenience method for appending a string to the log file. + * Don't use this if there is an error. + * + * @param message something to append to the log file + */ + public static void logInfo(String message){ + log(IStatus.INFO, IStatus.OK, message, null); + } + + /** + * Convenience method for appending an unexpected exception to the log file + * + * @param exception some problem + */ + public static void logError(Throwable exception){ + logError("Unexpected Exception", exception); + } + + /** + * Convenience method for appending an exception with a message + * + * @param message a message, preferably something about the problem + * @param exception the problem + */ + public static void logError(String message, Throwable exception){ + log(IStatus.ERROR, IStatus.OK, message, exception); + } + + /** + * Adapter method that creates the appropriate status to be logged + * + * @param severity integer code indicating the type of message + * @param code plug-in-specific status code + * @param message a human readable message + */ + public static void log(int severity, int code, String message, Throwable exception){ + log(createStatus(severity, code, message, exception)); + } + + /** + * Creates a status object to log + * + * @param severity integer code indicating the type of message + * @param code plug-in-specific status code + * @param message a human readable message + * @param a low-level exception, or null + * @return status object + */ + public static IStatus createStatus(int severity, int code, String message, Throwable exception){ + return new Status(severity, ProcessingEditorPlugin.PLUGIN_ID, code, message, exception); + } + + /** + * Write a status to the log + * + * @param status + */ + public static void log(IStatus status){ + ProcessingEditorPlugin.getDefault().getLog().log(status); + } + +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingPartitionScanner.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingPartitionScanner.java new file mode 100644 index 000000000..27eea7283 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingPartitionScanner.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; + +/** + * Processing uses Java comments, so we use the same scanner. The class name is + * changed for consistency. + * + * This scanner recognizes the JavaDoc comments and Java multi line comments. + */ +public class ProcessingPartitionScanner extends RuleBasedPartitionScanner { + + public final static String JAVA_MULTILINE_COMMENT= "__java_multiline_comment"; //$NON-NLS-1$ + //Removing JavaDoc support from sketches, but leave in code +// public final static String JAVA_DOC= "__java_javadoc"; //$NON-NLS-1$ +// public final static String[] JAVA_PARTITION_TYPES= new String[] { JAVA_MULTILINE_COMMENT, JAVA_DOC }; + public final static String[] JAVA_PARTITION_TYPES= new String[] { JAVA_MULTILINE_COMMENT }; + + /** + * Detector for empty comments. + */ + static class EmptyCommentDetector implements IWordDetector { + + /* (non-Javadoc) + * Method declared on IWordDetector + */ + public boolean isWordStart(char c) { + return (c == '/'); + } + + /* (non-Javadoc) + * Method declared on IWordDetector + */ + public boolean isWordPart(char c) { + return (c == '*' || c == '/'); + } + } + + /** + * + */ + static class WordPredicateRule extends WordRule implements IPredicateRule { + + private IToken fSuccessToken; + + public WordPredicateRule(IToken successToken) { + super(new EmptyCommentDetector()); + fSuccessToken= successToken; + addWord("/**/", fSuccessToken); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.jface.text.rules.IPredicateRule#evaluate(ICharacterScanner, boolean) + */ + public IToken evaluate(ICharacterScanner scanner, boolean resume) { + return super.evaluate(scanner); + } + + /* + * @see org.eclipse.jface.text.rules.IPredicateRule#getSuccessToken() + */ + public IToken getSuccessToken() { + return fSuccessToken; + } + } + + /** + * Creates the partitioner and sets up the appropriate rules. + */ + public ProcessingPartitionScanner() { + super(); + //Removing JavaDoc support from sketches, but leave in code +// IToken javaDoc= new Token(JAVA_DOC); + IToken comment= new Token(JAVA_MULTILINE_COMMENT); + + List rules= new ArrayList(); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", Token.UNDEFINED)); //$NON-NLS-1$ + + // Add rule for strings and character constants. + rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add special case word rule. + rules.add(new WordPredicateRule(comment)); + + // Add rules for multi-line comments and javadoc. + //Removing JavaDoc support from sketches, but leave in code +// rules.add(new MultiLineRule("/**", "*/", javaDoc, (char) 0, true)); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(new MultiLineRule("/*", "*/", comment, (char) 0, true)); //$NON-NLS-1$ //$NON-NLS-2$ + + IPredicateRule[] result= new IPredicateRule[rules.size()]; + rules.toArray(result); + setPredicateRules(result); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingSourceViewerConfiguration.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingSourceViewerConfiguration.java new file mode 100644 index 000000000..aff27dbf7 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingSourceViewerConfiguration.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + +import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.BufferedRuleBasedScanner; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.graphics.RGB; +import org.processing.editor.language.ProcessingAutoIndentStrategy; +import org.processing.editor.language.ProcessingCompletionProcessor; +import org.processing.editor.language.ProcessingDoubleClickSelector; +import org.processing.editor.util.ProcessingColorProvider; + +/** + * Configuration for the ProcessingSourceViewer. + */ +public class ProcessingSourceViewerConfiguration extends SourceViewerConfiguration { + + /** + * Single token scanner. + */ + static class SingleTokenScanner extends BufferedRuleBasedScanner { + public SingleTokenScanner(TextAttribute attribute) { + setDefaultReturnToken(new Token(attribute)); + } + } + + /** + * Default constructor. + */ + public ProcessingSourceViewerConfiguration() { + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new ProcessingAnnotationHover(); + } + + /* + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getAutoEditStrategies(org.eclipse.jface.text.source.ISourceViewer, java.lang.String) + */ + public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) { + IAutoEditStrategy strategy= (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType) ? new ProcessingAutoIndentStrategy() : new DefaultIndentLineAutoEditStrategy()); + return new IAutoEditStrategy[] { strategy }; + } + + /* + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getConfiguredDocumentPartitioning(org.eclipse.jface.text.source.ISourceViewer) + */ + public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) { + return ProcessingEditorPlugin.PROCESSING_PARTITIONING; + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + //Removing JavaDoc support from sketches, but leave in code + //return new String[] { IDocument.DEFAULT_CONTENT_TYPE, ProcessingPartitionScanner.JAVA_DOC, ProcessingPartitionScanner.JAVA_MULTILINE_COMMENT }; + return new String[] { IDocument.DEFAULT_CONTENT_TYPE, ProcessingPartitionScanner.JAVA_MULTILINE_COMMENT }; + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + + ContentAssistant assistant= new ContentAssistant(); + assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); + assistant.setContentAssistProcessor(new ProcessingCompletionProcessor(), IDocument.DEFAULT_CONTENT_TYPE); + // Disabling JavaDoc support [lonnen] june 12 2010 + //assistant.setContentAssistProcessor(new JavaDocCompletionProcessor(), ProcessingPartitionScanner.JAVA_DOC); + + assistant.enableAutoActivation(true); + assistant.setAutoActivationDelay(500); + assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); + assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); + assistant.setContextInformationPopupBackground(ProcessingEditorPlugin.getDefault().getProcessingColorProvider().getColor(new RGB(150, 150, 0))); + + return assistant; + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public String getDefaultPrefix(ISourceViewer sourceViewer, String contentType) { + return (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType) ? "//" : null); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) { + return new ProcessingDoubleClickSelector(); + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) { + return new String[] { "\t", " " }; //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + + ProcessingColorProvider provider= ProcessingEditorPlugin.getDefault().getProcessingColorProvider(); + + PresentationReconciler reconciler= new PresentationReconciler(); + reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); + + DefaultDamagerRepairer dr= new DefaultDamagerRepairer(ProcessingEditorPlugin.getDefault().getProcessingCodeScanner()); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + + //Removing JavaDoc support from sketches, but leave in code +// dr= new DefaultDamagerRepairer(ProcessingEditorPlugin.getDefault().getProcessingDocScanner()); +// reconciler.setDamager(dr, ProcessingPartitionScanner.JAVA_DOC); +// reconciler.setRepairer(dr, ProcessingPartitionScanner.JAVA_DOC); + + dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(ProcessingColorProvider.COMMENT1)))); + reconciler.setDamager(dr, ProcessingPartitionScanner.JAVA_MULTILINE_COMMENT); + reconciler.setRepairer(dr, ProcessingPartitionScanner.JAVA_MULTILINE_COMMENT); + + return reconciler; + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public int getTabWidth(ISourceViewer sourceViewer) { + return 4; + } + + /* (non-Javadoc) + * Method declared on SourceViewerConfiguration + */ + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + return new ProcessingTextHover(); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/ProcessingTextHover.java b/editor/org.processing.editor/src/org/processing/editor/ProcessingTextHover.java new file mode 100644 index 000000000..8cecda67b --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/ProcessingTextHover.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.swt.graphics.Point; + +/** + * Example implementation for an ITextHover which hovers over Java code. + */ +public class ProcessingTextHover implements ITextHover { + + /* (non-Javadoc) + * Method declared on ITextHover + */ + public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { + if (hoverRegion != null) { + try { + if (hoverRegion.getLength() > -1) + //TODO Implement a hover that returns something useful + return textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength()); + } catch (BadLocationException x) { + } + } + return ProcessingEditorMessages.getString("ProcessingTextHover.emptySelection"); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * Method declared on ITextHover + */ + public IRegion getHoverRegion(ITextViewer textViewer, int offset) { + Point selection= textViewer.getSelectedRange(); + if (selection.x <= offset && offset < selection.x + selection.y) + return new Region(selection.x, selection.y); + return new Region(offset, 0); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocCompletionProcessor.java b/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocCompletionProcessor.java new file mode 100644 index 000000000..32aad9f20 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocCompletionProcessor.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.javadoc; + + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.CompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +/** + * Example Java doc completion processor. Should work for Processing unmodified. Do we even use Javadoc? + */ +public class JavaDocCompletionProcessor implements IContentAssistProcessor { + + protected final static String[] fgProposals= { "@author", "@deprecated", "@exception", "@param", "@return", "@see", "@serial", "@serialData", "@serialField", "@since", "@throws", "@version" }; //$NON-NLS-12$ //$NON-NLS-11$ //$NON-NLS-10$ //$NON-NLS-7$ //$NON-NLS-9$ //$NON-NLS-8$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { + ICompletionProposal[] result= new ICompletionProposal[fgProposals.length]; + for (int i= 0; i < fgProposals.length; i++) + result[i]= new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length()); + return result; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { + return null; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return null; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public IContextInformationValidator getContextInformationValidator() { + return null; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public String getErrorMessage() { + return null; + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocScanner.java b/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocScanner.java new file mode 100644 index 000000000..765c9327d --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/javadoc/JavaDocScanner.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.javadoc; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; +import org.processing.editor.util.ProcessingColorProvider; +import org.processing.editor.util.ProcessingWhitespaceDetector; + + +/** + * A rule based JavaDoc scanner. + */ +public class JavaDocScanner extends RuleBasedScanner { + + /** + * A key word detector. + */ + static class JavaDocWordDetector implements IWordDetector { + + /* (non-Javadoc) + * Method declared on IWordDetector + */ + public boolean isWordStart(char c) { + return (c == '@'); + } + + /* (non-Javadoc) + * Method declared on IWordDetector + */ + public boolean isWordPart(char c) { + return Character.isLetter(c); + } + } + + private static String[] fgKeywords= { "@author", "@deprecated", "@exception", "@param", "@return", "@see", "@serial", "@serialData", "@serialField", "@since", "@throws", "@version" }; //$NON-NLS-12$ //$NON-NLS-11$ //$NON-NLS-10$ //$NON-NLS-7$ //$NON-NLS-9$ //$NON-NLS-8$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ + + /** + * Create a new javadoc scanner for the given color provider. + * + * @param provider the color provider + */ + public JavaDocScanner(ProcessingColorProvider provider) { + super(); + + IToken keyword= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.JAVADOC_KEYWORD))); + IToken tag= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.JAVADOC_TAG))); + IToken link= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.JAVADOC_LINK))); + + List list= new ArrayList(); + + // Add rule for tags. + list.add(new SingleLineRule("<", ">", tag)); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add rule for links. + list.add(new SingleLineRule("{", "}", link)); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add generic whitespace rule. + list.add(new WhitespaceRule(new ProcessingWhitespaceDetector())); + + // Add word rule for keywords. + WordRule wordRule= new WordRule(new JavaDocWordDetector()); + for (int i= 0; i < fgKeywords.length; i++) + wordRule.addWord(fgKeywords[i], keyword); + list.add(wordRule); + + IRule[] result= new IRule[list.size()]; + list.toArray(result); + setRules(result); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/language/ProcessingAutoIndentStrategy.java b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingAutoIndentStrategy.java new file mode 100644 index 000000000..449cef152 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingAutoIndentStrategy.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.language; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextUtilities; + +/** + * Auto indent line strategy sensitive to brackets. Should work for Processing unmodified. + */ +public class ProcessingAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { + + public ProcessingAutoIndentStrategy() { + } + + /* (non-Javadoc) + * Method declared on IAutoIndentStrategy + */ + public void customizeDocumentCommand(IDocument d, DocumentCommand c) { + if (c.length == 0 && c.text != null && endsWithDelimiter(d, c.text)) + smartIndentAfterNewLine(d, c); + else if ("}".equals(c.text)) { //$NON-NLS-1$ + smartInsertAfterBracket(d, c); + } + } + + /** + * Returns whether or not the given text ends with one of the documents legal line delimiters. + * + * @param d the document + * @param txt the text + * @return true if txt ends with one of the document's line delimiters, false otherwise + */ + private boolean endsWithDelimiter(IDocument d, String txt) { + String[] delimiters= d.getLegalLineDelimiters(); + if (delimiters != null) + return TextUtilities.endsWith(delimiters, txt) > -1; + return false; + } + + /** + * Returns the line number of the next bracket after end. + * + * @param document - the document being parsed + * @param line - the line to start searching back from + * @param end - the end position to search back from + * @param closingBracketIncrease - the number of brackets to skip + * @return the line number of the next matching bracket after end + * @throws BadLocationException in case the line numbers are invalid in the document + */ + protected int findMatchingOpenBracket(IDocument document, int line, int end, int closingBracketIncrease) throws BadLocationException { + + int start= document.getLineOffset(line); + int brackcount= getBracketCount(document, start, end, false) - closingBracketIncrease; + + // sum up the brackets counts of each line (closing brackets count negative, + // opening positive) until we find a line the brings the count to zero + while (brackcount < 0) { + line--; + if (line < 0) { + return -1; + } + start= document.getLineOffset(line); + end= start + document.getLineLength(line) - 1; + brackcount += getBracketCount(document, start, end, false); + } + return line; + } + + /** + * Returns the bracket value of a section of text. Closing brackets have a value of -1 and + * open brackets have a value of 1. + * + * @param document - the document being parsed + * @param start - the start position for the search + * @param end - the end position for the search + * @param ignoreCloseBrackets - whether or not to ignore closing brackets in the count + * @return the bracket value of a section of text + * @throws BadLocationException in case the positions are invalid in the document + */ + private int getBracketCount(IDocument document, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException { + + int begin = start; + int bracketcount= 0; + while (begin < end) { + char curr= document.getChar(begin); + begin++; + switch (curr) { + case '/' : + if (begin < end) { + char next= document.getChar(begin); + if (next == '*') { + // a comment starts, advance to the comment end + begin= getCommentEnd(document, begin + 1, end); + } else if (next == '/') { + // '//'-comment: nothing to do anymore on this line + begin= end; + } + } + break; + case '*' : + if (begin < end) { + char next= document.getChar(begin); + if (next == '/') { + // we have been in a comment: forget what we read before + bracketcount= 0; + begin++; + } + } + break; + case '{' : + bracketcount++; + ignoreCloseBrackets= false; + break; + case '}' : + if (!ignoreCloseBrackets) { + bracketcount--; + } + break; + case '"' : + case '\'' : + begin= getStringEnd(document, begin, end, curr); + break; + default : + } + } + return bracketcount; + } + + /** + * Returns the end position of a comment starting at the given position. + * + * @param document - the document being parsed + * @param position - the start position for the search + * @param end - the end position for the search + * @return the end position of a comment starting at the given position + * @throws BadLocationException in case position and end are invalid in the document + */ + private int getCommentEnd(IDocument document, int position, int end) throws BadLocationException { + int currentPosition = position; + while (currentPosition < end) { + char curr= document.getChar(currentPosition); + currentPosition++; + if (curr == '*') { + if (currentPosition < end && document.getChar(currentPosition) == '/') { + return currentPosition + 1; + } + } + } + return end; + } + + /** + * Returns the content of the given line without the leading whitespace. + * + * @param document - the document being parsed + * @param line - the line being searched + * @return the content of the given line without the leading whitespace + * @throws BadLocationException in case line is invalid in the document + */ + protected String getIndentOfLine(IDocument document, int line) throws BadLocationException { + if (line > -1) { + int start= document.getLineOffset(line); + int end= start + document.getLineLength(line) - 1; + int whiteend= findEndOfWhiteSpace(document, start, end); + return document.get(start, whiteend - start); + } + return ""; //$NON-NLS-1$ + } + + /** + * Returns the position of the character in the document after position. + * + * @param document - the document being parsed + * @param position - the position to start searching from + * @param end - the end of the document + * @param character - the character you are trying to match + * @return the next location of character + * @throws BadLocationException in case position is invalid in the document + */ + private int getStringEnd(IDocument document, int position, int end, char character) throws BadLocationException { + int currentPosition = position; + while (currentPosition < end) { + char currentCharacter= document.getChar(currentPosition); + currentPosition++; + if (currentCharacter == '\\') { + // ignore escaped characters + currentPosition++; + } else if (currentCharacter == character) { + return currentPosition; + } + } + return end; + } + + /** + * Set the indent of a new line based on the command provided in the supplied document. + * @param document - the document being parsed + * @param command - the command being performed + */ + protected void smartIndentAfterNewLine(IDocument document, DocumentCommand command) { + + int docLength= document.getLength(); + if (command.offset == -1 || docLength == 0) + return; + + try { + int p= (command.offset == docLength ? command.offset - 1 : command.offset); + int line= document.getLineOfOffset(p); + + StringBuffer buf= new StringBuffer(command.text); + if (command.offset < docLength && document.getChar(command.offset) == '}') { + int indLine= findMatchingOpenBracket(document, line, command.offset, 0); + if (indLine == -1) { + indLine= line; + } + buf.append(getIndentOfLine(document, indLine)); + } else { + int start= document.getLineOffset(line); + int whiteend= findEndOfWhiteSpace(document, start, command.offset); + buf.append(document.get(start, whiteend - start)); + if (getBracketCount(document, start, command.offset, true) > 0) { + buf.append('\t'); + } + } + command.text= buf.toString(); + + } catch (BadLocationException excp) { + System.out.println(ProcessingEditorMessages.getString("AutoIndent.error.bad_location_1")); //$NON-NLS-1$ + } + } + + /** + * Set the indent of a bracket based on the command provided in the supplied document. + * @param document - the document being parsed + * @param command - the command being performed + */ + protected void smartInsertAfterBracket(IDocument document, DocumentCommand command) { + if (command.offset == -1 || document.getLength() == 0) + return; + + try { + int p= (command.offset == document.getLength() ? command.offset - 1 : command.offset); + int line= document.getLineOfOffset(p); + int start= document.getLineOffset(line); + int whiteend= findEndOfWhiteSpace(document, start, command.offset); + + // shift only when line does not contain any text up to the closing bracket + if (whiteend == command.offset) { + // evaluate the line with the opening bracket that matches out closing bracket + int indLine= findMatchingOpenBracket(document, line, command.offset, 1); + if (indLine != -1 && indLine != line) { + // take the indent of the found line + StringBuffer replaceText= new StringBuffer(getIndentOfLine(document, indLine)); + // add the rest of the current line including the just added close bracket + replaceText.append(document.get(whiteend, command.offset - whiteend)); + replaceText.append(command.text); + // modify document command + command.length= command.offset - start; + command.offset= start; + command.text= replaceText.toString(); + } + } + } catch (BadLocationException excp) { + System.out.println(ProcessingEditorMessages.getString("AutoIndent.error.bad_location_2")); //$NON-NLS-1$ + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCodeScanner.java b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCodeScanner.java new file mode 100644 index 000000000..8e7ca492e --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCodeScanner.java @@ -0,0 +1,192 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.language; + + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; +import org.processing.editor.ProcessingEditorPlugin; +import org.processing.editor.util.ProcessingColorProvider; +import org.processing.editor.util.ProcessingWhitespaceDetector; +import org.processing.editor.util.ProcessingWordDetector; + +/** + * A Processing code scanner. + */ +public class ProcessingCodeScanner extends RuleBasedScanner { + + private static String keywordsFile = "keywords.txt"; // name of the syntax highlighting file + + private static String[] fgKeywords1; // keywords (new, return, super) + private static String[] fgKeywords2; // PDE methods (setup, random, size) + private static String[] fgKeywords3; // primitive types (int, color, float) + private static String[] fgLiterals1; // static tokens (null, true, P2D) + private static String[] fgLiterals2; // environmental variables (mouseX, width, pixels) + private static String[] fgLabels; // possibly unused? Supporting them here because Processing does. + private static String[] fgOperators; // mathematical operators (+, -, *) + private static String[] fgInvalids; // possibly unused? Supporting them here because Processing does. + + /* + * Static initialization block to load Processing Keywords in from keywords.txt + * This is similar to the way the Processing Developer Environment loads keywords + * for syntax highlighting. + * + * Reads in the keyword file and splits each line at the tabs. The first string + * is the symbol, the second is the category (empty strings indicate operators) + * and the third string is ignored. In Processing it is used to lookup reference + * HTML. + * + * A HashMap stores each category as a key corresponding to a HashSet value that + * holds the tokens belonging to each category. After the keywordsFile is + * processed, the HashMap sets are converted to string arrays and loaded into the + * static keyword lists the document expects. At the moment each set of keywords + * we create rules for are explicitly listed. If the keywords categories change in + * the future, there will need to new categories introduced in the code scanner + * and ProcessingColorProvider. + * + * Unexpected categories in the keywords file will be silently ignored. + * 'Unsure of how to JavaDoc an init block so I did this' - [lonnen] june 16, 2010 + */ + static { + HashMap KeywordMap = new HashMap(); + //Read in the values + try{ + InputStream is = ProcessingEditorPlugin.getDefault().getFileInputStream(keywordsFile); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader reader = new BufferedReader(isr); + + String line = null; + while ((line = reader.readLine()) != null){ + String pieces[] = line.split("\t"); // split the string at \t + if (pieces.length >= 2) { + String token = pieces[0].trim(); // ex. PVector + String coloring = pieces[1].trim(); // ex. KEWORD1 + //String reference = pieces[2].trim(); // used for reference in PDE, unused here + if (coloring.isEmpty()) // catches operators + coloring = "OPERATOR"; + if (KeywordMap.containsKey(coloring)){ + KeywordMap.get(coloring).add(token); + } else { + Set tokenSet = new HashSet(); + tokenSet.add(token); + KeywordMap.put(coloring, tokenSet); + } + //System.out.println(coloring + " " + token); // to print out a list of what is added + } + } + } + catch (Exception e){ + e.printStackTrace(); + } + + try{ + fgKeywords1= KeywordMap.containsKey("KEYWORD1") ? (String[]) KeywordMap.get("KEYWORD1").toArray(new String[KeywordMap.get("KEYWORD1").size()]) : new String[] {"test"}; + fgKeywords2= KeywordMap.containsKey("KEYWORD2") ? (String[]) KeywordMap.get("KEYWORD2").toArray(new String[KeywordMap.get("KEYWORD2").size()]) : new String[] {}; + fgKeywords3= KeywordMap.containsKey("KEYWORD3") ? (String[]) KeywordMap.get("KEYWORD3").toArray(new String[KeywordMap.get("KEYWORD3").size()]) : new String[] {}; + fgLiterals1= KeywordMap.containsKey("LITERAL1") ? (String[]) KeywordMap.get("LITERAL1").toArray(new String[KeywordMap.get("LITERAL1").size()]) : new String[] {}; + fgLiterals2= KeywordMap.containsKey("LITERAL2") ? (String[]) KeywordMap.get("LITERAL2").toArray(new String[KeywordMap.get("LITERAL2").size()]) : new String[] {}; + fgLabels = KeywordMap.containsKey("LABELS") ? (String[]) KeywordMap.get("LABELS").toArray(new String[KeywordMap.get("LABELS").size()]) : new String[] {}; //unused? + fgOperators = KeywordMap.containsKey("OPERATOR") ? (String[]) KeywordMap.get("OPERATOR").toArray(new String[KeywordMap.get("OPERATOR").size()]) : new String[] {}; + fgInvalids = KeywordMap.containsKey("INVALIDS") ? (String[]) KeywordMap.get("INVALIDS").toArray(new String[KeywordMap.get("INVALIDS").size()]) : new String[] {}; // unused? + } + catch (Exception e){ + e.printStackTrace(); + } + } + + /** + * Creates a Processing code scanner with the given color provider. + * + * @param provider the color provider + */ + public ProcessingCodeScanner(ProcessingColorProvider provider) { + + IToken keyword1= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.KEYWORD1))); + IToken keyword2= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.KEYWORD2))); + IToken keyword3= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.KEYWORD3))); + IToken literal1= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.LITERAL1))); + IToken literal2= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.LITERAL2))); + IToken label= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.LABEL))); + IToken operator= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.OPERATOR))); + IToken invalid= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.INVALID))); + // leave the rest for now + IToken string= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.STRING))); + IToken comment= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.COMMENT2))); + IToken other= new Token(new TextAttribute(provider.getColor(ProcessingColorProvider.DEFAULT))); + + List rules= new ArrayList(); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", comment)); //$NON-NLS-1$ + + // Add rule for strings and character constants. + rules.add(new SingleLineRule("\"", "\"", string, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + rules.add(new SingleLineRule("'", "'", string, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add generic whitespace rule. + rules.add(new WhitespaceRule(new ProcessingWhitespaceDetector())); + + // Add a rule for each keyword explaining how to color it + WordRule wordRule= new WordRule(new ProcessingWordDetector(), other); + for (int i= 0; i < fgKeywords1.length; i++) + wordRule.addWord(fgKeywords1[i], keyword1); + for (int i= 0; i < fgKeywords2.length; i++) + wordRule.addWord(fgKeywords2[i], keyword2); + for (int i= 0; i < fgKeywords3.length; i++) + wordRule.addWord(fgKeywords3[i], keyword3); + for (int i= 0; i < fgLiterals1.length; i++) + wordRule.addWord(fgLiterals1[i], literal1); + for (int i= 0; i < fgLiterals2.length; i++) + wordRule.addWord(fgLiterals2[i], literal2); + for (int i= 0; i < fgLabels.length; i++) + wordRule.addWord(fgLabels[i], label); + for (int i= 0; i < fgOperators.length; i++) + wordRule.addWord(fgOperators[i], operator); + for (int i= 0; i < fgInvalids.length; i++) + wordRule.addWord(fgInvalids[i], invalid); + // Set these as the colorizing rules for the document + rules.add(wordRule); + + IRule[] result= new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } + + /** + * Concatenates the keyword arrays into one array and returns it. + * + * @return A string array of all the keywords + */ + public final static String[] getKeywords(){ + String[] result = new String[fgKeywords1.length + fgKeywords2.length + fgKeywords3.length]; + System.arraycopy(fgKeywords1, 0, result, 0, fgKeywords1.length); + System.arraycopy(fgKeywords2, 0, result, fgKeywords1.length, fgKeywords2.length); + System.arraycopy(fgKeywords3, 0, result, fgKeywords1.length+fgKeywords2.length, fgKeywords3.length); + return result; + } + +} diff --git a/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCompletionProcessor.java b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCompletionProcessor.java new file mode 100644 index 000000000..0b5ca8cb7 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingCompletionProcessor.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.language; + + +import java.text.MessageFormat; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.contentassist.CompletionProposal; +import org.eclipse.jface.text.contentassist.ContextInformation; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationPresenter; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +/** + * Example Java completion processor. Should work unmodified for Processing. + */ +public class ProcessingCompletionProcessor implements IContentAssistProcessor { + + /** + * Simple content assist tip closer. The tip is valid in a range + * of 5 characters around its popup location. + */ + protected static class Validator implements IContextInformationValidator, IContextInformationPresenter { + + protected int fInstallOffset; + + /* + * @see IContextInformationValidator#isContextInformationValid(int) + */ + public boolean isContextInformationValid(int offset) { + return Math.abs(fInstallOffset - offset) < 5; + } + + /* + * @see IContextInformationValidator#install(IContextInformation, ITextViewer, int) + */ + public void install(IContextInformation info, ITextViewer viewer, int offset) { + fInstallOffset= offset; + } + + /* + * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, TextPresentation) + */ + public boolean updatePresentation(int documentPosition, TextPresentation presentation) { + return false; + } + } + + /* + * The list of proposals that populates the content assistance dialog box. + * + * Dialog assistance is not context sensitive right now, so it will always provide the same suggestions + * anytime is provides suggestions. I find it more annoying than useful, so until it is done right I'm + * turning off the pop up box by leaving this empty. + * + * Auto-completion by hotkey will still work, but it will pick the closest keyword or variable that is + * already present in the sketch. This is actually useful, so I'm leaving that intact for now. + * + * [lonnen] June 17, 2010 + * + * @see http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/jface.htm + */ + protected final static String[] fgProposals= //ProcessingCodeScanner.getKeywords(); // naive solution? + //generated automatically for Java. Not useful, ignoring them for now. +// { "abstract", "boolean", "break", "byte", "case", "catch", "char", "class", "continue", +// "default", "do", "double", "else", "extends", "false", "final", "finally", "float", "for", +// "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", +// "null", "package", "private", "protected", "public", "return", "short", "static", "super", +// "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", +// "volatile", "while" }; + {}; // turns off the content assist dialog box + + protected IContextInformationValidator fValidator= new Validator(); + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { + ICompletionProposal[] result= new ICompletionProposal[fgProposals.length]; + for (int i= 0; i < fgProposals.length; i++) { + IContextInformation info= new ContextInformation(fgProposals[i], MessageFormat.format(ProcessingEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ + result[i]= new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(ProcessingEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i]})); //$NON-NLS-1$ + } + return result; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { + IContextInformation[] result= new IContextInformation[5]; + for (int i= 0; i < result.length; i++) + result[i]= new ContextInformation( + MessageFormat.format(ProcessingEditorMessages.getString("CompletionProcessor.ContextInfo.display.pattern"), new Object[] { new Integer(i), new Integer(documentOffset) }), //$NON-NLS-1$ + MessageFormat.format(ProcessingEditorMessages.getString("CompletionProcessor.ContextInfo.value.pattern"), new Object[] { new Integer(i), new Integer(documentOffset - 5), new Integer(documentOffset + 5)})); //$NON-NLS-1$ + return result; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return new char[] { '.', '(' }; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public char[] getContextInformationAutoActivationCharacters() { + return new char[] { '#' }; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public IContextInformationValidator getContextInformationValidator() { + return fValidator; + } + + /* (non-Javadoc) + * Method declared on IContentAssistProcessor + */ + public String getErrorMessage() { + return null; + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/language/ProcessingDoubleClickSelector.java b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingDoubleClickSelector.java new file mode 100644 index 000000000..653a7dee4 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingDoubleClickSelector.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.language; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextViewer; + +/** + * Double click strategy aware of Java identifier syntax rules. These should work + * for Processing without modification. + */ +public class ProcessingDoubleClickSelector implements ITextDoubleClickStrategy { + + protected ITextViewer fText; + protected int fPos; + protected int fStartPos; + protected int fEndPos; + + protected static char[] fgBrackets= { '{', '}', '(', ')', '[', ']', '"', '"' }; + + /* + * Create a JavaDoubleClickSelector. + */ + public ProcessingDoubleClickSelector() { + super(); + } + + /* (non-Javadoc) + * Method declared on ITextDoubleClickStrategy + */ + public void doubleClicked(ITextViewer text) { + + fPos= text.getSelectedRange().x; + + if (fPos < 0) + return; + + fText= text; + + if (!selectBracketBlock()) + selectWord(); + } + + /** + * Match the brackets at the current selection. Return true if successful, + * false otherwise. + * + * @return true if brackets match, false otherwise + */ + protected boolean matchBracketsAt() { + + char prevChar, nextChar; + + int i; + int bracketIndex1= fgBrackets.length; + int bracketIndex2= fgBrackets.length; + + fStartPos= -1; + fEndPos= -1; + + // get the chars preceding and following the start position + try { + + IDocument doc= fText.getDocument(); + + prevChar= doc.getChar(fPos - 1); + nextChar= doc.getChar(fPos); + + // is the char either an open or close bracket? + for (i= 0; i < fgBrackets.length; i= i + 2) { + if (prevChar == fgBrackets[i]) { + fStartPos= fPos - 1; + bracketIndex1= i; + } + } + for (i= 1; i < fgBrackets.length; i= i + 2) { + if (nextChar == fgBrackets[i]) { + fEndPos= fPos; + bracketIndex2= i; + } + } + + if (fStartPos > -1 && bracketIndex1 < bracketIndex2) { + fEndPos= searchForClosingBracket(fStartPos, prevChar, fgBrackets[bracketIndex1 + 1], doc); + if (fEndPos > -1) + return true; + fStartPos= -1; + } else if (fEndPos > -1) { + fStartPos= searchForOpenBracket(fEndPos, fgBrackets[bracketIndex2 - 1], nextChar, doc); + if (fStartPos > -1) + return true; + fEndPos= -1; + } + + } catch (BadLocationException x) { + } + + return false; + } + + /** + * Select the word at the current selection location. Return true if successful, + * false otherwise. + * + * @return true if a word can be found at the current selection location, false otherwise + */ + protected boolean matchWord() { + + IDocument doc= fText.getDocument(); + + try { + + int pos= fPos; + char c; + + while (pos >= 0) { + c= doc.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + --pos; + } + + fStartPos= pos; + + pos= fPos; + int length= doc.getLength(); + + while (pos < length) { + c= doc.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + ++pos; + } + + fEndPos= pos; + + return true; + + } catch (BadLocationException x) { + } + + return false; + } + + /** + * Returns the position of the closing bracket after startPosition. + * + * @param startPosition - the beginning position + * @param openBracket - the character that represents the open bracket + * @param closeBracket - the character that represents the close bracket + * @param document - the document being searched + * @return the location of the closing bracket. + * @throws BadLocationException in case startPosition is invalid in the document + */ + protected int searchForClosingBracket(int startPosition, char openBracket, char closeBracket, IDocument document) throws BadLocationException { + int stack= 1; + int closePosition= startPosition + 1; + int length= document.getLength(); + char nextChar; + + while (closePosition < length && stack > 0) { + nextChar= document.getChar(closePosition); + if (nextChar == openBracket && nextChar != closeBracket) + stack++; + else if (nextChar == closeBracket) + stack--; + closePosition++; + } + + if (stack == 0) + return closePosition - 1; + return -1; + + } + + /** + * Returns the position of the open bracket before startPosition. + * + * @param startPosition - the beginning position + * @param openBracket - the character that represents the open bracket + * @param closeBracket - the character that represents the close bracket + * @param document - the document being searched + * @return the location of the starting bracket. + * @throws BadLocationException in case startPosition is invalid in the document + */ + protected int searchForOpenBracket(int startPosition, char openBracket, char closeBracket, IDocument document) throws BadLocationException { + int stack= 1; + int openPos= startPosition - 1; + char nextChar; + + while (openPos >= 0 && stack > 0) { + nextChar= document.getChar(openPos); + if (nextChar == closeBracket && nextChar != openBracket) + stack++; + else if (nextChar == openBracket) + stack--; + openPos--; + } + + if (stack == 0) + return openPos + 1; + return -1; + } + + /** + * Select the area between the selected bracket and the closing bracket. + * + * @return true if selection was successful, false otherwise + */ + protected boolean selectBracketBlock() { + if (matchBracketsAt()) { + + if (fStartPos == fEndPos) + fText.setSelectedRange(fStartPos, 0); + else + fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); + + return true; + } + return false; + } + + /** + * Select the word at the current selection. + */ + protected void selectWord() { + if (matchWord()) { + + if (fStartPos == fEndPos) + fText.setSelectedRange(fStartPos, 0); + else + fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/language/ProcessingEditorMessages.java b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingEditorMessages.java new file mode 100644 index 000000000..79f7f86b4 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/language/ProcessingEditorMessages.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.language; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class ProcessingEditorMessages { + + private static final String RESOURCE_BUNDLE= "org.processing.editor.ProcessingEditorMessages";//$NON-NLS-1$ + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private ProcessingEditorMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/util/ProcessingColorProvider.java b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingColorProvider.java new file mode 100644 index 000000000..4ac3b9b3b --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingColorProvider.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.util; + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +/** + * Manager for colors used in the Java editor + */ +public class ProcessingColorProvider { + + public static final RGB COMMENT1= new RGB(126, 126, 126); //comment 1 + public static final RGB COMMENT2= new RGB(126, 126, 126); //comment 2 + public static final RGB KEYWORD1= new RGB(204, 102, 0); + public static final RGB KEYWORD2= new RGB(204, 102, 0); + public static final RGB KEYWORD3= new RGB(204, 102, 0); + public static final RGB LITERAL1= new RGB(0, 102, 153); // currently unused [lonnen] june 16, 2010 + public static final RGB LITERAL2= new RGB(0, 102, 153); + public static final RGB LABEL= new RGB(0, 0, 128); // use listed as '?' in p5 doc + public static final RGB OPERATOR= new RGB(0, 0, 0); + public static final RGB INVALID= new RGB(126, 126, 126); // never used [lonnen] june 16, 2010 + public static final RGB STRING= new RGB(0, 102, 153); + public static final RGB DEFAULT= new RGB(0, 0, 0); + + // used to color JavaDoc by org.processing.editor.javadoc.JavaDocScanner + // currently ignored, as JavaDoc is treated like normal multiline comments + // left available to avoid compiler errors from the JavaDocScanner.java class + // which is never instantiated but wants access to them anyway because the + // compiler doesn't realize these things. [lonnen] june 16, 2010 + public static final RGB JAVADOC_KEYWORD= new RGB(126, 126, 126); + public static final RGB JAVADOC_TAG= new RGB(126, 126, 126); + public static final RGB JAVADOC_LINK= new RGB(126, 126, 126); + public static final RGB JAVADOC_DEFAULT= new RGB(126, 126, 126); + + protected Map fColorTable= new HashMap(17); + + /** + * Release all of the color resources held onto by the receiver. + */ + public void dispose() { + Iterator e= fColorTable.values().iterator(); + while (e.hasNext()) + ((Color) e.next()).dispose(); + } + + /** + * Return the color that is stored in the color table under the given RGB + * value. + * + * @param rgb the RGB value + * @return the color stored in the color table for the given RGB value + */ + public Color getColor(RGB rgb) { + Color color= (Color) fColorTable.get(rgb); + if (color == null) { + color= new Color(Display.getCurrent(), rgb); + fColorTable.put(rgb, color); + } + return color; + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWhitespaceDetector.java b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWhitespaceDetector.java new file mode 100644 index 000000000..93c328433 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWhitespaceDetector.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.util; + + +import org.eclipse.jface.text.rules.IWhitespaceDetector; + +/** + * A Processing aware white space detector, same as a java aware white space detector. + */ +public class ProcessingWhitespaceDetector implements IWhitespaceDetector { + + /* (non-Javadoc) + * Method declared on IWhitespaceDetector + */ + public boolean isWhitespace(char character) { + return Character.isWhitespace(character); + } +} diff --git a/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWordDetector.java b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWordDetector.java new file mode 100644 index 000000000..3b42dadea --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/editor/util/ProcessingWordDetector.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.processing.editor.util; + + +import org.eclipse.jface.text.rules.IWordDetector; + +/** + * A Processing aware word detector. Same as a java aware word detector. + */ +public class ProcessingWordDetector implements IWordDetector { + + /* (non-Javadoc) + * Method declared on IWordDetector. + */ + public boolean isWordPart(char character) { + return Character.isJavaIdentifierPart(character); + } + + /* (non-Javadoc) + * Method declared on IWordDetector. + */ + public boolean isWordStart(char character) { + return Character.isJavaIdentifierStart(character); + } +} diff --git a/editor/org.processing.editor/src/org/processing/preferences/PreferenceConstants.java b/editor/org.processing.editor/src/org/processing/preferences/PreferenceConstants.java new file mode 100644 index 000000000..be9b58470 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/preferences/PreferenceConstants.java @@ -0,0 +1,28 @@ +package org.processing.preferences; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants { + + // Editor Preferences + public static final String PROCESSING_SKETCHBOOK = "sketch_path"; // path preference + public static final String PROCESSING_LIBRARIES = "library_path"; // path preference + public static final String PROCESSING_AUTO_INDENT = "eclipse.editor.auto.indent"; + +// // PROCESSING_PREFERENCES prefix indicates membership in the processing.app preferences class +// public static final String PROCESSING_APP_PREFERENCES_EDITOR_TABS_SIZE = "editor.tabs.size"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_SUBSTITUTE_FLOATS= "preproc.substitute_floats"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_WEB_COLORS = "preproc.web_colors"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_COLOR_DATATYPE = "preproc.color_datatype"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_ENHANCED_CASTING = "preproc.enhanced_casted"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_SUBSTITUTE_UNICODE = "preproc.substitute.unicode"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_OUTPUT_PARSE_TREE = "preproc.output_parse.tree"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_EXPORT_APPLICATION_FULLSCREEN = "export.application.fullscreen"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_RUN_PRESENT_BGCOLOR = "run.present.bgcolor"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_EXPORT_APPLICATION_STOP = "export.application.stop"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_RUN_PRESENT_STOP_COLOR = "run.present.stop.color"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_RUN_WINDOW_BGCOLOR = "run.window.bgcolor"; +// public static final String PROCESSING_APP_PREFERENCES_PREPROC_PREPROC_IMPORTS_LIST = "preproc.imports.list"; + +} diff --git a/editor/org.processing.editor/src/org/processing/preferences/PreferenceInitializer.java b/editor/org.processing.editor/src/org/processing/preferences/PreferenceInitializer.java new file mode 100644 index 000000000..2533609f5 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/preferences/PreferenceInitializer.java @@ -0,0 +1,38 @@ +package org.processing.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import org.processing.editor.ProcessingEditorPlugin; + +/** + * Class used to initialize default preference values. + */ +public class PreferenceInitializer extends AbstractPreferenceInitializer { + + /** + * Sets the default preference values + */ + public void initializeDefaultPreferences() { + IPreferenceStore store = ProcessingEditorPlugin.getDefault().getPreferenceStore(); + + //store.setDefault(PreferenceContants.PROCESSING_SKETCH, value); + store.setDefault(PreferenceConstants.PROCESSING_AUTO_INDENT, true); + + // PROCESSING_PREFERENCES are processing.app preferences +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_EDITOR_TABS_SIZE, "4"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_SUBSTITUTE_FLOATS, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_WEB_COLORS, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_COLOR_DATATYPE, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_ENHANCED_CASTING, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_SUBSTITUTE_UNICODE, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_OUTPUT_PARSE_TREE, "false"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_EXPORT_APPLICATION_FULLSCREEN, "false"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_RUN_PRESENT_BGCOLOR, "#666666"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_EXPORT_APPLICATION_STOP, "true"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_RUN_PRESENT_STOP_COLOR, "#cccccc"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_RUN_WINDOW_BGCOLOR, "#ECE9D8"); +// store.setDefault(PreferenceConstants.PROCESSING_APP_PREFERENCES_PREPROC_PREPROC_IMPORTS_LIST, "java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image,java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.*"); + } + +} diff --git a/editor/org.processing.editor/src/org/processing/preferences/ProcessingPreferencesPage.java b/editor/org.processing.editor/src/org/processing/preferences/ProcessingPreferencesPage.java new file mode 100644 index 000000000..8ad2ade58 --- /dev/null +++ b/editor/org.processing.editor/src/org/processing/preferences/ProcessingPreferencesPage.java @@ -0,0 +1,70 @@ +package org.processing.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; +import org.processing.editor.ProcessingEditorPlugin; + +/** + * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + *

+ * Two editor preferences are included as examples, but + * currently do not do anything. + *

+ * //TODO transfer Processing.app preferences here + * this may involve subclassing PreferencePage, + * but things could be setup such that these are read + * from a file, and we could use a customized version of + * a standard Processing preferences file to store this. + * + * Added some validation and warning messages as examples. + * If we really want to implement ones of any complexity + * there should be an addition of propertyChange() and checkState() + * methods. + * See: http://sites.google.com/site/eclipseplugindevelopment/9-preference-pages + */ + +public class ProcessingPreferencesPage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public ProcessingPreferencesPage() { + super(GRID); + setPreferenceStore(ProcessingEditorPlugin.getDefault().getPreferenceStore()); + setDescription("Processing Plugin Preferences (nothing here is used, see JavaDoc)"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + // Sketchbook Directory Item setup + DirectoryFieldEditor nextField = new DirectoryFieldEditor(PreferenceConstants.PROCESSING_SKETCHBOOK, "Sketchbook Directory:", getFieldEditorParent()); + nextField.setEmptyStringAllowed(false); + nextField.setErrorMessage("The Sketchbook Directory shouldn't be empty!"); + addField(nextField); + // Library Path item setup + nextField = new DirectoryFieldEditor(PreferenceConstants.PROCESSING_LIBRARIES, "Processing Library Path:", getFieldEditorParent()); + nextField.setEmptyStringAllowed(false); + nextField.setErrorMessage("A library path is required to use libraries!"); + addField(nextField); + // Checkbox example setup! + addField( + new BooleanFieldEditor( + PreferenceConstants.PROCESSING_AUTO_INDENT, + "Auto indent", + getFieldEditorParent())); + } + + /** + * Initializes the preference page. Nothing to do here, but it has to be subclassed. + */ + public void init(IWorkbench workbench) {} + +} \ No newline at end of file