FileDocCategorySizeDatePackage
TextBoxLFImpl.javaAPI DocphoneME MR2 API (J2ME)22949Wed May 02 18:00:20 BST 2007javax.microedition.lcdui

TextBoxLFImpl

public class TextBoxLFImpl extends TextFieldLFImpl implements TextFieldLF
This is the look &s; feel implementation for TextBox.

Fields Summary
protected com.sun.midp.lcdui.TextInfo
myInfo
Contains line-break information for a blob of text
protected boolean
scrollInitialized
A flag indicating the scroll indicator has been initialized for this textbox. This happens only once when the textbox first paints its contents.
Constructors Summary
TextBoxLFImpl(TextField tf)
Creates TextFieldLF for the passed in TextField.

param
tf The TextField associated with this TextFieldLF

        super(tf);

        if (myInfo == null) {
            myInfo = new TextInfo(4); // IMPL NOTE: add initial size to skin
        }
        drawsTraversalIndicator = false;
    
Methods Summary
protected intgetIndexAt(int x, int y)
Get character index at the pointer position

param
x pointer x coordinate
param
y pointer y coordinate
return
the character index

        x -= contentBounds[X] +
            TextFieldSkin.BOX_MARGIN +
            TextFieldSkin.PAD_H;
        y -= contentBounds[Y] +
            TextFieldSkin.BOX_MARGIN +
            TextFieldSkin.PAD_V;
        int id = -1;
        // the pointer is inside of the content 
        if (x >= 0 && y >= 0) {
            
            int numLines = myInfo.topVis + y / ScreenSkin.FONT_INPUT_TEXT.getHeight();
            id = tf.buffer.length();
            
            // the cursor has to be moved to the symbol the pointer is clicked at
            // if pointer is out of text just move the cursor at the last text position
            // if pointer is out of line just move the cursor at the last line position
            if (numLines < myInfo.numLines) {
                char[] data = tf.buffer.toCharArray();
                int i = 1;
                int startId = myInfo.lineStart[numLines];
                for (; i <= myInfo.lineEnd[numLines] - startId; i++) {
                    if (x <= ScreenSkin.FONT_INPUT_TEXT.charsWidth(data, startId, i)) {
                        break;
                    }
                }
                id = startId + i - 1;
            }
        }
        return id;
    
protected int[]getInputModeAnchor()
This is a utility function to calculate the anchor point for the InputModeIndicator layer. Override TextFieldLFImpl version for effeciency.

return
anchor (x, y, w, h)

        ScreenLFImpl sLF = (ScreenLFImpl)tf.owner.getLF();
        
        int space = TextFieldSkin.BOX_MARGIN
                    + Font.getDefaultFont().getHeight();
        
        return new int[] {
            sLF.viewport[WIDTH] - TextFieldSkin.BOX_MARGIN - 4
                + getCurrentDisplay().getWindow().getBodyAnchorX(),
            getCurrentDisplay().getWindow().getBodyAnchorY(),
            sLF.viewport[HEIGHT] - space - 4,                    
            space};
    
voidlCallShowNotify()
Called by the system to notify this Item it is being shown

The default implementation of this method updates the 'visible' state

        super.lCallShowNotify();
        this.scrollInitialized = false;     
    
public voidlDelete(int offset, int length)
Notifies L&amsp;F of character deletion in the corresponding TextField.

param
offset the beginning of the deleted region
param
length the number of characters deleted
exception
IllegalArgumentException if the resulting contents would be illegal for the current
exception
StringIndexOutOfBoundsException if offset and length do not specify a valid range within the contents of the TextField

        if (editable) {
            if (cursor.index >= offset) {
                int diff = cursor.index - offset;
                cursor.index -= (diff < length) ? diff : length;
                cursor.option = Text.PAINT_USE_CURSOR_INDEX;
            }
        }
        myInfo.isModified = myInfo.scrollY = true;
        updateTextInfo();
    
voidlGetContentSize(int[] size, int availableWidth)
Sets the content size in the passed in array. Content is calculated based on the availableWidth. size[WIDTH] and size[HEIGHT] should be set by this method.

