[jsword-devel] FontChooser bugs

DM Smith jsword-devel@crosswire.org
Thu, 18 Mar 2004 09:59:56 -0500


This is a multi-part message in MIME format.

------=_NextPart_000_26f2_409e_4282
Content-Type: text/plain; format=flowed

Attached is a patch for the FontChooser problems mentioned in the referenced 
email.

The patch also contains a significant enhancement to xsl/cswing/simple.xsl:

1) The font specification coming into the stylesheet did not have its 
intended effect. The cause of this was that the font was specified as 
Tahoma,2,11, where 2 stood for italic (1 for bold, 3 for both) and 11 stood 
for 11pt. I added parsing of the parameter and built an embedded style for 
the font and set it on the body element. I removed references to the font 
name but left the modifications to the font (e.g. size, color) where it 
occurred. There is still a place in the stylesheet where multiple specs are 
built into <i>, <b>, <font color...> and the like, on a first come first 
serve basis. These could be done together. I would have to look at the 
schema to see if it is allowed.

With the changes I made to FontChooser, if a user changes the font, it is 
reflected in the InternalDisplayPane the next time the passage is rendered. 
[When the ok, apply and cancel buttons are put back in the options view, 
that is. ;^] If a listener were added to the change of the font property, 
the passage could be updated without user intervention.

2) I added support for CSS. If a param named css is passed with the absolute 
url to a css stylesheet, it will incorporate it. I have tested it and one 
neat behavior is that it is brought in everytime the xsl stylesheet is used. 
The difficulty in a WebStart environment is that the css stylesheet will 
need to be in a jar and I dont know how to specify an URL to a file in a 
jar. It does not matter to me if this mechanism is used or we add the 
loading of the css to the code.

3) I added support to turn on and off hypertexting of Strongs. By parming in 
strongs="false" (actually any value other than "true") it will turn off 
strongs hypertexting. I was thinking that we could figure out if there were 
any book installed which could be the target of the hypertext and if not 
then turn it off or publish a warning that one needed to be installed. Also 
to add a checkbox to the main display whose state would govern whether 
stongs would show or not.

4) I made the verse numbers superscript, a bit smaller and added spaces 
before them for readability.

5) I also added spaces between strongs hypertext links. This required 
knowing whether the following element was a strongs node or not.

6) I added a space between the verses listed for a given day's reading. They 
also were running together.

There are still some problems in the rendering of Gen 1 of the KJV with 
Strongs numbers and morphs. The notes don't have reasonable links; they 
display an underlined space for the link.

Here and there there are some additional spaces being added to the displayed 
text. I have narrowed it down to the HTMLDocument's renderer. It is adding 
whitespace to the beginning of nodes. When the previous node ended with 
whitespace, it creates two spaces.


>From: "DM Smith" <dmsmith555@hotmail.com>
>Reply-To: jsword-devel@crosswire.org
>To: jsword-devel@crosswire.org
>Subject: [jsword-devel] FontChooser bugs
>Date: Wed, 10 Mar 2004 10:01:25 -0500
>
>In setStyle, font.isBold() throws a NPE.
>
>In tracing this, it turns out it is because the "desktop" property 
>Looks.Configurable.Font has no value.
>
>Also in setStyle, name.setSelectedItem(font) does not work unless the font 
>being set is 16pt, PLAIN (since setSelectedItem does a scan using equals() 
>for the first match in the list)
>
>In FontChooser, the member variable "font" starts out as Serif, and nothing 
>is selected in the combo box to start out with. (Seems that the intention 
>was that "font" was to be a cached representation of the four widgets.) 
>However, with nothing selected, in getStyle the call selected.getName() 
>generates a NPE.
>
>In LookAndFeelUtil there is a comment that winlaf is being used to provide 
>a better rendition of text on large monitors. And in FontChooser, 
>defaultFont.getFont will return Tahoma, 11pt, plain. I think the intention 
>is to use Tahoma as the default font when nothing else is picked.
>
>Anyway, I have modified FontChooser to do the following:
>1) Use defaultFont.getFont as the initial pick in the combo box.
>2) Conditionally replace the pick with a new pick if it is valid.
>3) Use font.deriveFont rather than new Font where possible.
>4) Use symbolic constants for magic numbers (i.e. Font.PLAIN rather than 0 
>and RENDERER_FONT_SIZE rather than 16).
>
>This leaves two problems to solve:
>1) The default needs to be established in another part of the code so that 
>it can be used. I have not looked into it but it appears that property 
>change events are to propagate the selection, but unless the options dialog 
>is brought up, it can't propagate it. From a design perspective, this has 
>defaults being set in two locations, which is not ideal.
>
>2) Some of the fonts in the combo box do not render the name of the font in 
>a readable fashion. Some of the fonts are for symbols or other languages' 
>character set and do not contain the ASCII character set. I think the 
>solution to this is fairly simple: have a label whose font is changed to 
>match the selection and just give the name in the list. I think that using 
>the text from Gen 1.1, would be appropriate.

