    001package org.vishia.gral.widget;
    002
    003import java.util.List;
    004import java.util.Map;
    005
    006import org.vishia.gral.base.GralTable;
    007import org.vishia.gral.base.GralWidget;
    008import org.vishia.gral.ifc.GralMngBuild_ifc;
    009import org.vishia.gral.ifc.GralMng_ifc;
    010import org.vishia.gral.ifc.GralUserAction;
    011import org.vishia.gral.ifc.GralTableLine_ifc;
    012import org.vishia.util.Assert;
    013import org.vishia.util.KeyCode;
    014import org.vishia.util.Removeable;
    015
    016/**The base class for lists which supports nested selections. The associated widget is a table.
    017 * The action listener {@link #actionTable} captures all key and mouse activities on the table-widget.
    018 * It is the base class for file selection and command selection.
    019 * The base idea is, left and right keys navigates in a tree to outer and deeper nodes. The table
    020 * shows only members of the current node. A text line shows the current node path.
    021 * It may be possible to switch to a tree presentation (TODO). But this complex widget should occupy
    022 * only a simple rectangle of a GUI, not some windows etc. It may be less in spread too if necessary.
    023 * <br><br>
    024 * Note: this class should not be a derived class of {@link GralTable}, because instances of derived classes
    025 * should be created as final compositions in the main thread before the table can be presented
    026 * in the graphic thread. Therefore the aggregation {@link #wdgdTable} cannot be final. It is set
    027 * only when {@link #setToPanel(GralMngBuild_ifc, String, int, int[], char)} is called.
    028 * <pre>
    029 *  GralSelectList
    030 *        |--{@link #wdgdTable}--->GralTable         TableLineData
    031 *                                     |---idxLine------*>|
    032 *                                     |---tableLines---*>|
    033 * </pre>
    034 * @author Hartmut Schorrig
    035 *
    036 */
    037public abstract class GralSelectList<UserData> implements Removeable //extends GralWidget
    038{
    039  /**Version and history:
    040   * <ul>
    041   * <li>2018-10-28 Hartmut chg: {@link #createImplWidget_Gthread()} instead setToPanel(mng)
    042   * <li>2011-11-18 chg: This class does not inherit from GralWidget now. The GralWidget, which represents this class,
    043   *   is referenced with the public aggregation {@link #wdgdTable}. Only this instance is registered on a panel
    044   *   calling {@link #setToPanel(GralMngBuild_ifc, String, int, int[], char)}.
    045   * <li>2011-10-02 chg: Uses keycodes from {@link KeyCode} now,
    046   * <li>2011-10-02 chg: {@link #actionOk(Object, GralTableLine_ifc)} returns boolean now, false if no action is done.
    047   * <li>older- TODO
    048   * </ul>
    049   * <b>Copyright/Copyleft</b>:
    050   * For this source the LGPL Lesser General Public License,
    051   * published by the Free Software Foundation is valid.
    052   * It means:
    053   * <ol>
    054   * <li> You can use this source without any restriction for any desired purpose.
    055   * <li> You can redistribute copies of this source to everybody.
    056   * <li> Every user of this source, also the user of redistribute copies
    057   *    with or without payment, must accept this license for further using.
    058   * <li> But the LPGL ist not appropriate for a whole software product,
    059   *    if this source is only a part of them. It means, the user
    060   *    must publish this part of source,
    061   *    but don't need to publish the whole source of the own product.
    062   * <li> You can study and modify (improve) this source
    063   *    for own using or for redistribution, but you have to license the
    064   *    modified sources likewise under this LGPL Lesser General Public License.
    065   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    066   * </ol>
    067   * If you are indent to use this sources without publishing its usage, you can get
    068   * a second license subscribing a special contract with the author.
    069   *
    070   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    071   *
    072   */
    073  public static final String version = "2018-10-28";
    074
    075
    076  /**The table which is showing in the widget. */
    077  public GralTable<UserData> wdgdTable;
    078
    079
    080  /**The keys for left and right navigation. Default it is shift + left and right arrow key.
    081   *
    082   */
    083  protected int keyLeft = KeyCode.alt + KeyCode.left, keyRight = KeyCode.alt + KeyCode.right;
    084
    085
    086
    087  /**Not used yet, register actions? */
    088  protected Map<String, GralUserAction> actions;
    089
    090  protected GralSelectList(String posName, int rows, int[] columns, char size) //String name, GralWidgetMng mng)
    091  {
    092    if(posName == null){
    093      Assert.stop();
    094    }
    095    wdgdTable = new GralTable<UserData>(posName, rows, columns);
    096    wdgdTable.setVisible(true);
    097  }
    098
    099
    100  /**The left and right key codes for selection left and right can be changed.
    101   * The key code is a number maybe in combination with alt, ctrl, shift see {@link KeyCode}.
    102   * @param keyLeft Key code for outer selection
    103   * @param keyRight KeyCode for deeper selection
    104   */
    105  public final void setLeftRightKeys(int keyLeft, int keyRight){
    106    this.keyLeft = keyLeft; this.keyRight = keyRight;
    107  }
    108
    109  //public SelectList()
    110  //{
    111  //  super('l');
    112  //}
    113
    114
    115  /**
    116   * @param panel
    117   * @param identArgJbat
    118   * @param rows
    119   * @param columns
    120   * @param size
    121   */
    122  public void XXXsetToPanel(GralMngBuild_ifc gralMng)
    123  {
    124    wdgdTable.setToPanel(gralMng);
    125    //wdgdTable = gralMng.addTable(name, rows, columns);
    126    wdgdTable.setActionChange(actionTable);
    127  }
    128
    129
    130
    131  /**
    132   */
    133  public void createImplWidget_Gthread()
    134  {
    135    wdgdTable.createImplWidget_Gthread();
    136    wdgdTable.setActionChange(actionTable);
    137  }
    138
    139
    140
    141  public void set(List<String[]> listData)
    142  {
    143    for(String[] data: listData){
    144      wdgdTable.setValue(GralMng_ifc.cmdInsert, 0, data[0]);
    145    }
    146  }
    147
    148
    149  /**Sets the focus of the associated table widget.
    150   * @return true if focused.
    151   */
    152  public boolean setFocus(){ wdgdTable.setFocus(); return true; }
    153
    154  /**Removes all data and all widgets of this class. */
    155  @Override public boolean remove(){
    156    wdgdTable.remove();
    157    return true;
    158  }
    159
    160  /**Action if a table line is selected and entered. Its either a double click with the mouse
    161   * or click of OK (Enter) button.
    162   * @param userData The user data stored in the line of table.
    163   */
    164  protected abstract boolean actionOk(Object userData, GralTableLine_ifc<UserData> line);
    165
    166  /**Action if a table line is selected and ctrl-left is pressed or the release button is pressed.
    167   * @param userData The user data stored in the line of table.
    168   */
    169  protected abstract void actionLeft(Object userData, GralTableLine_ifc<UserData> line);
    170
    171  /**Action if a table line is selected and ctrl-right is pressed or the release button is pressed.
    172   * @param userData The user data stored in the line of table.
    173   */
    174  protected abstract void actionRight(Object userData, GralTableLine_ifc<UserData> line);
    175
    176
    177  /**Action if a table line is selected and any other key is pressed or the context menu is invoked.
    178   * @param key code or mouse code, one of constans from {@link KeyCode}.
    179   * @param userData The user data stored in the line of table.
    180   * @param line The table line.
    181   * @return true if is was relevant for the key.
    182   */
    183  protected abstract boolean actionUserKey(int key, Object userData, GralTableLine_ifc<UserData> line);
    184
    185
    186  private final GralUserAction actionTable = new GralUserAction("actionTable")
    187  {
    188
    189    @Override public boolean userActionGui(int keyCode, GralWidget widgdTable, Object... params)
    190    {
    191      //assert(sIntension.equals("table-key"));
    192      @SuppressWarnings("unchecked")
    193      GralTableLine_ifc<UserData> line = (GralTableLine_ifc<UserData>)params[0];
    194      Object data = line == null ? null : line.getUserData();
    195      //int keyCode = (Integer)params[1];
    196      boolean done = true;
    197      if(data !=null) {
    198        if(keyCode == keyLeft){ actionLeft(data, line); }
    199        else if(keyCode == keyRight){ actionRight(data, line); }
    200        else if(keyCode == KeyCode.enter){ done = actionOk(data, line); }
    201        else if(keyCode == KeyCode.mouse1Double){ done = actionOk(data, line); }
    202        else { done = actionUserKey(keyCode, data, line); }
    203      } else {
    204        done = false;
    205      }
    206      return done;
    207    }
    208
    209
    210  };
    211
    212
    213
    214  void stop(){}
    215
    216}