Vaadin wrapper for Ace editor
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
aceeditor-demo
aceeditor
.gitignore
.travis.yml
LICENSE
README.md
pom.xml

README.md

Vaadin AceEditor

Ace code editor wrapped inside a TextArea-like Vaadin component.

Available as an add-on in Vaadin Directory.

NOTE

Unfortunately I (@ahn) currently don't have time to maintain this project. I can accept pull requests and put a new version to Vaadin Directory once in a while but not do much beyond that. If you'd like to be a more active maintainer, feel free to contact me.

From version 0.8.15 onwards this add-on requires Vaadin 8. Versions 0.7.0 - 0.8.14 are for Vaadin 7, and versions before that are for Vaadin 6. The "quick and brutal" port to Vaadin 8 by willtemperley.

  • Currently using version 1.1.9 of Ace.

This add-on is still in an experimental phase, interfaces etc. are subject to change.

Getting started

  1. Start a Vaadin 8 project.
  2. Get the AceEditor addon from Vaadin directory. Maven is recommended.
  3. Compile widgetset.
  4. See below for instructions on how to use the AceEditor component.

How to use

These instructions are for Vaadin 7 version of AceEditor.

Basics

AceEditor editor = new AceEditor();
editor.setValue("Hello world!");
layout.addComponent(editor);
// ...
String s = editor.getValue();

Mode & theme

Mode defines the programming language used in the editor. Theme is the appearance of the editor.

editor.setMode(AceMode.python);
editor.setTheme(AceTheme.eclipse);

// Use worker (if available for the current mode)
editor.setUseWorker(true);

NOTE: to be able to use workers, you must host the worker files on the same server (same-origin policy restriction.) See below.

Ace file paths

By default, Vaadin AceEditor gets the mode, theme and worker files from the ace-builds repository via rawgit.com. For example: mode-javascript.js. Currently using version 1.1.9 of Ace. The 1.2.x doesn't work (yet).

It's probably safer to host the mode&theme files yourself so that you can be sure that they're compatible with the main Ace file used by this editor.

To host the files on your own server, here's how:

First, get the ace dir from the Vaadin Directory download package. It contains the src-min-noconflict Ace files compatible with this addon. Copy the ace dir to location webapp/static/ace in your Vaadin application. The structure should look something like this:

webapp/
  META-INF/
  static/
    ace/
      mode-abap.js
      ...
  VAADIN/
  WEB-INF/

And have this in your web.xml:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

Then, tell the editor to use the files in the location:

editor.setThemePath("/static/ace");
editor.setModePath("/static/ace");
editor.setWorkerPath("/static/ace");    
// or "/myapp/static/ace" depending on server configuration.

Now, Ace should read the theme/mode/worker files from your local server.

Other settings

editor.setWordWrap(false);
editor.setReadOnly(false);
editor.setShowInvisibles(false);
// TODO: more

Listeners

TextChangeListener
ed.addTextChangeListener(new TextChangeListener() {
    @Override
    public void textChange(TextChangeEvent event) {
        Notification.show("Text: " + event.getText());
    }
});
SelectionChangeListener
ed.addSelectionChangeListener(new SelectionChangeListener() {
    @Override
    public void selectionChanged(SelectionChangeEvent e) {
        int cursor = e.getSelection().getCursorPosition();
        Notification.show("Cursor at: " + cursor);
    }
});

Markers

Ace supports custom markers within the code. The marker appearance is defined by a css class.

String cssClass = "mymarker1";
TextRange range = editor.getSelection();    
AceMarker.Type type = AceMarker.Type.text; // text or line
boolean inFront = false; // whether in front or behind the text
AceMarker.OnTextChange onChange = AceMarker.OnTextChange.ADJUST;
String markerId = editor.addMarker(range, cssClass, type, inFront, onChange);
// ...
editor.removeMarker(markerId);

The cssClass must be defined in some css file, for example mymarkers.css:

.ace_marker-layer .mymarker1 {
    background: red;
	border-bottom: 2px solid black;
	position: absolute;
}

...and then use the file:

@StyleSheet("mymarkers.css")
public class MyUI extends UI {

The OnTextChange defines how the marker behaves when the editor text changes.

  • DEFAULT: stay in the original position. That's what Ace does by default.
  • ADJUST: adjust the marker position when text changes. For example, if a line is added before the marker, the marker is moved one line down, thus keeping its "logical" position within the text.
  • REMOVE: remove the marker on text change.

Annotations

Ace supports annotations, i.e little notes on the side of the editor.

Vaadin AceEditor has two types of Annotations: row annotations and marker annotations. Only one type of annotations is possible to be used on an AceEditor at a time.

Row annotations are standard Ace annotations that are added to a certain row and Ace handles their position from there on. (Their possibly changed positions can't be retrieved later from Ace, which is the cause for this two kinds of annotations mess in Vaadin AceEditor.)

Marker annotations are attached to a marker. If the marker changes position the annotation follows.

String msg = "Warning!!!";
AceAnnotation.Type type = AceAnnotation.Type.warning;
AceAnnotation ann = new AceAnnotation(msg, type);
if (rowAnnotations) {
    editor.addRowAnnotation(ann, 2);
}
else {
    String markerId = editor.addMarker(/*...*/);
    editor.addMarkerAnnotation(ann, markerId);
}
// ...
editor.clearRowAnnotations();
editor.clearMarkerAnnotations();

Suggestions

This addon also includes a SuggestionExtension for implementing a "suggester" that gives user a list of text suggestions after she presses Ctrl+Space in AceEditor. An example MySuggester implementation here. See the "suggestion demo" here.

new SuggestionExtension(new MySuggester()).extend(editor);

Compiling this project

To package and install the Vaadin AceEditor addon to your local Maven repository, run

cd aceeditor
mvn install

To run a demo application in http://localhost:8080

cd aceeditor-demo
mvn vaadin:compile jetty:run

To create an addon package that can be uploaded to Vaadin Directory

cd aceeditor
mvn clean package assembly:single

Build Status

Notes on implementation

Server-client communication

This addon uses diffs to communicate between the server-side and the client-side of the AceEditor component. That is, when a user types something, the whole text is not sent to the server, just some kind of diff from the old value to the new one. Similarly, diffs are sent if the value changes on the server. The addon utitlizes the diff-match-patch library along with the differential synchronization algorithm for communication.

Pros of this diff approach:

  • Less data to be sent between client and server.
  • The content of the editor can be changed concurrently on the server and on the client. This makes it possible to implement things like the "auto-correction demo" in the aceeditor demo (code of the server-side "auto-corrector" here). In the demo the value can be modified at the same time on the client and on the server without losing either modifications. Also, Google Docs style collaborative editor can be implemented on top of this.

Cons:

  • Requires more cpu, for computing the diffs etc. (There's a room for optimization in the current implementation.)
  • Complicates things...

Links

Related Projects