001package org.vishia.guiInspc;
002
003import java.io.File;
004import java.io.FileWriter;
005import java.io.Writer;
006import java.util.List;
007import java.util.Map;
008
009import org.vishia.byteData.VariableContainer_ifc;
010import org.vishia.curves.WriteCurveCsv;
011import org.vishia.curves.WriteCurve_ifc;
012import org.vishia.fileRemote.FileRemote;
013import org.vishia.gral.base.GralButton;
014import org.vishia.gral.base.GralCurveView;
015import org.vishia.gral.base.GralMenu;
016import org.vishia.gral.base.GralPos;
017import org.vishia.gral.base.GralTable;
018import org.vishia.gral.base.GralTable.TableLineData;
019import org.vishia.gral.base.GralTextField;
020import org.vishia.gral.base.GralWidget;
021import org.vishia.gral.base.GralMng;
022import org.vishia.gral.base.GralWindow;
023import org.vishia.gral.ifc.GralColor;
024import org.vishia.gral.ifc.GralCurveViewTrack_ifc;
025import org.vishia.gral.ifc.GralCurveView_ifc;
026import org.vishia.gral.ifc.GralPrimaryWindow_ifc;
027import org.vishia.gral.ifc.GralTableLine_ifc;
028import org.vishia.gral.ifc.GralUserAction;
029import org.vishia.gral.ifc.GralWidget_ifc;
030import org.vishia.gral.ifc.GralWindow_ifc;
031import org.vishia.gral.widget.GralColorSelector;
032import org.vishia.gral.widget.GralFileSelectWindow;
033import org.vishia.gral.widget.GralColorSelector.SetColorFor;
034import org.vishia.gral.widget.GralFileSelector;
035import org.vishia.inspcPC.mng.InspcFieldOfStruct;
036import org.vishia.util.Assert;
037import org.vishia.util.Debugutil;
038import org.vishia.util.FileSystem;
039import org.vishia.util.KeyCode;
040import org.vishia.util.StringFormatter;
041
042/**A curve view window inside the inspector.
043 * @author hartmut Schorrig
044 *
045 */
046public final class InspcCurveView
047{
048
049  /**Version, history and license. 
050   * <ul>
051   * <li>2018-01-08 Hartmut refactoring 
052   *   <ul>
053   *   <li>private class TrackValues removed, it hasn't any specific content, replaced by {@link GralCurveViewTrack_ifc}
054   *   which refers a {@link GralCurveView.Track}.
055   *   <li> new {@link #fillTableTracks()}, content from {@link #actionReadCfg(int, GralWidget_ifc, Object...)} 
056   *     but also invoked in {@link #actionReadValues(int, GralWidget_ifc, Object...)}. That may add tracks. 
057   *   </ul> 
058   * <li>2018-01-08 Hartmut new: If a datapath was written in a cell of variable paths which is not part of table, especially on an clean or small table,
059   *   than the routine {@link GralTable#getCellTextFocus()} is called to get the datapath as text. This is a new line, it is added.
060   *   Therewith now it is easy to add lines to an empty table via path in clibboard.
061   * <li>2016-05-03 Hartmut chg: Selection of file in this window instead an own dialog window: 
062   *   Advantage: This window is always on top. A opened dialog window may be in background - fatal.
063   *   It is well to use. 
064   * <li>2015-07-12 Hartmut new: switch on and off for curves. 
065   * <li>2015-07-12 Hartmut new: Better usability for scaling. [+] and [-] - Buttons works correctly. 
066   *   Enter in field for scaling values has an effect immediately. 
067   *   Support for more as one track with the same scaling.  
068   * <li>2013-05-19 Hartmut new: {@link #actionTrackSelected} with ctrl and left mouse pressed
069   * <li>2013-05-15 Hartmut new: Presentation of value on cursor
070   * <li>2013-05-14 Hartmut chg: 12 Tracks instead 10. A variableWindowSize cause problems (TODO)
071   * <li>2013-05-14 Hartmut progress: {@link #actionSwapVariable}, {@link #actionShiftVariable}
072   * <li>2013-05-13 Hartmut new: {@link #actionSwapVariable}, {@link #actionSelectOrChgVarPath}
073   * <li>2013-03-28 Hartmut adapt new {@link GralFileSelectWindow}
074   * <li>2013-03-27 Hartmut improved/bugfix: The {@link TrackValues#trackView} is the reference to the track in the 
075   *   {@link GralCurveView} instance. If a new config is loaded all tracks in {@link GralCurveView#getTrackInfo()}
076   *   are created newly using {@link GralCurveView#addTrack(String, String, GralColor, int, int, float, float)}.
077   *   Therefore the {@link TrackValues#trackView} should be updated. 
078   * <li>2012-10-09 Hartmut now ctrl-mouse down sets the scale settings for the selected channel. Faster user operation.
079   * <li>2012-08-10 Hartmut now uses a default directory for config file given in constructor.
080   * <li>2012-07-06 Hartmut now read and save of the file works.
081   * <li>2012-06-29 Hartmut new open file dialog
082   * <li>2012-06-08 Hartmut: new Buttons for read and save the configuration (setting). Yet only a simple file is used.
083   *   TODO: File selection.
084   * <li>2012-03-17 Hartmut creating using the {@link GralCurveView} in a special window
085   *   with the communication in {@link InspcMng}.
086   * </ul>
087   * <br><br> 
088   * 
089   * <b>Copyright/Copyleft</b>:
090   * For this source the LGPL Lesser General Public License,
091   * published by the Free Software Foundation is valid.
092   * It means:
093   * <ol>
094   * <li> You can use this source without any restriction for any desired purpose.
095   * <li> You can redistribute copies of this source to everybody.
096   * <li> Every user of this source, also the user of redistribute copies
097   *    with or without payment, must accept this license for further using.
098   * <li> But the LPGL is not appropriate for a whole software product,
099   *    if this source is only a part of them. It means, the user
100   *    must publish this part of source,
101   *    but don't need to publish the whole source of the own product.
102   * <li> You can study and modify (improve) this source
103   *    for own using or for redistribution, but you have to license the
104   *    modified sources likewise under this LGPL Lesser General Public License.
105   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
106   * </ol>
107   * If you are intent to use this sources without publishing its usage, you can get
108   * a second license subscribing a special contract with the author. 
109   * 
110   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
111   */
112  //@SuppressWarnings("hiding")
113  public final static String sVersion = "2014-01-10";
114
115  //boolean bTabWidget = true;
116
117  public static String sBtnReadCfg = "read cfg";
118  
119  public static String sBtnSaveCfg = "save cfg";
120  
121  public static String sBtnReadValues = "read data";
122  
123  public static String sBtnSaveValues = "save data";
124  
125  
126  protected final String sName;
127  
128  private final Map<String, String> curveExporterClasses;
129  
130  private final WriteCurve_ifc writerCurveCsv = new WriteCurveCsv();
131  
132  /**The window for curve view. */
133  GralWindow windCurve;
134  
135  /**Used for read/write config and for read/write data*/
136  private final GralFileSelector widgFileSelector;
137  
138  private String sWhatTodoWithFile;
139  
140  /**Shows the name and input name for read/write config and data. */
141  private final GralTextField widgFilename;
142
143  
144  
145  final GralMng gralMng;
146  
147  final VariableContainer_ifc variables;
148  
149  private final static String[] colorCurveDefault = new String[]{"rd", "gn", "lbl", "or", "ma", "bn", "dgn", "drd", "cy", "bl", "gn2", "pu"};
150  
151  
152  /**The input field which is the current scaling field. */
153  GralCurveViewTrack_ifc trackScale;
154  int ixTrackScale;
155  
156  //GralColor colorLineTrackSelected;
157
158  final GralColor colorBlack = GralColor.getColor("bk");
159  
160  GralColor colorTrackSameScale = GralColor.getColor("pgn");
161
162  GralColor colorTrackSameScaleSelected = GralColor.getColor("lgn");
163  
164  GralColor colorTrackOtherScaleSelected = GralColor.getColor("lam");
165  
166  GralColor colorTrackOtherScale = GralColor.getColor("wh");
167  
168  GralColor colorTrackNotShown = GralColor.getColor("lgr");
169
170  GralColor colorTrackNotShownSelected = GralColor.getColor("gr");
171  
172  GralColor colorBtnFileActive = GralColor.getColor("am");
173
174  GralColor colorBtnFileInactive = GralColor.getColor("wh");
175  
176  GralTable<GralCurveViewTrack_ifc> widgTableVariables;
177  
178  GralTextField widgScale, widgScale0, widgline0;
179  
180  /**The one of {@link #widgScale0}, {@link #widgScale0} or {@link #widgline0} which was focused lastly.
181   * To use for [+] and [-] button.
182   */
183  GralTextField scalingWidg;
184  
185  GralTextField widgValCursorLeft, widgValCursorRight; ///
186  
187  GralButton widgBtnUp, widgBtnDn, widgBtnScale, widgBtnReadCfg, widgBtnSaveCfg;
188  
189  GralButton widgBtnReadValues, widgBtnSaveValues, wdgButtonAutosave, widgBtnColor; 
190  
191  
192  GralButton widgBtnOff;
193  
194  /**The currently loaded file for curve settings. */
195  FileRemote fileCurveCfg;
196  
197  FileRemote dirCurveSave;
198  
199  //long timeLastSave;
200  
201  //long timePeriodSave = 1000L * 60 * 2;
202  
203  //boolean hasDataTosave;
204  
205  /**Temporary used formatter. */
206  StringFormatter sFormatter = new StringFormatter(50);
207  
208  /**Common ColorSelector for all curve views. */
209  GralColorSelector colorSelector;
210  
211  
212  
213  //final InspcGuiComm comm;
214  
215  GralCurveView widgCurve;
216  
217  /**Creates the instance. The graphical appearance will not be created. 
218   * Call {@link #buildGraphic(GralPrimaryWindow_ifc, GralColorSelector)} to do that.
219   * @param sName Name shown in title bar
220   * @param variables Container to find variables
221   * @param gralMng The Gral Graphic Manager
222   * @param defaultDir
223   * @param curveExporterClasses Class which is used to export curves.
224   */
225  InspcCurveView(String sName, VariableContainer_ifc variables, GralMng gralMng, FileRemote defaultDirCfg, FileRemote defaultDirSave, Map<String, String> curveExporterClasses){
226    //this.comm = comm;
227    this.sName = sName;
228    this.curveExporterClasses = curveExporterClasses;
229    this.variables = variables;
230    this.gralMng = gralMng;
231    fileCurveCfg = defaultDirCfg;
232    dirCurveSave = defaultDirSave;
233    widgFileSelector = new GralFileSelector("-selectFile", 100, new int[]{2,0,-6,-12}, null);
234    widgFileSelector.specifyActionOnFileSelected(actionSelectFile);
235    widgFileSelector.setActionOnEnterFile(actionEnterFile);
236
237    widgFilename = new GralTextField("-filename", GralTextField.Type.editable);
238     
239  }
240  
241  
242  /**Builds the graphic, it should be called only one time on startup in the graphic thread
243   * @param wind The main window where the menu to open will be added
244   * @param sName The name, used for menu entry too, sample "curve A"
245   */
246  public void buildGraphic(GralWindow_ifc wind, GralColorSelector colorSelector, GralCurveView.CommonCurve common)
247  {
248    this.colorSelector = colorSelector;
249    gralMng.selectPanel("primaryWindow");
250    //gralMng.setPosition(4, 0, 4, 0, 0, '.');
251    gralMng.setPosition(4, 56, 4, 104, 0, '.');
252    //int windProps = GralWindow.windConcurrently | GralWindow.windOnTop | GralWindow.windResizeable;
253    int windProps = GralWindow.windConcurrently | GralWindow.windOnTop; // | GralWindow.windResizeable;
254    windCurve = gralMng.createWindow("windMapVariables", sName, windProps);
255    //gralMng.setPosition(2, GralGridPos.size-1.6f, 0, 3.8f, 0, 'd');
256    buildGraphicInCurveWindow(common);
257    GralMenu menu = wind.getMenuBar();
258    menu.addMenuItem("&Window/open " + sName, actionOpenWindow);
259  }
260
261  
262  
263  void buildGraphicInCurveWindow(GralCurveView.CommonCurve common)
264  {
265    int posright = -20;
266    gralMng.setPosition(0, -4, 0, posright, 0, 'd');
267    widgFileSelector.createImplWidget_Gthread();
268    widgFileSelector.setVisible(false);
269    //widgFileSelector.set
270    //widgFileSelector.specifyActionOnFileSelected(actionSelectFile);
271    //widgFileSelector.setActionOnEnterFile(actionOk);
272    gralMng.setPosition(-4, -2, 0, posright, 0, 'd');
273    widgFilename.createImplWidget_Gthread();
274    widgFilename.setVisible(false);
275    widgFilename.setText("TEST xyz");
276    gralMng.setPosition(0, -2, 0, posright, 0, 'd');
277    widgCurve = gralMng.addCurveViewY(sName, 15000, common);
278    widgCurve.setActionMoveCursor(actionShowCursorValues);
279    widgCurve.setActionTrackSelected(actionTrackSelectedFromGralCurveViewCtrlMousePressed);
280    gralMng.setPosition(0, GralPos.size +2, posright, 0, 0, 'd', 0);
281    gralMng.addText("curve variable");
282    widgTableVariables = new GralTable<GralCurveViewTrack_ifc>("variables", new int[]{-posright});
283    gralMng.setPosition(2, GralPos.size +20, posright, 0, 0, 'd', 0);
284    widgTableVariables.setColumnEditable(0, true);
285    widgTableVariables.setToPanel(gralMng);
286    widgTableVariables.specifyActionOnLineSelected(actionSelectVariableInTable);
287    widgTableVariables.setActionChange(actionKeyHandlingTable);
288    //widgTableVariables.set
289    widgTableVariables.addContextMenuEntryGthread(0, null, "switch on-off <F2>", actionOnOffTrack);
290    widgTableVariables.addContextMenuEntryGthread(0, null, "insert variable", actionInsertVariable);
291    widgTableVariables.addContextMenuEntryGthread(0, null, "replace variable", actionReplaceVariable);
292    widgTableVariables.addContextMenuEntryGthread(0, null, "swap variable", actionSwapVariable);
293    widgTableVariables.addContextMenuEntryGthread(0, null, "delete variable", actionDeleteVariable);
294    widgTableVariables.addContextMenuEntryGthread(0, null, "shift variable", actionShiftVariable);
295    widgTableVariables.addContextMenuEntryGthread(0, null, "set color", actionColorSelectorOpen);
296    widgTableVariables.addContextMenuEntryGthread(0, null, "group scale", actionShareScale);
297    widgTableVariables.addContextMenuEntryGthread(0, null, "ungroup scale", actionUnshareScale);
298    gralMng.setPosition(/*22*/-19, GralPos.size +3, -8, 0, 0, 'd', 0);
299    widgScale = gralMng.addTextField("scale", true, "scale/div", "t");
300    widgScale.setActionFocused(actionFocusScaling);         //store which field, set color
301    widgScale.setActionChange(actionSetScaleValues2Track);  //on enter
302    scalingWidg = widgScale;  //set which is focused
303    widgScale0 = gralMng.addTextField("scale0", true, "mid", "t");
304    widgScale0.setActionFocused(actionFocusScaling);        //store which field, set color
305    widgScale0.setActionChange(actionSetScaleValues2Track);  //on enter
306    widgline0 = gralMng.addTextField("line0", true, "line-%", "t");
307    widgline0.setActionFocused(actionFocusScaling);         //store which field, set color
308    widgline0.setActionChange(actionSetScaleValues2Track);  //on enter
309    gralMng.setPosition(/*32*/-9, GralPos.size +2, -10, GralPos.size +2, 0, 'r', 1);
310    /*
311    gralMng.setPosition(-23, GralPos.size +1, -10, 0, 0, 'd', 2);
312    gralMng.addText("scale/div");
313    gralMng.addText("mid");
314    gralMng.addText("line-%");
315    gralMng.setPosition(-22, GralPos.size +2, -10, 0, 0, 'd', 1);
316    widgScale = gralMng.addTextField("scale", true, null, "t");
317    widgScale0 = gralMng.addTextField("scale0", true, null, "t");
318    widgline0 = gralMng.addTextField("line0", true, null, "t");
319    gralMng.setPosition(-12, GralPos.size +2, -10, GralPos.size +2, 0, 'r', 1);
320    */
321    widgBtnDn = gralMng.addButton("btnDn", actionSetScaleValues2Track, "-", null,  "-");
322    widgBtnUp = gralMng.addButton("btnUp", actionSetScaleValues2Track, "+", null, "+");
323    gralMng.setPosition(GralPos.same, GralPos.size +2, GralPos.next, GralPos.size +4, 0, 'r', 1);
324    gralMng.addButton("btnScale", actionColorSelectorOpen, "!", null,  "color");  
325    gralMng.setPosition(/*35*/ -6, GralPos.size +2, -10, GralPos.size +6, 0, 'r', 1);
326    widgBtnScale = gralMng.addButton("btnScale", actionSetScaleValues2Track, "!", null,  "set");
327    gralMng.setPosition(-22, GralPos.size +3, posright, GralPos.size +11, 0, 'd', 0);
328    widgValCursorLeft = gralMng.addTextField(null, true, "cursor left", "t");
329    widgValCursorRight = gralMng.addTextField(null, true, "cursor right", "t");
330    gralMng.setPosition(-15, GralPos.size +2, posright, GralPos.size +8, 0, 'd', 1);
331    widgBtnReadCfg = gralMng.addButton("btnReadCfg", actionOpenFileDialog, sBtnReadCfg, null, sBtnReadCfg);
332    widgBtnSaveCfg = gralMng.addButton("btnSaveCfg", actionOpenFileDialog, sBtnSaveCfg, null, sBtnSaveCfg);
333    widgBtnReadValues = gralMng.addButton("btnReadValues", actionOpenFileDialog, sBtnReadValues, null, sBtnReadValues);
334    widgBtnSaveValues = gralMng.addButton("btnSaveValues", actionOpenFileDialog, sBtnSaveValues, null, sBtnSaveValues);
335    wdgButtonAutosave = gralMng.addSwitchButton("btnAutoSaveValues", "off-autosave", "on-autosave", GralColor.getColor("lgn"), GralColor.getColor("am") );
336    
337    gralMng.setPosition(-3, GralPos.size +2, -9, -1, 0, 'd', 0);
338    widgBtnOff = gralMng.addSwitchButton(sName + "btnOff", "off / ?on", "on / ?off", GralColor.getColor("lgn"), GralColor.getColor("am"));
339  
340    
341  }
342  
343  
344  
345  
346  void fillTableTracks() {
347    Iterable<? extends GralCurveViewTrack_ifc> listTracks = widgCurve.getTrackInfo();
348    widgTableVariables.clearTable();
349    int iTrack = 0;
350    for(GralCurveViewTrack_ifc track: listTracks){
351      String sDataPath = track.getDataPath();
352      String[] sCellTexts = new String[1];
353      sCellTexts[0] = sDataPath;
354      GralTableLine_ifc<GralCurveViewTrack_ifc> line = widgTableVariables.addLine(sDataPath, sCellTexts, track);
355      line.setTextColor(track.getLineColor());
356      iTrack +=1;
357    }
358    widgTableVariables.setVisible(true);
359    widgTableVariables.repaint(500,500);
360
361  }
362  
363  
364  
365  void refreshCurve(){
366    if(widgCurve !=null && widgBtnOff !=null){
367      GralButton.State state = widgBtnOff.getState();
368      boolean bActive = state == GralButton.State.On;
369      widgCurve.activate( bActive);
370      if(bActive){
371        //hasDataTosave = true;
372        widgCurve.refreshFromVariable(variables);
373      }
374    }
375    actionShowCursorValues.exec(0, widgCurve);
376  }
377  
378  
379  
380  protected boolean dropVariable(int actionCode, GralWidget widgd, boolean bInsert){
381    if(actionCode == KeyCode.menuEntered){
382      GralWidget_ifc variableWidget = gralMng.getLastClickedWidget();
383      if(variableWidget == null) {
384        System.err.println("No variable clicked");
385        return false;
386      }
387      String sPath;
388      if(variableWidget instanceof TableLineData) {
389        Object data = variableWidget.getData();
390        if(data instanceof InspcFieldOfStruct) {
391          @SuppressWarnings("unchecked")
392          GralTable<InspcFieldOfStruct>.TableLineData line = (GralTable<InspcFieldOfStruct>.TableLineData)variableWidget;
393          sPath = InspcFieldTable.getDataPath(line); //((InspcFieldOfStruct)data).
394        } else {
395          sPath = null;
396        }
397      }
398      else {
399        sPath = variableWidget.getDataPath();
400      }
401      if(sPath !=null) {
402        GralCurveViewTrack_ifc input;
403        assert(widgd instanceof GralTable<?>);  //NOTE: context menu to table lines, has GralTable as widget.
404        @SuppressWarnings("unchecked")
405        GralTable<GralCurveViewTrack_ifc> table = (GralTable<GralCurveViewTrack_ifc>)widgd; //oContentInfo;
406        GralTable<GralCurveViewTrack_ifc>.TableLineData refline = table.getLineMousePressed();
407        int ixnewline =-1;
408        GralTableLine_ifc<GralCurveViewTrack_ifc> newline = null;
409        if(bInsert || refline == null){  //insert a line, build a new one
410          GralColor colorCurve = GralColor.getColor("rd");
411          input = widgCurve.addTrack(sName, sPath, colorCurve, 0, 50, 5000.0f, 0.0f);
412          if(refline ==null){
413            newline = table.addLine(sPath, new String[]{""}, input);  //add on end
414            ixnewline = table.size();  //first line
415          } else {
416            newline = refline.addPrevLine(sPath, new String[]{""}, input);
417            ixnewline = table.getIxLine(refline);
418          }
419          newline.setCellText(sPath, 0);
420        } 
421        else {
422          input = (GralCurveViewTrack_ifc)refline.getContentInfo();
423          input.setDataPath(sPath);
424          refline.setCellText(sPath, 0);
425        }
426        if(newline !=null && ixnewline >=0) {
427          table.setCurrentLine(newline, ixnewline, 0);
428        }
429        table.repaint();
430      } else {
431        System.out.printf("InspcCurveView - invalid widget to drop; %s\n", variableWidget.toString());
432      }
433    }
434    return true;
435    
436  }
437  
438  
439  
440  protected boolean deleteVariable(int actionCode, GralWidget widgd, boolean bInsert){
441    if(actionCode == KeyCode.menuEntered){
442      GralCurveViewTrack_ifc input;
443      assert(widgd instanceof GralTable<?>);  //NOTE: context menu to table lines, has GralTable as widget.
444      @SuppressWarnings("unchecked")
445      GralTable<GralCurveViewTrack_ifc> table = (GralTable<GralCurveViewTrack_ifc>)widgd; //oContentInfo;
446      GralTable<GralCurveViewTrack_ifc>.TableLineData refline = table.getLineMousePressed();
447      if(refline != null){  
448        input = (GralCurveViewTrack_ifc)refline.getContentInfo();
449        if(input != null) {
450          Debugutil.stop();
451          //TODO
452          //refline.deleteLine();
453          //delete the track line!
454          
455          
456      } }
457     
458      table.repaint();
459    }
460    return true;
461    
462  }
463  
464  
465  
466  void setDatapath(GralTable<GralCurveViewTrack_ifc>.TableLineData line, String sDatapath){
467    GralCurveViewTrack_ifc input = line.data;
468    if(input == null){
469      GralColor colorLine = GralColor.getColor("rd");
470      input = widgCurve.addTrack(sName, sDatapath, colorLine, 0, 50, 5000.0f, 0.0f);
471    } else {
472      input.setDataPath(sDatapath);
473    }
474    
475  }
476  
477  
478  
479  
480  /**Step routine to save a curve. A curve will be saved only if the time has expired and the autoSave button is on.
481   * 
482   */
483  public void stepSaveCurve(){
484    //long timeNextSave = timeLastSave + timePeriodSave;
485    //long timeNow = System.currentTimeMillis();
486    if(wdgButtonAutosave !=null && wdgButtonAutosave.isOn() && widgCurve.shouldAutosave()) { //xx hasDataTosave && timeNextSave <= timeNow){
487      saveCurve(GralCurveView_ifc.ModeWrite.autoSave);
488    }
489  }
490  
491  
492  
493  /**Reads a curve ///
494   * 
495   */
496  protected void readCurve(File file){
497    try{
498      widgCurve.readCurve(file);
499    } catch(Exception exc){
500      widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
501      System.err.println(Assert.exceptionInfo("InspcCurveView-read", exc, 1, 2));
502    }
503    
504  }
505  
506  
507  /**Saves a curve ///
508   * 
509   */
510  protected void saveCurve(GralCurveView_ifc.ModeWrite mode){
511    try{
512      //long dateStart;
513      CharSequence sDate;
514      if(mode == GralCurveView_ifc.ModeWrite.autoSave){
515        sDate = widgCurve.timeInitAutoSave(); 
516      } else {
517        sDate = widgCurve.timeInitSaveViewArea(); 
518       // widgCurve.
519      }
520      String sNameFile = sDate + "_" + sName;
521      //fileCurveSave.mkdirs();
522      FileRemote fileCurveSave = dirCurveSave.child(sNameFile + ".csv");
523      FileSystem.mkDirPath(fileCurveSave);
524      System.out.println("InspcCurveView - save curve data to; " + fileCurveSave.getAbsolutePath());
525      writerCurveCsv.setFile(fileCurveSave);
526      widgCurve.writeCurve(writerCurveCsv, mode);
527      
528      String sClassExportDat = curveExporterClasses.get("dat");
529      if(sClassExportDat !=null){
530        Class<?> clazzCurveWriter2 = Class.forName(sClassExportDat);
531        
532        WriteCurve_ifc writerCurve2 = (WriteCurve_ifc)clazzCurveWriter2.newInstance();
533        File fileDat = new File(dirCurveSave, sNameFile + ".dat");
534        
535        writerCurve2.setFile(fileDat);
536        widgCurve.writeCurve(writerCurve2, mode);
537      }
538      System.out.println("InspcCurveView - data saved; " + fileCurveSave.getAbsolutePath());
539
540      //timeLastSave = System.currentTimeMillis();
541    } catch(Exception exc){
542      widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
543      System.err.println(Assert.exceptionInfo("InspcCurveView-save", exc, 1, 2));
544    }
545    
546  }
547  
548  
549  
550  /**Adds an info block to the request telegram to get values. This routine is called
551   * when the tx telegram to get values from target is assembled.
552   * 
553  void addTxInfoBlock(){
554    if(widgBtnOff.getState() == GralButton.kOn){
555      GralCurveViewTrack_ifc inpLast = null;
556      for(GralCurveViewTrack_ifc inp: tracks){
557        if(inp.widgetVariable !=null){
558          String sDataPath = inp.widgetVariable.getDataPath(); //inp.widgVarPath.getText().trim();
559          //if(sDataPath.length() >0){
560          inpLast = inp;
561          inp.bLast = false;  //all set to fast, but only the inpLast.bLast = true;
562          comm.getValueByPath(sDataPath, inp.rxActionRxValueByPath);
563        }
564        
565      } //for
566      if(inpLast !=null){
567        //at least one variable given.
568        inpLast.bLast = true;
569      }
570    }
571  }
572   */
573  
574  
575  
576
577  
578  GralUserAction actionOpenWindow = new GralUserAction("actionOpenWindow"){
579    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){ 
580      windCurve.setVisible(true); //setWindowVisible(true);
581      widgFileSelector.setVisible(false);
582      widgFilename.setVisible(false);
583      widgBtnReadCfg.setVisible(true);
584      widgCurve.setFocus();
585      return true;
586    }
587
588  };
589  
590  
591  
592  /**This action will be called if the mouse is pressed on the drop field.
593   * It is not drag and drop because drag'ndrop doesn't works on a field which content is not be able to select.
594   * That is on show fields. Therefore the {@link GralMng#getLastClickedWidget()} is used to detect
595   * which show field was clicked last.
596   * 
597   */
598  GralUserAction actionReplaceVariable = new GralUserAction("actionReplaceVariable"){
599    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
600    { return dropVariable(actionCode, (GralWidget)widgd, false);
601    }
602  };
603
604  
605  GralUserAction actionDeleteVariable = new GralUserAction("actionReplaceVariable"){
606    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
607    { return deleteVariable(actionCode, (GralWidget)widgd, false);
608    }
609  };
610
611  
612  GralUserAction actionOnOffTrack = new GralUserAction("actionOnOffTrack"){
613    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
614    { if(trackScale.getVisible() ==0) {
615        trackScale.setVisible(2);
616        //line.setBackColor(colorTrackSameScale, -1);
617      } else {
618        trackScale.setVisible(0);
619        //line.setBackColor(GralColor.getColor("gr"), -1);
620      }
621      GralTable<GralCurveViewTrack_ifc>.TableLineData line = widgTableVariables.getCurrentLine();
622      actionSelectVariableInTable.exec(KeyCode.F2, widgTableVariables, line);
623      widgCurve.repaint();
624      return true;
625    }
626  };
627
628
629  GralUserAction actionInsertVariable = new GralUserAction("actionInsertVariable"){
630    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
631    { return dropVariable(actionCode, (GralWidget)widgd, true);
632    }
633  };
634
635
636  public GralUserAction actionKeyHandlingTable = new GralUserAction("actionEnterDatapath"){
637    @Override public boolean exec(int key, GralWidget_ifc widgd, Object... params){
638      if(key == KeyCode.enter){
639        @SuppressWarnings("unchecked")  //compatible to Java-6
640        GralTable<GralCurveViewTrack_ifc>.TableLineData line = (GralTable.TableLineData)params[0];
641        if(line == null) {
642          String sDatapath = widgTableVariables.getCellTextFocus();
643          GralColor colorCurve = GralColor.getColor("red");
644          GralCurveViewTrack_ifc input = widgCurve.addTrack(sName, sDatapath, colorCurve, 0, 50, 5000.0f, 0.0f);
645          GralTableLine_ifc<GralCurveViewTrack_ifc> newline = widgTableVariables.addLine(sDatapath, new String[]{""}, input);  //add on end
646          int ixnewline = widgTableVariables.size();  //first line
647          newline.setCellText(sDatapath, 0);
648          widgTableVariables.setCurrentLine(newline, ixnewline, 0);
649        } else {
650          String sDatapath = line.getCellText(0);
651          InspcCurveView.this.setDatapath(line, sDatapath);
652        }
653      }
654      else if(key == KeyCode.F2){
655        actionOnOffTrack.exec(key, null);
656      }
657      return true;
658    }
659  };
660
661
662
663
664  GralUserAction actionSwapVariable = new GralUserAction("actionSwapVariable"){
665    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
666      if(actionCode == KeyCode.menuEntered && trackScale !=null){
667        //read paths                                  
668        //Object oContent = widgd.getContentInfo();
669        assert(widgd instanceof GralTable<?>);
670        @SuppressWarnings("unchecked")
671        GralTable<GralCurveViewTrack_ifc> table = (GralTable<GralCurveViewTrack_ifc>) widgd;
672        GralTableLine_ifc<GralCurveViewTrack_ifc> linesrc = table.getCurrentLine();
673        GralTableLine_ifc<GralCurveViewTrack_ifc> linedst = table.getLineMousePressed();
674        /*
675        if(linedst !=null && linesrc != linedst){
676          TrackValues trackDst = linedst.getUserData();  //(TrackValues)oContent;
677          //if(trackDst != trackScale){
678            String sPathSwap = trackDst.getDataPath();
679            GralColor colorSwap = trackDst.getLineColor(); //trackDst.colorCurve; //  
680            GralCurveViewTrack_ifc trackViewSwap = trackDst;
681            String sPathDst = trackScale.getDataPath();
682            GralColor colorDst = trackScale.getLineColor();  //colorCurve; //  
683            GralCurveViewTrack_ifc trackViewDst = trackScale;
684            //set paths to other.
685            trackScale.colorCurve = colorSwap;
686            linesrc.setCellText(sPathSwap, 0);
687            //linesrc.setKey(sPathSwap);
688            trackScale.setDataPath(sPathSwap);
689            linesrc.setTextColor(colorSwap);
690            trackScale = trackViewSwap;
691            //the new one can be an empty track:
692            trackDst.colorCurve = colorDst;
693            trackDst.setDataPath(sPathDst);
694            lineDst.setCellText(sPathDst, 0);
695            lineDst.setTextColor(colorDst);
696            trackDst = trackViewDst;
697            //change track for scale. It is the same like mouse1Down on this text field:
698            //actionSelectOrChgVarPath.exec(KeyCode.mouse1Down, trackDst.widgVarPath);
699          }
700        }
701        */
702      }
703      return true;
704    }
705  };
706  
707  
708  
709
710  GralUserAction actionShiftVariable = new GralUserAction("actionShiftVariable"){
711    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
712      if(actionCode == KeyCode.menuEntered && trackScale !=null){
713        //read paths
714        assert(widgd instanceof GralTable<?>);
715        @SuppressWarnings("unchecked")
716        GralTable<GralCurveViewTrack_ifc> table = (GralTable<GralCurveViewTrack_ifc>) widgd;
717        GralTableLine_ifc<GralCurveViewTrack_ifc> linesrc = table.getCurrentLine();
718        GralTableLine_ifc<GralCurveViewTrack_ifc> linedst = table.getLineMousePressed();
719        /*
720        //save values of the current selected.
721        if(trackScale != trackDst){
722          
723          String sPathSel = trackScale.widgVarPath.getText();
724          GralColor colorSel = trackScale.getLineColor();  //colorCurve; //  
725          GralCurveViewTrack_ifc trackViewSel = trackScale;
726          if(trackScale.ix > trackDst.ix){  //shift current selected up, shift rest down
727            int ix;
728            for(ix = trackScale.ix -1; ix >= trackDst.ix; --ix){
729              String sPath1 = tracks[ix].widgVarPath.getText();
730              GralColor color1 = tracks[ix].getLineColor();  //colorCurve; //  
731              GralCurveViewTrack_ifc trackView1 = tracks[ix];
732              tracks[ix+1].colorCurve = color1;
733              tracks[ix+1].widgVarPath.setTextColor(color1);
734              tracks[ix+1].widgVarPath.setText(sPath1);
735              tracks[ix+1] = trackView1;
736            }
737            //write into dst selected.
738            trackDst.colorCurve = colorSel;
739            trackDst.widgVarPath.setText(sPathSel);
740            trackDst.widgVarPath.setTextColor(colorSel);
741            trackDst = trackViewSel;
742          } else { //shift current selected down, shift rest up
743            int ix;
744            for(ix = trackScale.ix; ix < trackDst.ix-1; ++ix){
745              String sPath1 = tracks[ix+1].widgVarPath.getText();
746              GralColor color1 = tracks[ix+1].getLineColor();  //colorCurve; //  
747              GralCurveViewTrack_ifc trackView1 = tracks[ix+1];
748              tracks[ix].colorCurve = color1;
749              tracks[ix].widgVarPath.setTextColor(color1);
750              tracks[ix].widgVarPath.setText(sPath1);
751              tracks[ix] = trackView1;
752            }
753            //write into dst selected.
754            tracks[ix].colorCurve = colorSel;
755            tracks[ix].widgVarPath.setText(sPathSel);
756            tracks[ix].widgVarPath.setTextColor(colorSel);
757            tracks[ix] = trackViewSel;
758          }
759        }
760        */
761        //change track for scale. It is the same like mouse1Down on this text field:
762        //actionSelectOrChgVarPath.exec(KeyCode.mouse1Down, trackDst.widgVarPath);
763      }
764      return true;
765    }
766  };
767
768  
769  GralUserAction actionShareScale = new GralUserAction("actionShareScale"){
770    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
771    { if( KeyCode.isControlFunctionMouseUpOrMenu(actionCode) && trackScale !=null){
772        GralTable<GralCurveViewTrack_ifc>.TableLineData refline = widgTableVariables.getLineMousePressed();
773        GralCurveViewTrack_ifc dst = refline.getUserData();     //the line which should be entered in the scale group
774        dst.groupTrackScale(trackScale);  //trackScale is the line which was  previously selected.
775      }
776      return true;
777    }
778  };
779  
780  
781  GralUserAction actionUnshareScale = new GralUserAction("actionShareScale"){
782    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
783    { if( KeyCode.isControlFunctionMouseUpOrMenu(actionCode) && trackScale !=null){
784        GralTable<GralCurveViewTrack_ifc>.TableLineData refline = widgTableVariables.getLineMousePressed();
785        GralCurveViewTrack_ifc dst = refline.getUserData();
786        dst.ungroupTrackScale();  
787      }
788      return true;
789    }
790  };
791  
792  
793  GralUserAction actionSetScaleValues2Track = new GralUserAction("actionSetScaleValues2Track"){
794    @Override public boolean exec(int actionCode, GralWidget_ifc widgi, Object... params)
795    { System.out.println("InspcCurveView - actionSetScaleValues2Track, actioncode = " + Integer.toHexString(actionCode));
796      GralWidget widgd = (GralWidget)widgi;
797      if( (KeyCode.isControlFunctionMouseUpOrMenu(actionCode) || actionCode == KeyCode.enter) && trackScale !=null){
798        boolean setScale = false;
799        GralCurveViewTrack_ifc dst;
800        if(actionCode == KeyCode.enter) {
801          dst = trackScale; //TEST
802          setScale = true;
803        }
804        else if(actionCode == KeyCode.menuEntered && widgd.sCmd == null){ //from menu
805          assert(false);  //unused since shareTrackScale
806          GralTable<GralCurveViewTrack_ifc>.TableLineData refline = widgTableVariables.getLineMousePressed();
807          dst = refline.getUserData();
808          setScale = true;
809        } else {
810          dst = trackScale;
811        }
812        try {
813          String s1 = widgScale.getText();
814          float scale = Float.parseFloat(s1);
815          s1 = widgScale0.getText();
816          float scale0 = Float.parseFloat(s1);
817          s1 = widgline0.getText();
818          int line0 = (int)Float.parseFloat(s1);
819          String sNameScalingWidgd = null;
820          if(widgd.sCmd != null && widgd.sCmd != "!") { //not for set cmd
821            sNameScalingWidgd = scalingWidg.getName();
822          }
823          float[] fixScales = {7.5f, 6.0f, 5.0f, 4.0f, 3.0f, 2.5f, 2.0f, 1.75f, 1.5f, 1.25f, 1.0f};
824          if(widgd.sCmd == "+" && sNameScalingWidgd.equals("scale")){ 
825            float value = scale;
826            float exp1 = (float)Math.log10(value);
827            float exp = (float)Math.floor(exp1); //-1.0f; 
828            float base = (float)Math.pow(10.0, exp);
829            float unit = value/base;  //1.0 till 9.999
830            if(unit < 1.01f) {
831              unit = fixScales[0]; base /= 10.0f;
832            } else {
833              for(int ii = 0; ii < fixScales.length; ++ii){
834                if(unit > fixScales[ii]){ unit = fixScales[ii];  break; }
835            } }
836            scale = value = unit * base;;
837            s1 = Float.toString(value);
838            widgScale.setText(s1);
839            setScale = true;
840          }
841          else if(widgd.sCmd == "-" && sNameScalingWidgd.equals("scale")){
842            float exp1 = (float)Math.log10(1.01f * scale); //regard rounding effect, 0.1 may be presented by 0.0999999
843            float exp = (float)Math.floor(exp1); //-1.0f; 
844            float base = (float)Math.pow(10.0, exp);
845            float unit = scale / base;  //1.0 till 9.999
846            if(unit >= 0.99f * fixScales[0]) {
847              unit = 1.0f; base *= 10.0f;
848            } else {
849              for(int ii = fixScales.length-1; ii >=0; --ii){
850                if(unit < 0.98f * fixScales[ii]){ unit = fixScales[ii];  break; }
851            } }
852            //scale = value = value*2;
853            scale = unit * base;;
854            s1 = Float.toString(scale);
855            widgScale.setText(s1);
856            setScale = true;
857          }
858          else if(widgd.sCmd == "-" && sNameScalingWidgd.equals("scale0")){
859            if(scale0 >0 && scale0 < scale) {
860              scale0 = 0;  //trap the 0.0
861            } else {
862              scale0 -= scale;
863            }
864            s1 = Float.toString(scale0);
865            widgScale0.setText(s1);
866            setScale = true;
867          }
868          else if(widgd.sCmd == "+" && sNameScalingWidgd.equals("scale0")){
869            if(scale0 <0 && scale0 > -scale) {
870              scale0 = 0;  //trap the 0.0
871            } else {
872              scale0 += scale;
873            }
874            s1 = Float.toString(scale0);
875            widgScale0.setText(s1);
876            setScale = true;
877          }
878          else if(widgd.sCmd == "-" && sNameScalingWidgd.equals("line0")){
879            if(line0 >= 5.0f) { 
880              line0 -= 5.0f;
881              s1 = Float.toString(line0);
882              widgline0.setText(s1);
883              setScale = true;
884            }
885          }
886          else if(widgd.sCmd == "+" && sNameScalingWidgd.equals("line0")){
887            if(line0 < 95.0f) { 
888              line0 += 5.0f;
889              s1 = Float.toString(line0);
890              widgline0.setText(s1);
891              setScale = true;
892            }
893          }
894
895          //set the scale.
896          if(dst !=null && (  setScale   //maybe cmd '+' or '-', maybe menu 
897                           || widgd.sCmd == "!"  //set key
898                  )        ) {  
899            //widgCurve.setMinMax(trackScale.scale, -trackScale.scale);
900            if(dst == null){
901              dst = widgCurve.addTrack(sName, null, trackScale.getLineColor(), 0, 50, 5000.0f, 0.0f);
902            }
903            widgCurve.repaint(500,500);
904            dst.setTrackScale(scale, scale0, line0);
905            widgBtnScale.setTextColor(GralColor.getColor("lgn"));
906          }
907        } catch(NumberFormatException exc){
908          widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
909        }
910      }
911      return true;
912  } };
913  
914
915  
916  
917  GralUserAction actionScaleFromMarkedTrack = new GralUserAction("actionScaleFromMarkedTrack"){
918    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
919      GralTableLine_ifc markedLine = widgTableVariables.getFirstMarkedLine(1);
920      if(markedLine !=null){
921        //float scale = markedLine.
922      }
923      return true;
924  } };
925
926
927  
928  /**called if The text field was entered with mouse 
929   * or the focus lost on a changed variable path field.
930   * 
931   */
932  GralUserAction actionSelectVariableInTable = new GralUserAction("actionSelectOrChgVarPath"){
933    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
934      @SuppressWarnings("unchecked") ////
935      GralTableLine_ifc<GralCurveViewTrack_ifc> line = (GralTableLine_ifc<GralCurveViewTrack_ifc>)params[0];
936      if(line !=null){
937        GralCurveViewTrack_ifc track = line.getUserData(); //(GralCurveViewTrack_ifc)line.getContentInfo();
938        if(track !=null){
939          //set the background color of all line with the same scaling.
940          if( track ==null //deselect scaled lines
941            || trackScale !=null && !track.isGroupedTrackScale(trackScale) //don't do if it is the same scale group
942            || actionCode == KeyCode.F2 //invoked from actionOnOffTrack
943            ) {
944            for(GralTableLine_ifc<GralCurveViewTrack_ifc> line1: widgTableVariables.iterLines()) { ////
945              GralCurveViewTrack_ifc track1 = line1.getUserData();
946              if(track1 !=null && track1.getVisible() == 0) {
947                line1.setBackColor(colorTrackNotShown, colorTrackNotShownSelected, colorTrackNotShownSelected, colorTrackNotShownSelected, colorTrackNotShownSelected, -1);
948              }
949              else if(track1 !=null && track!=null && track1.isGroupedTrackScale(track)){
950                line1.setBackColor(colorTrackSameScale, colorTrackSameScaleSelected, colorTrackSameScaleSelected, colorTrackSameScaleSelected, colorTrackSameScaleSelected, -1);  //same scale
951              } else {
952                line1.setBackColor(colorTrackOtherScale, colorTrackOtherScaleSelected, colorTrackOtherScaleSelected, colorTrackOtherScaleSelected, colorTrackOtherScaleSelected, -1);
953              }
954            }
955            widgTableVariables.repaint(500,500);
956          }
957          //set the line from the last selection to normal
958          if(trackScale !=null && trackScale !=null){
959            trackScale.setLineProperties(trackScale.getLineColor(), 1, 0);
960            if(trackScale.getVisible() !=0){
961              trackScale.setVisible(1);
962            }
963          }
964          //set the track bold and show the scaling of the track 
965          InspcCurveView.this.trackScale = track;
966          if(trackScale !=null && trackScale.getVisible() !=0){
967            trackScale.setLineProperties(trackScale.getLineColor(), 3, 0);
968            trackScale.setVisible(2);
969            widgScale.setText("" + track.getScale7div());
970            widgScale0.setText("" + track.getOffset());
971            widgline0.setText("" + track.getLinePercent());
972          }
973          System.out.println("InspcCurveView.action - SelectVariableInTable");
974          widgCurve.repaint(100, 200);
975        }
976      }
977      return true;
978    }
979  };
980
981  
982  
983  
984  /**called if The text field was entered with mouse 
985   * or the focus lost on a changed variable path field.
986   * 
987   */
988  GralUserAction actionSelectOrChgVarPath = new GralUserAction("actionSelectOrChgVarPath"){
989    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
990      assert(false);
991      GralWidget widg = (GralWidget)widgd;
992      if(actionCode == KeyCode.mouse1Down || actionCode == KeyCode.menuEntered){
993        chgSelectedTrack((GralCurveViewTrack_ifc)widgd.getContentInfo());
994      }
995      else if(actionCode == (KeyCode.mouse1Down | KeyCode.ctrl)){
996        if(trackScale !=null){
997          //last variable
998          //trackScale.widgVarPath.setBackColor(GralColor.getColor("wh"),0);
999          if(trackScale !=null){
1000            trackScale.setLineProperties(trackScale.getLineColor(), 1, 0);
1001          }
1002        }
1003        trackScale = (GralCurveViewTrack_ifc)widgd.getContentInfo();
1004        if(trackScale == null){
1005          trackScale = widgCurve.addTrack(sName, null, trackScale.getLineColor(), 0, 50, 5000.0f, 0.0f);
1006        }
1007        //colorLineTrackSelected = trackScale.getLineColor();
1008        trackScale.setLineProperties(trackScale.getLineColor(), 3, 0);
1009        //trackScale.widgVarPath.setBackColor(GralColor.getColor("lam"),0);
1010        try{
1011          String s1 = widgScale.getText();
1012          float scale = Float.parseFloat(s1);
1013          s1 = widgScale0.getText();
1014          float scale0 = Float.parseFloat(s1);
1015          s1 = widgline0.getText();
1016          int line0 = (int)Float.parseFloat(s1);
1017          //widgCurve.setMinMax(trackScale.scale, -trackScale.scale);
1018          trackScale.setTrackScale(scale, scale0, line0);
1019        } catch(NumberFormatException exc){
1020          System.err.println("InspcCurveView - read scale values format error.");
1021        }
1022      }
1023      else if(actionCode == KeyCode.focusLost && widgd.isChanged(true)){
1024        String sPath = (widg).getValue();
1025        if(sPath.length() >0 && !sPath.endsWith(".")){
1026          GralCurveViewTrack_ifc track = (GralCurveViewTrack_ifc)widgd.getContentInfo();
1027          track.setDataPath(sPath);
1028        }
1029      }
1030      return true;
1031    }
1032  };
1033  
1034  
1035  
1036  GralUserAction actionOpenFileDialog = new GralUserAction("OpenFileDialog"){
1037    @SuppressWarnings("synthetic-access") @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params)
1038    { if(actionCode == KeyCode.mouse1Up){
1039        try{
1040          String sCmd = widgd.getCmd();
1041          if(sCmd.equals(sWhatTodoWithFile)) {
1042            //file dialog is open, second press
1043            actionEnterFile.exec(KeyCode.menuEntered, null);
1044            //setVisible already done.
1045          } else if(sWhatTodoWithFile !=null) {
1046            //other button, it is esc
1047            sWhatTodoWithFile = null;
1048            widgFilename.setVisible(false);
1049            widgFileSelector.setVisible(false);
1050            widgCurve.setVisible(true);
1051            widgBtnReadCfg.setBackColor(colorBtnFileInactive,0);
1052            widgBtnSaveCfg.setBackColor(colorBtnFileInactive,0);
1053            widgBtnReadValues.setBackColor(colorBtnFileInactive,0);
1054            widgBtnSaveValues.setBackColor(colorBtnFileInactive,0);
1055          } else { 
1056            //button pressed first time because .WhatTodoWithFile == null
1057            sWhatTodoWithFile = widgd.getCmd(); //The button cmd.
1058            widgd.setBackColor(colorBtnFileActive, 0);
1059            final FileRemote dir;
1060            if(sCmd.equals(sBtnReadCfg)){
1061              dir = fileCurveCfg;
1062            } else if(widgd.getCmd().equals(sBtnSaveCfg)){
1063              //windFileCfg.openDialog(fileCurveCfg, widgd.getCmd(), true, actionSaveCfg);
1064              dir = fileCurveCfg;
1065            } else if(widgd.getCmd().equals(sBtnReadValues)){
1066              //windFileCfg.openDialog(dirCurveSave, "read values", false, actionReadValues);
1067              dir = dirCurveSave;
1068            } else if(widgd.getCmd().equals(sBtnSaveValues)){
1069              //windFileCfg.openDialog(dirCurveSave, "write values", true, actionSaveValues);
1070              dir = dirCurveSave;
1071            } else {
1072              dir = null; //unexpected
1073            }
1074            //windFileCfg.openDialog(fileCurveCfg, widgd.getCmd(), false, actionReadCfg);
1075            widgCurve.setVisible(false);
1076            widgFilename.setVisible(true);
1077            widgFileSelector.setVisible(true);
1078            widgFileSelector.fillIn(dir, false);
1079            widgFileSelector.setFocus();
1080          }
1081        } catch(Exception exc){
1082          widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
1083        }
1084      }
1085      return true;
1086  } };
1087  
1088  
1089  /**Action invoked for any selected file. */
1090  GralUserAction actionSelectFile = new GralUserAction("GralFileSelector-actionSelectFile"){
1091    /**The action called from {@link GralTable}.
1092     * @param params [0] is the Table line. The content of table cells are known here,
1093     *   because it is the file table itself. The {@link GralTableLine_ifc#getUserData()}
1094     *   returns the {@link FileRemote} file Object.
1095     * @see org.vishia.gral.ifc.GralUserAction#userActionGui(int, org.vishia.gral.base.GralWidget, java.lang.Object[])
1096     */
1097    @SuppressWarnings("synthetic-access") @Override 
1098    public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1099      GralTableLine_ifc<?> line = (GralTableLine_ifc<?>) params[0];
1100      String sFileCell = line.getCellText(GralFileSelector.kColFilename);
1101      widgFilename.setText(sFileCell);
1102      return true;
1103    }
1104  };
1105
1106  
1107  /**Action for Enter the file. 
1108   */
1109  GralUserAction actionEnterFile = new GralUserAction("GralFileSelector-actionOk"){
1110    @SuppressWarnings("synthetic-access") @Override 
1111    public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1112      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){  //supress both mouse up and down reaction
1113        FileRemote dir = widgFileSelector.getCurrentDir();
1114        String sFilename = widgFilename.getText();
1115        FileRemote file;
1116        if(sFilename.length()==0 || sFilename.equals("..")){
1117          file = dir;
1118        } else {
1119          file = dir.child(sFilename);
1120        }
1121        if(sWhatTodoWithFile.equals(sBtnReadCfg)) {
1122          actionReadCfg(KeyCode.menuEntered, null, file);
1123          widgBtnReadCfg.setBackColor(colorBtnFileInactive, 0);
1124        } 
1125        else if(sWhatTodoWithFile.equals(sBtnSaveCfg)) {
1126          actionSaveCfg(KeyCode.menuEntered, null, file);
1127          widgBtnSaveCfg.setBackColor(colorBtnFileInactive, 0);
1128        }
1129        else if(sWhatTodoWithFile.equals(sBtnReadValues)) {
1130          actionReadValues(KeyCode.menuEntered, null, file);
1131          widgBtnReadValues.setBackColor(colorBtnFileInactive, 0);
1132        }
1133        else if(sWhatTodoWithFile.equals(sBtnSaveValues)) {
1134          actionSaveValues(KeyCode.menuEntered, null, file);
1135          widgBtnSaveValues.setBackColor(colorBtnFileInactive, 0);
1136        }
1137        sWhatTodoWithFile = null;
1138        widgFilename.setVisible(false);
1139        widgFileSelector.setVisible(false);
1140        widgCurve.setVisible(true);
1141           
1142      }
1143      return true;
1144    }
1145  };
1146
1147  
1148  
1149  
1150  boolean actionReadCfg(int actionCode, GralWidget_ifc widgd, Object... params)
1151  { if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
1152      try{
1153        fileCurveCfg = (FileRemote)params[0];
1154        System.out.println("InspcCurveView - read curve view from; " + fileCurveCfg.getAbsolutePath());
1155        windCurve.setTitle(InspcCurveView.this.sName + ": " + fileCurveCfg.getName());
1156        String in = FileSystem.readFile(fileCurveCfg);
1157        if(in ==null){
1158          System.err.println("InspcCurveView - actionRead, file not found;" + fileCurveCfg.getAbsolutePath());
1159        } else {
1160          if(widgCurve.applySettings(in)){ //apply the content of the config file to the GralCurveView
1161            //and transfer the names into the variable text fields of this widget. 
1162            fillTableTracks();
1163          }
1164        }
1165      } catch(Exception exc){
1166        widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
1167      }
1168      //windFileCfg.closeWindow();
1169    }
1170    return true;
1171  }
1172  
1173  
1174  
1175
1176  void actionSaveCfg(int actionCode, GralWidget_ifc widgd, Object... params)
1177  { if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
1178      try{
1179        fileCurveCfg = (FileRemote)params[0];
1180        //File file = new File("curve.save");
1181        System.out.println("InspcCurveView - save curve view to; " + fileCurveCfg.getAbsolutePath());
1182        Writer out = new FileWriter(fileCurveCfg);
1183        String sTimeVariable = widgCurve.getTimeVariable();
1184        if(sTimeVariable !=null){
1185          out.append("timeVariable = ").append(sTimeVariable).append(";\n");
1186        }
1187        //don't use: widgCurve.writeSettings(out);
1188        //because it writes the order of curves in the view.
1189        List<GralCurveViewTrack_ifc> listTable = widgTableVariables.getListContent();
1190        for(GralCurveViewTrack_ifc trackValue: listTable){
1191          GralCurveViewTrack_ifc track = trackValue;
1192          String sDataPath;
1193          int ix = 0;
1194          if(track !=null && (sDataPath = track.getDataPath()) !=null && sDataPath.length() >0){
1195            out.append("track ").append("Track").append(Integer.toString(ix)).append(":");
1196            out.append(" datapath=").append(sDataPath);
1197            GralColor lineColor = track.getLineColor();
1198            if(lineColor !=null){
1199              out.append(", color=").append(track.getLineColor().toString());
1200            } else {
1201              out.append(", color=0x000000");
1202            }
1203            out.append(", scale=").append(Float.toString(track.getScale7div()));
1204            out.append(", offset=").append(Float.toString(track.getOffset()));
1205            out.append(", 0-line-percent=").append(Integer.toString(track.getLinePercent()));
1206            out.append(";\n");
1207          }
1208          ix +=1;
1209        }
1210        out.close();  //NOTE: it is not closed on any write exception.
1211      } catch(Exception exc){
1212        widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
1213      }
1214    }
1215  }  
1216
1217
1218  
1219  /**Action invoked if the read file was selected in the {@link GralFileSelectWindow}
1220   */
1221  void actionReadValues(int actionCode, GralWidget_ifc widgd, Object... params)
1222  { if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
1223      try{
1224        assert(params[0] instanceof File);
1225        FileRemote file = (FileRemote)params[0];
1226        dirCurveSave = file.getParentFile();
1227        
1228        readCurve(file);
1229        fillTableTracks();
1230
1231        ///
1232        
1233      } catch(Exception exc){
1234        widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
1235        System.err.println(Assert.exceptionInfo("InspcCurveView - Read Curve", exc, 1, 2));
1236      }
1237    }
1238  }
1239  
1240
1241  /**Action invoked if the write file was selected in the {@link GralFileSelectWindow}
1242   */
1243  void actionSaveValues(int actionCode, GralWidget_ifc widgd, Object... params)
1244  { if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
1245      try{
1246        dirCurveSave = (FileRemote)params[0];
1247        if(dirCurveSave.exists() && !dirCurveSave.isDirectory()){
1248          dirCurveSave = dirCurveSave.getParentFile();
1249        }
1250        saveCurve(GralCurveView_ifc.ModeWrite.currentView);
1251        ///
1252        
1253      } catch(Exception exc){
1254        widgBtnScale.setLineColor(GralColor.getColor("lrd"),0);
1255        System.err.println(Assert.exceptionInfo("InspcCurveView - dirCurveSave", exc, 1, 2));
1256      }
1257    }
1258  }
1259  
1260
1261  public GralUserAction actionFocusScaling = new GralUserAction("actionSetFocusScaling"){
1262    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1263      if(actionCode == KeyCode.focusGained) {
1264        if(scalingWidg !=null){
1265          scalingWidg.setBackColor(GralColor.getColor("wh"), 0);   //current, old  
1266        }
1267        scalingWidg = (GralTextField)widgd;
1268        scalingWidg.setBackColor(GralColor.getColor("lam"), 0);  //the new one
1269      }
1270      return true; 
1271    }
1272  };
1273 
1274  
1275  public GralUserAction actionColorSelectorOpen = new GralUserAction("GralColorSelector-open"){
1276    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1277      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){
1278        if(colorSelector == null) {
1279          colorSelector = new GralColorSelector("colorSelector", GralMng.get());
1280          
1281        }
1282        colorSelector.openDialog("select Color for selected track", actionColorSet);
1283        return true;
1284      } else return false;
1285    }
1286  };
1287 
1288  
1289  public GralColorSelector.SetColorIfc actionColorSet = new GralColorSelector.SetColorIfc(){
1290    @Override public void setColor(GralColor color, SetColorFor what)
1291    { if(what == SetColorFor.line){
1292        if(trackScale !=null){
1293          /*
1294          if(trackScale == null){
1295            trackScale = widgCurve.initTrack(sName, null, trackScale.colorCurve, 0, 50, 5000.0f, 0.0f);
1296          }
1297          trackScale.setLineProperties(color, 3, 0);  //change color immediately to see what happen
1298          trackScale.colorCurve = color;
1299          */
1300          GralTableLine_ifc<GralCurveViewTrack_ifc> line = widgTableVariables.getCurrentLine();
1301          line.setTextColor(color);
1302          GralCurveViewTrack_ifc track = (GralCurveViewTrack_ifc)line.getContentInfo();
1303          if(track == trackScale){
1304            track.setLineProperties(color, 3, 0);  //change color immediately to see what happen
1305            trackScale.setLineProperties(color, ixTrackScale, ixTrackScale);
1306          } else {
1307            track.setLineProperties(color, 1, 0);  //change color immediately to see what happen
1308          }
1309          //trackScale.widgVarPath.setTextStyle(color, null);
1310      }
1311    } else {
1312      System.out.println("InspcCurveView - unexpected what");
1313    }
1314  } };
1315
1316  
1317  public GralUserAction actionShowCursorValues = new GralUserAction("actionShowCursorValues"){
1318    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1319      if(trackScale !=null && trackScale !=null){
1320        float valueCursorLeft = trackScale.getValueCursorLeft();
1321        float valueCursorRight = trackScale.getValueCursorRight();
1322        widgValCursorLeft.setText("" + valueCursorLeft);
1323        widgValCursorRight.setText("" + valueCursorRight);
1324      }
1325      return true;
1326    }
1327  };
1328 
1329  
1330
1331 
1332  
1333
1334  public GralUserAction actionTrackSelectedFromGralCurveViewCtrlMousePressed = new GralUserAction("actionTrackSelected"){
1335    @Override public boolean exec(int actionCode, GralWidget_ifc widgd, Object... params){
1336      //assert(false);
1337      GralCurveViewTrack_ifc trackNew = (GralCurveViewTrack_ifc)params[0];
1338      if(trackScale !=null && trackScale == trackNew) return true;  //do nothing.
1339      else {
1340        widgTableVariables.setCurrentLine(trackNew.getDataPath());
1341        //Note: the GralTable will call actionSelectVariableInTable and mark the line.
1342      }
1343      return true;
1344    }
1345  };
1346 
1347  
1348
1349  protected void chgSelectedTrack(GralCurveViewTrack_ifc trackNew){
1350    assert(false);
1351    if(trackScale !=null){
1352      //last variable
1353      //trackScale.widgVarPath.setBackColor(GralColor.getColor("wh"),0);
1354      if(trackScale !=null){
1355        trackScale.setLineProperties(null, 1, 0);
1356      }
1357    }
1358    trackScale = trackNew; //(GralCurveViewTrack_ifc)widgd.getContentInfo();
1359    if(trackScale == null){
1360      GralColor lineColor = GralColor.getColor("rd");
1361      trackScale = widgCurve.addTrack(sName, null, lineColor, 0, 50, 5000.0f, 0.0f);
1362    }
1363    //colorLineTrackSelected = trackScale.getLineColor();
1364    trackScale.setLineProperties(null, 3, 0);
1365    //trackScale.widgVarPath.setBackColor(GralColor.getColor("lam"),0);
1366    widgScale.setText("" + trackScale.getScale7div());
1367    widgScale0.setText("" + trackScale.getOffset());
1368    widgline0.setText("" + trackScale.getLinePercent());
1369    widgCurve.repaint(100, 200);
1370
1371  }
1372  
1373  
1374  
1375  
1376  
1377}