    001package org.vishia.gral.area9;
    002
    003import java.io.File;
    004import java.io.IOException;
    005import java.util.Queue;
    006import java.util.concurrent.ConcurrentLinkedQueue;
    007
    008import org.vishia.gral.base.GralGraphicTimeOrder;
    009import org.vishia.gral.base.GralMenu;
    010import org.vishia.gral.base.GralPanelContent;
    011import org.vishia.gral.base.GralPos;
    012import org.vishia.gral.base.GralWidget;
    013import org.vishia.gral.base.GralWindow;
    014import org.vishia.gral.base.GralMng;
    015import org.vishia.gral.base.GralTextBox;
    016import org.vishia.gral.ifc.GralFileDialog_ifc;
    017import org.vishia.gral.ifc.GralPrimaryWindow_ifc;
    018import org.vishia.gral.ifc.GralRectangle;
    019import org.vishia.gral.ifc.GralUserAction;
    020import org.vishia.gral.ifc.GralTextBox_ifc;
    021import org.vishia.gral.ifc.GralWindow_ifc;
    022import org.vishia.gral.widget.GralInfoBox;
    023import org.vishia.mainCmd.MainCmd;
    024import org.vishia.mainCmd.MainCmd_ifc;
    025import org.vishia.util.FileSystem;
    026
    027/**This class presents a Window appearance with up to 9 areas as base for a user's application with several areas
    028 * of the main window and some sub windows.
    029 * The areas of the window can be used in several forms:
    030 * <pre>
    031 * +================================================================================+
    032 * |                |                                                |              +
    033 * |                |                                                |              +
    034 * |                |                                                |              +
    035 * |                |       central working area                     |   other      +
    036 * |     any        |                                                |   list       +
    037 * |     list       |                                                |              +
    038 * |                |                                                |              +
    039 * |                |                                                |              +
    040 * |                +---------------------------------------------------------------+
    041 * |                |                                                               +
    042 * |                |      status or output area                                   +
    043 * |                |                                                               +
    044 * |                |                                                               +
    045 * +================================================================================+
    046 *
    047 * +================================================================================+
    048 * |                |                                                               +
    049 * |                |                                                               +
    050 * |                |                                                               +
    051 * |                |       central working area                                    +
    052 * |     any        |                                                               +
    053 * |     list       |                                                               +
    054 * |                |                                                               +
    055 * |                |                                                               +
    056 * |                |                                                               +
    057 * |                |                                                               +
    058 * |--------------------------------------------------------------------------------+
    059 * |                       status line                                              +
    060 * +================================================================================+
    061 *
    062 * +================================================================================+
    063 * |                |                           |                                   +
    064 * |                |     one                   |            other                  +
    065 * |     any        |     panel                 |            panel                  +
    066 * |     list       |                           |                                   +
    067 * |                |                           |                                   +
    068 * |                |                           |                                   +
    069 * |----------------+---------------------------+-----------------------------------+
    070 * |                                                                                +
    071 * |            input area                                                          +
    072 * |----------------+---------------------------------------------------------------+
    073 * |                |                                                               +
    074 * |   info         |      status or output area                                    +
    075 * |   area         |                                                               +
    076 * |                |                                                               +
    077 * +================================================================================+
    078 * </pre>
    079 * or any other partitioning.
    080 * <br><br>
    081 * The main window has a menu bar which has some default entries:
    082 * <br><br>
    083 * The following sub windows are created:
    084 * <ul>
    085 * <li>{@link #infoHelp}: Window will be opened with key [F1] or menu help.  initially call {@link #setHelpBase(String)},
    086 *   then call {@link #setHelpUrl(String)} respectively set {@link GralWidget#setHtmlHelp(String)} for any widget.
    087 * <li>{@link #infoBox}: Window will be opened via menu or on demand if anything should be shown. Fill it with
    088 *   infoBox. {@link GralInfoBox#setText(CharSequence)}, {@link GralInfoBox#setText(CharSequence, int)} or
    089 *   {@link GralInfoBox#append(CharSequence)}. The info box should be used for on demand. it will be overridden
    090 *   and reused if necessary later.
    091 * <li>{@link #infoLog}: Window will be opened via menu or on demand if anything should be shown. Fill it with
    092 *   infoLog.{@link GralInfoBox#append(CharSequence)}.
    093 * <li>{@link #infoAbout}: Window will be opened with menu about. This box will be filled given with the content from
    094 *   {@link #mainCmd}. {@link MainCmd#addAboutInfo(String)} from the given MainCmd instance for {@link GralArea9Window#GralArea9Window(MainCmd, GralWindow)}.
    095 * </ul>
    096 *
    097 * @author hartmut
    098 *
    099 */
    100public class GralArea9Window implements GralArea9_ifc
    101{
    102
    103  /**Version and History
    104   * <ul>
    105   * <li>2015-10-26 Hartmut chg Help in now an integral part of the {@link GralMng}, but invoked here. This class in not change in functinality.
    106   * <li>2014-02-24 Hartmut new {@link #setHelpBase(String)} used in {@link #setHelpUrl(String)}.
    107   * <li>2012-05-17 Hartmut new: {@link #setMinMaxSizeArea(String, int, int, int, int)}: The size can be given
    108   *   with gral units, as min, max or absolute (min, max are equal). The size of a area border can be changed on runtime.
    109   * <li>2012-04-22 Hartmut new: {@link #setFullScreen(boolean)}
    110   * <li>2011-12-26 Hartmut chg: The help window is a html info box now. New method {@link #setHelpUrl(String)}
    111   *   supports context sensitive help.
    112   * <li>2011-11-12 Hartmut new: The SubWindow for Help, About, InfoBox and InfoLog are created here (InfoLog: TODO).
    113   *   This windows can be opened in demand.
    114   * <li>2011-11-12 Hartmut chg: All menu items should be prepared in the users application now. The items for help and about
    115   *   are supported with actions by {@link #getActionAbout()} and {@link #getActionAbout()}. This actions
    116   *   are the standard behavior and opens the sub-windows only. But the user can install a more complex functionality
    117   *   for example writing a context sensitive help.
    118   * <li>2011-11-12 Harmut chg {@link #initGraphic} was the old initOutputArea, but it does more as only the output area.
    119   *   Now creation of all necessities of Graphic in this functionality.
    120   *
    121   * </ul>
    122   *
    123   * <b>Copyright/Copyleft</b>:
    124   * For this source the LGPL Lesser General Public License,
    125   * published by the Free Software Foundation is valid.
    126   * It means:
    127   * <ol>
    128   * <li> You can use this source without any restriction for any desired purpose.
    129   * <li> You can redistribute copies of this source to everybody.
    130   * <li> Every user of this source, also the user of redistribute copies
    131   *    with or without payment, must accept this license for further using.
    132   * <li> But the LPGL ist not appropriate for a whole software product,
    133   *    if this source is only a part of them. It means, the user
    134   *    must publish this part of source,
    135   *    but don't need to publish the whole source of the own product.
    136   * <li> You can study and modify (improve) this source
    137   *    for own using or for redistribution, but you have to license the
    138   *    modified sources likewise under this LGPL Lesser General Public License.
    139   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    140   * </ol>
    141   * If you are indent to use this sources without publishing its usage, you can get
    142   * a second license subscribing a special contract with the author.
    143   *
    144   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    145   *
    146   *
    147   */
    148  public final static int version = 0x20120303;
    149
    150  public final MainCmd mainCmd;
    151
    152  //protected final GralWindowMng gralDevice;
    153
    154  protected final GralWindow window;
    155
    156  /**Area settings for output. */
    157  protected String outputArea;
    158
    159  protected GralPanelContent outputPanel;
    160
    161  /**A Text box which is used for common output. It may be edit-able.
    162   * This output box is created initially. It can be used to show error messages while starting the application
    163   * if other GUI-elements are not yet present. It can be used generally to show errors, infos and logs
    164   * adequate to a console output.*/
    165  public GralTextBox outputBox;
    166
    167
    168  private GralInfoBox infoAbout;
    169
    170  /** Current Directory for file choosing. */
    171  protected File currentDirectory = null;
    172
    173  protected GralUserAction actionFile;
    174
    175  /**Set on call of {@link #setStandardMenus(File)} to add in in the graphic thread. */
    176  protected boolean bSetStandardMenus;
    177
    178  protected Queue<String> outputTexts = new ConcurrentLinkedQueue<String>();
    179
    180
    181  /**All main components of the Display in each FrameArea. */
    182  protected GralPanelContent[][] componentFrameArea = new GralPanelContent[3][3];
    183
    184
    185  /**A little control to capture the mouse position for movement of area borders. */
    186  //private GralWidgetImplWrapper[] yAreaMover = new GralWidgetImplWrapper[2];
    187
    188
    189
    190  /**Position of the FrameArea borders in percent.
    191   * [0] is always 0, [1] and [2] are the given borders, [3] is always 100.
    192   * It is because lower and higher bound should be accessed always without tests.
    193   * Use area +1, because it is a Off-by-one problem */
    194  protected byte xpFrameArea[] = new byte[4],
    195               ypFrameArea[] = new byte[4];
    196
    197  /**spread of each frame area in x direction.
    198   * It it is -1, than the area is occupied by another area.
    199   * If it is 0, the area is free.
    200   * 1..3 are the number of areas in horizontal direction.
    201   */
    202  protected byte[][][] dxyFrameArea = new byte[3][3][2];
    203
    204  /**requested minimal size of each window area in GralPos units. If the minimal value is 0,
    205   * the size is calculated from percent always. If the minimal value of percent calculation is lesser
    206   * than this value, this value is used. Note that a given minimal value of all areas cannot required
    207   * if the window's size is lesser. Then the middle area will
    208   */
    209  private final short[] xMinGralSize = new short[3], yMinGralSize = new short[3];
    210
    211  /**requested maximal size of each window area in GralPos units. If the maximal value is greater than
    212   * the size calculated from percent always, the percent value is used.
    213   * Note that a given maximal value of all areas cannot regarded
    214   * if the window's size is greater. Then the middle area will be presented
    215   */
    216  private final short[] xMaxGralSize = new short[3], yMaxGralSize = new short[3];
    217
    218  /**Calculated borders of areas.
    219   * [0] is always 0, [1] and [2] are the given borders, [3] is always 100.
    220   * It is because lower and higher bound should be accessed always without tests.
    221   * Use area +1, because it is a Off-by-one problem */
    222  private final int[] xPixArea = new int[4], yPixArea = new int[4];
    223
    224  /**Number of pixels per percent unit of size, set if {@link #validateFrameAreas()} was called. */
    225  protected float pixelPerXpercent = 1, pixelPerYpercent =1;
    226
    227  /** The interface to the application. */
    228  //private final MainApplicationWin_ifc application;
    229
    230  /**The id of the thread, which created the display.
    231   * It is to check whether gui-commands should be queued or not. */
    232  //protected long idThreadGui;
    233
    234  final protected StringBuffer XXXsbWriteInfo = new StringBuffer(1000);  //max. 1 line!
    235
    236  /** If it is set, the writeInfo is redirected to this.*/
    237  protected GralTextBox_ifc textAreaOutput = null;
    238
    239
    240  /**Sets the output window to a defined area. .
    241   * Adds the edit-menu too.
    242   * @param xArea 1 to 3 for left, middle, right, See {@link #setFrameAreaBorders(int, int, int, int)}
    243   * @param yArea 1 to 3 for top, middle, bottom
    244   * @param dxArea 1 to 3 for 1 field to 3 fields to right.
    245   * @param dyArea 1 to 3 for 1 field to 3 field to bottom
    246   */
    247  public void XXXsetOutputArea(String area){
    248    outputArea = area;
    249  }
    250
    251  //private GuiMainAreaBase(MainCmd mainCmd){ this.mainCmd = mainCmd; }
    252
    253  /**
    254   * @param mainCmd Aggregation to a MainCmd implemenation.
    255   * @param guiDevice The window manager
    256   * @param window The window itself. It doesn't be the primary window but a sub window too.
    257   */
    258  public GralArea9Window(MainCmd mainCmd, GralWindow window)
    259  {
    260    super();
    261    this.mainCmd = mainCmd;
    262    //this.gralDevice = guiDevice;
    263    this.window = window;
    264    for(int ix = 0; ix < 3; ++ix) for(int iy = 0; iy < 3; ++iy){
    265      xMinGralSize[ix] = 4;
    266      yMinGralSize[iy] = 4;
    267      xMaxGralSize[ix] = Short.MAX_VALUE;
    268      yMaxGralSize[iy] = Short.MAX_VALUE;
    269    }
    270  }
    271
    272
    273  /**Initializes the output area, can be called after construction immediately.
    274   * @param sOutputArea String for example "A3C3". The letter character is the column. The digit is the row.
    275   * It is fromTo. The example means the whole bottom area.
    276   */
    277  @Override public void initGraphic(String sOutputArea){
    278    this.outputArea = sOutputArea;
    279    window.gralMng().gralDevice.addDispatchOrder(initGraphic);
    280    initGraphic.awaitExecution(1, 0);
    281    window.gralMng().gralDevice.addDispatchOrder(writeOutputTextDirectly);
    282
    283  }
    284
    285
    286
    287  GralGraphicTimeOrder initGraphic = new GralGraphicTimeOrder("GralArea9Window.initGraphic"){
    288    @Override public void executeOrder()
    289    {
    290      window.setResizeAction(resizeAction);   //sets the resize action from this instead a standard window for the primaryWindow.
    291      setFrameAreaBorders(30,70,30,70);
    292      if(bSetStandardMenus){
    293        //setStandardMenusGThread(currentDirectory, actionFile);
    294      }
    295      GralMng.get().createHtmlInfoBoxes(mainCmd);
    296      //
    297      window.gralMng().selectPanel("primaryWindow");
    298      window.gralMng().setPosition(0,20,15,GralPos.size + 50,0,'.');
    299      infoAbout = window.gralMng().createTextInfoBox("About", "About");
    300      try{
    301        for(String line: mainCmd.listAboutInfo){
    302          infoAbout.append(line).append("\n");
    303        }
    304      } catch(Exception exc){ window.gralMng().writeLog(0, exc); }
    305      //
    306
    307
    308      if(outputArea != null){
    309        outputPanel = addOutputFrameArea(outputArea);
    310        //window.gralMng().registerPanel(outputPanel);
    311      }
    312    }
    313  };
    314
    315
    316
    317  @Override public MainCmd_ifc getMainCmd(){ return mainCmd; }
    318
    319  @Override public GralWindow_ifc mainWindow(){ return window; }
    320
    321  @Override public GralPanelContent getOutputPanel(){ return outputPanel; } ///
    322
    323  @Override public GralTextBox getOutputBox(){ return outputBox; }
    324
    325
    326
    327
    328  /**Sets the divisions of the frame. The frame is divide into 9 parts,
    329   * where two horizontal and two vertical lines built them:
    330   * <pre>
    331   * +=======+===============+===========+
    332   * |       |               |           |
    333   * +-------+---------------+-----------+
    334   * |       |               |           |
    335   * |       |               |           |
    336   * +-------+---------------+-----------+
    337   * |       |               |           |
    338   * |       |               |           |
    339   * +=======+===============+===========+
    340   * </pre>
    341   *
    342   * @param x1p percent from left for first vertical divide line.
    343   * @param x2p percent from left for second vertical divide line.
    344   * @param y1p percent from left for first horizontal divide line.
    345   * @param y2p percent from left for first horizontal divide line.
    346   */
    347  @Override public void setFrameAreaBorders(int x1p, int x2p, int y1p, int y2p)
    348  { xpFrameArea[0] = 0;
    349    xpFrameArea[1] = (byte)x1p;
    350    xpFrameArea[2] = (byte)x2p;
    351    xpFrameArea[3] = 100;
    352    ypFrameArea[0] = 0;
    353    ypFrameArea[1] = (byte)y1p;
    354    ypFrameArea[2] = (byte)y2p;
    355    ypFrameArea[3] = 100;
    356    validateFrameAreas();
    357  }
    358
    359
    360
    361
    362  @Override public void addFrameArea(String sArea, GralPanelContent component)
    363  throws IndexOutOfBoundsException {
    364    GralRectangle r = convertArea(sArea);
    365    addFrameArea(r.x, r.y, r.dx, r.dy, component);
    366  }
    367
    368
    369  /**Sets a Component into a defined area. See {@link #setFrameAreaBorders(int, int, int, int)}.
    370   * It should be called only in the GUI-Thread.
    371   * @param xArea 1 to 3 for left, middle, right
    372   * @param yArea 1 to 3 for top, middle, bottom
    373   * @param dxArea 1 to 3 for 1 field to 3 fields to right.
    374   * @param dyArea 1 to 3 for 1 field to 3 field to bottom
    375   * @param component The component.
    376   * @throws IndexOutOfBoundsException if the arguments are false or the area is occupied already.
    377   */
    378  @Override public final void addFrameArea(int xArea, int yArea, int dxArea, int dyArea, GralPanelContent component)
    379  throws IndexOutOfBoundsException
    380  { //int idxArea = (x -1) + 3 * (y -1);
    381    //Composite component = new Composite(swtWindow.graphicThreadSwt, SWT.NONE);
    382    if(  xArea <1 || xArea > componentFrameArea[0].length
    383      || dxArea < 1
    384      || xArea+dxArea-2 > componentFrameArea[0].length
    385      || yArea <1 || yArea > componentFrameArea.length
    386      || dyArea < 1
    387      || yArea+dyArea-1 > componentFrameArea.length
    388      )
    389      throw new IndexOutOfBoundsException("failed argument");
    390    for(int idxArea = xArea-1; idxArea <= xArea + dxArea -2; idxArea++)
    391    { for(int idyArea = yArea-1; idyArea <= yArea + dyArea -2; idyArea++)
    392      { if(dxyFrameArea[idyArea][idxArea][0] != 0) throw new IndexOutOfBoundsException("area occupied already");
    393      }
    394    }
    395    for(int idxArea = xArea-1; idxArea <= xArea + dxArea -2; idxArea++)
    396    { for(int idyArea = yArea-1; idyArea <= yArea + dyArea -2; idyArea++)
    397      { dxyFrameArea[idyArea][idxArea][0] = -1; //ocuupy it.
    398      }
    399    }
    400    dxyFrameArea[yArea-1][xArea-1][0] = (byte)dxArea;
    401    dxyFrameArea[yArea-1][xArea-1][1] = (byte)dyArea;
    402    //JScrollPane scrollPane = new JScrollPane(component);
    403    //scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    404    //scrollPane.setViewportView(component);
    405    componentFrameArea[yArea-1][xArea-1] = component; //scrollPane;
    406    //setBoundsForFrameArea(xArea-1, yArea-1);
    407    //scrollPane.validate();
    408    //swtWindow.graphicThreadSwt.add(component); //scrollPane);
    409    /*TODO
    410      ((Control)component.getWidgetImplementation()).addMouseListener(mouseListener);
    411      if(yAreaMover[1] == null){
    412        yAreaMover[1] = new Canvas(swtWindow.graphicThreadSwt.windowSwt, SWT.None);
    413        yAreaMover[1].setSize(10,10);
    414        yAreaMover[1].setBackground(swtWindow.graphicThreadSwt.displaySwt.getSystemColor(SWT.COLOR_GREEN));
    415      }
    416    */
    417    validateFrameAreas();
    418    //return component;
    419  }
    420
    421
    422
    423  @Override public void setMinMaxSizeArea(String sArea, int yMinUnit, int yMaxUnit, int xMinUnit, int xMaxUnit)
    424  throws IndexOutOfBoundsException {
    425    GralRectangle r = convertArea(sArea);
    426    yMinGralSize[r.y -1] = (short)yMinUnit;
    427    yMaxGralSize[r.y -1] = yMaxUnit <=0 ? Short.MAX_VALUE : (short)yMaxUnit;
    428    xMinGralSize[r.x -1] = (short)xMinUnit;
    429    xMaxGralSize[r.x -1] = xMaxUnit <=0 ? Short.MAX_VALUE : (short)xMaxUnit;
    430
    431    validateFrameAreas();
    432  }
    433
    434
    435
    436
    437  /**Set the bounds of all areas.
    438   * Calls {@link GralWindow#getPixelPositionSize()} to get the size of working area of the whole window
    439   *
    440   */
    441  protected void validateFrameAreas()
    442  {
    443    GralRectangle posSize = window.getPixelPositionSize();
    444    //Point size = swtWindow.graphicThreadSwt.windowSwt.getSize();
    445    int xWidth = posSize.dx; // -6; //swtWindow.graphicThreadSwt.getWidth();
    446    int yWidth = posSize.dy; //  -50; //swtWindow.graphicThreadSwt.getHeight() - 50;  //height of title and menu TODO calculate correctly
    447    //Control content = swtWindow.graphicThreadSwt.getContentPane();
    448    //xWidth = content.getWidth();
    449    //yWidth = content.getHeight();
    450    pixelPerXpercent = xWidth / 100.0F;
    451    pixelPerYpercent = yWidth / 100.0F;
    452
    453    int xPixUnit = window.gralMng().propertiesGui().xPixelUnit();
    454    int yPixUnit = window.gralMng().propertiesGui().yPixelUnit();
    455    pixelPerXpercent = xWidth / 100.0F;
    456    pixelPerYpercent = yWidth / 100.0F;
    457
    458    calcPixSize(xPixArea, xpFrameArea, xMinGralSize, xMaxGralSize, xPixUnit, xWidth, pixelPerXpercent);
    459    calcPixSize(yPixArea, ypFrameArea, yMinGralSize, yMaxGralSize, yPixUnit, yWidth, pixelPerYpercent);
    460
    461    for(int idxArea = 0; idxArea <= 2; idxArea++)
    462    { for(int idyArea = 0; idyArea <= 2; idyArea++)
    463      { GralPanelContent component = componentFrameArea[idyArea][idxArea];
    464        if(component !=null)
    465        { //setBoundsForFrameArea(idxArea, idyArea);
    466          int xp = xPixArea[idxArea];
    467          int dxf = dxyFrameArea[idyArea][idxArea][0]; //nr of occupied areas
    468          int xf2 = xPixArea[idxArea + dxf]; //percent right
    469          int dxp =  xf2 - xp;
    470
    471          int yp = yPixArea[idyArea];
    472          int dyf = dxyFrameArea[idyArea][idxArea][1];
    473          int yf2 = yPixArea[idyArea + dyf];
    474          int dyp =  yf2 - yp;
    475          GralPanelContent area = componentFrameArea[idyArea][idxArea];
    476          area.setBoundsPixel(xp, yp, dxp, dyp);
    477          area.repaint();
    478    } } }
    479    /*
    480    for(int ixMover = 0; ixMover < yAreaMover.length; ++ixMover){
    481      if(yAreaMover[ixMover] != null){
    482        int yp = (int)(ypFrameArea[ixMover+1] * pixelPerYpercent);
    483        //TODO it doesn't work yet, not visible, why?:
    484        /*
    485        yAreaMover[ixMover].setBounds(10,yp,10,10);
    486        yAreaMover[ixMover].update();
    487        yAreaMover[ixMover].redraw();
    488        * /
    489      }
    490    }
    491    */
    492    //swtWindow.graphicThreadSwt.update();
    493    //swtWindow.graphicThreadSwt.redraw();
    494    //swtWindow.graphicThreadSwt.update();
    495
    496  }
    497
    498
    499
    500  private void calcPixSize(int[] zPixArea, byte[] zpFrameArea, short[] zMinGralSize, short[] zMaxGralSize
    501    , int zPixUnit, int zSize, float pixelPerZpercent){
    502    int zMinWin = zMinGralSize[0] + zMinGralSize[1] + zMinGralSize[2];
    503    zPixArea[0] = 0;
    504    if(zSize >= (zPixUnit * zMinWin)){
    505      int zPix = 0;
    506      for(int iz=1; iz < 4; ++iz){
    507        int zPix2 = (int)(zpFrameArea[iz] * pixelPerZpercent);
    508        if((zPix2 - zPix) > (zMaxGralSize[iz-1] * zPixUnit)){
    509          zPix2 = zPix + zMaxGralSize[iz-1] * zPixUnit;
    510        }
    511        else if((zPix2 - zPix) < (zMinGralSize[iz-1] * zPixUnit)){
    512          zPix2 = zPix + zMinGralSize[iz-1] * zPixUnit;
    513        }
    514        zPixArea[iz] = zPix = zPix2;
    515      }
    516      if(zPixArea[3] < zSize){
    517        zPixArea[3] = zPix = zSize;
    518        for(int iz=2; iz >=0; --iz){
    519          if(zPix - zPixArea[iz] > zMaxGralSize[iz] * zPixUnit){
    520            zPixArea[iz] = zPix - zMaxGralSize[iz] * zPixUnit;
    521          }
    522          zPix = zPixArea[iz];
    523        }
    524      } else if(zPixArea[3] > zSize){
    525        zPixArea[3] = zPix = zSize;
    526        for(int iz=2; iz >=0; --iz){
    527          if(zPix - zPixArea[iz] < zMinGralSize[iz] * zPixUnit){
    528            zPixArea[iz] = zPix - zMinGralSize[iz] * zPixUnit;
    529          }
    530          zPix = zPixArea[iz];
    531        }
    532      }
    533    } else { //the window is less than the minimal area sizes:
    534      //then the percent are valid, lesser as planned
    535      for(int iz=0; iz < 3; ++iz){
    536        zPixArea[iz] = (int)(zpFrameArea[iz] * pixelPerZpercent);
    537      }
    538    }
    539
    540  }
    541
    542
    543
    544
    545
    546
    547
    548  /**Sets the bounds for the component, which is localized at the given area.
    549   * @param idxArea
    550   * @param idyArea
    551   */
    552  private void setBoundsForFrameArea(int idxArea, int idyArea)
    553  { //Point size = swtWindow.graphicThreadSwt.windowSwt.getSize();
    554    GralRectangle posSize = window.getPixelPositionSize();
    555    int xWidth = posSize.dx -6; //swtWindow.graphicThreadSwt.getWidth();
    556    int yWidth = posSize.dy -53; //swtWindow.graphicThreadSwt.getHeight() - 50;  //height of title and menu TODO calculate correctly
    557    //Control content = swtWindow.graphicThreadSwt.getContentPane();
    558    //xWidth = content.getWidth();
    559    //yWidth = content.getHeight();
    560    pixelPerXpercent = xWidth / 100.0F;
    561    pixelPerYpercent = yWidth / 100.0F;
    562    int xf1 = xpFrameArea[idxArea];  //percent left
    563    int yf1 = ypFrameArea[idyArea];
    564    int dxf = dxyFrameArea[idyArea][idxArea][0]; //nr of occupied areas
    565    int dyf = dxyFrameArea[idyArea][idxArea][1];
    566    int xf2 = xpFrameArea[idxArea + dxf]; //percent right
    567    int yf2 = ypFrameArea[idyArea + dyf];
    568
    569    //calculate pixel size for the component:
    570    int xp = (int)(xf1  * pixelPerXpercent);
    571    int yp = (int)(yf1  * pixelPerYpercent);
    572    int dxp = (int) ((xf2-xf1) * pixelPerXpercent);
    573    int dyp = (int) ((yf2-yf1) * pixelPerYpercent);
    574    int xPixUnit = window.gralMng().propertiesGui().xPixelUnit();
    575    int yPixUnit = window.gralMng().propertiesGui().yPixelUnit();
    576    int xMax = xPixUnit * xMaxGralSize[idxArea];
    577    int xMin = xPixUnit * xMinGralSize[idxArea];
    578    int yMax = xPixUnit * yMaxGralSize[idyArea];
    579    int yMin = xPixUnit * yMinGralSize[idyArea];
    580    GralPanelContent area = componentFrameArea[idyArea][idxArea];
    581    area.setBoundsPixel(xp, yp, dxp, dyp);
    582    area.repaint();
    583  }
    584
    585
    586
    587
    588
    589
    590  /**Converts a string given are designation to indices.
    591   * @param area A, B , C for column, 1, 2, 3 for row.
    592   * @return
    593   */
    594  protected GralRectangle convertArea(String area)
    595  { int x1,x2,y1,y2;
    596    x1 = "ABC".indexOf(area.charAt(0));
    597    if(x1 < 0){x1 = "ABC".indexOf(area.charAt(1));}
    598    y1 = "123".indexOf(area.charAt(0));
    599    if(y1 < 0){y1 = "123".indexOf(area.charAt(1));}
    600    if(area.length() >=2){
    601      x2 = "ABC".indexOf(area.charAt(2));
    602      if(x2 < 0){x2 = "ABC".indexOf(area.charAt(3));}
    603      y2 = "123".indexOf(area.charAt(2));
    604      if(y2 < 0){y2 = "123".indexOf(area.charAt(3));}
    605    } else {
    606      x2 = x1; y2 = y1;
    607    }
    608    GralRectangle ret = new GralRectangle(x1+1, y1+1, x2-x1+1, y2-y1+1);
    609    return ret;
    610  }
    611
    612
    613
    614
    615  public final void setStandardMenus(File openStandardDirectory, GralUserAction actionFile)
    616  { this.currentDirectory = openStandardDirectory;
    617    this.actionFile = actionFile;
    618    this.bSetStandardMenus = true;
    619
    620  }
    621
    622
    623
    624
    625  public final void setStandardMenusGThread(File openStandardDirectory, GralUserAction actionFile)
    626  { this.currentDirectory = openStandardDirectory;
    627    this.actionFile = actionFile;
    628    //if(window instanceof GralPrimaryWindow_ifc)
    629    { //GralPrimaryWindow_ifc pWindow = (GralPrimaryWindow_ifc) window;
    630      //create the menue
    631      window.addMenuBarItemGThread("menuFileOpen", "&File/&Open", this.new GralActionFileOpen());
    632      //swtWindow.addMenuItemGThread("&File/&Close", this.new ActionFileClose());
    633      window.addMenuBarItemGThread("menuFileSave", "&File/&Save", actionFile);
    634      //swtWindow.addMenuItemGThread("&File/E&xit", this.new ActionFileOpen());
    635      //swtWindow.graphicThreadSwt.setJMenuBar(menuBar);
    636      //swtWindow.graphicThreadSwt.setVisible( true );
    637      window.repaint();
    638    //} else {
    639    //  throw new IllegalArgumentException("Error: can't apply menus in a sub window");
    640      //window.getMng().writeLog(0, "Error: can't apply menus in a sub window");
    641    }
    642
    643  }
    644
    645
    646  @Deprecated @Override public void addMenuBarArea9ItemGThread(String name, String sMenuPath, GralUserAction action)
    647  { //if(window instanceof GralPrimaryWindow_ifc)
    648    { //GralPrimaryWindow_ifc pWindow = (GralPrimaryWindow_ifc) window;
    649      window.addMenuBarItemGThread(name, sMenuPath, action);
    650    }
    651  }
    652
    653
    654  @Override public GralMenu getMenuBar(){ return window.getMenuBar(); }
    655
    656
    657
    658  @Override public void setFullScreen(boolean full){ window.setFullScreen(full); }
    659
    660
    661
    662  protected GralPanelContent addOutputFrameArea(String area)
    663  {
    664    GralRectangle areaR = convertArea(area);
    665    window.gralMng().selectPanel("primaryWindow");
    666    GralPanelContent outputPanel = window.gralMng().createCompositeBox("outputArea");
    667    window.gralMng().setPosition(0,0,0,0,0,'b');
    668    //NOTE: it is a edit-able box. It may be usefully to edit the content by user sometimes.
    669    outputBox = window.gralMng().addTextBox("output", true, null, '.');
    670    try{ outputBox.append("output...\n"); } catch(IOException exc){}
    671    addFrameArea(areaR.x, areaR.y, areaR.dx, areaR.dy, outputPanel);
    672    return outputPanel;
    673  }
    674
    675
    676
    677  private final GralGraphicTimeOrder writeOutputTextDirectly = new GralGraphicTimeOrder("GralArea9Window.writeOutputTextDirectly")
    678  { @Override public void executeOrder()
    679    { String line;
    680      while((line = outputTexts.poll())!=null){
    681        writeDirectly(line, MainCmd.kInfoln_writeInfoDirectly);
    682      }
    683    }
    684  };
    685
    686
    687
    688
    689
    690  /** Overloads MainCmd.writeDirectly. This method may be overloaded by the user
    691   * if it has a better way to show infos.*/
    692  protected void writeDirectly(String sInfo, short kind)  //##a
    693  { if(textAreaOutput != null){
    694      if(Thread.currentThread().getId() == window.gralMng().gralDevice.getThreadIdGui()){
    695        try{
    696          if((kind & MainCmd.mNewln_writeInfoDirectly) != 0)
    697          { textAreaOutput.append("\n");
    698          }
    699          textAreaOutput.append(sInfo);
    700          int nrofLines = textAreaOutput.getNrofLines();
    701          textAreaOutput.viewTrail();
    702          //textAreaOutput.setCaretPosition(nrofLines-1);
    703          textAreaOutput.repaint(100, 500);
    704        } catch(IOException exc){ getGralMng().writeLog(0, exc); }
    705      } else {
    706        //queue the text
    707        outputTexts.add(sInfo);
    708        window.gralMng().gralDevice.wakeup();
    709      }
    710    }
    711    else mainCmd.writeDirectly(sInfo, kind);
    712  }
    713
    714
    715
    716
    717
    718
    719  /* (non-Javadoc)
    720   * @see org.vishia.gral.area9.GralArea9_ifc#setHelpBase(java.lang.String)
    721   */
    722  @Override public void setHelpBase(String path){
    723    GralMng.get().setHelpBase(path);
    724  }
    725
    726
    727
    728
    729  /* (non-Javadoc)
    730   * @see org.vishia.gral.ifc.GralMngApplAdapter_ifc#setHelpUrl(java.lang.String)
    731   */
    732  @Override public void setHelpUrl(String url){ GralMng.get().setHelpUrl(url); }
    733
    734
    735
    736
    737  //@Override public void repaint(){  window.repaint(); }
    738
    739
    740
    741
    742  /** Gets the graphical frame. */
    743  //@Override public Object getitsGraphicFrame(){ return window.getWidgetImplementation(); }
    744
    745
    746
    747
    748  @Override public GralMng getGralMng()
    749  { return window.gralMng();
    750  }
    751
    752
    753
    754
    755
    756
    757
    758
    759  private final GralUserAction mouseAction = new GralUserAction("mouseAction")
    760  { int captureAreaDivider;
    761
    762
    763    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params)
    764    { GralRectangle mousePos = (GralRectangle)params[0];
    765      int yf1 = ypFrameArea[1];
    766      int yf2 = ypFrameArea[2];
    767      int xf1 = xpFrameArea[1]; //percent right
    768      int xf2 = xpFrameArea[2]; //percent right
    769      if(mousePos.x < 20){
    770        //calculate pixel size for the component:
    771        int y1 = (int)(yf1  * pixelPerYpercent);
    772        int y2 = (int)(yf1  * pixelPerYpercent);
    773        if(mousePos.y > y1-20 && mousePos.y < y1 + 20){
    774          captureAreaDivider = 1;
    775      }
    776    }
    777return true;
    778  } };
    779
    780
    781  private final GralUserAction resizeAction = new GralUserAction("resizeAction")
    782  { @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params)
    783    { validateFrameAreas();  //calculates the size of the areas newly and redraw.
    784      return true;
    785  } };
    786
    787
    788  /**TODO actionFile in user space?
    789   *
    790   */
    791  protected class GralActionFileOpen extends GralUserAction
    792  { private final GralFileDialog_ifc fileDialog;
    793
    794    public GralActionFileOpen(){
    795      super("GralActionFileOpen");
    796      fileDialog = window.gralMng().createFileDialog();
    797      fileDialog.open("FileDialog", 0);
    798    }
    799    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params)
    800    { fileDialog.show("d:/vishia", "", "*.*", "select");
    801      return true;
    802  } }
    803
    804
    805  private final GralUserAction actionAbout = new  GralUserAction("actionAbout")
    806  { //final InfoBox infoHelp;
    807    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params)
    808    { try{
    809        for(String line: mainCmd.listAboutInfo){
    810          //infoAbout.append(line).append("\n");
    811        }
    812      } catch(Exception exc){ window.gralMng().writeLog(0, exc); }
    813      //infoAbout.setWindowVisible(true);
    814      infoAbout.setFocus();
    815      return true;
    816  } };
    817
    818
    819  /**Returns the standard behavior: opens the help window with its constant text.
    820   * @see org.vishia.gral.area9.GralArea9_ifc#getActionAbout()
    821   */
    822  @Override public GralUserAction getActionAbout()
    823  { return actionAbout;
    824  }
    825
    826  /**Returns the standard behavior: opens the about window with its constant text.
    827   * @see org.vishia.gral.area9.GralArea9_ifc#getActionAbout()
    828   */
    829  @Override public GralUserAction getActionHelp()
    830  { return GralMng.get().actionHelp;
    831  }
    832
    833
    834
    835}