站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Netbeans 专题NetBeans Manifest File Syntax Highlighting 模块教程

NetBeans Manifest File Syntax Highlighting 模块教程

摘要: NetBeans Manifest File Syntax Highlighting 模块教程 反馈 请注意, 并不是本教程中介绍的所有 API 都是当前最新的 。在您自己的磁盘上使用它们。不保证本教...
NetBeans Manifest File Syntax Highlighting 模块教程

反馈

请注意,并不是本教程中介绍的所有 API 都是当前最新的。在您自己的磁盘上使用它们。不保证本教程中使用的 NetBeans 与最终版本或下一个版本的 NetBeans 兼容。

本教程向您介绍如何通过添加 Manifest 文件的高亮显示语法来改进 IDE。在本教程的结尾您将拥有一个可以与其他人共享的 NetBeans 插件模块文件 (NBM)。当通过 NetBeans Update Center 安装时,manifest 条目的“name”、“colon”和“value”将具有不同的颜色,如下所示:

此外,您可以使用 Options 窗口修改颜色。

本教程将介绍以下主题:

安装完软件之后,本教程可以在 60 分钟之内完成。

有关创建 NetBeans 插件模块的更多信息,请参见 NetBeans 网站上的 NetBeans Development Project 主页。如果有问题,请访问 NetBeans Developer FAQ 或使用本页顶部的反馈链接。


了解示例

开始编写插件模块之前,必须确保您具备所有必要的软件。此外,您可能想在亲自构建之前使用示例。

安装软件

开始之前,需要在您的计算机上安装以下软件:

  • NetBeans IDE 5.0(下载
  • Java Standard Development Kit (JDK!") version 1.4.2(下载)或 5.0(下载

安装示例

采用以下步骤来安装示例:

  1. 解压缩附加的文件
  2. 在 IDE 中,选择 File > Open Project,然后浏览到包含已解压缩文件的文件夹。打开模块项目。其形式如下:

  3. 右键单击项目节点并在 Target Platform 中选择 Install/Reload。将打开目标平台并安装该模块。

介绍示例

  1. 使用 New project 向导 (Ctrl-Shift-N) 来创建 Java 应用程序项目或 NetBeans 插件模块项目,并注意到项目的 manifest 文件具有高亮显示的语法,如本教程的介绍部分所示。
  2. 选择 Tools > Options。在 Options 窗口中,单击左边栏中的 Fonts & Colors,并注意到在 Language 下拉列表中有一个名为“Manifest”的条目,如下面所示:

  3. 从 Fonts & Colors 页面的顶部的 Profile 下拉列表中选择 City Lights,并注意到语法的变化,如下所示:

  4. 单击左边栏中的 Editor,并注意到在 Language 下拉列表中有一个名为“Manifest”的条目,如下所示:

  5. 单击 Options 窗口左下角的 Advanced Options。在 Editor Settings 节点中,注意到有一个 Manifest Editor 的新条目,如下所示:

您已经了解了 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 文件数据对象的能力(通过 .mf 文件扩展名和 text/x-java-jar-manifest MIME Type)。
    • 出现在右键单击菜单中的操作。
    • 用于创建新 Manifest 文件的虚拟模板在 New File 向导中注册。
    • 编辑器套件,包含语法高亮显示信息。
    • 在 Options 窗口中用于相关信息的实例化的选项设置文件。
    • Options 窗口的颜色信息,一个设置用于 NetBeans 配置文件,另一个设置用于 City Lights 配置文件。

  • 支持文件。

    • 数据对象文件。 使 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 提供一个向导,用于设置模块所需的所有基本文件。

创建模块项目

  1. 选择 File > New Project。在 Categories 下,选择 NetBeans Plug-in Modules。在 Projects 下,选择 Module Project 并单击 Next。
  2. 在 Name and Location 面板中,在 Project Name 中键入 ManifestSupport。将 Project Location 更改为您计算机上的任何目录,如 c:\mymodules。选择 Standalone Module 单选按钮和 Set as Main Project 复选框。单击 Next。
  3. 在 Basic Module Configuration 面板中,将 Code Name Base 中的 yourorghere 替换为 netbeans.modules,于是全名为 org.netbeans.modules.manifestsupport。在 Module Display Name 中填入 ManifestSupport。留出本地化资源包和 XML 层的位置,以便将它们存储在名为 org.netbeans.modules.manifestsupport 的包中。单击 Finish。

IDE 创建 ManifestSupport 项目。该项目包含所有资源和项目元数据,如该项目的 Ant 构建脚本。该项目在 IDE 中打开。您可以在 Projects 窗口 (Ctrl-1) 中查看其逻辑结构,在 Files 窗口 (Ctrl-2) 中查看其文件结构。

指定模块的依存关系

您需要将几个属于 NetBeans API 的类设为子类。每个类都将被声明为 Module 依存关系。使用 Project Properties 对话框来执行此操作。

  1. 在 Projects 窗口中,右键单击 ManifestSupport 项目节点并选择 Properties。在 Project Properties 对话框中单击 Libraries。
  2. 对于在 Libraries 面板中已经不存在的以下每个 API,单击“Add...”,从 Module 列表中选择名称,然后单击 OK 确认:

    现在应该看到下图:

  3. 单击 OK,退出 Project Properties 对话框。
  4. 在 Projects 窗口中,展开 Important Files 节点,双击 Project Metadata 节点,并注意查看您选择的 API 是否按模块依存关系进行了声明:
  5. <?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 文件的编辑器。

创建标记

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,并在 Class Name 中键入 ManifestTokenContext。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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);
            }
        }
    }
  2. 理解文件。 该 Java 类为我们想使用的每个 Manifest 文件中的每个项指定一个标记。Manifest 文件中的每个区分项目是一个标记:“name”、“colon”和“value”。此外,还有一个行结束标记,因为我们需要使用行的结束来确定值的结束位置和下一个名称的开始位置。以上构造方法指定前缀为“mf-”的所有标记。因此,我们现在创建名为“mf-name”、“mf-colon”、“mf-value”和“mf-end-of-line”的标记。

