Fwd: [platform-dev] Re: NB Editor Notes

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Fwd: [platform-dev] Re: NB Editor Notes

ThSITC
Just *again* telling you, what *others* are *doing*! :-)

Thomas.
===============================================


-------- Original-Nachricht --------
Betreff: [platform-dev] Re: NB Editor Notes
Datum: Wed, 28 Nov 2012 10:48:40 +0100
Von: Geertjan Wielenga [hidden email]
Antwort an: [hidden email]
An: [hidden email]




Plus, in your own blog and/or on NetBeans Zone (the more places the better) -- it's really great info.

Gj

On 11/28/2012 09:36 AM, Tim Boudreau wrote:
This would be great material to add to the Developer FAQ (it's a wiki - any community member can add stuff):

Nice writeup,

-Tim


On Sun, Nov 25, 2012 at 8:09 PM, Steven Yi <[hidden email]> wrote:
Hi All,

I've been looking into the Netbeans Editor infrastructure quite a bit
in order to use various parts.  Geertjan has done some nice blog posts
that talked about getting code completion working, and there are some
good tutorials for Antlr and JavaCC for getting syntax highlighting
and other features going.  However, my current need is to replace a
text editor component I was using, and I had to do some further work
to be able to replace what I had.  I thought I'd share here some notes
of mine on what I found out, in hopes it might be useful to some and
perhaps can be corrected by others if I'm mistaken.

* The NB Editor system revolves around the use of NbEditorKit and
NbEditorDocument, used in conjunction with JEditorPane.

* To get Code Completion working, you need to have a NbEditorKit that
is registered to a mime-type, then a CodeCompletionProvider that is
registered to the same mime-type.  You also need to make sure the
NbEditorDocument has the same mime-type. Once you have that, code
completion will work.

* Creating a subclass of NbEditorKit that returns your mime-type in
getContentType() is probably the easiest way to do this, for example:

public class CsoundOrcEditorKit extends NbEditorKit {

    @Override
    public Document createDefaultDocument() {

        Document doc = new CsoundOrcEditorDocument(getContentType());
        doc.putProperty(Language.class, CsoundOrcTokenId.language());
        return doc;
    }

    @Override
    public String getContentType() {
        return "text/x-csound-orc";
    }

    public class CsoundOrcEditorDocument extends NbEditorDocument {

        public CsoundOrcEditorDocument(Class kitClass) {
            super(kitClass);
        }

        public CsoundOrcEditorDocument(String mimeType) {
            super(mimeType);
        }

    }

}


That can be registered in layer.xml, for example, in the folder
Editor/text/x-csound-orc, I have:

        <file name="EditorKit.instance">
          <attr name="instanceClass"
stringvalue="blue.ui.editor.csound.orc.CsoundOrcEditorKit"/>
          <attr name="instanceOf"
stringvalue="javax.swing.text.EditorKit,blue.ui.editor.csound.orc.CsoundOrcEditorKit"/>
          <attr name="beaninfo" boolvalue="false"/>
        </file>


After that, I'm able to use
CloneableEditorSupport.getEditorKit("text/x-csound-orc") and set that
on a JEditorPane.  With that, the CodeCompletionProvider I registered
there works.

* At this point, to get Syntax Highlighting, you only need a Lexer,
and do not need a Parser.  The Lexer needs to implement
org.netbeans.spi.lexer.Lexer.  I first tried using Antlr, but as I'm
not so experienced with it, I ended up modifying the example hand-made
Lexer from the "How to use certain Netbeans APIs" page:

http://bits.netbeans.org/dev/javadoc/usecases.html

(under "How to use Lexer?", specifically under the "SPI Use Cases")
After writing the Lexer, I was able to register it with this in
layer.xml:

<file name="language.instance">
          <attr name="instanceCreate"
methodvalue="com.kunstmusik.syntax.CsoundOrcTokenId.language"/>
          <attr name="instanceOf"
stringvalue="org.netbeans.api.lexer.Language"/>
        </file>

(also in Editor/text/x-csound-orc)

* The next step I wanted to take was to use declarative registration
of actions for the popup menu.  However, at this point, even if you
put Actions in the Popup folder (i.e. Editor/text/x-csound-orc/Popup),
they will not show up in your JEditorPane.  I found that the code that
assembles the popup checks if the NbEditorDocument has built an
extended custom editor or not.  If it hasn't, then the popup will not
generate.  It seems to me that the Editor infrastructure is really
built around the idea that it will build a CloneableEditor (a
TopComponent) for each mime-type, rather than designed for use with
any particular JEditorPane.  To get around this, I found I had to do
some of the same things that were happening in CloneeableEditor.
Specifically, I ended up using this utility function:

public static Component convertEditorForMimeType(JEditorPane editor,
String mimeType) {

        Component retVal = editor;
        EditorKit kit = CloneableEditorSupport.getEditorKit(mimeType);
        editor.setEditorKit(kit);

        BaseDocument doc = Utilities.getDocument(editor);

        if (doc instanceof NbDocument.CustomEditor) {
            NbDocument.CustomEditor ce = (NbDocument.CustomEditor) doc;
            retVal = ce.createEditor(editor);
        } else {
            retVal = new JScrollPane(editor);
        }

        return retVal;
  }


Given a JEditorPane and a mimeType, this will try to build the custom
editor.  In the NbEditorDocument, what happens is that it ends up
wrapping the JEditorPane and returning a JPanel.  It adds things like
the gutter and status line and turns on line numbering, but most
importantly, things are now set for other parts of the Editor library
to work.  Using the returned Component, I saw line numbers as well as
popup actions now showing.

To simplify things, I made a utility UI class for that calls the above:

public class MimeTypeEditorComponent extends JPanel {

    JEditorPane editor = new JEditorPane();

    public MimeTypeEditorComponent(){
        this("text/plain");
    }

    public MimeTypeEditorComponent(String mimeType) {
        this.setLayout(new BorderLayout());
        this.add(BlueNbUtilities.convertEditorForMimeType(editor, mimeType));
    }

    public JEditorPane getJEditorPane() {
        return editor;
    }

}


This component will handle creating the extended editor or not, and
ensure that a scroll pane is added if the extended editor doesn't get
created.  It also keeps a reference to the JEditorPane so that you can
call getDocument() on it later.

===
That's as far as I've gotten so far; I'm still testing/experimenting
and I'm sure to run into further issues (hopefully not too many!).

Hope this might be useful!

steven



--



--
http://www.thsitc.com Austria, Europe Skype ID: Thomas.Schneider.Wien Yahoo ID: [hidden email] FaceBook ID: Thomas.Schneider.Wien Member of the Rexx Languge Asscociation (www.rexxla.org) Member of the NetRexx Developer's Team (www.netrexx.org)




_______________________________________________
Ibm-netrexx mailing list
[hidden email]
Online Archive : http://ibm-netrexx.215625.n3.nabble.com/

Thomas Schneider, Vienna, Austria (Europe) :-)

www.thsitc.com
www.db-123.com