Home Tutorials Training Consulting Products Books Company Donate Contact us









Online Training

Quick links

Share

This tutorial describes how to create a text editor in Eclipse.

1. Eclipse Editors

An editor allows to modify data. It typically requires that the user explicitly performs a save action to apply the changes to the data. By default, Eclipse opens editors in the same shared area.

1.1. Defining an editor

If you are planning to provide editor functionality for a certain file extension or content type, you basically have two choices:

  • Re-use the generic editor and extend it

  • Define your own editor

Add support a new content type in the generic editor you need to:

  • add a content type

  • register a PresentationReconsiler to it via the org.eclipse.ui.genericeditor.presentationReconcilers extension point

Reusing the generic editor is the preferred choice as of Eclipse 4.8 and will be demonstrated in the following exercises.

1.2. Introduction to presentation reconciler

The highlighting of source code can be archived by using an presentation reconciler. Such a presentation reconciler can be defined via an org.eclipse.ui.genericeditor.presentationReconcilers extension. It requires the specification of a contentType and a class, which implements the IPresentationReconciler interface. When using an IPresentationReconciler certain IRules can be applied for a specified content type. An IRule defines a rule used in the scanning of text for the purpose of document partitioning or text styling.

2. Implementing your custom editor

While it is recommended to reuse the generic editor instead defining a new one, this is still supported. This chapter gives an explanation how this can be done.

2.1. IEditorPart and EditorPart

To define a new editor for the Eclipse IDE, you typically: * Create an IEditorInput class * Define an extension for the org.eclipse.ui.editors extension point * Implement a class extending IEditorPart

IEditorInput serves as the model for the editor. Eclipse will buffer IEditorInput objects therefore this object should be relatively small.

It is supposed to be a light-weight representation of the model. For example the Eclipse IDE uses IEditorInput objects to identify files without handling with the complete file.

The equals() of IEditorInput define the identity of the editor, e.g., it will be used to determine if an editor is already open or not.

The editor receives the IEditorSite and the IEditorInput in the init() method. It must set the input via the setInput() method and the side via the setSite() method.

init() is called before createPartControl() (which creates the user interface). Therefore you can use the input during your UI creation.

If you define your own perspective, you can enable the editor area via the following code in your perspective implementation.

import org.eclipse.ui.IPageLayout;

public class Perspective implements IPerspectiveFactory {

    public void createInitialLayout(IPageLayout layout) {
        //layout.setEditorAreaVisible(false);
        layout.setFixed(true);
    }

}

2.2. Setting the editor title and tooltip

By default, the editor will use the tooltip and title from the IEditorInput. Therefore you may want to change the title and tooltip in your Editor. Use setPartName() to set the title of the Editor and getTitleToolTip() for setting the tooltip. See Bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=107772 for details on the tooltip.

2.3. Saving the editor content

The method isDirty() determines if the editor contains modified data. For inform the workbench about changes in the dirty state you fired an event.

firePropertyChange(IEditorPart.PROP.DIRTY);

2.4. API for working with editors

You can open an Editor via the current active page. For this you need the EditorInput object and the ID for the editor which is defined in the "org.eclipse.ui.editors" extension point.

page.openEditor(new YourEditorInput(), ID_OF_THE_EDITOR);

To get the page you can use:

// If you are in a view
getViewSite().getPage();
// If you are in an command
HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
// Somewhere else
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();

If you hold down the Ctrl and click on an element in the Java editor you can navigate to it.

This functionality is provided via extensions for the org.eclipse.ui.workbench.texteditor.hyperlinkDetectors extension point. The specified name is visible in the preferences under General  Editors  Text Editors  Hyperlinking. The targetId points to the type of editor you want to support. If you want to use in all text editors use org.eclipse.ui.DefaultTextEditor. To target the generic editor use the org.eclipse.ui.genericeditor.GenericEditor target id.

An IHyperlinkDetector is supposed to return an array of IHyperlink objects. The IHyperlink implemention performs the hyperlink action.

3.2. Adding colors and fonts preferences

Eclipse provides a page for the customizations of colors and fonts by the user under General  Appearance  Colors and Fonts.

To define an entry for this page, you need to define an extension for the org.eclipse.ui.themes extension point.