创建语法

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,并在 Class Name 中键入 ManifestSyntax。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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;
        }
    }
  2. 理解文件。 该 Java 类 IDE 哪部分文本被标记。通过从初始状态开始,顺序查看文本中的每个字符并决定是否处于该状态,然后移动到另一个状态或宣布已经发现了一个标记。

    例如,对于名称,IDE 从初始状态开始,首先它遇到了名称的有效字符,然后又进入 ISI_NAME 状态。它一直保持该状态,直到它遇到了一个 \r\n:字符,这些字符不属于名称。当它遇到这样一个字符时,IDE 知道它刚刚经过的这个字符由名称标记组成。代码在 while 循环中运行。结尾处有一个中断状态,它增加了文本的偏移量。该代码中的返回状态避免增加偏距,并且确保分析名称之后将以这个字符(它可能是一个冒号,这是自身有意义的标记)开始的下一个标记。另一方面,中断状态确保增加偏移量。当所有靠近冒号的字符都测试过之后,IDE 知道光标是否位于名称内部。

对 IDE 进行读测试

执行以下操作:

  1. 创建文件。 右键单击 Unit Test Packages 节点,选择 New > Java Class,在 Class Name 中键入 ManifestSyntaxTest,在 Package 中键入 org.netbeans.modules.manifestsupport。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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);
        }
    }
  2. 理解文件。 该 Java 类检查 IDE 是否能够将文本正确地转换为标记。要运行测试,请右键单击该项目节点,然后选择 Run Unit Tests。测试应该继续,在 JUnit Test Results 窗口中返回以下结果:

    您可以使用 testNextToken() 方法查看当输入的文本与指定的标记不相符时 IDE 执行的操作。例如,通过删除一个标记 ID (ManifestTokenContext.VALUE) 更改方法,于是该方法如下:

    public void testNextToken() {
       doParse("Manifest-Version: 1.0", Arrays.asList(new TokenID[] {
            ManifestTokenContext.NAME,
            ManifestTokenContext.COLON,
       }));
    }

    现在标记比标记 ID 多。(此处有两个标记 ID—ManifestTokenContext.NAMEManifestTokenContext.COLON。)当您运行 JUnit 测试时,返回消息“More tokens returned than expected。”:

    现在通过删除 Manifest-Version1.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 文件并使颜色与标记相关联。

创建 EditorKit

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,并在 Class Name 中键入 ManifestEditorKit。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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;
        }
    }
  2. 理解文件。 该 Java 类指定专门用于 NetBeans 编辑器的 EditorKit。因此,它扩展 NBEditorKit 类。编辑器套件建立文本组件所需的一组内容,用于正确合理地为某些类型的文本内容运行编辑器。在这种情况下,该编辑器是针对使用 text/x-java-jar-manifest MIME Type 的内容。

