<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<!-- -*- xhtml -*- --> | |
<title>NetBeans Manifest File Syntax Highlighting Module Tutorial</title> | |
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"> | |
<meta name="AUDIENCE" content="NBUSER"> | |
<meta name="TYPE" content="ARTICLE"> | |
<meta name="EXPIRES" content="N"> | |
<meta name="developer" content="gwielenga@netbeans.org"> | |
<meta name="indexed" content="y"> | |
<meta name="description" | |
content="A short guide to using the Nodes API."> | |
<!-- Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. --> | |
<!-- Use is subject to license terms.--> | |
</head> | |
<body> | |
<h1>NetBeans Manifest File Syntax Highlighting Module Tutorial</h1> | |
<p> | |
<div style="border: 1px solid rgb(14, 27, 85); padding: 10px 30px; background-color: rgb(231, 231, 231); margin-left: 60px; margin-right: 40px;"> | |
Please note that this tutorial is <b>obsolete</b>. Go here instead:<p> | |
<a href="http://wiki.netbeans.org/How_to_create_support_for_a_new_language">http://wiki.netbeans.org/How_to_create_support_for_a_new_language</a> | |
</div> | |
<p>This tutorial shows you how to enhance the IDE by adding syntax highlighting for Manifest files. At the end of this tutorial, | |
you will have a NetBeans plug-in module file (NBM) that you can share with others. When it is installed | |
via the NetBeans Update Center, the 'name', 'colon', and 'value' | |
of manifest entries will have distinct colors, as illustrated below: | |
<p><img src="../images/tutorials/mf_syntax/result1.png" alt="Highlighted manifest file"> | |
<p>In addition, you will be able to use the Options window to modify the colors. | |
<p>The following topics are covered in this tutorial:</p> | |
<ul> | |
<li><a href="#gettingtoknowthesample">Getting to Know the Sample</a></li> | |
<ul> | |
<li><a href="#installing-software">Installing the Software</a></li> | |
<li><a href="#installing-sample">Installing the Sample</a></li> | |
<li><a href="#introducing-sample">Introducing the Sample</a></li> | |
<li><a href="#introducing-sources">Introducing the Sources</a></li> | |
</ul> | |
<li><a href="#settingupthemoduleproject">Setting Up the Module Project</a></li> | |
<ul> | |
<li><a href="#creatingthemoduleproject">Creating the Module Project</a></li> | |
<li><a href="#specifying">Specifying the Module's Dependencies</a></li> | |
</ul> | |
<li><a href="#creatingthemainfiles">Creating the Main Files</a></li> | |
<ul> | |
<li><a href="#tokenizing">Creating Tokens</a> | |
<li><a href="#syntaxing">Creating Syntax</a> | |
<li><a href="#testing">Giving the IDE a Reading Test</a> | |
<li><a href="#editorkitting">Creating the Editor Kit</a> | |
<li><a href="#syntaxcoloring">Creating the Syntax Coloring</a> | |
<li><a href="#colorrestoring">Creating the Color Restorer</a></ul> | |
<li><a href="#creatingthemainfiles">Creating the Supporting Files</a></li> | |
<ul> | |
<li><a href="#creatingoptions">Creating Options</a> | |
<li><a href="#dipslayingoptionsinoptionswindow">Displaying the Options in the Options Window</a> | |
<li><a href="#instantiating">Instantiating the Options</a> | |
<li><a href="#registeringoptions">Registering the Options in the NetBeans System Filesystem</a> | |
</ul> | |
<li><a href="#building">Building and Installing the Module</a></li> | |
<li><a href="#explore">Exploring Further</a></li> | |
</ul> | |
<p><a name="top"></a>Once the software is installed, this tutorial can be completed in 60 minutes. | |
<p>For more information on creating NetBeans plug-in modules, see the <a href="https://platform.netbeans.org/index.html"> | |
NetBeans Development Project home</a> on the NetBeans website. If you have questions, visit the | |
<a href="http://wiki.netbeans.org/wiki/view/NetBeansDeveloperFAQ">NetBeans Developer FAQ</a> or use the feedback link | |
at the top of this page.</p> | |
<br /> | |
<!-- ===================================================================================== --> | |
<h2><a name="gettingtoknowthesample"></a>Getting to Know the Sample</h2> | |
<p>Before you start writing the module, you have to make sure you have all of the necessary software. | |
In addition, you might want to play with the sample before building it yourself.</p> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="installing-software"></a>Installing the Software</h3> | |
<p>Before you begin, you need to install the following software on your | |
computer:</p> | |
<ul> | |
<li>NetBeans IDE 5.x (<a href="http://www.netbeans.info/downloads/download.php?a=n&p=1">download</a>)</li> | |
<li>Java Standard Development Kit (JDK™) version | |
1.4.2 (<a href="http://java.sun.com/j2se/1.4.2/download.html">download</a>) | |
or 5.0 (<a href="http://java.sun.com/j2se/1.5.0/download.jsp">download</a>)</li> | |
</ul> | |
<h3 class="tutorial"><a name="installing-sample"></a>Installing the Sample</h3> | |
<p>Take the following steps to install the sample: | |
<ol><p><li>Unzip the <a href="https://netbeans.org/files/documents/4/583/ManifestSupport.zip">attached file</a>. | |
<p><li>In the IDE, choose File > Open Project and browse to the folder that contains the unzipped file. | |
Open the module project. It should look as follows: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window.png" alt="Final Projects window"> | |
<p><li>Right-click the project node and choose Install/Reload in Target Platform. The target | |
platform opens and the module is installed.</ol> | |
<h3 class="tutorial"><a name="introducing-sample"></a>Introducing the Sample</h3> | |
<ol> | |
<p><li>Use the New project wizard (Ctrl-Shift-N) to create a new Java application | |
project or NetBeans plug-in module project and notice | |
that the project's manifest file has syntax highlighting, as shown in the introduction of this tutorial. | |
<p><li>Choose Tools > Options. In the Options window, click Fonts & Colors in the left sidebar | |
and notice that there is an entry called 'Manifest' in the Language drop-down list, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-1.png" alt="Fonts and Colors 1"> | |
<p><li>Select City Lights in the Profile drop-down list at the top of the Fonts & Colors page, | |
and notice that the syntax changes, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-4.png" alt="Fonts and Colors 4"> | |
<p><li>Click Editor in the left sidebar | |
and notice that there is an entry called 'Manifest' in the Language drop-down list, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-2.png" alt="Fonts and Colors 2"> | |
<p><li>Click Advanced Options in the lower left corner of the Options window. In the Editor Settings node, notice that there is a new entry | |
for the Manifest Editor, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-3.png" alt="Fonts and Colors 3"> | |
</ol> | |
<p>Now that you know what the user interface of the Manifest Support plug-in module looks like, | |
let's have a quick look at what each of the source files does. | |
<p><h3 class="tutorial"><a name="introducing-sources"></a>Introducing the Sources</h3> | |
<p>The Manifest Support sample consists of main files and supporting files.</p> | |
<ul><li><p><b>Main Files.</b> The module's main files are in the <tt>org.netbeans.modules.manifestsupport</tt> package: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window1.png" alt="Main files."> | |
<p><table width="76%" border="1"> | |
<tbody><tr> | |
<td> | |
<div align="left"><b>File</b></div> | |
</td> | |
<td> | |
<div align="left"><b>Description</b></div> | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>Bundle.properties</tt></td> | |
<td> | |
Localization information. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><a href="#editorkitting"><tt>ManifestEditorKit.java</tt></a></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/NbEditorKit.html">NbEditorKit</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><a href="#syntaxcoloring"><tt>ManifestSettingsInitializer.java</tt></a></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/org/netbeans/editor/Settings.AbstractInitializer.html">Settings.AbstractInitializer</a> class. Includes an inner class than extends the <a href="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/org/netbeans/editor/SettingsUtil.TokenColoringInitializer.html">SettingsUtil.TokenColoringInitializer</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><a href="#syntaxing"><tt>ManifestSyntax.java</tt></a></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/org/netbeans/editor/Syntax.html">Syntax</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><a href="#tokenizing"><tt>ManifestTokenContext.java</tt></a></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/org/netbeans/editor/TokenContext.html">TokenContext</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><a href="#colorrestoring"><tt>RestoreColoring.java</tt></a></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/ModuleInstall.html">ModuleInstall</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>layer.xml</tt></td> | |
<td> | |
This is the NetBeans System Filesystem configuration file. It registers the | |
following information in the NetBeans System Filesystem: | |
<ul> | |
<li>Ability to distinguish Manifest file data objects (via the <tt>.mf</tt> file extension and <tt>text/x-java-jar-manifest</tt> MIME Type). | |
<li>Actions that appear in the right-click pop-up menu. | |
<li>A dummy template for creating new Manifest files is registered in the New File wizard. | |
<li>Editor kit, containing syntax highlighting information. | |
<li>Options settings file for instantiation of the relevant information in the Options window. | |
<li>Coloring information for the Options window, one set for the NetBeans profile and another set for the City Lights profile. | |
</ul> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<li><p><b>Supporting Files.</b> | |
<ul><li><p><b>Data Object Files.</b> The module's files that distinguish Manifest files from other files | |
are in the <tt>org.netbeans.modules.manifestsupport.dataobject</tt> package: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window2.png" alt="Data object files."> | |
<p>For information on these files, see the <a href="https://platform.netbeans.org/tutorials/nbm-filetype.html">NetBeans DataLoader Module Tutorial</a>. | |
<li><p><b>Options Window Files.</b> The module's files that install information in the Options window | |
are in the <tt>org.netbeans.modules.manifestsupport.options</tt> package: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window3.png" alt="Options window files."> | |
<p><table width="76%" border="1"> | |
<tbody><tr> | |
<td> | |
<div align="left"><b>File</b></div> | |
</td> | |
<td> | |
<div align="left"><b>Description</b></div> | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>Bundle.properties</tt></td> | |
<td> | |
Localization information. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>ManifestOptions.java</tt></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/options/BaseOptions.html">BaseOptions</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>ManifestOptions.settings</tt></td> | |
<td> | |
Instantiation data for the Options window. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>ManifestOptionsBeanInfo.java</tt></td> | |
<td> | |
Extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/options/BaseOptionsBeanInfo.html">BaseOptionsBeanInfo</a> class. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>mfOptions.gif</tt></td> | |
<td>GIF file displayed in the node for the Manifest Editor in the Classic View of the Options window. | |
</td> | |
</tr> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<li><p><b>Resources.</b> The module's resources | |
are in the <tt>org.netbeans.modules.manifestsupport.resources</tt> package | |
and in the Unit Test Packages node: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window4.png" alt="Resources files."> | |
<p><table width="76%" border="1"> | |
<tbody><tr> | |
<td> | |
<div align="left"><b>File</b></div> | |
</td> | |
<td> | |
<div align="left"><b>Description</b></div> | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>CityLights-Properties-fontsColors.xml</tt></td> | |
<td> | |
Colors for the CityLights profile in the Fonts & Colors page of the Options window. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>ManifestExample</tt></td> | |
<td> | |
Example used in the Fonts & Colors page of the Options window. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>NetBeans-Manifest-fontsColors.xml</tt></td> | |
<td> | |
Colors for the NetBeans profile in the Fonts & Colors page of the Options window. | |
</td> | |
</tr> | |
<tr> | |
<td align="left" valign="top"><tt>ManifestSyntaxTest.java</tt></td> | |
<td> | |
JUnit test for testing the Manifest file's tokens. | |
</td> | |
</tr> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<li><p><b>Important Files.</b> The Projects window is typically used to display a project's packages. However, | |
to simplify working with some of the more important files in the project, you can access them through the | |
Important Files node: | |
<p><img src="../images/tutorials/mf_syntax/final_projects_window5.png" alt="Important files."> | |
<p>For basic information each of the Important Files, see the | |
<a href="https://netbeans.org/kb/articles/quickstart-nbm.html">Introduction to NetBeans Module Development</a>.</ul></ul> | |
</div> | |
<br /> | |
<!-- ===================================================================================== --> | |
<h2><a name="settingupthemoduleproject"></a>Setting Up the Module Project</h2> | |
<p>Before you start writing the module, you have to make sure you | |
that your project is set up correctly. <a href="http://www.netbeans.info/downloads/download.php?a=n&p=1">NetBeans IDE 5.x</a> provides a wizard that sets up all the basic files | |
needed for a module.</p> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="creatingthemoduleproject"></a>Creating the Module Project</h3> | |
<ol> | |
<p><li>Choose File > New Project. Under Categories, select NetBeans Plug-in Modules. Under projects, | |
select Module Project and click Next.</li> | |
<p><li>In the Name and Location panel, type <tt>ManifestSupport</tt> in Project Name. | |
Change the | |
Project Location to any directory on your computer, such as <tt>c:\mymodules</tt>. Leave the Standalone Module radiobutton | |
and the Set as Main Project checkbox selected. | |
Click Next. | |
<p><li>In the Basic Module Configuration panel, replace <tt>yourorghere</tt> in Code Name Base with <tt>netbeans.modules</tt> | |
so that the whole name is <tt>org.netbeans.modules.manifestsupport</tt>. Leave <tt>ManifestSupport</tt> as the Module Display Name. | |
Leave the location of the localizing bundle and XML layer, so that they will be stored in a | |
package with the name <tt>org.netbeans.modules.manifestsupport</tt>. Click Finish.</ol> | |
<p> The IDE creates the <tt>ManifestSupport</tt> | |
project. The project contains all of your sources and | |
project metadata, such as the project's Ant build script. The project | |
opens in the IDE. You can view its logical structure in the Projects window (Ctrl-1) and its | |
file structure in the Files window (Ctrl-2). | |
<p><h3 class="tutorial"><a name="specifying"></a>Specifying the Module's Dependencies</h3> | |
<p>You will need to subclass several classes that belong to <a href="https://netbeans.org/download/dev/javadoc/">NetBeans APIs</a>. | |
Each has to be declared as a Module dependency. Use the Project Properties dialog box for this purpose. | |
<ol> | |
<li>In the Projects window, right-click the <tt>ManifestSupport</tt> project node and choose Properties. | |
In the Project Properties dialog box, click Libraries.</li> | |
<p><li>For each of the following APIs that is not already present in the Libraries panel, click "Add...", | |
select the name from the Module list, and then click OK to confirm it: | |
<p><ul> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-loaders/org/openide/loaders/doc-files/api.html">Datasystems API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-text/overview-summary.html">Editor API</a></tt> | |
<li><tt>Editor Library API</tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-filesystems/overview-summary.html">File System API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-modules/overview-summary.html">Module System API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/overview-summary.html">Nodes API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-options/org/openide/options/doc-files/api.html">Settings Options API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-text/overview-summary.html">Text API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-util/overview-summary.html">Utilities API</a></tt> | |
<li><tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-windows/overview-summary.html">Window System API</a></tt> | |
</ul> | |
<p>You should now see the following: | |
<p><img src="../images/tutorials/mf_syntax/proj-props1.png" alt="Project Properties dialog box."> | |
<p><li>Click OK to exit the Project Properties dialog box. | |
<p><li>In the Projects window, expand the Important Files node, double-click the Project Metadata node, and note that the APIs you selected have been | |
declared as Module dependencies:</li> | |
<pre class=examplecode><?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="https://netbeans.org/ns/project/1"> | |
<type>org.netbeans.modules.apisupport.project</type> | |
<configuration> | |
<data xmlns="https://netbeans.org/ns/nb-module-project/2"> | |
<code-name-base>org.netbeans.modules.manifestsupport</code-name-base> | |
<standalone/> | |
<module-dependencies> | |
<dependency> | |
<code-name-base>org.netbeans.modules.editor</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<release-version>3</release-version> | |
<specification-version>1.25.0.1</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.netbeans.modules.editor.lib</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<release-version>1</release-version> | |
<specification-version>1.8.0.1</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.modules</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.4</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.options</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.3</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.util</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.5</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.filesystems</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.3</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.loaders</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>5.7</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.nodes</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.6</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.text</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.7</specification-version> | |
</run-dependency> | |
</dependency> | |
<dependency> | |
<code-name-base>org.openide.windows</code-name-base> | |
<build-prerequisite/> | |
<compile-dependency/> | |
<run-dependency> | |
<specification-version>6.3</specification-version> | |
</run-dependency> | |
</dependency> | |
</module-dependencies> | |
<public-packages/> | |
</data> | |
</configuration> | |
</project></pre> | |
</ol> | |
<!-- ===================================================================================== --> | |
<h2><a name="creatingthemodule"></a>Creating the Main Files</h2> | |
<p>Creating the module starts with ensuring that the IDE recognizes Manifest files. By default, it does not | |
recognize them and, therefore, treats them as text files. Work through the <a href="https://platform.netbeans.org/tutorials/nbm-filetype.html">NetBeans DataLoader Module Tutorial</a> | |
before going further—make sure that you put the files you create in a package | |
called <tt>org.netbeans.modules.manifestsupport.dataobject</tt>. Before you go further with this tutorial, | |
the IDE should be able to recognize Manifest files. At the end of the NetBeans DataLoader Module Tutorial, you should | |
have a new MIME Type, too: <tt>text/x-java-jar-manifest</tt>. This MIME Type is used throughout this tutorial. | |
<p>Once you have a dataloader specifically for Manifest files, you need to identify items in the Manifest file that you want the IDE to be able to distinguish | |
from each other. Each distinct item is called a <i>token</i>. Once you have created tokens, you need to tell the IDE | |
how to interpret the text it finds—it needs to be told which piece of text constitutes which token. | |
In other words, you need to create a <i>syntax</i>. Next, you associate the tokens | |
with colors. In the process, you create an editor specifically for Manifest files. | |
<div class="indent"> | |
<p><h3 class="tutorial"><a name="tokenizing"></a>Creating Tokens</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
and type <tt>ManifestTokenContext</tt> in Class Name. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport; | |
import org.netbeans.editor.BaseTokenID; | |
import org.netbeans.editor.TokenContext; | |
import org.netbeans.editor.TokenContextPath; | |
import org.netbeans.editor.Utilities; | |
public class ManifestTokenContext extends <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/org/netbeans/editor/TokenContext.html">TokenContext</a> { | |
// Numeric-ids for token categories | |
public static final int NAME_ID = 1; | |
public static final int COLON_ID = 2; | |
public static final int VALUE_ID = 3; | |
public static final int END_OF_LINE_ID = 4; | |
// Token-ids | |
public static final BaseTokenID NAME = new BaseTokenID("name", NAME_ID); | |
public static final BaseTokenID COLON = new BaseTokenID("colon", COLON_ID); | |
public static final BaseTokenID VALUE = new BaseTokenID("value", VALUE_ID); | |
public static final BaseTokenID END_OF_LINE = | |
new BaseTokenID("end-of-line", END_OF_LINE_ID); | |
// Context instance declaration | |
public static final ManifestTokenContext context = new ManifestTokenContext(); | |
public static final TokenContextPath contextPath = context.getContextPath(); | |
/** | |
* Construct a new ManifestTokenContext | |
*/ | |
private ManifestTokenContext() { | |
super("mf-"); | |
try { | |
addDeclaredTokenIDs(); | |
} catch (Exception e) { | |
Utilities.annotateLoggable(e); | |
} | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class specifies a token for each item in the Manifest file with which we want to | |
work. Each distinct item in a Manifest file is a token: | |
'name', 'colon', and 'value'. In addition, there is also a token for the end of the line, because we need to | |
work with the end of the line—the end of the line | |
determines where a value ends and the next name begins. The constructor above specifies that all tokens will | |
be prefaced by 'mf-'. So, we've now created tokens called 'mf-name', 'mf-colon', 'mf-value', and 'mf-end-of-line'. | |
</ol> | |
<h3 class="tutorial"><a name="syntaxing"></a>Creating Syntax</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
and type <tt>ManifestSyntax</tt> in Class Name. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport; | |
import org.netbeans.editor.Syntax; | |
import org.netbeans.editor.TokenID; | |
import org.openide.ErrorManager; | |
public class ManifestSyntax extends Syntax { | |
/** | |
* The logger for this class. It can be used for tracing the class activity, | |
* logging debug messages, etc. | |
*/ | |
private static final ErrorManager LOGGER = | |
ErrorManager.getDefault().getInstance("org.netbeans.modules." + | |
"manifestsupport.ManifestSyntax"); | |
/** | |
* Used to avoing calling the log() or notify() method if the message | |
* wouldn't be loggable anyway. | |
*/ | |
private static final boolean LOG = | |
LOGGER.isLoggable(ErrorManager.INFORMATIONAL); | |
// The states for the lexical analyzer | |
private static final int ISI_NAME = 1; // inside the name part | |
private static final int ISA_AFTER_NAME = ISI_NAME + 1; // immediately after the name part | |
private static final int ISA_AFTER_COLON = ISA_AFTER_NAME + 1; // immediately after the | |
// colon between the name | |
// and the value | |
private static final int ISI_VALUE = ISA_AFTER_COLON + 1; // inside the value part | |
protected TokenID parseToken() { | |
TokenID result = doParseToken(); | |
if (LOG) { | |
LOGGER.log(ErrorManager.INFORMATIONAL, "parseToken: " + result); | |
} | |
return result; | |
} | |
private TokenID doParseToken() { | |
char actChar; | |
while (offset < stopOffset) { | |
actChar = buffer[offset]; | |
switch (state) { | |
case INIT: | |
switch (actChar) { | |
case ':': | |
state = ISA_AFTER_COLON; | |
offset++; | |
return ManifestTokenContext.COLON; | |
case '\n': | |
state = INIT; | |
offset++; | |
return ManifestTokenContext.END_OF_LINE; | |
default: | |
state = ISI_NAME; | |
} | |
break; | |
case ISI_NAME: | |
switch (actChar) { | |
case ':': | |
case '\n': | |
state = ISA_AFTER_NAME; | |
return ManifestTokenContext.NAME; | |
} | |
break; | |
case ISA_AFTER_NAME: | |
switch (actChar) { | |
case ':': | |
state = ISA_AFTER_COLON; | |
offset++; | |
return ManifestTokenContext.COLON; | |
case '\n': | |
state = INIT; | |
offset++; | |
return ManifestTokenContext.END_OF_LINE; | |
default: | |
assert false; | |
} | |
break; | |
case ISA_AFTER_COLON: | |
switch (actChar) { | |
case '\n': | |
state = INIT; | |
offset++; | |
return ManifestTokenContext.END_OF_LINE; | |
default: | |
state = ISI_VALUE; | |
} | |
break; | |
case ISI_VALUE: | |
switch (actChar) { | |
case '\n': | |
state = INIT; | |
return ManifestTokenContext.VALUE; | |
} | |
break; | |
} | |
offset++; | |
} | |
/* | |
* At this stage there's no more text in the scanned buffer. | |
* It is valid to return a token here only if this is the last | |
* buffer (otherwise the token could continue in the next buffer). | |
*/ | |
if (lastBuffer) { | |
switch (state) { | |
case ISI_NAME: | |
state = INIT; | |
return ManifestTokenContext.NAME; | |
case ISI_VALUE: | |
state = INIT; | |
return ManifestTokenContext.VALUE; | |
} | |
} | |
return null; | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class tells the IDE which part of the text is which token. | |
It does this by starting in an initial state and sequentially looking at each character in the text | |
and deciding if it stays in that state, moves to another state, or announces that a token was found. | |
<p>For example, for names the IDE starts in the initial state and the first time it encounters a valid character | |
for a name, it enters the <tt>ISI_NAME</tt> state. It stays in this state until it encounters a <tt>\r</tt>, <tt>\n</tt> or <tt>:</tt> | |
character, which cannot be part of a name. When it encounters such a character, the IDE knows that | |
the characters it just traversed make up a name token. The code runs within a while loop. At the end there is | |
a break statement, which increases the offset | |
in the text. The return statement in the code avoids increasing the offset and ensures that the parsing | |
of the next token, after a name, will start with this character (it will likely be a colon, which is a | |
meaningful token itself). | |
The break statement, on the other hand, ensures that offset is increased. When all the characters | |
up to the colon are tested, the IDE knows whether the cursor is inside a name or not. | |
</ol> | |
<h3 class="tutorial"><a name="testing"></a>Giving the IDE a Reading Test</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the Unit Test Packages node, choose New > Java Class, | |
type <tt>ManifestSyntaxTest</tt> in Class Name, and type <tt>org.netbeans.modules.manifestsupport</tt> in Package. | |
Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>import java.util.Arrays; | |
import java.util.Iterator; | |
import java.util.List; | |
import junit.framework.TestCase; | |
import org.netbeans.editor.Syntax; | |
import org.netbeans.editor.TokenID; | |
import org.netbeans.modules.manifestsupport.*; | |
import junit.framework.TestCase; | |
public class ManifestSyntaxTest extends TestCase { | |
public ManifestSyntaxTest(String testName) { | |
super(testName); | |
} | |
public void testNextToken() { | |
doParse("Manifest-Version: 1.0", new TokenID[] { | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
ManifestTokenContext.VALUE, | |
}); | |
doParse("Manifest-Version: 1.0\n\n" + | |
"OpenIDE-Module: org.netbeans.modules.manifestsupport\n", | |
new TokenID[] { | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
ManifestTokenContext.VALUE, | |
ManifestTokenContext.END_OF_LINE, | |
ManifestTokenContext.END_OF_LINE, | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
ManifestTokenContext.VALUE, | |
ManifestTokenContext.END_OF_LINE, | |
}); | |
} | |
public void doParse(String m, TokenID[] expected) { | |
Syntax s = new ManifestSyntax(); | |
s.load(null, m.toCharArray(), 0, m.length(), true, m.length()); | |
TokenID token = null; | |
Iterator i = Arrays.asList(expected).iterator(); | |
do { | |
token = s.nextToken(); | |
if (token != null) { | |
if (!i.hasNext()) { | |
fail("More tokens returned than expected."); | |
} else { | |
assertSame("Tokens differ", i.next(), token); | |
} | |
} else { | |
assertFalse("More tokens expected than returned.", i.hasNext()); | |
} | |
System.out.println(token); | |
} while (token != null); | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class checks that the IDE is able to correctly convert text to tokens. | |
To run the test, right-click the project node and choose Run Unit Tests. The test should succeed, returning the | |
following result in the JUnit Test Results window: | |
<p><img src="../images/tutorials/mf_syntax/junit-success.png" alt="error result from JUnit test."> | |
<p>You can play with the <tt>testNextToken()</tt> method to see what the IDE does when the entered | |
text does not comply with the specified tokens. For example, change the method by deleting one of the token IDs (<tt>ManifestTokenContext.VALUE</tt>), | |
so that the method looks as follows: | |
<p><pre class="examplecode">public void testNextToken() { | |
doParse("Manifest-Version: 1.0", new TokenID[] { | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
}); | |
}</pre> | |
<p>Now there are more tokens than token IDs. (There are two token IDs here—<tt>ManifestTokenContext.NAME</tt> and <tt>ManifestTokenContext.COLON</tt>.) When you run the JUnit test, the message 'More tokens returned than expected.' is returned: | |
<p><img src="../images/tutorials/mf_syntax/junit-more-tokens-than-expected.png" alt="error result from JUnit test."> | |
<p>Now change the method by deleting the colon between <tt>Manifest-Version</tt> and <tt>1.0</tt>, as shown below: | |
<p><pre class="examplecode">public void testNextToken() { | |
doParse("Manifest-Version 1.0", new TokenID[] { | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
ManifestTokenContext.VALUE, | |
}); | |
}</pre> | |
<p>Now there are too few tokens. When you run the JUnit test, the message 'More tokens expected than returned.' is returned: | |
<p><img src="../images/tutorials/mf_syntax/junit-more-tokens-than-returned.png" alt="error result from JUnit test."> | |
<p>Finally, let's test to see that the IDE understands more than just when there are too many or | |
too few tokens—it should also know when a token is in the wrong place. Add the token | |
that specifies the end-of-line. For example, here <tt>\n</tt> is added right after the name and | |
before the colon: | |
<p><pre class="examplecode">public void testNextToken() { | |
doParse("Manifest-Version\n:1.0", new TokenID[] { | |
ManifestTokenContext.NAME, | |
ManifestTokenContext.COLON, | |
ManifestTokenContext.VALUE, | |
}); | |
}</pre> | |
<p>When you run the test, the following error is returned: | |
<p><img src="../images/tutorials/mf_syntax/junit-wrong-token.png" alt="error result from JUnit test."> | |
<p>Now that we know that the IDE correctly converts manifest entries into tokens, lets create an editor | |
to work with Manifest files and associate colors with tokens. | |
</ol> | |
<h3 class="tutorial"><a name="editorkitting"></a>Creating the EditorKit</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
and type <tt>ManifestEditorKit</tt> in Class Name. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport; | |
import javax.swing.text.Document; | |
import org.netbeans.editor.BaseDocument; | |
import org.netbeans.editor.Syntax; | |
import org.netbeans.editor.SyntaxSupport; | |
import org.netbeans.modules.editor.NbEditorKit; | |
import org.openide.ErrorManager; | |
public class ManifestEditorKit extends <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/NbEditorKit.html">NbEditorKit</a> { | |
public static final String MIME_TYPE = "text/x-java-jar-manifest"; // NOI18N | |
/** | |
* Creates a new instance of ManifestEditorKit | |
*/ | |
public ManifestEditorKit() { | |
} | |
/** | |
* Create a syntax object suitable for highlighting Manifest file syntax | |
*/ | |
public Syntax createSyntax(Document doc) { | |
return new ManifestSyntax(); | |
} | |
/** | |
* Retrieves the content type for this editor kit | |
*/ | |
public String getContentType() { | |
return MIME_TYPE; | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class specifies an <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/text/EditorKit.html">EditorKit</a> specifically for a NetBeans editor. Therefore, it extends the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/NbEditorKit.html">NBEditorKit</a> class. An editor kit establishes the set of things needed by a text | |
component to be a reasonably functioning editor for some type of text content. In this case, the editor is for | |
content that uses the <tt>text/x-java-jar-manifest</tt> MIME Type. | |
</ol> | |
<h3 class="tutorial"><a name="syntaxcoloring"></a>Creating the Syntax Coloring</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
and type <tt>ManifestSettingsInitializer</tt> in Class Name. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport; | |
import java.awt.Color; | |
import java.awt.Font; | |
import java.util.Map; | |
import org.netbeans.editor.BaseKit; | |
import org.netbeans.editor.Coloring; | |
import org.netbeans.editor.Settings; | |
import org.netbeans.editor.SettingsDefaults; | |
import org.netbeans.editor.SettingsNames; | |
import org.netbeans.editor.SettingsUtil; | |
import org.netbeans.editor.TokenCategory; | |
import org.netbeans.editor.TokenContext; | |
import org.netbeans.editor.TokenContextPath; | |
public class ManifestSettingsInitializer | |
extends Settings.AbstractInitializer { | |
public static final String NAME = | |
"manifest-settings-initializer"; // NOI18N | |
/** | |
* Constructor | |
*/ | |
public ManifestSettingsInitializer() { | |
super(NAME); | |
} | |
/** | |
* Update map filled with the settings. | |
* @param kitClass kit class for which the settings are being updated. | |
* It is always non-null value. | |
* @param settingsMap map holding [setting-name, setting-value] pairs. | |
* The map can be empty if this is the first initializer | |
* that updates it or if no previous initializers updated it. | |
*/ | |
public void updateSettingsMap(Class kitClass, Map settingsMap) { | |
if (kitClass == BaseKit.class) { | |
new ManifestTokenColoringInitializer(). | |
updateSettingsMap(kitClass, settingsMap); | |
} | |
if (kitClass == ManifestEditorKit.class) { | |
SettingsUtil.updateListSetting( | |
settingsMap, | |
SettingsNames.TOKEN_CONTEXT_LIST, | |
new TokenContext[] | |
{ ManifestTokenContext.context } | |
); | |
} | |
} | |
/** | |
* Class for adding syntax coloring to the editor | |
*/ | |
/** Properties token coloring initializer. */ | |
private static class ManifestTokenColoringInitializer | |
extends SettingsUtil.TokenColoringInitializer { | |
/** Bold font. */ | |
private static final Font boldFont = | |
SettingsDefaults.defaultFont.deriveFont(Font.BOLD); | |
/** Italic font. */ | |
private static final Font italicFont = | |
SettingsDefaults.defaultFont.deriveFont(Font.ITALIC); | |
/** Key coloring. */ | |
private static final Coloring keyColoring = | |
new Coloring(boldFont, Coloring.FONT_MODE_APPLY_STYLE, | |
Color.blue, null); | |
/** Value coloring. */ | |
private static final Coloring valueColoring = | |
new Coloring(null, Color.magenta, null); | |
/** Colon coloring. */ | |
private static final Coloring colonColoring = | |
new Coloring(null, Color.DARK_GRAY, null); | |
/** Empty coloring. */ | |
private static final Coloring emptyColoring = | |
new Coloring(null, null, null); | |
/** Constructs <code>PropertiesTokenColoringInitializer</code>. */ | |
public ManifestTokenColoringInitializer() { | |
super(ManifestTokenContext.context); | |
} | |
/** Gets token coloring. */ | |
public Object getTokenColoring(TokenContextPath tokenContextPath, | |
TokenCategory tokenIDOrCategory, boolean printingSet) { | |
if(!printingSet) { | |
int tokenID = tokenIDOrCategory.getNumericID(); | |
if(tokenID == ManifestTokenContext.NAME_ID) { | |
return keyColoring; | |
} else if(tokenID == ManifestTokenContext.VALUE_ID) { | |
return valueColoring; | |
} else if(tokenID == ManifestTokenContext.COLON_ID) { | |
return colonColoring; | |
} | |
} else { // printing set | |
return SettingsUtil.defaultPrintColoringEvaluator; | |
} | |
return null; | |
} | |
} // End of class ManifestTokenColoringInitializer. | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class sets the default colors for our tokens. Thanks to the supporting files | |
described in the following sections, the user will be able to | |
use the Options window to change the defaults. | |
</ol> | |
<h3 class="tutorial"><a name="colorrestoring"></a>Creating the Color Restorer</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
and type <tt>RestoreColoring </tt> in Class Name. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport; | |
import org.netbeans.editor.LocaleSupport; | |
import org.netbeans.editor.Settings; | |
import org.openide.modules.ModuleInstall; | |
import org.openide.util.NbBundle; | |
public class RestoreColoring extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/ModuleInstall.html">ModuleInstall</a> { | |
/** | |
* <code>Localizer</code> passed to editor. | |
*/ | |
private static LocaleSupport.Localizer localizer; | |
/** | |
* Registers properties editor, installs options and copies settings. | |
* Overrides superclass method. | |
*/ | |
public void restored() { | |
addInitializer(); | |
installOptions(); | |
} | |
/** | |
* Uninstalls properties options. | |
* And cleans up editor settings copy. | |
* Overrides superclass method. | |
*/ | |
public void uninstalled() { | |
uninstallOptions(); | |
} | |
/** | |
* Adds initializer and registers editor kit. | |
*/ | |
public void addInitializer() { | |
Settings.addInitializer(new ManifestSettingsInitializer()); | |
} | |
/** | |
* Installs properties editor and print options. | |
*/ | |
public void installOptions() { | |
// Adds localizer. | |
LocaleSupport.addLocalizer(localizer = new LocaleSupport.Localizer() { | |
public String getString(String key) { | |
return NbBundle.getMessage(RestoreColoring.class, key); | |
} | |
}); | |
} | |
/** Uninstalls properties editor and print options. */ | |
public void uninstallOptions() { | |
// remove localizer | |
LocaleSupport.removeLocalizer(localizer); | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class is used to install the module and maintain its state. In addition to creating it, | |
you must specify this class in the module's manifest file, by adding the following line: | |
<p><pre class="examplecode">OpenIDE-Module-Install: org/netbeans/modules/manifestsupport/RestoreColoring.class</pre><p> | |
<p>Note that the <tt>OpenIDE-Module-Install</tt> key belongs at the end of the first section (it is highlighted in bold below): | |
<p><pre class="examplecode">Manifest-Version: 1.0 | |
OpenIDE-Module: org.netbeans.modules.manifestsupport | |
OpenIDE-Module-Layer: org/netbeans/modules/manifestsupport/layer.xml | |
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/manifestsupport/Bundle.properties | |
OpenIDE-Module-Specification-Version: 1.0 | |
<b>OpenIDE-Module-Install: org/netbeans/modules/manifestsupport/RestoreColoring.class</b> | |
Name: org/netbeans/modules/manifestsupport/dataobject/ManifestDataLoader.class | |
OpenIDE-Module-Class: Loader</pre> | |
</ol> | |
<h2><a name="creatingthemodule"></a>Creating the Supporting Files</h2> | |
<p>In this section, you update the | |
Options window to allow the user to customize the way the tokens are presented | |
in the IDE. Not only the colors, but also the font type and style, and the Manifest editor itself, can then | |
be modified by the user in the Options window. | |
<div class="indent"> | |
<p><h3 class="tutorial"><a name="creatingoptions"></a>Creating the Options</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Right-click the <tt>ManifestSupport</tt> project node, choose New > Java Class, | |
type <tt>ManifestOptions</tt> in Class Name, and type <tt>org.netbeans.modules.manifestsupport.options</tt> | |
in Package. Click Finish. The new Java class opens in the Source Editor. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport.options; | |
import java.util.MissingResourceException; | |
import org.netbeans.modules.editor.options.BaseOptions; | |
import org.netbeans.modules.manifestsupport.ManifestEditorKit; | |
import org.openide.util.HelpCtx; | |
import org.openide.util.NbBundle; | |
public class ManifestOptions extends BaseOptions { | |
public static String MANIFEST = "Manifest"; // NOI18N | |
/** Name of property. */ | |
private static final String HELP_ID = "editing.editor.mf"; // NOI18N | |
//no manifest specific options at this time | |
static final String[] MF_PROP_NAMES = new String[] {}; | |
public ManifestOptions() { | |
super(ManifestEditorKit.class, MANIFEST); | |
} | |
/** | |
* Gets the help ID | |
*/ | |
public HelpCtx getHelpCtx() { | |
return new HelpCtx(HELP_ID); | |
} | |
/** | |
* Look up a resource bundle message, if it is not found locally defer to | |
* the super implementation | |
*/ | |
protected String getString(String key) { | |
try { | |
return NbBundle.getMessage(ManifestOptions.class, key); | |
} catch (MissingResourceException e) { | |
return super.getString(key); | |
} | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class registers the <tt>ManifestEditorKit</tt> in the | |
Options window. If there were properties specific to the Manifest Editor, they would be added in | |
the <tt>static final String[] MF_PROP_NAMES = new String[] {};</tt> declaration. However, in this | |
implementation, only the default options will be supported. In addition, this file adds the string 'Manifest' to the drop-down list in the Code Templates | |
page of the Editor section, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-2.png" alt="Fonts and Colors 2"> | |
</ol> | |
<h3 class="tutorial"><a name="dipslayingoptionsinoptionswindow"></a>Displaying the Options in the Options Window</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Create the <tt>ManifestOptionsBeanInfo</tt> file and add it | |
to the <tt>org.netbeans.modules.manifestsupport.options</tt> package. | |
Replace the default code with the following: | |
<pre class=examplecode>package org.netbeans.modules.manifestsupport.options; | |
import java.util.MissingResourceException; | |
import org.netbeans.modules.editor.options.BaseOptionsBeanInfo; | |
import org.netbeans.modules.editor.options.OptionSupport; | |
import org.openide.util.NbBundle; | |
public class ManifestOptionsBeanInfo extends BaseOptionsBeanInfo { | |
/** | |
* Constructor. The parameter in the superclass constructor is the | |
* icon prefix. | |
*/ | |
public ManifestOptionsBeanInfo() { | |
super("/org/netbeans/modules/manifestsupport/options/mfOptions"); // NOI18N | |
} | |
/* | |
* Gets the property names after merging it with the set of properties | |
* available from the BaseOptions from the editor module. | |
*/ | |
protected String[] getPropNames() { | |
return OptionSupport.mergeStringArrays( | |
super.getPropNames(), | |
ManifestOptions.MF_PROP_NAMES); | |
} | |
/** | |
* Get the class described by this bean info | |
*/ | |
protected Class getBeanClass() { | |
return ManifestOptions.class; | |
} | |
/** | |
* Look up a resource bundle message, if it is not found locally defer to | |
* the super implementation | |
*/ | |
protected String getString(String key) { | |
try { | |
return NbBundle.getMessage(ManifestOptionsBeanInfo.class, key); | |
} catch (MissingResourceException e) { | |
return super.getString(key); | |
} | |
} | |
}</pre></li> | |
<p><li><b>Understand the file.</b> This Java class displays the options specified | |
in <tt>ManifestOptions</tt> in the Options window. The file referenced in the constructor | |
can be any 16x16 pixel file. If you do not have one, you can get it from the downloadable | |
ZIP file at the top of the page or you can right-click and save it here: <img src="../images/tutorials/mf_syntax/mfOptions.gif" alt="mfOptions"> | |
<p>Add a <tt>Bundle.properties</tt> file to the <tt>org.netbeans.modules.manifestsupport.options</tt> | |
package and add this line to it: | |
<p><pre class="examplecode">OPTIONS_Manifest=Manifest Editor</pre> | |
<p>The string after the "OPTIONS_" above <b>must</b> match the String declaration in the | |
<tt>ManifestOptions</tt> class. For example, in this tutorial, the following string is declared in | |
<tt>ManifestOptions.java</tt>: | |
<p><pre class="examplecode">public static String MANIFEST = "Manifest";</pre> | |
<p>However, if this line was as follows: | |
<p><pre class="examplecode">public static String MANIFEST = "MF";</pre> | |
Then the <tt>Bundle.properties</tt> file would specify this string instead: | |
<p><pre class="examplecode">OPTIONS_MF=Manifest Editor</pre> | |
<p>Note also that the string is case-sensitive. | |
<p>Now this is the label that will be displayed in the Classic View of the Options window, to | |
distinguish the Manifest Editor section from the other editors displayed in the Classic View of the Options window, as shown below: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-3.png" alt="Fonts and Colors 3"> | |
<p>Notice that there is an icon to the left of the label 'Manifest Editor' in the screenshot above. This is | |
the <tt>mfOptions.gif</tt> file specified in the <tt>ManifestOptionsBeanInfo </tt> class. | |
</ol> | |
<h3 class="tutorial"><a name="instantiating"></a>Instantiating the Options</h3> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Create the file.</b> Create an XML file called <tt>ManifestOptions.settings</tt> | |
and place it in the <tt>org.netbeans.modules.manifestsupport.options</tt> package. | |
Replace the default code with the following: | |
<pre class=examplecode><?xml version="1.0"?> | |
<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" | |
"https://netbeans.org/dtds/sessionsettings-1_0.dtd"> | |
<settings version="1.0"> | |
<module name="org.netbeans.modules.manifestsupport"/> | |
<instanceof class="java.io.Externalizable"/> | |
<instanceof class="org.openide.util.SharedClassObject"/> | |
<instanceof class="java.beans.beancontext.BeanContextProxy"/> | |
<instanceof class="java.io.Serializable"/> | |
<instanceof class="org.openide.options.SystemOption"/> | |
<instanceof class="org.netbeans.modules.editor.options.OptionSupport"/> | |
<instanceof class="org.netbeans.modules.editor.options.BaseOptions"/> | |
<instance class="org.netbeans.modules.manifestsupport.options.ManifestOptions"/> | |
</settings></pre></li> | |
<p><li><b>Understand the file.</b> This file lets the IDE quickly instantiate the <tt>ManifestOptions.java</tt> | |
file, whenever called upon to do so. The next section shows you how to register the settings file in the | |
NetBeans System Filesystem. | |
</ol> | |
<h3 class="tutorial"><a name="registeringoptions"></a>Registering the Options in the NetBeans System Filesystem</h3> | |
<p>To register the module in the Options window, you | |
must do the following in the <tt>layer.xml</tt> file: | |
<ul> | |
<li>Create default colors for each profile that the IDE supports. Currently, the IDE supports a profile | |
called 'NetBeans' and a profile called 'City Lights'. They can be selected from the Profile drop-down list | |
at the top of the Fonts & Colors section. | |
<li>Register the <tt>ManifestEditorKit.java</tt> class. | |
<li>Register the <tt>ManifestOptions.settings</tt> file. | |
<li>Create a file containing a text that will be shown in the Preview window, | |
at the bottom of the Fonts & Colors section of the Options window. | |
<li>Localize the strings in the <tt>layer.xml</tt> file. | |
</ul> | |
<p>The screenshot on the left shows the NetBeans profile; on the right you see the City Lights profile: | |
<p><img src="../images/tutorials/mf_syntax/fonts-and-colors-1.png" alt="Fonts and Colors 1"> | |
<img src="../images/tutorials/mf_syntax/fonts-and-colors-4.png" alt="Fonts and Colors 4"> | |
<p>Do the following: | |
<ol> | |
<p><li><b>Update the <tt>layer.xml</tt> file.</b> Add the following entries to the <tt>layer.xml</tt> file: | |
<pre class=examplecode><folder name="Editors"> | |
<folder name="text"> | |
<folder name="x-java-jar-manifest"> | |
<attr name="SystemFileSystem.localizingBundle" | |
stringvalue="org.netbeans.modules.manifestsupport.Bundle"/> | |
<folder name="NetBeans"> | |
<folder name="Defaults"> | |
<file name="coloring.xml" | |
url="resources/NetBeans-Manifest-fontsColors.xml"> | |
<attr name="SystemFileSystem.localizingBundle" | |
stringvalue="org.netbeans.modules.manifestsupport.Bundle"/> | |
</file> | |
</folder> | |
</folder> | |
<folder name="CityLights"> | |
<folder name="Defaults"> | |
<file name="coloring.xml" | |
url="resources/CityLights-Properties-fontsColors.xml"> | |
<attr name="SystemFileSystem.localizingBundle" | |
stringvalue="org.netbeans.modules.manifestsupport.Bundle"/> | |
</file> | |
</folder> | |
</folder> | |
<file name="Settings.settings" | |
url="options/ManifestOptions.settings"/> | |
<file name="EditorKit.instance"> | |
<attr name="instanceClass" | |
stringvalue="org.netbeans.modules.manifestsupport.ManifestEditorKit"/> | |
</file> | |
</folder> | |
</folder> | |
</folder> | |
<folder name="OptionsDialog"> | |
<folder name="PreviewExamples"> | |
<folder name="text"> | |
<file name="x-java-jar-manifest" url="resources/ManifestExample"/> | |
</folder> | |
</folder> | |
</folder></pre></li> | |
<p><li><b>Localize the Fonts & Colors page.</b> In the package where the <tt>layer.xml</tt> file | |
is found (i.e., in <tt>org.netbeans.modules.manifestsupport</tt>), add the following entries | |
to the <tt>Bundle.properties</tt> file: | |
<p><pre class="examplecode">text/x-java-jar-manifest=Manifest | |
NetBeans=NetBeans | |
mf-name=Name | |
mf-value=Value | |
mf-colon=Colon</pre> | |
<p><li><b>Create a color file for each profile.</b> Create a package called <tt>org.netbeans.modules.manifestsupport.resources</tt> | |
and add two files, <tt>NetBeans-Manifest-fontsColors.xml</tt> and <tt>CityLights-Properties-fontsColors.xml</tt>: | |
<ul><p><li><tt>NetBeans-Manifest-fontsColors.xml</tt> has the following content: | |
<p><pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | |
<fontscolors> | |
<fontcolor name="mf-name" foreColor="blue" default="default"/> | |
<fontcolor name="mf-value" foreColor="magenta" default="default"/> | |
<fontcolor name="mf-colon" default="default"/> | |
</fontscolors></pre> | |
<p><li><tt>CityLights-Properties-fontsColors.xml</tt> has the following content: | |
<pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | |
<fontscolors> | |
<fontcolor name="mf-name" default="default"/> | |
<fontcolor name="mf-value" default="default"/> | |
<fontcolor name="mf-colon" default="default"/> | |
</fontscolors></pre></ul> | |
<p><li><b>Create the Preview file.</b> At the bottom of the Fonts & Colors section in the Options window, | |
the user can preview changes made to the way the Manifest file's entries are displayed in the editor. | |
To specify the text that is displayed in the preview window, you need to create a file, as | |
specified in the <tt>OptionsDialog</tt> folder of the <tt>layer.xml</tt> file above. | |
In the <tt>org.netbeans.modules.manifestsupport.resources</tt> package, | |
add a file called <tt>ManifestExample</tt> (note that this file has no extension), with the following content: | |
<p><pre class="examplecode">Manifest-Version: 1.0</pre> | |
</ol> | |
<h2><a name="building"></a>Building and Installing the Module</h2> | |
<p>The IDE uses an Ant build script to build and install your module. The build script is created for you | |
when you create the module project.</p> | |
<div class="indent"> | |
<h3 class="tutorial">Installing and Testing the NetBeans Module</h3> | |
<p> | |
<ol> | |
<li>In the Projects window, right-click the <tt>ManifestSupport</tt> project and choose Install/Reload | |
in Target Platform. | |
<p>The module is built and installed in the target IDE or Platform. The target IDE or Platform opens so that you | |
can try out your new module. The default target IDE or Platform is the | |
installation used by the current instance of the development IDE. Note that when you run your module, you will be using | |
a temporary test user directory, not the development IDE's user directory. | |
<li>Choose File > New Project (Ctrl-Shift-N). Create a new Java application project | |
or a new Plug-in Module project. Open the project's Manifest file in the Source Editor | |
and notice the syntax highlighting. <p>For other aspects of this module, see the <a href="#introducing-sample">Introducing the Sample</a> section. | |
</ol> <p> | |
<h3 class="tutorial">Creating a Shareable Module Binary (NBM File)</h3> | |
<p>An NBM file is a NetBeans module packaged for delivery via the web. | |
The principal differences between NBM files and module JAR files are: | |
<ul><li>An NBM file is compressed. | |
<li>An NBM file can contain more than one JAR file—modules can package any libraries they use into their NBM file. | |
<li>An NBM file contains metadata that NetBeans will use to display information about it in the Update Center, such as the manifest contents, the license, etc. | |
<li>An NBM file is typically signed for security purposes.</ul> | |
<p>NBM files are just ZIP files with a special extension. They use the JDK's mechanism for | |
signing JAR files. Unless you are doing something unusual, you will not need to worry about the | |
contents of an NBM file—just let the standard Ant build script for NBM creation take care of | |
it for you. The IDE generates the build script based on the options you enter in the project's | |
Project Properties dialog box. You can set the module's dependencies, versioning, and packaging | |
information in the Project Properties dialog box. You can further customize program execution | |
by editing the Ant script and Ant properties for the project. | |
<ol> | |
<li>In the Projects window, right-click the <tt>ManifestSupport</tt> project node and choose Create NBM. | |
<p>The NBM file is created and you can view it in the Files window (Ctrl-2): | |
<p align="left"><img src="../images/tutorials/mf_syntax/create-nbm.png" alt="Shareable NBM."> | |
<li>Make it available to others via, for example, e-mail. | |
<p><li>Use the Update Center to install the NBM file. | |
</ol> | |
<h2><a name="explore"></a>Exploring Further</h2> <div class="indent"> | |
<p>Below are some other avenues that you might want to explore.</p> | |
<h3 class="tutorial">Associating the EditorKit with a JEditorPane</h3> | |
<p>Instead of using the EditorKit in the Source Editor, you can associate it | |
with a <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JEditorPane.html">JEditorPane</a>. | |
<p>Do the following: | |
<ol> | |
<p><li>Select the <tt>JEditorPane</tt>, click the <tt>editorKit</tt> property, | |
and make the following selections: | |
<p align="left"><img src="../images/tutorials/mf_syntax/editorPane.png" alt="editorPane."> | |
<p><li>Select the <tt>JEditorPane</tt>, click the <tt>contentType</tt> property, | |
and type the Manifest file's MIME Type (<tt>text/x-java-jar-manifest</tt>): | |
<p align="left"><img src="../images/tutorials/mf_syntax/editorPane2.png" alt="editorPane2."> | |
<p><li>When you deploy the module, syntax highlighting will be enabled in the JEditorPane: | |
<p align="left"><img src="../images/tutorials/mf_syntax/editorPane3.png" alt="editorPane3."> | |
<p>In effect, the JEditorPane is now your editor. You can use the Options window to | |
modify fonts and colors, just as if you were using the Source Editor. | |
</ol> | |
<h3 class="tutorial">Code Folding</h3> | |
<p>To come.</p> | |
<h3 class="tutorial">Indentation Engine</h3> | |
<p>To come.</p> | |
<h3 class="tutorial">Other Options</h3> | |
<p>To come.</p> | |
</div> | |
<br /> | |
<h2><a name="explore"></a>Applying What You Have Learned</h2> <div class="indent"> | |
<p>Once you are comfortable with the principles outlined in this tutorial, | |
you can begin applying them to your own scenarios. For example, here is | |
NetBeans user Valentin Buergel's Wiki syntax highlighting:</p> | |
<p align="left"><img src="../images/tutorials/mf_syntax/wiki-screenshot.png" alt="wiki-screenshot"> | |
</div> | |
<br /> | |
<!-- ===================================================================================== --> | |
<br> | |
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Manifest%20Highlighting%20Module%20Tutorial">Send Us Your Feedback</a></div> | |
<br style="clear:both;" /> | |
<!-- ======================================================================================== --> | |
<h2><a name="nextsteps"></a>Next Steps</h2> | |
<p>For more information about creating and developing NetBeans Module, see the following resources: | |
<ul> | |
<p><li><a href="https://platform.netbeans.org/index.html">Module Developer's Resources</a></li> | |
<p><li><a href="https://netbeans.org/download/dev/javadoc/">NetBeans API List (Current Development Version)</a></li> | |
<p><li><a href="http://apisupport.netbeans.org/new-apisupport.html">New API Support-Proposal</a></li></ul> | |
</p> | |
<hr> | |
<!-- ======================================================================================== --> | |
<h2><a name="version"></a>Versioning </h2> | |
<p> | |
<table width="76%" border="1"> | |
<tbody> | |
<tr> | |
<td> | |
<div align="left"><b>Version</b></div> | |
</td> | |
<td> | |
<div align="left"><b>Date</b></div> | |
</td> | |
<td> | |
<div align="left"><b>Changes</b></div> | |
</td> | |
<tr> | |
<td> | |
1 | |
</td> | |
<td> | |
23 October 2005 | |
</td> | |
<td><ul> | |
<li>Initial version. | |
</td> | |
</tr> | |
<tr> | |
<td> | |
2 | |
</td> | |
<td> | |
30 November 2005 | |
</td> | |
<td><ul> | |
<li>Added Valentin's screenshot at the end. | |
<li>Fixed some smaller issues: | |
<ul><li><a href="https://netbeans.org/bugzilla/show_bug.cgi?id=69568">issue 69568</a> | |
<li>Wrong closing tag in one of the coloring XML files. | |
<li><tt>NbEditorKit</tt> was mistakenly <tt>NBEditorkit</tt> before | |
</ul> | |
<li>Need to fix several larger issues (from Andrei Badea and one or two people from openide mailing list) | |
soon. | |
</td> | |
</tr> | |
<tr> | |
<td> | |
3 | |
</td> | |
<td> | |
5 March 2006 | |
</td> | |
<td><ul> | |
<li>Several fixes: | |
<ul><li>Successfully worked through the whole tutorial, using NetBeans IDE 5.x (final version). | |
<li>Added new test (from Andrei Badea) to assert new line parsing is working. | |
<li>Fixed layer.xml error relating to new way of registering the preview file. | |
<li>Tried to use Andrei Badea (and Vladimir) fixes for manifestSyntax,java, but that broke other things. | |
Need to check that with him. | |
</ul> | |
</td> | |
</tr> | |
<tr> | |
<td> | |
4 | |
</td> | |
<td> | |
13 June 2006 | |
</td> | |
<td><ul> | |
<li>Took the ZIP attached to this tutorial, installed the NBM in 5.5 dev. No | |
problems, worked as expected, except JUnit test had problems -- no junit.framework.test | |
found in JUnit module.</li> | |
<li>Following suggestion by Tim B., shortened many lines of code to ensure that | |
people don't need to scroll to the right too much, but some instances of this problem | |
remain.</li> | |
<li>Need to go back to the code snippets and put back links to Javadoc, which | |
were removed when I replaced the code, straight from the Source Editor, which I | |
did to make sure that the shortened lines wouldn't cause errors.</li> | |
<li>Need to change the ZIP file to match the changes made in previous versions of the | |
tutorial.</li> | |
<li>Need to integrate the Module Installer wizard, no need to manually create | |
one (plus automatic manifest.mf and project.xml change).</li> | |
</ul> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<p>Many thanks to Andrei Badea, Tom Ball, and Martin Adamek for help and inspiration. | |
</body> | |
</html> |