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}