001package org.vishia.guiInspc; 002 003import java.util.LinkedList; 004import java.util.List; 005import java.util.ListIterator; 006import java.util.Map; 007import java.util.TreeMap; 008import java.util.concurrent.atomic.AtomicBoolean; 009 010import org.vishia.byteData.VariableAccess_ifc; 011import org.vishia.gral.base.GralButton; 012import org.vishia.gral.base.GralMng; 013import org.vishia.gral.base.GralTable; 014import org.vishia.gral.base.GralTextField; 015import org.vishia.gral.base.GralWidget; 016import org.vishia.gral.base.GralWindow; 017import org.vishia.gral.ifc.GralColor; 018import org.vishia.gral.ifc.GralTableLine_ifc; 019import org.vishia.gral.ifc.GralUserAction; 020import org.vishia.gral.ifc.GralWidget_ifc; 021import org.vishia.gral.ifc.GralWindow_ifc; 022import org.vishia.inspcPC.InspcAccessExecRxOrder_ifc; 023import org.vishia.inspcPC.InspcAccess_ifc; 024import org.vishia.inspcPC.accTarget.InspcTargetAccessor; 025import org.vishia.inspcPC.mng.InspcFieldOfStruct; 026import org.vishia.inspcPC.mng.InspcMng; 027import org.vishia.inspcPC.mng.InspcStruct; 028import org.vishia.inspcPC.mng.InspcVariable; 029import org.vishia.util.KeyCode; 030 031 032/**This class presents a window with one table and some buttons to view and edit all fields in one instance 033 * in a target system. 034 * 035 * 036 * <br> 037 * The InspcFieldTable shows one struct from target data or one instance, all fields of a class of Java reflection view. 038 * The fields are stored in instances of {@link InspcFieldOfStruct} which are referenced as data in the {@link GralTable} 039 * of the private composite reference {@link #widgTable}. 040 * <br><br> 041 * 042 * <br><br> 043 * <b>Filling the table with the fields of a reflection target</b>:<br> 044 * <img src="../../../img/guiInspc_getFieldsTableOmd.png"> 045 * <br>guiInspc_getFieldsTableOmd 046 * <br> 047 * One of the methods {@link #fillTableFromFocusedVariable()}, {@link #actionBack()}, {@link #getSubStruct(GralTableLine_ifc)} 048 * are invoked from operator GUI actions. They call 049 * <br> {@link #fillTableStruct()}<br> 050 * This method checks the {@link InspcStruct} of the variable respectively the shown struct in table whether it is known already, 051 * using {@link InspcStruct#isUpdated()}. It it is not updated, on selection a new variable, the 052 * <br><br> 053 * {@link InspcTargetAccessor#requestFields(org.vishia.inspcPC.InspcTargetAccessData, InspcAccessExecRxOrder_ifc, Runnable)} 054 * <br><br> 055 * is called. This routine sets only the reference to the {@link InspcTargetAccessData} and the 2 callbacks. 056 * This action is done especially in the graphical thread. 057 * <br><br> 058 * If {@link InspcStruct#isUpdated()} returns true, then the struct was updated already. Then it can be shown in the {@link GralTable} 059 * with the names of its elements and the last gotten values. 060 * <br><br> 061 * The organization thread of {@link InspcMng} invokes {@link InspcMng#procComm()} cyclically to show and request values. 062 * In this thread via calling {@link InspcTargetAccessor#requestStart(long)} the request for getFields is recognized. 063 * For that the {@link InspcTargetAccessor#cmdGetFields(String, org.vishia.inspcPC.InspcAccessExecRxOrder_ifc)} 064 * is invoked for the path of the struct. That is sent to the target. 065 * <br><br> 066 * The target answers with some items for all fields in one or more datagram but for that request with the same sequence number. 067 * For any item respectively element of the struct the given instance to {@link InspcStruct#rxActionGetFields} 068 * is invoked which fills the struct. 069 * <br><br> 070 * After the last datagram of this answer the stored reference to the {@link Runnable}: {@link #actionUpdated} of this class 071 * is invoked. This action calls {@link #fillTableStruct()} now with received and stored fields. 072 * <br> 073 * <img src="../../../img/guiInspc_getFieldsTableSeq.png"> 074 * <br>guiInspc_getFieldsTableSeq<br> 075 * <b>Show and request values for the fields</b><br> 076 * This is simple done by getting maybe with creation of the variable for the requested field: 077 * {@link InspcFieldOfStruct#variable(InspcVariable, org.vishia.byteData.VariableContainer_ifc)} 078 * and request a new value with {@link InspcVariable#requestValue(long, Runnable)}. The callback invoked on end of the last datagram 079 * is a temporary instance {@link RunOnReceive#RunOnReceive(GralTableLine_ifc)} with the given line of the table which invokes 080 * {@link #showValue(GralTableLine_ifc, boolean)}. 081 * <br> 082 * <img src="../../../img/guiInspc_getValueTableOmd.png"> 083 * <br>guiInspc_getValueTableOmd<br> 084 * 085 * @author Hartmut Schorrig 086 * 087 */ 088public class InspcFieldTable 089{ 090 /**Version, history and license. 091 * <ul> 092 * <li>2018-09-08 Hartmut chg: because {@link InspcFieldOfStruct} hasSubstruct. 093 * <li>2016-10 Hartmut chg: Regards a field which is a node of tree, not only leaf. 094 * <li>2015-06-21 requests a new value if the older is older than 1 second, fast refresh 095 * <li>2015-05-29 requests a new value only if the current is older than 5 seconds. 096 * <li>2014-01-05 indexSelection 097 * <li>2013-12-18 Created. 098 * </ul> 099 * 100 * <b>Copyright/Copyleft</b>: 101 * For this source the LGPL Lesser General Public License, 102 * published by the Free Software Foundation is valid. 103 * It means: 104 * <ol> 105 * <li> You can use this source without any restriction for any desired purpose. 106 * <li> You can redistribute copies of this source to everybody. 107 * <li> Every user of this source, also the user of redistribute copies 108 * with or without payment, must accept this license for further using. 109 * <li> But the LPGL is not appropriate for a whole software product, 110 * if this source is only a part of them. It means, the user 111 * must publish this part of source, 112 * but don't need to publish the whole source of the own product. 113 * <li> You can study and modify (improve) this source 114 * for own using or for redistribution, but you have to license the 115 * modified sources likewise under this LGPL Lesser General Public License. 116 * You mustn't delete this Copyright/Copyleft inscription in this source file. 117 * </ol> 118 * If you are intent to use this sources without publishing its usage, you can get 119 * a second license subscribing a special contract with the author. 120 * 121 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 122 * 123 */ 124 //@SuppressWarnings("hiding") 125 protected final static String sVersion = "2015-05-30"; 126 127 @SuppressWarnings("synthetic-access") 128 class RunOnReceive implements Runnable { 129 //GralTable<FieldOfStruct>.TableLineData line; 130 GralTableLine_ifc<InspcFieldOfStruct> line; 131 132 RunOnReceive(GralTableLine_ifc<InspcFieldOfStruct> line){ 133 this.line = line; 134 } 135 136 @Override public void run(){ 137 InspcFieldTable.this.showValue(line, false); 138 } 139 } 140 141 142 /**An instance of this class is used to prepare setValueByPath on a changed value in a line. 143 */ 144 public static class TxOrderSetValue implements Runnable 145 { 146 final String sValue; 147 final InspcVariable var; 148 149 public TxOrderSetValue(String sValue, InspcVariable var) 150 { this.sValue = sValue; 151 this.var = var; 152 } 153 154 /**This method will be invoked before finish of a send session. */ 155 @Override public void run() 156 { 157 var.ds.targetAccessor.cmdSetStringByPath(var, sValue); 158 } 159 160 161 } 162 163 164 /**Sizes in table in Graphic grid units.*/ 165 private static final int sizeStruct = 3, sizeName = 20, sizeType = 10; 166 167 /**The window to present. */ 168 private final GralWindow wind; 169 170 /**Shows the path in target to this struct. */ 171 private final GralTextField widgPath; 172 173 /**Table of fields, type and value. */ 174 private final GralTable<InspcFieldOfStruct> widgTable; 175 176 177 private final GralButton btnBack, btnHelp, btnRefresh, btnShowAll, btnSetValue, btnRepeat; 178 179 /**Aggregation. To get variable, send requests etc. */ 180 private final InspcMng inspcMng; 181 182 /**This index stores the last selected file for any component which was used. 183 * If the component path is reused later, the same field will be selected initially. 184 * It helps by navigation through the file tree. 185 * <ul> 186 * <li>The key is the path in canonical form with '/' as separator (in windows too!) 187 * but without terminating '/'. 188 * <li>The value is the name of the file in this directory. 189 * </ul> 190 */ 191 private final Map<String, String> indexSelection = new TreeMap<String, String>(); 192 193 194 195 //private InspcStruct struct; 196 private InspcVariable structVar; 197 198 /**Path in target to the struct which is shown in table. */ 199 private String sPathStruct; 200 201 202 /**Name and path to the current selected field. */ 203 private String sFieldCurrent, sPathCurrent; 204 205 private long timeLineSelected; 206 207 /**Set in graphic thread with {@link #btnSetValue}, ask and reset in the InspcMng-thread. */ 208 protected AtomicBoolean XXXbSetValue = new AtomicBoolean(); 209 210 public InspcFieldTable(InspcMng inspcMng) 211 { //inspcMng.addUserOrder(this); //invoke run in any communication step. 212 this.wind = new GralWindow(null, "InspcFieldTableWind", "Fields of ...", GralWindow_ifc.windOnTop | GralWindow_ifc.windResizeable); 213 this.widgPath = new GralTextField("InspcFieldTableWind"); 214 this.widgTable = new GralTable<InspcFieldOfStruct>("InspcFieldTable", new int[]{sizeStruct, sizeName, 0, -sizeType}); 215 this.widgTable.setColumnEditable(2, true); 216 this.widgTable.setActionChange(this.actionChgTable); 217 this.widgTable.specifyActionOnLineSelected(actionLineSelected); 218 this.widgTable.setHtmlHelp("HelpInspc.html#Topic.HelpInspc.fieldsof."); 219 this.btnBack = new GralButton("@InspcFieldBack", "<<", actionBack); 220 this.btnHelp = new GralButton("@InspcFieldHelp", "help [F1]", GralMng.get().actionHelp); 221 this.btnRefresh = new GralButton("@InspcFieldRefresh", "refresh [F5]", actionRefresh); 222 this.btnShowAll = new GralButton("@InspcFieldShowAll", "show all [c+]", actionShowAll); 223 this.btnSetValue = new GralButton("@InspcFieldSetValue", "set values", actionSetValues); 224 this.btnRepeat = new GralButton("@InspcFieldSetValue", "repeat", null); 225 this.btnRepeat.setSwitchMode(GralColor.getColor("gn"), GralColor.getColor("wh"), null); 226 this.inspcMng = inspcMng; 227 } 228 229 230 public void setToPanel(GralMng mng){ 231 wind.createImplWidget_Gthread(); 232 mng.setPosition(0, 2, 0, 3, 0, 'd'); 233 btnBack.createImplWidget_Gthread(); 234 mng.setPosition(0, 2, 3, 0, 0, 'd'); 235 widgPath.createImplWidget_Gthread(); 236 mng.setPosition(2, -4, 0, 0, 0, 'd'); 237 widgTable.createImplWidget_Gthread(); 238 mng.setPosition(-2, 0, 0, 9, 0, 'r'); 239 btnHelp.createImplWidget_Gthread(); 240 btnRefresh.createImplWidget_Gthread(); 241 mng.setPosition(-2, 0, sizeName, sizeName + 12, 1, 'r'); 242 btnSetValue.createImplWidget_Gthread(); 243 //mng.setPosition(-2, 0, sizeName+13, sizeName + 23, 0, 'r'); 244 btnRepeat.createImplWidget_Gthread(); 245 //mng.setPosition(-2, 0, sizeName + 13, sizeName + 23, 0, 'r'); 246 btnShowAll.createImplWidget_Gthread(); 247 } 248 249 250 251 void fillTableFromFocusedVariable(){ 252 GralWidget widgd = wind.gralMng().getWidgetInFocus(); 253 if(widgd !=null){ 254 String sDatapathWithPrefix = widgd.getDataPath(); 255 String sDatapath = widgd.gralMng().getReplacerAlias().replaceDataPathPrefix(sDatapathWithPrefix); 256 int posLastDot = sDatapath.lastIndexOf('.'); 257 if(posLastDot >=0) { 258 sPathStruct = sDatapath.substring(0, posLastDot); //With device:path 259 } else { 260 sPathStruct = ""; 261 } 262 VariableAccess_ifc vari = inspcMng.getVariable(sDatapath); 263 if(vari instanceof InspcVariable){ 264 InspcVariable vars = (InspcVariable) vari; 265 if(vars.getStruct() != null) { 266 this.structVar = vars; //It is a non-leafe-variable, use it to show the fields. 267 } else { 268 this.structVar = vars.parent; //for a leaf variable, normal case, if it is a non-leafe-variable, use its parent though. 269 } 270 //if(structVar == null) 271 //struct = var.struct(); 272 //- sPathStruct = struct.path(); //NOTE it is without device. 273 // 274 fillTableStruct(true); //checks whether the struct is updated, requests update. 275 // 276 } else { //NOTE: fillTableStruct sets the widgPath too. 277 widgPath.setText(sPathStruct); 278 } 279 } 280 widgTable.setFocus(); 281 wind.setVisible(true); 282 283 } 284 285 286 287 /**Fills the graphic table to show the structural content of a data node (a C struct or class). 288 * @since 2018-09: For array elements uses the {@link InspcFieldOfStruct#hasSubstruct} info from the parent (the field of the array). 289 * Note: It comes from the target: "type..." or "type[size]..." in the telegram. 290 * @param bCanRequest 291 */ 292 void fillTableStruct(boolean bCanRequest){ 293 widgTable.clearTable(); 294 InspcStruct struct = structVar.getOrCreateStructForNonLeafVariables(); 295 if(struct.isUpdated()){ 296 //search the root: 297 List<InspcVariable> parents = new LinkedList<InspcVariable>(); 298 InspcVariable parent = structVar; 299 while(parent !=null) { 300 parents.add(parent); 301 parent = parent.parent; 302 } 303 //fill parents 304 ListIterator<InspcVariable> iter = parents.listIterator(parents.size()); 305 306 while( iter.hasPrevious()) { //traverse through list from start. 307 parent = iter.previous(); 308 //InspcStruct struct1 = parent.struct(); 309 InspcFieldOfStruct fieldParent = new InspcFieldOfStruct(parent, null, 0, true); 310 GralTableLine_ifc<InspcFieldOfStruct> line = widgTable.addLine(parent.ds.sName, null, fieldParent); 311 line.setCellText("/", 0); 312 line.setCellText(parent.ds.sName, 1); 313 //line.setCellText() 314 line.setDataPath(parent.ds.sDataPath); 315 } 316 // 317 //fill with all fields 318 // 319 for(InspcFieldOfStruct field: struct.fieldIter()){ 320 GralTableLine_ifc<InspcFieldOfStruct> line = widgTable.addLine(field.nameShow, null, field); 321 if(field.hasSubstruct) { 322 line.setCellText("+", 0); 323 } else { 324 line.setCellText("", 0); 325 } 326 line.setCellText(field.nameShow, 1); 327 line.setCellText(field.type, 3); 328 line.setDataPath(sPathStruct + "." + field.nameShow); 329 } 330 // 331 //Select last line: 332 // 333 String key = indexSelection.get(sPathStruct); 334 if(key !=null){ 335 widgTable.setCurrentLine(key); 336 } 337 } else if(bCanRequest) { 338 GralTableLine_ifc<InspcFieldOfStruct> line = widgTable.addLine("$", null, null); 339 line.setCellText("pending request", 1); 340 InspcAccess_ifc target = structVar.ds.targetAccessor; 341 //=========> 342 struct.requestFields(); //clear the struct, set to request. 343 target.requestFields(struct.varOfStruct(inspcMng).ds, struct.rxActionGetFields, actionUpdated); 344 } else { //!bCanRequest - calling parameter: 345 GralTableLine_ifc<InspcFieldOfStruct> line = widgTable.addLine("?", null, null); 346 line.setCellText("...no answer", 1); 347 } 348 349 } 350 351 352 353 354 /**Shows the current value inside the target for the specified line. 355 * This routine is called both if the operator requests a refresh of content of the line: {@link #actionChgTable} 356 * or if a new value was received: {@link RunOnReceive#run()} invoked from {@link InspcVariable#requestValue(long, Runnable)}. 357 * The last one method requestValue() is invoked in this routine if the argument request is set to true. 358 * @param line The line of this table, contains the {@link InspcFieldOfStruct} as user data , {@link GralTableLine_ifc#getUserData()}. 359 * Therein the variable for this line is stored or will be created with {@link InspcMng#getOrCreateVariable(InspcStruct, InspcFieldOfStruct)}. 360 * @param request true then a new value for the variable of this line will be requested here. 361 */ 362 private void showValue(GralTableLine_ifc<InspcFieldOfStruct> line, boolean request){ 363 InspcFieldOfStruct field = line.getUserData(); 364 if(field !=null){ 365 InspcVariable var = field.variable(structVar, inspcMng); //get or create the variable for the field 366 if(var !=null){ 367 long time = System.currentTimeMillis(); 368 long timelast = var.getLastRefreshTime(); 369 char cType = var.getType(); 370 String sVal; 371 switch(cType){ 372 case 'F': { float val = var.getFloat(); sVal = Float.toString(val); } break; 373 case 'I': { int val = var.getInt(); sVal = "0x" + Integer.toHexString(val); } break; 374 case 'c': case 's': { sVal = var.getString(); } break; 375 default: { float val = var.getFloat(); sVal = Float.toString(val); } 376 } 377 int dtime = (int)(time - timelast); 378 if(timelast == 0 || dtime > 5000){ //5 sec 379 sVal = "? " + sVal; //a really old value or never gotten. 380 } 381 if(request && timelast == 0 || dtime > 500){ //request a new value if it is older than 0.5 sec 382 var.requestValue(time, this.new RunOnReceive(line)); 383 } 384 line.setCellText(sVal, 2); 385 } 386 } 387 388 } 389 390 391 void refresh(){ 392 InspcStruct struct = structVar.getOrCreateStructForNonLeafVariables(); 393 struct.requestFields(); 394 fillTableStruct(true); 395 } 396 397 398 void showAll(){ 399 fillTableStruct(true); 400 for(GralTableLine_ifc<InspcFieldOfStruct> line: widgTable.iterLines()){ 401 showValue(line, true); 402 } 403 } 404 405 406 407 public String getCurrentPathField(){ return sPathCurrent; } 408 409 410 411 public static String getDataPath(GralTable<InspcFieldOfStruct>.TableLineData line) 412 { String sPath = null; 413 String sField1 = line.getKey(); 414 //sPathCurrent = line.getDataPath(); 415 InspcFieldOfStruct field = line.data; 416 InspcVariable var = field.variableExisting(); 417 if(var !=null) { 418 sPath = var.ds.sPathWithAlias; 419 } 420 else 421 { //The varOfStruct is exisiting in any case. get it to get the short data path. 422 InspcVariable varStruct = field.struct.varOfStruct(null); 423 if(sField1.charAt(0) =='[') { //array element 424 sPath = varStruct.ds.sPathWithAlias + sField1; 425 } 426 else if(":.".indexOf(varStruct.ds.sPathWithAlias.charAt(varStruct.ds.sPathWithAlias.length()-1))<0) { 427 sPath = varStruct.ds.sPathWithAlias + "." + sField1; 428 } else { 429 sPath = varStruct.ds.sPathWithAlias + sField1; 430 } 431 } 432 return sPath; 433 } 434 435 436 437 438 void setCurrentFieldInfo(GralTable<InspcFieldOfStruct>.TableLineData line){ 439 sFieldCurrent = line.getKey(); 440 sPathCurrent = getDataPath(line); 441 timeLineSelected = System.currentTimeMillis(); 442 widgPath.setText(sPathCurrent + " : " + line.getCellText(3)); 443 444 } 445 446 447 void actionBack(){ 448 GralTable<InspcFieldOfStruct>.TableLineData line = widgTable.getCurrentLine(); 449 String key; 450 if(line !=null) { 451 key = line.getKey(); 452 indexSelection.put(sPathStruct, key); //select the current field if the view goes back to this table 453 } 454 InspcVariable parent = structVar.parent; 455 if(parent !=null){ 456 int posNameInPath = sPathStruct.lastIndexOf('.')+1; 457 key = sPathStruct.substring(posNameInPath); //it is the field name of this table in the parent. 458 this.structVar = parent; 459 this.sPathStruct = parent.ds.sDataPath; 460 indexSelection.put(sPathStruct, key); //select the field of the leaved table in its parent! 461 fillTableStruct(true); 462 } 463 } 464 465 466 void getSubStruct(GralTableLine_ifc<InspcFieldOfStruct> line){ 467 String key = line.getKey(); 468 indexSelection.put(sPathStruct, key); 469 470 InspcFieldOfStruct field = line.getUserData(); 471 if(field.nrofArrayElements >1){ 472 if(!line.hasChildren()){ 473 //no array elements yet initialized: 474 //InspcVariable varArray = field.variable(structVar, inspcMng); 475 InspcStruct structArray = field.struct; //varArray.struct(); 476 String[] lineTexts = new String[4]; 477 for(int ix = 0; ix < field.nrofArrayElements; ++ix) { 478 String ident = field.identifier + "[" + ix + "]"; //creates a field with index 479 //The field for the array element: 480 boolean bHasSubstruct = field.hasSubstruct; //The info about sub structure is stored in the array field already. 481 InspcFieldOfStruct fieldElement = new InspcFieldOfStruct(structArray, ident, ident, field.type, -1, bHasSubstruct); 482 lineTexts[0] = "-"; 483 lineTexts[1] = ident; 484 lineTexts[2] = ""; 485 lineTexts[3] = field.type; 486 line.addChildLine(ident, lineTexts, fieldElement); 487 } 488 } 489 line.showChildren(true, false, true); 490 } 491 else if(field.hasSubstruct){ 492 structVar = field.variable(structVar, inspcMng); 493 sPathStruct = structVar.ds.sDataPath; 494 fillTableStruct(true); 495 } 496 } 497 498 499 500 void actionSetValues(){ 501 for(GralTableLine_ifc<InspcFieldOfStruct> line: widgTable.iterLines()){ 502 if(line.isChanged(true)){ 503 sendValueChange(line); 504 } 505 } 506 } 507 508 /**This method is invoked if the value in the table is changed and this change should be applied to the target, key ctrl-enter. */ 509 void sendValueChange(GralTableLine_ifc<InspcFieldOfStruct> line) { 510 InspcFieldOfStruct field = line.getUserData(); //// 511 String sValue = line.getCellText(2); 512 InspcVariable var = field.variable(structVar, inspcMng); //creates the variable if not given yet. 513 TxOrderSetValue order = new TxOrderSetValue(sValue, var); 514 var.ds.targetAccessor.addUserTxOrder(order); 515 } 516 517 518 519 520 521 522 GralUserAction actionOpenWindow = new GralUserAction("InspcFieldTable - open window"){ 523 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 524 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 525 fillTableFromFocusedVariable(); 526 return true; 527 } else { 528 return false; 529 } 530 } 531 }; 532 533 534 535 /**This action is invoked on any keyboard hits which are not handled in the GralTable. 536 * 537 */ 538 GralUserAction actionChgTable = new GralUserAction("InspcFieldTable - change Table"){ 539 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 540 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 541 assert(params[0] instanceof GralTableLine_ifc<?>); 542 @SuppressWarnings("unchecked") 543 GralTableLine_ifc<InspcFieldOfStruct> line = (GralTableLine_ifc<InspcFieldOfStruct>)params[0]; 544 if(key == KeyCode.enter){ 545 showValue(line, true); 546 } else if(key == KeyCode.ctrl + KeyCode.enter) { 547 sendValueChange(line); //// 548 } else if(key == KeyCode.ctrl + 'R' || key == KeyCode.F5){ 549 refresh(); 550 } else if(key == KeyCode.ctrl + KeyCode.pgup) { 551 actionBack(); 552 } else if(key == KeyCode.ctrl + KeyCode.pgdn) { 553 getSubStruct(line); 554 } else if(key == KeyCode.ctrl + '+') { 555 showAll(); 556 } 557 return true; 558 } else if(key == KeyCode.mouse1Double){ 559 assert(params[0] instanceof GralTableLine_ifc<?>); 560 @SuppressWarnings("unchecked") 561 GralTableLine_ifc<InspcFieldOfStruct> line = (GralTableLine_ifc<InspcFieldOfStruct>)params[0]; 562 InspcFieldOfStruct field = line.getUserData(); 563 if(field.hasSubstruct){ 564 getSubStruct(line); 565 } else { 566 showValue(line, true); 567 } 568 return true; 569 } else { 570 return false; 571 } 572 } 573 }; 574 575 576 577 GralUserAction actionLineSelected = new GralUserAction("InspcFieldTable - line selected"){ 578 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 579 if(key == KeyCode.defaultSelect || key == KeyCode.userSelect){ 580 @SuppressWarnings("unchecked") 581 GralTable<InspcFieldOfStruct>.TableLineData line = (GralTable.TableLineData)params[0]; 582 if(line !=null && line.data !=null) { setCurrentFieldInfo(line); } 583 return true; 584 } else { 585 return false; 586 } 587 } 588 }; 589 590 591 592 593 GralUserAction actionBack = new GralUserAction("InspcFieldTable - back"){ 594 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 595 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 596 actionBack(); 597 return true; 598 } else { 599 return false; 600 } 601 } 602 }; 603 604 605 606 607 GralUserAction actionRefresh = new GralUserAction("InspcFieldTable - refresh"){ 608 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 609 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 610 refresh(); 611 return true; 612 } else { 613 return false; 614 } 615 } 616 }; 617 618 619 620 GralUserAction actionShowAll = new GralUserAction("InspcFieldTable - show all"){ 621 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 622 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 623 showAll(); 624 return true; 625 } else { 626 return false; 627 } 628 } 629 }; 630 631 632 633 GralUserAction actionSetValues = new GralUserAction("InspcFieldTable - set values"){ 634 @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){ 635 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 636 //bSetValue.set(true); 637 actionSetValues(); 638 //InspcFieldTable.this.inspcMng.addUserOrder(InspcFieldTable.this); 639 return true; 640 } else { 641 return false; 642 } 643 } 644 }; 645 646 647 648 Runnable actionUpdated = new Runnable(){ 649 @Override public void run(){ fillTableStruct(false); } //after receive the datagram, can not request newly. 650 }; 651 652 653 654}