    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}