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}