001package org.vishia.gral.base; 002 003import org.vishia.gral.ifc.GralFactory; 004import org.vishia.gral.ifc.GralMngBuild_ifc; 005import org.vishia.gral.ifc.GralMng_ifc; 006import org.vishia.gral.ifc.GralRectangle; 007import org.vishia.gral.ifc.GralUserAction; 008import org.vishia.gral.ifc.GralWidget_ifc; 009import org.vishia.gral.ifc.GralWindow_ifc; 010import org.vishia.msgDispatch.LogMessage; 011import org.vishia.msgDispatch.LogMessageStream; 012 013/**This class represents a window of an application, either the primary window or any sub window. 014 * The {@link GralPos#pos} of the baseclass is the position of the window derived from any other 015 * Position. 016 * @author Hartmut Schorrig 017 * 018 */ 019public class GralWindow extends GralPanelContent implements GralWindow_ifc 020{ 021 022 /**Version, history and license. 023 * <ul> 024 * <li>2016-09-23 Hartmut chg: {@link #create(String, char, LogMessage, GralGraphicTimeOrder)} now needs an obligate argument which can be null 025 * for the first callback routine for graphic initializing. 026 * <li>2016-09-18 Hartmut chg: renaming {@link #specifyActionOnCloseWindow(GralUserAction)} instead 'setActionOnSettingInvisible', more expressive name. 027 * <li>2016-08-28 Hartmut new {@link #create(String, char, LogMessage, GralGraphicTimeOrder)} to create either the primary window inclusive the whole graphic machine, 028 * or create any secondary window. 029 * <li>2015-05-31 Hartmut The {@link GraphicImplAccess} is now derived from {@link GralPanelContent.ImplAccess} 030 * because this class is derived from that too. Parallel inheritance. 031 * <li>2013-12-19 Hartmut bugfix: {@link #setFullScreen(boolean)} now works. 032 * <li>2013-12-19 Hartmut new: Now it is able to instantiate without Graphic Layer and {@link #setToPanel(GralMngBuild_ifc)} 033 * is supported. 034 * <li>2012-04-16 Hartmut new: {@link #actionResizeOnePanel} 035 * <li>2012-03-13 Hartmut chg: Some abstract method declarations moved to its interface. 036 * <li>2011-12-31 Hartmut chg: Implements the set-methods of {@link GralWindow_ifc} in form of calling 037 * {@link GralMng_ifc#setInfo(GralWidget, int, int, Object, Object)}. This methods 038 * can be called in any thread, it may be stored using 039 * {@link GralGraphicThread#addRequ(org.vishia.gral.base.GralWidgetChangeRequ)}. 040 * <li>2011-11-27 Hartmut new: {@link #addMenuBarItemGThread(String, String, GralUserAction)} copied 041 * from {@link org.vishia.gral.ifc.GralPrimaryWindow_ifc}. The capability to have a menu bar 042 * should be enabled for sub-windows too. To support regularity, the property bit {@link #windHasMenu} 043 * is created. The property whether a window has a menu bar or not should be given on creation already. 044 * <li>2011-11-27 Hartmut new: {@link #windProps} now stored for all implementations here. 045 * {@link #visibleFirst}: Maybe a problem while creation a menu bar in SWT (?) 046 * <li>2011-11-18 Hartmut new: {@link #windExclusive} etc. as properties for creation a window. 047 * <li>2011-11-12 Hartmut chg: Because the {@link GralPanelContent} inherits {@link GralWidget} 048 * and this class has a {@link GralWidget#pos}, the member 'posWindow' is removed. 049 * <li>2011-10-31 Hartmut new: {@link #setResizeAction(GralUserAction)} and {@link #setMouseAction(GralUserAction)} 050 * for operations with the whole window. 051 * <li>2011-10-30 Hartmut new: {@link #resizeAction} 052 * <li>2011-09-23 Hartmut new: member GralGridPos: Position of the window. The position is referred 053 * to any Panel in another Window. It can be tuned and it is used if the Window is set visible. 054 * <li>2011-09-18 Hartmut creation: Now a PrimaryWindow and a SubWindow are defined. 055 * </ul> 056 * 057 * <b>Copyright/Copyleft</b>: 058 * For this source the LGPL Lesser General Public License, 059 * published by the Free Software Foundation is valid. 060 * It means: 061 * <ol> 062 * <li> You can use this source without any restriction for any desired purpose. 063 * <li> You can redistribute copies of this source to everybody. 064 * <li> Every user of this source, also the user of redistribute copies 065 * with or without payment, must accept this license for further using. 066 * <li> But the LPGL is not appropriate for a whole software product, 067 * if this source is only a part of them. It means, the user 068 * must publish this part of source, 069 * but doesn't need to publish the whole source of the own product. 070 * <li> You can study and modify (improve) this source 071 * for own using or for redistribution, but you have to license the 072 * modified sources likewise under this LGPL Lesser General Public License. 073 * You mustn't delete this Copyright/Copyleft inscription in this source file. 074 * </ol> 075 * If you intent to use this source without publishing its usage, you can get 076 * a second license subscribing a special contract with the author. 077 * 078 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 079 * 080 * 081 */ 082 @SuppressWarnings("hiding") 083 public static final String version = "2016-08-28"; 084 085 /**Standard action for resizing, used if the window contains one panel. 086 * It calls {@link GralMng_ifc#resizeWidget(GralWidget, int, int)} 087 * for all widgets in the {@link GralPanelContent#widgetsToResize} 088 */ 089 protected class ActionResizeOnePanel extends GralUserAction 090 { 091 ActionResizeOnePanel(){ super("actionResizeOnePanel - window: " + GralWindow.this.name); } 092 @Override public boolean exec(int keyCode, GralWidget_ifc widgi, Object... params) 093 { for(GralWidget widgd: widgetsToResize){ 094 if(widgd instanceof GralWindow) { 095 System.err.println("GralWindow.ActionResizeOnePanel - A window itself should not be added to widgetsToResize"); 096 } else { 097 widgd.gralMng().impl.resizeWidget(widgd, 0, 0); 098 } 099 } 100 return true; 101 } 102 }; 103 104 /**Or of some wind... constants. 105 */ 106 int windProps; 107 108 /**This action is called whenever the window is resized by user handling on GUI 109 * and the window is determined as {@link GralWindow_ifc#windResizeable}. 110 * Per default an instance of {@link ActionResizeOnePanel} is called. 111 * See {@link GralWindow_ifc#setResizeAction(GralUserAction)}. */ 112 protected GralUserAction resizeAction; 113 114 protected GralUserAction actionOnCloseWindow; 115 116 /**See {@link GralWindow_ifc#setMouseAction(GralUserAction)}. */ 117 protected GralUserAction mouseAction; 118 119 protected GralMenu menuBarGral; 120 121 protected boolean visibleFirst; 122 123 /**State of visible, fullScreen, close set by {@link #setVisible(boolean)}, {@link #setFullScreen(boolean)}, 124 * {@link #closeWindow()} called in another thread than the graphic thread. It is stored here 125 * and executed in the {@link GralWidgImpl_ifc#repaintGthread()}. */ 126 protected boolean XXXbVisible, bFullScreen, bShouldClose; 127 128 129 130 /**Constructs a window. 131 * 132 * @param nameWindow 133 * @param windProps 134 * @param mng 135 * @param panelComposite The implementing instance for a panel. 136 * @deprecated: the panelComposite is not used. The GralMng is singleton. use {@link GralWindow#GralWindow(String, String, String, int)}. 137 */ 138 @Deprecated public GralWindow(String posString, String nameWindow, String sTitle, int windProps, GralMng mng, Object panelComposite) 139 { 140 super( posString, nameWindow, 'w'); //relative Window position. 141 dyda.displayedText = sTitle; //maybe null 142 this.windProps = windProps; 143 if((windProps & windResizeable)!=0){ 144 resizeAction = new ActionResizeOnePanel(); 145 } 146 147 } 148 149 150 151 /**Constructs a window. 152 * @param posString the position relative to a given position of the parent window. "!" on top level window. 153 * @param nameWindow 154 * @param sTitle 155 * @param windProps See {@link GralWindow_ifc#windResizeable} etc. 156 */ 157 public GralWindow(String posString, String nameWindow, String sTitle, int windProps) 158 { 159 super( posString, nameWindow, 'w'); //relative Window position. 160 dyda.displayedText = sTitle; //maybe null 161 this.windProps = windProps; 162 if((windProps & windResizeable)!=0){ 163 resizeAction = new ActionResizeOnePanel(); 164 } 165 166 } 167 168 @Override public void specifyActionOnCloseWindow(GralUserAction action) 169 { actionOnCloseWindow = action; 170 } 171 172 173 174 /**Creates the window. Either the {@link GralGraphicThread#isRunning()} already then it is a second window. 175 * If the graphic thread is not running, it would be started and this is the primary window. 176 * The it invokes {@link GralFactory#createGraphic(GralWindow, char, LogMessage, String)}. 177 * The application should not know whether it is the primary or any secondary window. 178 * That helps for applications which are started from a Gral graphic application itself without an own operation system process. 179 * @param awtOrSwt see {@link GralFactory#createGraphic(GralWindow, char, LogMessage, String)} 180 * @param size 'A'..'G', 'A' is a small size, 'G' is the largest. 181 * @param log maybe null. If not given a {@link LogMessageStream} with System.out will be created. For internal logging. 182 * @param initializeInGraphicThread maybe null, an order which will be executed in the graphic thread after creation of the window. 183 */ 184 public void create(String awtOrSwt, char size, LogMessage log, GralGraphicTimeOrder initializeInGraphicThread){ 185 if(_wdgImpl !=null) throw new IllegalStateException("window already created."); 186 GralMng mng = GralMng.get(); 187 GralGraphicThread gthread = mng.gralDevice(); 188 if(gthread.isRunning()) { 189 gthread.addDispatchOrder(createImplWindow); 190 } else { 191 //it is the primary window, start the graphic with it. 192 if(log == null) { log = new LogMessageStream(System.out); } 193 gthread = GralFactory.createGraphic(this, size, log, awtOrSwt); 194 } 195 if(initializeInGraphicThread !=null) { 196 gthread.addDispatchOrder(initializeInGraphicThread); 197 } 198 } 199 200 201 @Override public void setWindowVisible(boolean visible){ 202 setVisible(visible); 203 } 204 205 206 @Override public void closeWindow(){ 207 setVisible(false); 208 } 209 210 211 212 @Override public boolean remove() { 213 super.remove(); 214 itsMng.deregisterPanel(this); 215 return true; 216 } 217 218 @Override 219 public GralRectangle getPixelPositionSize() 220 { 221 return _wdgImpl.getPixelPositionSize(); 222 } 223 224 225 226 227 /**It assumes that the window implementation is present. 228 * It calls {@link GralWindowImpl_ifc#addMenuBarArea9ItemGThread(String, String, GralUserAction)} 229 * with the known {@link GralWidget#_wdgImpl} instance 230 * to invoke the graphic implementation layer method for the window. 231 * @deprecated use {@link #getMenuBar()} and then {@link GralMenu#addMenuItem(String, String, GralUserAction)} 232 * */ 233 @Override @Deprecated 234 public void addMenuBarItemGThread(String nameMenu, String sMenuPath, GralUserAction action) 235 { GralMenu menu = getMenuBar(); 236 menu.addMenuItem(nameMenu, sMenuPath, action); 237 //((GralWindowImpl_ifc)wdgImpl).addMenuItemGThread(nameMenu, sMenuPath, action); 238 } 239 240 241 242 /**Gets the menu bar to add a menu item. If this window hasn't a gral menu bar, then the menu bar 243 * is created by calling {@link GralMng#createMenuBar(GralWindow)}. 244 * If the window has a menu bar already, it is stored in the reference {@link #menuBarGral}. 245 * @return the menu root for this window. 246 */ 247 public GralMenu getMenuBar(){ 248 if(menuBarGral == null){ 249 menuBarGral = itsMng.createMenuBar(this); //delegation, the widget mng knows the implementation platform. 250 } 251 return menuBarGral; 252 } 253 254 255 256 257 258 @Override 259 public void setMouseAction(GralUserAction action) 260 { 261 mouseAction = action; 262 //repaint(repaintDelay, repaintDelayMax); 263 } 264 265 266 267 @Override 268 public void setResizeAction(GralUserAction action) 269 { resizeAction = action; 270 //repaint(repaintDelay, repaintDelayMax); 271 } 272 273 274 275 @Override 276 public void setTitle(String sTitle) 277 { 278 dyda.displayedText = sTitle; 279 dyda.setChanged(ImplAccess.chgText); 280 repaint(repaintDelay, repaintDelayMax); 281 } 282 283 284 @Override 285 public void setFullScreen(boolean val){ 286 if(bFullScreen !=val){ 287 bFullScreen = val; 288 repaint(); 289 } 290 } 291 292 293 @Override 294 public boolean isWindowsVisible() 295 { 296 return bVisibleState; 297 } 298 299 300 /**This class is not intent to use from an application, it is the super class for the implementation layer 301 * to access all necessary data and methods with protected access rights. 302 * The methods are protected because an application should not use it. This class is public because 303 * it should be visible from the graphic implementation which is located in another package. 304 */ 305 public abstract static class GraphicImplAccess extends GralPanelContent.ImplAccess //access to GralWidget 306 implements GralWidgImpl_ifc 307 { 308 309 protected final GralWindow gralWindow; //its outer class. 310 311 protected GraphicImplAccess(GralWindow gralWdg){ 312 super(gralWdg); 313 this.gralWindow = gralWdg; //References the environment class 314 } 315 316 /**The title is stored in the {@link GralWidget.DynamicData#displayedText}. */ 317 protected String getTitle(){ return gralWindow.dyda.displayedText; } 318 319 /**Window properties as Gral bits given on ctor of GralWindow. */ 320 protected int getWindowProps(){ return gralWindow.windProps; } 321 322 323 324 //protected boolean isVisible(){ return gralWindow.bVisible; } 325 326 protected boolean isFullScreen(){ return gralWindow.bFullScreen; } 327 328 protected boolean shouldClose(){ return gralWindow.bShouldClose; } 329 330 /**The resizeAction from the {@link GralWindow_ifc#setResizeAction(GralUserAction)} */ 331 protected GralUserAction resizeAction(){ return gralWindow.resizeAction; } 332 333 /**The mouseAction from the {@link GralWindow_ifc#setMouseAction(GralUserAction)} */ 334 protected GralUserAction mouseAction(){ return gralWindow.mouseAction; } 335 336 /**The invisibleSetAction from the {@link GralWindow_ifc#specifyActionOnCloseWindow(GralUserAction)} */ 337 protected GralUserAction actionOnCloseWindow(){ return gralWindow.actionOnCloseWindow; } 338 339 340 341 342 343 344 } 345 346 347 348 /**Code snippet for initializing the GUI area (panel). This snippet will be executed 349 * in the GUI-Thread if the GUI is created. 350 */ 351 GralGraphicTimeOrder createImplWindow = new GralGraphicTimeOrder("GralWindow.createImplWindow") 352 { 353 @Override public void executeOrder() 354 { GralMng mng = GralMng.get(); 355 mng.selectPrimaryWindow(); 356 GralWindow.this.createImplWidget_Gthread(); 357 GralWindow.this.setVisible(true); 358 } 359 }; 360 361 362 363 364}