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}