If you are using Internet Explorer, please remove blackberry.com from your compatibility view settings.

Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Developer
ccodere
Posts: 17
Registered: ‎02-09-2010
My Device: Blackberry 9000
My Carrier: None

Simple HTMLTextField implementation...

Greetings,

                 For me, I think that creating a RichTextField correctly with the correct styles was kind of difficult, so I decided to create a small wrapper class called HTMLTextField which supports some simply markup that creates the RichTextField with everything setup automatically.

 

p.s: Currently the size modifiers are not supported, please free to use and extend! If you extend it, please give back the code in the forums so everyone can enjoy it!

 

 

import java.util.Stack;
import java.util.Vector;

import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.component.RichTextField;

/** Class that implements very basic formatting of a label 
 *  field using HTML codes. Only the basic XHTML elements
 *  are currently supported:
 *  <ul>
 *   <li>tt: Renders as teletype or monospaced text.</li>
 *   <li>i: Renders as italic text style.</li>
 *   <li>b: Renders as bold text style.</li>
 *   <li>big: Renders text in a "large" font.(1.2 times bigger, as specified in CSS-2)</li>
 *   <li>small: Renders text in a "small" font. (1.2 times smaller, as specified in CSS-2</li>  
 *  </ul>
 *  
 * This field does not support data that contains those
 * embedded items in the string, since they will be considered
 * as xhtml codes.
 * 
 * Validation is strictly limited.
 * 
 * @author Carl Eric Codere
 *
 */
public class HTMLTextField extends RichTextField
{
  
  private static final String[] TAGS = {"i", "b","tt","big","small"};

  //Type
  private static final int TAG_STYLE_ITALICS = 0x01;
  private static final int TAG_STYLE_BOLD = 0x02;
  private static final int TAG_STYLE_TELETYPE = 0x04;
  private static final int TAG_STYLE_NORMAL = 0x00;
  //Size
  //These two last items are exclusive. 
  private static final int TAG_SIZE_NORMAL = 0x80;
  private static final int TAG_SIZE_BIG =  0x82;
  private static final int TAG_SIZE_SMALL = 0x84;

  private static final int[] TAG_TYPES =
  {TAG_STYLE_ITALICS,TAG_STYLE_BOLD,TAG_STYLE_TELETYPE,TAG_SIZE_BIG,TAG_SIZE_SMALL};
  

   public HTMLTextField(String text, int[] offsets, byte[] attributes, Font[] fonts, long style) 
   {
       super(text, offsets, attributes, fonts, style); 
   }
   

   private static final class ElementState 
   {
     int startPos;
     int endPos;
     int tagType;

     public ElementState(int currentPos)
     {
       startPos = currentPos;
       tagType = TAG_STYLE_NORMAL | TAG_SIZE_NORMAL;
     }
   }

   private static class ElementStateList extends Vector
   {
     public void add(ElementState o)
     {
       ElementState e;
       int i;
       // We merge this element with another element of this type
       // if it already exists at this offset.
       for (i= 0; i < size(); i++)
       {
         e = (ElementState)elementAt(i);
         // There is a match, then we must merge the data
         if (e.startPos == o.startPos)
         {
            e.tagType = e.tagType | o.tagType;
            e.endPos = o.endPos;
            return;
        }
       }
       super.addElement(o);
     }
   }
     


   private static int getTagType(String s)
   {
     int i;
     for (i = 0; i < TAGS.length; i++)
     {
       if (s.equals(TAGS[i]))
       {
         return (TAG_SIZE_NORMAL | TAG_TYPES[i]);
       }
     }
     return -1;
   }

   /** This method parses a text string containing XHTML markup text which is limited
    *  to only certain elements, and then creates a correct RichTextField field 
    *  already setup correctly with all correct handling of the markup..
    * 
    * @param text The text, optionally containing valid XHTML markup
    * @param style The style
    * @return a new instance of HTMLTextField
    * @throws java.lang.IllegalArgumentException
    */
   public static HTMLTextField getInstance(String text, long style) throws IllegalArgumentException
   {
     int i = 0;
 
     char c;
     int fontStyle;
     ElementState currentState;
     ElementState e;
     Stack stack;
     String currentTag ="";
     String cleanString = "";
     boolean validTag = false;
     int tagType;
     ElementStateList states = new ElementStateList();
     stack = new Stack();
 
     currentState = new ElementState(0);

     // Push the normal state element
     states.add(currentState);
     i = 0;
     while (i < text.length())
     {
       c = text.charAt(i);
       if (c == '<')
       {
         currentTag = "";
         i++;
         validTag = false;
         while (i < text.length()) 
         {
            c = text.charAt(i);
            if (c == '>')
            {
                  validTag = true;
                  break;
            }
            currentTag = currentTag + c;
            i++;
        }
        // The end of the text string was reached without an end 
        // tag.
        if (validTag == false)
        {
           cleanString = cleanString + "<"+ currentTag; 
           i++;
           continue;
        }
        // Now check if this is an end tag or not
        if (currentTag.charAt(0) == '/')
        {
            currentTag = currentTag.substring(1);
            tagType = getTagType(currentTag);
            if (tagType == -1)
            {
                cleanString = cleanString + "</"+currentTag+">";
                i++;
                continue;
            }
            // Illegal value
            if (stack.empty()==true)
                throw new IllegalArgumentException("Mssing start tag for "+currentTag);
            e = (ElementState)stack.peek();
            // The values are bitmasks
            if ((e.tagType & tagType)==0)
            {
                throw new IllegalArgumentException("Missing start tag for "+currentTag);
            }
            stack.pop();
            e.endPos = cleanString.length();
            states.add(e);
            // Push the normal state element
            currentState = new ElementState(cleanString.length());
            states.add(currentState);
        } else
        {
            // This is the start of the element
            tagType = getTagType(currentTag);
            if (tagType == -1)
            {
                cleanString = cleanString+"<"+currentTag+">";
                i++;
                continue;
            }
            e = new ElementState(cleanString.length());
            currentState.endPos = cleanString.length();
            e.tagType = tagType;
            stack.push(e);
        }
     }
     else
       cleanString = cleanString + c;
     i++;
     }
     currentState.endPos = cleanString.length();
     // Remove this last element if it points to invalid data.
     if (currentState.endPos == currentState.startPos)
     {
         int deleteIdx = states.indexOf(currentState);
         states.removeElementAt(deleteIdx);
     }
 
     // Normally all elements should have been emptied
     if (stack.empty() == false)
     {
       throw new IllegalArgumentException("Missing end tag(s)");
     }
 
     // Now create the tables for the RichTextField...
     int[] off = new int[states.size()+1];
     byte[] attr = new byte[states.size()];
     Font defaultFont = Font.getDefault();
     Font[] fon = new Font[states.size()];
     for (i = 0; i < states.size(); i++)
     {
       e = (ElementState)states.elementAt(i);
       off[i] = e.startPos;
       // Now retrieve the information on the changes in styles we have to do
       fontStyle = Font.PLAIN;
       if ((e.tagType & TAG_STYLE_ITALICS)==TAG_STYLE_ITALICS)
       {
          fontStyle |= Font.ITALIC;   
       }
       if ((e.tagType & TAG_STYLE_BOLD)==TAG_STYLE_BOLD)
       {
          fontStyle |= Font.BOLD;   
       }
       attr[i] = (byte)i;
       //Ui.UNITS_pt
       fon[i] = defaultFont.derive(fontStyle);
     }   
     off[states.size()] = cleanString.length();
     return new HTMLTextField(cleanString,off,attr,fon,style);
     
  }
}

 

 

