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}