For example, you can provide a category, font and color with the following entry in the plugin.xml file or your plug-in.

 <extension point="org.eclipse.ui.themes">
    <themeElementCategory
        id="com.vogella.eclipse.preferences.mythemeElementCategory"
        label="vogella category">
        <description>
            An example theme category
        </description>
    </themeElementCategory>
    <colorDefinition
        categoryId="com.vogella.eclipse.preferences.mythemeElementCategory"
        id="com.vogella.eclipse.preferences.myFirstColorDefinition"
        label="vogella color"
        value="COLOR_DARK_BLUE">
        <description>
            Your description for the color
        </description>
    </colorDefinition>
    <fontDefinition
        categoryId="com.vogella.eclipse.preferences.mythemeElementCategory"
        id="com.vogella.eclipse.preferences.myFirstFontDefinition"
        label="vogella Font"
        value="Lucida Sans-italic-18">
        <description>
            Your description for the font
        </description>
    </fontDefinition>
</extension>

The value for the color can be a COLOR_* constants defined in the SWT class. You can also specify RGB values like 255,0,0. The value for the font is defined via the following pattern:`fontname-style-height`

The preference can now be changed via the user or via the CSS engine. To get the current value you can use the IThemeManager.

// Eclipse 4 API
@Inject IThemeManager themeManager;

// Eclipse 3 API
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();

ITheme currentTheme = themeManager.getCurrentTheme();

ColorRegistry colorRegistry = currentTheme.getColorRegistry();
Color color = colorRegistry.get("com.vogella.eclipse.preferences.myFirstColorDefinition");

FontRegistry fontRegistry = currentTheme.getFontRegistry();
Font font = fontRegistry.get("com.vogella.eclipse.preferences.myFirstFontDefinition");

3.3. Custom spelling engine

The org.eclipse.ui.workbench.texteditor plug-in provides the option to register a custom spelling engine via the org.eclipse.ui.workbench.texteditor.spellingEngine extension point.

4. Exercise : Extend the generic editor to support a custom file type

4.1. Create a new plug-in

In this exercise you associated files with the tasks extension with the generic text editor in Eclipse. Within this file, you want to supported editing property files as for example.

test:Hello
Helper:stuff

Create a new plug-in project called com.vogella.ide.editor.tasks and add the following dependencies to its manifest.

  • org.eclipse.text

  • org.eclipse.ui

  • org.eclipse.ui.editors

  • org.eclipse.ui.genericeditor

  • org.eclipse.ui.workbench.texteditor

  • org.eclipse.jface.text

  • org.eclipse.core.runtime

  • org.eclipse.core.resources

  • com.vogella.tasks.model

The resulting MANIFEST.MF should look similar to the following. Bundle-versions have been removed as they change to frequently.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Editor
Bundle-SymbolicName: com.vogella.ide.editor.tasks;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: VOGELLA
Automatic-Module-Name: com.vogella.ide.editor
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.eclipse.text,
 org.eclipse.ui,
 org.eclipse.ui.editors,
 org.eclipse.ui.genericeditor,
 org.eclipse.ui.ide,
 org.eclipse.ui.workbench.texteditor,
 org.eclipse.jface.text,
 org.eclipse.core.runtime,
 org.eclipse.core.resources,
 com.vogella.tasks.model

4.2. Define content type

Select in the MANIFEST.MF the Extensions tab. Add an extension for the org.eclipse.core.contenttype.contentTypes extension point. Use the Add button for this.

contentTypes extension10

Right-click on your new entry and select New  content-type. Specify a content type for files with the .tasks extension. Your plugin.xml file should look similar to the following listing.

<extension
      point="org.eclipse.core.contenttype.contentTypes">
   <content-type
         file-extensions="tasks"
         id="com.vogella.ide.contenttype.tasks"
         name="Tasks"
         priority="high">
   </content-type>
</extension>

4.3. Associate content type with editor

This content type can be associated with a certain editor. The org.eclipse.ui.editors extension point can be used for this.

Add the org.eclipse.ui.editors extension. Right-click on your org.eclipse.ui.editors, and select New  editorContentTypeBinding to define this.

<extension
      point="org.eclipse.ui.editors">
   <editorContentTypeBinding
         contentTypeId="com.vogella.ide.contenttype.tasks"
         editorId="org.eclipse.ui.genericeditor.GenericEditor">
   </editorContentTypeBinding>
</extension>

You should have at least two entries in the extension tab.

editor contenttype pluginxml

4.4. Add your plug-in to your product via the feature

If you are using a product, add your new plug-in to your feature and start a runtime Eclipse via the product. Otherwise, update the launch configuration directly to ensure you new plug-in is included in the start.

4.5. Test your development

Start a runtime Eclipse which contains your new plug-in.

Ensure that you content type is visible in Window  Preferences  General  Content Types.

content type task result

