001package org.vishia.gral.base;
002
003import java.io.File;
004import java.io.IOException;
005import java.io.InputStream;
006import java.io.Writer;
007import java.lang.reflect.Constructor;
008import java.lang.reflect.InvocationTargetException;
009import java.text.ParseException;
010import java.util.LinkedList;
011import java.util.List;
012import java.util.Map;
013import java.util.Queue;
014import java.util.Set;
015import java.util.TreeMap;
016import java.util.concurrent.ConcurrentLinkedQueue;
017
018import org.vishia.byteData.VariableContainer_ifc;
019import org.vishia.gral.base.GralCurveView.CommonCurve;
020import org.vishia.gral.cfg.GralCfgBuilder;
021import org.vishia.gral.cfg.GralCfgData;
022import org.vishia.gral.cfg.GralCfgDesigner;
023import org.vishia.gral.cfg.GralCfgWriter;
024import org.vishia.gral.ifc.GralColor;
025import org.vishia.gral.ifc.GralCurveView_ifc;
026import org.vishia.gral.ifc.GralFactory;
027import org.vishia.gral.ifc.GralFileDialog_ifc;
028import org.vishia.gral.ifc.GralMngBuild_ifc;
029import org.vishia.gral.ifc.GralMngApplAdapter_ifc;
030import org.vishia.gral.ifc.GralPoint;
031import org.vishia.gral.ifc.GralTableLine_ifc;
032import org.vishia.gral.ifc.GralTextBox_ifc;
033import org.vishia.gral.ifc.GralVisibleWidgets_ifc;
034import org.vishia.gral.ifc.GralMng_ifc;
035import org.vishia.gral.ifc.GralRectangle;
036import org.vishia.gral.ifc.GralUserAction;
037import org.vishia.gral.ifc.GralWidget_ifc;
038import org.vishia.gral.ifc.GralWindowMng_ifc;
039import org.vishia.gral.ifc.GralWindow_ifc;
040import org.vishia.gral.widget.GralInfoBox;
041import org.vishia.gral.widget.GralLabel;
042import org.vishia.inspcPC.InspcReplAlias;
043import org.vishia.mainCmd.MainCmd;
044import org.vishia.mainCmd.MainCmdLoggingStream;
045import org.vishia.mainCmd.Report;
046import org.vishia.msgDispatch.LogMessage;
047import org.vishia.util.Debugutil;
048import org.vishia.util.FileSystem;
049import org.vishia.util.KeyCode;
050import org.vishia.util.ReplaceAlias_ifc;
051
052/**This is the Manager for the graphic. 
053 * It contains the independent parts of graphic organization.
054 * This class <code>GralMng</code> is a common approach to work with graphical interface simply. 
055 * The inner class {@link ImplAccess} is implemented by the several graphic-system-supporting classes.
056 * <ul>
057 * <li>{@link org.vishia.gral.swt.SwtMng}
058 * <li>{@link org.vishia.gral.awt.AwtWidgetMng}
059 * </ul>
060 * <br><br>
061 * 
062 * @author Hartmut Schorrig
063 *
064 */
065@SuppressWarnings("synthetic-access") 
066public class GralMng implements GralMngBuild_ifc, GralMng_ifc
067{
068  /**Version, history and license.
069   * <ul>
070   * <li>2016-11-04 Hartmut chg: {@link #notifyFocus(GralWidget)}: Only widgets with datapath. It is only for the inspector etc. TODO: Is there a list necessary? Store only the last widget in focus!
071   * <li>2016-09-02 Hartmut new: {@link #setPosPanel(GralPanelContent)} now invoked especially from ctor of {@link GralPanelContent}
072   *   and from ctor of {@link GralPanelContent.ImplAccess}. If a new Panel was created with a given {@link GralWidget#pos()} then that panel
073   *   is set as current one for the next widgets. Either the widgets are created before the implementation graphic with given position string,
074   *   then the panel should have a position string too to assigned them. Or the widgets are created with creation of the implementation graphic,
075   *   then a panel should be created in the same kind, and invoke {@link #setPosPanel(GralPanelContent)} in the ctor of its implementation.
076   *   The contract is unchanged: A created panel determines that all following widgets are created on that panel.
077   * <li>2016-09-02 Hartmut chg: {@link #registerPanel(GralPanelContent)} is only be called in the ctor of {@link GralPanelContent} 
078   *   because any panel is based on GralPanelContent. 
079   *   The definition of the panel in the {@link #pos()} used for the next widgets are done now in the extra routine {@link #setPosPanel(GralPanelContent)}. 
080   * <li>2016-09-01 Hartmut chg: instead implements {@link ReplaceAlias_ifc} now contains {@link #getReplacerAlias()}.
081   *   It is an extra class for a ReplacerAlias given independent of the graphic. 
082   * <li>2016-07-20 Hartmut chg: instead setToPanel now {@link #createImplWidget_Gthread()}. It is a better name. 
083   * <li>2015-10-29 Hartmut chg: Problem on {@link #pos()} with a second thread: The MainWindow- {@link GralPos#panel} was registered in another thread
084   *   and therefore unknown in the new {@link #pos()} for that thread. Solution: If the thread-specific GralPos will be created,
085   *   it should copy the data from the {@link #posCurrent} which is valid any case for valid initial data.   
086   * <li>2015-10-26 Hartmut new: The help and info box is an integral part of the GralMng and therefore available for any small application without additional effort.
087   *   Only the {@link #createHtmlInfoBoxes(MainCmd)} should be invoked in the graphic thread while initializing the application. 
088   * <li>2015-07-13 Hartmut chg: {@link GralMngFocusListener#focusLostGral(GralWidget)} now invokes the {@link GralWidget#actionFocused} too.
089   *   The action should distinguish between focus gained and focus lost in its action routine. That should be added to the code. Done for all vishia sources.  
090   * <li>2015-07-13 Hartmut new: {@link #registerUserAction(String, GralUserAction)} now knows possibility of usage the own name with "<name>" 
091   * <li>2015-07-13 Hartmut chg: Positioning: The new concept gets a position in the constructor of {@link GralWidget} via 
092   *   {@link #getPosCheckNext()}. That routine sets the current position in this class to {@link PosThreadSafe#posUsed} 
093   *   for further using to increment. That is correct. 
094   *   The problem before was faulty old-concept usage of org.vishia.gral.swt.SwtMng#XXXsetPosAndSizeSwt
095   *   which invokes {@link #setNextPosition()} which increments the position too, therefore twice. The usage of that routine
096   *   is prevented for Swt implementation, TODO for awt yet now. 
097   * <li>2015-05-31 Hartmut chg: {@link GralMngFocusListener}: invokes repaint() because of maybe changed outfit on focus gained
098   * <li>2015-05-02 Hartmut chg: {@link #registerWidget(GralWidget)} is obsolete now, it is empty yet. 
099   *   Instead {@link #registerWidget(String, GralWidget)} by given name and {@link #removeWidget(String)} by name.
100   *   See description of registering on {@link GralWidget#setToPanel(GralMngBuild_ifc)}. 
101   * <li>2015-04-27 Hartmut new {@link #selectPanel(GralPanelContent)} not only with String given
102   * <li>2015-01-18 Hartmut chg: Now the implementation for any Grahic (SwtMng) and the GralMng are two separated instances.
103   *   The SwtMng extends the {@link GralMng.ImplAccess} which accesses all private data of the GralMng.
104   * <li>2013-12-21 Hartmut new: {@link #createImplWidget_Gthread(GralWidget)} for all set to panel actions. That method handles all widget types. 
105   * <li>2013-03-20 Hartmut adap: {@link #actionFileSelect} with setText(...), now the file select field was filled.
106   * <li>2012-08-20 Hartmut new: {@link #getWidgetsPermanentlyUpdating()} created but not used yet because 
107   *   {@link #refreshCurvesFromVariable(VariableContainer_ifc)} has the necessary functionality.
108   * <li>2012-06-30 Hartmut new: Composition {@link #widgetHelper} The widget helper is implemented in the graphic system
109   *   for example as {@link org.vishia.gral.swt.SwtWidgetHelper} to do some widget specific things.
110   * <li>2012-06-30 Hartmut new: Composition {@link #_impl}.{@link InternalPublic#gralKeyListener}
111   * <li>2012-04-22 Hartmut new: {@link #addLine(GralColor, List)} to add in a {@link GralCanvasStorage}.
112   * <li>2012-04-01 Hartmut new: {@link #addDataReplace(Map)}, {@link #replaceDataPathPrefix(String)}.
113   *   using alias in the {@link GralWidget#setDataPath(String)}. The resolving of the alias is done
114   *   only if the datapath is used.   * <li>2012-03-17 Hartmut new: {@link #calcWidgetPosAndSize(GralPos, int, int)} as abstract method.
115   * <li>2012-03-10 Hartmut chg: {@link #addText(String)} now uses the background color {@link GralGridProperties#colorBackground_}.
116   * <li>2012-01-14 Hartmut chg: {@link #registerWidget(GralWidget)}: uses {@link GralPanelContent#addWidget(GralWidget, boolean)}.
117   * <li>2012-01-14 Hartmut new {@link #getValueFromWidget(GralWidget)} implementing here for non-platform depending values, especially GralTable.
118   * <li>2011-12-26 Hartmut new {@link #setApplicationAdapter(GralMngApplAdapter_ifc)} to support context sensitive help by focusGained of widgets.
119   * <li>2011-11-18 Hartmut new {@link #getLastClickedWidget()} to get the last clicked widget in any user routine.
120   *   The information about the widget can be used to capture widgets for any script.
121   * <li>2011-11-17 Hartmut new addText(String) as simple variant.  
122   * <li>2011-11-14 Hartmut bugfix: copy values of GralTabbedPanel.pos to this.pos instead set the reference from GralWidgetMng to GralTabbedPanel.pos 
123   *   The bug effect was removed panel in GralTabbedPanel.pos because it was the same instance as GralWidgetMng.
124   * <li>2011-10-01 Hartmut chg: move {@link #registerPanel(GralPanelContent)} from the SWT implementation to this.
125   * <li>2011-10-01 Hartmut new: method {@link #getPanel(String)} to get a registered panel by name.    
126   * <li>2011-09-30 Hartmut new: {@link #actionDesignEditField}. It is the action which is called from menu now.
127   * <li>2011-09-29 Hartmut chg: {@link #calcWidgetPosAndSize(GralPos, int, int, int, int)}: calculates dy and dx one pixel less.
128   * <li>2011-09-23 Hartmut chg: All implementation routines for positioning are moved to the class {@link GralPos}. This class contains only wrappers now.
129   * <li>2011-09-18 Hartmut chg: Inner static class GuiChangeReq now stored in an own class {@link GralWidgetChangeRequ}.
130   * <li>2011-09-18 Hartmut new: : {@link GralPos#setFinePosition(int, int, int, int, int, int, int, int, int, char, GralPos)} calculates from right or bottom with negative values.                            
131   * <li>2011-09-10 Hartmut chg: Renaming this class, old name was GuiMngBase.                             
132   * <li>2011-09-10 Hartmut chg: Some routines form SWT implementation moved to this base class. It doesn't depends on the underlying graphic base.                            
133   * <li>2011-08-13 Hartmut chg: New routines for store and calculate the position to regard large widgets.
134   * </ul>
135   * 
136   * <b>Copyright/Copyleft</b>:
137   * For this source the LGPL Lesser General Public License,
138   * published by the Free Software Foundation is valid.
139   * It means:
140   * <ol>
141   * <li> You can use this source without any restriction for any desired purpose.
142   * <li> You can redistribute copies of this source to everybody.
143   * <li> Every user of this source, also the user of redistribute copies
144   *    with or without payment, must accept this license for further using.
145   * <li> But the LPGL is not appropriate for a whole software product,
146   *    if this source is only a part of them. It means, the user
147   *    must publish this part of source,
148   *    but don't need to publish the whole source of the own product.
149   * <li> You can study and modify (improve) this source
150   *    for own using or for redistribution, but you have to license the
151   *    modified sources likewise under this LGPL Lesser General Public License.
152   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
153   * </ol>
154   * If you are intent to use this sources without publishing its usage, you can get
155   * a second license subscribing a special contract with the author. 
156   * 
157   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
158   */
159  public final static String sVersion = "2015-10-30";
160  
161        /**This class is used for a selection field for file names and paths. */
162  protected class FileSelectInfo
163  {
164    public List<String> listRecentFiles;
165    public String sRootDir;
166    public String sLocalDir;
167    public String sMask;
168    public String sTitle;
169    public final GralFileDialog_ifc dialogFile;
170    public final GralWidget dstWidgd;
171    
172    
173    public FileSelectInfo(String sTitle, List<String> listRecentFiles, String startDirMask, GralWidget dstWidgd)
174    { this.listRecentFiles = listRecentFiles;
175      this.dstWidgd = dstWidgd;
176      this.sTitle = sTitle;
177      int posColon = startDirMask.indexOf(':',2);  //regard : after windows drive letter.
178      String sLocalDir1;
179      if(posColon >=0){
180        this.sRootDir = startDirMask.substring(0, posColon) + "/";
181        sLocalDir1 = startDirMask.substring(posColon+1);
182      } else {
183        this.sRootDir = "";
184        sLocalDir1 = startDirMask;
185      }
186      int mode;
187      String sMask1;
188      int posSlash = sLocalDir1.lastIndexOf('/');
189      if(posSlash == sLocalDir1.length()-1){ //last is slash
190        mode = GralFileDialog_ifc.directory;
191        sMask1 = "";
192      } else {
193        mode = 0;
194        sMask1 = sLocalDir1.substring(posSlash+1);
195        if(sMask1.indexOf('*') >=0){ //contains an asterix
196          sLocalDir1 = posSlash >=0 ? sLocalDir1.substring(0, posSlash) : "";
197        } else {
198          sMask1 = null;  //no mask, sLocalDir is a directory.  
199        }
200      }
201      this.sMask = sMask1;
202      this.sLocalDir = sLocalDir1;
203      this.dialogFile = createFileDialog();
204      this.dialogFile.open(sTitle, mode);
205    }
206    
207  }
208  
209  
210  
211  /*package private*/ static final class PosThreadSafe
212  {
213    /**Position of the next widget to add. If some widgets are added one after another, 
214     * it is similar like a flow-layout.
215     * But the position can be set.
216     * The values inside the position are positive in any case, so that the calculation of size is simple.
217     */
218    protected final GralPos pos; //xPos, xPosFrac =0, xPosEnd, xPosEndFrac, yPos, yPosEnd, yPosFrac, yPosEndFrac =0;
219    
220    /**False if the position is given newly. True if it is used. Then the next add-widget invocation 
221     * calculates the next position in direction see {@link GralPos#setNextPosition()}. */
222    protected boolean posUsed;
223    
224    final long threadId;
225    
226    PosThreadSafe() {
227      threadId = Thread.currentThread().getId();
228      pos = new GralPos();
229    }
230    
231    PosThreadSafe(GralPos exists) {
232      threadId = Thread.currentThread().getId();
233      pos = new GralPos(exists);
234    }
235    
236    @Override public String toString(){ return "thread=" + threadId + ": " + pos.toString(); }
237   
238  }
239  
240  
241  /**The current position as helper if it is the same thread.
242   * Initialized firstly empty.
243   */
244  private PosThreadSafe posCurrent = new PosThreadSafe();
245
246  private final Map<Long, PosThreadSafe> posThreadSafe = new TreeMap<Long, PosThreadSafe>();
247  { //part of construction: safe the first instance.
248    posThreadSafe.put(posCurrent.threadId, posCurrent);
249  }
250  
251  
252  /**This instance helps to create the Dialog Widget as part of the whole window. It is used only in the constructor.
253   * Therewith it may be defined stack-locally. But it is better to show and explain if it is access-able at class level. */
254  //GuiDialogZbnfControlled dialogZbnfConfigurator;   
255  GralCfgBuilder cfgBuilder;
256  
257  GralCfgWriter cfgWriter;
258  
259  /**The designer is an aggregated part of the PanelManager, but only created if necessary. 
260   * TODO check whether it should be disposed to {@link #gralDevice} .*/
261  protected GralCfgDesigner designer;
262  
263  private GralCfgData cfgData;
264  
265  public boolean bDesignMode = false;
266  
267  /**Some actions may be processed by a user implementation. */
268  //private final GuiPlugUser_ifc user;
269  
270  protected boolean bDesignerIsInitialized = false;
271  
272  //final GralMng parent;
273  
274  /**Base class for managing all panels and related windows.
275   * This base class contains all common resources to manage panels and windows.
276   */
277  public final GralGraphicThread gralDevice = new GralGraphicThread();
278
279  /**Properties of this Dialog Window. */
280  public GralGridProperties propertiesGui;
281
282  /**Index of all input fields to access symbolic for all panels. */
283  protected final Map<String, GralWidget> indexNameWidgets = new TreeMap<String, GralWidget>();
284
285  /**Index of all input fields to access symbolic. NOTE: The generic type of WidgetDescriptor is unknown,
286   * because the set is used independently from the graphic system. */
287  protected final Map<String, GralWidget> showFields = new TreeMap<String, GralWidget>();
288
289  //private final IndexMultiTable showFieldsM;
290
291  private final List<GralWidget> widgetsInFocus = new LinkedList<GralWidget>();
292 
293  /**The one instance of the primary window created in the {@link org/vishia/ifc/GralFactory#createWindow(String, String, int)} . */
294  private GralWindow windPrimary;
295  
296  /**Three windows as sub window for html help, info and logging created if the primary window is created. */
297  public GralInfoBox infoHelp, infoBox, infoLog;
298  
299  private String sHelpBase;
300
301
302  
303  /**List of all panels which may be visible yet. 
304   * The list can be iterated. Therefore it is lock-free multi-threading accessible.
305   */
306  protected final ConcurrentLinkedQueue<GralVisibleWidgets_ifc> listVisiblePanels = new ConcurrentLinkedQueue<GralVisibleWidgets_ifc>();
307  
308  
309  Queue<GralWidget> listWidgetsPermanentUpdating = new LinkedList<GralWidget>();
310  
311  
312  /**It is possible to write any message via this class to a logging system.
313   * All internal methods of gral writes exceptions to that logging system instead abort the execution of the application.
314   */
315  public final LogMessage log;
316  
317  
318  protected GralMngApplAdapter_ifc applAdapter;
319  
320        /**Composition of some curve view widgets, which should be filled indepentent of there visibility. */
321  @Deprecated public final List<GralCurveView_ifc> curveContainer = new LinkedList<GralCurveView_ifc>();
322        
323  /**Position of the next widget to add. If some widgets are added one after another, 
324   * it is similar like a flow-layout.
325   * But the position can be set.
326   * The values inside the position are positive in any case, so that the calculation of size is simple.
327   */
328  protected final GralPos XXXpos = new GralPos(); //xPos, xPosFrac =0, xPosEnd, xPosEndFrac, yPos, yPosEnd, yPosFrac, yPosEndFrac =0;
329  
330  /**False if the position is given newly. True if it is used. Then the next add-widget invocation 
331   * calculates the next position in direction see {@link GralPos#setNextPosition()}. */
332  protected boolean XXXposUsed;
333  
334
335  
336  
337  /**Saved last use position. After calling {@link #setPosAndSize_(Control, int, int, int, int)}
338   * the xPos and yPos are setted to the next planned position.
339   * But, if a new position regarded to the last given one is selected, the previous one is need.
340   */
341  //protected int xPosPrev, xPosPrevFrac, yPosPrev, yPosPrevFrac;
342  
343  /**width and height for the next element. If a value */
344  //protected int xSize, xSizeFrac, ySize, ySizeFrac;
345  
346  /**'l' - left 'r'-right, 't' top 'b' bottom. */ 
347  //protected char xOrigin = 'l', yOrigin = 'b';
348  
349  //protected char pos.dirNext = 'r';
350  
351  /**The width of the last placed element. 
352   * It is used to determine a next xPos in horizontal direction. */
353  //int xWidth;
354  
355  /**True if the next element should be placed below the last. */
356  protected boolean bBelow, bRigth;
357  
358  
359  /**
360   * 
361   */
362  protected GralUserAction userMainKeyAction;
363  
364  InspcReplAlias replacerAlias = new InspcReplAlias();
365  
366  //public final GralWidgetHelper widgetHelper;
367  
368        /**Creates an nee Panel Manager in a new Window.
369         * @param graphicBaseSystem
370         * @return
371         */
372        @SuppressWarnings("unchecked")
373        public static GralMng createWindow(String graphicBaseSystem)
374        { Class<GralMng> mngClass;
375                GralMng mng = null;
376                String sGraphicBaseSystem = "org.vishia.mainGuiSwt.GuiPanelMngSwt";
377                try{ 
378                        mngClass = (Class<GralMng>) Class.forName(sGraphicBaseSystem);
379                } catch(ClassNotFoundException exc){ mngClass = null; }
380                
381                if(mngClass == null) throw new IllegalArgumentException("Graphic base system not found: " + sGraphicBaseSystem);
382                try{ 
383                        Constructor<GralMng> ctor = mngClass.getConstructor();
384                        mng = ctor.newInstance();
385                        //mng = mngClass.newInstance();
386                
387                } catch(IllegalAccessException exc){ throw new IllegalArgumentException("Graphic base system access error: " + sGraphicBaseSystem);
388                } catch(InstantiationException exc){ throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem);
389                } catch (SecurityException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem);
390                } catch (NoSuchMethodException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem);
391                } catch (IllegalArgumentException exc) {throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem);
392                } catch (InvocationTargetException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem);
393                }
394                return mng;
395        }
396        
397  PosThreadSafe pos() 
398  { long threadId1 = Thread.currentThread().getId();
399    PosThreadSafe ret = posCurrent;   //thread safe: atomic access, use ret.
400    if(ret.threadId != threadId1) {   //only access to map if necessary.
401      Long threadId = new Long(threadId1);
402      ret = posThreadSafe.get(threadId);
403      if(ret == null){
404        ret = new PosThreadSafe(posCurrent.pos); //copy values from the last one 
405        posThreadSafe.put(threadId, ret);
406      }
407    }
408    posCurrent = ret;                 //store for next access, it may be faster.
409    return ret;
410  }
411  
412  
413  /**Sets the position with a given String, see {@link GralPos#setPosition(CharSequence, GralPos)}
414   * whereby the parent is the current position value.
415   * @param sPosition
416   * @throws ParseException
417   */
418  public void setPos(String sPosition) 
419  throws ParseException
420  { PosThreadSafe pos = pos();
421    pos.pos.setPosition(sPosition, null);
422    pos.posUsed = false;
423  }
424  
425  @Override public void setPositionSize(int line, int column, int height, int width, char direction)
426  { PosThreadSafe pos = pos();
427    if(line < 0){ line = pos.posUsed? GralPos.next: GralPos.same; }
428    if(column < 0){ column = pos.posUsed? GralPos.next: GralPos.same; }
429    setFinePosition(line, 0, height + GralPos.size, 0, column, 0, width + GralPos.size, 0, 1, direction, 0 ,0 , pos.pos);
430  }
431
432  @Override public void setPosition(float line, float lineEndOrSize, float column, float columnEndOrSize
433    , int origin, char direction)
434  { setPosition(pos().pos, line, lineEndOrSize, column, columnEndOrSize, origin, direction);
435  }
436
437
438  @Override public void setPosition(float line, float lineEndOrSize, float column, float columnEndOrSize
439    , int origin, char direction, float border)
440  { PosThreadSafe pos = pos();
441    pos.pos.setPosition(pos.pos, line, lineEndOrSize, column, columnEndOrSize, origin, direction, border);
442    pos.posUsed = false;
443  }
444
445
446  @Override public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize
447    , int origin, char direction)
448  { PosThreadSafe pos = pos();
449    pos.pos.setPosition(framePos, line, lineEndOrSize, column, columnEndOrSize, origin, direction);
450    pos.posUsed = false;
451  }
452  
453  @Override public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize
454    , int origin, char direction, float border)
455  { PosThreadSafe pos = pos();
456      pos.pos.setPosition(framePos, line, lineEndOrSize, column, columnEndOrSize, origin, direction, border);
457      pos.posUsed = false;
458  }
459  
460  @Override public void setFinePosition(int line, int yPosFrac, int ye, int yef
461    , int column, int xPosFrac, int xe, int xef, int origin, char direction, int border, int borderFrac, GralPos frame)
462  { PosThreadSafe pos = pos();
463    pos.pos.setFinePosition(line, yPosFrac, ye, yef, column, xPosFrac, xe, xef, origin, direction, border, borderFrac, frame);
464    pos.posUsed = false;
465  }
466  
467  
468  @Override public void setSize(int height, int ySizeFrac, int width, int xSizeFrac)
469  { PosThreadSafe pos = pos();
470    pos.pos.setSize(height, ySizeFrac, width, xSizeFrac);  //NOTE: setSize sets the next pos 
471    pos.posUsed = false;
472  }
473  
474  void setSize(float height, float width)
475  { PosThreadSafe pos = pos();
476    pos.pos.setSize(height, width, pos.pos);
477    pos.posUsed = false;
478  }
479  
480  /**Not for user: Checks whether the position is used, sets the next position then, markes the position as used.
481   * See @link GralPos#setNextPosition(), {@link #posUsed}. TODO remove in AwtMng*/
482  @Deprecated public void setNextPosition()
483  { PosThreadSafe pos = pos();
484    if(pos.posUsed){
485      pos.pos.setNextPosition();
486    }
487    pos.posUsed = true;
488  }  
489  
490  /**Not for user: Checks whether the position is used, sets the next position then, markes the position as used.
491   * See @link GralPos#setNextPosition(), {@link #posUsed}. */
492  public void setNextPositionUnused()
493  { PosThreadSafe pos = pos();
494    if(pos.posUsed){
495      pos.pos.setNextPosition();
496    }
497    pos.posUsed = false;
498  }  
499  
500  public void registerShowField(GralWidget widg){
501    //link the widget with is information together.
502    if(widgetsInFocus.size()==0 && widg.getDataPath() !=null) {
503      //it has not a datapath initally. Never come here.
504      widgetsInFocus.add(widg);   //add first widget.
505    }
506    if(widg.name !=null){
507      showFields.put(widg.name, widg);
508    }
509
510  }
511  
512  
513  @Override public GralPos getPositionInPanel(){ return pos().pos.clone(); }
514  
515  public GralPos getPosCheckNext(){ 
516    PosThreadSafe pos = pos();
517    if(pos.posUsed){
518      pos.pos.setNextPosition();
519      pos.posUsed = false;
520    }
521    pos.posUsed = true;
522    return pos.pos.clone(); 
523  }
524  
525  
526  /**Used for deprecated style, without independent GralWidget. TODO remove.
527   * @return Independent GralPos from the GralMng
528   */
529  public GralPos getPosOldPositioning(){ return getPosCheckNext(); }
530        
531  /**Map of all panels. A panel may be a dialog box etc. */
532  protected final Map<String,GralPanelContent> panels = new TreeMap<String,GralPanelContent>();
533  
534  /**Any kind of TabPanel for this PanelManager TODO make protected
535   */
536  public GralTabbedPanel currTabPanel;
537  
538  //public GralPanelContent currPanel;
539  
540  protected String sCurrPanel;
541  
542  /**Last focused widget or last selected line in a table. 
543   * This info can be used to get the last widget on a context menu etc. on another widget.
544   * See {@link #getLastClickedWidget()}
545   */
546  private GralWidget_ifc lastClickedWidget;
547  
548  //private String lastClickedDatapath;
549  
550  //private String lastClickedVariable;
551  
552  @Deprecated @Override public List<GralWidget> getListCurrWidgets(){ return pos().pos.panel.widgetList; }
553        
554  /**Index of all user actions, which are able to use in Button etc. 
555   * The user action "showWidgetInfos" defined here is added initially.
556   * Some more user-actions can be add calling {@link #registerUserAction(String, GralUserAction)}. 
557   * */
558  protected final Map<String, GralUserAction> userActions = new TreeMap<String, GralUserAction>();
559  //private final Map<String, ButtonUserAction> userActions = new TreeMap<String, ButtonUserAction>();
560  
561  /**Index of all Tables, which are representable. */
562  //private final Map<String, Table> userTableAccesses = new TreeMap<String, Table>();
563  
564  /**Map of replacements of paths to data. Filled from ZBNF: DataReplace::= <$?key> = <$-/\.?string> */
565  private final Map<String, String> dataReplace = new TreeMap<String,String>();
566
567  public ImplAccess impl;
568  
569  private static GralMng singleton;
570        
571  /*
572  public GralMng(GralGraphicThread device, LogMessage log)
573  { this.gralDevice = device;
574    //this.propertiesGui = props;
575      this.log = log;
576  //its a user action able to use in scripts.
577      userActions.put("showWidgetInfos", this.actionShowWidgetInfos);
578  GralMng.singleton = this; 
579  }
580  */
581
582  private GralMng(LogMessage log)
583  { //this.propertiesGui = props;
584      this.log = log;
585    //its a user action able to use in scripts.
586    userActions.put("showWidgetInfos", this.actionShowWidgetInfos);
587    GralMng.singleton = this; 
588  }
589
590  
591  /**Creates the singleton instance of the GralMng. If this routine is invoked more as one time, the first invocation
592   * is the correct one. The more-time-invocation is supported because an application may not invoke this routine.
593   * Therefore it is invoked later additional.
594   * <br> See also {@link #get()}.
595   * @param log The first invocation determines the log output.
596   * @return true if created, false if exists already.
597   * @??deprecated {@link #get()} is sufficient TODO detemine log
598   */
599  public static boolean create(LogMessage log){
600    if(singleton !=null) return false;
601    else { 
602      singleton = new GralMng(log);
603      return true;
604    }
605  }
606  
607
608  /**Returns the singleton of the GralMng. Creates it if it is not instantiated yet. 
609   * On creation all logging output will be redirect to System.out.
610   * To use another logging output, create the GralMng using {@link GralMng#GralMng(LogMessage)}
611   * on start of application, before this routine is firstly called. */
612  public static GralMng get(){ 
613    if(singleton == null) { //not initialized yet, early invocation:
614      singleton = new GralMng(new MainCmdLoggingStream(System.out));
615    }
616    return singleton; 
617  }
618  
619  
620  public void setProperties(GralGridProperties props) {
621    this.propertiesGui = props;
622  }
623  
624  public void setFirstlyThePrimaryWindow(GralWindow primaryWindow){
625    if(this.windPrimary !=null)
626      throw new IllegalStateException("Primary Window should set only one time.");
627    this.windPrimary = primaryWindow; 
628    panels.put("primaryWindow", primaryWindow);
629  };
630  
631  
632  public static void createMainWindow(GralFactory factory, GralWindow window, char sizeShow, int left, int top, int xSize, int ySize) {
633    factory.createWindow(window, sizeShow, left, top, xSize, ySize);
634  }
635  
636  
637  
638  /**This routine should be called in the initializing routine in the graphic thread one time.
639   * @param mainCmd If given the help from mainCmd will be written into the Help box.
640   */
641  public void createHtmlInfoBoxes(MainCmd mainCmd)
642  {
643    setPosition(10, 0, 10, 0, 0, 'd');
644    infoBox = createTextInfoBox("infoBox", "Info");
645    //
646    selectPanel("primaryWindow");
647    setPosition(0,40,10,0,0,'.');
648    infoHelp = GralInfoBox.createHtmlInfoBox(null, "Help", "Help", true);
649    if(mainCmd !=null) {
650      try{
651        for(String line: mainCmd.listHelpInfo){
652          infoHelp.append(line).append("\n");
653        }
654      } catch(Exception exc){ writeLog(0, exc); }
655    }
656  }
657  
658  
659  
660  /**Not that this routine must not invoked before the {@link GralFactory#createWindow(GralWindow, char, int, int, int, int)}
661   * was not called.
662   * @see org.vishia.gral.ifc.GralMngBuild_ifc#createImplWidget_Gthread(org.vishia.gral.base.GralWidget)
663   */
664  @Override public void createImplWidget_Gthread(GralWidget widgg){ 
665    if(widgg instanceof GralWindow){
666      GralWindow wind1 = (GralWindow)widgg;
667      impl.createSubWindow(wind1);
668      //registerPanel(wind1);
669      //set the current position of the manager to this window, initalize it.
670      //PosThreadSafe pos = pos();
671      //pos.pos.panel = wind1; //it is selected.
672      //pos.pos.setPosition(null, 0,0,0,0,0,'r');  //per default the whole window as position and size.
673
674    } else {  
675      impl.createImplWidget_Gthread(widgg); 
676    }
677  }
678  
679  
680  /* (non-Javadoc)
681   * @see org.vishia.gral.ifc.GralMngBuild_ifc#setMainKeyAction(org.vishia.gral.ifc.GralUserAction)
682   */
683  @Override public GralUserAction setMainKeyAction(GralUserAction userMainKeyAction){
684    GralUserAction last = this.userMainKeyAction;
685    this.userMainKeyAction = userMainKeyAction;
686    return last;
687  }
688  
689  
690  
691  /**package private*/ GralUserAction userMainKeyAction(){ return userMainKeyAction; }
692  
693  
694  @Override public GralGridProperties propertiesGui(){ return propertiesGui; }
695  
696  @Override public GralGraphicThread gralDevice(){ return gralDevice; }
697  
698  @Override public LogMessage log(){ return log; }
699
700
701  
702  /**Returns null if the widget value can only be gotten platform-depending.
703   * The platform widget manager should override this method too and invoke super.getValueFromWidget()
704   * to call this method. If it returns a value, then it is ok.
705   * A user invocation calls the overridden platform depending method automatically.
706   * <br>
707   * See {@link org.vishia.gral.swt.SwtMng}.   
708   */
709  @Override public String getValueFromWidget(GralWidget widgd)
710  { String sValue = null;
711    if(widgd instanceof GralTable){
712      StringBuilder u = new StringBuilder();
713      GralTableLine_ifc line = ((GralTable)widgd).getCurrentLine();
714      String[] texts = line.getCellTexts();
715      for(int iCol = 0; iCol < texts.length; ++iCol){
716        u.append(texts[iCol]).append('\t');
717      }
718      sValue = u.toString();
719    }
720    return sValue;
721  }
722
723  public void setApplicationAdapter(GralMngApplAdapter_ifc adapter){ this.applAdapter = adapter; }
724  
725
726  public GralMngApplAdapter_ifc getApplicationAdapter(){ return applAdapter; } 
727  
728  
729  @Override public ReplaceAlias_ifc getReplacerAlias(){ return replacerAlias; }
730  
731  
732
733  public void setHelpBase(String path){ 
734    sHelpBase = path; 
735  }
736  
737  
738  
739  public void setHelpUrl(String url){ 
740    String sUrl;
741    if(url.startsWith("+")){
742      sUrl = sHelpBase + url.substring(1);
743    } else if(FileSystem.isAbsolutePath(url)) { 
744      sUrl = url;  //absolute path
745    } else if (sHelpBase !=null) { //it is a directory which does not end with "/"
746      sUrl = sHelpBase + "/" + url;  //url is a "file.html+label"
747    } else {
748      sUrl = url;  //should be absolute
749    }
750    if(infoHelp !=null) infoHelp.setUrl(sUrl); 
751  }
752  
753
754  
755  public void setHtmlHelp(String url){
756    setHelpUrl(url); 
757    /*
758    if(applAdapter !=null){
759      applAdapter.setHelpUrl(url);
760    }
761    */
762  }
763  
764  public void showInfo(CharSequence text) {
765    if(infoBox == null) return;
766    if(text !=null){ infoBox.setText(text); }
767    infoBox.setFocus();
768  }
769  
770  public void setInfo(CharSequence text) {
771    if(infoBox == null) return;
772    infoBox.setText(text);
773  }
774  
775
776  
777  public void addInfo(CharSequence info, boolean show)
778  {
779    if(infoBox == null) return;
780    try{ infoBox.append(info); }
781    catch(IOException exc){}
782    if(show){
783      infoBox.setFocus(); //setWindowVisible(true);
784    }
785  }
786
787  
788  
789  /**selects a registered panel for the next add-operations. 
790   */
791  @Override public void selectPanel(String sName){ 
792    PosThreadSafe pos = pos();
793    pos.pos.panel = panels.get(sName);
794    sCurrPanel = sName;
795    if(pos.pos.panel == null && currTabPanel !=null) {
796      //use the position of the current tab panel for the WidgetMng. Its panel is the parent.
797      pos.pos.set(currTabPanel.pos());  
798      pos.pos.panel = currTabPanel.addGridPanel(sName, /*"&" + */sName,1,1,10,10);
799      panels.put(sName, pos.pos.panel);  //TODO unnecessay, see addGridPanel
800      log.sendMsg(0, "GuiPanelMng:selectPanel: unknown panel name %s", sName);
801      //Note: because the pos.panel is null, not placement will be done.
802    }
803    setPosition(0,0,0,0,0,'d');  //set the position to default, full panel because the panel was selected newly.
804  }
805  
806  
807  /**Selects the given panel as current panel to build some content. */
808  @Override public void selectPanel(GralPanelContent panel) {
809    pos().pos.panel = panel;
810    sCurrPanel = panel == null ? null: panel.name;
811    setPosition(0,0,0,0,0,'d');  //set the position to default, full panel because the panel was selected newly.
812  }
813  
814  /**Selects the primary window as current panel to build some content. */
815  @Override public void selectPrimaryWindow() { selectPanel(windPrimary); } 
816  
817  @Override public boolean currThreadIsGraphic(){
818    return Thread.currentThread().getId() == gralDevice.getThreadIdGui();
819  }
820
821
822  
823  @Override public GralWidget getWidget(String name)
824  { return indexNameWidgets.get(name);
825  }
826  
827  
828  
829  @Override public void buildCfg(GralCfgData data, File fileCfg) //GuiCfgBuilder cfgBuilder)
830  {
831    this.cfgData = data;
832    File currentDir = FileSystem.getDir(fileCfg);
833    this.cfgBuilder = new GralCfgBuilder(cfgData, this, currentDir);
834    cfgBuilder.buildGui(log, 0);
835    this.designer = new GralCfgDesigner(cfgBuilder, this, log);  
836    this.bDesignMode = true;
837  }
838
839  /**Sets or resets the design mode. The design mode allows to change the content.
840   * @param mode
841   */
842  @Override public void setDesignMode(boolean mode){ this.bDesignMode = mode; }
843  
844  /**Saves the given configuration.
845   * @param dest
846   * @return
847   */
848  @Override public String saveCfg(Writer dest)
849  { cfgWriter = new GralCfgWriter(log);
850    String sError = cfgWriter.saveCfg(dest, cfgData);
851    return sError;
852  }
853  
854
855  
856  
857        /**This method is called whenever the left mouse is pressed on a widget, whiches 
858         * @param lastClickedWidgetInfo
859         */
860        public void setLastClickedWidget(GralWidget_ifc lastClickedWidgetInfo)
861        {
862                this.lastClickedWidget = lastClickedWidgetInfo;
863        }
864        
865        
866  /**Returns that widget which was clicked by mouse at last. This method is usefully for debugging
867   * and for special functionality. A widget which {@link GralWidget#setDataPath(String)} is initialized
868   * with "widgetInfo" is not captured for this operation. It means, if any user action method uses
869   * this method to get the last clicked widget, that widget itself have to be marked with
870   * <b>setDataPath("widgetInfo");</b> to prevent getting its own widget info.  
871   * @return The last clicked widget
872   */
873  public GralWidget_ifc getLastClickedWidget(){ return lastClickedWidget; }
874  
875  
876  /**Returns that widget which was clicked by mouse at last. This method is usefully for debugging
877   * and for special functionality. A widget which {@link GralWidget#setDataPath(String)} is initialized
878   * with "widgetInfo" is not captured for this operation. It means, if any user action method uses
879   * this method to get the last clicked widget, that widget itself have to be marked with
880   * <b>setDataPath("widgetInfo");</b> to prevent getting its own widget info.  
881   * @return The last clicked widget
882   */
883  //public String getLastClickedDatapath(){ return lastClickedWidget; }
884  
885  
886  /**Registers all user actions, which are able to use in Button etc.
887   * The name is related with the <code>userAction=</code> designation in the configuration String.
888   * @param name if it contains "<name>" then that is replace by the {@link GralUserAction#name}. 
889   *   You can give "<name>" only to set the action's name.
890   * @param action
891   */
892  @Override public void registerUserAction(String name, GralUserAction action)
893  { final String name1;
894    if(name.indexOf("<name>") >=0){
895      name1 = name.replace("<name>", action.name);
896    } else {
897      name1 = name;
898    }
899    userActions.put(name1, action);
900  }
901  
902  @Override public GralUserAction getRegisteredUserAction(String name)
903  {
904    return userActions.get(name);
905  }
906  
907  
908  void registerWidget(String name, GralWidget widgd) {
909    indexNameWidgets.put(name, widgd);
910  }
911  
912  void removeWidget(String name) {
913    indexNameWidgets.remove(name);
914  }
915  
916  @Override public void registerWidget(GralWidget widgd)
917  {
918    /*
919    PosThreadSafe pos = pos();
920    GralPanelContent panel = widgd.pos() !=null ? widgd.pos().panel : pos.pos.panel;
921    if(widgd.name != null){
922      indexNameWidgets.put(widgd.name, widgd);
923    }
924    //only widgets with size from right TODO percent size too.
925    boolean toResize = pos.pos.x.p1 < 0 || pos.pos.x.p2 <= 0 || pos.pos.y.p1< 0 || pos.pos.y.p2 <=0; 
926    panel.addWidget(widgd, toResize);
927    */
928  }
929  
930  
931  public void deregisterWidgetName(GralWidget widg)
932  {
933    if(widg.name != null){
934      indexNameWidgets.remove(widg.name);
935    }
936    
937  }
938  
939  /**Registers a panel to place the widgets. 
940   * After registration, this panel is the current one, stored in {@link #pos()} for this thread. 
941   * The panel can be selected with its name calling the {@link #selectPanel(String)} -routine
942   * @param key Name of the panel.
943   * @param panel The panel.
944   */
945  @Override public void registerPanel(GralPanelContent panel){
946    GralPanelContent exist = panels.get(panel.name);
947    if(exist !=null){
948      if(exist == panel) System.out.println("info: unnecessary registerPanel " + panel.name);
949      else System.err.println("info: faulty registerPanel " + panel.name);
950    }
951    panels.put(panel.name, panel);
952  }
953  
954  
955  public void setPosPanel(GralPanelContent panel) {
956    GralMng.PosThreadSafe pos = pos();
957    pos.pos.panel = panel;
958    //initialize the position because its a new panel. The initial position is the whole panel.
959    pos.pos.setFinePosition(0,0,0,0,0,0,0,0,0,'d',0,0, pos.pos);
960    sCurrPanel = panel.name;
961  }
962  
963  
964  /*package private*/ void deregisterPanel(GralPanelContent panel) {
965    if(sCurrPanel.equals(panel.name)) {
966      sCurrPanel = windPrimary.name;
967    }
968    panels.remove(panel.name);
969  }
970  
971  
972  /**Returns a Set of all fields, which are created to show.
973   * @return the set, never null, possible an empty set.
974   */
975  public Set<Map.Entry<String, GralWidget>> getShowFields()
976  {
977    Set<Map.Entry<String, GralWidget>> set =showFields.entrySet();
978    return set; //(Set<Entry<String, WidgetDescriptor>>)set;
979  }
980
981  
982  public Map<String, String> getAllValues()
983  {
984      Map<String, String> values = new TreeMap<String, String>();
985  for(GralWidget input: indexNameWidgets.values()){
986      String sValue = getValueFromWidget(input);
987    values.put(input.name, sValue);
988  }
989  return values;
990  }
991
992  @Override public String getValue(String sName)
993  { final String sValue;
994      GralWidget widgetDescr = indexNameWidgets.get(sName);
995      if(widgetDescr !=null){
996          sValue = getValueFromWidget(widgetDescr);
997      } else {
998          sValue = null;
999      }
1000      return sValue;
1001  }
1002  
1003
1004  
1005  /**It is a special routine for tabbedPanel.
1006   * The reason: If a new tab should add in {@link GralTabbedPanel#addGridPanel(String, String, int, int, int, int)}
1007   * then the mng is set to the tabbed panel.
1008   * @param tabbedPanel
1009   */
1010  /*package private*/public void setTabbedPanel(GralPanelContent tabbedPanel){
1011    pos().pos.panel = tabbedPanel;
1012  }
1013  
1014  
1015  public GralPanelContent getPanel(String name){
1016    return panels.get(name);
1017  }
1018  
1019  
1020  public GralWindow getPrimaryWindow(){ return windPrimary; }
1021  
1022  
1023  public GralPanelContent getCurrentPanel(){ return pos().pos.panel; }
1024  
1025  public GralPanelActivated_ifc actionPanelActivate = new GralPanelActivated_ifc()
1026  { @Override public void panelActivatedGui(List<GralWidget> widgetsP)
1027    {  //changeWidgets(widgetsP);
1028    }
1029  };
1030
1031
1032  
1033  protected void checkAdmissibility(boolean value){
1034    if(!value){
1035      throw new IllegalArgumentException("failure");
1036    }
1037  }
1038  
1039  
1040  private GralWidget findWidget(String name){
1041    GralWidget widg = indexNameWidgets.get(name);
1042    if(widg == null){
1043      log.sendMsg(0, "GuiMainDialog:setBackColor: unknown widget %s", name);
1044    }
1045    return widg;
1046  }
1047  
1048  
1049  /**Sets the background color of any widget. The widget may be for example:
1050   * <ul>
1051   * <li>a Table: Then a new line will be colored. 
1052   * <li>a Tree: Then a new leaf is colored.
1053   * <li>a Text-edit-widget: Then the field background color is set.
1054   * </ul>
1055   * The color is written into a queue, which is red in another thread. 
1056   * It may be possible too, that the GUI is realized in another module, maybe remote.
1057   * It means, that a few milliseconds should be planned before the change appears.
1058   * If the thread doesn't run or the remote receiver isn't present, 
1059   * than the queue may be overflowed or the request may be lost.
1060   *    
1061   * @param name The name of the widget, which was given by the add...()-Operation
1062   * @param ident A identifying number. It meaning depends on the kind of widget.
1063   *        0 means, insert on top.  Integer.MAXVALUE means, insert after the last element (append).
1064   * @param content The content to insert.
1065   * @return
1066   */
1067  @Override public void setBackColor(String name, int ix, int color)
1068  {
1069    GralWidget widg;
1070    if( (widg = findWidget(name)) !=null){
1071      widg.setBackColor(GralColor.getColor(color), ix);
1072    }
1073  } 
1074  
1075  
1076  @Override public void setText(String name, CharSequence text){
1077    GralWidget widg;
1078    if( (widg = findWidget(name)) !=null){
1079      widg.setText(text);
1080    }
1081  }
1082
1083  
1084  
1085  @Override public void setValue(String widget, Object visibleInfo, Object userData){
1086    GralWidget widg;
1087    if( (widg = findWidget(widget)) !=null){
1088      widg.setValue(0,0, visibleInfo, userData);
1089    }
1090    
1091  }
1092  
1093  @Override public void addText(String name, CharSequence text){
1094    GralWidget widg;
1095    if( (widg = findWidget(name)) !=null){
1096      if(widg instanceof GralTextBox_ifc){
1097        try{ ((GralTextBox)widg).append(text); }
1098        catch(IOException exc){ System.err.println("TODO"); }
1099      }
1100      else {
1101        System.err.println("GralMng - addText not possible;" + name);
1102      }
1103    }
1104  }
1105
1106  
1107  @Override public GralWidget addText(String sText, int origin, GralColor textColor, GralColor backColor)
1108  {
1109    GralLabel widgg = new GralLabel(null, sText, origin);
1110    widgg.setTextColor(textColor);
1111    widgg.setBackColor(backColor, 0);
1112    widgg.setToPanel(this); //Note: sets TextFont, don't call this.setToPanel
1113    return widgg;
1114  }
1115
1116  
1117  /** Adds a text field for showing or editing a text value.
1118   * 
1119   * @param sName The registering name
1120   * @param width Number of grid units for length
1121   * @param editable true than edit-able, false to show content 
1122   * @param prompt If not null, than a description label is shown
1123   * @param promptStylePosition Position and size of description label:
1124   *   upper case letter: normal font, lower case letter: small font
1125   *   'l' left, 't' top (above field) 
1126   * @return
1127   */
1128  @Override public GralTextField addTextField(String name, boolean editable, String prompt, String promptStylePosition){
1129    if(name !=null && name.charAt(0) == '$'){
1130      name = sCurrPanel + name.substring(1);
1131    }
1132    GralTextField widgg = new GralTextField(name);
1133    widgg.setPrompt(prompt, promptStylePosition);
1134    widgg.setEditable(editable);
1135    createImplWidget_Gthread(widgg);
1136    //SwtTextFieldWrapper.createTextField(widgg, this);   
1137    return widgg;
1138  }
1139
1140  
1141  
1142
1143  
1144/** Adds a text box for showing or editing a text in multi lines.
1145 * 
1146 * @param sName The registering name
1147 * @param width Number of grid units for length
1148 * @param editable true than edit-able, false to show content 
1149 * @param prompt If not null, than a description label is shown
1150 * @param promptStylePosition Position and size of description label:
1151 *   upper case letter: normal font, lower case letter: small font
1152 *   'l' left, 't' top (above field) 
1153 * @return
1154 */
1155@Override public GralTextBox addTextBox(String name, boolean editable, String prompt, char promptStylePosition)
1156{ 
1157  if(name !=null && name.charAt(0) == '$'){
1158    name = sCurrPanel + name.substring(1);
1159  }
1160  GralTextBox widgg = new GralTextBox(name);
1161  char[] prompt1 = new char[1];
1162  prompt1[0] = promptStylePosition;
1163  widgg.setPrompt(prompt, new String(prompt1));
1164  widgg.setEditable(editable);
1165  createImplWidget_Gthread(widgg);
1166  //SwtTextFieldWrapper.createTextField(widgg, this);   
1167  return widgg;
1168
1169}
1170
1171
1172
1173@Override public GralValueBar addValueBar(
1174  String sName
1175//, String sShowMethod
1176, String sDataPath
1177)
1178{ 
1179  GralValueBar wdgg = new GralValueBar(sName);
1180  wdgg.setDataPath(sDataPath);
1181  wdgg.setToPanel(this);
1182  return wdgg;
1183}
1184
1185
1186@Override public GralButton addButton(
1187    String sName
1188  , GralUserAction action
1189  , String sButtonText
1190  )
1191{ return addButton(sName, action, null, null, sButtonText);
1192}  
1193
1194@Override public GralButton addButton(
1195  String sName
1196, GralUserAction action
1197, String sCmd
1198//, String sShowMethod
1199, String sDataPath
1200, String sButtonText
1201  //, int height, int width
1202  //, String sCmd, String sUserAction, String sName)
1203)
1204{
1205  setNextPositionUnused();  //since 130523 it should be the valid one.
1206  float ySize = pos().pos.height();
1207  int xSize = (int)pos().pos.width();
1208  
1209  char size = ySize > 3? 'B' : 'A';
1210  if(sName == null){ sName = sButtonText; }
1211  GralButton widgButton = new GralButton(sName);
1212  //SwtButton widgButton = new SwtButton(sName, this, (Composite)pos().panel.getPanelImpl(), 0, size);
1213  if(action !=null)
1214    stop();
1215  widgButton.setActionChange(action);  //maybe null
1216  widgButton.setText(sButtonText);
1217  //in ctor: widgButton.setPanelMng(this);
1218  widgButton.sCmd = sCmd;
1219  widgButton.setDataPath(sDataPath);
1220  registerWidget(widgButton);
1221  createImplWidget_Gthread(widgButton);
1222  return widgButton;
1223}
1224
1225
1226
1227@Override public GralButton addSwitchButton(
1228  String sName
1229, GralUserAction action
1230, String sCmd
1231, String sDataPath
1232, String sButtonText
1233, String sColor0
1234, String sColor1
1235  //, int height, int width
1236  //, String sCmd, String sUserAction, String sName)
1237)
1238{
1239  int ySize = (int)pos().pos.height();
1240  int xSize = (int)pos().pos.width();
1241  
1242  char size = ySize > 3? 'B' : 'A';
1243  if(sName == null){ sName = sButtonText; }
1244  GralButton widgButton = new GralButton(sName);
1245  GralColor colorOff = GralColor.getColor(sColor0);
1246  GralColor colorOn = GralColor.getColor(sColor1);
1247  widgButton.setSwitchMode(colorOff, colorOn);
1248  widgButton.setActionChange(action);  //maybe null
1249  widgButton.setText(sButtonText);
1250  //widgButton.setPanelMng(this);
1251  widgButton.sCmd = sCmd;
1252  widgButton.setDataPath(sDataPath);
1253  registerWidget(widgButton);
1254  createImplWidget_Gthread(widgButton);
1255  return widgButton;
1256}
1257
1258
1259@Override public GralButton addSwitchButton(
1260  String sName
1261, String sButtonTextOff
1262, String sButtonTextOn
1263, GralColor colorOff
1264, GralColor colorOn
1265  //, int height, int width
1266  //, String sCmd, String sUserAction, String sName)
1267)
1268{
1269  int ySize = (int)pos().pos.height();
1270  int xSize = (int)pos().pos.width();
1271  
1272  char size = ySize > 3? 'B' : 'A';
1273  GralButton widgButton = new GralButton(sName);
1274  widgButton.setSwitchMode(colorOff, colorOn);
1275  widgButton.setSwitchMode(sButtonTextOff, sButtonTextOn);
1276  //in ctor: widgButton.setPanelMng(this);
1277  if(sName !=null){ registerWidget(widgButton); }
1278  createImplWidget_Gthread(widgButton);
1279  return widgButton;
1280}
1281
1282
1283
1284public GralButton addCheckButton(
1285  String sName
1286, String sButtonTextOn
1287, String sButtonTextOff
1288, String sButtonTextDisabled
1289, GralColor colorOn
1290, GralColor colorOff
1291, GralColor colorDisabled
1292)
1293{
1294  int ySize = (int)pos().pos.height();
1295  int xSize = (int)pos().pos.width();
1296  
1297  char size = ySize > 3? 'B' : 'A';
1298  GralButton widgButton = new GralButton(sName);
1299  widgButton.setSwitchMode(colorOff, colorOn, colorDisabled);
1300  widgButton.setSwitchMode(sButtonTextOff, sButtonTextOn, sButtonTextDisabled);
1301  //widgButton.setPanelMng(this);
1302  if(sName !=null){ registerWidget(widgButton); }
1303  createImplWidget_Gthread(widgButton);
1304  return widgButton;
1305}
1306
1307
1308
1309
1310@Override public GralLed addLed(
1311  String sName
1312//, String sShowMethod
1313, String sDataPath
1314)
1315{
1316  int ySize = (int)(pos().pos.height());
1317  int xSize = (int)(pos().pos.width());
1318
1319  GralLed gralLed = new GralLed(sName);
1320  //SwtLed swtLed = new SwtLed(gralLed, this);
1321  gralLed.setDataPath(sDataPath);
1322  //registerWidget(gralLed);
1323  gralLed.setToPanel(this);
1324  return gralLed;
1325}
1326
1327
1328  @Deprecated @Override public void setBackColor(GralWidget widg, int ix, int color)
1329  { widg.setBackColor(GralColor.getColor(color), ix);
1330  } 
1331  
1332  
1333  @Deprecated @Override public void setLineColor(GralWidget widg, int ix, int color)
1334  { widg.setLineColor(GralColor.getColor(color), ix);
1335  } 
1336  
1337  
1338  @Deprecated @Override public void setTextColor(GralWidget widg, int ix, int color)
1339  { widg.setTextColor(GralColor.getColor(color));
1340  } 
1341  
1342  
1343  
1344  /**Adds a line.
1345   * <br><br>To adding a line is only possible if the current panel is of type 
1346   * {@link SwtCanvasStorePanel}. This class stores the line coordinates and conditions 
1347   * and draws it as background if drawing is invoked.
1348   * 
1349   * @param colorValue The value for color, 0xffffff is white, 0xff0000 is red.
1350   * @param xa start of line relative to current position in grid units.
1351   *          The start is relative to the given position! Not absolute in window! 
1352   * @param ya start of line relative to current position in grid units.
1353   * @param xe end of line relative to current position in grid units.
1354   * @param ye end of line relative to current position in grid units.
1355   */
1356  @Deprecated @Override public void addLine(int colorValue, float xa, float ya, float xe, float ye){
1357    //if(pos().pos.panel.getPanelImpl() instanceof SwtCanvasStorePanel){
1358    if(pos().pos.panel.canvas !=null){
1359      GralColor color = propertiesGui.color(colorValue);
1360      int xgrid = propertiesGui.xPixelUnit();
1361      int ygrid = propertiesGui.yPixelUnit();
1362      int x1 = (int)((pos().pos.x.p1 + xa) * xgrid);
1363      int y1 = (int)((pos().pos.y.p1 - ya) * ygrid);
1364      int x2 = (int)((pos().pos.x.p1 + xe) * xgrid);
1365      int y2 = (int)((pos().pos.y.p1 - ye) * ygrid);
1366      //Any panel which is created in the SWT-implementation is a CanvasStorePanel.
1367      //This is because lines should be drawn.
1368      //((SwtCanvasStorePanel) pos().pos.panel.getPanelImpl()).store.drawLine(color, x1, y1, x2, y2);
1369      pos().pos.panel.canvas.drawLine(color, x1, y1, x2, y2);
1370      //furtherSetPosition((int)(xe + 0.99F), (int)(ye + 0.99F));
1371    } else {
1372      log.sendMsg(0, "GuiPanelMng:addLine: panel is not a CanvasStorePanel");
1373    }
1374  }
1375  
1376  
1377  @Override public void addLine(GralColor color, List<GralPoint> points){
1378    if(pos().pos.panel.canvas !=null){
1379      pos().pos.panel.canvas.drawLine(pos().pos, color, points);
1380    } else {
1381      log.sendMsg(0, "GralMng.addLine - panel is not a CanvasStorePanel;");
1382    }
1383  }
1384  
1385
1386  
1387  @Override public void setLed(GralWidget widg, int colorBorder, int colorInner)
1388  {
1389    ((GralLed)widg).setColor(GralColor.getColor(colorBorder), GralColor.getColor(colorInner));
1390  }
1391  
1392
1393  @Override public ConcurrentLinkedQueue<GralVisibleWidgets_ifc> getVisiblePanels()
1394  {
1395    return listVisiblePanels;
1396  }
1397
1398  @Override public GralVisibleWidgets_ifc getWidgetsPermanentlyUpdating(){
1399    ///
1400    return null;
1401  }
1402
1403  
1404  
1405  @Override public void setFocus(GralWidget widgd)
1406  {
1407    widgd.setFocus();
1408  }
1409  
1410  @Override public void notifyFocus(GralWidget widgd)
1411  {
1412    if(widgd.getDataPath() !=null) {  
1413      //regard only widgets with datapath, all other are not used.
1414      //Therewith preserve the last focused widget which has a datapath.
1415      synchronized(widgetsInFocus){
1416        widgetsInFocus.remove(widgd);  //remove it anywhere inside
1417        widgetsInFocus.add(0, widgd);     //add at start.
1418      }
1419    }
1420  }
1421  
1422  @Override public GralWidget getWidgetInFocus(){ return widgetsInFocus.size() >0 ? widgetsInFocus.get(0) : null; }
1423  
1424  @Override public List<GralWidget> getWidgetsInFocus(){ return widgetsInFocus; }
1425  
1426  @Override public int getColorValue(String sColorName){ return propertiesGui.getColorValue(sColorName); }
1427
1428  @Override public GralColor getColor(String sColorName){ return propertiesGui.color(getColorValue(sColorName)); }
1429
1430
1431
1432        GralUserAction actionShowWidgetInfos = new GralUserAction("actionShowWidgetInfos")
1433        {
1434
1435                @Override public boolean userActionGui(
1436                        String sCmd
1437                , GralWidget infos, Object... params
1438                )
1439                { 
1440                        if(lastClickedWidget !=null){
1441                                log.sendMsg(Report.info, "widget %s, datapath=%s"
1442                                        , GralMng.this.lastClickedWidget.getName()
1443                                        , GralMng.this.lastClickedWidget.getDataPath());
1444              return true;
1445                        } else {
1446                                log.sendMsg(0, "widgetInfo - no widget selected");
1447                        }
1448      return false;
1449                }
1450                
1451        };
1452        
1453        
1454        
1455        
1456  
1457  
1458  
1459  
1460
1461        
1462        
1463        
1464  
1465  /**Calculates the pixel position and size with a given GralPos for the given size of display appearance.
1466   * @param pos Given position
1467   * @param widthParentPixel width of the container. This value will be used if the position is given 
1468   *   from right with negative numbers.
1469   * @param heightParentPixel height of the container. This value will be used if the position is given 
1470   *   from bottom with negative numbers.
1471   * @param widthWidgetNat natural width of the component which will be positioning. 
1472   *   This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the xe-value
1473   * @param heightWidgetNat natural height of the component which will be positioning. 
1474   *   This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the ye-value
1475   * @return The position and size relative in the container. 
1476   * @deprecated, use {@link #calcWidgetPosAndSizeSwt(GralPos, int, int)} because the parent is known in pos.
1477   */
1478  public GralRectangle calcWidgetPosAndSize(GralPos pos,
1479    int widthParentPixel, int heightParentPixel,
1480    int widthWidgetNat, int heightWidgetNat
1481  ){ return pos.calcWidgetPosAndSize(propertiesGui, widthParentPixel, heightParentPixel
1482                                    , widthWidgetNat, heightWidgetNat);
1483  }
1484  
1485  
1486  
1487
1488  
1489  
1490  
1491  /* (non-Javadoc)
1492   * @see org.vishia.gral.ifc.GralMngBuild_ifc#addFileSelectField(java.lang.String, java.util.List, java.lang.String, java.lang.String, java.lang.String)
1493   */
1494  @Override public GralTextField addFileSelectField(String name, List<String> listRecentFiles
1495    , String startDirMask, String prompt, String promptStylePosition)
1496  { //int xSize1 = xSize;
1497    //The macro widget consists of more as one widget. Position the inner widgets:
1498    GralPos posAll = getPositionInPanel(); //saved whole position.
1499    //reduce the length of the text field:
1500    setPosition(GralPos.same, GralPos.same, GralPos.same, GralPos.same -2.0F, 1, 'r');
1501    
1502    //xSize -= ySize;
1503    GralTextField widgd = addTextField(name, true, prompt, promptStylePosition );
1504    setSize(posAll.height(), 2.0F);
1505    //xPos += xSize;
1506    //xSize = ySize;
1507    GralWidget widgdSelect = addButton(name + "<", actionFileSelect,  "<");
1508    FileSelectInfo fileSelectInfo = new FileSelectInfo(name, listRecentFiles, startDirMask, widgd);
1509    widgdSelect.setContentInfo(fileSelectInfo); 
1510    //xSize = xSize1;
1511    pos().pos.set(posAll);  //the saved position.
1512    return widgd;
1513  }
1514
1515  
1516  
1517  GralUserAction actionFileSelect = new GralUserAction("actionFileSelect")
1518  { @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params)
1519    { assert(false);
1520      return userActionGui(null, infos);
1521    }
1522  
1523    @Override public boolean userActionGui(int actionCode, GralWidget widgg, Object... params) 
1524    {
1525      if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){  //supress both mouse up and down reaction
1526        FileSelectInfo fileSelectInfo = (FileSelectInfo)widgg.getContentInfo();
1527        if(fileSelectInfo.listRecentFiles !=null){
1528          stop();
1529        } else {
1530          fileSelectInfo.dialogFile.show(fileSelectInfo.sRootDir, fileSelectInfo.sLocalDir
1531            , fileSelectInfo.sMask, fileSelectInfo.sTitle);
1532          String fileSelect = fileSelectInfo.dialogFile.getSelection(); 
1533          if(fileSelect !=null){
1534            fileSelectInfo.dstWidgd.setText(fileSelect);
1535            //fileSelectInfo.dstWidgd.setValue(cmdSet, 0, fileSelect);
1536            GralWidget_ifc.ActionChange action = fileSelectInfo.dstWidgd.getActionChange(GralWidget_ifc.ActionChangeWhen.onEnter); 
1537            if(action !=null){
1538              Object[] args = action.args();
1539              if(args == null){ action.action().exec(KeyCode.menuEntered, fileSelectInfo.dstWidgd, fileSelect); }
1540              else { action.action().exec(KeyCode.menuEntered, fileSelectInfo.dstWidgd, args, fileSelect); }
1541            }
1542          }
1543        }
1544      }
1545      return true;      
1546    }; 
1547    
1548  };
1549  
1550  
1551
1552  /**Action to edit the properties of one widget in the graphic. */
1553  public GralUserAction actionDesignEditField = new GralUserAction("actionDesignEditField")
1554  { 
1555    @Override public boolean userActionGui(int key, GralWidget infos, Object... params)
1556    {
1557      GralWidget widgd = getWidgetInFocus();
1558      if(widgd !=null){
1559        designer.editFieldProperties(widgd, null);
1560      }
1561      return true;
1562    }
1563    
1564    @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params)
1565    {
1566      GralWidget widgd = getWidgetInFocus();
1567      if(widgd !=null){
1568        designer.editFieldProperties(widgd, null);
1569      }
1570      return true;
1571    }
1572  };
1573
1574
1575  
1576
1577  /**Action to edit the properties of one widget in the graphic. */
1578  public GralUserAction actionReadPanelCfg = new GralUserAction("actionReadPanelCfg")
1579  { @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params)
1580    {
1581      //GralPanelContent currPanel = 
1582      GralWidget widgd = getWidgetInFocus();
1583      if(widgd !=null){
1584        GralPanelContent panel = widgd.pos().panel;
1585        String namePanel = panel.name;
1586        cfgBuilder.buildGui(log, 0);
1587        //designer.editFieldProperties(widgd, null);
1588      }
1589      return true;
1590    }
1591  };
1592
1593
1594  
1595
1596  
1597  
1598  /**It will be called only at the GUI-implementation level. TODO protected and delegation.
1599   * @param widgd
1600   * @param xy
1601   */
1602  public void pressedLeftMouseDownForDesign(GralWidget widgd, GralRectangle xy)
1603  { designer.pressedLeftMouseDownForDesign(widgd, xy);
1604  }
1605  
1606  
1607  /**It will be called only at the GUI-implementation level. TODO protected and delegation.
1608   * @param widgd
1609   * @param xy
1610   */
1611  public void releaseLeftMouseForDesign(GralWidget widgd, GralRectangle xy, boolean bCopy)
1612  { designer.releaseLeftMouseForDesign(widgd, xy, bCopy);
1613  }
1614  
1615  public void markWidgetForDesign(GralWidget widgg){
1616    designer.markWidgetForDesign(widgg);
1617  }
1618  
1619  /**It will be called only at the GUI-implementation level. TODO protected and delegation.
1620   * @param widgd
1621   * @param xy
1622   */
1623  public void XXXpressedRightMouseDownForDesign(GralWidget widgd, GralRectangle xy)
1624  { designer.editFieldProperties(widgd, xy);
1625  }
1626  
1627  
1628  
1629  public void initCfgDesigner(){
1630    designer.setToPanel();
1631  }
1632  
1633  @Override public GralInfoBox createTextInfoBox(String name, String title)
1634  {
1635    return GralInfoBox.createTextInfoBox(this, name, title);
1636  }
1637
1638  
1639  @Override public GralInfoBox createHtmlInfoBox(String posString, String name, String title, boolean onTop)
1640  {
1641    return GralInfoBox.createHtmlInfoBox(posString, name, title, onTop);
1642  }
1643
1644  
1645  /**Adds a text to the current panel at given position with standard colors, left origin.
1646   * The size of text is calculated using the height of positioning values.
1647   * see also {@link #addText(String, int, GralColor, GralColor)},
1648   * {@link #addTextField(String, boolean, String, String)}
1649   * @param text
1650   */
1651  @Override public GralWidget addText(String text)
1652  { //return addText(text, 0, GralColor.getColor("bk"), GralColor.getColor("wh"));
1653    return addText(text, 0, GralColor.getColor("bk"), propertiesGui.colorBackground_);
1654  }
1655  
1656  
1657  
1658  
1659  
1660  @Override public void repaint()
1661  {
1662    assert(false);
1663    //gralDevice.redraw();
1664  }
1665  
1666  
1667  
1668  @Override public void repaintCurrentPanel()
1669  {
1670    pos().pos.panel.repaint();
1671  }
1672  
1673  
1674
1675  
1676  
1677  @Override public void refreshCurvesFromVariable(VariableContainer_ifc container){
1678    for(GralCurveView_ifc curve : curveContainer){
1679      if(curve.isActiv()){
1680        curve.refreshFromVariable(container);
1681      }
1682    }
1683  }
1684  
1685  @Override public boolean remove(GralWidget widget)
1686  { widget.remove();  //remove instance by Garbage collector.
1687    return true;
1688    
1689  }
1690
1691  
1692
1693  @Override public void writeLog(int msgId, Exception exc)
1694  {
1695    String sMsg = exc.toString();
1696    StackTraceElement[] stackTrace = exc.getStackTrace();
1697    String sWhere = stackTrace[0].getFileName() + ":" + stackTrace[0].getLineNumber();
1698    log.sendMsg(msgId, sMsg + " @" + sWhere);
1699  }
1700  
1701  
1702  
1703  public final GralUserAction actionHelp = new  GralUserAction("actionHelp")
1704  { 
1705    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params)
1706    { infoHelp.activate();
1707      infoHelp.setFocus(); //setWindowVisible(true);
1708      return true; 
1709  } };
1710
1711
1712
1713  
1714  
1715  /**This standard Gral focus listener is the base class for the common implementation layer focus listener.
1716   * The both methods {@link #focusGainedGral(GralWidget)} and {@link #focusLostGral(GralWidget)} will be invoked
1717   * with that GralWidget, which is referred by the implementation layer widgets data.
1718   * <br><br>
1719   * The GralMng implementation classes should offer a focus listener for common usage, see 
1720   * {@link org.vishia.gral.swt.SwtMng.SwtMngFocusListener} and its instance {@link org.vishia.gral.swt.SwtMng.focusListener}. 
1721   * That reference and class is protected and therewith package visible because only swt implementations needs it. 
1722   * An implementation widget class can use this instance of SwtMng.focusListener immediately for standard behavior.
1723   * The standard behavior is realized in this class, see {@link GralMngFocusListener#focusGainedGral(GralWidget)}.
1724   * <br><br>
1725   * For enhanced functionality of a focus listener the implementation layer SwtFocusListener class can be enhanced.
1726   * That is realized for example in {@link org.vishia.gral.swt.SwtTextFieldWrapper}. That's focus listener should 
1727   * update the text in the widget with the gral text store {@link GralWidget.DynamicData#displayedText}
1728   * on focus gained, and overtake a changed content on focus lost. Adequate it is on all edit-able widgets.
1729   * The SwtTextFieldWrapper.TextFieldFocusListener.focusGained(...) and focusLost(...) methods executes the special
1730   * functionality. After them 'super.focusGained/Lost(ev);' is in called to execute the standard behavior.
1731   */
1732  public class GralMngFocusListener
1733  {
1734    
1735    /**Standard action on focus lost:
1736     * @param widgg
1737     */
1738    public void focusLostGral(GralWidget widgg){
1739      GralWidget.ImplAccess.setFocused(widgg, false);  //denotes that the GralWidget has lost the focus
1740      widgg.repaint();  //maybe changed outfit on focus lost.
1741      if(widgg.cfg.actionFocused !=null){ widgg.cfg.actionFocused.exec(KeyCode.focusLost, widgg); }
1742      //CharSequence text = Assert.stackInfo("", 1, 5);
1743      //System.out.println("GralMng - widget focus lost;" + widgg.name + text);
1744    }
1745
1746    /**Standard action on focus gained:
1747     * <ul>
1748     * <li>Sets the html help into the {@link GralMng#setApplicationAdapter(GralMngApplAdapter_ifc)} if given.
1749     * <li> invokes the {@link GralWidget#setActionFocused(GralUserAction)} if given.
1750     * <li>invokes {@link GralMng#notifyFocus(GralWidget)} to detect the {@link GralMng#getWidgetInFocus()}.
1751     * </ul>
1752     * @param widgg
1753     */
1754    public void focusGainedGral(GralWidget widgg){
1755      GralMng.this.notifyFocus(widgg);
1756      GralWidget.ImplAccess.setFocused(widgg, true);  //denotes that the GralWidget has gained the focus
1757      widgg.repaint();  //maybe changed outfit on focus gained.
1758      String htmlHelp = widgg.getHtmlHelp();
1759      if(htmlHelp !=null && applAdapter !=null){
1760        applAdapter.setHelpUrl(htmlHelp);
1761      }
1762      if(widgg.cfg.actionFocused !=null){ widgg.cfg.actionFocused.exec(KeyCode.focusGained, widgg); }
1763    }
1764  }
1765  
1766  
1767  /**This instance can be used if any other focus listener is necessary for any implementation widget.
1768   * The standard behavior for GralWidget is supported using this aggregate.
1769   * In Opposite a full ready to use focus listener based on this class in the implementation layer,
1770   * see {@link org.vishia.gral.swt.SwtMng.SwtMngFocusListener}.
1771   */
1772  public GralMngFocusListener gralFocusListener = new GralMngFocusListener();
1773  
1774  /**This inner class is public only because the implementation uses it. It is not public for applications.
1775   *
1776   *
1777   */
1778  public class InternalPublic{
1779    public GralKeyListener gralKeyListener = new GralKeyListener(GralMng.this);
1780  }
1781  
1782  /**Implementation specific fields.
1783   * 
1784   */
1785  public final InternalPublic _impl = new InternalPublic();
1786  
1787  
1788  /**This class is used only for the implementation level of the graphic. It is not intent to use
1789   * by any application. It is public because the implementation level should accesses it.
1790   * It is the super class for several Graphic-Adapters (AWT/Swing, SWT etc.).
1791   * 
1792   * 
1793   */
1794  public static abstract class ImplAccess {
1795    public GralMng mng;
1796    
1797    
1798    public ImplAccess(GralMng mng, GralGridProperties props){
1799      this.mng = mng;
1800      mng.setProperties(props);
1801      mng.impl = this;
1802    }
1803    
1804    protected GralPos pos(){ return mng.pos().pos; }
1805
1806    protected String sCurrPanel(){ return mng.sCurrPanel; }
1807    
1808    protected void listVisiblePanels_add(GralTabbedPanel panel){ mng.listVisiblePanels.add(panel); }
1809    
1810    public abstract Object getCurrentPanel();
1811    
1812    protected GralWidget indexNameWidgets(String name){ return mng.indexNameWidgets.get(name); }
1813    
1814    protected GralUserAction userMainKeyAction(){ return mng.userMainKeyAction; }
1815    
1816    
1817    public abstract void createImplWidget_Gthread(GralWidget widgg);
1818    /**Creates the context menu for the given widget for right-mouse pressing.
1819     * This method is invoked only in {@link GralWidget#getContextMenu()} whereby an existing
1820     * context menu is stored in the {@link GralWidget#contextMenu} association. 
1821     * The widget have to be set to panel already, an implementation widget have to be existing.
1822     * It means {@link GralWidget#getWidgetImplementation()} should be return that instance
1823     * where the menu is to be added.
1824     * This method is package protected because it should only be called internally.
1825     * @param widg The widget
1826     */
1827    protected abstract GralMenu createContextMenu(GralWidget widgg);
1828    
1829    
1830    /**Creates a box inside the current panel to hold some widgets.
1831     * 
1832     * @return
1833     * @since 2010-05-01
1834     */
1835    protected abstract GralPanelContent createCompositeBox(String name);
1836   
1837    /**Creates an independent grid panel which is managed by this.
1838     * The panel can be associated to any graphic frame.
1839     * @param namePanel
1840     * @param backGround
1841     * @param xG
1842     * @param yG
1843     * @param xS
1844     * @param yS
1845     * @return
1846     */
1847    protected abstract GralPanelContent createGridPanel(String namePanel, GralColor backGround, int xG, int yG, int xS, int yS);
1848
1849    
1850    public abstract boolean remove(GralPanelContent compositeBox);
1851    
1852    /**Creates the menu bar for the given window.
1853     * This method is invoked only in {@link GralWindow#getMenuBar()} whereby an existing
1854     * menu bar is stored in the {@link GralWindow#menuBarGral} association. 
1855     * @param windg The window
1856     */
1857    protected abstract GralMenu createMenuBar(GralWindow windg);
1858    
1859    
1860    @Deprecated public abstract GralWindow createWindow(String name, String title, int windProps);
1861    
1862    
1863    protected abstract void createSubWindow(GralWindow windowGral);
1864    
1865    public abstract GralTabbedPanel addTabbedPanel(String namePanel, GralPanelActivated_ifc user, int property);
1866    
1867    @Deprecated public abstract GralWidget addText(String sText, char size, int color);
1868    
1869    
1870    public abstract GralHtmlBox addHtmlBox(String name);
1871    
1872    public abstract Object addImage(String sName, InputStream imageStream, int height, int width, String sCmd);
1873    
1874    public abstract GralWidget addSlider(
1875        String sName
1876        , GralUserAction action
1877        , String sShowMethod
1878        , String sDataPath
1879        );
1880    
1881    
1882    public abstract GralCurveView addCurveViewY(String sName, int nrofXvalues, GralCurveView.CommonCurve common);
1883    
1884    
1885    public abstract GralWidget addFocusAction(String sName, GralUserAction action, String sCmdEnter, String sCmdRelease);
1886
1887    public abstract void addFocusAction(GralWidget widgetInfo, GralUserAction action, String sCmdEnter, String sCmdRelease);
1888    
1889    
1890    @Deprecated public abstract GralTable addTable(String sName, int height, int[] columnWidths);
1891    
1892    public abstract GralFileDialog_ifc createFileDialog();
1893    
1894    protected abstract GralMenu XXXaddPopupMenu(String sName);
1895    
1896
1897    /**Calculates the bounds of a widget with a given pos independent of this {@link #pos}.
1898     * This method is a part of the implementing GralMng because the GralPos is not implemented for
1899     * any underlying graphic system and the {@link #propertiesGuiSwt} are used.
1900     * This method is not intent to use from an application, only for implementing methods of Gral.
1901     * Therefore it isn't a member of the {@link GralWindowMng_ifc} and {@link GralMngBuild_ifc}
1902     * It is possible to tune the bounds after calculation, for example to enhance the width if a text
1903     * is larger then the intended position. 
1904     * @param pos The position.
1905     * @param widthwidgetNat The natural size of the component.
1906     * @param heigthWidgetNat The natural size of the component.
1907     * @return A rectangle with position and size.
1908     */
1909    public abstract GralRectangle calcWidgetPosAndSize(GralPos pos, int widthwidgetNat, int heigthWidgetNat);
1910
1911    @Deprecated public abstract String getValueFromWidget(GralWidget widgd);
1912    
1913    /**Gets the color of the graphic implementation (swt.Color, swing.TODO)
1914     * Either the implementation color instance is stored already in the GralColor,
1915     * or it will be created, stored in GralColor and returned here.
1916     * @param color The Color.
1917     * @return Instance of the implementation color.
1918     */
1919    public abstract Object getColorImpl(GralColor color);
1920    
1921    /**Forces the redrawing for all set samples. It should be called after { @link #setSampleCurveViewY(String, float[])}.
1922     * @param sName The name of the widget.
1923     */
1924    protected abstract void redrawWidget(String sName);
1925    
1926    
1927    
1928    /**Forces the resizing of the given widged. 
1929     * @param widgd the widget
1930     */
1931    protected abstract void resizeWidget(GralWidget widgd, int xSizeParent, int ySizeParent);
1932    
1933    
1934    /**Adds a sampling value set.
1935     * @param sName The registered name
1936     * @param values The values.
1937     */
1938    protected abstract void setSampleCurveViewY(String sName, float[] values);
1939    
1940    /**Shows the context menu of any widget independent of the internal right-mouse invocation.
1941     * @param widg The widget.
1942     * @return true if the widget have a context menu.
1943     */
1944    protected abstract boolean showContextMenuGthread(GralWidget widg);
1945    
1946    
1947    /**Sets a given and registered window visible at the given position and size or set it invisible.
1948     * <br>
1949     * A window can be created by invoking {@link org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(String, boolean)}
1950     * in the build phase of the gui. It can be hidden because it is not necessary to show and operate with them.
1951     * In a adequate phase of operate it can be shown and focused.
1952     * <br>
1953     * The position is given relative to that panel,
1954     * which is stored in {@link GralPos#panel}. To get a position instance,
1955     * you can set a position invoking 
1956     * <ul>
1957     * <li>{@link org.vishia.gral.ifc.GralMngBuild_ifc#selectPanel(String)}
1958     * <li>{@link org.vishia.gral.ifc.GralMngBuild_ifc#setPosition(float, float, float, float, int, char)}
1959     * <li>GralGridPos pos = {@link org.vishia.gral.ifc.GralMngBuild_ifc#getPositionInPanel()}.
1960     * </ul>
1961     * That can be done in the build phase of the graphic. The position can be stored. It is possible to adjust
1962     * the position relative to the unchanged panel by changing the values of {@link GralPos#x} etc.
1963     * It is possible too to change the Panel which relates to the position. Then the grid managing instance 
1964     * have to be known via the {@link org.vishia.gral.ifc.GralMngBuild_ifc} to select a panel.
1965     * The panels may be moved or resized. With the knowledge of the relative position of the window in respect to a panel
1966     * of the parent window, the window can be placed onto a proper position of the whole display.
1967     *   
1968     * @param window the instance of the window wrapper.
1969     * @param atPos If null then hide the window. If not null then show the window. 
1970     *        The position and size of the window is given related to any panel of any other window. 
1971     *         
1972     * @return true if it is visible.
1973     * @deprecated
1974     */
1975    @Deprecated
1976    protected abstract boolean XXXsetWindowsVisible(GralWindow_ifc window, GralPos atPos);
1977    
1978  }
1979  
1980  
1981  
1982
1983  void stop(){}
1984
1985  
1986  protected GralMenu createContextMenu(GralWidget widg){ return impl.createContextMenu(widg); }
1987  
1988  protected GralMenu createMenuBar(GralWindow windg){ return impl.createMenuBar(windg); }
1989
1990  
1991  @Override public GralTabbedPanel addTabbedPanel(String namePanel, GralPanelActivated_ifc user,
1992      int properties)
1993  {
1994    return impl.addTabbedPanel(namePanel, user, properties);
1995  }
1996
1997  @Override public GralWidget addSlider(String sName, GralUserAction action, String sShowMethod,
1998      String sDataPath)
1999  {
2000    // TODO Auto-generated method stub
2001    return impl.addSlider(sName, action, sShowMethod, sDataPath);
2002  }
2003
2004  @Override @Deprecated public GralTable addTable(String sName, int height, int[] columnWidths)
2005  {
2006    // TODO Auto-generated method stub
2007    return impl.addTable(sName, height, columnWidths);
2008  }
2009
2010  @Override @Deprecated public GralWidget addText(String sText, char size, int color)
2011  {
2012    // TODO Auto-generated method stub
2013    return impl.addText(sText, size, color);
2014  }
2015
2016  @Override public Object addImage(String sName, InputStream imageStream, int height, int width, String sCmd)
2017  {
2018    // TODO Auto-generated method stub
2019    return impl.addImage(sName, imageStream, height, width, sCmd);
2020  }
2021
2022  @Override public GralHtmlBox addHtmlBox(String name)
2023  {
2024    // TODO Auto-generated method stub
2025    return impl.addHtmlBox(name);
2026  }
2027
2028  @Override public GralCurveView addCurveViewY(String sName, int nrofXvalues, CommonCurve common)
2029  {
2030    // TODO Auto-generated method stub
2031    return impl.addCurveViewY(sName, nrofXvalues, common);
2032  }
2033
2034  @Override public GralWidget addFocusAction(String sName, GralUserAction action, String sCmdEnter,
2035      String sCmdRelease)
2036  {
2037    // TODO Auto-generated method stub
2038    return addFocusAction(sName, action, sCmdEnter, sCmdRelease);
2039  }
2040
2041  @Override public void addFocusAction(GralWidget widgetInfo, GralUserAction action, String sCmdEnter,
2042      String sCmdRelease)
2043  {
2044    // TODO Auto-generated method stub
2045    impl.addFocusAction(widgetInfo, action, sCmdEnter, sCmdRelease);
2046  }
2047
2048  @Override public GralPanelContent createCompositeBox(String name)
2049  {
2050    // TODO Auto-generated method stub
2051    return impl.createCompositeBox(name);
2052  }
2053
2054  @Override public GralPanelContent createGridPanel(String namePanel, GralColor backGround, int xG, int yG,
2055      int xS, int yS)
2056  {
2057    // TODO Auto-generated method stub
2058    return impl.createGridPanel(namePanel, backGround, xG, yG, xS, yS);
2059  }
2060
2061  @Override public boolean remove(GralPanelContent compositeBox)
2062  {
2063    // TODO Auto-generated method stub
2064    return impl.remove(compositeBox);
2065  }
2066
2067
2068  /**Must only invoke from the Main window close listener. */
2069  public static void closeGral() {
2070    singleton.gralDevice.bExit = true; 
2071  }
2072  
2073
2074
2075  /* (non-Javadoc)
2076   * @see org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(java.lang.String, java.lang.String, int)
2077   * @deprecated use {@link GralWindow#GralWindow(String, String, String, int)} and then {@link GralWidget#createImplWidget_Gthread()}
2078   *   with this window.
2079   */
2080  @Override @Deprecated public GralWindow createWindow(String name, String title, int windProps)
2081  { GralPos pos = pos().pos;  //without clone.
2082    String sPos = pos.posString(); 
2083    GralWindow windowGral = new GralWindow(sPos, name, title, windProps);
2084    impl.createSubWindow(windowGral);
2085    return windowGral;
2086  }
2087
2088  @Override public GralFileDialog_ifc createFileDialog()
2089  {
2090    // TODO Auto-generated method stub
2091    return impl.createFileDialog();
2092  }
2093
2094  @Override public void redrawWidget(String sName)
2095  {
2096    // TODO Auto-generated method stub
2097    impl.redrawWidget(sName);
2098  }
2099
2100  @Override public void resizeWidget(GralWidget widgd, int xSizeParent, int ySizeParent)
2101  {
2102    // TODO Auto-generated method stub
2103    impl.resizeWidget(widgd, xSizeParent, ySizeParent);
2104  }
2105
2106  @Override public boolean XXXsetWindowsVisible(GralWindow_ifc window, GralPos atPos)
2107  {
2108    // TODO Auto-generated method stub
2109    return false;
2110  }
2111
2112  @Override public void setSampleCurveViewY(String sName, float[] values)
2113  {
2114    impl.setSampleCurveViewY(sName, values);
2115  }
2116        
2117
2118        
2119}