    001package org.vishia.gral.base;
    002
    003import java.util.ArrayList;
    004import java.util.LinkedList;
    005import java.util.List;
    006import java.util.Map;
    007import java.util.TreeMap;
    008
    009import org.vishia.gral.ifc.GralCanvasStorage;
    010import org.vishia.gral.ifc.GralMngBuild_ifc;
    011import org.vishia.gral.ifc.GralRectangle;
    012import org.vishia.gral.ifc.GralWidget_ifc;
    013import org.vishia.util.Debugutil;
    014
    015
    016/**This class describes a panel with its content for managing. */
    017public class GralPanelContent extends GralWidget implements GralWidget_ifc
    018{
    019
    020  /**Version history:
    021   *
    022   * <ul>
    023   * <li>2018-08-17 Hartmut new: {@link #getWidget(String)}, {@link #getTextFrom(String)}
    024   * <li>2016-07-16 Hartmut chg: On {@link #setToPanel(GralMngBuild_ifc)} all widgets of this panel are initialized too. More simple for user application.
    025   * <li>2015-05-02 Hartmut new: {@link #setTextIn(String, CharSequence)}, change of registering a widget. Now any panel knows its widgets
    026   *   by name.
    027   * <li>2012-07-13 Hartmut new:  {@link #getPixelSize()}, chg: {@link #getPixelPositionSize()} in all implementations.
    028   *   A swt.widget.Shell now returns the absolute position and the real size of its client area without menu and title bar.
    029   * <li>2012-04-22 Hartmut new: {@link #canvas} as property maybe null for each panel to support stored graphics.
    030   * <li>2012-03-31 Hartmut new: {@link #implMethodPanel_} and {@link MethodsCalledbackFromImplementation#setVisibleState(boolean)}.
    031   * <li>2012-01-14 Hartmut new: {@link #setPrimaryWidget(GralWidget)} for panel focus.
    032   * <li>2012-01-08 Hartmut new: {@link #remove()}
    033   * <li>2011-11-19 Hartmut chg: The 'itsTabSwt' is moved to {@link org.vishia.gral.swt.SwtPanel} now.
    034   * <li>2011-11-12 Hartmut new: {@link #getPixelPositionSize()}.
    035   * </ul>
    036   *
    037   * <b>Copyright/Copyleft</b>:
    038   * For this source the LGPL Lesser General Public License,
    039   * published by the Free Software Foundation is valid.
    040   * It means:
    041   * <ol>
    042   * <li> You can use this source without any restriction for any desired purpose.
    043   * <li> You can redistribute copies of this source to everybody.
    044   * <li> Every user of this source, also the user of redistribute copies
    045   *    with or without payment, must accept this license for further using.
    046   * <li> But the LPGL ist not appropriate for a whole software product,
    047   *    if this source is only a part of them. It means, the user
    048   *    must publish this part of source,
    049   *    but don't need to publish the whole source of the own product.
    050   * <li> You can study and modify (improve) this source
    051   *    for own using or for redistribution, but you have to license the
    052   *    modified sources likewise under this LGPL Lesser General Public License.
    053   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    054   * </ol>
    055   * If you are intent to use this sources without publishing its usage, you can get
    056   * a second license subscribing a special contract with the author.
    057   *
    058   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    059   */
    060  @SuppressWarnings("hiding")
    061  public final static int version = 20120713;
    062
    063  //public GralPrimaryWindow_ifc mainWindow;
    064
    065  //public final GralMng gralMng;
    066
    067
    068  /**The widget which should be focused if the panel is focused.
    069   * It is possible to set any actual widget to store the focus situation,
    070   * It is possible too to have only one widget to focus. if the panel gets the focus. */
    071  protected GralWidget primaryWidget;
    072
    073  /**List of all widgets which are contained in this panel or Window, to refresh the graphic.
    074   * This list is used in the communication thread to update the content of all widgets in the panel.
    075   */
    076  //private List<GralWidget> _wdgList = new ArrayList<GralWidget>();
    077
    078  /**List of all widgets which are contained in this panel.
    079   * This list is used in the communication thread to update the content of all widgets in the panel.
    080   */
    081  protected List<GralWidget> widgetList = new ArrayList<GralWidget>();
    082
    083  public List<GralWidget> widgetsToResize = new LinkedList<GralWidget>();
    084
    085  private final Map<String, GralWidget> idxWidgets = new TreeMap<String, GralWidget>();
    086
    087  /**True then the content of the panel is zoomed with the actual size of panel.
    088   * It means that all widgets are zoomed in position and size,  but there content isn't changed. */
    089  protected boolean bZoomed;
    090
    091  /**True then the grid of the panel is zoomed with the actual size of panel.
    092   * It means that all fonts are changed too.
    093   * */
    094  protected boolean bGridZoomed;
    095
    096
    097  /**If this instance is not null, the content of that should be paint in the paint routine
    098   * of the implementation graphic. */
    099  public GralCanvasStorage canvas;
    100
    101
    102  @Deprecated public GralPanelContent(String namePanel, GralMng mng, Object panelComposite)
    103        //public PanelContent(CanvasStorePanel panelComposite)
    104        { super(namePanel, '$');
    105          this.name = namePanel;
    106                //this.panelComposite = panelComposite;
    107    //GralMng mng = GralMng.get();
    108    mng.registerPanel(this);
    109    if( pos()!=null) {
    110      mng.setPosPanel(this);
    111    }
    112    int property = 0; //TODO parameter
    113    bZoomed = (property & GralMngBuild_ifc.propZoomedPanel) !=0;
    114    bGridZoomed = (property & GralMngBuild_ifc.propGridZoomedPanel) !=0;
    115        }
    116
    117
    118
    119  /**Create a panel, registers it and sets the {@link GralMng#pos()} of this thread to the panel. */
    120  public GralPanelContent(String posString, String namePanel)
    121  { this(posString, namePanel, '$');
    122  }
    123
    124  /**Create a panel, registers it and sets the {@link GralMng#pos()} of this thread to the panel. */
    125  public GralPanelContent(String posString, String namePanel, char whatIsit)
    126  //public PanelContent(CanvasStorePanel panelComposite)
    127  { super(posString, namePanel, whatIsit);
    128    this.name = namePanel;
    129    GralMng mng = GralMng.get();
    130    mng.registerPanel(this);
    131    if( pos()!=null) {
    132      mng.setPosPanel(this);
    133    }
    134    int property = 0; //TODO parameter
    135    bZoomed = (property & GralMngBuild_ifc.propZoomedPanel) !=0;
    136    bGridZoomed = (property & GralMngBuild_ifc.propGridZoomedPanel) !=0;
    137  }
    138        /*
    139  private GralPanelContent(String namePanel, GralPrimaryWindow_ifc mainWindow)
    140  { super(namePanel, '$', null);
    141    this.namePanel = namePanel; this.gralMng = null; //mainWindow.;
    142  }
    143
    144
    145  private GralPanelContent(String namePanel, GralWidgetMng mng)
    146  { super(namePanel, '$', mng);
    147    this.namePanel = namePanel; this.gralMng = mng;
    148  }
    149  */
    150
    151
    152
    153  public void setPrimaryWidget(GralWidget widg){ primaryWidget = widg; }
    154
    155
    156  /*package private*/
    157  /**Adds a widget to its panel. This method will be called in {@link GralWidget#initPosAndRegisterWidget(GralPos)}
    158   * either on creation the GralWidget with a given position String or on {@link GralWidget#setToPanel(GralMngBuild_ifc)}
    159   * with the given currently {@link GralMng#pos()}.
    160   * @param widg
    161   * @param toResize
    162   */
    163  void addWidget(GralWidget widg, boolean toResize){
    164    String nameWidg = widg.name;
    165    if(widg instanceof GralWindow)
    166      Debugutil.stop();
    167    if(nameWidg !=null) {
    168      String nameGlobal;
    169      if(nameWidg.startsWith("@")) {
    170        nameWidg = nameWidg.substring(1);  //without @
    171        nameGlobal = super.name + "." + nameWidg;  //panel.widget
    172      } else {
    173        nameGlobal = nameWidg;
    174      }
    175      itsMng.registerWidget(nameGlobal, widg);
    176      idxWidgets.put(nameWidg, widg);
    177    }
    178    if(widgetList.remove(widg)){
    179      System.err.println("Widget added twice; " + nameWidg);
    180    }
    181    widgetList.add(widg);
    182    if(toResize) {
    183      if(widg instanceof GralWindow) {
    184        System.err.println("GralPanelContent.addWidget - A window itself should not be added to widgetsToResize, " + widg.name);
    185      } else {
    186        widgetsToResize.add(widg);
    187      }
    188    }
    189    if(primaryWidget ==null && !(widg instanceof GralPanelContent)) {  //register only a non-panel widget as primary - for the panel or window.
    190      primaryWidget = widg;
    191    }
    192  }
    193
    194
    195
    196  /**Overridden implementation of {@link GralWidget#createImplWidget_Gthread()} for instantiation of all widgets of this panel.
    197   */
    198  @Override public void createImplWidget_Gthread() throws IllegalStateException {
    199    super.createImplWidget_Gthread(); //from GralWidget.
    200    for(GralWidget widg: widgetList) {
    201      widg.createImplWidget_Gthread();
    202    }
    203  }
    204
    205        /**Removes this widget from the lists in this panel. This method is not intent to invoke
    206   * by an application. It is only used in {@link GralWidget#remove()}. Use the last one method
    207   * to remove a widget includint is disposition and remove from the panel.
    208   * @param widg The widget.
    209   */
    210  public void removeWidget(GralWidget widg)
    211  { String nameWidg = widg.name;
    212    if(nameWidg !=null) {
    213      String nameGlobal;
    214      if(nameWidg.startsWith("@")) {
    215        nameWidg = nameWidg.substring(1);  //without @
    216        nameGlobal = super.name + "." + nameWidg;  //panel.widget
    217      } else {
    218        nameGlobal = nameWidg;
    219      }
    220      itsMng.removeWidget(nameGlobal);
    221      idxWidgets.remove(nameWidg);
    222    }
    223
    224    widgetList.remove(widg);
    225    widgetsToResize.remove(widg);
    226
    227  }
    228
    229  /**This overridden form of {@link GralWidget_ifc#remove()} removes all widgets of this panel.
    230   * It includes the disposition  of the widgets in the graphic. It is done by invocation
    231   * {@link GralWidget#remove()}.
    232   * @return true because it is done.
    233   */
    234  @Override public boolean remove(){
    235    int catastrophicCt = 100000; //safety of all while loops! No more than 100000 widgets.
    236    while(--catastrophicCt >=0 && widgetList.size() >0){
    237      //remove all widgets from the panel via Widget.remove, it removes it from this list too.
    238      widgetList.get(0).remove();
    239    }
    240    assert(catastrophicCt >0);
    241    widgetList.clear();      //the lists may be cleared already
    242    widgetsToResize.clear(); //because widg.remove() removes the widget from the panel.
    243    super.remove();
    244    return true;
    245  }
    246
    247
    248
    249
    250
    251
    252  /**
    253   * @deprecated use {@link #getWidgetList()}
    254   */
    255  @Deprecated public List<GralWidget> widgetList(){ return widgetList; }
    256
    257  public List<GralWidget> getWidgetList(){ return widgetList; }
    258
    259  /**Gets a named widget on this panel. Returns null if faulty name.
    260   * @since 2018-09
    261   */
    262  public GralWidget getWidget(String name){ return idxWidgets.get(name); }
    263
    264
    265
    266
    267  /**Sets the text to the named widget
    268   * @param nameWidget the registered widget in its panel.
    269   * @param text The text to set.
    270   * @throws IllegalArgumentException on faulty widget name
    271   * @since 2015-05-02
    272   */
    273  public void setTextIn(String nameWidget, CharSequence text) {
    274    GralWidget widg = idxWidgets.get(nameWidget);
    275    if(widg == null) throw new IllegalArgumentException("GralPanel - Widget not found, " + nameWidget);
    276    widg.setText(text);
    277  }
    278
    279
    280
    281  /**Gets the text from the named widget
    282   * @param nameWidget the registered widget in its panel.
    283   * @param text The text to set.
    284   * @throws IllegalArgumentException on faulty widget name
    285   * @since 2015-05-02
    286   */
    287  public String getTextFrom(String nameWidget) {
    288    GralWidget widg = idxWidgets.get(nameWidget);
    289    if(widg == null) throw new IllegalArgumentException("GralPanel - Widget not found, " + nameWidget);
    290    return widg.getText();
    291  }
    292
    293
    294
    295
    296
    297
    298  /**Sets the focus to the primary widget if it is set.
    299   * Elsewhere do nothing and returns false.
    300   * The focus may be set then by the inherit implementation class.
    301   * <br>See {@link #setPrimaryWidget(GralWidget)}.
    302   * @return true if the focus is set to the primary widget.
    303   */
    304  //@Override
    305  public boolean XXXsetFocusGThread()
    306  {
    307    if(primaryWidget !=null) {
    308      //invokes the setFocus routine to mark focus in table etc.
    309      primaryWidget.setFocus();  //invokes setFocusGThread because it is the graphic thread.
    310      return true;  //TODO check focus
    311      //return primaryWidget.setFocusGThread();
    312    }
    313    else return false;
    314  }
    315
    316  /**Use GralWidet._wdgImpl.getWidgetImplementation() internally! Not public.
    317   * @return
    318   */
    319  @Deprecated public Object getWidgetImplementation()
    320  { return _wdgImpl.getWidgetImplementation(); //panelComposite;
    321  }
    322
    323
    324  /**Returns the container instance of the panel of the implementing graphic.
    325   * @return The container.
    326   */
    327  //public abstract Object getPanelImpl();
    328
    329
    330
    331  @Override public String toString(){ return "GralPanel:" + name; }
    332
    333
    334
    335  /**This inner class contains methods which can call by the implementation layer.
    336   * That methods are not intent to be called by the application.
    337   * It is public because the implementation level in another package should accesses it.
    338   */
    339  public abstract static class MethodsCalledbackFromImplementation
    340  extends GralWidget.ImplAccess
    341  {
    342
    343    private final GralPanelContent panelg;
    344
    345    MethodsCalledbackFromImplementation(GralPanelContent panelg, GralMng mng){
    346      super(panelg, mng);
    347      this.panelg = panelg;
    348    }
    349    @Override public void setVisibleState(boolean visible){
    350      for(GralWidget widget: panelg.widgetList){
    351        widget.setVisibleState(visible);
    352      }
    353    }
    354  } //class MethodsCalledbackFromImplementation
    355
    356  /**This reference is a inner class which contains methods which can call by the implementation layer.
    357   * That methods are not intent to be called by the application.
    358   * It is public because the implementation level in another package should accesses it.
    359   */
    360  //public MethodsCalledbackFromImplementation implMethodPanel_ = new MethodsCalledbackFromImplementation(this);
    361
    362  /**Sets the visible state to all widgets of the panel, but not to windows (that is only in the primaryWindow)
    363   * @see org.vishia.gral.base.GralWidget#setVisibleState(boolean)
    364   */
    365  @Override public void setVisibleState(boolean visible){
    366    if(isVisible() != visible) {
    367      //only invoke for all sub widgets when the visible state of the parent is changed. Otherwise do nothing - nothing is changed, no effort.
    368      //for tabbed panels etc. it is specially processed
    369      super.setVisibleStateWidget(visible);  //for the own panel
    370      for(GralWidget widget: widgetList){
    371        if(widget != this && !(widget instanceof GralWindow)) {
    372          widget.setVisibleState(visible);
    373        }
    374      }
    375    }
    376  }
    377
    378
    379  public abstract static class ImplAccess extends GralWidget.ImplAccess
    380  {
    381
    382    /**Same reference as {@link GralWidget.ImplAccess#widgg} but type of this class. */
    383    //GralPanelContent gralPanel;
    384
    385    protected ImplAccess(GralPanelContent widgg)
    386    {
    387      super(widgg);
    388      //for all following actions: this is the current panel.
    389      GralMng mng = GralMng.get();
    390      mng.setPosPanel((GralPanelContent)widgg);
    391    }
    392
    393    public GralPanelContent gralPanel(){ return (GralPanelContent) widgg; } //It is the correct type.
    394
    395    /**Returns the absolute position of this panel on screen and its size.
    396     * If it is a main window, the useable area of the window without title and menu bar is returned.
    397     * @return
    398     */
    399    @Override
    400    public abstract   GralRectangle getPixelPositionSize();
    401
    402
    403
    404  /**Returns the size of this panel in pixel.
    405   * @return the x and y is 0, the dy and dy is the size.
    406   */
    407    public abstract GralRectangle getPixelSize();
    408
    409
    410
    411  }
    412
    413}
    414