_________________________________________________________________
Get reliable access on MSN 9 Dial-up. 3 months for the price of 1! 
(Limited-time offer) http://click.atdmt.com/AVE/go/onm00200361ave/direct/01/

------=_NextPart_000_26f2_409e_4282
Content-Type: text/plain; name="patchfont.txt"; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="patchfont.txt"

Index: java/common/org/crosswire/common/swing/FontChooser.java
===================================================================
retrieving revision 1.13
diff -u -r1.13 FontChooser.java
--- java/common/org/crosswire/common/swing/FontChooser.java	5 Feb 2004 
23:26:20 -0000	1.13
+++ java/common/org/crosswire/common/swing/FontChooser.java	18 Mar 2004 
14:20:45 -0000
@@ -67,23 +67,26 @@
             }
         };

+        font = defaultFont.getFont();
         name.setModel(new CustomComboBoxModel());
         name.setRenderer(new CustomListCellRenderer());
+        name.setSelectedItem(font.deriveFont(Font.PLAIN, 
RENDERED_FONT_SIZE));
         name.addItemListener(changer);

         for (int i = 5; i < 20; i++)
         {
             size.addItem(new Integer(i));
         }
-
+
+        size.setSelectedItem(new Integer(font.getSize()));
         size.addItemListener(changer);
-
+
         bold.setSelected(font.isBold());
         bold.addItemListener(changer);
-
+
         italic.setSelected(font.isItalic());
         italic.addItemListener(changer);
-
+
         setLayout(new GridLayout(2, 2));

         add(name);
@@ -156,15 +159,19 @@
      * Set the Font displayed
      * @param font The current Font
      */
