本教程演示如何创建提供拖放新文件类型的代码片段的 Component Palette。代码片段用来加速编码的过程。IDE 为 JSP 文件、HTML 文件和 Form 文件提供 Component Palette。在本教程中,您将学习如何为不同的文件类型(默认情况下 IDE 不识别的文件类型)创建 Component Palette。首先,您使用 New File Type 向导使 IDE 能够识别新的文件类型。然后,您实现 NetBeans Palette API 提供的几个类。最后,您在 layer.xml 文件中注册新的 Component Palette。
本教程中创建的 Component Palette 将由 JBoss 部署描述符文件 (jboss-web.xml) 使用。jboss-web.xml 文件通过它的名称空间与所有其他 XML 文件相区别:
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_0.dtd">
仅当具有以上名称空间的文件在 IDE 的 Source Editor 中打开时,本教程中创建的 Component Palette 才可见。仅针对这些文件,Component Palette 将在 jboss-web.xml 文件中包括三个典型元素的代码片段:“Context Root”、“Security Domain”和“Resource Reference”。如上所示,工具提示将显示拖放代码片段时在 Source Editor 中的光标位置插入的标记。
如果您不想创建新的 component palette,而只想向现有的 component palette 中添加代码片段,请参阅 NetBeans Code Snippet 模块教程。
本教程将介绍以下主题:
安装完软件之后,本教程可以在 45 分钟之内完成。
有关使用模块的详细信息,请参阅 NetBeans 网站上的 NetBeans Development Project 主页。如果有问题,请访问 NetBeans Developer FAQ 或使用本页顶部的反馈链接。
开始之前,需要在您的计算机上安装以下软件:
采用以下步骤来安装示例:
该文件在 Source Editor 中打开,并且 component palette 打开,显示三个代码片段,如本教程的介绍部分中的屏幕截图所示。如果 component palette 未自动打开,则按 Ctrl-Shift-8 手动打开它。
出现 Palette Manager,包含您的新代码片段,如下所示:
知道了最终结果后,将从头开始创建模块,并且在创建的同时了解每个部分。
开始编写模块前,必须确保正确地设置了项目。NetBeans IDE 5.0 提供一个向导,用于设置模块所需的所有基本文件。
IDE 创建 jbosswebxml 项目。该项目包含所有资源和项目元数据,如该项目的 Ant 构建脚本。该项目在 IDE 中打开。您可以在 Projects 窗口 (Ctrl-1) 中查看其逻辑结构,在 Files 窗口 (Ctrl-2) 中查看其文件结构。
File Recognition 面板应该如下所示:
注意以下关于 File Recognition 面板中各字段的内容:
注意,JAR 文件中的 manifests 是“MANIFEST.MF”并且区分大小写(至少在 Unix 上)。由于这个原因,在本教程中您指定两个 MIME 类型,即 .mf 和 .MF。
单击 Next。
注意在 NetBeans 安装目录中发现了几个 16x16 像素图像文件,例如,在以下位置:
enterprise2/jakarta-tomcat-5.5.7/server/webapps/admin/images.
例如,您可以使用上面目录中的 Datasource.gif 图像。其形式如下:
现在 Projects 窗口应该显示如下:
下面简要介绍每个新生成的文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE MIME-resolver PUBLIC "-//NetBeans//DTD MIME Resolver 1.0//EN" "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd"> <MIME-resolver> <file> <ext name="xml"/> <resolver mime="text/x-jboss+xml"> <xml-rule> <doctype public-id="-//JBoss//DTD Web Application 2.3//EN"/> </xml-rule> </resolver> </file> </MIME-resolver>
您需要将几个属于 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.jbosswebxml</code-name-base> <standalone/> <module-dependencies> <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.9.0.1</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.netbeans.modules.projectapi</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <release-version>1</release-version> <specification-version>1.9</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.netbeans.spi.palette</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <release-version>0</release-version> <specification-version>1.5</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.dialogs</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.4</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.filesystems</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.4</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.loaders</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>5.9</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.nodes</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.7</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.text</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.9</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.util</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.8</specification-version> </run-dependency> </dependency> <dependency> <code-name-base>org.openide.windows</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> <specification-version>6.5</specification-version> </run-dependency> </dependency> </module-dependencies> <public-packages/> </data> </configuration> </project>
Component Palette 由 NetBeans Palette API 定义。对于本教程来说实现 NetBeans Palette API 意味着实现以下 NetBeans Palette API 类:
文件
|
描述
|
PaletteFactory | 创建 Component Palette 的新实例。要完成此操作,它调用从 JBOSSPalette 文件夹创建新调色板的 createPalette 方法,该方法是在 layer.xml 文件中定义的。 |
PaletteController | 提供对 Component Palette 中数据的访问。 |
PaletteActions | (将要执行) |
此外,您还将创建以下支持类:
文件
|
描述
|
jbossddPaletteUtilities | 通过实现两个 NetBeans API 类来处理放置的代码片段的插入和格式:
|
jbossddPaletteCustomizerAction | 提供打开 Palette Manager 的菜单项:
|
jbossddPaletteDropDefault | (将要执行) |
要实现 NetBeans Palette API,请采用以下步骤:
现在您应该拥有以下文件(在下面的屏幕截图中高亮显示):
package org.netbeans.modules.jbosswebxml.palette; import java.io.IOException; import org.netbeans.spi.palette.PaletteController; import org.netbeans.spi.palette.PaletteFactory; public class jbossddPaletteFactory { public static final String JBOSS_PALETTE_FOLDER = "JBOSSPalette"; private static PaletteController palette = null; public static PaletteController getPalette() throws IOException { if (palette == null) palette = PaletteFactory.createPalette(JBOSS_PALETTE_FOLDER, new jbossddPaletteActions()); return palette; } }
package org.netbeans.modules.jbosswebxml.palette; import java.awt.event.ActionEvent; import java.io.IOException; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.text.JTextComponent; import org.netbeans.editor.Utilities; import org.netbeans.spi.palette.PaletteActions; import org.netbeans.spi.palette.PaletteController; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.text.ActiveEditorDrop; import org.openide.util.Lookup; import org.openide.util.NbBundle; public class jbossddPaletteActions extends PaletteActions { /** Creates a new instance of jbossddPaletteActions */ public jbossddPaletteActions() { } public Action[] getImportActions() { return new Action[0]; //TODO implement this } public Action[] getCustomCategoryActions(Lookup category) { return new Action[0]; //TODO implement this } public Action[] getCustomItemActions(Lookup item) { return new Action[0]; //TODO implement this } public Action[] getCustomPaletteActions() { return new Action[0]; //TODO implement this } public Action getPreferredAction( Lookup item ) { return new MFPaletteInsertAction(item); } private static class MFPaletteInsertAction extends AbstractAction { private Lookup item; MFPaletteInsertAction(Lookup item) { this.item = item; } public void actionPerformed(ActionEvent e) { ActiveEditorDrop drop = (ActiveEditorDrop) item.lookup(ActiveEditorDrop.class); JTextComponent target = Utilities.getFocusedComponent(); if (target == null) { String msg = NbBundle.getMessage(jbossddPaletteActions.class, "MSG_ErrorNoFocusedDocument"); DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(msg, NotifyDescriptor.ERROR_MESSAGE)); return; } try { drop.handleTransfer(target); } finally { Utilities.requestFocus(target); } try { PaletteController pc = jbossddPaletteFactory.getPalette(); pc.clearSelection(); } catch (IOException ioe) { } //should not occur } } }
package org.netbeans.modules.jbosswebxml.palette; import java.awt.Component; import java.awt.Container; import java.util.StringTokenizer; import javax.swing.JTree; import javax.swing.text.BadLocationException; import javax.swing.text.Caret; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.SourceGroup; import org.netbeans.api.project.Sources; import org.netbeans.editor.BaseDocument; import org.netbeans.editor.Formatter; import org.openide.filesystems.FileObject; public class jbossddPaletteUtilities { /** Creates a new instance of jbossddPaletteUtilities */ public jbossddPaletteUtilities() { } public static void insert(String s, JTextComponent target) throws BadLocationException { insert(s, target, true); } public static void insert(String s, JTextComponent target, boolean reformat) throws BadLocationException { if (s == null) s = ""; Document doc = target.getDocument(); if (doc == null) return; if (doc instanceof BaseDocument) ((BaseDocument)doc).atomicLock(); int start = insert(s, target, doc); if (reformat && start >= 0 && doc instanceof BaseDocument) { // format the inserted text int end = start + s.length(); Formatter f = ((BaseDocument)doc).getFormatter(); f.reformat((BaseDocument)doc, start, end); } if (doc instanceof BaseDocument) ((BaseDocument)doc).atomicUnlock(); } private static int insert(String s, JTextComponent target, Document doc) throws BadLocationException { int start = -1; try { //at first, find selected text range Caret caret = target.getCaret(); int p0 = Math.min(caret.getDot(), caret.getMark()); int p1 = Math.max(caret.getDot(), caret.getMark()); doc.remove(p0, p1 - p0); //replace selected text by the inserted one start = caret.getDot(); doc.insertString(start, s, null); } catch (BadLocationException ble) {} return start; } }
package org.netbeans.modules.jbosswebxml.palette; import java.io.IOException; import org.openide.ErrorManager; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; public class jbossddPaletteCustomizerAction extends CallableSystemAction { private static String name; public jbossddPaletteCustomizerAction () { putValue("noIconInMenu", Boolean.TRUE); // NOI18N } protected boolean asynchronous() { return false; } /** Human presentable name of the action. This should be * presented as an item in a menu. * @return the name of the action */ public String getName() { if (name == null) name = NbBundle.getBundle(jbossddPaletteCustomizerAction.class).getString("ACT_OpenjbossddCustomizer"); // NOI18N return name; } /** Help context where to find more about the action. * @return the help context for this action */ public HelpCtx getHelpCtx() { return null; } /** This method is called by one of the "invokers" as a result of * some user's action that should lead to actual "performing" of the action. */ public void performAction() { try { jbossddPaletteFactory.getPalette().showCustomizer(); } catch (IOException ioe) { ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, ioe); } } }
package org.netbeans.modules.jbosswebxml.palette; import javax.swing.text.BadLocationException; import javax.swing.text.JTextComponent; import org.openide.text.ActiveEditorDrop; public class jbossddPaletteDropDefault implements ActiveEditorDrop { String body; public jbossddPaletteDropDefault(String body) { this.body = body; } public boolean handleTransfer(JTextComponent targetComponent) { if (targetComponent == null) return false; try { jbossddPaletteUtilities.insert(body, (JTextComponent)targetComponent); } catch (BadLocationException ble) { return false; } return true; } }
MSG_ErrorNoFocusedDocument=No document selected. Please select a document to insert the item into. ACT_OpenJbossddCustomizer=&JBoss Code Clips
每个代码片段都需要以下文件:
已经创建或向 NetBeans 模块添加以上文件之后,您在资源声明 XML 文件中声明它们,该文件是您使用 layer.xml 文件在 NetBeans System Filesystem 中注册的。
有关以上所有项目的详细信息,请浏览 NetBeans Code Snippet 模块教程。
作为示例,当您创建三个名为 ContextRoot.java、ResourceReference.java 和 SecurityDomain.java 的代码片段时,结果应该如下所示(下面高亮显示的包包含代码片段及其支持资源):
<folder name="Menu"> <folder name="Tools"> <folder name="PaletteManager"> <file name="org-netbeans-modules-jbosswebxml-palette-jbossddPaletteCustomizerAction.instance"/> </folder> </folder> </folder> <folder name="JBOSSPalette"> <folder name="JBoss"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.jbosswebxml.palette.Bundle"/> <file name="ContextRoot.xml" url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/ContextRoot.xml"/> <file name="SecurityDomain.xml" url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/SecurityDomain.xml"/> <file name="ResourceReference.xml" url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/ResourceReference.xml"/> </folder> </folder>
JBOSSPalette/JBoss=JBoss Deployment Descriptor JBOSSPalette/JBoss/ContextRoot.xml=Context Root JBOSSPalette/JBoss/ResourceReference.xml=Resource Reference JBOSSPalette/JBoss/SecurityDomain.xml=Security Domain
上面列出的键值本地化在 layer.xml 文件中注册的项目。
ACT_OpenJbossddCustomizer=&HTML/JSP Code Clips
<folder name="Menu"> <folder name="Tools"> <folder name="PaletteManager"> <file name="org-netbeans-modules-jbosswebxml-palette-jbossddPaletteCustomizerAction.instance"/> <file name="org-netbeans-modules-html-palette-HTMLPaletteCustomizerAction.instance_hidden"/> <file name="org-netbeans-modules-web-core-palette-JSPPaletteCustomizerAction.instance_hidden"/> </folder> </folder> </folder>
<folder name="JBOSSPalette"> <folder name="JBoss"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.jbosswebxml.Bundle"/> <file name="ContextRoot.xml" url="ContextRoot.xml"/> <file name="ResourceReference.xml" url="ResourceReference.xml"/> <file name="SecurityDomain.xml" url="SecurityDomain.xml"/> </folder> <folder name="HTML.shadow"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.web.core.palette.Bundle"/> <attr name="originalFile" stringvalue="HTMLPalette/HTML"/> </folder> <folder name="HTML_Forms.shadow"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.web.core.palette.Bundle"/> <attr name="originalFile" stringvalue="HTMLPalette/HTML_Forms"/> </folder> <folder name="JSP.shadow"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.web.core.palette.Bundle"/> <attr name="originalFile" stringvalue="JSPPalette/JSP"/> </folder> <folder name="Database.shadow"> <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.web.core.palette.Bundle"/> <attr name="originalFile" stringvalue="JSPPalette/Database"/> </folder> </folder>
现在当您构建和安装模块时,如下部分所述,jboss-web.xml 文件的 Component Palette 将包含 JSP 提供的所有 代码片段以及 HTML 提供的所有 代码片段。
IDE 使用 Ant 构建脚本来构建和安装您的模块。构建脚本是创建模块项目时为您创建的。
模块即在目标平台中构建和安装。目标平台打开,您可以试用新的模块。默认目标平台是由开发 IDE 的当前实例使用的安装。
将创建 NBM 文件并且可以在 Files 窗口中查看它 (Ctrl-2):