javauis/lcdui_qt/src/javax/microedition/lcdui/TextFieldLayouter.java
branchRCL_3
changeset 65 ae942d28ec0e
equal deleted inserted replaced
60:6c158198356e 65:ae942d28ec0e
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 package javax.microedition.lcdui;
       
    18 
       
    19 import org.eclipse.ercp.swt.mobile.TextExtension;
       
    20 import org.eclipse.swt.SWT;
       
    21 import org.eclipse.swt.events.*;
       
    22 import org.eclipse.swt.graphics.Point;
       
    23 import org.eclipse.swt.widgets.Composite;
       
    24 import org.eclipse.swt.widgets.Control;
       
    25 import org.eclipse.swt.internal.extension.TextExtensionExtension;
       
    26 /**
       
    27  * Responsible for correct layout of TextField in a Form.
       
    28  */
       
    29 class TextFieldLayouter extends ItemLayouter
       
    30 {
       
    31 
       
    32     /**
       
    33      * Key name for modify listener.
       
    34      */
       
    35     private static final String MODIFY_LISTENER = "modify";
       
    36 
       
    37     /**
       
    38      * Key name for key listener.
       
    39      */
       
    40     private static final String KEY_LISTENER = "key";
       
    41 
       
    42     /**
       
    43      * Key name for mouse listener.
       
    44      */
       
    45     private static final String MOUSE_LISTENER = "mouse";
       
    46 
       
    47 
       
    48     /**
       
    49      * Percentage of the whole screen.
       
    50      */
       
    51     private static final int TOTAL_PERCENTAGE = 100;
       
    52 
       
    53 
       
    54     // private static Control[] staticControls = new Control[6];
       
    55 
       
    56     private static boolean isCorrectText;
       
    57 
       
    58     /**
       
    59      * Constructor.
       
    60      *
       
    61      * @param aFormLayouter FormLayouter used for layouting.
       
    62      */
       
    63     TextFieldLayouter(FormLayouter aFormLayouter)
       
    64     {
       
    65         super(aFormLayouter);
       
    66     }
       
    67 
       
    68     /**
       
    69      * Get static eSWT control (ConstraintText or TextExtension).
       
    70      *
       
    71      * @param constraint
       
    72      */
       
    73     static Control eswtGetStaticTextControl(int constraint)
       
    74     {
       
    75         Control ret = null;
       
    76 
       
    77         /*
       
    78         int maskedConstraint = constraint & TextField.CONSTRAINT_MASK;
       
    79 
       
    80         if (staticControls[maskedConstraint] == null) {
       
    81             staticControls[maskedConstraint] = TextWrapper.eswtConstructText(
       
    82                     eswtGetStaticShell(), SWT.MULTI | SWT.WRAP, constraint);
       
    83             ret = staticControls[maskedConstraint];
       
    84         }
       
    85         */
       
    86 
       
    87         if (constraint == TextField.NUMERIC) {
       
    88             constraint = TextExtensionExtension.NUMERIC;
       
    89         }
       
    90         else if (constraint == TextField.DECIMAL) {
       
    91             constraint = TextExtensionExtension.DECIMAL;
       
    92         }
       
    93         else if (constraint == TextField.PHONENUMBER) {
       
    94             constraint = TextExtensionExtension.PHONENUMBER;
       
    95         }
       
    96         else
       
    97         {
       
    98             // TODO: eSWT support required - text validation on EMAIL and URL constraints
       
    99             // default
       
   100             constraint = 0;
       
   101         }
       
   102 
       
   103         return new TextExtensionExtension(eswtGetStaticShell(), SWT.MULTI | SWT.WRAP,constraint);
       
   104     }
       
   105 
       
   106     /**
       
   107      * Check that text satisfies specified constraints.
       
   108      *
       
   109      * @param constraint TextField.NUMERIC etc.
       
   110      * @return true if text is correct for specified constraint.
       
   111      */
       
   112     static boolean checkText(final int constraint, final String text)
       
   113     {
       
   114         isCorrectText = true;
       
   115 
       
   116         try
       
   117         {   
       
   118          	  if(constraint == TextField.NUMERIC && !text.equals(""))
       
   119             {
       
   120                 Integer.parseInt(text);
       
   121             }
       
   122             else if(constraint == TextField.DECIMAL && !text.equals(""))
       
   123             {
       
   124                 Float.parseFloat(text);
       
   125             }
       
   126         }
       
   127         catch( NumberFormatException e )
       
   128         {   
       
   129         	  // Illegal text
       
   130             return false;
       
   131         }
       
   132 
       
   133         ESWTUIThreadRunner.syncExec(new Runnable()
       
   134         {
       
   135             public void run()
       
   136             {
       
   137                 try
       
   138                 {
       
   139                     TextWrapper.eswtSetContent(
       
   140                         eswtGetStaticTextControl(constraint), text);
       
   141                 }
       
   142                 catch(IllegalArgumentException e)
       
   143                 {
       
   144                     isCorrectText = false;
       
   145                 }
       
   146             }
       
   147         });
       
   148         return isCorrectText;
       
   149     }
       
   150 
       
   151     /**
       
   152      * eSWT specific calls to implement getControl.
       
   153      *
       
   154      * @param parent for the control.
       
   155      * @param item TextField item.
       
   156      */
       
   157     Control eswtGetControl(Composite parent, Item item)
       
   158     {
       
   159         TextField textfield = (TextField) item;
       
   160 
       
   161         Control te = TextWrapper.eswtConstructText(parent,
       
   162                      SWT.WRAP | SWT.MULTI, textfield.getConstraints());
       
   163         TextWrapper.eswtSetMaxSize(te, textfield.getMaxSize());
       
   164         TextWrapper.eswtSetContent(te, textfield.getString());
       
   165         TextWrapper.eswtSetSelection(te,
       
   166                                      textfield.getCaretPosition(), textfield.getCaretPosition());
       
   167 
       
   168         if(textfield.getInitialInputMode() != null)
       
   169         {
       
   170             eswtUpdateItem(textfield, te, TextField.UPDATE_INITIALINPUTMODE,
       
   171                            null);
       
   172         }
       
   173         return te;
       
   174     }
       
   175 
       
   176     /**
       
   177      * Returns true if this eSWT control is suitable to be used for updating.
       
   178      *
       
   179      * @param item Item.
       
   180      * @param control eSWT control.
       
   181      *
       
   182      * @return true if this control is suitable for update
       
   183      */
       
   184     boolean eswtIsSpecificControl(Item item, Control control)
       
   185     {
       
   186         return (control instanceof TextExtension);
       
   187     }
       
   188 
       
   189     /**
       
   190      * Updates the values of TextField.
       
   191      *
       
   192      * @param item Item.
       
   193      * @param control eSWT control.
       
   194      * @param reason reason to update.
       
   195      */
       
   196     void eswtUpdateItem(Item item, Control control, int reason, Object param)
       
   197     {
       
   198         TextField textfield = (TextField) item;
       
   199         if(reason == TextField.UPDATE_INITIALINPUTMODE)
       
   200         {
       
   201             TextWrapper.eswtSetInputMode(control,
       
   202                                          textfield.getInitialInputMode(),
       
   203                                          textfield.getConstraints());
       
   204         }
       
   205         else
       
   206         {
       
   207             TextWrapper.eswtSetContent(control, textfield.getString());
       
   208         }
       
   209     }
       
   210 
       
   211     /**
       
   212      * Update size of TextField.
       
   213      *
       
   214      * @param item TextField.
       
   215      * @param control Control which represents TextField.
       
   216      * @param width which control must occupy.
       
   217      */
       
   218     void eswtResizeControl(Item item, Control control, int width, int height)
       
   219     {
       
   220         super.eswtResizeControl(item, control, width, height);
       
   221         if(control instanceof TextExtension)
       
   222         {
       
   223             TextExtension te = (TextExtension) control;
       
   224             ((TextField) item).internalSetLinesCount(te.getLineCount());
       
   225         }
       
   226     }
       
   227 
       
   228     /**
       
   229      * Returns true if that key was consumed by TextField.
       
   230      *
       
   231      * @param item TextField.
       
   232      * @param key keyCode.
       
   233      */
       
   234     boolean eswtOfferKeyPressed(Item item, int key)
       
   235     {
       
   236         TextField tf = (TextField) item;
       
   237         if(item.hasLayout(Item.LAYOUT_SHRINK))
       
   238         {
       
   239             if((key == SWT.ARROW_LEFT
       
   240                     && tf.getCaretPosition() == 0)
       
   241                     || (key == SWT.ARROW_RIGHT
       
   242                         && tf.getCaretPosition() == tf.size()))
       
   243             {
       
   244                 return false;
       
   245             }
       
   246         }
       
   247         if(((key == SWT.ARROW_UP)
       
   248                 && (tf.getCaretPosition() == 0))
       
   249                 || ((key == SWT.ARROW_DOWN)
       
   250                     && (tf.getCaretPosition() == tf.size())))
       
   251         {
       
   252             return false;
       
   253         }
       
   254         return true;
       
   255     }
       
   256 
       
   257     /**
       
   258      * Responsible for reacting on focusGained event, and according to direction
       
   259      * from which that event comes sets the caret of the TextField.
       
   260      *
       
   261      * @param item TextField.
       
   262      * @param dir direction from which focus came, in case if it was set with
       
   263      *            setCurrentItem() default direction is used (-1).
       
   264      */
       
   265     void eswtFocusGained(Item item, int dir)
       
   266     {
       
   267         super.eswtFocusGained(item, dir);
       
   268         TextField tf = (TextField) item;
       
   269         // direction = dir;
       
   270         resetCaretPosition(tf, dir);
       
   271         Control control = eswtGetFirstSpecificControl(item);
       
   272         TextWrapper.eswtSetSelection(control,
       
   273                                      tf.getCaretPosition(), tf.getCaretPosition());
       
   274     }
       
   275 
       
   276     /**
       
   277      * Returns the minimum area needed to display a TextField.
       
   278      *
       
   279      * @param textField TextField object
       
   280      * @return Minimum area needed to display TextField.
       
   281      */
       
   282     static Point calculateMinimumBounds(final TextField textField)
       
   283     {
       
   284         final Point minSize = new Point(0, 0);
       
   285         ESWTUIThreadRunner.syncExec(new Runnable()
       
   286         {
       
   287             public void run()
       
   288             {
       
   289                 TextExtension tempExt = (TextExtension) eswtGetStaticTextControl(TextField.ANY);
       
   290                 tempExt.setText(ItemLayouter.MIN_TEXT);
       
   291                 tempExt.pack();
       
   292                 minSize.x = tempExt.getSize().x;
       
   293                 minSize.y = tempExt.getSize().y + Config.TEXTFIELD_MARGIN;
       
   294                 applyMinMargins(textField, minSize);
       
   295             }
       
   296         });
       
   297         return minSize;
       
   298     }
       
   299 
       
   300     /**
       
   301      * Returns the preferred area needed to display an Item.
       
   302      *
       
   303      * @param item Item.
       
   304      * @return Preferred area needed to display Item. x is width and y is
       
   305      *         height.
       
   306      */
       
   307     static Point calculatePreferredBounds(Item item)
       
   308     {
       
   309         final TextField textfield = (TextField) item;
       
   310         final Point prefSize = new Point(0, 0);
       
   311         ESWTUIThreadRunner.syncExec(new Runnable()
       
   312         {
       
   313             public void run()
       
   314             {
       
   315                 TextExtension te = (TextExtension) eswtGetStaticTextControl(TextField.ANY);
       
   316                 te.setText(textfield.getString());
       
   317 
       
   318                 int maxHeight = (formHeigh
       
   319                                  * Config.TEXTFIELD_MAX_SCREEN_PERCENTAGE / TOTAL_PERCENTAGE)
       
   320                                 - Config.TEXTFIELD_MARGIN;
       
   321                 textfield.internalSetMaxVisibleLines(maxHeight
       
   322                                                      / te.getLineHeight());
       
   323 
       
   324                 prefSize.x = getMaximumItemWidth(textfield);
       
   325                 prefSize.y = Config.TEXTFIELD_MARGIN + Math.min(
       
   326                                  te.computeSize(prefSize.x, SWT.DEFAULT).y, maxHeight);
       
   327                 // prefSize.y = Math.min(calc.y, maxHeight) + MARGIN;
       
   328                 applyPrefMargins(textfield, prefSize);
       
   329             }
       
   330         });
       
   331         return prefSize;
       
   332     }
       
   333 
       
   334     /**
       
   335      * Update caret position based on direction.
       
   336      *
       
   337      * @param textfield TextField for which to update caret position.
       
   338      * @param dir direction of scrolling.
       
   339      */
       
   340     private void resetCaretPosition(TextField textfield, int dir)
       
   341     {
       
   342         switch(dir)
       
   343         {
       
   344         case SWT.ARROW_DOWN:
       
   345             textfield.internalSetCaretPosition(0);
       
   346             break;
       
   347         case SWT.ARROW_RIGHT:
       
   348             textfield.internalSetCaretPosition(0);
       
   349             break;
       
   350         case SWT.ARROW_UP:
       
   351             textfield.internalSetCaretPosition(textfield.size());
       
   352             break;
       
   353         case SWT.ARROW_LEFT:
       
   354             textfield.internalSetCaretPosition(textfield.size());
       
   355             break;
       
   356         default:
       
   357             break;
       
   358         }
       
   359     }
       
   360 
       
   361     /**
       
   362      * Add TextField listeners when form is activated.
       
   363      *
       
   364      * @param item TextField.
       
   365      * @param control Control which represents TextField.
       
   366      */
       
   367     void eswtAddSpecificListeners(Item item, Control control)
       
   368     {
       
   369         super.eswtAddSpecificListeners(item, control);
       
   370         TextField textfield = (TextField) item;
       
   371         ModifyListener listener = new TextFieldModifyListener(textfield);
       
   372         TextWrapper.eswtAddModListener(control, listener);
       
   373         control.setData(MODIFY_LISTENER, listener);
       
   374         KeyListener listener2 = new TextFieldKeyListener(textfield);
       
   375         control.addKeyListener(listener2);
       
   376         control.setData(KEY_LISTENER, listener2);
       
   377         MouseListener listener4 = new AllMouseListener(textfield);
       
   378         control.addMouseListener(listener4);
       
   379         control.setData(MOUSE_LISTENER, listener4);
       
   380     }
       
   381 
       
   382     /**
       
   383      * Remove listeners from a TextField if the form goes to background.
       
   384      *
       
   385      * @param item TextField.
       
   386      * @param control Control which represents TextField.
       
   387      */
       
   388     void eswtRemoveSpecificListeners(Item item, Control control)
       
   389     {
       
   390         super.eswtRemoveSpecificListeners(item, control);
       
   391         ModifyListener l1 = (ModifyListener) control.getData(MODIFY_LISTENER);
       
   392         if(l1 != null)
       
   393         {
       
   394             TextWrapper.eswtRemoveModListener(control, l1);
       
   395             control.setData(MODIFY_LISTENER, null);
       
   396         }
       
   397         KeyListener l2 = (KeyListener) control.getData(KEY_LISTENER);
       
   398         if(l2 != null)
       
   399         {
       
   400             control.removeKeyListener(l2);
       
   401             control.setData(KEY_LISTENER, null);
       
   402         }
       
   403         MouseListener l4 = (MouseListener) control.getData(MOUSE_LISTENER);
       
   404         if(l4 != null)
       
   405         {
       
   406             control.removeMouseListener(l4);
       
   407             control.setData(MOUSE_LISTENER, null);
       
   408         }
       
   409     }
       
   410 
       
   411     /**
       
   412      * Class that receives ModifyEvents from TextExtension and updates values of
       
   413      * TextField.
       
   414      */
       
   415     class TextFieldModifyListener implements ModifyListener
       
   416     {
       
   417 
       
   418         private TextField textfield;
       
   419 
       
   420         TextFieldModifyListener(TextField textField)
       
   421         {
       
   422             this.textfield = textField;
       
   423         }
       
   424 
       
   425         private void handleLinesChange(TextExtension te)
       
   426         {
       
   427             int lines = te.getLineCount();
       
   428             int visibleLines = te.getSize().y / te.getLineHeight();
       
   429             if(lines != textfield.internalGetLinesCount())
       
   430             {
       
   431                 textfield.internalSetLinesCount(lines);
       
   432                 Control control = eswtGetFirstControl(textfield);
       
   433                 if(control.getSize().y + te.getLineHeight()
       
   434                         + Config.TEXTFIELD_MARGIN <= formLayouter.getFormHeight())
       
   435                 {
       
   436                     textfield.updateParent(Item.UPDATE_HEIGHT_CHANGED);
       
   437                 }
       
   438                 if(textfield.internalGetLinesCount() > lines)
       
   439                 {
       
   440                     if((te.getTopIndex() + visibleLines) > lines)
       
   441                     {
       
   442                         te.setTopIndex(Math.max(0, lines - visibleLines));
       
   443                     }
       
   444                     if(visibleLines > lines)
       
   445                     {
       
   446                         textfield.updateParent(Item.UPDATE_HEIGHT_CHANGED);
       
   447                     }
       
   448                 }
       
   449 
       
   450                 te.setTopIndex(Math.max(te.getCaretLineNumber() + 1
       
   451                                         - textfield.internalGetMaxVisibleLines(), 0));
       
   452             }
       
   453         }
       
   454 
       
   455         public void modifyText(ModifyEvent modifyEvent)
       
   456         {
       
   457             Control te = (Control) modifyEvent.widget;
       
   458             if(textfield.internalSetString(TextWrapper.eswtGetContent(te)))
       
   459             {
       
   460                 Logger.method(textfield, "modify", modifyEvent);
       
   461                 textfield.internalSetCaretPosition(
       
   462                     TextWrapper.eswtGetCaretPosition(te));
       
   463                 if(te instanceof TextExtension)
       
   464                 {
       
   465                     handleLinesChange((TextExtension) te);
       
   466                 }
       
   467                 textfield.notifyStateChanged();
       
   468             }
       
   469         }
       
   470     }
       
   471 
       
   472     /**
       
   473      * Class that receives KeyEvents from TextExtension and updates
       
   474      * caret position for TextField.
       
   475      */
       
   476     class TextFieldKeyListener implements KeyListener
       
   477     {
       
   478 
       
   479         private TextField textfield;
       
   480 
       
   481         TextFieldKeyListener(TextField textField)
       
   482         {
       
   483             this.textfield = textField;
       
   484         }
       
   485 
       
   486         public void keyPressed(KeyEvent keyEvent)
       
   487         {
       
   488             Control te = (Control) keyEvent.widget;
       
   489             int caretPos = TextWrapper.eswtGetCaretPosition(te);
       
   490             int caretLine = TextWrapper.eswtGetCaretLine(te);
       
   491 
       
   492             if(keyEvent.keyCode == SWT.ARROW_UP && caretLine == 0)
       
   493             {
       
   494                 caretPos = 0;
       
   495                 TextWrapper.eswtSetSelection(te, caretPos, caretPos);
       
   496             }
       
   497             else if(keyEvent.keyCode == SWT.ARROW_DOWN
       
   498                     && (caretLine == (TextWrapper.eswtGetLineCount(te) - 1)))
       
   499             {
       
   500                 caretPos = textfield.size();
       
   501                 TextWrapper.eswtSetSelection(te, caretPos, caretPos);
       
   502             }
       
   503 
       
   504             textfield.internalSetCaretPosition(caretPos);
       
   505         }
       
   506 
       
   507         public void keyReleased(KeyEvent keyEvent)
       
   508         {
       
   509             // this is needed if focus was changed with touch.
       
   510             // so ne scrolling was done in DFI.
       
   511             if(!formLayouter.isItemFullyVisible(textfield))
       
   512             {
       
   513                 formLayouter.eswtScrollToItem(textfield);
       
   514             }
       
   515             textfield.internalSetCaretPosition(
       
   516                 TextWrapper.eswtGetCaretPosition((Control) keyEvent.widget));
       
   517         }
       
   518 
       
   519     }
       
   520 
       
   521     class AllMouseListener implements MouseListener, MouseMoveListener
       
   522     {
       
   523 
       
   524         private TextField textfield;
       
   525         private boolean isEnabled;
       
   526 
       
   527         AllMouseListener(TextField tf)
       
   528         {
       
   529             textfield = tf;
       
   530         }
       
   531 
       
   532         public void enable(boolean enabled)
       
   533         {
       
   534             isEnabled = enabled;
       
   535         }
       
   536 
       
   537         public void mouseUp(MouseEvent me)
       
   538         {
       
   539             if(isEnabled)
       
   540             {
       
   541                 //
       
   542             }
       
   543         }
       
   544 
       
   545         public void mouseDown(MouseEvent me)
       
   546         {
       
   547             textfield.internalSetCaretPosition(
       
   548                 TextWrapper.eswtGetCaretPosition((Control) me.widget));
       
   549         }
       
   550 
       
   551         public void mouseMove(MouseEvent me)
       
   552         {
       
   553         }
       
   554 
       
   555         public void mouseDoubleClick(MouseEvent me)
       
   556         {
       
   557         }
       
   558 
       
   559     }
       
   560 
       
   561 }