|  | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | 
|  | <html xmlns="http://www.w3.org/1999/xhtml"> | 
|  | <head> | 
|  | <title>NetBeans Platform Ant Tutorial</title> | 
|  | <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/> | 
|  | <meta name="AUDIENCE" content="NBUSER"/> | 
|  | <meta name="TYPE" content="ARTICLE"/> | 
|  | <meta name="EXPIRES" content="N"/> | 
|  | <meta name="indexed" content="y"/> | 
|  | <meta name="description" | 
|  | content="A short guide to getting started with EMF on the NetBeans Platform."/> | 
|  | <!--      Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | 
|  | <!--     Use is subject to license terms.--> | 
|  | </head> | 
|  | <body> | 
|  |  | 
|  | <h1>NetBeans Platform Ant Tutorial</h1> | 
|  |  | 
|  | <p>This document shows you how to use Ant and the command line to | 
|  | set up and deploy NetBeans Platform applications. | 
|  | </p> | 
|  |  | 
|  | <p> | 
|  | You will start by setting up a folder and file structure for | 
|  | deploying a NetBeans Platform application. The structure will | 
|  | consist of folders, together with Ant scripts and property files. | 
|  | For example, one of the Ant targets will download the NetBeans Platform, while | 
|  | another will run it. Next, you will create a new folder and file structure | 
|  | for adding a new module to the application. Finally, you will add | 
|  | code that will enable your module to provide new components, such as | 
|  | a new menu item, to the application. | 
|  | </p> | 
|  |  | 
|  | <p>Once you have gone through this simple scenario, you should not <i>need</i> to | 
|  | use NetBeans IDE at all when creating NetBeans Platform applications. | 
|  | On the other hand, you might still <i>want</i> to use NetBeans IDE, since | 
|  | it provides many wizards, templates, and other tools for generating | 
|  | code and visualizing module structures, which are features | 
|  | that no other IDE currently provides. Simultaneously, the instructions | 
|  | below provide all the NetBeans-specific information needed for someone to create a plugin | 
|  | for a different IDE enabling developers to use other IDEs to provide | 
|  | the folder structures and file contents outlined below. | 
|  | </p> | 
|  |  | 
|  | <p><b>Contents</b></p> | 
|  | <ul class="toc"> | 
|  | <li><a href="#rcp">Downloading the NetBeans Platform</a></li> | 
|  | <li><a href="#application">Setting Up a NetBeans Platform Application</a></li> | 
|  | <li><a href="#module">Setting Up a NetBeans Module</a></li> | 
|  | <li><a href="#menu">Adding a Menu Item</a></li> | 
|  | <li><a href="#window">Adding a Window</a></li> | 
|  | </ul> | 
|  |  | 
|  | <p><b>To follow this tutorial, you need the software and resources listed in the following table.</b></p> | 
|  |  | 
|  | <table> | 
|  | <tbody> | 
|  | <tr> | 
|  | <th class="tblheader" scope="col">Software or Resource</th> | 
|  | <th class="tblheader" scope="col">Version Required</th> | 
|  | </tr> | 
|  | <tr> | 
|  | <td class="tbltd1"><a href="http://ant.apache.org/">Ant</a></td> | 
|  | <td class="tbltd1"></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> | 
|  | <td class="tbltd1">Version 6</td> | 
|  | </tr> | 
|  | </tbody> | 
|  | </table> | 
|  |  | 
|  | <p>The tutorial assumes you have set up Ant and that you know how to use it.</p> | 
|  |  | 
|  |  | 
|  | <!-- ===================================================================================== --> | 
|  | <p></p> | 
|  | <h2><a name="rcp"></a>Downloading the NetBeans Platform</h2> | 
|  | <p>In this section, you begin to set up a folder structure | 
|  | for your NetBeans Platform work, focusing on an Ant script | 
|  | to download the NetBeans Platform.</p> | 
|  |  | 
|  | <ol> | 
|  |  | 
|  | <li><p>Create a new folder with a name of your choosing (here referred to as <code>ABC</code>) and, within it, create a folder | 
|  | named <code>myapp</code> (or any other name), containing a file named <code>build.xml</code>. At this | 
|  | point the structure of your application should be as follows:</p> | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-structure-0.png" alt="structure 1"/></p> | 
|  | </li> | 
|  |  | 
|  | <li>Read <a href="http://wiki.netbeans.org/AutoUpdateTask">http://wiki.netbeans.org/AutoUpdateTask</a>.</li> | 
|  |  | 
|  | <li><p>Define the content of the <code>build.xml</code> file as follows:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  |  | 
|  | <project name="myapp" basedir="."> | 
|  |  | 
|  | <description>Builds, tests, and runs the project "myapp".</description> | 
|  |  | 
|  | <!-- change this: --> | 
|  | <property name="netbeans" | 
|  | value="/home/geertjan/ABC/nbrcp"/> | 
|  |  | 
|  | <property name="bootstrap.url" | 
|  | value="http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastStableBuild/artifact/nbbuild/netbeans/harness/tasks.jar"/> | 
|  |  | 
|  | <property name="netbeans.updatecenter.url" | 
|  | value="http://bits.netbeans.org/netbeans/6.9/community/fcs/uc/catalog.xml.gz"/> | 
|  |  | 
|  | <target name="download-netbeans-rcp"> | 
|  | <mkdir dir="${netbeans}/harness"/> | 
|  | <get src="${bootstrap.url}" dest="${netbeans}/harness/tasks.jar" usetimestamp="true" verbose="true"/> | 
|  | <taskdef name="autoupdate" classname="org.netbeans.nbbuild.AutoUpdate" classpath="${netbeans}/harness/tasks.jar"/> | 
|  | <autoupdate installdir="${netbeans}" updatecenter="${netbeans.updatecenter.url}"> | 
|  | <modules includes=".*" clusters="harness[0-9]*"/> | 
|  | <modules includes=".*" clusters="platform[0-9]*"/> | 
|  | </autoupdate> | 
|  | </target> | 
|  |  | 
|  | </project> | 
|  | </pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>On the command line, go to the "ABC/myapp" folder and run this:</p> | 
|  |  | 
|  | <pre class="examplecode">ant download-netbeans-rcp</pre> | 
|  |  | 
|  | <p>You now see the NetBeans Platform downloading:</p> | 
|  |  | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-download.png" alt="structure 1"/></p> | 
|  |  | 
|  | <p>In your ABC folder, you now have a folder named "nbrcp", as shown below:</p> | 
|  |  | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-structure-1.png" alt="structure 1"/></p> | 
|  |  | 
|  | <p>Read <code>harness/README</code> for a lot of tips, configuration data, and advice.</p> | 
|  |  | 
|  | <p>The folder "myapp" is where you will create your application, | 
|  | on top of the NetBeans Platform, which is in the folder "nbrcp".</p> | 
|  | </li> | 
|  | </ol> | 
|  |  | 
|  | <p><b>Note:</b> Instead of using the Ant target above, you can simply download the ZIP | 
|  | files for <code>harness</code> and <code>platform</code>:</p> | 
|  |  | 
|  | <ul> | 
|  | <li><p>platform: <a href="https://netbeans.org/downloads/start.html?filename=zip/moduleclusters/netbeans-6.9-201006101454-ml-platform.zip&pagelang=" rel="nofollow">http://netbeans.org/downloads/start.html?filename=zip/moduleclusters/netbeans-6.9-201006101454-ml-platform.zip&pagelang=</a></p></li> | 
|  | <li><p>harness: <a href="https://netbeans.org/downloads/start.html?filename=zip/moduleclusters/netbeans-6.9-201006101454-ml-harness.zip&pagelang=" rel="nofollow">http://netbeans.org/downloads/start.html?filename=zip/moduleclusters/netbeans-6.9-201006101454-ml-harness.zip&pagelang=</a></p></li> | 
|  | </ul> | 
|  |  | 
|  | <p>Now that you have the NetBeans Platform, you can start creating | 
|  | an application on top of it.</p> | 
|  |  | 
|  | <!-- ===================================================================================== --> | 
|  | <p></p> | 
|  | <h2><a name="application"></a>Setting Up a NetBeans Platform Application</h2> | 
|  | <p>In this section, you set up a minimal folder and file structure for a new | 
|  | NetBeans Platform application.</p> | 
|  |  | 
|  | <p>At the end of this section, you will have a source structure | 
|  | on disk, as follows:</p> | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-structure.png" alt="structure 1"/></p> | 
|  |  | 
|  | <ol> | 
|  |  | 
|  | <li><p>Within the "myapp" folder, create a folder named "nbproject". | 
|  | This folder will, from now onwards, be referred to as | 
|  | the "application project folder", while "myapp" will be referred to | 
|  | as the "application root folder".</p></li> | 
|  |  | 
|  | <li><p>Within the application project folder, create a file named | 
|  | <code>build-impl.xml</code>, with the following content.</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  |  | 
|  | <project name="myapp-impl" basedir=".." xmlns:sproject="https://netbeans.org/ns/nb-module-suite-project/1"> | 
|  |  | 
|  | <property file="nbproject/platform.properties"/> | 
|  |  | 
|  | <macrodef name="property" uri="https://netbeans.org/ns/nb-module-suite-project/1"> | 
|  | <attribute name="name"/> | 
|  | <attribute name="value"/> | 
|  | <sequential> | 
|  | <property name="@{name}" value="${@{value}}"/> | 
|  | </sequential> | 
|  | </macrodef> | 
|  |  | 
|  | <macrodef name="evalprops" uri="https://netbeans.org/ns/nb-module-suite-project/1"> | 
|  | <attribute name="property"/> | 
|  | <attribute name="value"/> | 
|  | <sequential> | 
|  | <property name="@{property}" value="@{value}"/> | 
|  | </sequential> | 
|  | </macrodef> | 
|  |  | 
|  | <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/> | 
|  |  | 
|  | <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/> | 
|  |  | 
|  | <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/> | 
|  |  | 
|  | <import file="${harness.dir}/suite.xml"/> | 
|  |  | 
|  | </project></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li>Import the <code>build-impl.xml</code> file into the <code>build.xml</code> file, | 
|  | as follows: | 
|  |  | 
|  | <pre class="examplecode"><import file="nbproject/build-impl.xml"/></pre> | 
|  |  | 
|  | <p>The <code>build-impl.xml</code> file gives you access to the NetBeans Platform | 
|  | infrastructure, such as its "run" target. You will never need to change | 
|  | the <code>build-impl.xml</code> file. On the other hand, the <code>build.xml</code> file | 
|  | is the Ant script where you will customize, where necessary, your application's | 
|  | build process.</p></li> | 
|  |  | 
|  | <li><p>Within the application project folder, create a file named | 
|  | <code>platform.properties</code>, with the following content.</p> | 
|  |  | 
|  | <pre class="examplecode">nbplatform.active=default | 
|  | nbplatform.active.dir=/home/geertjan/ABC/nbrcp | 
|  | harness.dir=${nbplatform.active.dir}/harness | 
|  | cluster.path=${nbplatform.active.dir}/platform | 
|  | disabled.modules=</pre> | 
|  |  | 
|  | <p>As you can see, the <code>platform.properties</code> file | 
|  | configures your NetBeans Platform application, pointing to | 
|  | its <code>harness</code> and the <code>platform</code> folders, | 
|  | as well as a placeholder for the modules you will disable, later | 
|  | in your development work. Make sure to | 
|  | change <code>nbplatform.active.dir</code> above to point to | 
|  | your "nbrcp" folder.</p> | 
|  |  | 
|  | </li> | 
|  | <li><p>Within the application project folder, create a file named | 
|  | <code>project.properties</code>, with the following content.</p> | 
|  |  | 
|  | <pre class="examplecode">app.name=myapp | 
|  | branding.token=${app.name} | 
|  | modules=</pre> | 
|  |  | 
|  | <p>As you can see, the <code>project.properties</code> file | 
|  | is focused on the application. In this case, you have added | 
|  | keys in the file for the name | 
|  | of the application and the custom modules that the | 
|  | application will provide.</p> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>On the command line, go to the "ABC/myapp" folder and run this:</p> | 
|  |  | 
|  | <pre class="examplecode">ant run</pre> | 
|  |  | 
|  | </li> | 
|  | </ol> | 
|  |  | 
|  | <p>The NetBeans Platform starts up and you see a main window, with | 
|  | a menu bar and a tool bar, as shown below:</p> | 
|  |  | 
|  | <p><img src="../images/tutorials/ant/ant-result-0.png" alt="structure 1"/></p> | 
|  |  | 
|  | <p>Try out some of the toolbar buttons | 
|  | and menu items, to see what the NetBeans Platform provided by default.</p> | 
|  |  | 
|  | <!-- ===================================================================================== --> | 
|  | <p></p> | 
|  | <h2><a name="module"></a>Setting Up a NetBeans Module</h2> | 
|  | <p>In this section, you set up a minimal folder and file structure for a new | 
|  | NetBeans module in your NetBeans Platform application. In the process, | 
|  | you also register the module with the application so that, when the application | 
|  | starts up, it will load the module together with the default NetBeans | 
|  | Platform modules making | 
|  | up the application.</p> | 
|  |  | 
|  | <ol> | 
|  |  | 
|  | <li><p>Start by creating some folders:</p> | 
|  |  | 
|  | <ul><li><p>Within the "myapp" folder, create a folder named "mymodule". | 
|  | This folder will, from now onwards, be referred to as | 
|  | the "module root folder". </p></li> | 
|  |  | 
|  | <li><p>Within the module root folder, | 
|  | create a new folder named "nbproject", which will, | 
|  | from now onwards, be referred to | 
|  | as the "module project folder".</p></li> | 
|  |  | 
|  | <li><p>Within the module root folder, | 
|  | create a new folder structure "src/org/demo/mymodule", which will | 
|  | be the main package.</p></li></ul> | 
|  |  | 
|  | <p>Check that the structure you have created | 
|  | is now as follows:</p> | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-structure-2.png" alt="structure 1"/></p> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>In the module project folder, create the following:</p> | 
|  |  | 
|  |  | 
|  | <ul><li><p>A file named <code>suite.properties</code>, with this content:</p> | 
|  |  | 
|  | <pre class="examplecode">suite.dir=${basedir}/..</pre> | 
|  |  | 
|  | <p>The above points to the "myapp" folder, specifying that | 
|  | it is the application that owns this module.</p> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>A file named <code>project.properties</code>, with this content:</p> | 
|  |  | 
|  | <pre class="examplecode">javac.source=1.6 | 
|  | javac.compilerargs=-Xlint -Xlint:-serial</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>A file named <code>project.xml</code>, with this content:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <project xmlns="https://netbeans.org/ns/project/1"> | 
|  | <type>org.netbeans.modules.apisupport.project</type> | 
|  | <configuration> | 
|  | <data xmlns="https://netbeans.org/ns/nb-module-project/3"> | 
|  | <code-name-base>org.demo.mymodule</code-name-base> | 
|  | <suite-component/> | 
|  | <module-dependencies> | 
|  | </module-dependencies> | 
|  | <public-packages/> | 
|  | </data> | 
|  | </configuration> | 
|  | </project></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>A file named | 
|  | <code>build-impl.xml</code>, with this content:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  |  | 
|  | <project name="org.demo.mymodule-impl" basedir=".."> | 
|  |  | 
|  | <property file="nbproject/suite.properties"/> | 
|  |  | 
|  | <property file="${suite.dir}/nbproject/platform.properties"/> | 
|  |  | 
|  | <macrodef name="property" uri="https://netbeans.org/ns/nb-module-project/2"> | 
|  | <attribute name="name"/> | 
|  | <attribute name="value"/> | 
|  | <sequential> | 
|  | <property name="@{name}" value="${@{value}}"/> | 
|  | </sequential> | 
|  | </macrodef> | 
|  |  | 
|  | <macrodef name="evalprops" uri="https://netbeans.org/ns/nb-module-project/2"> | 
|  | <attribute name="property"/> | 
|  | <attribute name="value"/> | 
|  | <sequential> | 
|  | <property name="@{property}" value="@{value}"/> | 
|  | </sequential> | 
|  | </macrodef> | 
|  |  | 
|  | <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="https://netbeans.org/ns/nb-module-project/2"/> | 
|  | <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="https://netbeans.org/ns/nb-module-project/2"/> | 
|  | <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="https://netbeans.org/ns/nb-module-project/2"/> | 
|  |  | 
|  | <import file="${harness.dir}/build.xml"/> | 
|  |  | 
|  | </project></pre> | 
|  |  | 
|  | </li> | 
|  | </ul></li> | 
|  | <li><p>In the module root folder, that is, within the "mymodule" folder, | 
|  | create the following:</p> | 
|  |  | 
|  | <ul><li><p>A file named <code>build.xml</code>, with the | 
|  | following content:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <project name="org.demo.mymodule" default="netbeans" basedir="."> | 
|  | <description>Builds, tests, and runs the project org.demo.mymodule.</description> | 
|  | <import file="nbproject/build-impl.xml"/> | 
|  | </project></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>A file named <code>manifest.mf</code>, with the | 
|  | following content:</p> | 
|  |  | 
|  | <pre class="examplecode">Manifest-Version: 1.0 | 
|  | OpenIDE-Module: org.demo.mymodule | 
|  | OpenIDE-Module-Specification-Version: 1.0</pre> | 
|  |  | 
|  | </li></ul></li> | 
|  |  | 
|  | <li><p>Check that the "mymodule" structure you have created | 
|  | is now as follows:</p> | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-structure-3.png" alt="structure 1"/></p></li> | 
|  |  | 
|  | <li><p>In the application project folder, that is, "myapp/nbproject", | 
|  | change the "modules" key to the following, to register the | 
|  | module with the application:</p> | 
|  | <pre class="examplecode">modules=${project.org.demo.mymodule} | 
|  |  | 
|  | project.org.demo.mymodule=MyModule</pre></li> | 
|  |  | 
|  |  | 
|  | <li><p>On the command line, go to the "ABC/myapp" folder and run this:</p> | 
|  |  | 
|  | <pre class="examplecode">ant run</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>The application starts up and, since you didn't add any code | 
|  | to the module, you see no changes in the application. | 
|  | Nevertheless, looking at the output, you can see that the module loaded successfully:</p> | 
|  |  | 
|  | <p><img style="border: 1px solid" src="../images/tutorials/ant/ant-result-1.png" alt="structure 1"/></p></li> | 
|  |  | 
|  | </ol> | 
|  |  | 
|  | <p>In the next section, you add a new feature to the application.</p> | 
|  |  | 
|  | <!-- ===================================================================================== --> | 
|  | <p></p> | 
|  | <h2><a name="menu"></a>Adding a Menu Item</h2> | 
|  | <p>In this section, you add a menu item to the module you created in the | 
|  | previous section. All the files | 
|  | described below are assumed to be created in the main package, which is | 
|  | <code>org.demo.mymodule</code>.</p> | 
|  |  | 
|  | <ol> | 
|  |  | 
|  | <li><p>Add a new Action class to the module:</p> | 
|  |  | 
|  | <pre class="examplecode">package org.demo.mymodule; | 
|  |  | 
|  | import java.awt.event.ActionEvent; | 
|  | import java.awt.event.ActionListener; | 
|  | import javax.swing.JOptionPane; | 
|  |  | 
|  | public final class HelloWorldAction implements ActionListener { | 
|  | public void actionPerformed(ActionEvent e) { | 
|  | JOptionPane.showMessageDialog(null, "hello..."); | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Register the new Action class in a new <code>layer.xml</code> file:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "https://netbeans.org/dtds/filesystem-1_2.dtd"> | 
|  | <filesystem> | 
|  | <folder name="Actions"> | 
|  | <folder name="Window"> | 
|  | <file name="org-demo-mymodule-HelloWorldAction.instance"> | 
|  | <attr name="delegate" newvalue="org.demo.mymodule.HelloWorldAction"/> | 
|  | <attr name="displayName" bundlevalue="org.demo.mymodule.Bundle#CTL_HelloWorldAction"/> | 
|  | <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/> | 
|  | </file> | 
|  | </folder> | 
|  | </folder> | 
|  | <folder name="Menu"> | 
|  | <folder name="Window"> | 
|  | <file name="HelloWorldAction.shadow"> | 
|  | <attr name="originalFile" stringvalue="Actions/Window/org-demo-mymodule-HelloWorldAction.instance"/> | 
|  | </file> | 
|  | </folder> | 
|  | </folder> | 
|  | </filesystem></pre> | 
|  |  | 
|  | <p>Above, you're registering the <code><a href="http://bits.netbeans.org/dev/javadoc/org-openide-awt/org/openide/awt/Actions.html#alwaysEnabled%28java.awt.event.ActionListener,%20java.lang.String,%20java.lang.String,%20boolean%29">Actions.alwaysEnabled</a></code> | 
|  | factory method defined in the UI Utilities API.</p> | 
|  |  | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Add a <code>Bundle.properties</code> file:</p> | 
|  |  | 
|  | <pre class="examplecode">CTL_HelloWorldAction=Hello World</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Register the <code>layer.xml</code> file and the <code>Bundle.properties</code> file | 
|  | in the <code>manifest.mf</code> file:</p> | 
|  |  | 
|  | <pre class="examplecode">OpenIDE-Module-Layer: org/demo/mymodule/layer.xml | 
|  | OpenIDE-Module-Localizing-Bundle: org/demo/mymodule/Bundle.properties</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>On the command line, go to the "ABC/myapp" folder and run this:</p> | 
|  |  | 
|  | <pre class="examplecode">ant run</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>The application starts up and shows a new menu item under the Window menu:</p> | 
|  | <p><img src="../images/tutorials/ant/ant-result.png" alt="structure 1"/></p> | 
|  |  | 
|  | </li> | 
|  | </ol> | 
|  | <!-- ===================================================================================== --> | 
|  | <p></p> | 
|  | <h2><a name="window"></a>Adding a Window</h2> | 
|  | <p>In this section, you use the NetBeans TopComponent class | 
|  | to add a window to the module you created previously. All the files | 
|  | described below are assumed to be created in the main package, which is | 
|  | <code>org.demo.mymodule</code>.</p> | 
|  |  | 
|  | <ol> | 
|  |  | 
|  | <li><p>Add a new TopComponent class to the module, including | 
|  | some code for initializing and | 
|  | persisting the TopComponent:</p> | 
|  |  | 
|  | <pre class="examplecode">package org.demo.mymodule; | 
|  |  | 
|  | import java.awt.BorderLayout; | 
|  | import java.util.logging.Logger; | 
|  | import javax.swing.JLabel; | 
|  | import org.netbeans.api.settings.ConvertAsProperties; | 
|  | import org.openide.util.NbBundle; | 
|  | import org.openide.windows.TopComponent; | 
|  | import org.openide.windows.WindowManager; | 
|  |  | 
|  | @ConvertAsProperties(dtd = "-//org.demo.mymodule//HelloTopComponent//EN", autostore = false) | 
|  | public class HelloTopComponent extends TopComponent { | 
|  |  | 
|  | private static HelloTopComponent instance; | 
|  | private static final String PREFERRED_ID = "HelloTopComponent"; | 
|  |  | 
|  | public HelloTopComponent() { | 
|  | setName(NbBundle.getMessage(HelloTopComponent.class, "CTL_HelloTopComponent")); | 
|  | setToolTipText(NbBundle.getMessage(HelloTopComponent.class, "HINT_HelloTopComponent")); | 
|  | //        setIcon(ImageUtilities.loadImage(ICON_PATH, true)); | 
|  | setLayout(new BorderLayout()); | 
|  | add(new JLabel("hello"), BorderLayout.CENTER); | 
|  | } | 
|  |  | 
|  | public static synchronized HelloTopComponent getDefault() { | 
|  | if (instance == null) { | 
|  | instance = new HelloTopComponent(); | 
|  | } | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Obtain the HelloTopComponent instance. Never call {@link #getDefault} directly! | 
|  | */ | 
|  | public static synchronized HelloTopComponent findInstance() { | 
|  | TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); | 
|  | if (win == null) { | 
|  | Logger.getLogger(HelloTopComponent.class.getName()).warning( | 
|  | "Cannot find " + PREFERRED_ID + " component. It will not be " | 
|  | + "located properly in the window system."); | 
|  | return getDefault(); | 
|  | } | 
|  | if (win instanceof HelloTopComponent) { | 
|  | return (HelloTopComponent) win; | 
|  | } | 
|  | Logger.getLogger(HelloTopComponent.class.getName()).warning( | 
|  | "There seem to be multiple components with the '" + PREFERRED_ID | 
|  | + "' ID. That is a potential source of errors and unexpected behavior."); | 
|  | return getDefault(); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int getPersistenceType() { | 
|  | return TopComponent.PERSISTENCE_ALWAYS; | 
|  | } | 
|  |  | 
|  | void writeProperties(java.util.Properties p) { | 
|  | // better to version settings since initial version as advocated at | 
|  | // http://wiki.apidesign.org/wiki/PropertyFiles | 
|  | p.setProperty("version", "1.0"); | 
|  | // TODO store your settings | 
|  | } | 
|  |  | 
|  | Object readProperties(java.util.Properties p) { | 
|  | if (instance == null) { | 
|  | instance = this; | 
|  | } | 
|  | instance.readPropertiesImpl(p); | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | private void readPropertiesImpl(java.util.Properties p) { | 
|  | String version = p.getProperty("version"); | 
|  | // TODO read your settings according to their version | 
|  | } | 
|  |  | 
|  | @Override | 
|  | protected String preferredID() { | 
|  | return PREFERRED_ID; | 
|  | } | 
|  |  | 
|  | }</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Create a file named <code>HelloTopComponentSettings.xml</code>, | 
|  | with this content:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <!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.demo.mymodule" spec="1.0"/> | 
|  | <instanceof class="org.openide.windows.TopComponent"/> | 
|  | <instanceof class="org.demo.mymodule.HelloTopComponent"/> | 
|  | <instance class="org.demo.mymodule.HelloTopComponent" method="getDefault"/> | 
|  | </settings></pre> | 
|  |  | 
|  | <p>Read <a href="http://wiki.netbeans.org/DevFaqDotSettingsFiles">http://wiki.netbeans.org/DevFaqDotSettingsFiles</a> | 
|  | for background on the above file.</p> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Create a file named <code>HelloTopComponentWstcref.xml</code>, | 
|  | with this content:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "https://netbeans.org/dtds/tc-ref2_0.dtd"> | 
|  | <tc-ref version="2.0" > | 
|  | <module name="org.demo.mymodule" spec="1.0"/> | 
|  | <tc-id id="HelloTopComponent"/> | 
|  | <state opened="true"/> | 
|  | </tc-ref></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Register the new TopComponent class in the <code>layer.xml</code> file | 
|  | created previously, within the <code>filesystem/Windows2</code> folder:</p> | 
|  |  | 
|  | <pre class="examplecode"><folder name="Windows2"> | 
|  | <folder name="Components"> | 
|  | <file name="HelloTopComponent.settings" url="HelloTopComponentSettings.xml"/> | 
|  | </folder> | 
|  | <folder name="Modes"> | 
|  | <folder name="editor"> | 
|  | <file name="HelloTopComponent.wstcref" url="HelloTopComponentWstcref.xml"/> | 
|  | </folder> | 
|  | </folder> | 
|  | </folder></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>Register a menu item for opening your new TopComponent class. | 
|  | The Action for the menu item will not exist in your own code, | 
|  | since it already exists in the API of the TopComponent class. | 
|  | You simply need to refer to that API in your Action definition | 
|  | in the <code>layer.xml</code> file, while referring to that | 
|  | Action from the Menu folder:</p> | 
|  |  | 
|  | <pre class="examplecode"><folder name="Actions"> | 
|  | <folder name="Window"> | 
|  | <file name="org-demo-mymodule-HelloAction.instance"> | 
|  | <attr name="component" methodvalue="org.demo.mymodule.HelloTopComponent.findInstance"/> | 
|  | <attr name="displayName" bundlevalue="org.demo.mymodule.Bundle#CTL_HelloAction"/> | 
|  | <attr name="instanceCreate" methodvalue="org.openide.windows.TopComponent.openAction"/> | 
|  | </file> | 
|  | </folder> | 
|  | </folder> | 
|  | <folder name="Menu"> | 
|  | <folder name="Window"> | 
|  | <file name="HelloAction.shadow"> | 
|  | <attr name="originalFile" stringvalue="Actions/Window/org-demo-mymodule-HelloAction.instance"/> | 
|  | </file> | 
|  | </folder> | 
|  | </folder></pre> | 
|  |  | 
|  | <p>Above, you're registering the <code><a href="http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#openAction%28org.openide.windows.TopComponent,%20java.lang.String,%20java.lang.String,%20boolean%29">TopComponent.openAction</a></code> | 
|  | factory method defined in the Window System API.</p> | 
|  | </li> | 
|  |  | 
|  | <li><p>Add the following to the <code>Bundle.properties</code> file:</p> | 
|  |  | 
|  | <pre class="examplecode">CTL_HelloAction=Hello | 
|  | CTL_HelloTopComponent=Hello Window</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>In the module project folder, create a file named <code>project.xml</code>, | 
|  | which the NetBeans Platform | 
|  | uses to specify module dependencies in the <code>manifest.mf</code> | 
|  | file:</p> | 
|  |  | 
|  | <pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> | 
|  | <project xmlns="https://netbeans.org/ns/project/1"> | 
|  | <type>org.netbeans.modules.apisupport.project</type> | 
|  | <configuration> | 
|  | <data xmlns="https://netbeans.org/ns/nb-module-project/3"> | 
|  | <code-name-base>org.demo.mymodule</code-name-base> | 
|  | <suite-component/> | 
|  | <module-dependencies> | 
|  | <dependency> | 
|  | <code-name-base>org.netbeans.modules.settings</code-name-base> | 
|  | <build-prerequisite/> | 
|  | <compile-dependency/> | 
|  | <run-dependency> | 
|  | <release-version>1</release-version> | 
|  | <specification-version>1.26.1</specification-version> | 
|  | </run-dependency> | 
|  | </dependency> | 
|  | <dependency> | 
|  | <code-name-base>org.openide.awt</code-name-base> | 
|  | <build-prerequisite/> | 
|  | <compile-dependency/> | 
|  | <run-dependency> | 
|  | <specification-version>7.23.1</specification-version> | 
|  | </run-dependency> | 
|  | </dependency> | 
|  | <dependency> | 
|  | <code-name-base>org.openide.util</code-name-base> | 
|  | <build-prerequisite/> | 
|  | <compile-dependency/> | 
|  | <run-dependency> | 
|  | <specification-version>8.6.1</specification-version> | 
|  | </run-dependency> | 
|  | </dependency> | 
|  | <dependency> | 
|  | <code-name-base>org.openide.util.lookup</code-name-base> | 
|  | <build-prerequisite/> | 
|  | <compile-dependency/> | 
|  | <run-dependency> | 
|  | <specification-version>8.3.1</specification-version> | 
|  | </run-dependency> | 
|  | </dependency> | 
|  | <dependency> | 
|  | <code-name-base>org.openide.windows</code-name-base> | 
|  | <build-prerequisite/> | 
|  | <compile-dependency/> | 
|  | <run-dependency> | 
|  | <specification-version>6.33.1</specification-version> | 
|  | </run-dependency> | 
|  | </dependency> | 
|  | </module-dependencies> | 
|  | <public-packages/> | 
|  | </data> | 
|  | </configuration> | 
|  | </project></pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>On the command line, go to the "ABC/myapp" folder and run this:</p> | 
|  |  | 
|  | <pre class="examplecode">ant run</pre> | 
|  |  | 
|  | </li> | 
|  |  | 
|  | <li><p>The application starts up and shows a new window, which can also be | 
|  | opened from the Window menu.</p> | 
|  | <p><img src="../images/tutorials/ant/ant-result-2.png" alt="structure 1"/></p> | 
|  |  | 
|  | </li> | 
|  | </ol> | 
|  |  | 
|  | <p>Congratulations, you've successfully set up a pure Ant-based application structure | 
|  | for working with the NetBeans Platform.</p> | 
|  |  | 
|  | <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20EMF%20Integration%20Tutorial">Send Us Your Feedback</a></div> | 
|  | <br style="clear:both;" /> | 
|  |  | 
|  | </body> | 
|  |  | 
|  | </html> |