Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Adding the NetBeans HTML Source Editor to the Visual HTML Editor

DZone's Guide to

Adding the NetBeans HTML Source Editor to the Visual HTML Editor

· Java Zone
Free Resource

Microservices! They are everywhere, or at least, the term is. When should you use a microservice architecture? What factors should be considered when making that decision? Do the benefits outweigh the costs? Why is everyone so excited about them, anyway?  Brought to you in partnership with IBM.

As a follow up to my previous article here I'll show you how to add the NetBeans HTML Editor as a source code view for the FCKEditor/CKEditor using the NetBeans MultiView Window API. Thanks to some help from Geertjan Wielenga I finally got this working. :-) You can of course choose to use the HTML Editor without using the MultiView Window API, instead rolling your own "multiview" with JTabs, for instance.

To get down to business, this is what we are trying to achieve:



And:



This way we can get the best of two worlds, a nice functional Word-like interface for our users without knowledge of HTML and we can give our power users access to the HTML source code with syntax highlighting.

These are the steps I took to get this to work:

1.) Created a new module HTMLEditorMultiView and added the following dependencies:

  • Datasystems API
  • DJNativeSwingAPI
  • Editor Library 2
  • File System API
  • Lookup
  • MultiView Windows
  • Nodes API
  • Settings API
  • Text API
  • UI Utilities API
  • Utilities API
  • Window System API - Need to add this from the Platform-cluster.

Now you need to add several dependencies on the IDE Cluster and MultiView Windows from the Platform cluster.
The way you add this is by going to the properties view on your platform application and clicking on Libraries.
Select IDE->HTML and HTML Editor and add any dependencies. Also add the MultiView Windows from the Platform cluster.

And finally you have to add, and this is important, the "Lexer to NetBeans Bridge" from the IDE cluster. (Thanks Geertjan!)
This, for some reason, isn't added automatically but you won't get syntax highlighting without it.

2.) Created two JPanels, HTMLEditorPanel and HTMLSourcePanel that both implement MultiViewElement.

HTMLEditorPanel.java - Set the layout to BorderLayout.

    private JToolBar toolbar = new JToolBar();
    private MultiViewElementCallback callback = null;
    private static Browser createBrowser;

    public HTMLEditorPanel() {
        initComponents();

        BrowserProvider bp = Lookup.getDefault().lookup(BrowserProvider.class);
        if(bp!=null)
        {
            createBrowser = bp.createBrowser();
    add(createBrowser.getBrowserComponent(),BorderLayout.CENTER);
        }
    }

    public static String getHTMLSource()
    {
        return createBrowser.getEditorContents();
    }
    public static void setHTMLSource(String source)
    {
        createBrowser.setEditorContents(source);
    }

    @Override
    public JComponent getVisualRepresentation() {
        return this;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        return toolbar;
    }

    @Override
    public Action[] getActions() {
        if(callback != null)
            return callback.createDefaultActions();
        else
            return new Action[] {};
    }

    @Override
    public Lookup getLookup() {
        return Lookups.singleton(this);
    }

    @Override
    public void componentOpened() {
        callback.updateTitle("HTML Designer");
    }

    @Override
    public void componentClosed() {

    }

    @Override
    public void componentShowing() {

    }

    @Override
    public void componentHidden() {

    }

    @Override
    public void componentActivated() {
        callback.updateTitle("HTML Designer");
    }

    @Override
    public void componentDeactivated() {

    }

    @Override
    public UndoRedo getUndoRedo() {
        return UndoRedo.NONE;
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback mvec) {
        callback = mvec;
    }

    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }


HTMLSourcePanel.java
Add a JEditorPane to the JPanel, I called it jep in my code.

    private JToolBar toolbar = new JToolBar();
    private MultiViewElementCallback callback = null;

    public HTMLSourcePanel() {
        initComponents();

        EditorKit kit = CloneableEditorSupport.getEditorKit("text/x-html");
        jep.setEditorKit(kit);
        FileObject fob;
        try {
            fob = FileUtil.createMemoryFileSystem().getRoot().createData("tmp", "html");
            DataObject dob = DataObject.find(fob);
            jep.getDocument().putProperty(
                    Document.StreamDescriptionProperty,
                    dob);
            DialogBinding.bindComponentToFile(fob, 0, 0, jep);
            jep.setText("");

        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    @Override
    public JComponent getVisualRepresentation() {
        return this;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        return toolbar;
    }

    @Override
    public Action[] getActions() {
        if(callback != null)
            return callback.createDefaultActions();
        else
            return new Action[] {};
    }

    @Override
    public Lookup getLookup() {
        return Lookups.singleton(this);
    }

    @Override
    public void componentOpened() {
        callback.updateTitle("Source");
    }

    @Override
    public void componentClosed() {

    }

    @Override
    public void componentShowing() {
        jep.setText(HTMLEditorPanel.getHTMLSource());
    }

    @Override
    public void componentHidden() {
    }

    @Override
    public void componentActivated() {
    }

    @Override
    public void componentDeactivated() {
        HTMLEditorPanel.setHTMLSource(jep.getText());
    }

    @Override
    public UndoRedo getUndoRedo() {
        return UndoRedo.NONE;
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback mvec) {
        callback = mvec;
    }

    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }
Now we need to add HTMLEditorPanelDescription.java and HTMLSourcePanelDescription.java these implement MultiViewDescription and Serializable.
import java.awt.Image;
import java.io.Serializable;
import org.netbeans.core.spi.multiview.MultiViewDescription;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.openide.util.HelpCtx;
import org.openide.windows.TopComponent;

public class HTMLSourcePanelDescription implements MultiViewDescription, Serializable
{

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_NEVER;
    }

    @Override
    public String getDisplayName() {
        return "Source";
    }

    @Override
    public Image getIcon() {
        return null;
    }

    @Override
    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }

    @Override
    public String preferredID() {
        return "HTML_SOURCE";
    }

    @Override
    public MultiViewElement createElement() {
        return new HTMLSourcePanel();
    }

}
import java.awt.Image;
import java.io.Serializable;
import org.netbeans.core.spi.multiview.MultiViewDescription;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.openide.util.HelpCtx;
import org.openide.windows.TopComponent;

public class HTMLEditorPanelDescription implements MultiViewDescription, Serializable {

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_NEVER;
    }

    @Override
    public String getDisplayName() {
        return "Designer";
    }

    @Override
    public Image getIcon() {
        return null;
    }

    @Override
    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }

    @Override
    public String preferredID() {
        return "HTML_DESIGNER_1";
    }

    @Override
    public MultiViewElement createElement() {
        return new HTMLEditorPanel();
    }
}
And finally you need some way to launch this MultiView HTML Editor, for the sake of simplicity I just added an explorer window with a JButton that did the trick.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        MultiViewDescription[] mvd = {
        new HTMLEditorPanelDescription(),
        new HTMLSourcePanelDescription()
        };
        TopComponent tc = MultiViewFactory.createMultiView(mvd, mvd[0]);
        tc.open();
}

As a side note, you might want to consider, in the two JPanels, to use one of the other functions to push and pull the contents of the WYSIWYG editor. As the different functions hook into different parts of the lifecycle, but for small documents the chosen approach seems to work just fine.

I haven't been able to get Code Completion to work within the HTML Editor, so if you get it working please feel free to leave a comment! :-)

Discover how the Watson team is further developing SDKs in Java, Node.js, Python, iOS, and Android to access these services and make programming easy. Brought to you in partnership with IBM.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}