-    public void setStyle(Font font)
+    public void setStyle(Font newFont)
     {
         suppressEvents = true;

+        if (newFont == null) {
+            return;
+        }
+
         CustomComboBoxModel model = (CustomComboBoxModel) name.getModel();
-        model.setSelectedItem(font);
+        model.setSelectedItem(newFont.deriveFont(Font.PLAIN, 
RENDERED_FONT_SIZE));

-        bold.setSelected(font.isBold());
-        italic.setSelected(font.isItalic());
+        bold.setSelected(newFont.isBold());
+        italic.setSelected(newFont.isItalic());
         size.setSelectedItem(new Integer(font.getSize()));

         suppressEvents = false;
@@ -178,10 +185,13 @@
     {
         Font selected = (Font) name.getSelectedItem();

-        int font_style = 0 | (bold.isSelected() ? Font.BOLD : 0) | 
(italic.isSelected() ? Font.ITALIC : 0);
+        if (selected == null)
+            return defaultFont.getFont();
+
+        int font_style = (bold.isSelected() ? Font.BOLD : Font.PLAIN) | 
(italic.isSelected() ? Font.ITALIC : Font.PLAIN);
         int font_size = ((Integer) size.getSelectedItem()).intValue();

-        return new Font(selected.getName(), font_style, font_size);
+        return selected.deriveFont(font_style, font_size);
     }

     /**
@@ -234,7 +244,10 @@

             for (int i = 0; i < fonts.length; i++)
             {
-                fonts[i] = new Font(names[i], 0, 16);
+                fonts[i] = new Font(names[i], Font.PLAIN, 
RENDERED_FONT_SIZE);
+//                System.err.println("Font name = " + fonts[i].getName()
+//                        + " Style = " + fonts[i].getStyle()
+//                        + " Size = " + fonts[i].getSize());
             }
         }

@@ -325,9 +338,13 @@
     protected PropertyChangeSupport listeners = new 
PropertyChangeSupport(this);

     /**
-     * The currnet font
+     * The current font
+     */
+    protected Font font = null;
+    /**
+     * The default size of the rendered font
      */
-    protected Font font = new Font("Serif", Font.PLAIN, 10);
+    private final static int RENDERED_FONT_SIZE = 16;

     /**
      * The choice of font name
Index: resource/xsl/cswing/simple.xsl
===================================================================
retrieving revision 1.3
diff -u -r1.3 simple.xsl
--- resource/xsl/cswing/simple.xsl	29 Jan 2004 10:54:26 -0000	1.3
+++ resource/xsl/cswing/simple.xsl	18 Mar 2004 14:21:04 -0000
@@ -1,12 +1,33 @@
<?xml version="1.0"?>

<xsl:stylesheet xmlns="http://www.w3.org/TR/REC-html40" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-<xsl:output method="html" omit-xml-declaration = "yes" indent="yes"/>
+<xsl:output method="html" omit-xml-declaration="yes" indent="no"/>
+<xsl:strip-space elements="*"/>

   <xsl:param name="strongs.hebrew.url" select="'dict:'"/>
   <xsl:param name="strongs.greek.url" select="'dict:'"/>
-
+
+  <!-- Whether to show Strongs or not -->
+  <xsl:param name="strongs" select="'true'"/>
+
+  <!-- The CSS stylesheet to use. The url must be absolute. -->
+  <xsl:param name="css"/>
+
+  <!-- The font that is passed in is of the form: font,style,size
+       where style is a bit mask with 1 being bold and 2 being italic.
+       This needs to be changed into a style="xxx" specification
+    -->
   <xsl:param name="font"/>
+  <xsl:variable name="fontfamily" select='concat("font-family: &apos;", 
substring-before($font, ","), "&apos;;")' />
+  <xsl:variable name="fontsize" select="concat(' font-size: ', 
substring-after(substring-after($font, ','), ','), 'pt;')" />
+  <xsl:variable name="styling" 
select="substring-before(substring-after($font, ','), ',')" />
+  <xsl:variable name="fontweight">
+    <xsl:if test="$styling = '1' or $styling = '3'"><xsl:text> font-weight: 
bold;</xsl:text></xsl:if>
+  </xsl:variable>
+  <xsl:variable name="fontstyle">
+    <xsl:if test="$styling = '2' or $styling = '3'"> font-style: 
italic;</xsl:if>
+  </xsl:variable>
+  <xsl:variable name="fontspec" select="concat($fontfamily, $fontsize, 
$fontweight, $fontstyle, 'line-height: 300%;')"/>

   <!--
   For now, we assume that all the works inside a corpus are of the
@@ -41,7 +62,12 @@
   
<!--=======================================================================-->
   <xsl:template match="/osis">
     <html>
-      <body>
+      <head>
+        <xsl:if test="$css != ''">
+		  <link rel="stylesheet" type="text/css" href="{$css}" title="styling" />
+		</xsl:if>
+      </head>
+      <body style="{$fontspec}">
         <xsl:apply-templates/>
         <xsl:apply-templates select="//note" mode="print-notes"/>
       </body>
@@ -87,6 +113,8 @@
       <a href="{@osisID}">
       <xsl:apply-templates/>
       </a>
+      <!-- DMS: reading references need a following space -->
+      <xsl:text> </xsl:text>
     </xsl:if>
     <xsl:if test="not(@osisID)">
       <xsl:apply-templates/>
@@ -98,12 +126,10 @@

   
<!--=======================================================================-->
   <xsl:template match="verse">
-    <font size="-1" color="gray" face="{$font}">
-      <a name="{@osisID}"><xsl:value-of 
select="substring-after(substring-after(@osisID, '.'), '.')"/></a>
-    </font>
-    <font size="+1" face="{$font}">
-      <xsl:apply-templates />
-    </font>
+    <!-- DMS: if the verse is not the first verse of a set of siblings, 
output two spaces. -->
+    <xsl:if test="preceding-sibling::*[local-name() = 
'verse']"><xsl:text>&#160;&#160;</xsl:text></xsl:if>
+    <a name="{@osisID}"><sup><font size="-1" color="gray"><xsl:value-of 
select="substring-after(substring-after(@osisID, '.'), 
'.')"/></font></sup></a>
+    <font size="+1"><xsl:apply-templates /></font>
   </xsl:template>

   
<!--=======================================================================-->
@@ -119,9 +145,9 @@
     <xsl:text> </xsl:text>
     <xsl:if test="string-length(.) &lt; 4">
       <a href="#{generate-id(.)}">
-        <font size="-1" face="{$font}">
+        <font size="-1">
           <xsl:number level="any" from="/" count="note[string-length(.) 
&lt; 4]" format="a"/>
-        </font>
+		</font>
       </a>
     </xsl:if>
   </xsl:template>
@@ -161,8 +187,10 @@
   
<!--=======================================================================-->
   <xsl:template match="w">
     <!-- FIXME: Handle all the other attributes besides lemma. -->
+	  <xsl:variable name="siblings" select="../child::node()"/>
+      <xsl:variable name="next-position" select="position() + 1"/>
       <xsl:choose>
-        <xsl:when test="starts-with(@lemma, 'x-Strongs:')">
+        <xsl:when test="$strongs = 'true' and starts-with(@lemma, 
'x-Strongs:')">
           <xsl:variable name="orig-strongs-number" 
select="substring-after(@lemma, ':')"/>
           <xsl:variable name="strongs-type" 
select="substring($orig-strongs-number, 1, 1)"/>
           <xsl:variable name="numeric-portion" 
select="substring($orig-strongs-number, 2)"/>
@@ -185,6 +213,13 @@
           <xsl:apply-templates/>
         </xsl:otherwise>
       </xsl:choose>
+		 except when followed by a text node or non-printing node.
+		 This is true whether the href is output or not.
+      -->
+	<xsl:if test="$siblings[$next-position] and 
name($siblings[$next-position]) != ''">
+  	  <xsl:text> </xsl:text>
+  	</xsl:if>
   </xsl:template>

   
<!--=======================================================================-->
@@ -206,12 +241,12 @@
         </u>
       </xsl:when>
       <xsl:when test="starts-with(@type, 'color:')">
-        <font color="substring-before(substring-after(@type, 'color: '), 
';')" face="{$font}">
+        <font color="substring-before(substring-after(@type, 'color: '), 
';')">
           <xsl:apply-templates/>
         </font>
       </xsl:when>
       <xsl:when test="starts-with(@type, 'font-size:')">
-        <font size="substring-before(substring-after(@type, 'font-size: '), 
';')" face="{$font}">
+        <font size="substring-before(substring-after(@type, 'font-size: '), 
';')">
           <xsl:apply-templates/>
         </font>
       </xsl:when>
@@ -239,12 +274,12 @@
   <xsl:template match="speaker">
     <xsl:choose>
       <xsl:when test="@who='Jesus'">
-        <font color="red" face="{$font}">
+        <font color="red">
           <xsl:apply-templates/>
         </font>
       </xsl:when>
       <xsl:otherwise>
-        <font color="blue" face="{$font}">
+        <font color="blue">
           <xsl:apply-templates/>
         </font>
       </xsl:otherwise>


------=_NextPart_000_26f2_409e_4282--