001package org.vishia.guiInspc;
002
003import java.util.Locale;
004
005import org.vishia.gral.base.GralButton;
006import org.vishia.gral.base.GralMng;
007import org.vishia.gral.base.GralTable;
008import org.vishia.gral.base.GralTextField;
009import org.vishia.gral.base.GralWidget;
010import org.vishia.gral.base.GralWindow;
011import org.vishia.gral.ifc.GralColor;
012import org.vishia.gral.ifc.GralTableLine_ifc;
013import org.vishia.gral.ifc.GralUserAction;
014import org.vishia.gral.ifc.GralWidget_ifc;
015import org.vishia.gral.ifc.GralWindow_ifc;
016import org.vishia.inspcPC.InspcPlugUser_ifc;
017import org.vishia.inspcPC.accTarget.InspcTargetAccessor;
018import org.vishia.inspcPC.mng.InspcMng;
019import org.vishia.msgDispatch.LogMessage;
020import org.vishia.msgDispatch.LogMessageFile;
021import org.vishia.util.Debugutil;
022import org.vishia.util.KeyCode;
023import org.vishia.util.StringFunctions_C;
024
025/**This class contains some status and control widgets for the Inspector Gui to show the status of communication.
026 * The communication itself is organized in {@link org.vishia.inspcPC.accTarget.InspcTargetAccessor} in the software component javaSrc_vishiaRun.
027 * @author Hartmut Schorrig
028 *
029 */
030public class InspcViewTargetComm
031{
032  /**Version, history and license.
033   * <ul>
034   * <li>2018-10-19 chg: The Log on/off button is related to the target direct, not to the gui. Therefore handler implemented here.
035   * <li>2018-10-19 new {@link #windTargetSettings} for target settings, better handling of timeout, password-setting. 
036   *   Better handling of clearReq: Now it works with timeout=0 and manual clearRequest on stepbystep-debugging of the target.
037   * <li>2015-05-30 Created.
038   * </ul>
039   * 
040   * <b>Copyright/Copyleft</b>:
041   * For this source the LGPL Lesser General Public License,
042   * published by the Free Software Foundation is valid.
043   * It means:
044   * <ol>
045   * <li> You can use this source without any restriction for any desired purpose.
046   * <li> You can redistribute copies of this source to everybody.
047   * <li> Every user of this source, also the user of redistribute copies
048   *    with or without payment, must accept this license for further using.
049   * <li> But the LPGL is not appropriate for a whole software product,
050   *    if this source is only a part of them. It means, the user
051   *    must publish this part of source,
052   *    but don't need to publish the whole source of the own product.
053   * <li> You can study and modify (improve) this source
054   *    for own using or for redistribution, but you have to license the
055   *    modified sources likewise under this LGPL Lesser General Public License.
056   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
057   * </ol>
058   * If you are intent to use this sources without publishing its usage, you can get
059   * a second license subscribing a special contract with the author. 
060   * 
061   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
062   * 
063   */
064  //@SuppressWarnings("hiding")
065  protected final static String sVersion = "2018-10-19";
066
067  
068  /**The window to present. */
069  private final GralWindow windStateOfTarget;
070  
071  /**The window to input passwords. */
072  private final GralWindow windTargetSettings;
073  
074  /**Shows the path in target to this struct. */
075  //private final GralTextField widgPath;
076  
077  /**Table of fields, type and value. */
078  private final GralTable<InspcTargetAccessor> widgTable;
079
080
081  private final GralButton wdgBtnLog, wdgBtnRetry, wdgBtnClearReq, wdgBtnPerHandle, wdgBtnTargetSettings;
082  
083  
084  private final GralTextField wdgPwdAccess, wdgAccLevels; //, wdgPwdAccess1, wdgPwdChg1, wdgPwdAccess2, wdgPwdChg2, wdgPwdAccess3, wdgPwdChg3; 
085
086  private final GralTextField wdgTargetIdent, wdgTimeout, wdgTimeCycle;
087  
088  private final GralButton wdgBtnTargetSettingsOk; 
089  
090  private GralColor colorInactive = GralColor.getColor("wh")
091                  , colorIdle = GralColor.getColor("lgn")
092                  , colorWait = GralColor.getColor("lrd")
093                  , color2 = GralColor.getColor("or");
094
095  
096  String targetKeySettingwindow = "";
097  
098  LogMessage logTelg;
099
100
101  final InspcGui gui;
102  
103  
104  InspcTargetAccessor targetForSettingsWindow;
105  
106  public InspcViewTargetComm(InspcGui gui)
107  { //inspcMng.addUserOrder(this);  //invoke run in any communication step.
108    this.gui = gui;
109    this.windStateOfTarget = new GralWindow("@primaryWindow,-21..0,-50..0", "InspcCtrlStatusWind", "State of targets", GralWindow_ifc.windOnTop | GralWindow_ifc.windResizeable);
110    this.widgTable = new GralTable<InspcTargetAccessor>("@InspcCtrlStatusWind,0..-3,0..0=TargetTable", new int[]{3, 0,-6,-6});
111    this.widgTable.setColumnEditable(2,  true);
112    this.widgTable.setColumnEditable(3,  true);
113    //this.widgTable.setColumnEditable(2, true);
114    this.widgTable.setHtmlHelp("HelpInspc.html#Topic.HelpInspc.ctrlStatus.");
115    this.wdgBtnLog = new GralButton("@InspcCtrlStatusWind,-2..0,0..8=BtnLog", "Enable Log", null);
116    this.wdgBtnLog.setSwitchMode("? Log", "Log ?off");
117    this.wdgBtnLog.setSwitchMode(GralColor.getColor("wh"), GralColor.getColor("am"));
118    this.wdgBtnLog.specifyActionChange("switch log telg", actionEnableLog, null);
119    this.wdgBtnRetry = new GralButton("@InspcCtrlStatusWind,-2..0,9..17=BtnRetry", "Retry", null);
120    this.wdgBtnRetry.setSwitchMode("? Retry", "Retry ?off");
121    this.wdgBtnRetry.setSwitchMode(GralColor.getColor("wh"), GralColor.getColor("am"));
122    this.wdgBtnRetry.specifyActionChange("retry variables", gui.actionSetRetryDisabledVariable, null);
123    this.wdgBtnClearReq = new GralButton("@InspcCtrlStatusWind,-2..0,18..27=BtnClearReq", "ClearReq", null);
124    this.wdgBtnClearReq.specifyActionChange("retry variables", actionClearReq, null);
125    this.wdgBtnPerHandle = new GralButton("@InspcCtrlStatusWind,-2..0,28..37=BtnLog", "Enable Log", null);
126    this.wdgBtnPerHandle.setSwitchMode("? use Handle", "use Handle ?off");
127    this.wdgBtnPerHandle.setSwitchMode(GralColor.getColor("wh"), GralColor.getColor("gn"));
128    this.wdgBtnPerHandle.specifyActionChange("use handle", gui.actionUseGetValueByHandle, null);
129    this.wdgBtnTargetSettings = new GralButton("@InspcCtrlStatusWind,-2..0,38..47=BtnTargetSettings", "@Settings", null);
130    this.wdgBtnTargetSettings.specifyActionChange("openPwd", actionOpenWindowTargetSettings, null);
131  
132    this.windTargetSettings = new  GralWindow("@primaryWindow,-36..-18,-30..0", "InspcTargetPwdWind", "Passwords for Target", GralWindow_ifc.windOnTop);
133    
134    this.wdgTargetIdent = new GralTextField("@InspcTargetPwdWind, 2-2,1+20=targetident");
135    this.wdgTimeCycle = new GralTextField("@InspcTargetPwdWind, 6-4,1+10=timeCycle", GralTextField.Type.editable);
136    this.wdgTimeout =    new GralTextField("@InspcTargetPwdWind, 6-4,12+10=timeout",   GralTextField.Type.editable);
137    this.wdgTimeCycle.setPrompt("cycle [s]", "t");
138    this.wdgTimeout.setPrompt("timeout [s] 0-debug", "t");
139    
140    this.wdgPwdAccess = new GralTextField("@InspcTargetPwdWind, 10-4,1+10=PwdAccess0", GralTextField.Type.editable);
141    this.wdgAccLevels =    new GralTextField("@InspcTargetPwdWind, 10-4,12+10=PwdChg0");
142    this.wdgPwdAccess.setPrompt("pwd", "t");
143    this.wdgAccLevels.setPrompt("access levels", "t");
144    //    this.wdgPwdAccess1 = new GralTextField("@InspcTargetPwdWind, 6-2,5+10=PwdAccess1", GralTextField.Type.editable);
145//    this.wdgPwdChg1 =    new GralTextField("@InspcTargetPwdWind, 6-2,17+10=PwdChg1",   GralTextField.Type.editable);
146//    this.wdgPwdAccess2 = new GralTextField("@InspcTargetPwdWind, 8-2,5+10=PwdAccess2", GralTextField.Type.editable);
147//    this.wdgPwdChg2 =    new GralTextField("@InspcTargetPwdWind, 8-2,17+10=PwdChg2",   GralTextField.Type.editable);
148//    this.wdgPwdAccess3 = new GralTextField("@InspcTargetPwdWind, 10-2,5+10=PwdAccess3", GralTextField.Type.editable);
149//    this.wdgPwdChg3 =    new GralTextField("@InspcTargetPwdWind, 10-2,17+10=PwdChg3",   GralTextField.Type.editable);
150    this.wdgBtnTargetSettingsOk = new GralButton("@InspcTargetPwdWind, 14-3,16+6=BtnSettingsOk", "ok", null);
151    this.wdgBtnTargetSettingsOk.specifyActionChange("openPwd", actionSetTargetSettings, null);
152  
153  
154  }
155  
156  
157  /**Invoked in the graphic thread.
158   */
159  public void setToPanel(){
160    GralMng mng = GralMng.get();
161    windStateOfTarget.setToPanel(mng);
162    windTargetSettings.createImplWidget_Gthread();
163    //mng.setPosition(0, 2, 0, 3, 0, 'd');
164    //mng.setPosition(0, 2, 3, 0, 0, 'd');
165    //mng.setPosition(2, -4, 0, 0, 0, 'd');
166    widgTable.setToPanel(mng);
167    //mng.setPosition(-2, 0, 0, 7, 0, 'd');
168  }
169  
170
171  GralUserAction setVisible = new GralUserAction("")
172  { public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params) {
173      windStateOfTarget.setFocus(); //Visible(true);   
174      return true;
175    }
176  };
177  
178  
179  public void addTarget(String key, String info, float cycle, float timeout){
180//    GralTableLine_ifc<InspcTargetAccessor> line = widgTable.addLine(key, null, null);
181//    line.setCellText(key + "@" + info, 1);
182//    line.setCellText(String.format(Locale.US, "%1.1f", cycle), 2);  //use a 0.2 and not 0,2 in a german installation
183//    line.setCellText(String.format(Locale.US, "%3.1f", timeout), 3);
184  }
185
186  
187  
188  void registerTarget(String name, String sAddr, InspcTargetAccessor targetAcc) {
189    GralTableLine_ifc<InspcTargetAccessor> line = widgTable.addLine(name, null, targetAcc);
190    line.setCellText(name + "@" + sAddr, 1);
191    line.setCellText(String.format(Locale.US, "%1.1f", targetAcc.cycle_timeout[0]), 2);  //use a 0.2 and not 0,2 in a german installation
192    line.setCellText(String.format(Locale.US, "%3.1f", targetAcc.cycle_timeout[1]), 3);
193  }
194  
195  
196  public void setStateInfo(String key, InspcPlugUser_ifc.TargetState state, int count, int accLevels, float[] cycle_timeout){
197    GralColor color;
198    switch(state) {
199      case idle: color = colorIdle; break;
200      case inactive: color = colorInactive; break;
201      case waitReceive: color = colorWait; break;
202      case receive: color = color2; break;
203      default: color = color2;
204    }
205    if(key.equals(targetKeySettingwindow)) {
206      wdgAccLevels.setText(Integer.toHexString(accLevels & 0xffff));
207      if((accLevels & 0x10000) !=0) {
208        wdgPwdAccess.setBackColor(GralColor.getColor("lrd"), 0);
209      } else {
210        wdgPwdAccess.setBackColor(GralColor.getColor("wh"), 0);
211      }
212    }
213    GralTableLine_ifc<InspcTargetAccessor> line = widgTable.getLine(key);
214    if(line !=null) {
215      line.setCellText(Integer.toHexString(count & 0xff), 0);
216      line.setBackColor(color, 0);
217      line.setCellText(Float.toString(cycle_timeout[0]), 2);
218      line.setCellText(Float.toString(cycle_timeout[1]), 3);
219//      if(cycle_timeout !=null) { 
220//        String sLine = line.getCellText(3);
221//        float timeout = StringFunctions_C.parseFloat(sLine, 0, -1, null);
222//        if(timeout > 0){
223//          //cycle_timeout[1] = timeout;
224//        }
225//      }
226    } else {
227      System.err.println("InspcViewTargetComm - unknown target, "+ key);
228    }
229  }
230  
231  
232  public boolean isLogOn() { return wdgBtnLog.getState()== GralButton.State.On; }
233  
234  float getTimeout(String target){
235    float timeout; 
236    GralTableLine_ifc<InspcTargetAccessor> line = widgTable.getLine(target);
237     if(line !=null) {
238       String sLine = line.getCellText(3);
239       timeout = StringFunctions_C.parseFloat(sLine, 0, -1, null);
240       if(timeout <= 0){
241         timeout = 1.0f;
242       }
243     } else {
244       System.err.println("InspcViewTargetComm - unknown target, "+ target);
245       timeout = 5.0f;
246     }
247     return timeout;
248   }
249  
250  /**Action for button log. It switches on or off the logging functionality to log the telegram traffic
251   * for debugging. */
252  GralUserAction actionOpenWindowTargetSettings = new GralUserAction("InspcGui - OpenPwd"){
253    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params) { 
254      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
255        InspcViewTargetComm.this.targetForSettingsWindow = widgTable.getCurrentLine().data;
256        InspcViewTargetComm.this.targetKeySettingwindow = InspcViewTargetComm.this.targetForSettingsWindow.name;
257        windTargetSettings.setVisible(true);
258        wdgTargetIdent.setText(InspcViewTargetComm.this.targetKeySettingwindow);
259        wdgTimeCycle.setText("" + targetForSettingsWindow.cycle_timeout[0]);
260        wdgTimeout.setText("" + targetForSettingsWindow.cycle_timeout[1]);
261        wdgPwdAccess.setText("");
262      }
263      return true;
264    }
265  };
266  
267
268
269  /**Action for button log. It switches on or off the logging functionality to log the telegram traffic
270   * for debugging. */
271  GralUserAction actionSetTargetSettings = new GralUserAction("InspcGui - OpenPwd"){
272    @Override public boolean exec(int actionCode, GralWidget_ifc widgi, Object... params) { 
273      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
274        String pwdAccess = wdgPwdAccess.getText().trim();
275        String pwdChange = wdgAccLevels.getText().trim();
276        String sTimeCycle = wdgTimeCycle.getText();
277        float timeCycle = StringFunctions_C.parseFloat(sTimeCycle, 0, -1, null);
278        String sTimeout = wdgTimeout.getText();
279        float timeout = StringFunctions_C.parseFloat(sTimeout, 0, -1, null);
280        
281        targetForSettingsWindow.setPwdCycle(pwdAccess, timeCycle, timeout);
282      }
283      return true;
284    }
285  };
286  
287
288  /**Action for button log. It switches on or off the logging functionality to log the telegram traffic
289   * for debugging. */
290  GralUserAction actionClearReq = new GralUserAction("InspcGui - clearReq"){
291    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params) { 
292      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
293        gui.inspcMng.clearRequestedVariables();
294        InspcTargetAccessor target = widgTable.getCurrentLine().getUserData();
295        target.setReady();
296        
297      }
298      return true;
299    }
300  };
301  
302
303  
304  
305  /**Action for button log. It switches on or off the logging functionality to log the telegram traffic
306   * for debugging. */
307  GralUserAction actionEnableLog = new GralUserAction("InspcGui - enableLog"){
308    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params) { 
309      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
310        InspcTargetAccessor target = widgTable.getCurrentLine().getUserData();
311        GralButton widgButton = (GralButton)widgd;
312        if(widgButton.isOn()){
313          if(logTelg == null){
314            logTelg = new LogMessageFile("telgLog.csv", 10, 1, null, null, null);
315          }
316          target.setLog(logTelg, 1000);
317
318        } else {
319          if(logTelg !=null){
320            logTelg.close();
321            logTelg = null;
322          }
323          target.setLog(null, 1000);
324        }
325      }
326      return true;
327    }
328  };
329  
330
331
332
333}