Results 1 to 4 of 4
Thread: Clickable text in a component
- 10-31-2011, 06:37 PM #1
Clickable text in a component
I'm looking for a way to create a text box, like a JTextArea, that has links that underline when you hover over them. Ideally, when a link is clicked it would call a listener method with the link text as an argument. This is not for HTML. It's more like a remote log file browser.
Edit: the component does not need to do any lexing or parsing. When text is appended to it, the caller will specify if it is a link or not.
Does anyone know if the terminal component in the JTA telnet/ssh library can do this? Or know of another library that can?Last edited by kjkrum; 10-31-2011 at 06:40 PM.
Get in the habit of using standard Java naming conventions!
- 11-04-2011, 09:38 PM #2
Re: Clickable text in a component
Bump, and here is what I have learned.
I could use a JEditorPane and set it to content type text/html. The text I want to display is not HTML, it's ASCII with ANSI X3.64 escape codes. I'd have to parse and convert that to HTML, and insert anchor tags for the text I want to be links.
I've also looked a bit at the internals of the JTA SwingTerminal and VDUBuffer classes. Without modifying that library at all, I think I could use mouse listeners on the SwingTerminal to convert pointer position to character coordinates and change the text attributes in the VDUBuffer when the mouse moves in or out of text I want to be a hyperlink. And also detect clicks the same way.
Both of these possibilities would be a lot of work, though. I just want to make sure there's no off-the-shelf solution before I do this.Get in the habit of using standard Java naming conventions!
- 11-05-2011, 10:15 PM #3
Re: Clickable text in a component
This turned out to be a bit easier than I expected. I extended the SwingTerminal class from JTA and gave it some hyperlink capabilities. This two-file demo is just a crude proof of concept. JTA has some poorly chosen access modifiers, and I've wantonly abused them in this demo. I think for actual use, I'm going to create my own API and wrap a SwingTerminal and VDUBuffer inside it.
HyperlinkTerminal.java
Demo.javaJava Code:import java.awt.Cursor; import java.awt.Font; import java.awt.Point; import java.awt.event.MouseEvent; import de.mud.terminal.SwingTerminal; import de.mud.terminal.VDUBuffer; public class HyperlinkTerminal extends SwingTerminal { private static final long serialVersionUID = 1L; /** * Link character attribute. First bit above the color attributes. */ public static final int LINK = 1 << 14; /** * Character coordinates of the last mouse press on button 1. */ private Point lastPress = null; /** * Character coordinates of the beginning of the link currently * highlighted by the mouse pointer. */ private Point hoverBegin = null; /** * Length of the link currently highlighted by the mouse pointer. */ private int hoverLength = 0; /** * Character buffer. Hides private superclass field of the same name. */ private VDUBuffer buffer; /** * Normal cursor. */ Cursor normalCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); /** * Hand cursor. */ Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); @Override public void mousePressed(MouseEvent evt) { super.mousePressed(evt); if(evt.getButton() == MouseEvent.BUTTON1) { lastPress = mouseGetPos(evt.getPoint()); } } @Override public void mouseReleased(MouseEvent evt) { super.mouseReleased(evt); if(evt.getButton() == MouseEvent.BUTTON1) { Point release = mouseGetPos(evt.getPoint()); if(release.equals(lastPress)) { int attr = buffer.charAttributes[release.y + buffer.windowBase][release.x]; if(attr >= LINK) { // TODO: it's a link } // debug System.err.println("click: " + release.y + ", " + release.x); System.err.println("attributes at click: " + attr); } } } @Override public void mouseMoved(MouseEvent evt) { super.mouseMoved(evt); Point p = mouseGetPos(evt.getPoint()); // if a hover is currently on... if(hoverBegin != null) { // find out if we are still in it if(p.y == hoverBegin.y && p.x >= hoverBegin.x && p.x < hoverBegin.x + hoverLength) { return; } // no... so turn it off else { System.err.println("exited link"); toggleHover(); hoverBegin = null; setCursor(normalCursor); } } // find out if we moved into a new link int attr = buffer.charAttributes[p.y + buffer.windowBase][p.x]; if(attr >= LINK) { System.err.println("entered link"); // find the first column in the link int first = p.x; while(first > 0 && buffer.charAttributes[p.y + buffer.windowBase][first - 1] >= LINK) { --first; } // find the last column int last = p.x; while(last < buffer.width - 1 && buffer.charAttributes[p.y + buffer.windowBase][last + 1] >= LINK) { ++last; } hoverBegin = new Point(first, p.y); hoverLength = last - first + 1; System.err.println("begin: " + hoverBegin.toString() + " length: " + hoverLength); toggleHover(); setCursor(handCursor); } // debug //System.err.println("motion: " + p.y + ", " + p.x); } /** * Toggles the current hover highlight. */ void toggleHover() { for(int i = 0; i < hoverLength; ++i) { int attr = buffer.charAttributes[hoverBegin.y + buffer.windowBase][hoverBegin.x + i]; attr = attr ^ VDUBuffer.UNDERLINE; buffer.charAttributes[hoverBegin.y + buffer.windowBase][hoverBegin.x + i] = attr; } buffer.markLine(hoverBegin.y, 1); redraw(); } public void makeLink(int row, int column, int length) { // TODO: sanity check for(int i = 0; i < length; ++i) { int attr = buffer.charAttributes[row + buffer.windowBase][column + i]; attr = attr | LINK; buffer.charAttributes[row + buffer.windowBase][column + i] = attr; } } public HyperlinkTerminal(VDUBuffer buffer, Font font) { super(buffer, font); this.buffer = buffer; } public HyperlinkTerminal(VDUBuffer buffer) { super(buffer); this.buffer = buffer; } }
Java Code:import javax.swing.JFrame; import de.mud.terminal.SwingTerminal; import de.mud.terminal.vt320; public class Demo { /** * @param args */ public static void main(String[] args) { // stock components vt320 buffer = new vt320(80, 25) { // dummy method public void write(byte[] b) { } }; HyperlinkTerminal terminal = new HyperlinkTerminal(buffer); terminal.setResizeStrategy(SwingTerminal.RESIZE_SCREEN); // frame to display them JFrame frame = new JFrame("Hyperlink SwingTerminal Demo"); frame.getContentPane().add(terminal); // finalize frame frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); // print some text in the terminal buffer.putString("\r\nClick the number: 12345\r\n"); terminal.makeLink(1, 18, 5); //buffer.setBufferSize(30); //for(int i = 0; i < 50; ++i) { // buffer.putString("line " + (i + 1) + "\r\n"); //} //buffer.putString("\033[1;31mHAAAAAY! \033[0;4m0123456789\033[0m\r\nABCDEFGHIJKLMNOPQRSTUVWXYZ "); //buffer.putString("window base: " + buffer.getWindowBase()); } }Get in the habit of using standard Java naming conventions!
- 11-05-2011, 11:25 PM #4
Senior Member
- Join Date
- Jul 2009
- Posts
- 1,143
- Rep Power
- 5
Re: Clickable text in a component
1) Create an ArrayList that tracks all the links. I guess you would need to keep track of all offset and the link itself.
2) Add a MouseListener to the text area to listen for mouse moves and mouse clicks
3) Get the mouse point from the MouseEvent so you can use the viewToModel(...) method of the text area to get the offset of the character at the mouse
4) Loop through the ArrayList to determine is the mouse if over a link
5) When over a link add a Highlighter to the text area. If not over a link, then remove all Highlighters.
Same basic logic for a click.
You will need to create a custom Highlighter to display a line under the text. You can start with the Rectangle Painter « Java Tips Weblog.
Similar Threads
-
JButton not clickable
By StevenTNorris in forum AWT / SwingReplies: 5Last Post: 11-09-2012, 08:59 PM -
Make a clickable moving image?
By scheffetz in forum New To JavaReplies: 1Last Post: 04-08-2011, 07:54 PM -
Disable copy paste in SWT Text Component
By subysri in forum SWT / JFaceReplies: 1Last Post: 09-18-2010, 10:11 AM -
Double Clickable Application
By ellias2007 in forum Advanced JavaReplies: 7Last Post: 03-08-2010, 04:08 PM -
Putting clickable icons on an image
By szakee in forum AWT / SwingReplies: 3Last Post: 04-06-2009, 10:25 AM


1Likes
LinkBack URL
About LinkBacks
Reply With Quote
Bookmarks