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}