    001package org.vishia.gral.awt;
    002
    003import java.awt.Canvas;
    004import java.awt.Component;
    005import java.awt.Container;
    006import java.awt.Graphics;
    007import java.awt.Label;
    008import java.awt.Rectangle;
    009import java.awt.TextField;
    010import java.awt.event.FocusListener;
    011import java.awt.event.HierarchyBoundsListener;
    012import java.awt.event.HierarchyEvent;
    013import java.awt.event.KeyEvent;
    014import java.awt.event.KeyListener;
    015
    016import org.vishia.gral.base.GralPos;
    017import org.vishia.gral.base.GralTextField;
    018import org.vishia.gral.base.GralWidget;
    019import org.vishia.gral.ifc.GralRectangle;
    020import org.vishia.gral.swt.SwtMng;
    021import org.vishia.util.KeyCode;
    022
    023/**Implementation of the {@link GralTextField} in awt graphics.
    024 * The original {@link java.awt.TextField} has a considerable border for a smart outfit. That is not proper for some applications
    025 * which needs an slim and simple outfit without borders because the smart outfit properties are given outside of the textfield itself.
    026 * Therefore the functionality of a text field is implemented with a simple canvas. All functions to edit the content with keyboard
    027 * are implemented here in an independent way of the awt.TextField. The {@link #paint(Graphics)} shows the simple outfit in a special kind.
    028 *
    029 * @author Hartmut Schorrig
    030 *
    031 */
    032public class AwtTextField extends GralTextField.GraphicImplAccess
    033{
    034
    035    /**Version, history and license.
    036   * <ul>
    037   * <li>2015-10-30 Hartmut improved, own implementation with canvas
    038   * <li>2011-10-31 Hartmut created.
    039   * </ul>
    040   *
    041   * <b>Copyright/Copyleft</b>:
    042   * For this source the LGPL Lesser General Public License,
    043   * published by the Free Software Foundation is valid.
    044   * It means:
    045   * <ol>
    046   * <li> You can use this source without any restriction for any desired purpose.
    047   * <li> You can redistribute copies of this source to everybody.
    048   * <li> Every user of this source, also the user of redistribute copies
    049   *    with or without payment, must accept this license for further using.
    050   * <li> But the LPGL is not appropriate for a whole software product,
    051   *    if this source is only a part of them. It means, the user
    052   *    must publish this part of source,
    053   *    but don't need to publish the whole source of the own product.
    054   * <li> You can study and modify (improve) this source
    055   *    for own using or for redistribution, but you have to license the
    056   *    modified sources likewise under this LGPL Lesser General Public License.
    057   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    058   * </ol>
    059   * If you are intent to use this sources without publishing its usage, you can get
    060   * a second license subscribing a special contract with the author.
    061   *
    062   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    063   */
    064  public final static String sVersion = "2015-10-30";
    065
    066
    067  /**The AWT widget. A TextField is not used because a TextField has a border which is not proper in any case.
    068   * Therefore the capability of text output and edit is implemented with an own algorithm.
    069   */
    070  final TextCanvas widgetAwt;
    071
    072  /**A possible prompt for the text field or null. */
    073  /*packagePrivate*/ Label promptSwt;
    074
    075  /**It contains the association to the swt widget (Control) and the {@link SwtMng}
    076   * and implements some methods of {@link GralWidgImpl_ifc} which are delegate from this.
    077   */
    078  private final AwtWidgetHelper widgHelper;
    079
    080  StringBuilder editBuffer;
    081
    082
    083  public AwtTextField(GralTextField widgg, AwtWidgetMng mng)
    084  { widgg.super(widgg); //NOTE: superclass is a non static inner class of GralTextField.
    085    if(widgg.isEditable()){
    086      editBuffer = new StringBuilder(20);
    087      editBuffer.setLength(0); editBuffer.append(dyda().displayedText);
    088    }
    089    GralPos pos = widgg.pos();
    090    Container panelAwt = (Container)pos.panel.getWidgetImplementation();
    091
    092    widgetAwt = new TextCanvas(); //TextField();
    093    widgetAwt.setData(widgg);
    094    widgetAwt.addFocusListener(mng.focusListener);
    095    widgetAwt.addMouseListener(mng.mouseStdAction);
    096    widgetAwt.addKeyListener(keyListener);
    097    //widgetAwt.set
    098    //widgetAwt.addHierarchyBoundsListener(hierarchyBoundsListener);
    099    mng.setPosAndSize_(posField, widgetAwt);
    100    //widgetAwt.setForeground(mng.propertiesGuiAwt.colorAwt(GralColor.getColor("rd")));
    101    //widgetAwt.setBackground(mng.propertiesGuiAwt.colorAwt(GralColor.getColor("gn")));
    102    panelAwt.add(widgetAwt);
    103    widgHelper = new AwtWidgetHelper(widgetAwt, mng);
    104  }
    105
    106  @Override
    107  public void removeWidgetImplementation()
    108  {
    109      // TODO Auto-generated method stub
    110
    111  }
    112
    113  //@Override public int getCursorPos(){ return widgetAwt.getCaretPosition(); }
    114
    115
    116  @Override
    117  public Object getWidgetImplementation()
    118  {
    119    return widgetAwt;
    120  }
    121
    122
    123
    124  @Override public boolean setFocusGThread()
    125  { return AwtWidgetHelper.setFocusOfTabSwt(widgetAwt);
    126  }
    127
    128  /**Sets the implementation widget vible or not.
    129   * @see org.vishia.gral.base.GralWidgImpl_ifc#setVisibleGThread(boolean)
    130   */
    131  @Override public void setVisibleGThread(boolean bVisible){ super.setVisibleState(bVisible); widgHelper.setVisibleGThread(bVisible); }
    132
    133
    134  public int setCursorPos(int pos){
    135    //int oldPos = widgetAwt.getCaretPosition();
    136    ///widgetAwt.setCaretPosition(pos);
    137    return 0; //oldPos;
    138  }
    139
    140
    141
    142
    143
    144
    145  @Override
    146  public void setBoundsPixel(int x, int y, int dx, int dy){ widgHelper.setBoundsPixel(x, y, dx, dy); }
    147
    148
    149
    150
    151
    152  public void setEditable(boolean editable){
    153    //widgetAwt.setEditable(editable);
    154  }
    155
    156
    157
    158  @Override public void repaintGthread(){
    159    GralWidget.DynamicData dyda = dyda();
    160    int chg = dyda.getChanged();
    161    if((chg & chgText) !=0  && dyda.displayedText !=null){
    162      if(widgg.isEditable()){
    163        editBuffer.setLength(0); editBuffer.append(dyda().displayedText);
    164      }
    165    }
    166    if((chg & chgEditable) !=0) {
    167      if(widgg.isEditable()){
    168        if(editBuffer == null) { editBuffer = new StringBuilder(20); }
    169        editBuffer.setLength(0); editBuffer.append(dyda().displayedText);
    170      } else { //not editable
    171        editBuffer = null;  //garbage it.
    172      }
    173    }
    174    dyda.acknChanged(chg);
    175    if((chg & chgColorText) !=0){ widgetAwt.setForeground(widgHelper.mng.getColorImpl(dyda.textColor)); }
    176    if((chg & chgColorBack) !=0){ widgetAwt.setBackground(widgHelper.mng.getColorImpl(dyda.backColor)); }
    177    widgetAwt.repaint();
    178  }
    179
    180
    181
    182  @Override public GralRectangle getPixelPositionSize()
    183  {
    184    // TODO Auto-generated method stub
    185    return null;
    186  }
    187
    188
    189
    190
    191  private void processKey(int key){
    192    int caretPos = caretPos();
    193    int caretPos1 = caretPos;
    194    if(KeyCode.isWritingKey(key) && widgg.isEditable()){
    195      switch(key){
    196        case KeyCode.del: {
    197          if(caretPos < editBuffer.length()) {
    198            editBuffer.deleteCharAt(caretPos);
    199            caretPos1 = -1; //force repaint
    200          }
    201        } break;
    202        case KeyCode.back: {
    203          if(caretPos >=1){
    204            caretPos -=1;
    205            editBuffer.deleteCharAt(caretPos);
    206          }
    207        } break;
    208        default: {
    209        }
    210        editBuffer.insert(caretPos, (char)key);
    211        caretPos +=1;
    212      } //switch
    213      dyda().displayedText = editBuffer.toString(); //it will be shown, a String is necessary.
    214    } else {
    215      switch(key){
    216        case KeyCode.left: if(caretPos >=1){ caretPos -=1; } break;
    217        case KeyCode.right: if(caretPos < editBuffer.length()){ caretPos +=1; } break;
    218      }
    219    }
    220    if(caretPos != caretPos1) {
    221      caretPos(caretPos);  //set new pos.
    222      widgetAwt.repaint();
    223    }
    224  }
    225
    226
    227  private void paint(Graphics gc) {
    228    String text = dyda().displayedText;
    229    Rectangle r = widgetAwt.getBounds();
    230    if(text != null) {
    231      gc.drawString(text, 1, r.height -2);
    232      if(widgg.isEditable() && widgg.isInFocus()) {
    233        int caretPos = caretPos();
    234        int x = 7*caretPos;
    235        gc.drawLine(x, 1, x, r.height-2);
    236      }
    237    }
    238  }
    239
    240  HierarchyBoundsListener hierarchyBoundsListener = new HierarchyBoundsListener()
    241  {
    242
    243    @Override public void ancestorMoved(HierarchyEvent e)
    244    {
    245      System.out.println("AwtField: hierarchy-anchestorMoved");
    246
    247    }
    248
    249    @Override public void ancestorResized(HierarchyEvent e)
    250    {
    251      System.out.println("AwtField: hierarchy-anchestorResized");
    252
    253    }
    254
    255  };
    256
    257
    258  @SuppressWarnings("serial")
    259  class TextCanvas extends Canvas implements AwtWidget {
    260
    261    Object data;
    262
    263    @SuppressWarnings("synthetic-access")
    264    @Override public void paint(Graphics gc) {
    265      AwtTextField.this.paint(gc);
    266    }
    267
    268    @Override public Object getData() { return data; }
    269
    270    @Override public void setData(Object data){ this.data = data; }
    271
    272  }
    273
    274
    275
    276  KeyListener keyListener = new KeyListener() {
    277
    278    /**Invoked on character keys
    279     * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
    280     */
    281    @SuppressWarnings("synthetic-access")
    282    @Override public void keyTyped(KeyEvent e)
    283    {
    284      int key = AwtGralKey.convertFromAwt(e.getKeyCode(), e.getModifiersEx(), e.getKeyChar());
    285      //processKey(key);
    286
    287    }
    288
    289    /**Invoked on function keys and on character keys.
    290     * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
    291     */
    292    @SuppressWarnings("synthetic-access")
    293    @Override public void keyPressed(KeyEvent e)
    294    {
    295      int key = AwtGralKey.convertFromAwt(e.getKeyCode(), e.getModifiersEx(), e.getKeyChar());
    296      processKey(key);
    297    }
    298
    299    @Override public void keyReleased(KeyEvent e)
    300    {
    301      // TODO Auto-generated method stub
    302
    303    }
    304
    305  };
    306
    307
    308
    309
    310
    311
    312
    313
    314}