[jsword-svn] r1981 - trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic

dmsmith at crosswire.org dmsmith at crosswire.org
Sun Feb 21 08:43:50 MST 2010


Author: dmsmith
Date: 2010-02-21 08:43:50 -0700 (Sun, 21 Feb 2010)
New Revision: 1981

Added:
   trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/URITipMgr.java
Modified:
   trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/TextPaneBookDataDisplay.java
Log:
Updated tooltips for Strong's numbers and morphology. Thanks to Yingjie.

Modified: trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/TextPaneBookDataDisplay.java
===================================================================
--- trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/TextPaneBookDataDisplay.java	2010-02-21 15:24:21 UTC (rev 1980)
+++ trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/TextPaneBookDataDisplay.java	2010-02-21 15:43:50 UTC (rev 1981)
@@ -21,8 +21,8 @@
  */
 package org.crosswire.bibledesktop.display.basic;
 
-import java.awt.Color;
 import java.awt.Component;
+import java.awt.Dimension;
 import java.awt.event.MouseListener;
 import java.beans.PropertyChangeEvent;
 import java.net.MalformedURLException;
@@ -31,9 +31,8 @@
 import java.util.Arrays;
 import java.util.Locale;
 
+
 import javax.swing.JTextPane;
-import javax.swing.JToolTip;
-import javax.swing.border.TitledBorder;
 import javax.swing.event.EventListenerList;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
