    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}