创建语法颜色

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,并在 Class Name 中键入 ManifestSettingsInitializer。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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.
       
    }
  2. 理解文件。 该 Java 类为我们的标记设置默认的颜色。由于在以下部分中描述了支持文件,用户将能够使用 Options 窗口来更改默认值。

创建 Color Restorer

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,并在 Class Name 中键入 RestoreColoring。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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);
        }
       
    }
  2. 理解文件。 该 Java 类用于安装模块并维护其状态。除了创建它之后,您必须在模块的 manifest 文件中指定该类,方法是添加以下行:
    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 编辑器本身。

创建选项

执行以下操作:

  1. 创建文件。 右键单击 ManifestSupport 项目节点,选择 New > Java Class,在 Class Name 中键入 ManifestOptions,在 Package 中键入 org.netbeans.modules.manifestsupport.options。单击 Finish。新 Java 类将在 Source Editor 中打开。用以下内容替换默认代码:
    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);
            }
        }
       
    }
  2. 理解文件。 该 Java 类在 Options 窗口中注册 ManifestEditorKit。如果有特定于 Manifest Editor 的属性,则将它们添加到 static final String[] MF_PROP_NAMES = new String[] {}; 声明中。但是,在该实现中,只支持默认的选项。此外,该文件还向 Editor 部分的 Code Templates 页面的下拉列表中添加字符串“Manifest”,如下所示:

在 Options 窗口中显示选项

执行以下操作:

  1. 创建文件。 创建 ManifestOptionsBeanInfo 文件并将其添加到 org.netbeans.modules.manifestsupport.options 包中。用以下内容替换默认代码:
    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);
            }
        }
    }
  2. 理解文件。 该 Java 类将 ManifestOptions 中指定的选项显示在 Options 窗口中。在构造方法中参考的文件可以是任何 16x16 像素的文件。如果没有这样的文件,您可以从页面顶部可下载的 ZIP 文件中获得或者右键单击并将其保存在此处:

    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 文件。

实例化选项

执行以下操作:

  1. 创建文件。 创建名为 ManifestOptions.settings 的 XML 文件并将其放置在 org.netbeans.modules.manifestsupport.options 包中。用以下内容替换默认代码:
    <?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>
  2. 理解文件。 该文件在要求实例化文件时让 IDE 快速实例化 ManifestOptions.java 文件。下一部分向您介绍在 NetBeans System Filesystem 中注册设置文件。

在 NetBeans System Filesystem 中注册选项

要在 Options 窗口中注册模块,您必须在 layer.xml 文件中执行以下操作:

  • 为每个 IDE 支持的配置文件创建默认的颜色。当前,IDE 支持名为“NetBeans”和名为“City Lights”的配置文件。可以从 Fonts & Colors 部分顶部的 Profile 下拉列表中进行选择。
  • 注册 ManifestEditorKit.java 类。
  • 注册 ManifestOptions.settings 文件。
  • 创建一个包含将在 Preview 窗口中显示的文本的文件,Preview 窗口位于 Options 窗口的 Fonts & Colors 部分的底部。
  • 本地化 layer.xml 文件中的字符串。

左侧的屏幕截图显示 NetBeans 配置文件,右侧的屏幕截图显示 City Lights 配置文件:

执行以下操作:

  1. 更新 layer.xml 文件。将以下条目添加到 layer.xml 文件:
    <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>
  2. 本地化 Fonts & Colors 页面。layer.xml 文件所在的包中(即在 org.netbeans.modules.manifestsupport 中),向 Bundle.properties 文件中添加以下条目:
    text/x-java-jar-manifest=Manifest
    NetBeans=NetBeans
    mf-name=Name
    mf-value=Value
    mf-colon=Colon
  3. 为每个配置文件创建一个颜色文件。 创建名为 org.netbeans.modules.manifestsupport.resources 的包并添加两个文件即 NetBeans-Manifest-fontsColors.xmlCityLights-Properties-fontsColors.xml
    • NetBeans-Manifest-fontsColors.xml 具有以下内容:
      <?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>
    • CityLights-Properties-fontsColors.xml 具有以下内容:
      <?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>
  4. 创建 Preview 文件。 在 Options 窗口的 Fonts & Colors 部分底部,用户可以预览对 Manifest 文件条目显示在编辑器中的方式所做的更改。要指定在预览窗口中显示的文本,您需要创建一个文件,如上面 layer.xml 文件的 OptionsDialog 文件夹中所指定。在 org.netbeans.modules.manifestsupport.resources 包中,添加名为 ManifestExample 的文件(注意该文件没有扩展名),它具有以下内容:
    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 构建脚本来构建和安装您的模块。构建脚本是创建模块项目时为您创建的。

