001package org.vishia.gral.cfg;
002
003import java.util.ArrayList;
004import java.util.LinkedList;
005import java.util.List;
006import java.util.Map;
007import java.util.Set;
008import java.util.TreeMap;
009
010import org.vishia.gral.ifc.GralMngBuild_ifc;
011
012
013/**This class contains all configuration data for the appearance of the GUI.
014 * It can be filled by {@link org.vishia.gral.cfg.GralCfgZbnf} or others.
015 * It is changed by user handling on GUI.
016 * It can be written out in a new configuration file
017 * 
018 * @author Hartmut Schorrig
019 *
020 */
021public final class GralCfgData
022{
023  
024  /**Version and history
025   * <ul>
026   * <li>2014-02-24 Hartmut new element help now also in config.
027   * <li>2013-12-02 Hartmut new conditional configuration. 
028   * <li>2012-04-22 Hartmut support {@link #new_Type()}.
029   * <li>2012-02-25 Hartmut chg {@link GuiCfgCurveLine#colorValue} = -1 initially to check whether it is given,
030   *   see {@link GralCfgBuilder#buildWidget(GralCfgElement)}
031   * <li>2011-06-00 Hartmut created: The old concept was evaluating ZBNF parse result of cfg file manually,
032   *   now usage of {@link org.vishia.zbnf.ZbnfJavaOutput} to write result info in this class.
033   * </ul>
034   *
035   * <b>Copyright/Copyleft</b>:<br>
036   * For this source the LGPL Lesser General Public License,
037   * published by the Free Software Foundation is valid.
038   * It means:
039   * <ol>
040   * <li> You can use this source without any restriction for any desired purpose.
041   * <li> You can redistribute copies of this source to everybody.
042   * <li> Every user of this source, also the user of redistribute copies
043   *    with or without payment, must accept this license for further using.
044   * <li> But the LPGL is not appropriate for a whole software product,
045   *    if this source is only a part of them. It means, the user
046   *    must publish this part of source,
047   *    but doesn't need to publish the whole source of the own product.
048   * <li> You can study and modify (improve) this source
049   *    for own using or for redistribution, but you have to license the
050   *    modified sources likewise under this LGPL Lesser General Public License.
051   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
052   * </ol>
053   * If you intent to use this source without publishing its usage, you can get
054   * a second license subscribing a special contract with the author. 
055   * 
056   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
057   */
058  public static final int version = 20120422;
059 
060  
061  
062  public final class Conditional
063  {
064    public boolean condition;
065    
066    
067    final Conditional parentLevel;
068    
069    public Conditional(GralCfgData cfgData, Conditional parent){
070      //super(cfgData);
071      parentLevel = parent;
072    }
073    
074  }
075  
076  
077  
078  /**ZBNF: DataReplace::= <$?key> = <$-/\.?string> ;
079   * Class for temporary instance to capture key and string. */
080  public final static class DataReplace
081  { public String key; public String string; 
082  }//class DataReplace
083  
084  
085  /**ZBNF: Element::= ... ;
086   * Class for instance to capture and store one element. */
087  //public final static class GuiCfgElement 
088  
089  /**ZBNF: position::= ... ;
090   * Class for instance to capture and store the position in an element. */
091  //public final static class GuiCfgPosition{  }//class Position
092  
093  
094  /**This is the base class of all configuration data for one widget. It contains common elements.
095   * It is used as destination for the parser of the configuration file.
096   */
097  public static class GuiCfgWidget implements Cloneable
098  {
099    /**Backward aggregation to the config element queue, to the item.*/
100    private final GralCfgElement itsElement;
101
102    /**See {@link org.vishia.gral.base.GralWidget#whatIs}. */
103    final char whatIs;
104
105    public boolean editable;
106    
107    /**From ZBNF-parser param::=<?> ...name = <""?name> etc. values are set if it is parsed. */
108    public String name, text, cmd, userAction, mouseAction, data, showMethod, format, type, prompt, promptPosition, help;
109    
110    /**From ZBNF-parser param::=<?> ...dropFiles = <""?name> etc. values are set if it is parsed. */
111    public String dragFiles, dropFiles, dragText, dropText;
112    
113    //public GuiCfgColor colorName = null; 
114    public GuiCfgColor color0 = null, color1 = null;
115    
116    /**From ZBNF-parser param::=<?> ...<?dragFiles> etc. boolean values are set if <?name> is parsed. */
117    
118    public GuiCfgWidget(GralCfgElement itsElement, char whatIs){ 
119      this.itsElement = itsElement; 
120      this.whatIs = whatIs;
121    }
122    
123    public void set_data(String val){ this.data = val; }
124    
125    public void set_help(String sHelp){ this.help = sHelp; }
126    
127    public GuiCfgColor new_colorName(){ return color0 = new GuiCfgColor(); }
128    
129    public void set_colorName(GuiCfgColor value){}
130    
131    public GuiCfgColor new_color0(){ return color0 = new GuiCfgColor(); }
132    
133    public void set_color0(GuiCfgColor value){}
134    
135    public GuiCfgColor new_color1(){ return color1 = new GuiCfgColor(); }
136    
137    public void set_color1(GuiCfgColor value){}
138
139    @Override
140    protected GuiCfgWidget clone()
141    { GuiCfgWidget clone = null;
142      try{ clone = (GuiCfgWidget)super.clone(); } 
143      catch(CloneNotSupportedException exc){ assert(false); }
144      return clone;
145    }
146
147    /**Sets all fields which are not determined by this instance from any other instance,
148     * especially from a type instance.
149     * @param src source for all values which are not determined in this yet.
150     */
151    public void setFromType(GuiCfgWidget src){
152      if(text ==null){ text = src.text; }
153      if(cmd ==null){ cmd = src.cmd; }
154      if(userAction ==null){ userAction = src.userAction; }
155      if(data ==null){ data = src.data; }
156      if(showMethod ==null){ showMethod = src.showMethod; }
157      if(prompt ==null){ prompt = src.prompt; }
158      if(promptPosition !=null){ promptPosition = src.promptPosition;}
159      if(dragFiles ==null){ dragFiles = src.dragFiles; }
160      if(dropFiles ==null){ dropFiles = src.dropFiles; }
161      if(dragText ==null){ dragText = src.dragText; }
162      //if(colorName ==null){ colorName = src.colorName; }
163      if(color0 ==null){ color0 = src.color0; }
164      if(color1 ==null){ color1 = src.color1; }
165    }
166    
167    
168  }//class WidgetTypeBase
169  
170  
171  /**ZBNF: Text::= ... ;
172   * Class for instance to capture and store the Table data. */
173  public final static class GuiCfgType extends GuiCfgWidget implements Cloneable
174  {
175    public String typeName;
176    public GuiCfgType(){ super(null, '*'); }
177  }
178  
179  
180  /**ZBNF: Text::= ... ;
181   * Class for instance to capture and store the Table data. */
182  public final static class GuiCfgText extends GuiCfgWidget implements Cloneable
183  {
184    public String size = "B";
185    public int colorValue;
186    public GuiCfgText(GralCfgElement itsElement){ super(itsElement, 'S'); }
187    public void XXXset_colorValue(int value){
188      //colorName = 
189    }
190  }
191  
192  
193  /**ZBNF: Text::= ... ;
194   * Class for instance to capture and store the Table data. */
195  public final static class GuiCfgLed extends GuiCfgWidget implements Cloneable
196  {
197    //public String size = "B";
198    public GuiCfgLed(GralCfgElement itsElement){ super(itsElement, 'D'); }
199    
200    @Override
201    public void set_data(String val){ this.data = val; }
202
203  }
204  
205  
206  
207  /**ZBNF: Line::= ... ;
208   * Class for instance to capture and store the Table data. */
209  public final static class GuiCfgLine extends GuiCfgWidget implements Cloneable
210  {
211    List<GuiCfgCoord> coords = new LinkedList<GuiCfgCoord>();
212    
213    public GuiCfgLine(GralCfgElement itsElement){ super(itsElement, 'I'); }
214    
215    public void set_coord(String value){}
216    
217    public GuiCfgCoord new_coord(){ return new GuiCfgCoord(); }
218    
219    public void add_coord(GuiCfgCoord value){ coords.add(value); }
220  }
221  
222  
223  /**ZBNF: |<?coord> <#f?x>, <#f?y>
224   */
225  public final static class GuiCfgCoord
226  {
227    public float x,y;
228  }
229  
230
231  /**ZBNF: Text::= ... ;
232   * Class for instance to capture and store the Table data. */
233  public final static class GuiCfgImage extends GuiCfgWidget implements Cloneable
234  {
235    public String size = "B";
236    
237    String file_;
238    
239    public GuiCfgImage(GralCfgElement itsElement){ super(itsElement, 'i'); }
240  
241    public void set_file(String value){ file_ = value; }
242  }
243  
244  
245  
246  /**ZBNF: ShowField::= ... ;
247   * Class for instance to capture and store the Table data. */
248  public final static class GuiCfgShowField extends GuiCfgWidget implements Cloneable
249  {
250    
251    public GuiCfgShowField(GralCfgElement itsElement){ super(itsElement, 'S'); }
252  }
253  
254  
255  /**ZBNF: ShowField::= ... ;
256   * Class for instance to capture and store the Table data. */
257  public final static class GuiCfgInputFile extends GuiCfgWidget implements Cloneable
258  {
259    
260    public GuiCfgInputFile(GralCfgElement itsElement){ super(itsElement, 'F'); }
261  }
262  
263  
264  /**ZBNF: Button::= ... ;
265   * Class for instance to capture and store the Button data. */
266  public final static class GuiCfgButton extends GuiCfgWidget implements Cloneable
267  {
268    final boolean bSwitch;
269    public GuiCfgButton(GralCfgElement itsElement){ super(itsElement, 'B'); bSwitch = false; }
270    public GuiCfgButton(GralCfgElement itsElement, boolean bSwitch){ super(itsElement, 'B'); this.bSwitch = bSwitch; }
271  }
272  
273  
274  
275  /**ZBNF: Table::= ... ;
276   * Class for instance to capture and store the Table data. */
277  public final static class GuiCfgTable extends GuiCfgWidget implements Cloneable
278  {
279    
280    public GuiCfgTable(GralCfgElement itsElement){ super(itsElement, 'l'); }
281
282    public int height;
283    
284    private final List<Integer> columnWidths = new LinkedList<Integer>();
285    
286    public void set_columnWidth(int val){ columnWidths.add(val); }
287    
288    public void set_text(String value){ super.text = value; }
289    
290    public List<Integer> getColumnWidths(){ return columnWidths; } 
291  }
292  
293  
294  /**ZBNF: Table::= ... ;
295   * Class for instance to capture and store the Table data. */
296  public final static class GuiCfgCurveview extends GuiCfgWidget implements Cloneable
297  {
298    public int nrofPoints;
299    
300    public boolean activate;
301    
302    List<GuiCfgCurveLine> lines = new LinkedList<GuiCfgCurveLine>();
303    
304    /**The element is created if the text if {@link #set_line(String)} is invoked 
305     * before {@link #newGuiElement} is invoked. The association is temporary valid for the current element. */
306    private GuiCfgCurveLine newLine;
307    
308    
309    public GuiCfgCurveview(GralCfgElement itsElement){ super(itsElement, 'c'); }
310
311    
312    /**ZBNF: DataReplace: CurveView::= .... <?line> */
313    public GuiCfgCurveLine new_line()
314    { 
315      if(newLine == null){ newLine = new GuiCfgCurveLine(null); }
316      return newLine; 
317    }  
318    
319    /**ZBNF: DataReplace: < Element> */
320    public void set_Element(String val)
321    { 
322      if(newLine == null){ newLine = new GuiCfgCurveLine(null); }
323      newLine.content = val;
324      //NOTE: the newGuiElement will be returned to fill in in new_Element()
325    }
326    
327    
328    
329    /**From ZBNF: DataReplace: < DataReplace> */
330    public void add_line(GuiCfgCurveLine value)
331    { lines.add(value);
332      newLine = null;
333    } 
334    
335    
336  }
337  
338
339  /**ZBNF: {<?line> ... ;
340   * Class for instance to capture and store the Table data. */
341  public final static class GuiCfgCurveLine extends GuiCfgWidget implements Cloneable
342  {
343    String content;
344    
345    public GuiCfgCurveLine(GralCfgElement itsElement){ super(itsElement, 'C'); }
346    
347    public int colorValue = 0;
348    public float offset, scale;
349    public int nullLine;
350  }
351  
352  
353  public final static class GuiCfgColor
354  {
355    public String color;
356  }
357  
358  
359  final List<String> cfgConditions;
360  
361  
362  GralCfgElement firstElement = null;
363  
364  private GralCfgElement actualElement = null;
365  
366  private Conditional actualConditional;
367  
368  /**ZBNF: DataReplace::= <$?key> = <$-/\.?string> ;
369   * Temporary instance to capture key and string. */
370  private final DataReplace dataReplaceTempInstance = new DataReplace();
371  
372  
373  /**The element is created if the text if {@link #set_Element(String)} is invoked 
374   * before {@link #newGuiElement} is invoked. The association is temporary valid for the current element. */
375  private GralCfgElement newGuiElement;
376  
377  /**Map of replacements of paths to data. Filled from ZBNF: DataReplace::= <$?key> = <$-/\.?string> */
378  public final Map<String, String> dataReplace = new TreeMap<String,String>();
379
380  Map<String, GuiCfgWidget> idxTypes = new TreeMap <String, GuiCfgWidget>();
381  
382  
383  /**TODO widgets sorted to panels and tabs!
384   * 
385   */
386  final List<GralCfgElement> listElementsInTextfileOrder = new ArrayList<GralCfgElement>();
387  
388  GralCfgPanel actPanel;
389  
390  /**Map of replacements of paths to data. Filled from ZBNF: DataReplace::= <$?key> = <$-/\.?string> */
391  private final Map<String, GralCfgPanel> idxPanels = new TreeMap<String,GralCfgPanel>();
392
393  
394  public GralCfgData(List<String> conditions)
395  {
396    this.cfgConditions = conditions;
397  }
398  
399  
400  public Set<Map.Entry<String, GralCfgPanel>> getPanels(){return idxPanels.entrySet(); } 
401  
402  /**ZBNF: size( <#?ySize> , <#?xSize> ) */
403  public void set_ySize(int value)
404  {
405    
406  }
407  
408  /**ZBNF: size( <#?ySize> , <#?xSize> ) */
409  public void set_xSize(int value)
410  {
411    
412  }
413  
414  
415  /**From ZBNF: DataReplace: < DataReplace> */
416  public DataReplace new_DataReplace(){ return dataReplaceTempInstance; }
417  
418  /**From ZBNF: DataReplace: < DataReplace> */
419  public void set_DataReplace(DataReplace value)
420  { dataReplace.put(value.key, value.string);
421  } 
422  
423  
424  
425  
426  
427  /**ZBNF: DataReplace: < ?Element >[ | | ] */
428  public GralCfgData new_Conditional()
429  { Conditional conditional = new Conditional(this, actualConditional);
430    actualConditional = conditional;
431    return this; 
432  }  
433
434  
435  /**ZBNF: DataReplace: < ?Element >[ | | ] */
436  public GralCfgData new_ElseConditional()
437  { Conditional conditional = new Conditional(this, actualConditional);
438    actualConditional = conditional;
439    return this; 
440  }  
441
442  
443  /**It is called on end of conditional block.
444   * @param val
445   */
446  public void add_Conditional(GralCfgData val){
447    actualConditional = actualConditional.parentLevel;
448  }
449  
450  
451  public void set_ifCondition(String cond){ 
452    
453    actualConditional.condition = cfgConditions.contains(cond);
454  }
455
456  
457  public void set_elseCondition(){ 
458    
459    actualConditional.condition = !actualConditional.condition;
460  }
461
462  
463
464  public GralCfgPanel new_Window()
465  { GralCfgPanel panel = new GralCfgPanel();
466    panel.widgetType = new GuiCfgWidget(panel, 'w');
467    return panel;
468  }
469
470  public void add_Window(GralCfgPanel panel)
471  {
472    idxPanels.put(panel.name, panel); 
473    listElementsInTextfileOrder.add(panel);  //list of elements in text file
474    
475  }
476
477  
478  /**ZBNF: DataReplace: < ?Element >[ | | ] */
479  public GralCfgElement new_Element()
480  { 
481    if(newGuiElement == null){ newGuiElement = new GralCfgElement(); }
482    //
483    if(actualConditional ==null || actualConditional.condition){
484      if(firstElement ==null){
485        firstElement = newGuiElement;
486      }
487      //GralCfgElement actual1 = actualConditional == null ? actualElement : actualConditional.actualElement;
488      if(actualElement !=null){
489        actualElement.next = newGuiElement;
490      }
491      newGuiElement.previous = actualElement;  //may be null
492      actualElement = newGuiElement;
493    }
494    return newGuiElement; 
495  }  
496
497  
498  /**From ZBNF: DataReplace: < DataReplace> */
499  public void add_Element(GralCfgElement value)
500  { 
501    if(actualConditional ==null || actualConditional.condition){
502      String sPanel = value.positionInput.panel;
503      if(value.widgetType != null && value.widgetType.text !=null && value.widgetType.text.equals("wd:yCos"))
504        stop();
505      if(sPanel == null){ //the last panel is used furthermore.
506        if(actPanel == null){ 
507          actPanel = new GralCfgPanel("$");
508        }
509        sPanel = actPanel.name;
510        value.setPanel(sPanel);
511      } else { //a panel is given.
512        actPanel = idxPanels.get(sPanel); 
513        if(actPanel == null){ //first time use that:
514          actPanel = new GralCfgPanel(sPanel);
515          idxPanels.put(sPanel, actPanel);
516        }
517      }
518      actPanel.listElements.add(value);      //list of elements in panels   
519      listElementsInTextfileOrder.add(value);  //list of elements in text file
520    }
521    newGuiElement = null;
522  } 
523  
524  
525
526  
527  /**ZBNF: DataReplace: < Element> */
528  public void set_Element(String val)
529  { 
530    if(newGuiElement == null){ newGuiElement = new GralCfgElement(); }
531    newGuiElement.content = val;
532    //NOTE: the newGuiElement will be returned to fill in in new_Element()
533  }
534  
535  /**ZBNF: Type::= typeName ( param ); */
536  public GralCfgData.GuiCfgType new_Type()
537  { GralCfgData.GuiCfgType widgt = new GralCfgData.GuiCfgType();
538    return widgt;
539  }
540
541  
542  /**ZBNF: Type::= typeName ( param ); */
543  public void add_Type(GralCfgData.GuiCfgType data){  
544    idxTypes.put(data.typeName, data);
545  }
546  
547
548  
549  
550  
551  
552  void XXXprocessConfiguration(final GralMngBuild_ifc panel)
553  {
554    
555  }
556
557  
558  public String XXXreplacePathPrefix(String path, String[] target)
559  {
560    String pathRet = path;
561    int posSep = path.indexOf(':');
562    if(posSep >=0){
563      String sRepl = dataReplace.get(path.substring(0, posSep));
564      if(sRepl !=null){
565        pathRet = sRepl + path.substring(posSep+1);  //Note: sRepl may contain a ':', its the device.
566      }
567      posSep = pathRet.indexOf(':');  //after replace or if it isn't replaced
568      if(posSep >=0){
569        target[0] = pathRet.substring(0, posSep);
570        pathRet = pathRet.substring(posSep+1);
571      }
572    }
573    return pathRet;
574  }
575  
576  
577  void stop(){}
578}