001package org.vishia.gral.base;
002
003import org.vishia.gral.ifc.GralUserAction;
004import org.vishia.gral.ifc.GralWidget_ifc;
005import org.vishia.util.KeyCode;
006
007/**The main key listener.
008 * <b>Processing of keys</b>: (2012-06-17)<br>
009 * Key events are produced by the underlying graphic operation system. Usual they are applied to the widgets of the
010 * operation system graphic. For example, key left and right are used to navigate in a text field.
011 * <br><br>
012 * On system graphic level any widget can have its key listener. Then the keys are applied to it, the listener determines 
013 * what to do with keys. Usual the key is applied to the standard behavior of the widget after them. 
014 * But the key event may be set to 'do not do it' in the key listener. Then the standard behavior of the key in that widget is prevent.
015 * <br><br>
016 * The action for some keys may be determined for a special widget or widget type in an graphic system independent way.
017 * The {@link GralWidget#setActionChange(org.vishia.gral.ifc.GralUserAction)} method can be given for any widget.
018 * The {@link GralUserAction#userActionGui(int, GralWidget, Object...)} will be invoked with the {@link KeyCode} 
019 * and the widget reference. But firstly the {@link #specialKeysOfWidgetType(int, GralWidget)} is called. 
020 * This method may be overridden for the widget type. If it returns true, the key code is not applied to any user action,
021 * it is a widget-special key. 
022 * <br><br>
023 * If that method returns false or a {@link GralWidget#getActionChange()} action is not given for this widget,
024 * the key will be applied to the {@link GralMng#setMainKeyAction(org.vishia.gral.ifc.GralUserAction)}.
025 * In that way a application-global usage of some keys is organized.
026 * <br><br>
027 * If any of the both widget specific or global {@link GralUserAction#userActionGui(int, GralWidget, Object...)} method 
028 * returns true, the key is not used for the widget in the graphic system. In that kind some keys can be blocked
029 * for standard behavior.
030 * <br><br>
031 * <b>class diagramm of usage for example in SWT: </b>
032 * <pre>
033 *                                                                 GralWidget <------------|
034 *                                                                                         |
035 *    SwtSpecialWidgetKeyListener ----|> SwtKeyListner ----|> swt.KeyListener <------- SwtWidget
036 *    + specialKeysOfWidgetType()                  |
037 *                                           |<----| 
038 *                                           |
039 *    GralSpecialWidgetKeyListener ---|> GralKeyListener
040 *    +specialKeysOfWidgetType()             * keyPressed(key, gralWidg)
041 *                                                * gralWidg.getActionChange().userActionGui(...)
042 *                                                * mng.userMainKeyAction().userActionGui(...)
043 *  
044 *  </pre>
045 *  (See {@link org.vishia.util.Docu_UML_simpleNotation})
046 *  <br><br>
047 *  The implementing graphic system aggregates an instance of this class.
048 *  An underived instance is created in the {@link GralMng.InternalPublic#gralKeyListener}.
049 *  This instance can be used as aggregation in all implementing system listeners, if the
050 *  {@link #specialKeysOfWidgetType(int, GralWidget)} should not overridden.
051 *  
052 * @author Hartmut Schorrig
053 *
054 */
055public class GralKeyListener implements GralKeySpecial_ifc
056{
057  /**Version, history and license
058   * <ul>
059   * <li>2011-12-03 Hartmut created. Any widget may have the same key listener. It is the baseclass of it
060   *   and empty yet. 
061   * </ul>
062   * 
063   * <b>Copyright/Copyleft</b>:
064   * For this source the LGPL Lesser General Public License,
065   * published by the Free Software Foundation is valid.
066   * It means:
067   * <ol>
068   * <li> You can use this source without any restriction for any desired purpose.
069   * <li> You can redistribute copies of this source to everybody.
070   * <li> Every user of this source, also the user of redistribute copies
071   *    with or without payment, must accept this license for further using.
072   * <li> But the LPGL ist not appropriate for a whole software product,
073   *    if this source is only a part of them. It means, the user
074   *    must publish this part of source,
075   *    but don't need to publish the whole source of the own product.
076   * <li> You can study and modify (improve) this source
077   *    for own using or for redistribution, but you have to license the
078   *    modified sources likewise under this LGPL Lesser General Public License.
079   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
080   * </ol>
081   * If you are intent to use this sources without publishing its usage, you can get
082   * a second license subscribing a special contract with the author. 
083   * 
084   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
085   * 
086   * 
087   */
088  public final static int version = 20120609;
089 
090  
091  protected final GralMng mng;
092  
093  
094  public GralKeyListener(GralMng mng){
095    this.mng = mng;
096  }
097  
098  
099  
100  public boolean keyPressed(int keyCode, GralWidget_ifc widgi, Object widgImpl){
101    boolean actionDone;
102    GralWidget_ifc.ActionChange action = widgi.getActionChange(GralWidget_ifc.ActionChangeWhen.onAnyChgContent); 
103    if(action !=null){
104      Object[] args = action.args();
105    }
106    final GralMng mng = widgi.gralMng();
107    try{
108      actionDone = specialKeysOfWidgetType(keyCode, widgi, widgImpl);
109      if(!actionDone && action !=null){ 
110        Object[] args = action.args();
111        if(args == null){ actionDone = action.action().exec(keyCode, widgi); }
112        else { actionDone = action.action().exec(keyCode, widgi, args); }
113      } //if(table.)
114      if(!actionDone && mng.userMainKeyAction() !=null){
115        actionDone = mng.userMainKeyAction().exec(keyCode, widgi);
116      }
117      if(!actionDone){
118        GralUserAction mainKeyAction = mng.getRegisteredUserAction("KeyAction");
119        if(mainKeyAction !=null){
120          //old form called because compatibility, if new for with int-parameter returns false.
121          if(!mainKeyAction.exec(keyCode, widgi)){
122            mainKeyAction.exec(keyCode, widgi, new Integer(keyCode));
123          }
124        }
125      }
126    } catch(Exception exc){
127      mng.log.sendMsg(0, "KeyListener - UsercallException; key=%8x; %s;", keyCode, exc.getLocalizedMessage());
128    }
129
130    return true;
131  }
132  
133  
134  @Override public boolean specialKeysOfWidgetType(int key, GralWidget_ifc widgg, Object widgImpl){ return false; }
135
136  
137}