Create a new project and a new file with the .tasks extension. If you open the file, it should open in the generic text editor.

tasks in genericeditor10

Use the Plug-in Spy Shift+Alt+F1 to see the editor class, it should be the ` ExtensionBasedTextEditor` class. To use the Plug-in Spy in your runtime IDE, add the org.eclipse.pde feature to your product. Ensure you start via the product.

5. Optional exercise: Create a editor association for .gradle files

5.1. Associate Gradle with the generic editor

Associate the .gradle file extension with the generic editor. If you have Gradle installed into your IDE, ensure that you do not include it into your runtime IDE.

5.2. Validate

Ensure that .gradle files open in the generic editor.

6. Exercise: Implementing syntax highlighting

In this exercise .tasks files you implement syntax highlighting for your editor.

6.1. Implement syntax highlighting

Continue to work in the com.vogella.ide.editor.tasks plug-in.

Implement the following class to define a IRule.

package com.vogella.ide.editor.tasks;

import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;

public class PropertyNameRule implements IRule {

    private final Token token;

    public PropertyNameRule(Token token) {
        this.token = token;
    }

    @Override
    public IToken evaluate(ICharacterScanner scanner) {
        int c = scanner.read();
        int count = 1;

        while (c != ICharacterScanner.EOF) {

            if (c == ':') {
                return token;
            }

            if ('\n' == c || '\r' == c) {
                break;
            }

            count++;
            c = scanner.read();
        }

        // put the scanner back to the original position if no match
        for (int i = 0; i < count; i++) {
            scanner.unread();
        }

        return Token.UNDEFINED;
    }
}

Implement the following PresentationReconciler as your reconciler.

package com.vogella.ide.editor.tasks;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;

public class PropertiesReconciler extends PresentationReconciler {

    private final TextAttribute tagAttribute = new TextAttribute(
            Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN));

    public PropertiesReconciler() {
        RuleBasedScanner scanner = new RuleBasedScanner();
        IRule rule = new PropertyNameRule(new Token(tagAttribute));
        scanner.setRules(new IRule[] { rule });
        DefaultDamagerRepairer dr = new DefaultDamagerRepairer(scanner);
        this.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
        this.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
    }
}

Add the an extension to the org.eclipse.ui.genericeditor.presentationReconcilers extension point to the plugin.xml file of the com.vogella.ide.editor.tasks plug-in.

<extension
      point="org.eclipse.ui.genericeditor.presentationReconcilers">
    <presentationReconciler
         class="com.vogella.ide.editor.tasks.PropertiesReconciler"
         contentType="com.vogella.ide.contenttype.tasks">
   </presentationReconciler>
</extension>

6.2. Test your implementation

Restart your runtime Eclipse and open your file. Enter a few property values in the file.

test:Hello
Helper:stuff

The result should look similar to this:

editor syntax highlight

7. Optional exercise: Add Gradle syntax highlighting to the generic editor

This exercise requires that you associated the .gradle file extension with the generic editor.

Use two SingleLineRule to highlight quotes, string between '' and "", e.g., 'doit'. Use a NumberRule to highlight numbers.

Implement your customer rule GradleKeywordRule extending WordRule to identify at highlight the words allprojects and apply. This requires your custom IWordDetector implementation.

package com.vogella.ide.editor.gradle;

import org.eclipse.jface.text.rules.IWordDetector;

class Detector implements IWordDetector {
    public boolean isWordStart(char c) {
        return Character.isAlphabetic(c);
    }

    public boolean isWordPart(char c) {
        return Character.isAlphabetic(c);
    }
}

Use WordRule#addWord in your GradleKeywordRule constructor for adding words.

 public GradleKeywordRule() {
        super(new Detector());
        // TODO add your works with Tolkens
    }

7.1. Validate

Ensure that .gradle files open in the generic editor. Create the following file and check that your syntax highlighting works.

buildscript {
    repositories {
        jcenter()
        mavenLocal()
        maven{ url 'https://dl.bintray.com/vogellacompany/Gradle-AsciiDoctor-Plugin/' }
    }
    dependencies {
        classpath 'com.vogella.gradle:com.vogella.gradle.plugin.asciidoc:0.15.0'
    }
}

allprojects {
    apply plugin: 'com.vogella.gradle.plugin'
}

The result should be similar to the following.

generic editor gradle result

8. About this website

9.1. vogella GmbH training and consulting support

To learn more please join our interactive learning platform.

Copyright © 2012-2018 vogella GmbH. Free use of the software examples is granted under the terms of the Eclipse Public License 2.0. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.