本教程向您介绍如何通过添加 Manifest 文件的高亮显示语法来改进 IDE。在本教程的结尾您将拥有一个可以与其他人共享的 NetBeans 插件模块文件 (NBM)。当通过 NetBeans Update Center 安装时,manifest 条目的“name”、“colon”和“value”将具有不同的颜色,如下所示:
此外,您可以使用 Options 窗口修改颜色。
本教程将介绍以下主题:
安装完软件之后,本教程可以在 60 分钟之内完成。
有关创建 NetBeans 插件模块的更多信息,请参见 NetBeans 网站上的 NetBeans Development Project 主页。如果有问题,请访问 NetBeans Developer FAQ 或使用本页顶部的反馈链接。
开始编写插件模块之前,必须确保您具备所有必要的软件。此外,您可能想在亲自构建之前使用示例。
开始之前,需要在您的计算机上安装以下软件:
采用以下步骤来安装示例:
您已经了解了 Manifest Support 插件模块的界面外观,现在让我们快速浏览一下每个源文件的作用。
Manifest Support 示例由主文件和支持文件组成。
主文件。 模块的主文件位于 org.netbeans.modules.manifestsupport 包中:
文件
|
描述
|
Bundle.properties | 本地化信息。 |
ManifestEditorKit.java | 扩展 NbEditorKit 类。 |
ManifestSettingsInitializer.java | 扩展 Settings.AbstractInitializer 类。包含扩展 SettingsUtil.TokenColoringInitializer 类的内部类。 |
ManifestSyntax.java | 扩展 Syntax 类。 |
ManifestTokenContext.java | 扩展 TokenContext 类。 |
RestoreColoring.java | 扩展 ModuleInstall 类。 |
layer.xml | 这是 NetBeans System Filesystem 配置文件它在 NetBeans System Filesystem 中注册以下信息:
|
支持文件。
数据对象文件。 使 Manifest 文件区别于其他文件的模块的文件位于 org.netbeans.modules.manifestsupport.dataobject 包中:
有关这些文件的详细信息,请参阅 NetBeans DataLoader 模块教程。
Options 窗口文件。 在 Options 窗口中安装信息的模块文件位于 org.netbeans.modules.manifestsupport.options 包中:
文件
|
描述
|
Bundle.properties | 本地化信息。 |
ManifestOptions.java | 扩展 BaseOptions 类。 |
ManifestOptions.settings | Options 窗口的实例化数据。 |
ManifestOptionsBeanInfo.java | 扩展 BaseOptionsBeanInfo 类。 |
mfOptions.gif | 在 Options 窗口的 Classic View 的 Manifest Editor 节点中显示的 GIF 文件。 |
资源。 模块的资源位于 org.netbeans.modules.manifestsupport.resources 包和 Unit Test Packages 节点中:
文件
|
描述
|
CityLights-Properties-fontsColors.xml | Options 窗口的 Fonts & Colors 页面中 CityLights 配置文件的颜色。 |
ManifestExample | 在 Options 窗口的 Fonts & Colors 页面中使用的示例。 |
NetBeans-Manifest-fontsColors.xml | Options 窗口的 Fonts & Colors 页面中 NetBeans 配置文件的颜色。 |
ManifestSyntaxTest.java | 用于测试 Manifest 文件标记的 JUnit 测试。 |
重要文件。 Projects 窗口通常用于显示项目的包。但是,为了简化在项目中使用一些更重要的文件,您可以通过 Important Files 节点访问它们:
有关每个 Important Files 的基本信息,请参阅 NetBeans 插件模块的快速入门指南。
开始编写模块前,必须确保正确地设置了项目。NetBeans IDE 5.0 提供一个向导,用于设置模块所需的所有基本文件。
IDE 创建 ManifestSupport 项目。该项目包含所有资源和项目元数据,如该项目的 Ant 构建脚本。该项目在 IDE 中打开。您可以在 Projects 窗口 (Ctrl-1) 中查看其逻辑结构,在 Files 窗口 (Ctrl-2) 中查看其文件结构。
您需要将几个属于 NetBeans API 的类设为子类。每个类都将被声明为 Module 依存关系。使用 Project Properties 对话框来执行此操作。
现在应该看到下图:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://www.netbeans.org/ns/project/1"> <type>org.netbeans.modules.apisupport.project</type> <configuration> <data xmlns="http://www.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>
创建模块首先要确保 IDE 识别 Manifest 文件。默认情况下,它不识别它们,因此将它们视为文本文件。进行下一步前仔细通读 NetBeans DataLoader 模块教程,确保将您所创建的文件放置在名为 org.netbeans.modules.manifestsupport.dataobject 的包中。继续深入本教程之前,IDE 应该能够识别 Manifest 文件。在 NetBeans DataLoader 模块教程的结尾,您还应该拥有一个新的 MIME Type:text/x-java-jar-manifest。整个教程通篇都使用 MIME Type。
您拥有专门用于 Manifest 文件的数据加载程序之后,需要在您希望 IDE 能够区分彼此的 Manifest 文件中标识这些项。每个不同的项称为一个标记。创建标记之后,您需要告诉 IDE 如何解释它找到的文本,需要告诉它哪些文本由哪些标记组成。换句话说就是您需要创建语法。接下来,您用颜色使这些标记相关联。在这个过程中,您创建特定于 Manifest 文件的编辑器。
执行以下操作:
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 */ public ManifestTokenContext() { super("mf-"); try { addDeclaredTokenIDs(); } catch (Exception e) { Utilities.annotateLoggable(e); } } }
执行以下操作:
package org.netbeans.modules.manifestsupport; import org.netbeans.editor.Syntax; import org.netbeans.editor.TokenID; import org.openide.ErrorManager; public class ManifestSyntax extends Syntax { private static final int ISI_NAME = 1; private static final int ISA_CR = 2; private static final int ISA_LF = 3; private static final int ISA_CRLF = 4; private static final int ISA_AFTER_NAME = 6; private static final int ISA_COLON = 7; private static final int ISA_AFTER_COLON = 8; private static final int ISI_VALUE = 9; /** Creates a new instance of ManifestSyntax */ public ManifestSyntax() { tokenContextPath = ManifestTokenContext.contextPath; } protected TokenID parseToken() { TokenID result = doParseToken(); 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; case '/r': state = ISA_CR; break; default: state = ISI_NAME; } break; case ISI_NAME: switch (actChar) { case ':': case '/r': case '/n': state = ISA_AFTER_NAME; return ManifestTokenContext.NAME; } break; case ISA_CR: if (actChar == '/n') { offset++; } state = INIT; return ManifestTokenContext.END_OF_LINE; 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; case '/r': state = ISA_CR; break; default: assert false; } break; case ISA_AFTER_COLON: switch (actChar) { case '/n': state = INIT; offset++; return ManifestTokenContext.END_OF_LINE; case '/r': state = ISA_CR; break; default: state = ISI_VALUE; } break; case ISI_VALUE: switch (actChar) { case '/r': case '/n': state = INIT; return ManifestTokenContext.VALUE; } break; } offset++; } switch (state) { case ISI_NAME: state = INIT; return ManifestTokenContext.NAME; case ISI_VALUE: state = INIT; return ManifestTokenContext.VALUE; } return null; } }
例如,对于名称,IDE 从初始状态开始,首先它遇到了名称的有效字符,然后又进入 ISI_NAME 状态。它一直保持该状态,直到它遇到了一个 /r、/n 或 :字符,这些字符不属于名称。当它遇到这样一个字符时,IDE 知道它刚刚经过的这个字符由名称标记组成。代码在 while 循环中运行。结尾处有一个中断状态,它增加了文本的偏移量。该代码中的返回状态避免增加偏距,并且确保分析名称之后将以这个字符(它可能是一个冒号,这是自身有意义的标记)开始的下一个标记。另一方面,中断状态确保增加偏移量。当所有靠近冒号的字符都测试过之后,IDE 知道光标是否位于名称内部。
执行以下操作:
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.*; public class ManifestSyntaxTest extends TestCase { public ManifestSyntaxTest(String testName) { super(testName); } public void testNextToken() { doParse("Manifest-Version: 1.0", Arrays.asList(new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, ManifestTokenContext.VALUE, })); } public void doParse(String m, List expected) { Syntax s = new ManifestSyntax(); s.load(null, m.toCharArray(), 0, m.length(), true, m.length()); TokenID token = null; Iterator i = 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); } }
您可以使用 testNextToken() 方法查看当输入的文本与指定的标记不相符时 IDE 执行的操作。例如,通过删除一个标记 ID (ManifestTokenContext.VALUE) 更改方法,于是该方法如下:
public void testNextToken() { doParse("Manifest-Version: 1.0", Arrays.asList(new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, })); }
现在标记比标记 ID 多。(此处有两个标记 ID—ManifestTokenContext.NAME 和 ManifestTokenContext.COLON。)当您运行 JUnit 测试时,返回消息“More tokens returned than expected。”:
现在通过删除 Manifest-Version 和 1.0 之间的冒号更改方法,如下所示:
public void testNextToken() { doParse("Manifest-Version 1.0", Arrays.asList(new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, ManifestTokenContext.VALUE, })); }
现在标记太少了。当您运行 JUnit 测试时,返回消息“More tokens expected than returned。”:
最后,让我们测试看看当有过多或太少的标记时 IDE 的理解—它应该也能知道标记是否放错了位置。添加指定行结束的标记。例如,此处在名称之后和冒号之前添加 /n:
public void testNextToken() { doParse("Manifest-Version/n:1.0", Arrays.asList(new TokenID[] { ManifestTokenContext.NAME, ManifestTokenContext.COLON, ManifestTokenContext.VALUE, })); }
当您运行测试时,返回以下错误:
现在我们知道了 IDE 将 manifest 条目正确地转换为标记,接下来我们创建一个编辑器来使用 Manifest 文件并使颜色与标记相关联。
执行以下操作:
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; } }
执行以下操作:
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.
}
执行以下操作:
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
注意,OpenIDE-Module-Install 键属于第一部分的结尾部分(它在下面用粗体高亮显示):
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
在本部分中,您更新 Options 窗口以允许用户自定义在 IDE 中表示标记的方法。用户在 Options 窗口中不仅仅可以更改颜色,而且还有字体类型和样式以及 Manifest 编辑器本身。
执行以下操作:
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); } } }
执行以下操作:
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); } } }
将 Bundle.properties 文件添加到 org.netbeans.modules.manifestsupport.options 包中并向它添加该行:
OPTIONS_Manifest=Manifest Editor
上面“OPTIONS_”之后的字符串必须与 ManifestOptions 类中的 String 声明相匹配。例如,在本教程中,在 ManifestOptions.java 中声明以下字符串:
public static String MANIFEST = "Manifest";
但是,如果该行如下:
public static String MANIFEST = "MF";则 Bundle.properties 文件将指定该字符串:
OPTIONS_MF=Manifest Editor
还要注意该字符串区分大小写。
现在这是一个标签,将显示在 Options 窗口的 Classic View 中,以区分 Manifest Editor 部分和 Options 窗口的 Classic View 中显示的其他编辑器,如下所示:
注意,在上面的屏幕截图中“Manifest Editor”标签左侧有一个图标。这是在 ManifestOptionsBeanInfo 类中指定的 mfOptions.gif 文件。
执行以下操作:
<?xml version="1.0"?> <!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.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>
要在 Options 窗口中注册模块,您必须在 layer.xml 文件中执行以下操作:
左侧的屏幕截图显示 NetBeans 配置文件,右侧的屏幕截图显示 City Lights 配置文件:
执行以下操作:
<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"> <file name="ManifestExample" url="resources/ManifestExample"/> </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
注意: 在 layer.xml 文件中,Preview 文件的名称为 localized-mimetypeExample。由于本地化的 MIME Type 为“Manifest”(如本部分的第二步所指定),上面的 layer.xml 文件注册 Preview 文件如下:
<folder name="OptionsDialog"> <folder name="PreviewExamples"> <file name="ManifestExample" url="resources/ManifestExample"/> </folder> </folder>
因此,如果本地化的 MIME Type 包含空格,如“Jackpot Rules”,则在 layer.xml 中的注册将为:
<folder name="OptionsDialog"> <folder name="PreviewExamples"> <file name="Jackpot RulesExample" url="resources/RulesExample"/> </folder> </folder>
IDE 使用 Ant 构建脚本来构建和安装您的模块。构建脚本是创建模块项目时为您创建的。
模块即在目标 IDE 或平台中构建和安装。目标 IDE 或平台打开,您可以试用新的模块。默认目标 IDE 或平台是由开发 IDE 的当前实例使用的安装平台。注意到当您运行模块时,您将使用临时测试用户目录,而不是开发 IDE 的用户目录。
有关该模块的其他方面,请参阅介绍示例部分。
NBM 文件是一个 NetBeans 模块,该模块已被打包以便通过 Web 发送。NBM 文件和模块 JAR 文件之间的主要差别为:
NBM 文件只是具有特殊扩展名的 ZIP 文件。它们使用 JDK 机理给 JAR 文件签名。除非您正在执行一些不同寻常的操作,否则不需要担心 NBM 文件的内容,只需让 NBM 创建的标准 Ant 构建脚本为您完成所有工作。IDE 根据在 Project Properties 对话框的项目中输入的选项生成构建脚本。您可以在 Project Properties 对话框中设置模块的依存关系、版本控制和打包信息。通过为项目编辑 Ant 脚本和 Ant 属性,您可以进一步自定义程序执行。
将创建 NBM 文件并且可以在 Files 窗口中查看它 (Ctrl-2):
下面是您可能研究的一些其他途径。
代替在 Source Editor 中使用 EditorKit,您可以使它与 JEditorPane 相关联。
执行以下操作:
实际上,现在 JEditorPane 就是您的编辑器。您可以使用 Options 窗口修改字体和颜色,就像您使用 Source Editor 一样。
即将研究。
即将研究。
即将研究。
您熟悉了本教程中介绍的原理之后,您就可以将它们应用到您自己的方案中。例如,此处是 NetBeans 用户 Valentin Buergel 的 Wiki 语法高亮显示: