http://wiki.netbeans.org/How_to_create_support_for_a_new_language
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:
In addition, you will be able to use the Options window to modify the colors.
The following topics are covered in this tutorial:
Once the software is installed, this tutorial can be completed in 60 minutes.
For more information on creating NetBeans plug-in modules, see the NetBeans Development Project home on the NetBeans website. If you have questions, visit the NetBeans Developer FAQ or use the feedback link at the top of this page.
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.
Before you begin, you need to install the following software on your computer:
Take the following steps to install the sample:
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.
The Manifest Support sample consists of main files and supporting files.
Main Files. The module's main files are in the org.netbeans.modules.manifestsupport package:
File
|
Description
|
Bundle.properties | Localization information. |
ManifestEditorKit.java | Extends the NbEditorKit class. |
ManifestSettingsInitializer.java | Extends the Settings.AbstractInitializer class. Includes an inner class than extends the SettingsUtil.TokenColoringInitializer class. |
ManifestSyntax.java | Extends the Syntax class. |
ManifestTokenContext.java | Extends the TokenContext class. |
RestoreColoring.java | Extends the ModuleInstall class. |
layer.xml |
This is the NetBeans System Filesystem configuration file. It registers the
following information in the NetBeans System Filesystem:
|
Supporting Files.
Data Object Files. The module's files that distinguish Manifest files from other files are in the org.netbeans.modules.manifestsupport.dataobject package:
For information on these files, see the NetBeans DataLoader Module Tutorial.
Options Window Files. The module's files that install information in the Options window are in the org.netbeans.modules.manifestsupport.options package:
File
|
Description
|
Bundle.properties | Localization information. |
ManifestOptions.java | Extends the BaseOptions class. |
ManifestOptions.settings | Instantiation data for the Options window. |
ManifestOptionsBeanInfo.java | Extends the BaseOptionsBeanInfo class. |
mfOptions.gif | GIF file displayed in the node for the Manifest Editor in the Classic View of the Options window. |
Resources. The module's resources are in the org.netbeans.modules.manifestsupport.resources package and in the Unit Test Packages node:
File
|
Description
|
CityLights-Properties-fontsColors.xml | Colors for the CityLights profile in the Fonts & Colors page of the Options window. |
ManifestExample | Example used in the Fonts & Colors page of the Options window. |
NetBeans-Manifest-fontsColors.xml | Colors for the NetBeans profile in the Fonts & Colors page of the Options window. |
ManifestSyntaxTest.java | JUnit test for testing the Manifest file's tokens. |
Important Files. 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:
For basic information each of the Important Files, see the Introduction to NetBeans Module Development.
Before you start writing the module, you have to make sure you that your project is set up correctly. NetBeans IDE 5.x provides a wizard that sets up all the basic files needed for a module.
The IDE creates the ManifestSupport 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).
You will need to subclass several classes that belong to NetBeans APIs. Each has to be declared as a Module dependency. Use the Project Properties dialog box for this purpose.
You should now see the following:
<?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>
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 NetBeans DataLoader Module Tutorial before going further—make sure that you put the files you create in a package called org.netbeans.modules.manifestsupport.dataobject. 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: text/x-java-jar-manifest. This MIME Type is used throughout this tutorial.
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 token. 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 syntax. Next, you associate the tokens with colors. In the process, you create an editor specifically for Manifest files.
Do the following:
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 TokenContext { // 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); } } }
Do the following:
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; } }
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 ISI_NAME state. It stays in this state until it encounters a \r, \n or : 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.
Do the following:
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); } }
You can play with the testNextToken() 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 (ManifestTokenContext.VALUE), so that the method looks as follows:
public void testNextToken() { doParse("Manifest-Version: 1.0", new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, }); }
Now there are more tokens than token IDs. (There are two token IDs here—ManifestTokenContext.NAME and ManifestTokenContext.COLON.) When you run the JUnit test, the message 'More tokens returned than expected.' is returned:
Now change the method by deleting the colon between Manifest-Version and 1.0, as shown below:
public void testNextToken() { doParse("Manifest-Version 1.0", new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, ManifestTokenContext.VALUE, }); }
Now there are too few tokens. When you run the JUnit test, the message 'More tokens expected than returned.' is returned:
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 \n is added right after the name and before the colon:
public void testNextToken() { doParse("Manifest-Version\n:1.0", new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, ManifestTokenContext.VALUE, }); }
When you run the test, the following error is returned:
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.
Do the following:
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 NbEditorKit { 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; } }
Do the following:
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 PropertiesTokenColoringInitializer
. */
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.
}
Do the following:
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 ModuleInstall {
/**
* Localizer
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);
}
}
OpenIDE-Module-Install: org/netbeans/modules/manifestsupport/RestoreColoring.class
Note that the OpenIDE-Module-Install key belongs at the end of the first section (it is highlighted in bold below):
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 OpenIDE-Module-Install: org/netbeans/modules/manifestsupport/RestoreColoring.class Name: org/netbeans/modules/manifestsupport/dataobject/ManifestDataLoader.class OpenIDE-Module-Class: Loader
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.
Do the following:
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); } } }
Do the following:
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); } } }
Add a Bundle.properties file to the org.netbeans.modules.manifestsupport.options package and add this line to it:
OPTIONS_Manifest=Manifest Editor
The string after the "OPTIONS_" above must match the String declaration in the ManifestOptions class. For example, in this tutorial, the following string is declared in ManifestOptions.java:
public static String MANIFEST = "Manifest";
However, if this line was as follows:
public static String MANIFEST = "MF";Then the Bundle.properties file would specify this string instead:
OPTIONS_MF=Manifest Editor
Note also that the string is case-sensitive.
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:
Notice that there is an icon to the left of the label 'Manifest Editor' in the screenshot above. This is the mfOptions.gif file specified in the ManifestOptionsBeanInfo class.
Do the following:
<?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>
To register the module in the Options window, you must do the following in the layer.xml file:
The screenshot on the left shows the NetBeans profile; on the right you see the City Lights profile:
Do the following:
<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>
text/x-java-jar-manifest=Manifest NetBeans=NetBeans mf-name=Name mf-value=Value mf-colon=Colon
<?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>
<?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>
Manifest-Version: 1.0
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.
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.
For other aspects of this module, see the Introducing the Sample section.
An NBM file is a NetBeans module packaged for delivery via the web. The principal differences between NBM files and module JAR files are:
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.
The NBM file is created and you can view it in the Files window (Ctrl-2):
Below are some other avenues that you might want to explore.
Instead of using the EditorKit in the Source Editor, you can associate it with a JEditorPane.
Do the following:
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.
To come.
To come.
To come.
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:
For more information about creating and developing NetBeans Module, see the following resources:
Version
|
Date
|
Changes
|
1 | 23 October 2005 |
|
2 | 30 November 2005 |
|
3 | 5 March 2006 |
|
4 | 13 June 2006 |
|
Many thanks to Andrei Badea, Tom Ball, and Martin Adamek for help and inspiration.