param
size The array that holds Item content size and location in Item internal bounds coordinate system.
param
availableWidth The width available for this Item

        int oldWidth = size[WIDTH];
        int oldHeight = size[HEIGHT];
        try {
            // We size to the maximum allowed, minus the padding
            // defined in the skin.
            size[WIDTH] = ((DisplayableLFImpl)tf.owner.getLF()).
                getDisplayableWidth() - 2 * TextFieldSkin.BOX_MARGIN;
                       
            // Note: tf.owner is the original TextBox for this LFImpl
            size[HEIGHT] = ((DisplayableLFImpl)tf.owner.getLF()).
                getDisplayableHeight() - 2 * TextFieldSkin.BOX_MARGIN;
        } catch (Throwable t) {
            // NOTE: the above call to getCurrent() will size the textbox
            // appropriately if there is a title, ticker, etc. Calling
            // this method depends on the textbox being current however.
            size[WIDTH] = 100;
            size[HEIGHT] = 100;
            // IMPL NOTE: Log this as an error
        }
        if (oldHeight != size[HEIGHT] || oldWidth != size[WIDTH]) {
            myInfo.scrollY = myInfo.isModified = true;
            updateTextInfo();
        }
    
public voidlInsert(char[] data, int offset, int length, int position)
Notifies L&s;F of a character insertion in the corresponding TextBox.

param
data the source of the character data
param
offset the beginning of the region of characters copied
param
length the number of characters copied
param
position the position at which insertion occurred

        if (data != null) {
            if (editable) {
                if (position <= cursor.index) {
                    cursor.index += length;
                    cursor.option = Text.PAINT_USE_CURSOR_INDEX;
                }
            }
            myInfo.isModified = myInfo.scrollY = true;
            updateTextInfo();
        }
    
voidlPaintContent(Graphics g, int width, int height)
Paints the content area of this TextField. Graphics is translated to contents origin.

param
g The graphics where Item content should be painted
param
width The width available for the Item's content
param
height The height available for the Item's content

        g.translate(TextFieldSkin.BOX_MARGIN, TextFieldSkin.BOX_MARGIN);
        width -= (2 * TextFieldSkin.BOX_MARGIN);
        height -= ((2 * TextFieldSkin.BOX_MARGIN) +     
                   (inputModeIndicator.getDisplayMode() != null ?
                    Font.getDefaultFont().getHeight() : 0));

        if (editable) {
            if (TextFieldSkin.IMAGE_BG != null) {
                CGraphicsUtil.draw9pcsBackground(g, 0, 0, width, height,
                    TextFieldSkin.IMAGE_BG);
            } else {
                CGraphicsUtil.drawDropShadowBox(g, 0, 0, width, height,
                    TextFieldSkin.COLOR_BORDER,
                    TextFieldSkin.COLOR_BORDER_SHD, 
                    TextFieldSkin.COLOR_BG);
            }
        } else {
            if (TextFieldSkin.IMAGE_BG_UE != null) {
                CGraphicsUtil.draw9pcsBackground(g, 0, 0, width, height,
                    TextFieldSkin.IMAGE_BG_UE);
            } else {
                CGraphicsUtil.drawDropShadowBox(g, 0, 0, width, height,
                    TextFieldSkin.COLOR_BORDER_UE,
                    TextFieldSkin.COLOR_BORDER_SHD_UE, 
                    TextFieldSkin.COLOR_BG_UE);
            }
        }

        // We need to translate by 1 more pixel horizontally 
        // to reserve space for cursor in the empty textfield
        g.translate(TextFieldSkin.PAD_H + 1, TextFieldSkin.PAD_V);

        paint(g, tf.buffer,
              inputSession.getPendingChar(),
              tf.constraints, 
              ScreenSkin.FONT_INPUT_TEXT, 
              (editable ? TextFieldSkin.COLOR_FG : TextFieldSkin.COLOR_FG_UE), 
              width - (2 * (TextFieldSkin.PAD_H)), height, 0,  
              Text.NORMAL, cursor, myInfo); 

        if (!scrollInitialized) {
            setVerticalScroll();
            scrollInitialized = true;
        }
        
        g.translate(-(TextFieldSkin.PAD_H + 1), -(TextFieldSkin.PAD_V));

        if (usePreferredX) {
            cursor.preferredX = cursor.x +
                (myInfo.lineStart[myInfo.cursorLine] == cursor.index ?
                 ScreenSkin.FONT_INPUT_TEXT.charWidth(
                                                      tf.buffer.charAt(cursor.index)) :
                 0);
        }
        

        g.translate(-TextFieldSkin.BOX_MARGIN, -TextFieldSkin.BOX_MARGIN);
    