@@ -77,38 +76,14 @@
  */
 public class TextPaneBookDataDisplay implements BookDataDisplay, HyperlinkListener {
 
+
+
     /**
      * Simple ctor
      */
     public TextPaneBookDataDisplay() {
         converter = ConverterFactory.getConverter();
-
-        uritip = new URITipHelper();
-        this.addURIEventListener(uritip);
-        txtView = new AntiAliasedTextPane() {
-
-            /**
-             * serialVersionUID randomly generated by Eclipse.
-             */
-            private static final long serialVersionUID = 3249709554641593827L;
-            TitledBorder tiptit = new TitledBorder((String) null);
-
-            public String getToolTipText() {
-                tiptit.setTitle(uritip.getTipTitle());
-                return uritip.retrieve(converter);
-            }
-
-            public JToolTip createToolTip() {
-                JToolTip tip = uritip.fetchToolTip();
-                tip.setBorder(tiptit);
-                tip.setComponent(this); // for dynamic content update
-                tip.setBackground(Color.yellow);
-                tip.setForeground(Color.red);
-                return tip;
-            }
-        };
-        txtView.setToolTipText("dummy"); //$NON-NLS-1$
-
+        txtView = new AntiAliasedTextPane();
         txtView.setEditable(false);
         txtView.setEditorKit(new HTMLEditorKit());
         txtView.addHyperlinkListener(this);
@@ -116,8 +91,13 @@
         styledDoc = txtView.getStyledDocument();
         lastStart = -1;
         lastLength = -1;
+        
+        this.addURIEventListener(
+                new URITipMgr(txtView, 
+                        new Dimension(400,300)));
     }
 
+    
     /* (non-Javadoc)
      * @see org.crosswire.bibledesktop.display.BookDataDisplay#clearBookData()
      */
@@ -220,7 +200,7 @@
     /* (non-Javadoc)
      * @see javax.swing.event.HyperlinkListener#hyperlinkUpdate(javax.swing.event.HyperlinkEvent)
      */
-    public void hyperlinkUpdate(HyperlinkEvent ev) {
+    public void hyperlinkUpdate(HyperlinkEvent ev) { 
         // SPEEDUP(DMS): This needs to be optimized. It takes too much CPU
         try {
             HyperlinkEvent.EventType type = ev.getEventType();
@@ -505,8 +485,4 @@
      */
     private EventListenerList listenerList = new EventListenerList();
 
-    /**
-     * The Tool Tip helper for def/lemma/morph URIs.
-     */
-    URITipHelper uritip;
 }

Added: trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/URITipMgr.java
===================================================================
--- trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/URITipMgr.java	                        (rev 0)
+++ trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/display/basic/URITipMgr.java	2010-02-21 15:43:50 UTC (rev 1981)
@@ -0,0 +1,349 @@
+/**
+ * Distribution License:
+ * BibleDesktop is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 2 as published by
+ * the Free Software Foundation. This program 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 General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/gpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2007
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: org.eclipse.jdt.ui.prefs 1178 2006-11-06 12:48:02Z dmsmith $
+ */
+
+package org.crosswire.bibledesktop.display.basic;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.net.URI;
+import java.util.Locale;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.Popup;
+import javax.swing.PopupFactory;
+import javax.swing.Timer;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.html.HTMLEditorKit;
+
+import org.crosswire.bibledesktop.book.install.BookFont;
+import org.crosswire.bibledesktop.desktop.Desktop;
+import org.crosswire.bibledesktop.desktop.XSLTProperty;
+import org.crosswire.bibledesktop.display.URIEvent;
+import org.crosswire.bibledesktop.display.URIEventListener;
+import org.crosswire.common.swing.AntiAliasedTextPane;
+import org.crosswire.common.swing.GuiConvert;
+import org.crosswire.common.swing.GuiUtil;
+import org.crosswire.common.util.Reporter;
+import org.crosswire.common.xml.Converter;
+import org.crosswire.common.xml.SAXEventProvider;
+import org.crosswire.common.xml.TransformingSAXEventProvider;
+import org.crosswire.common.xml.XMLUtil;
+import org.crosswire.jsword.book.Book;
+import org.crosswire.jsword.book.BookCategory;
+import org.crosswire.jsword.book.BookData;
+import org.crosswire.jsword.book.BookMetaData;
+import org.crosswire.jsword.book.Books;
+import org.crosswire.jsword.book.Defaults;
+import org.crosswire.jsword.passage.NoSuchKeyException;
+import org.crosswire.jsword.util.ConverterFactory;
+
+/**
+ * How it works:
+ * 1. It keeps track of mouse movement.
+ * 2. It registers the URI entering event and starts a timer.
+ * 3. When the timer fires, a tip pops up, the timer stopped.
+ * 4. The timer is stopped when a URI leaving event is received.
+ * 5. Whenever mouse clicked outside the tip, it disappears.
+ * 6. Click in the tip to make it sticky, double-click to close. 
+ * 7. If sticky, tip updates as the mouse enters another URI. 
+ *    
+ * @see gnu.gpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Yingjie Lan [lanyjie at yahoo dot com]
+ */
+public class URITipMgr extends MouseAdapter implements ActionListener, MouseMotionListener, URIEventListener {
+    
+    Component owner;
+    JTextPane txtView;
+    JScrollPane scrView;
+    TitledBorder title;
+    Popup popup;
+    boolean sticky;
+
+    int lastx, lasty;
+    URIEvent event;
+    Timer timer;
+
+    Converter converter;
+    
+    public URITipMgr(Component own, Dimension dim) {
+        converter = ConverterFactory.getConverter();
+        owner = own;
+        txtView = new AntiAliasedTextPane();
+        txtView.setEditable(false);
+        txtView.setEditorKit(new HTMLEditorKit());
+        title = new TitledBorder((String) null);
+        scrView = new JScrollPane(txtView);
+        scrView.setBackground(Color.yellow);
+        scrView.setBorder(title);
+        scrView.getViewport().setPreferredSize(dim);
+        // listen to mouse events of the managed component
+        own.addMouseMotionListener(this);
+        own.addMouseListener(this);
+        // also hide popup if clicked inside popup
+        txtView.addMouseListener(this);
+        setDelay(1500);
+    }
+    
+    public void setDelay(int delay){
+        if(timer!=null) timer.stop();
+        timer = new Timer(delay, this);
+    }
+    
+    public void updateText() {
+        if (event == null)
+            return;
+        String txt = null;
+        String protocol = event.getScheme();
+        Book book = null;
+        if (protocol.equals(Desktop.GREEK_DEF_PROTOCOL)) {
+            book = Defaults.getGreekDefinitions();
+            title.setTitle("Greek Definition");
+        } else if (protocol.equals(Desktop.HEBREW_DEF_PROTOCOL)) {
+            book = Defaults.getHebrewDefinitions();
+            title.setTitle("Hebrew Definition");
+        } else if (protocol.equals(Desktop.GREEK_MORPH_PROTOCOL)) {
+            book = Defaults.getGreekParse();
+            title.setTitle("Greek Morphology");
+        } else if (protocol.equals(Desktop.HEBREW_MORPH_PROTOCOL)) {
+            book = Defaults.getHebrewParse();
+            title.setTitle("Hebrew Morphology");
+        }
+
+        if (book == null || Books.installed().getBook(book.getName()) == null) {
+            txtView.setText("Book Unavailable!"); //$NON-NLS-1$
+            title.setTitle("Exception");
+            return;
+        }
+
+        BookData bdata = null;
+
+        try {
+            bdata = new BookData(book, book.getKey(event.getURI()));
+        } catch (NoSuchKeyException ex) {
+            txtView.setText(ex.getDetailedMessage());
+            title.setTitle("Exception");
+            return;
+        }
+
+        assert (book == bdata.getFirstBook());
+
+        BookMetaData bmd = book.getBookMetaData();
+        if (bmd == null) {
+            txtView.setText("Book Meta Data Unavailable!"); //$NON-NLS-1$
+            title.setTitle("Exception");
+            return;
+        }
+
+        // Make sure Hebrew displays from Right to Left
+        boolean direction = bmd.isLeftToRight();
+        String fontSpec = GuiConvert.font2String(BookFont.instance().getFont(book));
+        try {
+            SAXEventProvider osissep = bdata.getSAXEventProvider();
+            TransformingSAXEventProvider htmlsep = (TransformingSAXEventProvider) converter.convert(osissep);
+            XSLTProperty.DIRECTION.setState(direction ? "ltr" : "rtl"); //$NON-NLS-1$ //$NON-NLS-2$
+
+            URI loc = bmd.getLocation();
+            XSLTProperty.BASE_URL.setState(loc == null ? "" : loc.getPath()); //$NON-NLS-1$
+
+            if (bmd.getBookCategory() == BookCategory.BIBLE) {
+                XSLTProperty.setProperties(htmlsep);
+            } else {
+                XSLTProperty.CSS.setProperty(htmlsep);
+                XSLTProperty.BASE_URL.setProperty(htmlsep);
+                XSLTProperty.DIRECTION.setProperty(htmlsep);
+            }
+            // Override the default if needed
+            htmlsep.setParameter(XSLTProperty.FONT.getName(), fontSpec);
+
+            txt = XMLUtil.writeToString(htmlsep);
+            /* BUG_PARADE(DMS): 4775730
+             * This bug shows up before Java 5 in GenBook Practice "/Part 1/THE THIRD STAGE" and elsewhere.
+             * It appears that it is a line too long issue.
+             */
+            /* Apply the fix if the text is too long and we are not Java 1.5 or greater */
+            if (txt.length() > 32768 && BookCategory.GENERAL_BOOK.equals(book.getBookCategory())) {
+                String javaVersion = System.getProperty("java.specification.version"); //$NON-NLS-1$
+                if (javaVersion == null || "1.5".compareTo(javaVersion) > 0) { //$NON-NLS-1$
+
+                    txt = txt.substring(0, 32760) + "..."; //$NON-NLS-1$
+                }
+            }
+
+        } catch (Exception e) {
+            // SAXException, BookException, TransformerException
+            Reporter.informUser(this, e);
+            e.printStackTrace();
+            txtView.setText(e.getMessage());
+            title.setTitle("Exception");
+        }
+        // Set the correct direction
+        GuiUtil.applyOrientation(txtView, direction);
+
+        // The content of the module determines how the display
+        // should behave. It should not be the user's locale.
+        // Set the correct locale
+        txtView.setLocale(new Locale(bmd.getLanguage().getCode()));
+        txtView.setText(txt);
+        txtView.setCaretPosition(0);
+    }
+    
+    void showTip() {
+        // when it is time to do so
+        updateText();
+        Point p = owner.getLocationOnScreen();
+        Dimension d = scrView.getPreferredSize();
+        Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
+        int x = p.x + lastx;
+        int y = p.y + lasty;
+        int horizDist = 30; // these numbers are hard coded
+        int vertiDist = 10; // but they depend on font size.
+        // always show tips in the 'better half'
+        if (x + x > s.width)
+            x -= horizDist + d.width;
+        else
+            x += horizDist;
+        if (y + y > s.height)
+            y -= vertiDist + d.height;
+        else
+            y += vertiDist;
+
+        popup = PopupFactory.getSharedInstance().getPopup(owner, scrView, x, y);
+        popup.show();
+    }
+    
+    void hideTip(boolean stick) {
+        if (popup != null) {
+            popup.hide();
+        }
+        popup = null;
+        sticky = stick;
+    }
+    
+    /**
+     * @param ev if we are interested in this event 
+     */
+    boolean interested(URIEvent ev){
+       //tell if it is interested in ev
+        String protocol = ev.getScheme();
+        if (protocol.equals(Desktop.GREEK_DEF_PROTOCOL)) {
+            return true;
+        }
+        if (protocol.equals(Desktop.HEBREW_DEF_PROTOCOL)) {
+            return true;
+        }
+        if (protocol.equals(Desktop.GREEK_MORPH_PROTOCOL)) {
+            return true;
+        }
+        if (protocol.equals(Desktop.HEBREW_MORPH_PROTOCOL)) {
+            return true;
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.bibledesktop.display.URIEventListener#activateURI(org.crosswire.bibledesktop.display.URIEvent)
+     */
+    public void activateURI(URIEvent ev) {
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.bibledesktop.display.URIEventListener#enterURI(org.crosswire.bibledesktop.display.URIEvent)
+     */
+    public void enterURI(URIEvent ev) {
+        if (!interested(ev)) {
+            return;
+        }
+        System.out.println("entering" + ev.getURI());
+        event = ev;
+        if (sticky) {
+            hideTip(true); // remain sticky
+            showTip(); // new tip immediately
+        } else
+            timer.start();
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.bibledesktop.display.URIEventListener#leaveURI(org.crosswire.bibledesktop.display.URIEvent)
+     */
+    public void leaveURI(URIEvent ev) {
+        if (!interested(ev)) {
+            return;
+        }
+        System.out.println("leaving" + ev.getURI());
+        timer.stop();
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+     */
+    public void actionPerformed(ActionEvent e) {
+        //A timer fires, time to show the tip.
+        //A tip might have been shown
+        hideTip(false); //unset sticky
+        showTip(); 
+        timer.stop();
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
+     */
+    public void mouseDragged(MouseEvent e) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    /* (non-Javadoc)
+     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
+     */
+    public void mouseMoved(MouseEvent e) {
+        lastx = e.getX();
+        lasty = e.getY();
+    }
+    
+    public void mouseClicked(MouseEvent e) {
+        // System.out.println(e);
+        if (e.getSource() == txtView && e.getClickCount() == 1) {
+            sticky = !sticky;
+        } else {
+            hideTip(false); // no longer sticky
+        }
+    }
+
+    public void mouseExited(MouseEvent e) {
+        // this is really a 'bug' for HTMLEditorKit:
+        // when the component having the URI is exited,
+        // yet it is not leaving the URI! We fix it here:
+        if (e.getSource() == owner) {
+            timer.stop();
+        }
+    }
+}




More information about the jsword-svn mailing list