    001package org.vishia.gral.swt;
    002
    003import org.eclipse.swt.SWT;
    004import org.eclipse.swt.events.KeyListener;
    005import org.eclipse.swt.events.KeyEvent;
    006import org.eclipse.swt.events.ShellListener;
    007import org.eclipse.swt.events.ShellEvent;
    008import org.eclipse.swt.events.TraverseEvent;
    009import org.eclipse.swt.events.TraverseListener;
    010import org.eclipse.swt.widgets.Display;
    011import org.eclipse.swt.widgets.Event;
    012import org.eclipse.swt.widgets.Listener;
    013import org.eclipse.swt.widgets.Menu;
    014import org.eclipse.swt.widgets.Shell;
    015import org.vishia.gral.base.GralGraphicThread;
    016import org.vishia.gral.base.GralGraphicThread.ImplAccess;
    017import org.vishia.gral.base.GralMng;
    018import org.vishia.gral.base.GralPos;
    019import org.vishia.gral.base.GralWindow;
    020import org.vishia.gral.ifc.GralWindow_ifc;
    021import org.vishia.msgDispatch.LogMessage;
    022
    023/**This class is the implementation class of a simple graphic implementation for SWT.
    024 * It doesn't depend of complex functionality of the org.vishia.gral. But that implementations based on this.
    025 * This class can be used for a simple SWT graphic implementation.
    026 */
    027class SwtGraphicThread extends GralGraphicThread.ImplAccess //implements Runnable
    028{
    029  /**Version, history and license.
    030   * <ul>
    031   * <li>2016-07-16 Hartmut chg: The main window will be created with same methods like all other windows.
    032   * <li>2015-01-17 Hartmut chg: Now {@link GralGraphicThread} is an own instance able to create before the graphic is established.
    033   *   This graphical implementation extends the {@link ImplAccess}.
    034   * <li<2012-07-14 Hartmut chg: {@link #traverseKeyFilter} now excludes [ctrl-tab]. Only [tab] is a traversal key.
    035   * <li>2012-04-16 Hartmut chg: {@link #initGraphic()} now creates the main window, creates the
    036   *   {@link SwtMng} instead it is doing in the non-graphic thread.
    037   * <li>2012-04-10 Hartmut chg: Now the traversal keys ctrl-Pgdn/up are disabled.
    038   * <li>2011-11-12 Hartmut chg: Now the primary window has a menu bar anyway.
    039   * </ul>
    040   * <b>Copyright/Copyleft</b>:
    041   * For this source the LGPL Lesser General Public License,
    042   * published by the Free Software Foundation is valid.
    043   * It means:
    044   * <ol>
    045   * <li> You can use this source without any restriction for any desired purpose.
    046   * <li> You can redistribute copies of this source to everybody.
    047   * <li> Every user of this source, also the user of redistribute copies
    048   *    with or without payment, must accept this license for further using.
    049   * <li> But the LPGL is not appropriate for a whole software product,
    050   *    if this source is only a part of them. It means, the user
    051   *    must publish this part of source,
    052   *    but don't need to publish the whole source of the own product.
    053   * <li> You can study and modify (improve) this source
    054   *    for own using or for redistribution, but you have to license the
    055   *    modified sources likewise under this LGPL Lesser General Public License.
    056   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    057   * </ol>
    058   * If you are intent to use this sources without publishing its usage, you can get
    059   * a second license subscribing a special contract with the author.
    060   *
    061   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    062   *
    063   */
    064  //@SuppressWarnings("hiding")
    065  public final static String version = "2015-01-17";
    066
    067  /**The graphical device for the application for all windows of this application. */
    068  Display displaySwt;
    069
    070  /**The main window. SWT: named as Shell. */
    071  Shell windowSwt;
    072
    073  //SwtPrimaryWindow instance;
    074
    075  SwtMng gralMng;
    076
    077  /**The windows-closing event handler. It is used private only, but public set because documentation.
    078   * The close event will be fired also when a SubWindow is closed. Therefore test the Shell instance.
    079   * Only if the main window is closed, bExit should be set to true.
    080   * */
    081  public final class WindowsCloseListener implements Listener{
    082    /**Invoked when the window is closed; it sets {@link #bExit}, able to get with {@link #isRunning()}.
    083     * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
    084     */
    085    @Override public void handleEvent(Event event) {
    086      setClosed( event.widget == windowSwt); //close if the main window was closed.
    087    }
    088  }
    089
    090  /**Instance of windowsCloseHandler. */
    091  private final WindowsCloseListener windowsCloseListener = new WindowsCloseListener();
    092
    093
    094
    095  KeyListener keyListener = new KeyListener()
    096  {
    097    @Override public void keyPressed(KeyEvent key)
    098    {
    099      // TODO Auto-generated method stub
    100      stop();
    101    }
    102
    103    @Override public void keyReleased(KeyEvent e)
    104    {
    105      // TODO Auto-generated method stub
    106
    107    }
    108
    109  };
    110
    111
    112
    113  /**Disables the ctrl-pgUp and ctrl-Pgdn as traversal key listener. It should be able to use
    114   * by the application. Only Tab and sh-Tab are usual. */
    115  TraverseListener XXXkeyTraverse = new TraverseListener(){
    116    @Override public void keyTraversed(TraverseEvent e) {
    117      stop();
    118      if(  e.detail == SWT.TRAVERSE_PAGE_NEXT //|| e.keyCode == SWT.PAGE_DOWN){
    119        || e.detail == SWT.TRAVERSE_PAGE_PREVIOUS
    120         ) {
    121        e.doit = true;
    122  } } };
    123
    124
    125  /**This interface routine is invoked on any key which is used as 'traverse' key to switch
    126   * between widgets, panels etc. SWT uses the ctrl-pgup and ctrl-pgdn to switch between the
    127   * tab cards on a TabbedPanel. This is not a standard behavior for all graphic systems.
    128   * That keys should be able to use in the application. Therefore they are disabled as traversal keys.
    129   * To switch between the tabs - it may be application specific to do it with keys - or the mouse
    130   * can be used.
    131   *
    132   */
    133  Listener traverseKeyFilter = new Listener(){
    134    @Override public void handleEvent(Event event) {
    135      int traverseIdent = event.detail;
    136      int key = event.keyCode;
    137      int keyModifier = event.stateMask;
    138      if(  traverseIdent == SWT.TRAVERSE_PAGE_NEXT         //the pg-dn key in SWT
    139        || traverseIdent == SWT.TRAVERSE_PAGE_PREVIOUS   //the pg-up key in SWT
    140        || key == '\t' && keyModifier == SWT.CTRL
    141        ) {
    142        event.doit = false;
    143      }
    144      stop();
    145    }
    146
    147  };
    148
    149
    150  ShellListener mainComponentListerner = new ShellListener()
    151  {
    152
    153
    154    @Override
    155    public void shellActivated(ShellEvent e) {
    156      // TODO Auto-generated method stub
    157
    158    }
    159
    160    @Override
    161    public void shellClosed(ShellEvent e) {
    162      // TODO Auto-generated method stub
    163
    164    }
    165
    166    @Override
    167    public void shellDeactivated(ShellEvent e) {
    168      // TODO Auto-generated method stub
    169
    170    }
    171
    172    @Override
    173    public void shellDeiconified(ShellEvent e) {
    174      // TODO Auto-generated method stub
    175
    176    }
    177
    178    @Override
    179    public void shellIconified(ShellEvent e) {
    180      // TODO Auto-generated method stub
    181
    182    }
    183
    184  };
    185
    186
    187
    188
    189  //final String sTitle;
    190  //final int xPos, yPos, xSize, ySize;
    191
    192  SwtGraphicThread(GralWindow windowGral, char sizeShow, LogMessage log)
    193  { super(sizeShow, windowGral, log);
    194    startThread();
    195    //this.sTitle = sTitle;
    196    //this.xPos = left; this.yPos = top; this.xSize = xSize; this.ySize = ySize;
    197  }
    198
    199
    200
    201
    202
    203
    204  /**
    205   * @see org.vishia.gral.base.GralGraphicThread#initGraphic()
    206   */
    207  @Override protected void initGraphic(){
    208    displaySwt = new Display();  //The organization class of the whole graphic independent of a concrete window.
    209    displaySwt.addFilter(SWT.Close, windowsCloseListener);
    210    displaySwt.addFilter(SWT.Traverse, traverseKeyFilter);
    211    SwtProperties propertiesGui = new SwtProperties(this.displaySwt, sizeCharProperties);
    212    gralMng = new SwtMng(displaySwt, propertiesGui, log);
    213
    214  }
    215
    216  void XXX_Old_createWindow__(){
    217
    218    SwtSubWindow windSwt = new SwtSubWindow(gralMng, mainWindow);
    219
    220    gralMng.mng.registerPanel(mainWindow);
    221
    222    windowSwt = windSwt.window; //, SWT.ON_TOP | SWT.MAX | SWT.TITLE);
    223    //windowSwt.addKeyListener(keyListener);
    224    //windowSwt.addTraverseListener(keyTraverse);
    225
    226    //graphicFramePos = new Position(graphicFrame.getContentPane());
    227    //graphicFramePos.set(0,0,xSize,ySize);
    228    // main = this;
    229    //windowSwt.setText(mainWindow.getText());
    230    //
    231    //set a menu bar anyway. Otherwise the calculation of used area of the window may be faulty
    232    //if it is calculated first, and after them menu items are added.
    233    //It isn't able to expected that the user won't have a menu bar in a primary window.
    234    Menu menuBar = new Menu(windowSwt, SWT.BAR);
    235    windowSwt.setMenuBar(menuBar);
    236    //graphicFrame.getContentPane().setLayout(new BorderLayout());
    237    //graphicFrame.addWindowListener(new WindowClosingAdapter(true));
    238    //graphicFrame.setSize( xSize, ySize );
    239    //if(xSize == -1 || ySize == -1){
    240      //windowSwt.setMaximized(true);
    241    //} else {
    242      //windowSwt.setBounds(xPos,yPos, xSize, ySize );  //Start position.
    243    //}
    244    windowSwt.open();
    245
    246    //graphicFrame.getContentPane().setLayout(new FlowLayout());
    247    windowSwt.setLayout(null);
    248    windowSwt.addShellListener(mainComponentListerner);
    249
    250
    251    //The propertiesGuiSwt needs the Display instance for Font and Color. Therefore the graphic thread with creation of Display should be executed before.
    252    //mainWindow.setPanelMng(gralMng);
    253    //int windProps = GralWindow_ifc.windResizeable;
    254    //GralWindow windowGral = new GralWindow("main", sTitle, windProps, gralMng, null );
    255
    256    //The PrimaryWindowSwt is a derivation of the GralPrimaryWindow. It is more as only a SWT Shell.
    257    //instance = new SwtPrimaryWindow(windowGral, gralMng, this, this.displaySwt);
    258    ///
    259
    260  }
    261
    262
    263  @Override
    264  protected boolean dispatchOsEvents()
    265  { return displaySwt.readAndDispatch();
    266  }
    267
    268  @Override
    269  protected void graphicThreadSleep()
    270  {
    271    displaySwt.sleep ();
    272  }
    273
    274
    275  /**Yet Experience: SWT knows the {@link Display#asyncExec(Runnable)}.
    276   * @param exec
    277   */
    278  protected void addToGraphicImplThread(Runnable exec){
    279    displaySwt.asyncExec(exec);
    280  }
    281
    282  @Override
    283  public void wakeup(){
    284    if(displaySwt == null){
    285
    286    }
    287    displaySwt.wake();
    288    //extEventSet.set(true);
    289    //isWakedUpOnly = true;
    290  }
    291
    292
    293
    294  void stop(){}
    295
    296}