public voidlSetChars()
Notifies L&F of a content change in the corresponding TextBox.

        cursor.index = tf.buffer.length(); // cursor at the end
        cursor.option = Text.PAINT_USE_CURSOR_INDEX;

        myInfo.scrollY = myInfo.isModified = true;
        updateTextInfo();
    
public voidlSetConstraints()
Notifies L&s;F that constraints have to be changed.

    	setConstraintsCommon(false);
        
        setVerticalScroll();
        
        // reset cursor position if needed
        if (editable && myInfo != null) {
            int pos = cursor.y / ScreenSkin.FONT_INPUT_TEXT.getHeight();
            int newPos = pos;
            if (pos <= myInfo.topVis) {
                newPos = myInfo.topVis + 1;
            } else if (pos > myInfo.topVis + myInfo.visLines) {
                newPos = myInfo.topVis + myInfo.visLines;
            }
            if (newPos != pos) {
                cursor.y = newPos  * ScreenSkin.FONT_INPUT_TEXT.getHeight();
                cursor.option = Text.PAINT_GET_CURSOR_INDEX;
                myInfo.isModified = myInfo.scrollY = true;
                updateTextInfo();
            }
        }
        
        lRequestPaint();
    
public voidlSetMaxSize(int maxSize)
Notifies L&s;F of a maximum size change in the corresponding TextBox.

param
maxSize - the new maximum size

        if (editable) {
            if (cursor.index >= maxSize) {
                cursor.index = maxSize;
                cursor.option = Text.PAINT_USE_CURSOR_INDEX;
            }
        }
        myInfo.isModified = myInfo.scrollY = true;
        updateTextInfo();
    
booleanmoveCursor(int dir)
Move the text cursor in the given direction

param
dir direction to move
return
true if the cursor was moved, false otherwise


        boolean keyUsed = false;

        switch (dir) {

	case Canvas.LEFT:
	    if (editable) {
                keyClicked(dir);
		if (cursor.index > 0) {
		    cursor.index--;
		    cursor.option = Text.PAINT_USE_CURSOR_INDEX;
		    myInfo.isModified = myInfo.scrollX = keyUsed = true;
		}
	    } else {
		keyUsed = myInfo.scroll(TextInfo.BACK);
	    }
	    break;

	case Canvas.RIGHT:
	    if (editable) {
                keyClicked(dir);
		if (cursor.index < tf.buffer.length()) {
		    cursor.index++;
		    cursor.option = Text.PAINT_USE_CURSOR_INDEX;
		    myInfo.isModified = myInfo.scrollX = keyUsed = true;
		}
	    } else {
		keyUsed = myInfo.scroll(TextInfo.FORWARD);
	    }
	    break;
	    
	case Canvas.UP:
	    if (editable) {
                keyClicked(dir);
		cursor.y -= ScreenSkin.FONT_INPUT_TEXT.getHeight();
		if (cursor.y > 0) {
		    cursor.option = Text.PAINT_GET_CURSOR_INDEX;
		    myInfo.isModified = myInfo.scrollY = keyUsed = true;
		} else { 
		    cursor.y += ScreenSkin.FONT_INPUT_TEXT.getHeight();
		}
	    } else {
		keyUsed = myInfo.scroll(TextInfo.BACK);
	    }
	    break;

	case Canvas.DOWN:
	    if (editable) {
                keyClicked(dir);
		cursor.y += ScreenSkin.FONT_INPUT_TEXT.getHeight();
		if (cursor.y <= myInfo.height) {
		    cursor.option = Text.PAINT_GET_CURSOR_INDEX;
		    myInfo.isModified = myInfo.scrollY = keyUsed = true;
		} else {
		    cursor.y -= ScreenSkin.FONT_INPUT_TEXT.getHeight();
		}
	    } else {
		keyUsed = myInfo.scroll(TextInfo.FORWARD);
	    }
	    break;
	default:
	    // no-op
	    break;
	}

        updateTextInfo();
        
        return keyUsed;
    
