views:

458

answers:

5

I have an idea to write a note-taking app in Java that does some simple text replacement as you type; probably a small subset of the Markdown syntax. So for instance, if you entered a line that was #sometext, it would get rendered:

sometext

Wikidpad is part of what I'm trying to do (I'm not just re-implementing that, just parts of the syntax/display functionality).

So essentially I'm looking for a way to write some kind of component that, when the user hits "return," it will look at the line entered and do any magic it needs to do to get the html tags right.

I've been beating my head against Documents and DocumentFilters and DocumentListeners and HTMLReaders and such without much luck, can anyone put me on the right path?

+1  A: 

Sounds like what you need to do is implement some sort of key listener in your editor component that examines key strokes before they enter the text field. It can then search back in the buffer, find your control characters and do what ever it needs to do.

I don't have a whole lot of experience with JEditorPanes and the like. But I think you can add key listeners to them just like any other swing component.

Basically I don't think there is a component like this that exists so you'll essentially need to implement your own.

I might be wrong though.

Daniel Bingham
Yes, I've played with keylisteners, but they don't seem to consume the key event, so I can't "do what I need to do" before the pane has already stuck the character in its content.
slide_rule
A: 

Does it have to happen when they hit enter, or just when they submit the data?

If it's on submit, wait for them to press a button that would save the data, then do JEditorPane.getText(), "fix" the text, and do JEditorPane.setText(text);

Okay, if it should be on the fly, try adding an Input Method Listener. InputMethodEvent should be able to call "getText()", and you should be able to parse for this after every keypress. If you want to do it after every time the user hits enter, get the text on every keypress, and see if the current location in the text is one character after an \n, or similar.

Dean J
I'd like to do it on the fly.
slide_rule
A: 

At first I recommend to use JTextPane, since this is more suitable for applying styles to text. Then, it is very easy to add a keyPressed event:

jTextPane1.addKeyListener(new java.awt.event.KeyAdapter() {
    public void keyPressed(java.awt.event.KeyEvent evt) {
     jTextPane1KeyPressed(evt);
    }
});

private void jTextPane1KeyPressed(java.awt.event.KeyEvent evt) {
    // TODO add your handling code here:
    String txt = jTextPane1.getText();

}

The above code was easily generated with Netbeans.

You can then apply styles doing something like this:

StyledDocument doc = jTextPane1.getStyledDocument();
Style style = jTextPane1.addStyle("Bold", null);
StyleConstants.setBold(style, true);

int pos, endpos;
// Find pos of word to be displayed in bold
...

// Set style
doc.setCharacterAttributes(pos, endpos, style, true);
kgiannakakis
slide_rule
You could use evt.getKeyChar() and read the whole text, only when is needed to. Set a flag when '#' is first pressed and then read the text and apply the format when space/new line is pressed. You should also cater for the case a user pastes text into the control. You can monitor meta characters for such events.
kgiannakakis
A: 

Use RSyntaxTextArea, it does what you need and you can add your own lexer/rules.

adrian.tarau
I will definitely check it out.
slide_rule
+1  A: 

What you are interested in is a java text editor kit. This tutorial was great and helped me implement a wiki-editor that sounds similar to your problem. The swing Editor kit (believe it or not) is specifically designed to handle your problem. I've written a dynamic wiki like linking system using this technique, albeit not without a lot of struggle. Here's what I had to do:

  1. Make a Document The first task is to create a document model that tags the pattern when it identifies the text. If you look at the JavaDocument in the linked example there is an insertUpdate call. In the document you can find the pattern you are looking for and replace it with a custom style appropriate. Essentially you just create a style and apply it to the document where the pattern is matched. An alternative to the update method is to make this use a private worker thread to periodically scan for new wiki content.

  2. Build a rendering Context After your model is complete you can implement a Context that builds a view appropriate to rendering your new text. In the linked example they extend a StyleContext. This is what is used to render the text to the view. Here you can set rendering rules that will find your specific tag and do something like underline it and remove the square brackets.

  3. Make an editor kit This will stitch everything together and identify a content type for your document.

The good thing about keeping the document and view as separate contexts is you can attach the document to two views, one in plain text, the other in your new custom context. Since the default style doesn't recognize your tag it should display it in the raw wiki code form. The new view will transform the view into the appropriate linking.

I hope this helps. A word of caution, this stuff is unfortunately complex, even for swing. Good luck!

reccles
Yes, that's where I've been headed - but I hadn't run across that tutorial yet. It's been frustratingly complex, but I think that page will help a lot.
slide_rule
I understand your frustration. The text editor could use some code usability refactoring
reccles