001package org.vishia.gral.ifc;
002
003import org.vishia.byteData.VariableContainer_ifc;
004import org.vishia.gral.base.GralMng;
005import org.vishia.gral.base.GralWidgImpl_ifc;
006import org.vishia.gral.base.GralWidget;
007import org.vishia.util.Debugutil;
008import org.vishia.util.Removeable;
009
010
011/**This is the basic interface for all widgets of the Graphic Adaption Layer (gral).
012 * <br>
013 * <b>Strategy of changing the graphical content of a widget</b>:<br>
014 * 2013-09-30<br>
015 * The SWT graphical implementation prohibits changing the graphical appearance, for example setText(newText),  
016 * in another thread. Other graphical implementations are not thread-safe. Often a graphic application
017 * runs in only one thread, so that isn't a problem. But applications with complex data gathering processes
018 * needs to run in several threads. It may be fine to set the widgets in that threads immediately,
019 * seen from the programmers perspective. For multithread usage see {@link org.vishia.gral.base.GralGraphicThread}.
020 * <br><br>
021 * The solution of setting any content in a Widget in any thread in Gral is:
022 * <ul>
023 * <li>The thread invokes methods of this <code>GralWidget_ifc</code> or methods of an derived <code>GralWidget</code>
024 *   such as {@link GralTable}, for example {@link #setText(CharSequence)}, {@link #setTextColor(GralColor)}
025 *   or {@link org.vishia.gral.base.GralTable#setColorCurrLine(GralColor)}.
026 * <li>That methods store the given data either in the common {@link GralWidget.DynamicData} {@link GralWidget#dyda} of the widget
027 *   or in specific data of a GralWidget implementation.
028 * <li>That method calls {@link #repaint(int, int)} with a proper millisecond delay (usual 100).
029 *   The graphic implementation widget is not touched in this time. Usual it is not necessary to show information
030 *   in a faster time than 100 ms if it is not a high speed animated graphic. The delayed repaint request
031 *   saves calculation time if more as one property is changed on the same widget.
032 * <li>The delayed repaint request queues the instance {@link GralWidget#repaintRequ} (only private visible)
033 *   of {@link org.vishia.gral.base.GralGraphicTimeOrder} in the central queue of requests using 
034 *   {@link org.vishia.gral.base.GralGraphicThread#addDispatchOrder(org.vishia.gral.base.GralGraphicTimeOrder)}. 
035 *   The {@link org.vishia.gral.base.GralGraphicThread} is known by {@link org.vishia.gral.base.GralWidget#itsMng}.
036 * <li>If for example 20 widgets are changed in maybe 40 properties, that queue contains the 20 instances of
037 *   {@link org.vishia.gral.base.GralGraphicTimeOrder}. Any of them may have a specific delay. 
038 *   The graphic thread organizes it in a proper kind of time.
039 * <li>If a {@link org.vishia.gral.base.GralGraphicTimeOrder} is dequeued in the graphic thread, 
040 *   its method {@link org.vishia.gral.base.GralGraphicTimeOrder#executeOrder(boolean)} is invoked. 
041 *   This method calls {@link GralWidgImpl_ifc#repaintGthread()} via the association {@link org.vishia.gral.base.GralWidget#_wdgImpl}.
042 * <li>The <code>rerepaintGthread()</code> method is overridden in the implementation layer
043 *   with the necessary statements to transfer the non-graphic data of this {@link GralWidget} especially
044 *   stored in {@link org.vishia.gral.base.GralWidget#dyda} to the special implementation widget method invocations
045 *   such as {@link org.eclipse.swt.widgets.Text#setText(String)} which touches the graphic widget.
046 *   Then a {@link org.eclipse.swt.widgets.Control#update()} and {@link org.eclipse.swt.widgets.Control#redraw()}
047 *   is invoked to show the content.         
048 * </ul>
049 * It is a complex approach. But it is simple for usage. The user can change the content in any thread.
050 * The user does not need to organize a queue for the graphic thread by itself. The queue is a part of Gral.
051 * 
052 * <br><br>
053 * <b>Strategy to create widgets and positioning</b>: see {@link GralMngBuild_ifc}.  
054 *  
055 * @author Hartmut Schorrig
056 *
057 */
058public interface GralWidget_ifc extends Removeable
059{
060  
061  /**Version, history and license.
062   * <ul>
063   * <li>2016-08-31 Hartmut new: {@link #isGraphicDisposed()} especially used for GralWindow-dispose detection. 
064   * <li>2016-07-20 Hartmut chg: instead setToPanel now {@link #createImplWidget_Gthread()}. It is a better name. 
065   * <li>2015-10-11 Hartmut new: {@link #createImplWidget_Gthread()} without mng as parameter.
066   * <li>2015-09-12 Hartmut new: {@link #getData()}, {@link #setData(Object)} was existent as {@link GralWidget#setContentInfo(Object)},
067   *   now explicit property of any widget. 
068   * <li>2015-07-12 Hartmut new: {@link #setCmd(String)} and {@link #getCmd()} is present in {@link org.vishia.gral.base.GralWidget}
069   *   since 2010 but it was not accepted as core property. But it is a core property.
070   * <li>2013-03-13 Hartmut new {@link #getContentIdent()}, {@link #setContentIdent(long)}
071   * <li>2013-03-13 Hartmut new {@link #isNotEditableOrShouldInitialize()} to support edit fields.
072   * <li>2012-08-21 The method {@link #setBackColor(GralColor, int)}, {@link #setLineColor(GralColor, int)} and {@link #setTextColor(GralColor)}
073   *  are declared here. What methods are deprecated? I thing {@link #setBackgroundColor(GralColor)}.  
074   * <li>2012-07-29 Hartmut chg: {@link #setFocus()} and {@link #setFocus(int, int)} can be called in any thread yet.
075   * <li>2012-07-13 Hartmut new. {@link #getWidgetMultiImplementations()}. This method is not used in any widget yet,
076   *   but it may be necessary for complex widgets.
077   * <li>2012-04-25 Hartmut new: {@link #refreshFromVariable(VariableContainer_ifc)}: Capability for any widget
078   *   to update its content from its associated variables described in its sDataPath.
079   * <li>2012-03-31 Hartmut new: {@link #isVisible()}
080   * <li>2012-01-16 Hartmut new: Concept {@link #repaint()}, can be invoked in any thread. With delay possible.
081   * <li>2011-06-00 Hartmut created
082   * </ul>
083   * 
084   * <b>Copyright/Copyleft</b>:<br>
085   * For this source the LGPL Lesser General Public License,
086   * published by the Free Software Foundation is valid.
087   * It means:
088   * <ol>
089   * <li> You can use this source without any restriction for any desired purpose.
090   * <li> You can redistribute copies of this source to everybody.
091   * <li> Every user of this source, also the user of redistribute copies
092   *    with or without payment, must accept this license for further using.
093   * <li> But the LPGL is not appropriate for a whole software product,
094   *    if this source is only a part of them. It means, the user
095   *    must publish this part of source,
096   *    but doesn't need to publish the whole source of the own product.
097   * <li> You can study and modify (improve) this source
098   *    for own using or for redistribution, but you have to license the
099   *    modified sources likewise under this LGPL Lesser General Public License.
100   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
101   * </ol>
102   * If you intent to use this source without publishing its usage, you can get
103   * a second license subscribing a special contract with the author. 
104   * 
105   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
106   */
107  public static final String sVersion = "2016-08-31";
108
109  public static class ActionChange
110  {
111    protected final GralUserAction action;
112    
113    /**Usual the given textual description of the action, can be shown to display or as menu item in context menu.*/
114    protected final String sAction;
115    
116    /**Any arguments, usual String[]. */
117    protected final Object[] args;
118    
119    public ActionChange(String sAction, GralUserAction action, Object[] args)
120    { if(args !=null)
121        Debugutil.stop();
122      this.action = action;
123      this.sAction = sAction;
124      this.args = args;
125    }
126
127    public GralUserAction action(){ return action; }
128    
129    public Object[] args(){ return args; }
130    
131    public String sAction(){ return sAction; }
132  }
133
134
135  public enum ActionChangeWhen
136  { onAnyChgContent
137  , onEnter
138  , onCtrlEnter
139  , onFocusGained
140  , onChangeAndFocusLost
141  , onMouse1Dn
142  , onMouse1Up
143  , onMouse1UpOutside
144  , onMouse2Up
145  , onMouse1Double
146  , onMouseWheel
147  , onDrop
148  , onDrag
149  };
150
151  
152  public String getName();
153  
154  public String getDataPath();
155  
156  /**Any widget can have a command String, which can be quest for example in an action. 
157   * The widget can be identified by its {@link #getCmd()} independent of its name which can be set on runtime with this method. */
158  void setCmd(String cmd);
159  
160  
161  /**Any widget can have a command String, which can be quest for example in an action. 
162   * The widget can be identified by this method independent of its name. See {@link #setCmd(String)}. */
163  String getCmd();
164  
165  
166    /**Sets a application specific data. 
167   * It should help to present user data which are associated to this widget. 
168   * This info can be set and changed anytime. */
169  void setData(Object data);
170  
171  /**Gets the application specific info. See {@link #setContentInfo(Object)}. */
172  Object getData();
173  
174
175  
176  
177  //public GralUserAction getActionChange();
178  
179  ActionChange getActionChange(ActionChangeWhen when);
180  
181  /**Sets this widget to the current panel at the current given position. 
182   * This routine should be called only one time after the Gral widget was created. 
183   * It creates the graphical appearance using the capabilities of the derived GralMng for the systems graphic level.
184   * This method invokes {@link GralMng#createImplWidget_Gthread(GralWidget)} which tests the type of the derived GralWidget
185   * to create the correct graphical widget. That method calls the implementing specific {@link GralMng.ImplAccess#createImplWidget_Gthread(GralWidget)}
186   * which knows the implementation graphic. 
187   * <br><br><b>Instance structure</b><br>
188   * The implementation of a widget is firstly a class which is inherit from {@link ImplAccess}. With them the {@link GralWidget}
189   * is references because it is the environment class. The core graphical widget is an aggregation in this instance. It is possible 
190   * that more as one implementation widget is used for a Gral Widget implementation. For example a text field with a prompt
191   * consists of two implementation widgets, the text field and a label for the prompt.
192   * <br><br>
193   * <b>Positioning and Registering the widget:</b>
194   * The registering of a widget is done in {@link GralWidget#initPosAndRegisterWidget(GralPos)} which is called either
195   * on construction of a widget with a String-given position, before it appears on graphic, or on construction of the 
196   * graphic widget. It calls the package private {@link GralWidget#initPosAndRegisterWidget(GralPos)}, which takes the 
197   * given position, stores it in the {@link GralWidget#pos()} and adds the widget both to its panel which is given
198   * with the pos and registers the widget in the GralMng for simple global access. 
199   * If the name of the widget starts with "@" its name in the panel is the part after "@" whereby the global name 
200   * is the "panelname.widgetname". If a widget's position is given from left and from right or with percent, it is resized
201   * on resizing the window and the panel.
202   * <br><br>
203   * 
204   * @throws IllegalStateException This routine can be called only if the graphic implementation widget is not 
205   *   existing. It is one time after startup or more as one time if {@link #removeWidgetImplementation()}
206   *   was called. 
207   */
208  void createImplWidget_Gthread();
209  
210  /**Deprecated. Use {@link #createImplWidget_Gthread()}.
211   * @param mng not used. It is known as singleton. Use null as argument.
212   */
213  void setToPanel(GralMngBuild_ifc mng);
214  
215  /**Returns the associated singleton GralMng. The GralMng is associated only if the widget is setToPanel,
216   * see {@link #setToPanel(GralMngBuild_ifc)}.
217   * @return null if the Widget is created yet without connection to the graphical implementation layer
218   */
219  GralMng gralMng();
220  
221  /**Sets the focus to the widget. . It can be called in any thread. If it is called in the graphic thread,
222   * the repaint action is executed immediately in the thread. Elsewhere the graphic thread will be woken up.
223   */
224  public abstract void setFocus();
225  
226  /**Sets the focus to the widget. . It can be called in any thread. If it is called in the graphic thread,
227   * the repaint action is executed immediately in the thread. Elsewhere the graphic thread will be woken up.
228   * @param delay
229   * @param latest
230   */
231  public abstract void setFocus(int delay, int latest);
232  
233  
234  
235  /**Returns true if this widget is the focused one.
236   */
237  boolean isInFocus();
238  
239  /**Returns true if the graphic implementatin widget was initialized, and then it was disposed. 
240   * It is able to use especially to detect whether a sub window is closed or if the primary window was closed,
241   * to finish any other (waiting) thread. It may be used on any disposed widget.
242   * @return true if the Widget was created and after them disposed again.
243   */
244  boolean isGraphicDisposed();
245
246  
247  /**Sets this widget visible on graphic or invisible. Any widget can be visible or not. More as one widgets
248   * can use the same position, only one of them may set visible. 
249   * For a {@link GralWindow}, its the visibility of the whole window. 
250   * Note that a window which is invisible is not shown in the task bar of the operation system. 
251   * Note that an application can have more as one window. 
252   * Note that a dialog window can be set to invisible if it is not need yet instead destroy and build newly.
253   * @param visible
254   * @return
255   */
256  boolean setVisible(boolean visible);
257  
258  /**Returns whether the widget is visible or not. This method can be invoked in any thread.
259   * It is an estimation because the state of the widget may be changed in the last time or a window
260   * can be covered by another one. The widget is not visible if it is a member of a card in a tabbed
261   * panel and that tab is not the selected one.
262   * @return true if the widget seams to be visible.
263   */
264  boolean isVisible();
265  
266  /**Sets whether it is able to edit the content of the text field or text box.
267   * If a content is not able to edit, it is a showing field or box. The user can't change the
268   * content. But the user can set the cursor, select any text and copy to the systems clipboard.
269   * If the content is able to edit, the change should be notified and the content should be gotten.
270   * To do that TODO
271   * @param editable true then the content is going to be able to change. 
272   *   False then the edit functionality is disabled. 
273   */
274  void setEditable(boolean editable);
275  
276  /**Query whether this widget is able to change from user handling. */
277  boolean isEditable();
278  
279  
280  /**Query whether this field should be written from any initial or actual data. */
281  public boolean isNotEditableOrShouldInitialize();
282
283  
284  
285  /**
286   * @deprecated use {@link #setBackColor(GralColor, int)}
287   */
288  @Deprecated
289  public abstract GralColor setBackgroundColor(GralColor color);
290  
291  /**
292   * @deprecated use {@link #setLineColor(GralColor, int)}
293   */
294  @Deprecated
295  public abstract GralColor setForegroundColor(GralColor color);
296  
297  
298  /**Sets the background color for the widget. It supports widgets with more as one background color by an index.
299   * The usage of the index is widget-specific. An index -1 should mean: All backgrounds. ix=0 means the first background.
300   * @param color Any color
301   * @param ix -1 for non-specific, 0 for the first color or if only one color is supported, 1, ... if the widget has more as one background.
302   */
303  void setBackColor(GralColor color, int ix);
304  
305  /**Gets the background color for the widget.
306   * @param ix 0 if only one color is supported, 1, ... if the widget has more as one background.
307   * @return color Any color
308   */
309  GralColor getBackColor(int ix);
310  
311  /**Sets the line color for the widget.
312   * @param color Any color
313   * @param ix 0 if only one color is supported, 1, ... if the widget has more as one line.
314   */
315  void setLineColor(GralColor color, int ix);
316  
317  /**Sets the text color for the widget.
318   * @param color Any color
319   */
320  void setTextColor(GralColor color);
321  
322
323  /**Set the text of the widget. If the widget is a button, the standard button text is changed.
324   * If it is a window, its title is changed.
325   * <br><br>
326   * <b>Concept of changing a widget from application</b>:<br>
327   * Here the generally approach is described, appropriate for this method, but in the same kind
328   * for all methods to set something like {@link #setBackColor(GralColor, int)} etc.
329   * <br><br>
330   * With the set methods the user stores the text, color etc. in graphic-independent attributes. Then the method
331   * {@link #repaint(int, int)} is invoked with the standard delay of {@link #repaintDelay} and {@link #repaintDelayMax}.
332   * With that the widget-specific private instance of {@link #repaintRequ} is added to the queue of requests
333   * in the {@link GralGraphicThread#addTimeOrder(GralGraphicTimeOrder)}. In the requested time that 
334   * dispatch order is executed in the graphic thread. It calls {@link GralWidgImpl_ifc#repaintGthread()}. 
335   * That method is implemented in the graphic implementation layer of the widget. It sets the appropriate values 
336   * from the independent Gral attributes to the implementation specifics and invoke a redraw of the graphic layer.
337   * <br><br>
338   * If more as one attribute is changed one after another, only one instance of the {@link GralGraphicTimeOrder}
339   * is queued. All changed attributes are stored in {@link DynamicData#whatIsChanged} and the
340   * {@link GralWidgImpl_ifc#repaintGthread()} quests all changes one after another. 
341   * It means that a thread switch is invoked only one time per widget for more as one change.
342   * <br>
343   * See {@link DynamicData}. That composite part of a widget stores all standard dynamic data of a widget. 
344   */
345  void setText(CharSequence text);
346
347  
348  /**Sets the html help url for this widget. That information will be used if the widget is focused
349   * to control the help window output.
350   * @param url String given url, maybe a local file too with #internalLabel.
351   */
352  void setHtmlHelp(String url);
353  
354  //public abstract GralWidget getGralWidget();
355
356  /**repaint request. It can be called in any thread. If it is called in the graphic thread,
357   * the repaint action is executed immediately in the thread. Elsewhere the graphic thread will be waken up
358   * in the standard repaint time (about 100 ms). If this routine is invoked more as one time 
359   * before the standard repaint time expires and not in the graphic thread,
360   * then the repaint is executed only one time after the given delay with the last set data.
361   * See {@link #repaint(int, int)}
362   */
363  public void repaint();
364  
365  /**Possible delayed repaint, can be called in any thread.
366   * If this method is re-called in the time where the delay is not elapsed
367   * then the delay will be set newly, the timer is winding up again. 
368   * But the latest time on first call will be used.
369   * @param delay in milliseconds. If 0 or less 0, then it is executed immediately if the calling
370   *   thread is the graphic thread.
371   * @param latest The latest draw time in milliseconds. If it is less 0, then it is unused.
372   *   If it is 0 or less delay if a delay is given, then the delay isn't wound up on re-call.
373   *   
374   */
375  public void repaint(int delay, int latest);
376  
377  void setBoundsPixel(int x, int y, int dx, int dy);
378 
379  
380  /**Sets the data path. It is a String in application context. If variables are used, it is the path
381   * of one or more variables, see {@link #refreshFromVariable(VariableContainer_ifc)}.
382   * @param sDataPath
383   */
384  void setDataPath(String sDataPath);
385  
386  
387  /**Returns true if the content is changed from a user action on GUI.
388   * @param setUnchanged If true then set to unchanged with this call.
389   * @return true if the content was changed since last setUnchanged.
390   */
391  boolean isChanged(boolean setUnchanged);
392  
393  
394  /**Sets a identification for the shown data. A widget may not need to refresh if the contentIdent
395   * is not changed. A refresh of a widget's content may have side effects
396   * in user handling such as selection of text etc. See {@link #getContentIdent()}.
397   * @param ident any number which identifies the value of content.
398   * @return the last stored ident.
399   */
400  long setContentIdent(long ident);
401  
402  /**Gets the content identification of the users data which are set with {@link #setContentIdent(long)}.
403   */
404  long getContentIdent();
405  
406  
407  Object getContentInfo();
408
409  /**Capability for any widget to update its content from its associated variables described in its sDataPath.
410   * @param container The container is used only if the variable is not known by direct reference
411   *   in the private {@link GralWidget#variable} or {@link GralWidget#variables}. If the variable(s) is/are
412   *   not known, they are searched by there data path set by {@link #setDataPath(String)}. More as one 
413   *   variables are possible separated by "," in the setDataPath("variable1, variable2").
414   *   The variables are searched in the container calling {@link VariableContainer_ifc#getVariable(String)}. 
415   */
416  void refreshFromVariable(VariableContainer_ifc container);
417  
418  
419  
420  void refreshFromVariable(VariableContainer_ifc container, long timeAtleast, GralColor colorRefreshed, GralColor colorOld);
421}