public voidpaint(Graphics g, com.sun.midp.lcdui.DynamicCharacterArray dca, char opChar, int constraints, Font font, int fgColor, int w, int h, int offset, int options, com.sun.midp.lcdui.TextCursor cursor, com.sun.midp.lcdui.TextInfo info)
Paint the text, linewrapping when necessary

param
g the Graphics to use to paint with. If g is null then only the first four arguments are used and nothing is painted. Use this to return just the displayed string
param
dca the text to paint
param
opChar if opChar > 0 then an optional character to paint.
param
constraints text constraints
param
font the font to use to paint the text
param
fgColor foreground color
param
w the available width for the text
param
h the available height for the text
param
offset the first line pixel offset
param
options any of Text.[NORMAL | INVERT | HYPERLINK | TRUNCATE]
param
cursor text cursor object to use to draw vertical bar
param
info TextInfo structure to use for paint

        if (opChar != 0) {
            cursor = new TextCursor(cursor);
            info.isModified = true;            
        }
        
        String str = getDisplayString(dca, opChar, constraints,
                                      cursor, true);
        info.isModified |= !bufferedTheSameAsDisplayed(tf.constraints);
        
        Text.updateTextInfo(str, font, w, h, offset, options, cursor, info);

        Text.paintText(info, g, str, font, fgColor, 0xffffff - fgColor,
                       w, h, offset, options, cursor);
        
        // just correct cursor index if the charracter has
        // been already committed 
        if (str != null && str.length() > 0) {
            getBufferString(new DynamicCharacterArray(str),
                            constraints, cursor, true);
        }
        
        // We'll double check our anchor point in case the Form
        // has scrolled and we need to update our InputModeLayer's
        // location on the screen
        if (hasFocus) {
            moveInputModeIndicator();
        }

        // has to be moved to correct place. It's incorrect to change 
        // the layer's dirty bounds in paint context 
        showPTPopup((int)0, cursor, w, h);
    
protected voidsetCaretPosition(int pos)
Set new cursor position. Update text info if cursor position is changed

param
pos new position

        int oldPos = cursor.index;
        super.setCaretPosition(pos);
        cursor.option = Text.PAINT_USE_CURSOR_INDEX;
        myInfo.isModified = myInfo.scrollY |= (oldPos != cursor.index);
        updateTextInfo();
    
booleansetVerticalScroll()
Used internally to set the vertical scroll position

        ScreenLFImpl lf = null;
        if (tf != null &&
            tf.owner != null &&
            (lf = (ScreenLFImpl)tf.owner.getLF()) != null &&
            myInfo != null) {
            return lf.setVerticalScroll(myInfo.getScrollPosition(),
                                 myInfo.getScrollProportion());          
        }
        return false;
    
voiduCallScrollContent(int scrollType, int thumbPosition)
Scroll content inside of the form.

