javauis/lcdui_qt/src/javax/microedition/lcdui/TextFieldLayouter.java
branchRCL_3
changeset 65 ae942d28ec0e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/TextFieldLayouter.java	Tue Aug 31 15:09:22 2010 +0300
@@ -0,0 +1,561 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+package javax.microedition.lcdui;
+
+import org.eclipse.ercp.swt.mobile.TextExtension;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.internal.extension.TextExtensionExtension;
+/**
+ * Responsible for correct layout of TextField in a Form.
+ */
+class TextFieldLayouter extends ItemLayouter
+{
+
+    /**
+     * Key name for modify listener.
+     */
+    private static final String MODIFY_LISTENER = "modify";
+
+    /**
+     * Key name for key listener.
+     */
+    private static final String KEY_LISTENER = "key";
+
+    /**
+     * Key name for mouse listener.
+     */
+    private static final String MOUSE_LISTENER = "mouse";
+
+
+    /**
+     * Percentage of the whole screen.
+     */
+    private static final int TOTAL_PERCENTAGE = 100;
+
+
+    // private static Control[] staticControls = new Control[6];
+
+    private static boolean isCorrectText;
+
+    /**
+     * Constructor.
+     *
+     * @param aFormLayouter FormLayouter used for layouting.
+     */
+    TextFieldLayouter(FormLayouter aFormLayouter)
+    {
+        super(aFormLayouter);
+    }
+
+    /**
+     * Get static eSWT control (ConstraintText or TextExtension).
+     *
+     * @param constraint
+     */
+    static Control eswtGetStaticTextControl(int constraint)
+    {
+        Control ret = null;
+
+        /*
+        int maskedConstraint = constraint & TextField.CONSTRAINT_MASK;
+
+        if (staticControls[maskedConstraint] == null) {
+            staticControls[maskedConstraint] = TextWrapper.eswtConstructText(
+                    eswtGetStaticShell(), SWT.MULTI | SWT.WRAP, constraint);
+            ret = staticControls[maskedConstraint];
+        }
+        */
+
+        if (constraint == TextField.NUMERIC) {
+            constraint = TextExtensionExtension.NUMERIC;
+        }
+        else if (constraint == TextField.DECIMAL) {
+            constraint = TextExtensionExtension.DECIMAL;
+        }
+        else if (constraint == TextField.PHONENUMBER) {
+            constraint = TextExtensionExtension.PHONENUMBER;
+        }
+        else
+        {
+            // TODO: eSWT support required - text validation on EMAIL and URL constraints
+            // default
+            constraint = 0;
+        }
+
+        return new TextExtensionExtension(eswtGetStaticShell(), SWT.MULTI | SWT.WRAP,constraint);
+    }
+
+    /**
+     * Check that text satisfies specified constraints.
+     *
+     * @param constraint TextField.NUMERIC etc.
+     * @return true if text is correct for specified constraint.
+     */
+    static boolean checkText(final int constraint, final String text)
+    {
+        isCorrectText = true;
+
+        try
+        {   
+         	  if(constraint == TextField.NUMERIC && !text.equals(""))
+            {
+                Integer.parseInt(text);
+            }
+            else if(constraint == TextField.DECIMAL && !text.equals(""))
+            {
+                Float.parseFloat(text);
+            }
+        }
+        catch( NumberFormatException e )
+        {   
+        	  // Illegal text
+            return false;
+        }
+
+        ESWTUIThreadRunner.syncExec(new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    TextWrapper.eswtSetContent(
+                        eswtGetStaticTextControl(constraint), text);
+                }
+                catch(IllegalArgumentException e)
+                {
+                    isCorrectText = false;
+                }
+            }
+        });
+        return isCorrectText;
+    }
+
+    /**
+     * eSWT specific calls to implement getControl.
+     *
+     * @param parent for the control.
+     * @param item TextField item.
+     */
+    Control eswtGetControl(Composite parent, Item item)
+    {
+        TextField textfield = (TextField) item;
+
+        Control te = TextWrapper.eswtConstructText(parent,
+                     SWT.WRAP | SWT.MULTI, textfield.getConstraints());
+        TextWrapper.eswtSetMaxSize(te, textfield.getMaxSize());
+        TextWrapper.eswtSetContent(te, textfield.getString());
+        TextWrapper.eswtSetSelection(te,
+                                     textfield.getCaretPosition(), textfield.getCaretPosition());
+
+        if(textfield.getInitialInputMode() != null)
+        {
+            eswtUpdateItem(textfield, te, TextField.UPDATE_INITIALINPUTMODE,
+                           null);
+        }
+        return te;
+    }
+
+    /**
+     * Returns true if this eSWT control is suitable to be used for updating.
+     *
+     * @param item Item.
+     * @param control eSWT control.
+     *
+     * @return true if this control is suitable for update
+     */
+    boolean eswtIsSpecificControl(Item item, Control control)
+    {
+        return (control instanceof TextExtension);
+    }
+
+    /**
+     * Updates the values of TextField.
+     *
+     * @param item Item.
+     * @param control eSWT control.
+     * @param reason reason to update.
+     */
+    void eswtUpdateItem(Item item, Control control, int reason, Object param)
+    {
+        TextField textfield = (TextField) item;
+        if(reason == TextField.UPDATE_INITIALINPUTMODE)
+        {
+            TextWrapper.eswtSetInputMode(control,
+                                         textfield.getInitialInputMode(),
+                                         textfield.getConstraints());
+        }
+        else
+        {
+            TextWrapper.eswtSetContent(control, textfield.getString());
+        }
+    }
+
+    /**
+     * Update size of TextField.
+     *
+     * @param item TextField.
+     * @param control Control which represents TextField.
+     * @param width which control must occupy.
+     */
+    void eswtResizeControl(Item item, Control control, int width, int height)
+    {
+        super.eswtResizeControl(item, control, width, height);
+        if(control instanceof TextExtension)
+        {
+            TextExtension te = (TextExtension) control;
+            ((TextField) item).internalSetLinesCount(te.getLineCount());
+        }
+    }
+
+    /**
+     * Returns true if that key was consumed by TextField.
+     *
+     * @param item TextField.
+     * @param key keyCode.
+     */
+    boolean eswtOfferKeyPressed(Item item, int key)
+    {
+        TextField tf = (TextField) item;
+        if(item.hasLayout(Item.LAYOUT_SHRINK))
+        {
+            if((key == SWT.ARROW_LEFT
+                    && tf.getCaretPosition() == 0)
+                    || (key == SWT.ARROW_RIGHT
+                        && tf.getCaretPosition() == tf.size()))
+            {
+                return false;
+            }
+        }
+        if(((key == SWT.ARROW_UP)
+                && (tf.getCaretPosition() == 0))
+                || ((key == SWT.ARROW_DOWN)
+                    && (tf.getCaretPosition() == tf.size())))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Responsible for reacting on focusGained event, and according to direction
+     * from which that event comes sets the caret of the TextField.
+     *
+     * @param item TextField.
+     * @param dir direction from which focus came, in case if it was set with
+     *            setCurrentItem() default direction is used (-1).
+     */
+    void eswtFocusGained(Item item, int dir)
+    {
+        super.eswtFocusGained(item, dir);
+        TextField tf = (TextField) item;
+        // direction = dir;
+        resetCaretPosition(tf, dir);
+        Control control = eswtGetFirstSpecificControl(item);
+        TextWrapper.eswtSetSelection(control,
+                                     tf.getCaretPosition(), tf.getCaretPosition());
+    }
+
+    /**
+     * Returns the minimum area needed to display a TextField.
+     *
+     * @param textField TextField object
+     * @return Minimum area needed to display TextField.
+     */
+    static Point calculateMinimumBounds(final TextField textField)
+    {
+        final Point minSize = new Point(0, 0);
+        ESWTUIThreadRunner.syncExec(new Runnable()
+        {
+            public void run()
+            {
+                TextExtension tempExt = (TextExtension) eswtGetStaticTextControl(TextField.ANY);
+                tempExt.setText(ItemLayouter.MIN_TEXT);
+                tempExt.pack();
+                minSize.x = tempExt.getSize().x;
+                minSize.y = tempExt.getSize().y + Config.TEXTFIELD_MARGIN;
+                applyMinMargins(textField, minSize);
+            }
+        });
+        return minSize;
+    }
+
+    /**
+     * Returns the preferred area needed to display an Item.
+     *
+     * @param item Item.
+     * @return Preferred area needed to display Item. x is width and y is
+     *         height.
+     */
+    static Point calculatePreferredBounds(Item item)
+    {
+        final TextField textfield = (TextField) item;
+        final Point prefSize = new Point(0, 0);
+        ESWTUIThreadRunner.syncExec(new Runnable()
+        {
+            public void run()
+            {
+                TextExtension te = (TextExtension) eswtGetStaticTextControl(TextField.ANY);
+                te.setText(textfield.getString());
+
+                int maxHeight = (formHeigh
+                                 * Config.TEXTFIELD_MAX_SCREEN_PERCENTAGE / TOTAL_PERCENTAGE)
+                                - Config.TEXTFIELD_MARGIN;
+                textfield.internalSetMaxVisibleLines(maxHeight
+                                                     / te.getLineHeight());
+
+                prefSize.x = getMaximumItemWidth(textfield);
+                prefSize.y = Config.TEXTFIELD_MARGIN + Math.min(
+                                 te.computeSize(prefSize.x, SWT.DEFAULT).y, maxHeight);
+                // prefSize.y = Math.min(calc.y, maxHeight) + MARGIN;
+                applyPrefMargins(textfield, prefSize);
+            }
+        });
+        return prefSize;
+    }
+
+    /**
+     * Update caret position based on direction.
+     *
+     * @param textfield TextField for which to update caret position.
+     * @param dir direction of scrolling.
+     */
+    private void resetCaretPosition(TextField textfield, int dir)
+    {
+        switch(dir)
+        {
+        case SWT.ARROW_DOWN:
+            textfield.internalSetCaretPosition(0);
+            break;
+        case SWT.ARROW_RIGHT:
+            textfield.internalSetCaretPosition(0);
+            break;
+        case SWT.ARROW_UP:
+            textfield.internalSetCaretPosition(textfield.size());
+            break;
+        case SWT.ARROW_LEFT:
+            textfield.internalSetCaretPosition(textfield.size());
+            break;
+        default:
+            break;
+        }
+    }
+
+    /**
+     * Add TextField listeners when form is activated.
+     *
+     * @param item TextField.
+     * @param control Control which represents TextField.
+     */
+    void eswtAddSpecificListeners(Item item, Control control)
+    {
+        super.eswtAddSpecificListeners(item, control);
+        TextField textfield = (TextField) item;
+        ModifyListener listener = new TextFieldModifyListener(textfield);
+        TextWrapper.eswtAddModListener(control, listener);
+        control.setData(MODIFY_LISTENER, listener);
+        KeyListener listener2 = new TextFieldKeyListener(textfield);
+        control.addKeyListener(listener2);
+        control.setData(KEY_LISTENER, listener2);
+        MouseListener listener4 = new AllMouseListener(textfield);
+        control.addMouseListener(listener4);
+        control.setData(MOUSE_LISTENER, listener4);
+    }
+
+    /**
+     * Remove listeners from a TextField if the form goes to background.
+     *
+     * @param item TextField.
+     * @param control Control which represents TextField.
+     */
+    void eswtRemoveSpecificListeners(Item item, Control control)
+    {
+        super.eswtRemoveSpecificListeners(item, control);
+        ModifyListener l1 = (ModifyListener) control.getData(MODIFY_LISTENER);
+        if(l1 != null)
+        {
+            TextWrapper.eswtRemoveModListener(control, l1);
+            control.setData(MODIFY_LISTENER, null);
+        }
+        KeyListener l2 = (KeyListener) control.getData(KEY_LISTENER);
+        if(l2 != null)
+        {
+            control.removeKeyListener(l2);
+            control.setData(KEY_LISTENER, null);
+        }
+        MouseListener l4 = (MouseListener) control.getData(MOUSE_LISTENER);
+        if(l4 != null)
+        {
+            control.removeMouseListener(l4);
+            control.setData(MOUSE_LISTENER, null);
+        }
+    }
+
+    /**
+     * Class that receives ModifyEvents from TextExtension and updates values of
+     * TextField.
+     */
+    class TextFieldModifyListener implements ModifyListener
+    {
+
+        private TextField textfield;
+
+        TextFieldModifyListener(TextField textField)
+        {
+            this.textfield = textField;
+        }
+
+        private void handleLinesChange(TextExtension te)
+        {
+            int lines = te.getLineCount();
+            int visibleLines = te.getSize().y / te.getLineHeight();
+            if(lines != textfield.internalGetLinesCount())
+            {
+                textfield.internalSetLinesCount(lines);
+                Control control = eswtGetFirstControl(textfield);
+                if(control.getSize().y + te.getLineHeight()
+                        + Config.TEXTFIELD_MARGIN <= formLayouter.getFormHeight())
+                {
+                    textfield.updateParent(Item.UPDATE_HEIGHT_CHANGED);
+                }
+                if(textfield.internalGetLinesCount() > lines)
+                {
+                    if((te.getTopIndex() + visibleLines) > lines)
+                    {
+                        te.setTopIndex(Math.max(0, lines - visibleLines));
+                    }
+                    if(visibleLines > lines)
+                    {
+                        textfield.updateParent(Item.UPDATE_HEIGHT_CHANGED);
+                    }
+                }
+
+                te.setTopIndex(Math.max(te.getCaretLineNumber() + 1
+                                        - textfield.internalGetMaxVisibleLines(), 0));
+            }
+        }
+
+        public void modifyText(ModifyEvent modifyEvent)
+        {
+            Control te = (Control) modifyEvent.widget;
+            if(textfield.internalSetString(TextWrapper.eswtGetContent(te)))
+            {
+                Logger.method(textfield, "modify", modifyEvent);
+                textfield.internalSetCaretPosition(
+                    TextWrapper.eswtGetCaretPosition(te));
+                if(te instanceof TextExtension)
+                {
+                    handleLinesChange((TextExtension) te);
+                }
+                textfield.notifyStateChanged();
+            }
+        }
+    }
+
+    /**
+     * Class that receives KeyEvents from TextExtension and updates
+     * caret position for TextField.
+     */
+    class TextFieldKeyListener implements KeyListener
+    {
+
+        private TextField textfield;
+
+        TextFieldKeyListener(TextField textField)
+        {
+            this.textfield = textField;
+        }
+
+        public void keyPressed(KeyEvent keyEvent)
+        {
+            Control te = (Control) keyEvent.widget;
+            int caretPos = TextWrapper.eswtGetCaretPosition(te);
+            int caretLine = TextWrapper.eswtGetCaretLine(te);
+
+            if(keyEvent.keyCode == SWT.ARROW_UP && caretLine == 0)
+            {
+                caretPos = 0;
+                TextWrapper.eswtSetSelection(te, caretPos, caretPos);
+            }
+            else if(keyEvent.keyCode == SWT.ARROW_DOWN
+                    && (caretLine == (TextWrapper.eswtGetLineCount(te) - 1)))
+            {
+                caretPos = textfield.size();
+                TextWrapper.eswtSetSelection(te, caretPos, caretPos);
+            }
+
+            textfield.internalSetCaretPosition(caretPos);
+        }
+
+        public void keyReleased(KeyEvent keyEvent)
+        {
+            // this is needed if focus was changed with touch.
+            // so ne scrolling was done in DFI.
+            if(!formLayouter.isItemFullyVisible(textfield))
+            {
+                formLayouter.eswtScrollToItem(textfield);
+            }
+            textfield.internalSetCaretPosition(
+                TextWrapper.eswtGetCaretPosition((Control) keyEvent.widget));
+        }
+
+    }
+
+    class AllMouseListener implements MouseListener, MouseMoveListener
+    {
+
+        private TextField textfield;
+        private boolean isEnabled;
+
+        AllMouseListener(TextField tf)
+        {
+            textfield = tf;
+        }
+
+        public void enable(boolean enabled)
+        {
+            isEnabled = enabled;
+        }
+
+        public void mouseUp(MouseEvent me)
+        {
+            if(isEnabled)
+            {
+                //
+            }
+        }
+
+        public void mouseDown(MouseEvent me)
+        {
+            textfield.internalSetCaretPosition(
+                TextWrapper.eswtGetCaretPosition((Control) me.widget));
+        }
+
+        public void mouseMove(MouseEvent me)
+        {
+        }
+
+        public void mouseDoubleClick(MouseEvent me)
+        {
+        }
+
+    }
+
+}