/** * MouseController.java * (c) Peter Bielik and Radek Burget, 2011-2012 * * SwingBox is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SwingBox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SwingBox. If not, see <http://www.gnu.org/licenses/>. * */ package org.fit.cssbox.swingbox.util; import java.awt.Cursor; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.net.MalformedURLException; import java.net.URL; import javax.swing.JEditorPane; import javax.swing.SwingUtilities; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent.EventType; import javax.swing.text.AttributeSet; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Element; import javax.swing.text.Position; import javax.swing.text.Position.Bias; import javax.swing.text.StyledDocument; import javax.swing.text.html.HTMLFrameHyperlinkEvent; import org.fit.cssbox.layout.TextBox; import org.fit.cssbox.swingbox.SwingBoxDocument; /** * This class adds the "mouse support" to BrowserPane - generates * HyperlinkEvents. * * @author Peter Bielik * @author Radek Burget */ public class MouseController extends MouseAdapter { private static final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); private static final Cursor textCursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR); private Element prevElem; private Anchor prevAnchor; @Override public void mouseClicked(MouseEvent e) { JEditorPane editor = (JEditorPane) e.getSource(); if (!editor.isEditable() && SwingUtilities.isLeftMouseButton(e)) { Bias[] bias = new Bias[1]; Point pt = new Point(e.getX(), e.getY()); int pos = editor.getUI().viewToModel(editor, pt, bias); if (bias[0] == Position.Bias.Backward && pos > 0) pos--; //Point pt = new Point(e.getX(), e.getY()); //int pos = editor.viewToModel(pt); // System.err.println("found position : " + pos); if (pos >= 0) { Element el = ((SwingBoxDocument) editor.getDocument()).getCharacterElement(pos); AttributeSet attr = el.getAttributes(); Anchor anchor = (Anchor) attr.getAttribute(Constants.ATTRIBUTE_ANCHOR_REFERENCE); if (anchor != null && anchor.isActive()) createHyperLinkEvent(editor, el, anchor, EventType.ACTIVATED); } } } @Override public void mouseMoved(MouseEvent e) { JEditorPane editor = (JEditorPane) e.getSource(); if (!editor.isEditable()) { Bias[] bias = new Bias[1]; Point pt = new Point(e.getX(), e.getY()); int pos = editor.getUI().viewToModel(editor, pt, bias); if (bias[0] == Position.Bias.Backward && pos > 0) pos--; if (pos >= 0 && (editor.getDocument() instanceof StyledDocument)) { Element elem = ((StyledDocument) editor.getDocument()).getCharacterElement(pos); Object bb = elem.getAttributes().getAttribute(Constants.ATTRIBUTE_BOX_REFERENCE); Anchor anchor = (Anchor) elem.getAttributes().getAttribute(Constants.ATTRIBUTE_ANCHOR_REFERENCE); //System.out.println("Pos: " + pos); //System.out.println("Elem: " + elem.getAttributes().getAttribute(Constants.ATTRIBUTE_BOX_REFERENCE)); //System.out.println("Anchor: " + anchor); if (elem != prevElem) { prevElem = elem; if (!anchor.isActive()) { if (bb != null && bb instanceof TextBox) setCursor(editor, textCursor); else setCursor(editor, defaultCursor); } } if (anchor != prevAnchor) { if (prevAnchor == null) { if (anchor.isActive()) { createHyperLinkEvent(editor, elem, anchor, EventType.ENTERED); } prevAnchor = anchor; } else if (!prevAnchor.equalProperties(anchor.getProperties())) { if (prevAnchor.isActive()) { createHyperLinkEvent(editor, prevElem, prevAnchor, EventType.EXITED); } if (anchor.isActive()) { createHyperLinkEvent(editor, elem, anchor, EventType.ENTERED); } prevAnchor = anchor; } } } else //nothing found { prevElem = null; if (prevAnchor != null && prevAnchor.isActive()) { createHyperLinkEvent(editor, prevElem, prevAnchor, EventType.EXITED); prevAnchor = null; } setCursor(editor, defaultCursor); } } } private void createHyperLinkEvent(JEditorPane editor, Element elem, Anchor anchor, EventType type) { HyperlinkEvent linkEvent; String href = anchor.getProperties().get(Constants.ELEMENT_A_ATTRIBUTE_HREF); String target = anchor.getProperties().get(Constants.ELEMENT_A_ATTRIBUTE_TARGET); URL url; URL base = (URL) editor.getDocument().getProperty(DefaultStyledDocument.StreamDescriptionProperty); try { url = new URL(base, href); } catch (MalformedURLException ignored) { url = null; } linkEvent = new HTMLFrameHyperlinkEvent(editor, type, url, href, elem, target); editor.fireHyperlinkUpdate(linkEvent); } protected void setCursor(JEditorPane editor, Cursor cursor) { if (editor.getCursor() != cursor) { editor.setCursor(cursor); } } }