    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}