Thanks for Open Sourcing IntelliJ IDEA
Without the Groovy facet, I would have been totally lost. I doubt that, now that that Groovy facet is available in the open source, a tutorial on facets is even needed. Simply read the Groovy facet and adapt it to your own purposes, as I did here:
Open source rocks!
Extending IntelliJ IDEA for NetBeans Platform Development
The above, which is in the free community edition, implies a future where NetBeans Platform development will be a first-class development option in IntelliJ IDEA. I have the basic plugin set up, as you can see above. However, is there someone who can tell me how I should continue from here? I need to be able to (1) set things on the classpath, (2) create runtime configurations, and (3) generate folders and files when Finish is clicked above.
Another option would be to hook a project in IntelliJ IDEA into an Ant script such as the one created in the NetBeans Platform Ant Tutorial. For example, when "Run" is invoked on the project, the related target in the NetBeans Platform would be invoked, via the Ant script outlined in the tutorial.
Any advice from IntelliJ IDEA API users out there?
JDesktopPane, JInternalFrame, and TopComponent
However, it would be better if the JInternalFrames were to be TopComponents instead. Any clues?
Here's how I created the above TopComponent:
...
...
...
private JDesktopPane jdpDesktop;
private int openFrameCount = 0;
public DemoTopComponent() {
initComponents();
setName(NbBundle.getMessage(DemoTopComponent.class, "CTL_DemoTopComponent"));
setToolTipText(NbBundle.getMessage(DemoTopComponent.class, "HINT_DemoTopComponent"));
setLayout(new BorderLayout());
jdpDesktop = new JDesktopPane();
createFrame(); // Create first window
createFrame(); // Create second window
createFrame(); // Create third window
//Add the JDesktop to the TopComponent
add(jdpDesktop);
}
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
jdpDesktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
}
}
class MyInternalFrame extends JInternalFrame {
int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
setLocation(xPosition * openFrameCount, yPosition * openFrameCount);
// Add some content:
add(new JLabel("hello IFrame #" + (openFrameCount)));
}
}
...
...
...
Hope someone has ideas on how to use TopComponents instead of JInternalFrames in this scenario!
NetBeans RCP via Ant + No NetBeans IDE
It's a pretty simplistic tutorial, which is based on the three part "Bye NetBeans IDE" series that has appeared in this blog over the past weeks, but gets the point across, I think. There's definitely enough info there to get up and running on the NetBeans Platform with Ant and the command line. I plan to add more info, on how to set dependencies between modules, how to add windows, and how to extend the Options window.
Here's the link to the tutorial, let me know if any info is missing or incorrect:
http://platform.netbeans.org/tutorials/nbm-ant.html
Bye NetBeans IDE (Part 3)
Creating the Module Structure
- Module Root Folder. Create a new folder within the application's main folder. Name it, for example, MyModule.
- Module Project Folder. Copy the application project folder into the module root folder. In other words, you will use the application project folder as the starting point for your module project folder.
- Suite Properties. In the module project folder, delete the 'platform.properties' file. Instead of a 'platform.properties' file, you need a 'suite.properties' file, which will point to the application that owns the module. It should have this content:
suite.dir=${basedir}/.. - Build Script. In the module root folder, create a 'build.xml' file, with this content:
<?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> - Manifest. In the module root folder, create a 'manifest.mf' file, with this content:
Manifest-Version: 1.0 OpenIDE-Module: org.demo.mymodule OpenIDE-Module-Specification-Version: 1.0
- Build-Impl Script. In the module project folder, create a file named 'build-impl.xml', with this content:
<?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="http://www.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="http://www.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="http://www.netbeans.org/ns/nb-module-project/2"/> <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> <import file="${harness.dir}/build.xml"/> </project> - Project Properties. In the module project folder, change the file named 'project.properties', to this content:
javac.source=1.6 javac.compilerargs=-Xlint -Xlint:-serial
- Project Configuration. In the module project folder, change the file named 'project.xml', to this content:
<?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/3"> <code-name-base>org.demo.mymodule</code-name-base> <suite-component/> <module-dependencies> </module-dependencies> <public-packages/> </data> </configuration> </project> - Main Package. In the module root folder, create folder structure 'src/org/demo/mymodule'. The content will be added later, we simply need to have the main package.
Registering the Module
Now that you have a module structure, lets register it in the application.
- Project Properties. In the application project folder, create a 'project.properties' file for the application, add this:
app.name=myapp branding.token=${app.name} modules=\ ${project.org.demo.mymodule} project.org.demo.mymodule=MyModule - Platform Properties. Change the 'platform.properties' file of the application to this:
nbplatform.active=default nbplatform.active.dir=/home/geertjan/Aaa/nbrcp/ harness.dir=${nbplatform.active.dir}/harness cluster.path=${nbplatform.active.dir}/platform disabled.modules= - Try It Out. Run the application and you'll see the module is loaded, by looking in the output:
Adding a Feature to the Module
We'll use the module to provide a new menu item to the application.
- Add an Action. In the "org.demo.mymodule" package, add a class named 'HelloWorldAction', with this content:
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..."); } } - Add a Layer. In the main package, create a new 'layer.xml' file that registers an Action item and a Menu item:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.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> - Add a Bundle. In the main package, add a file named 'Bundle.properties' with this content:
CTL_HelloWorldAction=Hello World
- Register the Layer and Bundle. Register the latter two files in the 'manifest.mf', which is in your module root folder:
OpenIDE-Module-Layer: org/demo/mymodule/layer.xml OpenIDE-Module-Localizing-Bundle: org/demo/mymodule/Bundle.properties
Run the application. It starts up and there's a new menu item under the Window menu.
How to Get Started Porting a Swing App to the NetBeans RCP???
Here's the direct link:
http://platform.netbeans.org/tutorials/nbm-porting-basic.html
Many thanks to Pierre-Yves Rouille, who provided many very useful comments on the above tutorial and motivated me to continue working on it!
As you can tell from the URL, an advanced porting tutorial is being planned (i.e., nbm-porting-advanced.html). I have some ideas of what should be in there—if anyone else out there has suggestions, please feel free to leave them in the comments to this blog entry.
Happy porting!
How Evil is "instanceof"? (Part 2)
The result of the code that follows, which completely replaces the LibraryNode class in the previous blog entry, is as follows:
And here's the code received from Josch, which is really quite pretty:
public class LibraryNode extends AbstractNode {
public LibraryNode(Library library) {
super(Children.create(new LibraryFactory(library), true));
setDisplayName(library.getName());
}
private static class LibraryFactory extends ChildFactory<String> {
private final Map<String, Node> categories = new HashMap<String, Node>();
private LibraryFactory(Library library) {
categories.put("Books", new BooksNode(library));
categories.put("Borrowers", new BorrowersNode(library));
}
@Override
protected boolean createKeys(List<String> list) {
list.addAll(categories.keySet());
return true;
}
@Override
protected Node createNodeForKey(String key) {
return categories.get(key);
}
}
}
class BooksNode extends AbstractNode {
public BooksNode(Library library) {
super(Children.create(new BooksFactory(library), true));
setDisplayName("Books");
}
private static class BooksFactory extends ChildFactory<Book> {
private final Library library;
private BooksFactory(Library library) {
this.library = library;
}
@Override
protected boolean createKeys(List<Book> list) {
EList<Book> books = library.getBooks();
for (Book book : books) {
list.add(book);
}
return true;
}
@Override
protected Node createNodeForKey(Book key) {
BeanNode node = null;
try {
node = new BeanNode(key);
node.setDisplayName(key.getTitle());
node.setIconBaseWithExtension("org/library/viewer/book.png");
} catch (IntrospectionException ex) {
Exceptions.printStackTrace(ex);
}
return node;
}
}
}
class BorrowersNode extends AbstractNode {
public BorrowersNode(Library library) {
super(Children.create(new BorrowersFactory(library), true));
setDisplayName("Borrowers");
}
private static class BorrowersFactory extends ChildFactory<Borrower> {
private final Library library;
private BorrowersFactory(Library library) {
this.library = library;
}
@Override
protected boolean createKeys(List<Borrower> list) {
EList<Borrower> borrowers = library.getBorrowers();
for (Borrower borrower : borrowers) {
list.add(borrower);
}
return true;
}
@Override
protected Node createNodeForKey(Borrower key) {
BeanNode node = null;
try {
node = new BeanNode(key);
node.setDisplayName(key.getLastName());
node.setIconBaseWithExtension("org/library/viewer/borrower.png");
} catch (IntrospectionException ex) {
Exceptions.printStackTrace(ex);
}
return node;
}
}
}
Thanks Josch!
Radio Monitoring Toolkit Platform on the NetBeans RCP
Yet another NetBeans Platform application is the CCRM Radio Monitoring Toolkit Platform, with modules providing instrument drivers, IQ based demodulators, data displays, measurements applications, and more. These modules work independently of each others by transferring data through a trace system.
A screenshot:
You can stay informed on the evolution of the platform via the CCRM Platform Blog.
How Evil is "instanceof"?
Here's the code I used for the above scenario:
public class LibraryNode extends AbstractNode {
public LibraryNode(Library library) {
super(Children.create(new SubChildFactory(library), true));
setDisplayName(library.getName());
}
private static class SubChildFactory extends ChildFactory<Object> {
private final Library library;
private SubChildFactory(Library library) {
this.library = library;
}
@Override
protected boolean createKeys(List list) {
EList<Book> books = library.getBooks();
for (Book book : books) {
list.add(book);
}
EList<Borrower> borrowers = library.getBorrowers();
for (Borrower borrower : borrowers) {
list.add(borrower);
}
return true;
}
@Override
protected Node createNodeForKey(Object key) {
BeanNode childNode = null;
try {
childNode = new BeanNode(key);
if (key instanceof Book) {
Book book = (Book) key;
childNode.setDisplayName(book.getTitle());
childNode.setIconBaseWithExtension("org/library/viewer/book.png");
} else if (key instanceof Borrower) {
Borrower borrower = (Borrower) key;
childNode.setDisplayName(borrower.getLastName());
childNode.setIconBaseWithExtension("org/library/viewer/borrower.png");
}
} catch (IntrospectionException ex) {
Exceptions.printStackTrace(ex);
}
return childNode;
}
}
}
Is the above evil and how should it be rewritten to use Lookup? I guess FilterNode should be used.
Update. See part 2 for a solution to the above problem!
Eclipse in a NetBeans Tutorial?
Then, you will be told how to import the EMF-related OSGi bundles into a new NetBeans Platform application. As a next step, you will create a new module and copy the classes generated by Eclipse (e.g., the Supplier and Product classes, together with their supporting classes) into the new module. Finally, you'll create a second module where the suppliers and products will be created and displayed:
That tutorial will, in the end, provide full instructions on a very common need—the need of EMF models to be handled within Swing applications. With NetBeans Platform 6.9, that process is now seamless. It's as easy to import an OSGi bundle as it is to import any other JAR file, while Equinox integration into NetBeans Platform applications ensures that the OSGi framework checks all the dependencies between the bundles when the application starts up. Currently I have all the dependencies correctly set up, the above application now deploys without a single problem message being generated by Equinox. Pretty cool.
In other news. If you understand German, take a look at Michael Müller's new review of Heiko Böck's NetBeans Platform 6.
Ouagadougou on the NetBeans Platform (Part 2)
When you run the above application, you see a general workspace with many different menu items:
Each of the main menus produces a different dialog for handling some data:
The benefit of the current state of the application is that (1) it is well organized, e.g., all the forms in the same package, and (2) all the forms are designed in the Matisse GUI Builder. These two decisions will definitely simplify porting to the NetBeans Platform.
Now, what's the first step in the porting procedure? Simple. We need to identify who the users of the application are. What are they doing with the application? Do all the users need all of the features? Based on the answers to these questions, we can decide where the module boundaries will be. It would be useful to the end user to have only those features available that are actually needed.
What if all features are needed by all users? Then we should determine module boundaries in some other way. Maybe we should identify a workflow in the application, with each step in the workflow being provided by a different module (or set of modules, i.e., a cluster of modules).
Definitely, there could be one single module containing all the entity classes. Then all other modules would depend on the entity module (i.e., this would be the model of the application, providing the API that the rest of the application would implement), without depending on each other. That would result in a modular loosely coupled application, which is the ideal endpoint of a NetBeans Platform porting procedure.
Either way, in rearchitecting this application from monolithic to modular, the above concerns are the first that should be addressed before any other. Probably, after that, we could look at how the NetBeans window system can be leveraged to better organize the UI of the application, i.e., the JPanels in the various dialogs could be displayed in TopComponents instead, each provided by modules dedicated to the feature for which they have been created.
Eclipse Nebula PShelf Widget for Swing
I found commercial versions of the above component, i.e., in its Swing version, and then found this written in 2005, but still completely valid:
JOutlookBar: Building an Outlook-Style Menu Component
Using the above, here's the result:
Nice thing is that each of the additions to the outlook panel could come from the layer, making the component pluggable, in the same way as shown in the article Pluggable JXTaskPane.
SaveAsCapability: For Editor Mode Only
Hence, unless the Node is displayed in a TopComponent in "editor" mode, the SaveAsAction will never be enabled. That's a bit unfortunate. The assumption seems to have been that the SaveAsAction can only be relevant to documents. However, in this case, I'd like to use the "Save As" dialog for a changed Node. Once the explorer view rendering the Node is in a TopComponent in "editor" mode, everything is fine—by adding the SaveAsCapable to the Node at the time when the Node had changed, I am able to enable the SaveAsAction.
Maybe I should create an issue for making the SaveAsCapable relevant to other modes too. Or I will need to create my own Action that is sensitive to SaveAsCapable.
Where to attend a presentation on the NetBeans Platform?
- London. http://java.dzone.com/free-netbeans-rcp-talk-london
- Johannesburg & Cape Town. http://netbeanstraining.co.za
- San Francisco. http://marakana.com/training/java/netbeans_platform.html
What will you learn? How to make large pluggable desktop applications like these.
Is your location not mentioned above? Fine. Invite us. Leave a comment at the end of this blog entry or write to users at edu dot netbeans dot org or write to me at geertjan dot wielenga at sun dot com.
NetBeans HTML Editor and Groovy Editor in a Multiview Component
So, each multiview component represents one article in the CMS. And each article in the CMS is represented by a domain object, with various fields for the article name, date, etc... as well as a field for HTML content. Hence the HTML content shown in the HTML tab of the multiview component should NOT come from an actual HTML file on disk. Instead, the NetBeans MemoryFileSystem should be used, while the features of the NetBeans HTML Editor should be made available for that specific field in the domain object.
After help from Vita Stejskal from the NetBeans editor team, everything is now working as expected:
To illustrate the point, I even integrated the NetBeans Groovy editor into the multiview component, within a new tab:
And one of the best things about it is that each tab is provided by a different module. Handy for the developers, handy for the end users, and handy for the pricing structure of the application.
Complete sources: cms.zip
Outline of NetBeans Platform 6.9 Developer's Guide
- Introduction. Introduces the book, providing a general overview of what is to come.
- Modules. Presents the application that you will create throughout the book, after introducing the concept of modularity, why modularity makes sense, and what its main features are.
- Forms. Starts the creation of the application's forms, via usage of the NetBeans Matisse GUI Builder, which is used to design the JPanels you will need throughout the book. (Of course, there' no rule saying you have to use Matisse, i.e., you could take the instructions and use a different form builder or no form builder at all.)
- Window System. Presents the NetBeans Platform's docking framework and instructs you how to integrate the JPanels created in the previous chapter into it.
- Lookup. Dives into the most complex part of the NetBeans Platform, i.e., how modules can be loosely coupled from each other via the event bus mechanism provided by the NetBeans Lookup infrastructure.
- Actions. Introduces you to the mechanism for registering your Actions into a NetBeans Platform application, focusing on global Actions, since context-sensitive Actions are addressed in the next chapter.
- Nodes & Explorer Views. Argues the case for loosely coupled views via Nodes, explorer views, modules, and Lookup, including an introduction to context-sensitive actions, progress bar, and the integration of Visual Library's widgets.
- File System. Recaps the usage of the central registry (i.e., the System FileSystem) that you've made use of throughout the book, as well as the FileSystem API, extending the application further in the process.
- Data System. Guides you through the resource system found above the File System, that is, the system providing access to file content, while you create a new file type for the application, together with context-sensitive capabilities.
- Dialogs. Presents the built-in dialog classes provided by the NetBeans Platform, with the majority of the chapter focusing on using the Wizard API to create a multi-step dialog for creating new tasks in the application.
- Settings. Shows you how to extend the Options Window with new tabs enabling the user to customize the application and code contributors to centrally register their settings panels.
- Help. Instructs you how to add JavaHelp to the application and how to bind TopComponents and Nodes to context-sensitive help topics.
- Branding. Shows you how to customize the icons, strings, and other brandable parts of the NetBeans Platform, teaching you how to avoid changing the NetBeans Platform sources during the branding stages of the application.
- Distribution. Focuses on how to get the application, in various forms (web start, installer-based, ZIP distribution) to the end user, as well as on how to distribute features and patches that the user can install at runtime into their installed application.
The entire book shows you how to create a very specific application, that is, a Task Manager. At the end of the book, you will not know everything there is to know about the NetBeans Platform (Heiko Boeck's Definitive Guide to the NetBeans Platform is better for that purpose), but you will know how to create a feature-complete application on the NetBeans Platform, for which a book has been mising, until now. So, the book is really targeted at newbies (as is the free Essential NetBeans Platform Refcard), i.e., advanced users are unlikely to find much that they don't know already, though would still gain from seeing all the NetBeans Platform topics presented in a single consecutive argument, as is done in this book.
Some 'limitations' of the book are that it is Ant-based (not Maven-based) and uses the NetBeans module system, rather than OSGi, but then, on the other hand, those aspects (i.e., choosing a module system and choosing a build system) play a relatively minor role in the book, since 90% of it deals with how to use NetBeans APIs, rather than how to configure your environment and ancillary matters of that kind. So, a book focusing on Maven and OSGi in relation to the NetBeans Platform is still to be written, though plenty tutorials exist on those points, so there's nothing stopping you from gaining knowledge in those areas. Also an 'Architect's Guide to the NetBeans Platform' would be a good book to have too, though that hasn't been written yet either. Another 'limitation' is that you have to use NetBeans IDE to follow the book, but until someone creates wizards and templates for creating NetBeans Platform applications in IntelliJ and Eclipse, using NetBeans IDE is the most obvious choice, especially when writing a book of this kind for newbies.
Expect the book to be coming out soon, we're working on the final editing and code checking details at the moment.
Lesser Known Weird Highlights of the Spain/Holland Connection
- Eighty Years' War. The Dutch War of Independence was fought from 1568 to 1648. It began as a revolt against Philip II of Spain, the overlord of the Habsburg Netherlands. The war ended with the Treaty of Westphalia. This revolt partly succeeded with the secession of seven provinces which formed the Dutch Republic. See Wikipedia for details. In other words, to cut a long story short, Spain was to Holland what England was to the American colonists.
- Sinterklaas. The Dutch version of Santa Claus is named Sinterklaas. He arrives on a white horse every year on 5 December, together with his assistants/helpers/slaves (take your pick). But, in an odd twist, that white horse on which Sinterklaas is found is itself found... on a steamboat. And that steamboat, at least officially, comes from... Spain! Also, if you've not been a good little boy or girl, you get put in a bag and taken... to Spain!
- "Den Koning van Hispanje heb ik altijd geëerd." Those are the words of the final line of the first verse of the Dutch national anthem, which you will hear at the start of the Holland/Spain match. What do those words mean? They mean, literally: "The king of Spain I have always honored!" Again, those words relate to the colonial rule of Spain over Holland in the 16th century. However, regardless of their origins, it will be a bit odd to start the Holland/Spain final with Holland vowing to always honor the king of Spain...
There are probably other weird connections like the above in relation to Holland/Spain. Feel free to share them here if you have anything to add... :-)
NetBeans HTML Editor in a Multiview Component
Since the above is the actual HTML Editor used in NetBeans IDE, its features are registered in the layer files of the modules that provide those features. Hence, since the NetBeans HTML Editor provides many features that are not relevant to files in the MemoryFileSystem, such as the one shown in the document above, removing those features is as easy as masking them out in the layer file. For example, I removed the whole popup menu (since everything in there is irrelevant to the above scenario), together with some of the actions in the toolbar, by adding this to a layer file:
<folder name="Editors">
<folder name="Toolbars">
<folder name="Default">
<file name="jump-list-next_hidden"/>
<file name="jump-list-prev_hidden"/>
</folder>
</folder>
<folder name="text">
<folder name="html">
<file name="Popup_hidden"/>
</folder>
</folder>
</folder>
Still buggy and not complete, but here's all the code that produces the above application: MyCMSSystem-alpha2.zip
Modular CMS on the NetBeans Platform
Not really complete yet, but this is what I have so far:
One problem is that I haven't integrated the NetBeans HTML Editor yet, so (as reported yesterday) a few features are missing at the moment, possibly because I'm not using the DialogBinding correctly, so maybe those features could be added without my needing to work with the NetBeans HTML Editor at all. For example, there's no code completion, formatting, or contextual menu, since the above isn't actually the NetBeans HTML Editor, but simply a JEditorPane bound to an HTML file in memory.
A nice feature is that each tab in the multiview window comes from a different module, which could be handy for setting up a modular pricing structure. For example, one tab could be free, while the other could be a commercial tab that the user would plug into the application after having paid for it:
Also, none of the UI modules depend on each other. The "CMSModel" module, which contains the Article object (which has two strings, "title" and "content"), is shared amongst all the other modules. There's another shared module called "CMSArticleContext", which uses Wade's CentralLookup (thanks Toni for the help) for the reason described by Tim (here): "I spent the last couple of days here in New Orleans working with some folks with a similar problem - they are building a CRM application on the NetBeans Platform, and the appropriate context for actions and palettes is the selected Customer - it doesn't matter which window has focus."
In the case of the application above, the context is the Article, while the selection is irrelevant, exactly as in Tim's case.
Bear in mind that it is in a very early state, and still error prone, but, if interested, get it here:
I'll upload the source somewhere sometime soon. Or someone else is welcome to do so.
NetBeans HTML Editor in a JEditorPane
The nice thing is that, simply by setting the content type of the second JEditorPane to text/x-html, I can set the second JEditorPane to the content of the first, when the Evaluate button is clicked. That's all the the Evaluate button does! Aside from code completion, I noticed that code formatting also doesn't work (yet). But keyboard shortcuts, such as Ctrl-E to delete a line, work fine, as was the case in yesterday's blog entry too.

