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}