-- Carl Eric Codère
Please use plain text.
Developer
dev2011
Posts: 17
Registered: ‎08-14-2009
My Device: Not Specified

Re: Simple HTMLTextField implementation...

Wow thanks, pretty awesome man, exactly what I needed right now -  That's what I call a time-saver :smileyhappy:

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: Simple HTMLTextField implementation...

Agree with the previous poster, haven't tested it, but the idea is excellent. Well done!

Please use plain text.
Developer
arkadyz
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Simple HTMLTextField implementation...

Wow - great initiative!

 

Some enhancement suggestions:

1) Teletype:

    private static final FontFamily fixedFamily = FontFamily.forName("BBSerifFixed"); // the only fixed family on BB

    ...

    Font fixedFont = fixedFamily.getFont(defaultFont.getStyle(), defaultFont.getHeight());

    <calculate style and ...>

    fon[i] = fixedFont.derive(fontStyle);

2) Big/Small:

    Can be emulated with defaultFont.getHeight() and then modifying that number.

    For example, for small:

        int newHeight = defaultFont.getHeight() - 2;

        fon[i] = defaultFont.derive(fontStyle, newHeight);

3) Underline (<u>....</u>):

        fontStyle |= Font.UNDERLINED;

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Please use plain text.
New Contributor
prashantwaykar
Posts: 8
Registered: ‎01-03-2010
My Device: Not Specified

Re: Simple HTMLTextField implementation...

Hi....

found just what i needed.

But can you please show how to use it?

Thanks in advance.

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: Simple HTMLTextField implementation...

1. Add this definition to your project.

2. Create aone using:

HTMLTextField htmlDisplayField = HTMLTextField.getInstance(String text, long style);

3. add htmlDisplayField to your screen

 

Try it and see. 

Please use plain text.
New Contributor
xander0528
Posts: 6
Registered: ‎02-07-2011
My Device: Not Specified

Re: Simple HTMLTextField implementation...

I know this may sound like a very simple question, but what do you mean by long style?

Please use plain text.
Developer
arkadyz
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Simple HTMLTextField implementation...

Have you had a chance to read BlackBerry API documentation? All fields accept style as a parameter in their constructors.

In brief, long style is a bitmask of the style flags you'd like your field to have, such as: FOCUSABLE, READONLY, USE_ALL_WIDTH, USE_TEXT_WIDTH (since this creates a RichTextField), FIELD_HCENTER, FIELD_LEFT, etc. You'll find a lot of examples utilizing these. Naturally, you use | (bitwise or) to combine more than one flag.

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Please use plain text.
New Contributor
xander0528
Posts: 6
Registered: ‎02-07-2011
My Device: Not Specified

Re: Simple HTMLTextField implementation...

I have read the documentation and find it a little confusing. If i have this html:

 

  <tr class=recent_even> 
    <td><a href=?nav=recent&sub=observed&units=metric&tz=UTC&pub=public&map_stati=1,2,3&stn=107&stream=p1&xitem=pm>107</a></td> 
    <td>46216</td> 
    <td><a href=?nav=recent&sub=observed&units=metric&tz=UTC&pub=public&map_stati=1,2,3&stn=107&stream=p1&xitem=pm>GOLETA POINT, CA</a></td> 
    <td>02/15</td> 
    <td>16:57</td> 
    <td>1.58</td> 
    <td>11.8</td> 
    <td>262</td> 
    <td>13.8</td> 
  </tr> 


how would I formate it to just get the number 1.58 from it? (I made it red so that it would be easier to see)

 

Thanks.


 

Please use plain text.
Developer
arkadyz
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Simple HTMLTextField implementation...

Then you've come to the wrong place - the original post shows how to take an HTML text with font-controlling tags such as <b>, <i> etc. and turn it into a RichTextField with all this formatting properly applied.

You want quite a standard HTML / XML processing - search the forums for those.

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Please use plain text.