param
scrollType scrollType. Scroll type can be one of the following
see
ScrollBarLayer.SCROLL_NONE
see
ScrollBarLayer.SCROLL_PAGEUP
see
ScrollBarLayer.SCROLL_PAGEDOWN
see
ScrollBarLayer.SCROLL_LINEUP
see
ScrollBarLayer.SCROLL_LINEDOWN or
see
ScrollBarLayer.SCROLL_THUMBTRACK
param
thumbPosition

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, 
                           LogChannels.LC_HIGHUI,
                           "TextBoxLFImpl.uCallScrollContent scrollType=" + scrollType + 
                           " thumbPosition=" + thumbPosition); 
        }
        
        switch (scrollType) {
            case ScrollBarLayer.SCROLL_PAGEUP:
                uScrollViewport(Canvas.UP);
                break;
            case ScrollBarLayer.SCROLL_PAGEDOWN:
                uScrollViewport(Canvas.DOWN);
                break;
            case ScrollBarLayer.SCROLL_LINEUP:
                uScrollByLine(Canvas.UP);
                break;
            case ScrollBarLayer.SCROLL_LINEDOWN:
                uScrollByLine(Canvas.DOWN);
                break;
            case ScrollBarLayer.SCROLL_THUMBTRACK:
                uScrollAt(thumbPosition);
                break;
            default:
                break;
        }
    
protected voiduScrollAt(int position)
Perform a scrolling at the given position.

param
context position

        int oldTopVis = myInfo.topVis;
        myInfo.topVis  = ((myInfo.height - myInfo.visLines * ScreenSkin.FONT_INPUT_TEXT.getHeight()) *
                          position / 100) / ScreenSkin.FONT_INPUT_TEXT.getHeight();
        
        if (myInfo.topVis < 0) {
            myInfo.topVis = 0;
        } else if (myInfo.topVis - myInfo.visLines > myInfo.numLines) {
            myInfo.topVis = myInfo.numLines - myInfo.visLines;
        }
        
        if (myInfo.topVis != oldTopVis) {
            if (editable) {
                cursor.y += (myInfo.topVis - oldTopVis) * ScreenSkin.FONT_INPUT_TEXT.getHeight();
                cursor.option = Text.PAINT_GET_CURSOR_INDEX;
            }
            myInfo.isModified = myInfo.scrollY = true;
            updateTextInfo();
        }
    
protected voiduScrollByLine(int dir)
Perform a line scrolling in the given direction. This method will attempt to scroll the view to show next/previous line.

param
dir the direction of the flip, either DOWN or UP

        int oldTopVis = myInfo.topVis;
        if (myInfo.scroll(dir == Canvas.UP ? TextInfo.BACK : TextInfo.FORWARD)) {
            if (editable) {
                cursor.y += (myInfo.topVis - oldTopVis) * ScreenSkin.FONT_INPUT_TEXT.getHeight();
                cursor.option = Text.PAINT_GET_CURSOR_INDEX;
            }
            updateTextInfo();
        }
    
protected voiduScrollViewport(int dir)
Perform a page flip in the given direction. This method will attempt to scroll the view to show as much of the next page as possible. It uses the locations and bounds of the items on the page to best determine a new location - taking into account items which may lie on page boundaries as well as items which may span several pages.

param
dir the direction of the flip, either DOWN or UP

        int lines = myInfo.scrollByPage(dir == Canvas.UP ?
                                        TextInfo.BACK : TextInfo.FORWARD);
        if (lines != 0) {
	    if (editable) {
                cursor.y += ScreenSkin.FONT_INPUT_TEXT.getHeight() * lines;
                cursor.option = Text.PAINT_GET_CURSOR_INDEX;
	    }
            updateTextInfo();
        }
    
private voidupdateTextInfo()
Update text info if required

        int w = contentBounds[WIDTH];
        int h = contentBounds[HEIGHT];
        // bounds are already initialized
        if (w > 0 && h > 0) {
            w -= 2 * TextFieldSkin.BOX_MARGIN + 2 * TextFieldSkin.PAD_H;
            h -= ((2 * TextFieldSkin.BOX_MARGIN) +     
                  (inputModeIndicator.getDisplayMode() != null ?
                   Font.getDefaultFont().getHeight() : 0));
            Text.updateTextInfo(tf.buffer.toString(),
                                ScreenSkin.FONT_INPUT_TEXT,
                                w, h, 0, Text.NORMAL,
                                cursor, myInfo);
            if (setVerticalScroll()) {
                lRequestInvalidate(true,true);
            } else {
                lRequestPaint();
            }
        }