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