    001package org.vishia.gral.cfg;
    002
    003import java.text.ParseException;
    004
    005import org.vishia.gral.base.GralButton;
    006import org.vishia.gral.base.GralPos;
    007import org.vishia.gral.base.GralWidget;
    008import org.vishia.gral.base.GralMng;
    009import org.vishia.gral.base.GralWindow;
    010import org.vishia.gral.ifc.GralColor;
    011import org.vishia.gral.ifc.GralMng_ifc;
    012import org.vishia.gral.ifc.GralRectangle;
    013import org.vishia.gral.ifc.GralUserAction;
    014import org.vishia.gral.ifc.GralWidget_ifc;
    015import org.vishia.gral.ifc.GralWindow_ifc;
    016import org.vishia.msgDispatch.LogMessage;
    017import org.vishia.util.KeyCode;
    018
    019public class GralCfgDesigner
    020{
    021
    022  /**Version, history and license.
    023   * <ul>2015-27-01 Hartmut new: Now a text field can be set editable. Usage of a boolean {@link GralCfgData#editable}
    024   * instead changing the type of a text field from 'S' to 'T', but in {@link GralCfgWriter#writeShowField(org.vishia.gral.cfg.GralCfgData.GuiCfgShowField)}
    025   *  it is written as a "InputTextline(...". It means next read of the config reads it as editable.
    026   * <li>2011-12-03 Hartmut chg: Now the current widget is stored by left-mouse-release in the field
    027   *   {@link #widggForDialog}. Editing of Led works. sFormat is regarded.
    028   * <li>2011-09-30 Hartmut chg: rename pressedRightMouseDownForDesign(...) to {@link #editFieldProperties(GralWidget, GralRectangle)}.
    029   *     because it isn't called as mouse action.
    030   * <li>2011-09-23 Hartmut corr: Use the new windows concept with {@link GralWindow}.
    031   * <li>2011-07-07 Hartmut new: Improve dialog, edit all fields of the {@link GralWidget} inclusive positions.
    032   * <li>2011-05-24 Created. The configuration of fields of a GUI are edit-able now in the GUI itself without any other tool.
    033   * </ul>
    034   *
    035   * <b>Copyright/Copyleft</b>:<br>
    036   * For this source the LGPL Lesser General Public License,
    037   * published by the Free Software Foundation is valid.
    038   * It means:
    039   * <ol>
    040   * <li> You can use this source without any restriction for any desired purpose.
    041   * <li> You can redistribute copies of this source to everybody.
    042   * <li> Every user of this source, also the user of redistribute copies
    043   *    with or without payment, must accept this license for further using.
    044   * <li> But the LPGL is not appropriate for a whole software product,
    045   *    if this source is only a part of them. It means, the user
    046   *    must publish this part of source,
    047   *    but doesn't need to publish the whole source of the own product.
    048   * <li> You can study and modify (improve) this source
    049   *    for own using or for redistribution, but you have to license the
    050   *    modified sources likewise under this LGPL Lesser General Public License.
    051   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    052   * </ol>
    053   * If you intent to use this source without publishing its usage, you can get
    054   * a second license subscribing a special contract with the author.
    055   *
    056   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    057   */
    058  public static final String version = "2015-01-27";
    059
    060  protected final LogMessage log;
    061
    062  private final GralMng mng;
    063
    064  private final GralCfgBuilder cfgBuilder;
    065
    066  /**A Panel which contains the table to select some projectPaths. */
    067  //private GuiShellMngBuildIfc dialogWindowProps;
    068  private GralWindow dialogWindowProps;
    069
    070  /**Some dialog widget elements. */
    071  GralWidget dialogFieldName, dialogFieldDatapath, dialogFieldText, dialogFieldFormat
    072    , dialogFieldShow, dialogFieldAction, dialogFieldPrompt, dialogFieldHelp, dialogFieldPromptPos
    073    , dialogFieldLine, dialogFieldColumn, dialogFieldHeight, dialogFieldWidth;
    074
    075  GralButton dialogBtnEditable;
    076
    077  private GralWidget dialogButtonOk, dialogButtonEsc;
    078
    079  /**Coordinates while left mouse pressed. */
    080  private int xMouse0, yMouse0;
    081
    082  /**Coordinates while mouse moved, capture on release button. */
    083  private int xMouse, yMouse;
    084
    085  private boolean bWidgetMoving = false;
    086
    087  /**The widget which properties are edit yet or null. */
    088  GralWidget widgdInDialog = null;
    089
    090  /**The widget which was marked (with left mouse up). This widget will be used for design-edit
    091   * if the next action is {@link #editFieldProperties(GralWidget, GralRectangle)}.
    092   */
    093  GralWidget widggForDialog;
    094
    095  public GralCfgDesigner(GralCfgBuilder cfgBuilder, GralMng mng, LogMessage log)
    096  { this.cfgBuilder = cfgBuilder;
    097    this.log = log;
    098    this.mng = mng;
    099  }
    100
    101
    102  /**Initializes the dialog box of the field properties.
    103   * It should be called in the GUI-Thread.
    104   */
    105  public void setToPanel()
    106  {
    107    assert(dialogWindowProps == null); //check call only one time.
    108    mng.selectPanel("primaryWindow");
    109    mng.setPosition(-38, GralPos.size +38, -40, GralPos.size +40, 1, 'r');
    110    dialogWindowProps = mng.createWindow("widgetEdit", "Widget Properties", GralWindow.windConcurrently);
    111
    112    mng.setPositionSize(1, 0, 3, 34, 'd');
    113    dialogFieldName = mng.addTextField("name", true, "name", "t");
    114    dialogFieldDatapath = mng.addTextField("dataPath", true, "data", "t");
    115    dialogFieldText = mng.addTextField("text", true, "text", "t");
    116    dialogFieldFormat = mng.addTextField("format", true, "format", "t");
    117    dialogFieldShow = mng.addTextField("show", true, "show method", "t");
    118    dialogFieldAction = mng.addTextField("action", true, "action method", "t");
    119    dialogFieldHelp = mng.addTextField("help", true, "help", "t");
    120    dialogFieldPrompt = mng.addTextField("prompt", true, "prompt", "t");
    121    //mng.setPositionSize(GralGridPos.same, GralGridPos.same, GralGridPos.next, 2, 'r');
    122    mng.setPositionSize(27, 2, 3, 5, 'r');
    123    dialogFieldLine = mng.addTextField("line", true, "pos-y", "t");
    124    //mng.addText(", ", 'B', 0);
    125    dialogFieldColumn = mng.addTextField("column", true, "pos-x", "t");
    126    //mng.addText("   ", 'B', 0);
    127    dialogFieldHeight = mng.addTextField("height", true, "size-y", "t");
    128    //mng.addText(" x ", 'B', 0);
    129    dialogFieldWidth = mng.addTextField("width", true, "size-x", "t");
    130    dialogFieldPromptPos = mng.addTextField("promptPos", true, "promptPos", "t");
    131    dialogBtnEditable = mng.addSwitchButton("editable", "view", "edit", GralColor.getColor("wh"), GralColor.getColor("or"));
    132    mng.setPositionSize(31, 2, 3, 8, 'r');
    133    dialogButtonEsc = mng.addButton("esc", actionEsc, null, null, "esc");
    134    dialogButtonOk = mng.addButton("del", actionDel, null, null, "del");
    135    dialogButtonOk = mng.addButton("OK", actionOk, null, null, "OK");
    136  }
    137
    138
    139
    140  public void pressedLeftMouseDownForDesign(GralWidget widgd, GralRectangle xy)
    141  {
    142    xMouse0 = xy.x;
    143    yMouse0 = xy.y;
    144    bWidgetMoving = true;
    145  }
    146
    147
    148  public void markWidgetForDesign(GralWidget widgg)
    149  {
    150    widggForDialog = widgg;
    151  }
    152
    153
    154  public void releaseLeftMouseForDesign(GralWidget widgd, GralRectangle xy, boolean bCopy)
    155  {
    156    if(bWidgetMoving){
    157      bWidgetMoving = false;
    158      int dxPixel = xy.x - xMouse0;
    159      int dyPixel = xy.y - yMouse0;
    160
    161      float dxGridf = (float)dxPixel / mng.propertiesGui.xPixelUnit();
    162      float dyGridf = (float)dyPixel / mng.propertiesGui.yPixelUnit();
    163
    164      int dxGrid = (int)(dxGridf >0 ? dxGridf + 0.5f : dxGridf - 0.5f);
    165      int dyGrid = (int)(dyGridf >0 ? dyGridf + 0.5f : dyGridf - 0.5f);
    166
    167      GralCfgElement cfge = (GralCfgElement)widgd.getCfgElement();
    168      if(cfge !=null){
    169        String sPanel = cfge.getPanel();  //Note: The cloned Object maybe empty here before buildWidget() is called
    170        int xPosAct = cfge.get_xPos();
    171        int yPosAct = cfge.get_yPos();
    172        if(bCopy){
    173          GralCfgElement cfgn = cfge.clone(); //cfgBuilder.newCfgElement(cfge);
    174          cfge = cfgn;
    175        }
    176        if(cfge.positionString !=null) {
    177
    178        } else {
    179          cfge.positionInput.xPos = xPosAct + dxGrid;
    180          cfge.positionInput.yPos = yPosAct + dyGrid;
    181        }
    182        if(!bCopy){
    183          widgd.remove();
    184          //mng.remove(widgd);  //remove the widget.
    185        }
    186        mng.selectPanel(sPanel);
    187        try{ cfgBuilder.buildWidget(cfge);
    188        } catch(ParseException exc) {
    189          System.err.println("GralCfgDesigner - setPos, " + exc.getMessage());
    190        }
    191      }
    192
    193    }
    194
    195  }
    196
    197
    198  public void editFieldProperties(GralWidget widgd, GralRectangle xy)
    199  { //widgd = widgdInDialog = widggForDialog;
    200    widgdInDialog = widggForDialog = widgd;
    201    if(widgdInDialog != null){
    202      //widgd = widgdInDialog;
    203      GralCfgElement cfge = (GralCfgElement)widgd.getCfgElement();
    204      String sName, sDataPath, sText, sFormat, sShowMethod,  sActionMethod;
    205      String sPrompt, sPromptPos;
    206      String sLine, sColumn, sWidth, sHeight;
    207      if(cfge !=null){
    208        sName = cfge.widgetType.name;
    209        sDataPath = cfge.widgetType.data;
    210        sText = cfge.widgetType.text;
    211        sFormat = cfge.widgetType.format;
    212        sShowMethod = cfge.widgetType.showMethod;
    213        sActionMethod = cfge.widgetType.userAction;
    214        sPrompt = cfge.widgetType.prompt;
    215        sPromptPos = cfge.widgetType.promptPosition;
    216
    217        sLine = (cfge.positionInput.yPosRelative ? "&" : "") + cfge.positionInput.yPos + (cfge.positionInput.yPosFrac !=0 ? "." + cfge.positionInput.yPosFrac : "");
    218        sColumn = (cfge.positionInput.xPosRelative ? "&" : "") + cfge.positionInput.xPos + (cfge.positionInput.xPosFrac !=0 ? "." + cfge.positionInput.xPosFrac : "");
    219        sHeight = "" + cfge.positionInput.ySizeDown + (cfge.positionInput.ySizeFrac !=0 ? "." + cfge.positionInput.ySizeFrac : "");
    220        sWidth = "" + cfge.positionInput.xWidth + (cfge.positionInput.xSizeFrac !=0 ? "." + cfge.positionInput.xSizeFrac : "");
    221        dialogFieldName.setText(sName ==null ? "" : sName);
    222        dialogFieldDatapath.setText( sDataPath == null ? "" : sDataPath);
    223        dialogFieldText.setText(sText ==null ? "" : sText);
    224        dialogFieldFormat.setText( sFormat ==null ? "" : sFormat);
    225        dialogFieldShow.setText( sShowMethod ==null ? "" : sShowMethod);
    226        dialogFieldAction.setText( sActionMethod ==null ? "" : sActionMethod);
    227        dialogFieldHelp.setText(cfge.widgetType.help !=null ? cfge.widgetType.help : "");
    228        dialogFieldPrompt.setText( sPrompt ==null ? "" : sPrompt);
    229        dialogFieldPromptPos.setText( sPromptPos ==null ? "" : sPromptPos);
    230        dialogFieldLine.setText( sLine);
    231        dialogFieldColumn.setText( sColumn);
    232        dialogFieldHeight.setText( sHeight);
    233        dialogFieldWidth.setText( sWidth);
    234        dialogBtnEditable.setValue(cfge.widgetType.editable ? 1 : 0);
    235      } else {
    236        dialogFieldName.setText( "ERROR cfge");
    237      }
    238    }
    239    //dialogWindowProps.posWindow.setPosition(widgd.pos, widgd.pos.y +2, GralGridPos.size+30, widgd.pos.x, GralGridPos.size+40, 1, 'r' );
    240    //dialogWindowProps.setWindowVisible(true);
    241    //use manager to position.
    242    dialogWindowProps.setFocus(); //Visible(true);
    243    //dialogWindowProps.chgPos(dialogWindowProps.pos());
    244    //mng.setWindowsVisible(dialogWindowProps, dialogWindowProps.pos());
    245  }
    246
    247  private final GralUserAction actionOk = new GralUserAction("actionOk")
    248  { @Override public boolean exec(int key, GralWidget_ifc widgd, Object... params)
    249    { //note widgd is the OK-button!
    250      if(KeyCode.isControlFunctionMouseUpOrMenu(key) && widgdInDialog !=null){
    251        String sName = dialogFieldName.getValue();
    252        String sDataPath = dialogFieldDatapath.getValue();
    253        String sText = dialogFieldText.getValue();
    254        String sFormat = dialogFieldFormat.getValue();
    255        String sShowMethod = dialogFieldShow.getValue();
    256        String sActionMethod = dialogFieldAction.getText();
    257        String sHelp = dialogFieldHelp.getValue();
    258        String sPrompt = dialogFieldPrompt.getValue();
    259        String sPromptPos = dialogFieldPromptPos.getValue();
    260        String sLine = dialogFieldLine.getValue();
    261        String sColumn = dialogFieldColumn.getValue();
    262        String sWidth = dialogFieldWidth.getValue();
    263        String sHeight = dialogFieldHeight.getValue();
    264        boolean editable = dialogBtnEditable.isOn();
    265
    266        GralCfgElement cfge = (GralCfgElement)widgdInDialog.getCfgElement();
    267        if(cfge !=null){
    268          String sPanel = cfge.getPanel();  //Note: The cloned Object maybe empty here before buildWidget() is called
    269            /*if(sName.trim().length() >0) { cfge.widgetType.name = sName; }
    270          if(sDataPath.trim().length() >0) { cfge.widgetType.info = sDataPath; }
    271          if(sText.trim().length() >0) { cfge.widgetType.text = sText; }
    272          if(sFormat.trim().length() >0) { cfge.widgetType.format = sFormat; }
    273          */
    274          cfge.widgetType.editable = editable;
    275          cfge.widgetType.name = sName.trim().length() >0 ? sName : null;
    276          cfge.widgetType.data = sDataPath.trim().length() >0 ? sDataPath : null;
    277          cfge.widgetType.text = sText.trim().length() >0 ? sText : null;
    278          cfge.widgetType.format = sFormat.trim().length() >0 ? sFormat : null;
    279          cfge.widgetType.showMethod = sShowMethod.trim().length() >0 ? sShowMethod : null;
    280          cfge.widgetType.help = sHelp.trim().length() >0 ? sHelp.trim(): null;
    281
    282          String sUserAction = sActionMethod.trim().length() >0 ? sActionMethod : null;
    283          if(editable) {
    284            //set userAction to "syncVariableOnFocus" if other is not given.
    285            cfge.widgetType.userAction = sUserAction != null ? sUserAction :  "syncVariableOnFocus";
    286          } else {
    287            //clear the userAction if "syncVariableOnFocus" was given before.
    288            cfge.widgetType.userAction = sUserAction !=null && sUserAction.equals("syncVariableOnFocus") ? null : sUserAction;
    289          }
    290          cfge.widgetType.prompt = sPrompt.trim().length() >0 ? sPrompt : null;
    291          cfge.widgetType.promptPosition = sPromptPos.trim().length() >0 ? sPromptPos : null;
    292          boolean bOk;
    293          bOk = cfge.positionInput.setPosElement('y', sLine.trim());
    294          bOk = bOk && cfge.positionInput.setPosElement('x', sColumn.trim());
    295          bOk = bOk && cfge.positionInput.setPosElement('h', sHeight.trim());
    296          bOk = bOk && cfge.positionInput.setPosElement('w', sWidth.trim());
    297          if(!bOk)
    298            stop();
    299          mng.remove(widgdInDialog);  //remove the widget.
    300          mng.selectPanel(sPanel);
    301          try{ cfgBuilder.buildWidget(cfge);
    302          } catch(ParseException exc) {
    303            //show the exception in the dialog box!
    304          }
    305        }
    306        dialogWindowProps.setWindowVisible(false);
    307        widgdInDialog = null;
    308      }
    309      return true;
    310    }
    311
    312  };
    313
    314
    315
    316
    317  private final GralUserAction actionDel = new GralUserAction("actionDel")
    318  { @Override public boolean exec(int key, GralWidget_ifc widgd, Object... params)
    319    { //note widgd is the OK-button!
    320      if(KeyCode.isControlFunctionMouseUpOrMenu(key) && widgdInDialog !=null){
    321        //widgdInDialog.remove();
    322        mng.remove(widgdInDialog);  //remove the widget.
    323        dialogWindowProps.setWindowVisible(false);
    324        widgdInDialog = null;
    325        return true;
    326      } else {
    327        return false;
    328      }
    329    }
    330
    331  };
    332
    333
    334
    335
    336
    337
    338
    339  private final GralUserAction actionEsc = new GralUserAction("actionEsc")
    340  { @Override public boolean exec(int key, GralWidget_ifc widgd, Object... params)
    341    { if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    342        dialogWindowProps.setWindowVisible(false);
    343        widgdInDialog = null;
    344      }
    345      return true;
    346    }
    347
    348  };
    349
    350
    351  void stop(){}
    352
    353}