安装和测试 NetBeans 模块

  1. 在 Projects 窗口,右键单击 ManifestSupport 项目并在 Target Platform 中选择 Install/Reload。

    模块即在目标 IDE 或平台中构建和安装。目标 IDE 或平台打开,您可以试用新的模块。默认目标 IDE 或平台是由开发 IDE 的当前实例使用的安装平台。注意到当您运行模块时,您将使用临时测试用户目录,而不是开发 IDE 的用户目录。

  2. 选择 File > New Project (Ctrl-Shift-N)。创建新的 Java 应用程序项目或新的 Plug-in Module 项目。在 Source Editor 中打开项目的 Manifest 文件,并注意到高亮显示的语法。

    有关该模块的其他方面,请参阅介绍示例部分。

创建可共享的模块二进制文件(NBM 文件)

NBM 文件是一个 NetBeans 模块,该模块已被打包以便通过 Web 发送。NBM 文件和模块 JAR 文件之间的主要差别为:

  • NBM 文件是压缩的文件。
  • NBM 文件可以包含多个 JAR 文件,即模块可以将它们使用的任何库打包到它们的 NBM 文件中。
  • NBM 文件包含 NetBeans 将用来在 Update Center 显示有关它信息的元数据,如 manifest 内容、许可等。
  • 出于安全考虑,NBM 文件通常都有签名。

NBM 文件只是具有特殊扩展名的 ZIP 文件。它们使用 JDK 机理给 JAR 文件签名。除非您正在执行一些不同寻常的操作,否则不需要担心 NBM 文件的内容,只需让 NBM 创建的标准 Ant 构建脚本为您完成所有工作。IDE 根据在 Project Properties 对话框的项目中输入的选项生成构建脚本。您可以在 Project Properties 对话框中设置模块的依存关系、版本控制和打包信息。通过为项目编辑 Ant 脚本和 Ant 属性,您可以进一步自定义程序执行。

  1. 在 Projects 窗口中,右键单击 ManifestSupport 项目节点,并选择 Create NBM。

    将创建 NBM 文件并且可以在 Files 窗口中查看它 (Ctrl-2):

  2. 通过电子邮件使其他人也可以使用。
  3. 使用 Update Center 来安装 NBM 文件。

进一步研究

下面是您可能研究的一些其他途径。

将 EditorKit 与 JEditorPane 关联

代替在 Source Editor 中使用 EditorKit,您可以使它与 JEditorPane 相关联。

执行以下操作:

  1. 选择 JEditorPane,单击 editorKit 属性并进行以下选择:

  2. 选择 JEditorPane,单击 contentType 属性并键入 Manifest 文件的 MIME Type (text/x-java-jar-manifest):

  3. 当您部署模块时,将在 JEditorPane 中启用高亮显示的语法:

    实际上,现在 JEditorPane 就是您的编辑器。您可以使用 Options 窗口修改字体和颜色,就像您使用 Source Editor 一样。

代码折叠

即将研究。

缩进引擎

即将研究。

其他选项

即将研究。


应用您所学的知识

您熟悉了本教程中介绍的原理之后,您就可以将它们应用到您自己的方案中。例如,此处是 NetBeans 用户 Valentin Buergel 的 Wiki 语法高亮显示:


下一步

有关创建和开发 NetBeans 模块的更多信息,请参见以下资源:


版本控制

版本
日期
更改
1 2005 年 10 月 23 日
  • 初始版本。
2 2005 年 11 月 30 日
  • 在结尾添加了 Valentin 的屏幕截图。
  • 解决了一些小事件:
    • 事件 69568
    • 在一个颜色 XML 文件中关闭标记错误。
    • 以前将 NbEditorKit 错误地认为是 NBEditorkit
  • 之后需要解决几个较大的事件(来自 Andrei Badea 以及来自 openide 邮件列表中的一两个人)。

非常感谢 Andrei Badea、Tom Ball 和 Martin Adamek 提供的帮助和灵感。




↑返回目录
前一篇: NetBeans Google Toolbar 模块教程
后一篇: NetBeans Component Palette 模块教程