    001package org.vishia.gral.swt;
    002
    003import java.io.InputStream;
    004import java.util.Map;
    005
    006import org.eclipse.swt.SWT;
    007import org.eclipse.swt.events.FocusEvent;
    008import org.eclipse.swt.events.FocusListener;
    009import org.eclipse.swt.events.MenuDetectEvent;
    010import org.eclipse.swt.events.MenuDetectListener;
    011import org.eclipse.swt.events.MouseListener;
    012import org.eclipse.swt.events.SelectionEvent;
    013import org.eclipse.swt.events.SelectionListener;
    014import org.eclipse.swt.graphics.Color;
    015import org.eclipse.swt.graphics.Font;
    016import org.eclipse.swt.graphics.Image;
    017import org.eclipse.swt.graphics.ImageData;
    018import org.eclipse.swt.graphics.Point;
    019import org.eclipse.swt.graphics.Rectangle;
    020import org.eclipse.swt.widgets.Button;
    021import org.eclipse.swt.widgets.Composite;
    022import org.eclipse.swt.widgets.Control;
    023import org.eclipse.swt.widgets.Display;
    024import org.eclipse.swt.widgets.Event;
    025import org.eclipse.swt.widgets.Label;
    026import org.eclipse.swt.widgets.Listener;
    027import org.eclipse.swt.widgets.Menu;
    028import org.eclipse.swt.widgets.Shell;
    029import org.eclipse.swt.widgets.Slider;
    030import org.eclipse.swt.widgets.TabFolder;
    031import org.eclipse.swt.widgets.Table;
    032import org.eclipse.swt.widgets.TableItem;
    033import org.eclipse.swt.widgets.Text;
    034import org.eclipse.swt.widgets.Widget;
    035import org.vishia.gral.base.GralButton;
    036import org.vishia.gral.base.GralCurveView;
    037import org.vishia.gral.base.GralGraphicThread;
    038import org.vishia.gral.base.GralGridProperties;
    039import org.vishia.gral.base.GralHtmlBox;
    040import org.vishia.gral.base.GralLed;
    041import org.vishia.gral.base.GralMenu;
    042import org.vishia.gral.base.GralPos;
    043import org.vishia.gral.base.GralTable;
    044import org.vishia.gral.base.GralValueBar;
    045import org.vishia.gral.base.GralWidget;
    046import org.vishia.gral.base.GralMng;
    047import org.vishia.gral.base.GralPanelContent;
    048import org.vishia.gral.base.GralWindow;
    049import org.vishia.gral.base.GralTabbedPanel;
    050import org.vishia.gral.base.GralPanelActivated_ifc;
    051import org.vishia.gral.base.GralTextBox;
    052import org.vishia.gral.base.GralTextField;
    053import org.vishia.gral.cfg.GralCfgBuilder;
    054import org.vishia.gral.ifc.GralCanvasStorage;
    055import org.vishia.gral.ifc.GralColor;
    056import org.vishia.gral.ifc.GralFileDialog_ifc;
    057import org.vishia.gral.ifc.GralImageBase;
    058import org.vishia.gral.ifc.GralMng_ifc;
    059import org.vishia.gral.ifc.GralRectangle;
    060import org.vishia.gral.ifc.GralWindow_ifc;
    061import org.vishia.gral.ifc.GralUserAction;
    062import org.vishia.gral.ifc.GralWidget_ifc;
    063import org.vishia.gral.widget.GralHorizontalSelector;
    064import org.vishia.gral.widget.GralLabel;
    065import org.vishia.gral.widget.GralPlotArea;
    066import org.vishia.msgDispatch.LogMessage;
    067
    068
    069
    070
    071
    072/**This class manages the building of Panels with GUI-Elements for example for a Dialog Box
    073 * The container can be visibilized as a part of another container of any window.
    074 * An example is given in {@link org.vishia.mainGuiSwt.SampleGuiSwtButtonInput}
    075 * <br><br>
    076 * The positions on the display are based on grid units.
    077 * The grid-size (number of x- and y-pixel per grid unit) is able to set, so a more large
    078 * or a more small representation of the graphic is shown, depending on the display point size,
    079 * the distance to view or personal defaults.
    080 * <br><br>
    081 * A layout manager like flow-layout is not used here. The user sets fix positions in the grid units.
    082 * A grid unit is a half-small-line in the vertical direction and about a small character width
    083 * in the x-direction. So a closed-to-user-thinking position is able to set for any component.
    084 * It is like rows or lines and columns.
    085 * An automatically layout managing using self-deciding positioning of any components is not done.
    086 * But a next added component may be positioned right from the previous or below the previous
    087 * without manually calculation and setting of the position. It simplifies positioning.
    088 * <br><br>
    089 * This class supports setting of values of shown components with symbolic access (String-name)
    090 * in runtime
    091 * and selecting of button-actions and data-container while creating with symbolic access
    092 * to the action-instance or the data-container. This property is used especially
    093 * by the text-script-controlled built of a dialog widget using the {@link GralCfgBuilder},
    094 * but it is able to simplify the access to data and actions elsewhere too.
    095 * <br><br>
    096 * <br><br>
    097 * <br><br>
    098 * <br><br>
    099 *
    100 * @author Hartmut Schorrig
    101 *
    102 */
    103//GralMng.ImplAccess
    104public class SwtMng extends GralMng.ImplAccess // implements GralMngBuild_ifc, GralMng_ifc
    105//GuiShellMngIfc<Control>
    106{
    107  //private static final long serialVersionUID = -2547814076794969689L;
    108
    109        /**Version, history and license. The version number is a date written as yyyymmdd as decimal number.
    110         * Changes:
    111         * <ul>
    112   * <li>2016-09-02 Hartmut chg: Some {@link GralPanelContent#GralPanelContent(String, String, char)} and {@link GralTabbedPanel#GralTabbedPanel(String, String, GralPanelActivated_ifc, int)}
    113   *   was invoked with "@" for the posString without any more posString information. That is false. The idea was: Set the current panel. But that does not run.
    114   *   See changes on {@link GralMng} on 2016-09-02.
    115   * <li>2013-12-21 Hartmut new: {@link #createImplWidget_Gthread(GralWidget)} instanciates all widget types.
    116         * <li>2012-07-13 Hartmut chg: {@link #resizeWidget(GralWidget, int, int)} can work with more as one widget implementation.
    117         *   But it isn't test and used yet. Size of any implementation widget?
    118         * <li>2012-03-17 Hartmut chg: some changes for {@link #setPosAndSizeSwt(Control, int, int)} etc.
    119         * <li>2012-01-26 Hartmut chg: prevent some error messages which are unnecessary.
    120         * <li>2012-01-01 Hartmut new: The {@link #setInfoGthread(GralWidget, int, int, Object, Object)} routine
    121         *   uses the {@link SwtSetValue_ifc} capability to associate cmd to types of widgets. Yet used only for {@link SwtSubWindow}.
    122         * <li>2011-12-03 Hartmut new: {@link #setInfoGthread(GralWidget, int, int, Object, Object)} catches
    123         *   any exception, before: An exception causes aborting the graphic thread.
    124         * <li>2011-12-03 Hartmut chg: {@link #addLed(String, String, String)} now uses {@link GralLed}.
    125         * <li>2011-12-03 Hartmut new: {@link #swtKeyListener} as base for all fields.
    126         * <li>2011-11-12 Hartmut chg: {@link #calcPositionOfWindow(GralPos)} improved
    127         * <li>2011-08-13 Hartmut chg: New routines for store and calculate the position to regard large widgets.
    128         * <li>2011-06-17 Hartmut getValueFromWidget(): Table returns the whole selected line, cells separated with tab.
    129         *     The String-return.split("\t") separates the result to the cell values.
    130         * <li>2011-05-08 Hartmut new; {@link GralMng_ifc#cmdClear} used to clear a whole swt.Table, commonly using: clear a content of widget.
    131   * <li>2010-12-02 Hartmut: in method insertInfo((): call of checkAdmissibility() for some input parameter,
    132         *     elsewhere exceptions may be possible on evaluating the inserted info in doBeforeDispatching().
    133         *     There the causer isn't found quickly while debugging.
    134         * <li>2010-12-02 Hartmut: Up to now this version variable, its description contains the version history.
    135         * </ul>
    136   * <br><br>
    137   * <b>Copyright/Copyleft</b>:
    138   * For this source the LGPL Lesser General Public License,
    139   * published by the Free Software Foundation is valid.
    140   * It means:
    141   * <ol>
    142   * <li> You can use this source without any restriction for any desired purpose.
    143   * <li> You can redistribute copies of this source to everybody.
    144   * <li> Every user of this source, also the user of redistribute copies
    145   *    with or without payment, must accept this license for further using.
    146   * <li> But the LPGL ist not appropriate for a whole software product,
    147   *    if this source is only a part of them. It means, the user
    148   *    must publish this part of source,
    149   *    but don't need to publish the whole source of the own product.
    150   * <li> You can study and modify (improve) this source
    151   *    for own using or for redistribution, but you have to license the
    152   *    modified sources likewise under this LGPL Lesser General Public License.
    153   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    154   * </ol>
    155   * If you are intent to use this sources without publishing its usage, you can get
    156   * a second license subscribing a special contract with the author.
    157   *
    158   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    159         */
    160  //@SuppressWarnings("hiding")
    161  public final static String version = "2015-01-18";
    162
    163        /**The GUI may be determined by a external user file. Not all planned fields, buttons etc.
    164   * may be placed in the GUI, a user can desire about the elements.
    165   * But an access to a non-existing element should be detected. This Exception should be caught
    166   * and an alternate behavior on non-existing elements may be programmed in the application.
    167   */
    168  public class NotExistException extends Exception
    169  {
    170    private static final long serialVersionUID = 1L;
    171
    172    NotExistException(String name)
    173    { super("GUI-Element doesn't exist in GUI: " + name);
    174    }
    175  }
    176
    177  /**The graphical frame. It is any part of a window (a Composite widget) or the whole window. */
    178  //public final Composite graphicFrame;
    179
    180  //public final Shell theShellOfWindow;
    181
    182  protected Rectangle XXXXXcurrPanelPos;
    183
    184
    185  /**Properties of this Dialog Window. The {@link GralMng} contains an aggregation
    186   * to the same instance, but with type {@link GralGridProperties}. Internally there are some more
    187   * Swt-capabilities in the derived type.
    188   */
    189  public  final SwtProperties propertiesGuiSwt;
    190
    191
    192  final Display displaySwt;
    193
    194  //public final SwtWidgetHelper widgetHelper = new SwtWidgetHelper(this);
    195
    196  /**This mouse-click-implementor is added to any widget,
    197   * which is associated to a {@link GralWidget} in its data.
    198   * The infos of the last clicked widget can be got with it.
    199   * @deprecated use {@link SwtGralMouseListener#mouseActionStd}, it is the same, but better structured.
    200   */
    201  @Deprecated MouseListener mouseClickForInfo = new SwtGralMouseListener.MouseListenerGralAction(); //NoAction();
    202
    203
    204  /**The instance for all traverse listener applicable to all widgets. */
    205  static SwtTraverseListener swtTraverseListener = new SwtTraverseListener();
    206
    207  //SwtKeyListener swtKeyListener = new SwtKeyListener(this);
    208
    209  /**It is a marker interface. */
    210  protected interface XXXUserAction{}
    211
    212
    213  /**Action for user commands of buttons.
    214   * An instance of this class is able to assign as button-action.
    215   * The actionPerformed-method is implemented here, but the procedure calls a used-defined
    216   * action method which is implemented in the user-space implementing the
    217   *  {@link GralUserAction#userActionGui(String, String, Map)}-interface.
    218   */
    219  protected class XXXButtonUserAction implements XXXUserAction, SelectionListener
    220  {
    221
    222    /**Reference to the users method. */
    223    private final GralUserAction userCmdGui;
    224
    225    /**Constructor.
    226     * @param userCmdGui The users method for the action. */
    227    private XXXButtonUserAction(GralUserAction userCmdGui)
    228    {
    229      this.userCmdGui = userCmdGui;
    230    }
    231
    232
    233                @Override
    234                public void widgetDefaultSelected(SelectionEvent e) {
    235                        // TODO Auto-generated method stub
    236
    237                }
    238
    239    /**Implementing of the primary action method,
    240     * implements @see org.eclipse.swt.events#widgetSelected(SelectionEvent)
    241     * All values of input fields are read out and filled in a list, to support locally access
    242     * to the values of the dialog.
    243     */
    244                @Override
    245                public void widgetSelected(SelectionEvent e) {
    246      /**prepare all inputs: */
    247      //String sButtonCmd = e.getActionCommand();
    248      //String sParamString = e.paramString();
    249                        Object data = null;
    250                        //String sParam = "";
    251                        Widget src = e.widget;
    252                        Object widgetData = src.getData();
    253                        GralWidget infos = widgetData instanceof GralWidget ? (GralWidget)widgetData : null;
    254                        if(src instanceof Button){
    255                                Button button = (Button)src;
    256                                data = button.getData();
    257                                if(data != null && data instanceof String){
    258                        //sParam = (String)data;
    259                }
    260                        }
    261                        /*
    262        Map<String,String> values;
    263                        if(sParam.endsWith("+")){
    264                                values = getAllValues();
    265                        } else {
    266                                values = null;
    267                        }
    268                        */
    269      userCmdGui.userActionGui("button", infos);
    270
    271                }
    272
    273  }
    274
    275
    276
    277        /**This class is only used to store values to inspect. The Inspector is a tool which works with
    278         * reflection and with it internal variable can be visited in runtime. See {@link org.vishia.inspectorTarget.Inspector}.
    279         */
    280        @SuppressWarnings("unused")
    281        private static class TestHelp{
    282        private GralCurveView curveView;
    283  }
    284        TestHelp testHelp = new TestHelp();
    285
    286
    287  /**Creates an instance.
    288   * @param guiContainer The container where the elements are stored in.
    289   * @param width in display-units for the window's width, the number of pixel depends from param displaySize.
    290   * @param height in display-units for the window's height, the number of pixel depends from param displaySize.
    291   * @param displaySize character 'A' to 'E' to determine the size of the content
    292   *        (font size, pixel per cell). 'A' is the smallest, 'E' the largest size. Default: use 'C'.
    293   */
    294  protected SwtMng(Display display /*, Composite graphicFrame */
    295  , char displaySize//, VariableContainer_ifc variableContainer
    296        , LogMessage log)
    297  { //super(sTitle);
    298        this(display, new SwtProperties(display, displaySize), log);
    299
    300  }
    301
    302  /**Creates an instance.
    303   * @param guiContainer The container where the elements are stored in.
    304   * @param width in display-units for the window's width, the number of pixel depends from param displaySize.
    305   * @param height in display-units for the window's height, the number of pixel depends from param displaySize.
    306   * @param displaySize character 'A' to 'E' to determine the size of the content
    307   *        (font size, pixel per cell). 'A' is the smallest, 'E' the largest size. Default: use 'C'.
    308   */
    309  public SwtMng(Display display
    310    , SwtProperties propertiesGui
    311        //, VariableContainer_ifc variableContainer
    312        , LogMessage log
    313        )
    314  { super(GralMng.get(), propertiesGui);
    315    this.propertiesGuiSwt = propertiesGui;
    316    //pos().x.p1 = 0; //start-position
    317    //pos().y.p1 = 4 * propertiesGui.yPixelUnit();
    318
    319
    320                displaySwt = display;
    321                //displaySwt.addFilter(SWT.KeyDown, mainKeyListener);
    322
    323
    324  }
    325
    326
    327
    328  /**The composite of the panel in SWT.
    329   * @see org.vishia.gral.base.GralMng.ImplAccess#getCurrentPanel()
    330   */
    331  @Override public Composite getCurrentPanel(){ return ((Composite)pos().panel.getWidgetImplementation()); }
    332
    333  public Composite getWidgetsPanel(GralWidget widg){
    334    GralPos pos = widg.pos();
    335    if(pos == null) { pos = pos(); } //from GralMng
    336    return ((Composite)pos.panel.getWidgetImplementation());
    337  }
    338
    339
    340  private Composite getCurrentPanel(GralWidget widgg){ return ((Composite)widgg.pos().panel.getWidgetImplementation()); }
    341
    342
    343  @Override public void createImplWidget_Gthread(GralWidget widgg){
    344    if(widgg instanceof GralHtmlBox) {  //NOTE: before GralTextField because a GralTextBox is a GralTextField (derived)
    345      SwtHtmlBox.createHtmlBox((GralHtmlBox)widgg, this);  //This may be the best variant.
    346    } else if(widgg instanceof GralTextBox) {  //NOTE: before GralTextField because a GralTextBox is a GralTextField (derived)
    347      SwtTextBox.createTextBox((GralTextBox)widgg, this);  //This may be the best variant.
    348    } else if(widgg instanceof GralTextField){
    349      SwtTextFieldWrapper.createTextField((GralTextField)widgg, mng);  //This may be the best variant.
    350    } else if(widgg instanceof GralHorizontalSelector<?>){
    351      SwtHorizontalSelector swtSel = new SwtHorizontalSelector(this, (GralHorizontalSelector<?>)widgg);
    352      mng.registerWidget(widgg);
    353    } else if(widgg instanceof GralTable<?>){
    354      SwtTable.createTable((GralTable<?>)widgg, this);  //This may be the best variant.
    355    } else if(widgg instanceof GralButton){
    356      new SwtButton((GralButton)widgg, this);
    357      mng.registerWidget(widgg);
    358    }
    359    else if(widgg instanceof GralLabel){
    360      new SwtLabel((GralLabel)widgg, this);
    361    }
    362    else if(widgg instanceof GralValueBar){
    363      new SwtValueBar((GralValueBar)widgg, this);
    364    }
    365    else if(widgg instanceof GralLed){
    366      new SwtLed((GralLed)widgg, this);
    367      mng.registerWidget(widgg);
    368    }
    369    else if(widgg instanceof GralPlotArea){
    370      new SwtPlotArea((GralPlotArea)widgg, this);
    371    }
    372  }
    373
    374
    375
    376
    377
    378
    379  @Override public GralPanelContent createCompositeBox(String name)
    380  {
    381    //Composite box = new Composite(graphicFrame, 0);
    382    Composite box = new Composite(getCurrentPanel(), 0);
    383    setPosAndSize_(mng.getPosOldPositioning(), box);
    384    Point size = box.getSize();
    385    GralPanelContent panelg = new GralPanelContent(null, name);
    386    GralPanelContent panel = (new SwtPanel(panelg, box)).gralPanel();
    387    //mng.registerPanel(panel);
    388    //GuiPanelMngSwt mng = new GuiPanelMngSwt(gralDevice, size.y, size.x, propertiesGuiSwt, variableContainer, log);
    389    return panel;
    390  }
    391
    392
    393  @Override public GralPanelContent createGridPanel(String namePanel, GralColor backGround, int xG, int yG, int xS, int yS)
    394  { GralPanelContent panelg = new GralPanelContent(null, namePanel);
    395    Color backColorSwt = propertiesGuiSwt.colorSwt(backGround);
    396    SwtGridPanel panel = new SwtGridPanel(panelg, null, 0, backColorSwt, xG, yG, xS, yS, mng);
    397    GralPanelContent gralPanel = panel.gralPanel();
    398    //mng.registerPanel(gralPanel);
    399
    400    return gralPanel;
    401  }
    402
    403
    404
    405  @Override public boolean remove(GralPanelContent compositeBox)
    406  { Composite panelSwt = ((SwtPanel)compositeBox.getWidgetImplementation()).panelComposite;
    407    panelSwt.dispose();
    408    return true;
    409  }
    410
    411
    412
    413  /* (non-Javadoc)
    414   * @see org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(java.lang.String, java.lang.String, int)
    415   */
    416  @Deprecated
    417  @Override public GralWindow createWindow(String name, String title, int windProps)
    418  {
    419    //GralWindow windowGral = new GralWindow("@", name, title, windProps);
    420    GralWindow windowGral = new GralWindow(null, name, title, windProps);
    421    //SwtGraphicThread swtDevice = (SwtGraphicThread)gralDevice;
    422    createSubWindow(windowGral);
    423    return windowGral;
    424
    425  }
    426
    427
    428
    429
    430  /* (non-Javadoc)
    431   * @see org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(org.vishia.gral.base.GralWindow)
    432   */
    433  @Override public void createSubWindow(GralWindow windowGral) {
    434    SwtSubWindow windowSwt = new SwtSubWindow(this, windowGral);
    435    //GralRectangle rect = calcPositionOfWindow(windowGral.pos());
    436    //windowSwt.window.setBounds(rect.x, rect.y, rect.dx, rect.dy );
    437    windowGral._wdgImpl = windowSwt;
    438  }
    439
    440
    441
    442
    443  @Override public boolean XXXsetWindowsVisible(GralWindow_ifc window, GralPos atPos)
    444  {return false;  }
    445
    446
    447
    448
    449
    450  /**Calculates the position as absolute value on screen from a given position inside a panel.
    451   * @param posWindow contains any {@link GralPos#panel}. Its absolute position will be determined.
    452   *   from that position and size the absolute postion will be calculate, with this given grid positions
    453   *   inside the panel.
    454   * @return Absolute pixel coordinate.
    455   */
    456  GralRectangle calcPositionOfWindow(GralPos posWindow)
    457  {
    458    final GralRectangle windowFrame;
    459    Control parentFrame;
    460    final Shell window;
    461    if(posWindow.panel !=null) {
    462      Object swtWidg = posWindow.panel.getWidgetImplementation();
    463      parentFrame = (Control)swtWidg; //((SwtPanel)(swtWidg)).panelComposite; //(Control)posWindow.panel.getPanelImpl();
    464      Point loc;
    465      window = parentFrame.getShell();
    466      int x = 6;
    467      windowFrame = getPixelUseableAreaOfWindow(posWindow.panel);
    468    } else {
    469      windowFrame = new GralRectangle(0,0,800,600);
    470      parentFrame = null;
    471      window = null;
    472    }
    473    int dxFrame, dyFrame;  //need if posWindow has coordinates from right or in percent
    474    Rectangle rectParent;
    475    if(parentFrame == window){
    476      dxFrame = windowFrame.dx; dyFrame = windowFrame.dy;
    477    } else {
    478      rectParent = parentFrame.getBounds();
    479      dxFrame = rectParent.width; dyFrame = rectParent.height;
    480    }
    481    final GralRectangle rectangle = mng.calcWidgetPosAndSize(posWindow, dxFrame, dyFrame, 400, 300);
    482    rectangle.x += windowFrame.x;
    483    rectangle.y += windowFrame.y;
    484
    485    //
    486    while ( parentFrame != window){ //The Shell is the last parentFrame
    487      //the bounds are relative to its container. Get all parent container and add all positions
    488      //until the shell is reached.
    489      rectParent = parentFrame.getBounds();
    490      rectangle.x += rectParent.x;
    491      rectangle.y += rectParent.y;
    492      parentFrame = parentFrame.getParent();
    493    }
    494    return rectangle;
    495
    496    /*
    497    Rectangle rectParent  = parentFrame instanceof Shell ? ((Shell)parentFrame).getClientArea()
    498                          : parentFrame.getBounds();
    499    //loc = panel.getLocation();
    500    int xPos = rectParent.x, yPos = rectParent.y;
    501    while( (parentFrame = parentFrame.getParent()) !=null){
    502      rectParent = parentFrame.getBounds();
    503      loc = parentFrame.getLocation();
    504      xPos += rectParent.x;
    505      yPos += rectParent.y;
    506      if(parentFrame instanceof Shell){
    507        Shell shell = (Shell)parentFrame;
    508        Rectangle rectArea = shell.getClientArea(); //size of client area
    509        Menu menu = shell.getMenuBar();
    510        //Point sizeArea = shell.getSize();
    511        int dy = rectParent.height - rectArea.height; //The start of client area
    512        if(menu !=null){ dy *=2; } //Menu needs the same size as title.
    513        int dx = rectParent.width - rectArea.width;
    514        xPos += dx;
    515        yPos += dy;
    516      } else {
    517      }
    518
    519    }
    520    rectangle.x += xPos;
    521    rectangle.y += yPos;
    522    return rectangle;
    523    */
    524  }
    525
    526
    527
    528  GralRectangle getPixelUseableAreaOfWindow(GralWidget widgg)
    529  { Object oControl = widgg._wdgImpl.getWidgetImplementation();
    530    Control control = (Control)oControl;
    531    Shell window = control.getShell();
    532    Rectangle rectWindow = window.getBounds();
    533    Rectangle rectWindowArea = window.getClientArea();  //it is inclusive the menu bar.
    534    //Problem: the x and y of client are are 0, it may bettet that they are the left top corner
    535    //inside the shell window.
    536    //assume that the client area is on bottom of the shell. Calculate top position:
    537    int dxBorder = rectWindow.width - rectWindowArea.width;
    538    int xPos = rectWindow.x + dxBorder/2;
    539    int dyTitleMenu = (rectWindow.height - rectWindowArea.height) - dxBorder;  //border and title bar
    540    Menu menu = window.getMenuBar();
    541    if(menu !=null){
    542      //assume that the menu has the same hight as title bar, there is not a way to determine it else
    543      dyTitleMenu *=2;
    544    }
    545    int yPos = rectWindow.y + dxBorder/2 + dyTitleMenu;
    546    GralRectangle ret = new GralRectangle(xPos, yPos, rectWindowArea.width, rectWindowArea.height - dyTitleMenu);
    547    return ret;
    548  }
    549
    550
    551
    552  /**This method can be override by the user to force some actions if the dialog window is closed. It may be left empty. */
    553  protected void windowClosing()
    554  {
    555
    556  }
    557
    558
    559  /**Places a current component with knowledge of the current positions and the spreads of the component on graphic.
    560   * @param component The component to place.
    561   */
    562  GralRectangle setBounds_(GralPos pos, Control component)
    563  { return setPosAndSize_(pos, component);
    564    //setBounds_(component, 0,0, 0, 0);
    565  }
    566
    567
    568
    569
    570  GralRectangle setPosAndSize_(GralPos pos, Control component)
    571  { return setPosAndSizeSwt(pos, component, 0,0);
    572  }
    573
    574
    575
    576
    577
    578
    579  /**Set bounds of a SWT component with this {@link GralMng#pos} from the GralWidgetMng.
    580   * The {@link #setNextPosition()} is called to process a used this.pos to its next.
    581   * This method is package-private for SWT-implementation. It calls
    582   * {@link #setNextPosition()} and {@link #setPosAndSizeSwt(GralPos, Control, int, int)}
    583   * with
    584   * @param component The SWT-widget.
    585   * @param widthwidgetNat The natural size of the component.
    586   * @param heigthWidgetNat The natural size of the component.
    587   *
    588   * NOTE: 2015-07-13: This method is set to unused because it uses the mng-position additional to the constructor of GralWidget.
    589   * This is the old concept which is in conflict with the usuage there.
    590   */
    591  void XXXsetPosAndSizeSwt(Control component, int widthwidgetNat, int heigthWidgetNat)
    592  { mng.setNextPosition();
    593    setPosAndSizeSwt(pos(), component, widthwidgetNat, heigthWidgetNat);
    594  }
    595
    596
    597
    598
    599  /**Set bounds of a SWT component with a given position.
    600   * This method is package-private for SWT-implementation.
    601   * @param posP The Position for the component.
    602   * @param component The SWT-widget.
    603   * @param widthwidgetNat The natural size of the component.
    604   * @param heigthWidgetNat The natural size of the component.
    605   */
    606  GralRectangle setPosAndSizeSwt(GralPos posP, Control component, int widthwidgetNat, int heigthWidgetNat)
    607  {
    608    GralRectangle rectangle = calcWidgetPosAndSizeSwt(posP, component.getParent(), widthwidgetNat, heigthWidgetNat);
    609    //on SWT it invokes the resize listener if given.
    610    component.setBounds(rectangle.x, rectangle.y, rectangle.dx, rectangle.dy );
    611    return rectangle;
    612  }
    613
    614
    615
    616
    617
    618  /**Calculates the bounds of a widget with a given pos independent of this {@link #pos}.
    619   * This method is a part of the implementing GralMng because the GralPos is not implemented for
    620   * any underlying graphic system and the {@link #propertiesGuiSwt} are used.
    621   * It is possible to tune the bounds after calculation, for example to enhance the width if a text
    622   * is larger then the intended position.
    623   * @param pos The position.
    624   * @param widthwidgetNat The natural size of the component.
    625   * @param heigthWidgetNat The natural size of the component.
    626   * @return A rectangle with position and size.
    627   */
    628  @Override public GralRectangle calcWidgetPosAndSize(GralPos pos, int widthwidgetNat, int heigthWidgetNat){
    629
    630    Object oParent = pos.panel.getWidgetImplementation();
    631    Composite parentComp = (Composite) oParent; //((SwtPanel)(pos().panel.getWidgetImplementation())).panelComposite; //(Composite)pos().panel.getPanelImpl();
    632    //Rectangle pos;
    633    final GralRectangle rectangle;
    634    final Rectangle parentSize;
    635    if(parentComp == null){
    636      parentSize = new Rectangle(0,0,800, 600);
    637    } else if(parentComp instanceof Shell) {
    638      parentSize = ((Shell)parentComp).getClientArea();
    639    } else {
    640      parentSize = parentComp.getBounds();
    641    }
    642    return pos().calcWidgetPosAndSize(mng.propertiesGui, parentSize.width, parentSize.height, widthwidgetNat, heigthWidgetNat);
    643  }
    644
    645
    646
    647
    648  /**Calculates the bounds of a SWT component with a given position independent of {@link #pos}.
    649   * This method is package-private for SWT-implementation.
    650   * It is possible to tune the bounds after calculation, for example to enhance the width if a text
    651   * is larger then the intended position.
    652   * @param pos The position.
    653   * @param component The SWT-widget.
    654   * @param widthwidgetNat The natural size of the component.
    655   * @param heigthWidgetNat The natural size of the component.
    656   * @return A rectangle with position and size.
    657   * @deprecated, use {@link #calcWidgetPosAndSizeSwt(GralPos, int, int)}
    658   */
    659  GralRectangle calcWidgetPosAndSizeSwt(GralPos pos, Control parentComp, int widthwidgetNat, int heigthWidgetNat){
    660    //Rectangle pos;
    661    final GralRectangle rectangle;
    662    final Rectangle parentSize;
    663    if(parentComp == null){
    664      parentSize = new Rectangle(0,0,800, 600);
    665    } else if(parentComp instanceof Shell) {
    666      parentSize = ((Shell)parentComp).getClientArea();
    667    } else {
    668      parentSize = parentComp.getBounds();
    669    }
    670    return mng.calcWidgetPosAndSize(pos, parentSize.width, parentSize.height, widthwidgetNat, heigthWidgetNat);
    671  }
    672
    673
    674
    675
    676
    677
    678        /**Adds a tab panel in implementation.
    679         * If this routine was called, the GralMng.pos is the pos for the Tabbed panel.
    680         * @see org.vishia.gral.base.GralMng.ImplAccess#addTabbedPanel(java.lang.String, org.vishia.gral.base.GralPanelActivated_ifc, int)
    681         */
    682        @Override public GralTabbedPanel addTabbedPanel(String namePanel, GralPanelActivated_ifc user, int property)
    683        { GralTabbedPanel panelg = new GralTabbedPanel(null, namePanel, user, property);
    684                SwtTabbedPanel tabMngPanel = new SwtTabbedPanel(panelg, this, user, property);
    685                mng.currTabPanel = panelg;
    686                //GralWidget tabFolder = currTabPanel;
    687                TabFolder tabFolderSwt = (TabFolder)tabMngPanel.getWidgetImplementation();
    688                setPosAndSize_(panelg.pos(), tabFolderSwt); //(Control)currTabPanel.getGuiComponent().getWidgetImplementation());
    689                listVisiblePanels_add(mng.currTabPanel);  //TODO checkit maybe currTabPanel.getCurrentPanel()
    690                //mng.registerWidget(tabMngPanel);
    691                return mng.currTabPanel;
    692        }
    693
    694
    695
    696
    697  @Override @Deprecated public GralWidget addText(String sText, char size, int color)
    698  {
    699    Composite swtPanel = ((Composite)(pos().panel.getWidgetImplementation()));
    700    Label widget = new Label(swtPanel, 0);
    701    widget.setForeground(propertiesGuiSwt.colorSwt(color));
    702    widget.setBackground(propertiesGuiSwt.colorBackground);
    703    widget.setText(sText);
    704    //Font font = propertiesGui.stdInputFont;
    705    Font font = propertiesGuiSwt.getSwtFont(pos().height());
    706    widget.setFont(font);
    707    //font.getFontData()[0].
    708    Point textSize = widget.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
    709    //int width = sText.length();
    710    //widget.setSize(sizePixel);
    711
    712    setPosAndSize_(mng.getPosOldPositioning(), widget);
    713
    714    Point widgetSize = widget.getSize();
    715    if(widgetSize.x < textSize.x){
    716      widget.setSize(textSize);
    717    }
    718    widget.setSize(textSize);
    719    //guiContent.add(widget);
    720    GralWidget widg = new GralWidget("labelText-" + sText, 'S', mng);
    721    SwtWidgetSimpleWrapper widgswt = new SwtWidgetSimpleWrapper(widget, this);
    722    //widg.implMethodWidget_.setWidgetImpl(widgswt);
    723    return widg;
    724  }
    725
    726
    727  /** Adds a text field for showing or editing a text value.
    728   *
    729   * @param sName The registering name
    730   * @param width Number of grid units for length
    731   * @param editable true than edit-able, false to show content
    732   * @param prompt If not null, than a description label is shown
    733   * @param promptStylePosition Position and size of description label:
    734   *   upper case letter: normal font, lower case letter: small font
    735   *   'l' left, 't' top (above field)
    736   * @return
    737   */
    738  public GralWidget XXXaddTextField(String name, boolean editable, String prompt, char promptStylePosition)
    739  {
    740    return null; //addTextField(null, name, editable, prompt, promptStylePosition);
    741  }
    742
    743
    744  /** Adds a text field for showing or editing a text value.
    745   *
    746   * @param sName The registering name
    747   * @param width Number of grid units for length
    748   * @param editable true than edit-able, false to show content
    749   * @param prompt If not null, than a description label is shown
    750   * @param promptStylePosition Position and size of description label:
    751   *   upper case letter: normal font, lower case letter: small font
    752   *   'l' left, 't' top (above field)
    753   * @return
    754   */
    755  public GralWidget XXXaddTextField(GralWidget widgetInfo, boolean editable, String prompt, char promptStylePosition)
    756  {
    757    return null; //addTextField(widgetInfo, null, editable, prompt, promptStylePosition);
    758  }
    759
    760
    761@Override public GralHtmlBox addHtmlBox(String name) {
    762  GralHtmlBox box = new GralHtmlBox(name);
    763  new SwtHtmlBox(box, this);
    764  return box;
    765}
    766
    767
    768
    769
    770  /* (non-Javadoc)
    771   * @see org.vishia.mainGui.GuiPanelMngIfc#addImage(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String)
    772   */
    773  @Override
    774  public Object addImage(String sName, InputStream imageStream, int height, int width, String sCmd)
    775  {
    776    ImageData imageData = new ImageData(imageStream);
    777    byte[] data = imageData.data;
    778    SwtPanel swtPanel = (SwtPanel)pos().panel.getImpl();
    779    Composite swtWidg = swtPanel.panelComposite;
    780    Image image = new Image(swtWidg.getDisplay(), imageData);
    781    GralImageBase imageGui = new SwtImage(image);
    782    GralRectangle size = imageGui.getPixelSize();
    783    GralRectangle rr = mng.calcWidgetPosAndSize(pos(), 0, 0, size.dx, size.dy);
    784    GralCanvasStorage canvas = pos().panel.canvas;
    785    if(canvas !=null){
    786      canvas.drawImage(imageGui, rr.x, rr.y, rr.dx, rr.dy, size);
    787    }
    788    return null;
    789  }
    790
    791
    792
    793
    794  @Override public GralWidget addSlider(
    795        String sName
    796  , GralUserAction action
    797  , String sShowMethod
    798  , String sDataPath
    799  )
    800  {
    801        Slider control = new Slider(getCurrentPanel(), SWT.VERTICAL);
    802        control.setBackground(propertiesGuiSwt.colorBackground);
    803        setPosAndSize_(mng.getPosOldPositioning(), control);
    804    GralWidget widg = new GralWidget(sName, 'V', mng);
    805    SwtWidgetSimpleWrapper widgswt = new SwtWidgetSimpleWrapper(control, this);
    806    //widg.implMethodWidget_.setWidgetImpl(widgswt);
    807    widg.setPanelMng(mng);
    808    if(action != null){
    809                SelectionListenerForSlider actionSlider = new SelectionListenerForSlider(widg, action);
    810                control.addSelectionListener(actionSlider);
    811        }
    812    widg.setDataPath(sDataPath);
    813    control.setData(widg);
    814    control.addMouseListener(mouseClickForInfo);
    815    return widg;
    816
    817  }
    818
    819
    820
    821        @Override public GralCurveView addCurveViewY(String sName, int nrofXvalues, GralCurveView.CommonCurve common) {
    822    //setNextPosition();
    823          GralCurveView widgg = new GralCurveView(sName, nrofXvalues, common);
    824          new SwtCurveView(widgg, this); //sName, this.pos(), this, nrofXvalues, common); //, curveView, 'c', sName, null);
    825                mng.curveContainer.add(widgg);
    826          //CurveView curveView = new CurveView(((SwtPanel)pos().panel).getPanelImpl(), dxWidget, dyWidget, nrofXvalues, nrofTracks);
    827                testHelp.curveView = widgg; //store to inspect.
    828                return widgg;
    829        }
    830
    831
    832
    833        @Override public GralWidget addFocusAction(String sName, GralUserAction action, String sCmdEnter, String sCmdRelease)
    834        {
    835    GralWidget widget = indexNameWidgets(sName);
    836        if(widget == null || widget._wdgImpl ==null || !(widget._wdgImpl.getWidgetImplementation() instanceof Control)){
    837                mng.log.sendMsg(0, "GuiMainDialog:addClickAction: unknown widget %s", sName);
    838        } else {
    839        /**The class ButtonUserAction implements the general button action, which class the registered user action. */
    840      ((Control)(widget._wdgImpl.getWidgetImplementation())).addFocusListener( new SwtFocusAction(this, action, sCmdEnter, sCmdRelease));
    841
    842        }
    843        return widget;
    844        }
    845
    846
    847        @Override public void addFocusAction(GralWidget widgetInfo, GralUserAction action, String sCmdEnter, String sCmdRelease)
    848        {
    849    ((Control)(widgetInfo._wdgImpl.getWidgetImplementation())).addFocusListener( new SwtFocusAction(this, action, sCmdEnter, sCmdRelease));
    850  }
    851
    852
    853  @Override @Deprecated public GralTable addTable(String sName, int height, int[] columnWidths)
    854  {
    855    GralTable table = new GralTable(sName, columnWidths);
    856    return SwtTable.addTable(table, this, sName, height, columnWidths);
    857
    858  }
    859
    860
    861  @Override protected GralMenu XXXaddPopupMenu(String sName){
    862    Control panelSwt = getCurrentPanel(); //(Control)pos().panel.getPanelImpl();
    863    GralMenu menu = new GralMenu(); new SwtMenu(menu, null, panelSwt);
    864    return menu;
    865  }
    866
    867
    868  @Override protected GralMenu createContextMenu(GralWidget widg){
    869    Control widgSwt = (Control)widg._wdgImpl.getWidgetImplementation();
    870    GralMenu menu = new GralMenu(); new SwtMenu(menu, widg, widgSwt);
    871    return menu;
    872  }
    873
    874
    875  @Override protected GralMenu createMenuBar(GralWindow windg){
    876    Shell windowSwt = (Shell)windg.getWidgetImplementation();
    877    GralMenu menu = new GralMenu(); new SwtMenu(menu, windg, windowSwt);
    878    return menu;
    879  }
    880
    881
    882
    883
    884  @Override public GralFileDialog_ifc createFileDialog()
    885  {
    886    Composite panelSwt = getCurrentPanel(); //(Composite)pos().panel.getPanelImpl(); //cast admissible, it should be SWT
    887    while(!(panelSwt instanceof Shell)){
    888      panelSwt = panelSwt.getParent();
    889    }
    890        return new SwtFileDialog((Shell)panelSwt);
    891  }
    892
    893
    894
    895  static class SelectionListenerForSlider implements SelectionListener
    896  {
    897        private final GralUserAction userAction;
    898
    899        private final GralWidget widgetInfo;
    900
    901
    902
    903        public SelectionListenerForSlider(GralWidget widgetInfo, GralUserAction userAction)
    904                {
    905                        this.userAction = userAction;
    906                this.widgetInfo = widgetInfo;
    907                }
    908
    909                @Override       public void widgetDefaultSelected(SelectionEvent e)
    910                {
    911                        widgetSelected(e);
    912
    913                }
    914
    915                @Override       public void widgetSelected(SelectionEvent e)
    916                {
    917                        // TODO Auto-generated method stub
    918                        //String sDataPath = widgetInfo.sDataPath;
    919                        Slider slider = (Slider)e.widget;
    920                        int value = slider.getSelection();
    921                        //String sParam = Integer.toString(value);
    922                        userAction.userActionGui("sliderValue", widgetInfo, value);
    923                }
    924
    925  }
    926
    927
    928        @Override
    929        public void setSampleCurveViewY(String sName, float[] values) {
    930                GralWidget descr = indexNameWidgets(sName);
    931                if(descr == null){
    932                //log.sendMsg(0, "GuiMainDialog:setSampleCurveViewY: unknown widget %s", sName);
    933        }
    934
    935        }
    936
    937
    938        @Override public void redrawWidget(String sName)
    939        {
    940                GralWidget descr = indexNameWidgets(sName);
    941                if(descr == null){
    942                //log.sendMsg(0, "GuiMainDialog:setSampleCurveViewY: unknown widget %s", sName);
    943        } else {
    944        }
    945        }
    946
    947
    948        @Override public void resizeWidget(GralWidget widgd, int xSizeParent, int ySizeParent)
    949        {
    950          //GralWidget_ifc widget = widgd.getGraphicWidgetWrapper();
    951          if(widgd._wdgImpl !=null) {
    952          Object owidg = widgd._wdgImpl.getWidgetImplementation();
    953          int test = 6;
    954          if(owidg !=null){
    955            Control swtWidget = (Control)owidg;
    956            GralPanelContent panel = widgd.pos().panel;
    957            GralRectangle size = panel._wdgImpl.getPixelPositionSize(); //PixelSize();
    958            GralRectangle posSize = mng.calcWidgetPosAndSize(widgd.pos(), size.dx, size.dy, 0, 0);
    959          //Note: the swtWidget may have a resizeListener, see there.
    960            swtWidget.setBounds(posSize.x, posSize.y, posSize.dx, posSize.dy );
    961          swtWidget.redraw();
    962          }
    963          }
    964        }
    965
    966
    967
    968
    969
    970        @Override @Deprecated public String getValueFromWidget(GralWidget widgd)
    971        { String sValue;
    972        sValue = mng.getValueFromWidget(widgd);  //platform independent getting of value
    973        if(sValue == null){
    974          GralWidget_ifc widget = widgd;
    975      Control swtWidget = (Control)widgd._wdgImpl.getWidgetImplementation();
    976                if(swtWidget instanceof Text){
    977          sValue = ((Text)swtWidget).getText();
    978        } else if(widgd instanceof GralButton){
    979                GralButton button = (GralButton)widgd;
    980                sValue = button.isOn() ? "1" : "0";
    981        } else if(swtWidget instanceof Button){
    982                sValue = "0"; //TODO input.button.isSelected() ? "1" : "0";
    983        } else if(swtWidget instanceof Table){
    984        Table table = (Table)swtWidget;
    985        sValue = getValueFromTable(table);
    986        } else {
    987          mng.log.sendMsg(0, "GuiPanelMngSwt.getValueFromWidget - unknown widget type;");
    988                sValue = "";
    989        }
    990        }
    991                return sValue;
    992        }
    993
    994
    995        private String getValueFromTable(Table table)
    996        { StringBuilder u = new StringBuilder();
    997    int actLine = table.getSelectionIndex();
    998    TableItem item = table.getItem(actLine);
    999    int nrofColumns = table.getColumnCount();
    1000    for(int iCol = 0; iCol < nrofColumns; ++iCol){
    1001      u.append(item.getText(iCol)).append('\t');
    1002    }
    1003          return u.toString();
    1004        }
    1005
    1006
    1007
    1008
    1009
    1010        @Override public Color getColorImpl(GralColor colorGral)
    1011        { return propertiesGuiSwt.colorSwt(colorGral);
    1012        }
    1013
    1014
    1015
    1016  @Override public boolean showContextMenuGthread(GralWidget widg) {
    1017    boolean bOk;
    1018    Control swtWidg = (Control)widg._wdgImpl.getWidgetImplementation();
    1019    Menu contextMenu = swtWidg.getMenu();
    1020    if(contextMenu == null){
    1021      bOk = false;
    1022    } else {
    1023      //Rectangle pos = swtWidg.getBounds();
    1024      GralRectangle pos = SwtWidgetHelper.getPixelPositionSize(swtWidg);
    1025      contextMenu.setLocation(pos.x + pos.dx, pos.y + pos.dy);
    1026      contextMenu.setVisible(true);
    1027      bOk = true;
    1028    }
    1029    return bOk;
    1030  }
    1031
    1032
    1033
    1034
    1035
    1036  /**This routine is invoked on any key event.
    1037   * It is possible to change keys, to disable the event handling and to call special routines.
    1038   * Yet not used.
    1039   */
    1040  Listener XXXX_mainKeyListener = new Listener(){
    1041    @Override public void handleEvent(Event event) {
    1042      // TODO Auto-generated method stub
    1043      if(userMainKeyAction() !=null
    1044          && (event.keyCode & 0xffff) !=0  //don't take anything on alt- etc. alone
    1045        ){
    1046        final int keyCode = SwtGralKey.convertFromSwt(event.keyCode, event.stateMask, event.character);
    1047        boolean bDone = userMainKeyAction().userActionGui(keyCode, null);
    1048        if(bDone){
    1049          event.type = SWT.None;
    1050          //event.doit = false;   //don't use this key for another action.
    1051        }
    1052      }
    1053      stop();
    1054    }
    1055  };
    1056
    1057
    1058
    1059
    1060
    1061
    1062
    1063  /**Universal focus listener to register which widgets were in focus in its order,
    1064   * to set htmlHelp and to invoke the {@link GralWidget#setActionFocused(GralUserAction)}.
    1065   */
    1066  protected class SwtMngFocusListener implements FocusListener
    1067  {
    1068    GralMng.GralMngFocusListener gralFocus;
    1069
    1070    SwtMngFocusListener(GralMng mng){
    1071      gralFocus = mng.new GralMngFocusListener();
    1072    }
    1073
    1074    @Override public void focusLost(FocusEvent ev)
    1075    { GralWidget widgg = GralWidget.ImplAccess.gralWidgetFromImplData(ev.widget.getData());
    1076      if(widgg !=null) { gralFocus.focusLostGral(widgg); }
    1077    }
    1078
    1079    @Override public void focusGained(FocusEvent ev)
    1080    { GralWidget widgg = GralWidget.ImplAccess.gralWidgetFromImplData(ev.widget.getData());
    1081    if(widgg !=null) { gralFocus.focusGainedGral(widgg); }
    1082    }
    1083  }
    1084
    1085  /**The package private universal focus listener. */
    1086  protected SwtMngFocusListener focusListener = new SwtMngFocusListener(mng);
    1087
    1088
    1089  /**Universal context menu listener
    1090   */
    1091  protected class SwtMngMouseMenuListener implements MenuDetectListener
    1092  {
    1093
    1094    @Override
    1095    public void menuDetected(MenuDetectEvent e)
    1096    {
    1097      // TODO Auto-generated method stub
    1098
    1099    }
    1100  }
    1101
    1102  /**The package private universal focus listener. */
    1103  SwtMngMouseMenuListener mouseMenuListener = new SwtMngMouseMenuListener();
    1104
    1105
    1106        void stop(){}  //debug helper
    1107
    1108
    1109}