001package org.vishia.gral.base; 002 003import java.io.File; 004import java.io.IOException; 005import java.io.InputStream; 006import java.io.Writer; 007import java.lang.reflect.Constructor; 008import java.lang.reflect.InvocationTargetException; 009import java.text.ParseException; 010import java.util.LinkedList; 011import java.util.List; 012import java.util.Map; 013import java.util.Queue; 014import java.util.Set; 015import java.util.TreeMap; 016import java.util.concurrent.ConcurrentLinkedQueue; 017 018import org.vishia.byteData.VariableContainer_ifc; 019import org.vishia.gral.base.GralCurveView.CommonCurve; 020import org.vishia.gral.cfg.GralCfgBuilder; 021import org.vishia.gral.cfg.GralCfgData; 022import org.vishia.gral.cfg.GralCfgDesigner; 023import org.vishia.gral.cfg.GralCfgWriter; 024import org.vishia.gral.ifc.GralColor; 025import org.vishia.gral.ifc.GralCurveView_ifc; 026import org.vishia.gral.ifc.GralFactory; 027import org.vishia.gral.ifc.GralFileDialog_ifc; 028import org.vishia.gral.ifc.GralMngBuild_ifc; 029import org.vishia.gral.ifc.GralMngApplAdapter_ifc; 030import org.vishia.gral.ifc.GralPoint; 031import org.vishia.gral.ifc.GralTableLine_ifc; 032import org.vishia.gral.ifc.GralTextBox_ifc; 033import org.vishia.gral.ifc.GralVisibleWidgets_ifc; 034import org.vishia.gral.ifc.GralMng_ifc; 035import org.vishia.gral.ifc.GralRectangle; 036import org.vishia.gral.ifc.GralUserAction; 037import org.vishia.gral.ifc.GralWidget_ifc; 038import org.vishia.gral.ifc.GralWindowMng_ifc; 039import org.vishia.gral.ifc.GralWindow_ifc; 040import org.vishia.gral.widget.GralInfoBox; 041import org.vishia.gral.widget.GralLabel; 042import org.vishia.inspcPC.InspcReplAlias; 043import org.vishia.mainCmd.MainCmd; 044import org.vishia.mainCmd.MainCmdLoggingStream; 045import org.vishia.mainCmd.Report; 046import org.vishia.msgDispatch.LogMessage; 047import org.vishia.util.Debugutil; 048import org.vishia.util.FileSystem; 049import org.vishia.util.KeyCode; 050import org.vishia.util.ReplaceAlias_ifc; 051 052/**This is the Manager for the graphic. 053 * It contains the independent parts of graphic organization. 054 * This class <code>GralMng</code> is a common approach to work with graphical interface simply. 055 * The inner class {@link ImplAccess} is implemented by the several graphic-system-supporting classes. 056 * <ul> 057 * <li>{@link org.vishia.gral.swt.SwtMng} 058 * <li>{@link org.vishia.gral.awt.AwtWidgetMng} 059 * </ul> 060 * <br><br> 061 * 062 * @author Hartmut Schorrig 063 * 064 */ 065@SuppressWarnings("synthetic-access") 066public class GralMng implements GralMngBuild_ifc, GralMng_ifc 067{ 068 /**Version, history and license. 069 * <ul> 070 * <li>2016-11-04 Hartmut chg: {@link #notifyFocus(GralWidget)}: Only widgets with datapath. It is only for the inspector etc. TODO: Is there a list necessary? Store only the last widget in focus! 071 * <li>2016-09-02 Hartmut new: {@link #setPosPanel(GralPanelContent)} now invoked especially from ctor of {@link GralPanelContent} 072 * and from ctor of {@link GralPanelContent.ImplAccess}. If a new Panel was created with a given {@link GralWidget#pos()} then that panel 073 * is set as current one for the next widgets. Either the widgets are created before the implementation graphic with given position string, 074 * then the panel should have a position string too to assigned them. Or the widgets are created with creation of the implementation graphic, 075 * then a panel should be created in the same kind, and invoke {@link #setPosPanel(GralPanelContent)} in the ctor of its implementation. 076 * The contract is unchanged: A created panel determines that all following widgets are created on that panel. 077 * <li>2016-09-02 Hartmut chg: {@link #registerPanel(GralPanelContent)} is only be called in the ctor of {@link GralPanelContent} 078 * because any panel is based on GralPanelContent. 079 * The definition of the panel in the {@link #pos()} used for the next widgets are done now in the extra routine {@link #setPosPanel(GralPanelContent)}. 080 * <li>2016-09-01 Hartmut chg: instead implements {@link ReplaceAlias_ifc} now contains {@link #getReplacerAlias()}. 081 * It is an extra class for a ReplacerAlias given independent of the graphic. 082 * <li>2016-07-20 Hartmut chg: instead setToPanel now {@link #createImplWidget_Gthread()}. It is a better name. 083 * <li>2015-10-29 Hartmut chg: Problem on {@link #pos()} with a second thread: The MainWindow- {@link GralPos#panel} was registered in another thread 084 * and therefore unknown in the new {@link #pos()} for that thread. Solution: If the thread-specific GralPos will be created, 085 * it should copy the data from the {@link #posCurrent} which is valid any case for valid initial data. 086 * <li>2015-10-26 Hartmut new: The help and info box is an integral part of the GralMng and therefore available for any small application without additional effort. 087 * Only the {@link #createHtmlInfoBoxes(MainCmd)} should be invoked in the graphic thread while initializing the application. 088 * <li>2015-07-13 Hartmut chg: {@link GralMngFocusListener#focusLostGral(GralWidget)} now invokes the {@link GralWidget#actionFocused} too. 089 * The action should distinguish between focus gained and focus lost in its action routine. That should be added to the code. Done for all vishia sources. 090 * <li>2015-07-13 Hartmut new: {@link #registerUserAction(String, GralUserAction)} now knows possibility of usage the own name with "<name>" 091 * <li>2015-07-13 Hartmut chg: Positioning: The new concept gets a position in the constructor of {@link GralWidget} via 092 * {@link #getPosCheckNext()}. That routine sets the current position in this class to {@link PosThreadSafe#posUsed} 093 * for further using to increment. That is correct. 094 * The problem before was faulty old-concept usage of org.vishia.gral.swt.SwtMng#XXXsetPosAndSizeSwt 095 * which invokes {@link #setNextPosition()} which increments the position too, therefore twice. The usage of that routine 096 * is prevented for Swt implementation, TODO for awt yet now. 097 * <li>2015-05-31 Hartmut chg: {@link GralMngFocusListener}: invokes repaint() because of maybe changed outfit on focus gained 098 * <li>2015-05-02 Hartmut chg: {@link #registerWidget(GralWidget)} is obsolete now, it is empty yet. 099 * Instead {@link #registerWidget(String, GralWidget)} by given name and {@link #removeWidget(String)} by name. 100 * See description of registering on {@link GralWidget#setToPanel(GralMngBuild_ifc)}. 101 * <li>2015-04-27 Hartmut new {@link #selectPanel(GralPanelContent)} not only with String given 102 * <li>2015-01-18 Hartmut chg: Now the implementation for any Grahic (SwtMng) and the GralMng are two separated instances. 103 * The SwtMng extends the {@link GralMng.ImplAccess} which accesses all private data of the GralMng. 104 * <li>2013-12-21 Hartmut new: {@link #createImplWidget_Gthread(GralWidget)} for all set to panel actions. That method handles all widget types. 105 * <li>2013-03-20 Hartmut adap: {@link #actionFileSelect} with setText(...), now the file select field was filled. 106 * <li>2012-08-20 Hartmut new: {@link #getWidgetsPermanentlyUpdating()} created but not used yet because 107 * {@link #refreshCurvesFromVariable(VariableContainer_ifc)} has the necessary functionality. 108 * <li>2012-06-30 Hartmut new: Composition {@link #widgetHelper} The widget helper is implemented in the graphic system 109 * for example as {@link org.vishia.gral.swt.SwtWidgetHelper} to do some widget specific things. 110 * <li>2012-06-30 Hartmut new: Composition {@link #_impl}.{@link InternalPublic#gralKeyListener} 111 * <li>2012-04-22 Hartmut new: {@link #addLine(GralColor, List)} to add in a {@link GralCanvasStorage}. 112 * <li>2012-04-01 Hartmut new: {@link #addDataReplace(Map)}, {@link #replaceDataPathPrefix(String)}. 113 * using alias in the {@link GralWidget#setDataPath(String)}. The resolving of the alias is done 114 * only if the datapath is used. * <li>2012-03-17 Hartmut new: {@link #calcWidgetPosAndSize(GralPos, int, int)} as abstract method. 115 * <li>2012-03-10 Hartmut chg: {@link #addText(String)} now uses the background color {@link GralGridProperties#colorBackground_}. 116 * <li>2012-01-14 Hartmut chg: {@link #registerWidget(GralWidget)}: uses {@link GralPanelContent#addWidget(GralWidget, boolean)}. 117 * <li>2012-01-14 Hartmut new {@link #getValueFromWidget(GralWidget)} implementing here for non-platform depending values, especially GralTable. 118 * <li>2011-12-26 Hartmut new {@link #setApplicationAdapter(GralMngApplAdapter_ifc)} to support context sensitive help by focusGained of widgets. 119 * <li>2011-11-18 Hartmut new {@link #getLastClickedWidget()} to get the last clicked widget in any user routine. 120 * The information about the widget can be used to capture widgets for any script. 121 * <li>2011-11-17 Hartmut new addText(String) as simple variant. 122 * <li>2011-11-14 Hartmut bugfix: copy values of GralTabbedPanel.pos to this.pos instead set the reference from GralWidgetMng to GralTabbedPanel.pos 123 * The bug effect was removed panel in GralTabbedPanel.pos because it was the same instance as GralWidgetMng. 124 * <li>2011-10-01 Hartmut chg: move {@link #registerPanel(GralPanelContent)} from the SWT implementation to this. 125 * <li>2011-10-01 Hartmut new: method {@link #getPanel(String)} to get a registered panel by name. 126 * <li>2011-09-30 Hartmut new: {@link #actionDesignEditField}. It is the action which is called from menu now. 127 * <li>2011-09-29 Hartmut chg: {@link #calcWidgetPosAndSize(GralPos, int, int, int, int)}: calculates dy and dx one pixel less. 128 * <li>2011-09-23 Hartmut chg: All implementation routines for positioning are moved to the class {@link GralPos}. This class contains only wrappers now. 129 * <li>2011-09-18 Hartmut chg: Inner static class GuiChangeReq now stored in an own class {@link GralWidgetChangeRequ}. 130 * <li>2011-09-18 Hartmut new: : {@link GralPos#setFinePosition(int, int, int, int, int, int, int, int, int, char, GralPos)} calculates from right or bottom with negative values. 131 * <li>2011-09-10 Hartmut chg: Renaming this class, old name was GuiMngBase. 132 * <li>2011-09-10 Hartmut chg: Some routines form SWT implementation moved to this base class. It doesn't depends on the underlying graphic base. 133 * <li>2011-08-13 Hartmut chg: New routines for store and calculate the position to regard large widgets. 134 * </ul> 135 * 136 * <b>Copyright/Copyleft</b>: 137 * For this source the LGPL Lesser General Public License, 138 * published by the Free Software Foundation is valid. 139 * It means: 140 * <ol> 141 * <li> You can use this source without any restriction for any desired purpose. 142 * <li> You can redistribute copies of this source to everybody. 143 * <li> Every user of this source, also the user of redistribute copies 144 * with or without payment, must accept this license for further using. 145 * <li> But the LPGL is not appropriate for a whole software product, 146 * if this source is only a part of them. It means, the user 147 * must publish this part of source, 148 * but don't need to publish the whole source of the own product. 149 * <li> You can study and modify (improve) this source 150 * for own using or for redistribution, but you have to license the 151 * modified sources likewise under this LGPL Lesser General Public License. 152 * You mustn't delete this Copyright/Copyleft inscription in this source file. 153 * </ol> 154 * If you are intent to use this sources without publishing its usage, you can get 155 * a second license subscribing a special contract with the author. 156 * 157 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 158 */ 159 public final static String sVersion = "2015-10-30"; 160 161 /**This class is used for a selection field for file names and paths. */ 162 protected class FileSelectInfo 163 { 164 public List<String> listRecentFiles; 165 public String sRootDir; 166 public String sLocalDir; 167 public String sMask; 168 public String sTitle; 169 public final GralFileDialog_ifc dialogFile; 170 public final GralWidget dstWidgd; 171 172 173 public FileSelectInfo(String sTitle, List<String> listRecentFiles, String startDirMask, GralWidget dstWidgd) 174 { this.listRecentFiles = listRecentFiles; 175 this.dstWidgd = dstWidgd; 176 this.sTitle = sTitle; 177 int posColon = startDirMask.indexOf(':',2); //regard : after windows drive letter. 178 String sLocalDir1; 179 if(posColon >=0){ 180 this.sRootDir = startDirMask.substring(0, posColon) + "/"; 181 sLocalDir1 = startDirMask.substring(posColon+1); 182 } else { 183 this.sRootDir = ""; 184 sLocalDir1 = startDirMask; 185 } 186 int mode; 187 String sMask1; 188 int posSlash = sLocalDir1.lastIndexOf('/'); 189 if(posSlash == sLocalDir1.length()-1){ //last is slash 190 mode = GralFileDialog_ifc.directory; 191 sMask1 = ""; 192 } else { 193 mode = 0; 194 sMask1 = sLocalDir1.substring(posSlash+1); 195 if(sMask1.indexOf('*') >=0){ //contains an asterix 196 sLocalDir1 = posSlash >=0 ? sLocalDir1.substring(0, posSlash) : ""; 197 } else { 198 sMask1 = null; //no mask, sLocalDir is a directory. 199 } 200 } 201 this.sMask = sMask1; 202 this.sLocalDir = sLocalDir1; 203 this.dialogFile = createFileDialog(); 204 this.dialogFile.open(sTitle, mode); 205 } 206 207 } 208 209 210 211 /*package private*/ static final class PosThreadSafe 212 { 213 /**Position of the next widget to add. If some widgets are added one after another, 214 * it is similar like a flow-layout. 215 * But the position can be set. 216 * The values inside the position are positive in any case, so that the calculation of size is simple. 217 */ 218 protected final GralPos pos; //xPos, xPosFrac =0, xPosEnd, xPosEndFrac, yPos, yPosEnd, yPosFrac, yPosEndFrac =0; 219 220 /**False if the position is given newly. True if it is used. Then the next add-widget invocation 221 * calculates the next position in direction see {@link GralPos#setNextPosition()}. */ 222 protected boolean posUsed; 223 224 final long threadId; 225 226 PosThreadSafe() { 227 threadId = Thread.currentThread().getId(); 228 pos = new GralPos(); 229 } 230 231 PosThreadSafe(GralPos exists) { 232 threadId = Thread.currentThread().getId(); 233 pos = new GralPos(exists); 234 } 235 236 @Override public String toString(){ return "thread=" + threadId + ": " + pos.toString(); } 237 238 } 239 240 241 /**The current position as helper if it is the same thread. 242 * Initialized firstly empty. 243 */ 244 private PosThreadSafe posCurrent = new PosThreadSafe(); 245 246 private final Map<Long, PosThreadSafe> posThreadSafe = new TreeMap<Long, PosThreadSafe>(); 247 { //part of construction: safe the first instance. 248 posThreadSafe.put(posCurrent.threadId, posCurrent); 249 } 250 251 252 /**This instance helps to create the Dialog Widget as part of the whole window. It is used only in the constructor. 253 * Therewith it may be defined stack-locally. But it is better to show and explain if it is access-able at class level. */ 254 //GuiDialogZbnfControlled dialogZbnfConfigurator; 255 GralCfgBuilder cfgBuilder; 256 257 GralCfgWriter cfgWriter; 258 259 /**The designer is an aggregated part of the PanelManager, but only created if necessary. 260 * TODO check whether it should be disposed to {@link #gralDevice} .*/ 261 protected GralCfgDesigner designer; 262 263 private GralCfgData cfgData; 264 265 public boolean bDesignMode = false; 266 267 /**Some actions may be processed by a user implementation. */ 268 //private final GuiPlugUser_ifc user; 269 270 protected boolean bDesignerIsInitialized = false; 271 272 //final GralMng parent; 273 274 /**Base class for managing all panels and related windows. 275 * This base class contains all common resources to manage panels and windows. 276 */ 277 public final GralGraphicThread gralDevice = new GralGraphicThread(); 278 279 /**Properties of this Dialog Window. */ 280 public GralGridProperties propertiesGui; 281 282 /**Index of all input fields to access symbolic for all panels. */ 283 protected final Map<String, GralWidget> indexNameWidgets = new TreeMap<String, GralWidget>(); 284 285 /**Index of all input fields to access symbolic. NOTE: The generic type of WidgetDescriptor is unknown, 286 * because the set is used independently from the graphic system. */ 287 protected final Map<String, GralWidget> showFields = new TreeMap<String, GralWidget>(); 288 289 //private final IndexMultiTable showFieldsM; 290 291 private final List<GralWidget> widgetsInFocus = new LinkedList<GralWidget>(); 292 293 /**The one instance of the primary window created in the {@link org/vishia/ifc/GralFactory#createWindow(String, String, int)} . */ 294 private GralWindow windPrimary; 295 296 /**Three windows as sub window for html help, info and logging created if the primary window is created. */ 297 public GralInfoBox infoHelp, infoBox, infoLog; 298 299 private String sHelpBase; 300 301 302 303 /**List of all panels which may be visible yet. 304 * The list can be iterated. Therefore it is lock-free multi-threading accessible. 305 */ 306 protected final ConcurrentLinkedQueue<GralVisibleWidgets_ifc> listVisiblePanels = new ConcurrentLinkedQueue<GralVisibleWidgets_ifc>(); 307 308 309 Queue<GralWidget> listWidgetsPermanentUpdating = new LinkedList<GralWidget>(); 310 311 312 /**It is possible to write any message via this class to a logging system. 313 * All internal methods of gral writes exceptions to that logging system instead abort the execution of the application. 314 */ 315 public final LogMessage log; 316 317 318 protected GralMngApplAdapter_ifc applAdapter; 319 320 /**Composition of some curve view widgets, which should be filled indepentent of there visibility. */ 321 @Deprecated public final List<GralCurveView_ifc> curveContainer = new LinkedList<GralCurveView_ifc>(); 322 323 /**Position of the next widget to add. If some widgets are added one after another, 324 * it is similar like a flow-layout. 325 * But the position can be set. 326 * The values inside the position are positive in any case, so that the calculation of size is simple. 327 */ 328 protected final GralPos XXXpos = new GralPos(); //xPos, xPosFrac =0, xPosEnd, xPosEndFrac, yPos, yPosEnd, yPosFrac, yPosEndFrac =0; 329 330 /**False if the position is given newly. True if it is used. Then the next add-widget invocation 331 * calculates the next position in direction see {@link GralPos#setNextPosition()}. */ 332 protected boolean XXXposUsed; 333 334 335 336 337 /**Saved last use position. After calling {@link #setPosAndSize_(Control, int, int, int, int)} 338 * the xPos and yPos are setted to the next planned position. 339 * But, if a new position regarded to the last given one is selected, the previous one is need. 340 */ 341 //protected int xPosPrev, xPosPrevFrac, yPosPrev, yPosPrevFrac; 342 343 /**width and height for the next element. If a value */ 344 //protected int xSize, xSizeFrac, ySize, ySizeFrac; 345 346 /**'l' - left 'r'-right, 't' top 'b' bottom. */ 347 //protected char xOrigin = 'l', yOrigin = 'b'; 348 349 //protected char pos.dirNext = 'r'; 350 351 /**The width of the last placed element. 352 * It is used to determine a next xPos in horizontal direction. */ 353 //int xWidth; 354 355 /**True if the next element should be placed below the last. */ 356 protected boolean bBelow, bRigth; 357 358 359 /** 360 * 361 */ 362 protected GralUserAction userMainKeyAction; 363 364 InspcReplAlias replacerAlias = new InspcReplAlias(); 365 366 //public final GralWidgetHelper widgetHelper; 367 368 /**Creates an nee Panel Manager in a new Window. 369 * @param graphicBaseSystem 370 * @return 371 */ 372 @SuppressWarnings("unchecked") 373 public static GralMng createWindow(String graphicBaseSystem) 374 { Class<GralMng> mngClass; 375 GralMng mng = null; 376 String sGraphicBaseSystem = "org.vishia.mainGuiSwt.GuiPanelMngSwt"; 377 try{ 378 mngClass = (Class<GralMng>) Class.forName(sGraphicBaseSystem); 379 } catch(ClassNotFoundException exc){ mngClass = null; } 380 381 if(mngClass == null) throw new IllegalArgumentException("Graphic base system not found: " + sGraphicBaseSystem); 382 try{ 383 Constructor<GralMng> ctor = mngClass.getConstructor(); 384 mng = ctor.newInstance(); 385 //mng = mngClass.newInstance(); 386 387 } catch(IllegalAccessException exc){ throw new IllegalArgumentException("Graphic base system access error: " + sGraphicBaseSystem); 388 } catch(InstantiationException exc){ throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem); 389 } catch (SecurityException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem); 390 } catch (NoSuchMethodException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem); 391 } catch (IllegalArgumentException exc) {throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem); 392 } catch (InvocationTargetException exc) { throw new IllegalArgumentException("Graphic base system not able to instanciate: " + sGraphicBaseSystem); 393 } 394 return mng; 395 } 396 397 PosThreadSafe pos() 398 { long threadId1 = Thread.currentThread().getId(); 399 PosThreadSafe ret = posCurrent; //thread safe: atomic access, use ret. 400 if(ret.threadId != threadId1) { //only access to map if necessary. 401 Long threadId = new Long(threadId1); 402 ret = posThreadSafe.get(threadId); 403 if(ret == null){ 404 ret = new PosThreadSafe(posCurrent.pos); //copy values from the last one 405 posThreadSafe.put(threadId, ret); 406 } 407 } 408 posCurrent = ret; //store for next access, it may be faster. 409 return ret; 410 } 411 412 413 /**Sets the position with a given String, see {@link GralPos#setPosition(CharSequence, GralPos)} 414 * whereby the parent is the current position value. 415 * @param sPosition 416 * @throws ParseException 417 */ 418 public void setPos(String sPosition) 419 throws ParseException 420 { PosThreadSafe pos = pos(); 421 pos.pos.setPosition(sPosition, null); 422 pos.posUsed = false; 423 } 424 425 @Override public void setPositionSize(int line, int column, int height, int width, char direction) 426 { PosThreadSafe pos = pos(); 427 if(line < 0){ line = pos.posUsed? GralPos.next: GralPos.same; } 428 if(column < 0){ column = pos.posUsed? GralPos.next: GralPos.same; } 429 setFinePosition(line, 0, height + GralPos.size, 0, column, 0, width + GralPos.size, 0, 1, direction, 0 ,0 , pos.pos); 430 } 431 432 @Override public void setPosition(float line, float lineEndOrSize, float column, float columnEndOrSize 433 , int origin, char direction) 434 { setPosition(pos().pos, line, lineEndOrSize, column, columnEndOrSize, origin, direction); 435 } 436 437 438 @Override public void setPosition(float line, float lineEndOrSize, float column, float columnEndOrSize 439 , int origin, char direction, float border) 440 { PosThreadSafe pos = pos(); 441 pos.pos.setPosition(pos.pos, line, lineEndOrSize, column, columnEndOrSize, origin, direction, border); 442 pos.posUsed = false; 443 } 444 445 446 @Override public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize 447 , int origin, char direction) 448 { PosThreadSafe pos = pos(); 449 pos.pos.setPosition(framePos, line, lineEndOrSize, column, columnEndOrSize, origin, direction); 450 pos.posUsed = false; 451 } 452 453 @Override public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize 454 , int origin, char direction, float border) 455 { PosThreadSafe pos = pos(); 456 pos.pos.setPosition(framePos, line, lineEndOrSize, column, columnEndOrSize, origin, direction, border); 457 pos.posUsed = false; 458 } 459 460 @Override public void setFinePosition(int line, int yPosFrac, int ye, int yef 461 , int column, int xPosFrac, int xe, int xef, int origin, char direction, int border, int borderFrac, GralPos frame) 462 { PosThreadSafe pos = pos(); 463 pos.pos.setFinePosition(line, yPosFrac, ye, yef, column, xPosFrac, xe, xef, origin, direction, border, borderFrac, frame); 464 pos.posUsed = false; 465 } 466 467 468 @Override public void setSize(int height, int ySizeFrac, int width, int xSizeFrac) 469 { PosThreadSafe pos = pos(); 470 pos.pos.setSize(height, ySizeFrac, width, xSizeFrac); //NOTE: setSize sets the next pos 471 pos.posUsed = false; 472 } 473 474 void setSize(float height, float width) 475 { PosThreadSafe pos = pos(); 476 pos.pos.setSize(height, width, pos.pos); 477 pos.posUsed = false; 478 } 479 480 /**Not for user: Checks whether the position is used, sets the next position then, markes the position as used. 481 * See @link GralPos#setNextPosition(), {@link #posUsed}. TODO remove in AwtMng*/ 482 @Deprecated public void setNextPosition() 483 { PosThreadSafe pos = pos(); 484 if(pos.posUsed){ 485 pos.pos.setNextPosition(); 486 } 487 pos.posUsed = true; 488 } 489 490 /**Not for user: Checks whether the position is used, sets the next position then, markes the position as used. 491 * See @link GralPos#setNextPosition(), {@link #posUsed}. */ 492 public void setNextPositionUnused() 493 { PosThreadSafe pos = pos(); 494 if(pos.posUsed){ 495 pos.pos.setNextPosition(); 496 } 497 pos.posUsed = false; 498 } 499 500 public void registerShowField(GralWidget widg){ 501 //link the widget with is information together. 502 if(widgetsInFocus.size()==0 && widg.getDataPath() !=null) { 503 //it has not a datapath initally. Never come here. 504 widgetsInFocus.add(widg); //add first widget. 505 } 506 if(widg.name !=null){ 507 showFields.put(widg.name, widg); 508 } 509 510 } 511 512 513 @Override public GralPos getPositionInPanel(){ return pos().pos.clone(); } 514 515 public GralPos getPosCheckNext(){ 516 PosThreadSafe pos = pos(); 517 if(pos.posUsed){ 518 pos.pos.setNextPosition(); 519 pos.posUsed = false; 520 } 521 pos.posUsed = true; 522 return pos.pos.clone(); 523 } 524 525 526 /**Used for deprecated style, without independent GralWidget. TODO remove. 527 * @return Independent GralPos from the GralMng 528 */ 529 public GralPos getPosOldPositioning(){ return getPosCheckNext(); } 530 531 /**Map of all panels. A panel may be a dialog box etc. */ 532 protected final Map<String,GralPanelContent> panels = new TreeMap<String,GralPanelContent>(); 533 534 /**Any kind of TabPanel for this PanelManager TODO make protected 535 */ 536 public GralTabbedPanel currTabPanel; 537 538 //public GralPanelContent currPanel; 539 540 protected String sCurrPanel; 541 542 /**Last focused widget or last selected line in a table. 543 * This info can be used to get the last widget on a context menu etc. on another widget. 544 * See {@link #getLastClickedWidget()} 545 */ 546 private GralWidget_ifc lastClickedWidget; 547 548 //private String lastClickedDatapath; 549 550 //private String lastClickedVariable; 551 552 @Deprecated @Override public List<GralWidget> getListCurrWidgets(){ return pos().pos.panel.widgetList; } 553 554 /**Index of all user actions, which are able to use in Button etc. 555 * The user action "showWidgetInfos" defined here is added initially. 556 * Some more user-actions can be add calling {@link #registerUserAction(String, GralUserAction)}. 557 * */ 558 protected final Map<String, GralUserAction> userActions = new TreeMap<String, GralUserAction>(); 559 //private final Map<String, ButtonUserAction> userActions = new TreeMap<String, ButtonUserAction>(); 560 561 /**Index of all Tables, which are representable. */ 562 //private final Map<String, Table> userTableAccesses = new TreeMap<String, Table>(); 563 564 /**Map of replacements of paths to data. Filled from ZBNF: DataReplace::= <$?key> = <$-/\.?string> */ 565 private final Map<String, String> dataReplace = new TreeMap<String,String>(); 566 567 public ImplAccess impl; 568 569 private static GralMng singleton; 570 571 /* 572 public GralMng(GralGraphicThread device, LogMessage log) 573 { this.gralDevice = device; 574 //this.propertiesGui = props; 575 this.log = log; 576 //its a user action able to use in scripts. 577 userActions.put("showWidgetInfos", this.actionShowWidgetInfos); 578 GralMng.singleton = this; 579 } 580 */ 581 582 private GralMng(LogMessage log) 583 { //this.propertiesGui = props; 584 this.log = log; 585 //its a user action able to use in scripts. 586 userActions.put("showWidgetInfos", this.actionShowWidgetInfos); 587 GralMng.singleton = this; 588 } 589 590 591 /**Creates the singleton instance of the GralMng. If this routine is invoked more as one time, the first invocation 592 * is the correct one. The more-time-invocation is supported because an application may not invoke this routine. 593 * Therefore it is invoked later additional. 594 * <br> See also {@link #get()}. 595 * @param log The first invocation determines the log output. 596 * @return true if created, false if exists already. 597 * @??deprecated {@link #get()} is sufficient TODO detemine log 598 */ 599 public static boolean create(LogMessage log){ 600 if(singleton !=null) return false; 601 else { 602 singleton = new GralMng(log); 603 return true; 604 } 605 } 606 607 608 /**Returns the singleton of the GralMng. Creates it if it is not instantiated yet. 609 * On creation all logging output will be redirect to System.out. 610 * To use another logging output, create the GralMng using {@link GralMng#GralMng(LogMessage)} 611 * on start of application, before this routine is firstly called. */ 612 public static GralMng get(){ 613 if(singleton == null) { //not initialized yet, early invocation: 614 singleton = new GralMng(new MainCmdLoggingStream(System.out)); 615 } 616 return singleton; 617 } 618 619 620 public void setProperties(GralGridProperties props) { 621 this.propertiesGui = props; 622 } 623 624 public void setFirstlyThePrimaryWindow(GralWindow primaryWindow){ 625 if(this.windPrimary !=null) 626 throw new IllegalStateException("Primary Window should set only one time."); 627 this.windPrimary = primaryWindow; 628 panels.put("primaryWindow", primaryWindow); 629 }; 630 631 632 public static void createMainWindow(GralFactory factory, GralWindow window, char sizeShow, int left, int top, int xSize, int ySize) { 633 factory.createWindow(window, sizeShow, left, top, xSize, ySize); 634 } 635 636 637 638 /**This routine should be called in the initializing routine in the graphic thread one time. 639 * @param mainCmd If given the help from mainCmd will be written into the Help box. 640 */ 641 public void createHtmlInfoBoxes(MainCmd mainCmd) 642 { 643 setPosition(10, 0, 10, 0, 0, 'd'); 644 infoBox = createTextInfoBox("infoBox", "Info"); 645 // 646 selectPanel("primaryWindow"); 647 setPosition(0,40,10,0,0,'.'); 648 infoHelp = GralInfoBox.createHtmlInfoBox(null, "Help", "Help", true); 649 if(mainCmd !=null) { 650 try{ 651 for(String line: mainCmd.listHelpInfo){ 652 infoHelp.append(line).append("\n"); 653 } 654 } catch(Exception exc){ writeLog(0, exc); } 655 } 656 } 657 658 659 660 /**Not that this routine must not invoked before the {@link GralFactory#createWindow(GralWindow, char, int, int, int, int)} 661 * was not called. 662 * @see org.vishia.gral.ifc.GralMngBuild_ifc#createImplWidget_Gthread(org.vishia.gral.base.GralWidget) 663 */ 664 @Override public void createImplWidget_Gthread(GralWidget widgg){ 665 if(widgg instanceof GralWindow){ 666 GralWindow wind1 = (GralWindow)widgg; 667 impl.createSubWindow(wind1); 668 //registerPanel(wind1); 669 //set the current position of the manager to this window, initalize it. 670 //PosThreadSafe pos = pos(); 671 //pos.pos.panel = wind1; //it is selected. 672 //pos.pos.setPosition(null, 0,0,0,0,0,'r'); //per default the whole window as position and size. 673 674 } else { 675 impl.createImplWidget_Gthread(widgg); 676 } 677 } 678 679 680 /* (non-Javadoc) 681 * @see org.vishia.gral.ifc.GralMngBuild_ifc#setMainKeyAction(org.vishia.gral.ifc.GralUserAction) 682 */ 683 @Override public GralUserAction setMainKeyAction(GralUserAction userMainKeyAction){ 684 GralUserAction last = this.userMainKeyAction; 685 this.userMainKeyAction = userMainKeyAction; 686 return last; 687 } 688 689 690 691 /**package private*/ GralUserAction userMainKeyAction(){ return userMainKeyAction; } 692 693 694 @Override public GralGridProperties propertiesGui(){ return propertiesGui; } 695 696 @Override public GralGraphicThread gralDevice(){ return gralDevice; } 697 698 @Override public LogMessage log(){ return log; } 699 700 701 702 /**Returns null if the widget value can only be gotten platform-depending. 703 * The platform widget manager should override this method too and invoke super.getValueFromWidget() 704 * to call this method. If it returns a value, then it is ok. 705 * A user invocation calls the overridden platform depending method automatically. 706 * <br> 707 * See {@link org.vishia.gral.swt.SwtMng}. 708 */ 709 @Override public String getValueFromWidget(GralWidget widgd) 710 { String sValue = null; 711 if(widgd instanceof GralTable){ 712 StringBuilder u = new StringBuilder(); 713 GralTableLine_ifc line = ((GralTable)widgd).getCurrentLine(); 714 String[] texts = line.getCellTexts(); 715 for(int iCol = 0; iCol < texts.length; ++iCol){ 716 u.append(texts[iCol]).append('\t'); 717 } 718 sValue = u.toString(); 719 } 720 return sValue; 721 } 722 723 public void setApplicationAdapter(GralMngApplAdapter_ifc adapter){ this.applAdapter = adapter; } 724 725 726 public GralMngApplAdapter_ifc getApplicationAdapter(){ return applAdapter; } 727 728 729 @Override public ReplaceAlias_ifc getReplacerAlias(){ return replacerAlias; } 730 731 732 733 public void setHelpBase(String path){ 734 sHelpBase = path; 735 } 736 737 738 739 public void setHelpUrl(String url){ 740 String sUrl; 741 if(url.startsWith("+")){ 742 sUrl = sHelpBase + url.substring(1); 743 } else if(FileSystem.isAbsolutePath(url)) { 744 sUrl = url; //absolute path 745 } else if (sHelpBase !=null) { //it is a directory which does not end with "/" 746 sUrl = sHelpBase + "/" + url; //url is a "file.html+label" 747 } else { 748 sUrl = url; //should be absolute 749 } 750 if(infoHelp !=null) infoHelp.setUrl(sUrl); 751 } 752 753 754 755 public void setHtmlHelp(String url){ 756 setHelpUrl(url); 757 /* 758 if(applAdapter !=null){ 759 applAdapter.setHelpUrl(url); 760 } 761 */ 762 } 763 764 public void showInfo(CharSequence text) { 765 if(infoBox == null) return; 766 if(text !=null){ infoBox.setText(text); } 767 infoBox.setFocus(); 768 } 769 770 public void setInfo(CharSequence text) { 771 if(infoBox == null) return; 772 infoBox.setText(text); 773 } 774 775 776 777 public void addInfo(CharSequence info, boolean show) 778 { 779 if(infoBox == null) return; 780 try{ infoBox.append(info); } 781 catch(IOException exc){} 782 if(show){ 783 infoBox.setFocus(); //setWindowVisible(true); 784 } 785 } 786 787 788 789 /**selects a registered panel for the next add-operations. 790 */ 791 @Override public void selectPanel(String sName){ 792 PosThreadSafe pos = pos(); 793 pos.pos.panel = panels.get(sName); 794 sCurrPanel = sName; 795 if(pos.pos.panel == null && currTabPanel !=null) { 796 //use the position of the current tab panel for the WidgetMng. Its panel is the parent. 797 pos.pos.set(currTabPanel.pos()); 798 pos.pos.panel = currTabPanel.addGridPanel(sName, /*"&" + */sName,1,1,10,10); 799 panels.put(sName, pos.pos.panel); //TODO unnecessay, see addGridPanel 800 log.sendMsg(0, "GuiPanelMng:selectPanel: unknown panel name %s", sName); 801 //Note: because the pos.panel is null, not placement will be done. 802 } 803 setPosition(0,0,0,0,0,'d'); //set the position to default, full panel because the panel was selected newly. 804 } 805 806 807 /**Selects the given panel as current panel to build some content. */ 808 @Override public void selectPanel(GralPanelContent panel) { 809 pos().pos.panel = panel; 810 sCurrPanel = panel == null ? null: panel.name; 811 setPosition(0,0,0,0,0,'d'); //set the position to default, full panel because the panel was selected newly. 812 } 813 814 /**Selects the primary window as current panel to build some content. */ 815 @Override public void selectPrimaryWindow() { selectPanel(windPrimary); } 816 817 @Override public boolean currThreadIsGraphic(){ 818 return Thread.currentThread().getId() == gralDevice.getThreadIdGui(); 819 } 820 821 822 823 @Override public GralWidget getWidget(String name) 824 { return indexNameWidgets.get(name); 825 } 826 827 828 829 @Override public void buildCfg(GralCfgData data, File fileCfg) //GuiCfgBuilder cfgBuilder) 830 { 831 this.cfgData = data; 832 File currentDir = FileSystem.getDir(fileCfg); 833 this.cfgBuilder = new GralCfgBuilder(cfgData, this, currentDir); 834 cfgBuilder.buildGui(log, 0); 835 this.designer = new GralCfgDesigner(cfgBuilder, this, log); 836 this.bDesignMode = true; 837 } 838 839 /**Sets or resets the design mode. The design mode allows to change the content. 840 * @param mode 841 */ 842 @Override public void setDesignMode(boolean mode){ this.bDesignMode = mode; } 843 844 /**Saves the given configuration. 845 * @param dest 846 * @return 847 */ 848 @Override public String saveCfg(Writer dest) 849 { cfgWriter = new GralCfgWriter(log); 850 String sError = cfgWriter.saveCfg(dest, cfgData); 851 return sError; 852 } 853 854 855 856 857 /**This method is called whenever the left mouse is pressed on a widget, whiches 858 * @param lastClickedWidgetInfo 859 */ 860 public void setLastClickedWidget(GralWidget_ifc lastClickedWidgetInfo) 861 { 862 this.lastClickedWidget = lastClickedWidgetInfo; 863 } 864 865 866 /**Returns that widget which was clicked by mouse at last. This method is usefully for debugging 867 * and for special functionality. A widget which {@link GralWidget#setDataPath(String)} is initialized 868 * with "widgetInfo" is not captured for this operation. It means, if any user action method uses 869 * this method to get the last clicked widget, that widget itself have to be marked with 870 * <b>setDataPath("widgetInfo");</b> to prevent getting its own widget info. 871 * @return The last clicked widget 872 */ 873 public GralWidget_ifc getLastClickedWidget(){ return lastClickedWidget; } 874 875 876 /**Returns that widget which was clicked by mouse at last. This method is usefully for debugging 877 * and for special functionality. A widget which {@link GralWidget#setDataPath(String)} is initialized 878 * with "widgetInfo" is not captured for this operation. It means, if any user action method uses 879 * this method to get the last clicked widget, that widget itself have to be marked with 880 * <b>setDataPath("widgetInfo");</b> to prevent getting its own widget info. 881 * @return The last clicked widget 882 */ 883 //public String getLastClickedDatapath(){ return lastClickedWidget; } 884 885 886 /**Registers all user actions, which are able to use in Button etc. 887 * The name is related with the <code>userAction=</code> designation in the configuration String. 888 * @param name if it contains "<name>" then that is replace by the {@link GralUserAction#name}. 889 * You can give "<name>" only to set the action's name. 890 * @param action 891 */ 892 @Override public void registerUserAction(String name, GralUserAction action) 893 { final String name1; 894 if(name.indexOf("<name>") >=0){ 895 name1 = name.replace("<name>", action.name); 896 } else { 897 name1 = name; 898 } 899 userActions.put(name1, action); 900 } 901 902 @Override public GralUserAction getRegisteredUserAction(String name) 903 { 904 return userActions.get(name); 905 } 906 907 908 void registerWidget(String name, GralWidget widgd) { 909 indexNameWidgets.put(name, widgd); 910 } 911 912 void removeWidget(String name) { 913 indexNameWidgets.remove(name); 914 } 915 916 @Override public void registerWidget(GralWidget widgd) 917 { 918 /* 919 PosThreadSafe pos = pos(); 920 GralPanelContent panel = widgd.pos() !=null ? widgd.pos().panel : pos.pos.panel; 921 if(widgd.name != null){ 922 indexNameWidgets.put(widgd.name, widgd); 923 } 924 //only widgets with size from right TODO percent size too. 925 boolean toResize = pos.pos.x.p1 < 0 || pos.pos.x.p2 <= 0 || pos.pos.y.p1< 0 || pos.pos.y.p2 <=0; 926 panel.addWidget(widgd, toResize); 927 */ 928 } 929 930 931 public void deregisterWidgetName(GralWidget widg) 932 { 933 if(widg.name != null){ 934 indexNameWidgets.remove(widg.name); 935 } 936 937 } 938 939 /**Registers a panel to place the widgets. 940 * After registration, this panel is the current one, stored in {@link #pos()} for this thread. 941 * The panel can be selected with its name calling the {@link #selectPanel(String)} -routine 942 * @param key Name of the panel. 943 * @param panel The panel. 944 */ 945 @Override public void registerPanel(GralPanelContent panel){ 946 GralPanelContent exist = panels.get(panel.name); 947 if(exist !=null){ 948 if(exist == panel) System.out.println("info: unnecessary registerPanel " + panel.name); 949 else System.err.println("info: faulty registerPanel " + panel.name); 950 } 951 panels.put(panel.name, panel); 952 } 953 954 955 public void setPosPanel(GralPanelContent panel) { 956 GralMng.PosThreadSafe pos = pos(); 957 pos.pos.panel = panel; 958 //initialize the position because its a new panel. The initial position is the whole panel. 959 pos.pos.setFinePosition(0,0,0,0,0,0,0,0,0,'d',0,0, pos.pos); 960 sCurrPanel = panel.name; 961 } 962 963 964 /*package private*/ void deregisterPanel(GralPanelContent panel) { 965 if(sCurrPanel.equals(panel.name)) { 966 sCurrPanel = windPrimary.name; 967 } 968 panels.remove(panel.name); 969 } 970 971 972 /**Returns a Set of all fields, which are created to show. 973 * @return the set, never null, possible an empty set. 974 */ 975 public Set<Map.Entry<String, GralWidget>> getShowFields() 976 { 977 Set<Map.Entry<String, GralWidget>> set =showFields.entrySet(); 978 return set; //(Set<Entry<String, WidgetDescriptor>>)set; 979 } 980 981 982 public Map<String, String> getAllValues() 983 { 984 Map<String, String> values = new TreeMap<String, String>(); 985 for(GralWidget input: indexNameWidgets.values()){ 986 String sValue = getValueFromWidget(input); 987 values.put(input.name, sValue); 988 } 989 return values; 990 } 991 992 @Override public String getValue(String sName) 993 { final String sValue; 994 GralWidget widgetDescr = indexNameWidgets.get(sName); 995 if(widgetDescr !=null){ 996 sValue = getValueFromWidget(widgetDescr); 997 } else { 998 sValue = null; 999 } 1000 return sValue; 1001 } 1002 1003 1004 1005 /**It is a special routine for tabbedPanel. 1006 * The reason: If a new tab should add in {@link GralTabbedPanel#addGridPanel(String, String, int, int, int, int)} 1007 * then the mng is set to the tabbed panel. 1008 * @param tabbedPanel 1009 */ 1010 /*package private*/public void setTabbedPanel(GralPanelContent tabbedPanel){ 1011 pos().pos.panel = tabbedPanel; 1012 } 1013 1014 1015 public GralPanelContent getPanel(String name){ 1016 return panels.get(name); 1017 } 1018 1019 1020 public GralWindow getPrimaryWindow(){ return windPrimary; } 1021 1022 1023 public GralPanelContent getCurrentPanel(){ return pos().pos.panel; } 1024 1025 public GralPanelActivated_ifc actionPanelActivate = new GralPanelActivated_ifc() 1026 { @Override public void panelActivatedGui(List<GralWidget> widgetsP) 1027 { //changeWidgets(widgetsP); 1028 } 1029 }; 1030 1031 1032 1033 protected void checkAdmissibility(boolean value){ 1034 if(!value){ 1035 throw new IllegalArgumentException("failure"); 1036 } 1037 } 1038 1039 1040 private GralWidget findWidget(String name){ 1041 GralWidget widg = indexNameWidgets.get(name); 1042 if(widg == null){ 1043 log.sendMsg(0, "GuiMainDialog:setBackColor: unknown widget %s", name); 1044 } 1045 return widg; 1046 } 1047 1048 1049 /**Sets the background color of any widget. The widget may be for example: 1050 * <ul> 1051 * <li>a Table: Then a new line will be colored. 1052 * <li>a Tree: Then a new leaf is colored. 1053 * <li>a Text-edit-widget: Then the field background color is set. 1054 * </ul> 1055 * The color is written into a queue, which is red in another thread. 1056 * It may be possible too, that the GUI is realized in another module, maybe remote. 1057 * It means, that a few milliseconds should be planned before the change appears. 1058 * If the thread doesn't run or the remote receiver isn't present, 1059 * than the queue may be overflowed or the request may be lost. 1060 * 1061 * @param name The name of the widget, which was given by the add...()-Operation 1062 * @param ident A identifying number. It meaning depends on the kind of widget. 1063 * 0 means, insert on top. Integer.MAXVALUE means, insert after the last element (append). 1064 * @param content The content to insert. 1065 * @return 1066 */ 1067 @Override public void setBackColor(String name, int ix, int color) 1068 { 1069 GralWidget widg; 1070 if( (widg = findWidget(name)) !=null){ 1071 widg.setBackColor(GralColor.getColor(color), ix); 1072 } 1073 } 1074 1075 1076 @Override public void setText(String name, CharSequence text){ 1077 GralWidget widg; 1078 if( (widg = findWidget(name)) !=null){ 1079 widg.setText(text); 1080 } 1081 } 1082 1083 1084 1085 @Override public void setValue(String widget, Object visibleInfo, Object userData){ 1086 GralWidget widg; 1087 if( (widg = findWidget(widget)) !=null){ 1088 widg.setValue(0,0, visibleInfo, userData); 1089 } 1090 1091 } 1092 1093 @Override public void addText(String name, CharSequence text){ 1094 GralWidget widg; 1095 if( (widg = findWidget(name)) !=null){ 1096 if(widg instanceof GralTextBox_ifc){ 1097 try{ ((GralTextBox)widg).append(text); } 1098 catch(IOException exc){ System.err.println("TODO"); } 1099 } 1100 else { 1101 System.err.println("GralMng - addText not possible;" + name); 1102 } 1103 } 1104 } 1105 1106 1107 @Override public GralWidget addText(String sText, int origin, GralColor textColor, GralColor backColor) 1108 { 1109 GralLabel widgg = new GralLabel(null, sText, origin); 1110 widgg.setTextColor(textColor); 1111 widgg.setBackColor(backColor, 0); 1112 widgg.setToPanel(this); //Note: sets TextFont, don't call this.setToPanel 1113 return widgg; 1114 } 1115 1116 1117 /** Adds a text field for showing or editing a text value. 1118 * 1119 * @param sName The registering name 1120 * @param width Number of grid units for length 1121 * @param editable true than edit-able, false to show content 1122 * @param prompt If not null, than a description label is shown 1123 * @param promptStylePosition Position and size of description label: 1124 * upper case letter: normal font, lower case letter: small font 1125 * 'l' left, 't' top (above field) 1126 * @return 1127 */ 1128 @Override public GralTextField addTextField(String name, boolean editable, String prompt, String promptStylePosition){ 1129 if(name !=null && name.charAt(0) == '$'){ 1130 name = sCurrPanel + name.substring(1); 1131 } 1132 GralTextField widgg = new GralTextField(name); 1133 widgg.setPrompt(prompt, promptStylePosition); 1134 widgg.setEditable(editable); 1135 createImplWidget_Gthread(widgg); 1136 //SwtTextFieldWrapper.createTextField(widgg, this); 1137 return widgg; 1138 } 1139 1140 1141 1142 1143 1144/** Adds a text box for showing or editing a text in multi lines. 1145 * 1146 * @param sName The registering name 1147 * @param width Number of grid units for length 1148 * @param editable true than edit-able, false to show content 1149 * @param prompt If not null, than a description label is shown 1150 * @param promptStylePosition Position and size of description label: 1151 * upper case letter: normal font, lower case letter: small font 1152 * 'l' left, 't' top (above field) 1153 * @return 1154 */ 1155@Override public GralTextBox addTextBox(String name, boolean editable, String prompt, char promptStylePosition) 1156{ 1157 if(name !=null && name.charAt(0) == '$'){ 1158 name = sCurrPanel + name.substring(1); 1159 } 1160 GralTextBox widgg = new GralTextBox(name); 1161 char[] prompt1 = new char[1]; 1162 prompt1[0] = promptStylePosition; 1163 widgg.setPrompt(prompt, new String(prompt1)); 1164 widgg.setEditable(editable); 1165 createImplWidget_Gthread(widgg); 1166 //SwtTextFieldWrapper.createTextField(widgg, this); 1167 return widgg; 1168 1169} 1170 1171 1172 1173@Override public GralValueBar addValueBar( 1174 String sName 1175//, String sShowMethod 1176, String sDataPath 1177) 1178{ 1179 GralValueBar wdgg = new GralValueBar(sName); 1180 wdgg.setDataPath(sDataPath); 1181 wdgg.setToPanel(this); 1182 return wdgg; 1183} 1184 1185 1186@Override public GralButton addButton( 1187 String sName 1188 , GralUserAction action 1189 , String sButtonText 1190 ) 1191{ return addButton(sName, action, null, null, sButtonText); 1192} 1193 1194@Override public GralButton addButton( 1195 String sName 1196, GralUserAction action 1197, String sCmd 1198//, String sShowMethod 1199, String sDataPath 1200, String sButtonText 1201 //, int height, int width 1202 //, String sCmd, String sUserAction, String sName) 1203) 1204{ 1205 setNextPositionUnused(); //since 130523 it should be the valid one. 1206 float ySize = pos().pos.height(); 1207 int xSize = (int)pos().pos.width(); 1208 1209 char size = ySize > 3? 'B' : 'A'; 1210 if(sName == null){ sName = sButtonText; } 1211 GralButton widgButton = new GralButton(sName); 1212 //SwtButton widgButton = new SwtButton(sName, this, (Composite)pos().panel.getPanelImpl(), 0, size); 1213 if(action !=null) 1214 stop(); 1215 widgButton.setActionChange(action); //maybe null 1216 widgButton.setText(sButtonText); 1217 //in ctor: widgButton.setPanelMng(this); 1218 widgButton.sCmd = sCmd; 1219 widgButton.setDataPath(sDataPath); 1220 registerWidget(widgButton); 1221 createImplWidget_Gthread(widgButton); 1222 return widgButton; 1223} 1224 1225 1226 1227@Override public GralButton addSwitchButton( 1228 String sName 1229, GralUserAction action 1230, String sCmd 1231, String sDataPath 1232, String sButtonText 1233, String sColor0 1234, String sColor1 1235 //, int height, int width 1236 //, String sCmd, String sUserAction, String sName) 1237) 1238{ 1239 int ySize = (int)pos().pos.height(); 1240 int xSize = (int)pos().pos.width(); 1241 1242 char size = ySize > 3? 'B' : 'A'; 1243 if(sName == null){ sName = sButtonText; } 1244 GralButton widgButton = new GralButton(sName); 1245 GralColor colorOff = GralColor.getColor(sColor0); 1246 GralColor colorOn = GralColor.getColor(sColor1); 1247 widgButton.setSwitchMode(colorOff, colorOn); 1248 widgButton.setActionChange(action); //maybe null 1249 widgButton.setText(sButtonText); 1250 //widgButton.setPanelMng(this); 1251 widgButton.sCmd = sCmd; 1252 widgButton.setDataPath(sDataPath); 1253 registerWidget(widgButton); 1254 createImplWidget_Gthread(widgButton); 1255 return widgButton; 1256} 1257 1258 1259@Override public GralButton addSwitchButton( 1260 String sName 1261, String sButtonTextOff 1262, String sButtonTextOn 1263, GralColor colorOff 1264, GralColor colorOn 1265 //, int height, int width 1266 //, String sCmd, String sUserAction, String sName) 1267) 1268{ 1269 int ySize = (int)pos().pos.height(); 1270 int xSize = (int)pos().pos.width(); 1271 1272 char size = ySize > 3? 'B' : 'A'; 1273 GralButton widgButton = new GralButton(sName); 1274 widgButton.setSwitchMode(colorOff, colorOn); 1275 widgButton.setSwitchMode(sButtonTextOff, sButtonTextOn); 1276 //in ctor: widgButton.setPanelMng(this); 1277 if(sName !=null){ registerWidget(widgButton); } 1278 createImplWidget_Gthread(widgButton); 1279 return widgButton; 1280} 1281 1282 1283 1284public GralButton addCheckButton( 1285 String sName 1286, String sButtonTextOn 1287, String sButtonTextOff 1288, String sButtonTextDisabled 1289, GralColor colorOn 1290, GralColor colorOff 1291, GralColor colorDisabled 1292) 1293{ 1294 int ySize = (int)pos().pos.height(); 1295 int xSize = (int)pos().pos.width(); 1296 1297 char size = ySize > 3? 'B' : 'A'; 1298 GralButton widgButton = new GralButton(sName); 1299 widgButton.setSwitchMode(colorOff, colorOn, colorDisabled); 1300 widgButton.setSwitchMode(sButtonTextOff, sButtonTextOn, sButtonTextDisabled); 1301 //widgButton.setPanelMng(this); 1302 if(sName !=null){ registerWidget(widgButton); } 1303 createImplWidget_Gthread(widgButton); 1304 return widgButton; 1305} 1306 1307 1308 1309 1310@Override public GralLed addLed( 1311 String sName 1312//, String sShowMethod 1313, String sDataPath 1314) 1315{ 1316 int ySize = (int)(pos().pos.height()); 1317 int xSize = (int)(pos().pos.width()); 1318 1319 GralLed gralLed = new GralLed(sName); 1320 //SwtLed swtLed = new SwtLed(gralLed, this); 1321 gralLed.setDataPath(sDataPath); 1322 //registerWidget(gralLed); 1323 gralLed.setToPanel(this); 1324 return gralLed; 1325} 1326 1327 1328 @Deprecated @Override public void setBackColor(GralWidget widg, int ix, int color) 1329 { widg.setBackColor(GralColor.getColor(color), ix); 1330 } 1331 1332 1333 @Deprecated @Override public void setLineColor(GralWidget widg, int ix, int color) 1334 { widg.setLineColor(GralColor.getColor(color), ix); 1335 } 1336 1337 1338 @Deprecated @Override public void setTextColor(GralWidget widg, int ix, int color) 1339 { widg.setTextColor(GralColor.getColor(color)); 1340 } 1341 1342 1343 1344 /**Adds a line. 1345 * <br><br>To adding a line is only possible if the current panel is of type 1346 * {@link SwtCanvasStorePanel}. This class stores the line coordinates and conditions 1347 * and draws it as background if drawing is invoked. 1348 * 1349 * @param colorValue The value for color, 0xffffff is white, 0xff0000 is red. 1350 * @param xa start of line relative to current position in grid units. 1351 * The start is relative to the given position! Not absolute in window! 1352 * @param ya start of line relative to current position in grid units. 1353 * @param xe end of line relative to current position in grid units. 1354 * @param ye end of line relative to current position in grid units. 1355 */ 1356 @Deprecated @Override public void addLine(int colorValue, float xa, float ya, float xe, float ye){ 1357 //if(pos().pos.panel.getPanelImpl() instanceof SwtCanvasStorePanel){ 1358 if(pos().pos.panel.canvas !=null){ 1359 GralColor color = propertiesGui.color(colorValue); 1360 int xgrid = propertiesGui.xPixelUnit(); 1361 int ygrid = propertiesGui.yPixelUnit(); 1362 int x1 = (int)((pos().pos.x.p1 + xa) * xgrid); 1363 int y1 = (int)((pos().pos.y.p1 - ya) * ygrid); 1364 int x2 = (int)((pos().pos.x.p1 + xe) * xgrid); 1365 int y2 = (int)((pos().pos.y.p1 - ye) * ygrid); 1366 //Any panel which is created in the SWT-implementation is a CanvasStorePanel. 1367 //This is because lines should be drawn. 1368 //((SwtCanvasStorePanel) pos().pos.panel.getPanelImpl()).store.drawLine(color, x1, y1, x2, y2); 1369 pos().pos.panel.canvas.drawLine(color, x1, y1, x2, y2); 1370 //furtherSetPosition((int)(xe + 0.99F), (int)(ye + 0.99F)); 1371 } else { 1372 log.sendMsg(0, "GuiPanelMng:addLine: panel is not a CanvasStorePanel"); 1373 } 1374 } 1375 1376 1377 @Override public void addLine(GralColor color, List<GralPoint> points){ 1378 if(pos().pos.panel.canvas !=null){ 1379 pos().pos.panel.canvas.drawLine(pos().pos, color, points); 1380 } else { 1381 log.sendMsg(0, "GralMng.addLine - panel is not a CanvasStorePanel;"); 1382 } 1383 } 1384 1385 1386 1387 @Override public void setLed(GralWidget widg, int colorBorder, int colorInner) 1388 { 1389 ((GralLed)widg).setColor(GralColor.getColor(colorBorder), GralColor.getColor(colorInner)); 1390 } 1391 1392 1393 @Override public ConcurrentLinkedQueue<GralVisibleWidgets_ifc> getVisiblePanels() 1394 { 1395 return listVisiblePanels; 1396 } 1397 1398 @Override public GralVisibleWidgets_ifc getWidgetsPermanentlyUpdating(){ 1399 /// 1400 return null; 1401 } 1402 1403 1404 1405 @Override public void setFocus(GralWidget widgd) 1406 { 1407 widgd.setFocus(); 1408 } 1409 1410 @Override public void notifyFocus(GralWidget widgd) 1411 { 1412 if(widgd.getDataPath() !=null) { 1413 //regard only widgets with datapath, all other are not used. 1414 //Therewith preserve the last focused widget which has a datapath. 1415 synchronized(widgetsInFocus){ 1416 widgetsInFocus.remove(widgd); //remove it anywhere inside 1417 widgetsInFocus.add(0, widgd); //add at start. 1418 } 1419 } 1420 } 1421 1422 @Override public GralWidget getWidgetInFocus(){ return widgetsInFocus.size() >0 ? widgetsInFocus.get(0) : null; } 1423 1424 @Override public List<GralWidget> getWidgetsInFocus(){ return widgetsInFocus; } 1425 1426 @Override public int getColorValue(String sColorName){ return propertiesGui.getColorValue(sColorName); } 1427 1428 @Override public GralColor getColor(String sColorName){ return propertiesGui.color(getColorValue(sColorName)); } 1429 1430 1431 1432 GralUserAction actionShowWidgetInfos = new GralUserAction("actionShowWidgetInfos") 1433 { 1434 1435 @Override public boolean userActionGui( 1436 String sCmd 1437 , GralWidget infos, Object... params 1438 ) 1439 { 1440 if(lastClickedWidget !=null){ 1441 log.sendMsg(Report.info, "widget %s, datapath=%s" 1442 , GralMng.this.lastClickedWidget.getName() 1443 , GralMng.this.lastClickedWidget.getDataPath()); 1444 return true; 1445 } else { 1446 log.sendMsg(0, "widgetInfo - no widget selected"); 1447 } 1448 return false; 1449 } 1450 1451 }; 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 /**Calculates the pixel position and size with a given GralPos for the given size of display appearance. 1466 * @param pos Given position 1467 * @param widthParentPixel width of the container. This value will be used if the position is given 1468 * from right with negative numbers. 1469 * @param heightParentPixel height of the container. This value will be used if the position is given 1470 * from bottom with negative numbers. 1471 * @param widthWidgetNat natural width of the component which will be positioning. 1472 * This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the xe-value 1473 * @param heightWidgetNat natural height of the component which will be positioning. 1474 * This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the ye-value 1475 * @return The position and size relative in the container. 1476 * @deprecated, use {@link #calcWidgetPosAndSizeSwt(GralPos, int, int)} because the parent is known in pos. 1477 */ 1478 public GralRectangle calcWidgetPosAndSize(GralPos pos, 1479 int widthParentPixel, int heightParentPixel, 1480 int widthWidgetNat, int heightWidgetNat 1481 ){ return pos.calcWidgetPosAndSize(propertiesGui, widthParentPixel, heightParentPixel 1482 , widthWidgetNat, heightWidgetNat); 1483 } 1484 1485 1486 1487 1488 1489 1490 1491 /* (non-Javadoc) 1492 * @see org.vishia.gral.ifc.GralMngBuild_ifc#addFileSelectField(java.lang.String, java.util.List, java.lang.String, java.lang.String, java.lang.String) 1493 */ 1494 @Override public GralTextField addFileSelectField(String name, List<String> listRecentFiles 1495 , String startDirMask, String prompt, String promptStylePosition) 1496 { //int xSize1 = xSize; 1497 //The macro widget consists of more as one widget. Position the inner widgets: 1498 GralPos posAll = getPositionInPanel(); //saved whole position. 1499 //reduce the length of the text field: 1500 setPosition(GralPos.same, GralPos.same, GralPos.same, GralPos.same -2.0F, 1, 'r'); 1501 1502 //xSize -= ySize; 1503 GralTextField widgd = addTextField(name, true, prompt, promptStylePosition ); 1504 setSize(posAll.height(), 2.0F); 1505 //xPos += xSize; 1506 //xSize = ySize; 1507 GralWidget widgdSelect = addButton(name + "<", actionFileSelect, "<"); 1508 FileSelectInfo fileSelectInfo = new FileSelectInfo(name, listRecentFiles, startDirMask, widgd); 1509 widgdSelect.setContentInfo(fileSelectInfo); 1510 //xSize = xSize1; 1511 pos().pos.set(posAll); //the saved position. 1512 return widgd; 1513 } 1514 1515 1516 1517 GralUserAction actionFileSelect = new GralUserAction("actionFileSelect") 1518 { @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params) 1519 { assert(false); 1520 return userActionGui(null, infos); 1521 } 1522 1523 @Override public boolean userActionGui(int actionCode, GralWidget widgg, Object... params) 1524 { 1525 if(KeyCode.isControlFunctionMouseUpOrMenu(actionCode)){ //supress both mouse up and down reaction 1526 FileSelectInfo fileSelectInfo = (FileSelectInfo)widgg.getContentInfo(); 1527 if(fileSelectInfo.listRecentFiles !=null){ 1528 stop(); 1529 } else { 1530 fileSelectInfo.dialogFile.show(fileSelectInfo.sRootDir, fileSelectInfo.sLocalDir 1531 , fileSelectInfo.sMask, fileSelectInfo.sTitle); 1532 String fileSelect = fileSelectInfo.dialogFile.getSelection(); 1533 if(fileSelect !=null){ 1534 fileSelectInfo.dstWidgd.setText(fileSelect); 1535 //fileSelectInfo.dstWidgd.setValue(cmdSet, 0, fileSelect); 1536 GralWidget_ifc.ActionChange action = fileSelectInfo.dstWidgd.getActionChange(GralWidget_ifc.ActionChangeWhen.onEnter); 1537 if(action !=null){ 1538 Object[] args = action.args(); 1539 if(args == null){ action.action().exec(KeyCode.menuEntered, fileSelectInfo.dstWidgd, fileSelect); } 1540 else { action.action().exec(KeyCode.menuEntered, fileSelectInfo.dstWidgd, args, fileSelect); } 1541 } 1542 } 1543 } 1544 } 1545 return true; 1546 }; 1547 1548 }; 1549 1550 1551 1552 /**Action to edit the properties of one widget in the graphic. */ 1553 public GralUserAction actionDesignEditField = new GralUserAction("actionDesignEditField") 1554 { 1555 @Override public boolean userActionGui(int key, GralWidget infos, Object... params) 1556 { 1557 GralWidget widgd = getWidgetInFocus(); 1558 if(widgd !=null){ 1559 designer.editFieldProperties(widgd, null); 1560 } 1561 return true; 1562 } 1563 1564 @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params) 1565 { 1566 GralWidget widgd = getWidgetInFocus(); 1567 if(widgd !=null){ 1568 designer.editFieldProperties(widgd, null); 1569 } 1570 return true; 1571 } 1572 }; 1573 1574 1575 1576 1577 /**Action to edit the properties of one widget in the graphic. */ 1578 public GralUserAction actionReadPanelCfg = new GralUserAction("actionReadPanelCfg") 1579 { @Override public boolean userActionGui(String sIntension, GralWidget infos, Object... params) 1580 { 1581 //GralPanelContent currPanel = 1582 GralWidget widgd = getWidgetInFocus(); 1583 if(widgd !=null){ 1584 GralPanelContent panel = widgd.pos().panel; 1585 String namePanel = panel.name; 1586 cfgBuilder.buildGui(log, 0); 1587 //designer.editFieldProperties(widgd, null); 1588 } 1589 return true; 1590 } 1591 }; 1592 1593 1594 1595 1596 1597 1598 /**It will be called only at the GUI-implementation level. TODO protected and delegation. 1599 * @param widgd 1600 * @param xy 1601 */ 1602 public void pressedLeftMouseDownForDesign(GralWidget widgd, GralRectangle xy) 1603 { designer.pressedLeftMouseDownForDesign(widgd, xy); 1604 } 1605 1606 1607 /**It will be called only at the GUI-implementation level. TODO protected and delegation. 1608 * @param widgd 1609 * @param xy 1610 */ 1611 public void releaseLeftMouseForDesign(GralWidget widgd, GralRectangle xy, boolean bCopy) 1612 { designer.releaseLeftMouseForDesign(widgd, xy, bCopy); 1613 } 1614 1615 public void markWidgetForDesign(GralWidget widgg){ 1616 designer.markWidgetForDesign(widgg); 1617 } 1618 1619 /**It will be called only at the GUI-implementation level. TODO protected and delegation. 1620 * @param widgd 1621 * @param xy 1622 */ 1623 public void XXXpressedRightMouseDownForDesign(GralWidget widgd, GralRectangle xy) 1624 { designer.editFieldProperties(widgd, xy); 1625 } 1626 1627 1628 1629 public void initCfgDesigner(){ 1630 designer.setToPanel(); 1631 } 1632 1633 @Override public GralInfoBox createTextInfoBox(String name, String title) 1634 { 1635 return GralInfoBox.createTextInfoBox(this, name, title); 1636 } 1637 1638 1639 @Override public GralInfoBox createHtmlInfoBox(String posString, String name, String title, boolean onTop) 1640 { 1641 return GralInfoBox.createHtmlInfoBox(posString, name, title, onTop); 1642 } 1643 1644 1645 /**Adds a text to the current panel at given position with standard colors, left origin. 1646 * The size of text is calculated using the height of positioning values. 1647 * see also {@link #addText(String, int, GralColor, GralColor)}, 1648 * {@link #addTextField(String, boolean, String, String)} 1649 * @param text 1650 */ 1651 @Override public GralWidget addText(String text) 1652 { //return addText(text, 0, GralColor.getColor("bk"), GralColor.getColor("wh")); 1653 return addText(text, 0, GralColor.getColor("bk"), propertiesGui.colorBackground_); 1654 } 1655 1656 1657 1658 1659 1660 @Override public void repaint() 1661 { 1662 assert(false); 1663 //gralDevice.redraw(); 1664 } 1665 1666 1667 1668 @Override public void repaintCurrentPanel() 1669 { 1670 pos().pos.panel.repaint(); 1671 } 1672 1673 1674 1675 1676 1677 @Override public void refreshCurvesFromVariable(VariableContainer_ifc container){ 1678 for(GralCurveView_ifc curve : curveContainer){ 1679 if(curve.isActiv()){ 1680 curve.refreshFromVariable(container); 1681 } 1682 } 1683 } 1684 1685 @Override public boolean remove(GralWidget widget) 1686 { widget.remove(); //remove instance by Garbage collector. 1687 return true; 1688 1689 } 1690 1691 1692 1693 @Override public void writeLog(int msgId, Exception exc) 1694 { 1695 String sMsg = exc.toString(); 1696 StackTraceElement[] stackTrace = exc.getStackTrace(); 1697 String sWhere = stackTrace[0].getFileName() + ":" + stackTrace[0].getLineNumber(); 1698 log.sendMsg(msgId, sMsg + " @" + sWhere); 1699 } 1700 1701 1702 1703 public final GralUserAction actionHelp = new GralUserAction("actionHelp") 1704 { 1705 @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params) 1706 { infoHelp.activate(); 1707 infoHelp.setFocus(); //setWindowVisible(true); 1708 return true; 1709 } }; 1710 1711 1712 1713 1714 1715 /**This standard Gral focus listener is the base class for the common implementation layer focus listener. 1716 * The both methods {@link #focusGainedGral(GralWidget)} and {@link #focusLostGral(GralWidget)} will be invoked 1717 * with that GralWidget, which is referred by the implementation layer widgets data. 1718 * <br><br> 1719 * The GralMng implementation classes should offer a focus listener for common usage, see 1720 * {@link org.vishia.gral.swt.SwtMng.SwtMngFocusListener} and its instance {@link org.vishia.gral.swt.SwtMng.focusListener}. 1721 * That reference and class is protected and therewith package visible because only swt implementations needs it. 1722 * An implementation widget class can use this instance of SwtMng.focusListener immediately for standard behavior. 1723 * The standard behavior is realized in this class, see {@link GralMngFocusListener#focusGainedGral(GralWidget)}. 1724 * <br><br> 1725 * For enhanced functionality of a focus listener the implementation layer SwtFocusListener class can be enhanced. 1726 * That is realized for example in {@link org.vishia.gral.swt.SwtTextFieldWrapper}. That's focus listener should 1727 * update the text in the widget with the gral text store {@link GralWidget.DynamicData#displayedText} 1728 * on focus gained, and overtake a changed content on focus lost. Adequate it is on all edit-able widgets. 1729 * The SwtTextFieldWrapper.TextFieldFocusListener.focusGained(...) and focusLost(...) methods executes the special 1730 * functionality. After them 'super.focusGained/Lost(ev);' is in called to execute the standard behavior. 1731 */ 1732 public class GralMngFocusListener 1733 { 1734 1735 /**Standard action on focus lost: 1736 * @param widgg 1737 */ 1738 public void focusLostGral(GralWidget widgg){ 1739 GralWidget.ImplAccess.setFocused(widgg, false); //denotes that the GralWidget has lost the focus 1740 widgg.repaint(); //maybe changed outfit on focus lost. 1741 if(widgg.cfg.actionFocused !=null){ widgg.cfg.actionFocused.exec(KeyCode.focusLost, widgg); } 1742 //CharSequence text = Assert.stackInfo("", 1, 5); 1743 //System.out.println("GralMng - widget focus lost;" + widgg.name + text); 1744 } 1745 1746 /**Standard action on focus gained: 1747 * <ul> 1748 * <li>Sets the html help into the {@link GralMng#setApplicationAdapter(GralMngApplAdapter_ifc)} if given. 1749 * <li> invokes the {@link GralWidget#setActionFocused(GralUserAction)} if given. 1750 * <li>invokes {@link GralMng#notifyFocus(GralWidget)} to detect the {@link GralMng#getWidgetInFocus()}. 1751 * </ul> 1752 * @param widgg 1753 */ 1754 public void focusGainedGral(GralWidget widgg){ 1755 GralMng.this.notifyFocus(widgg); 1756 GralWidget.ImplAccess.setFocused(widgg, true); //denotes that the GralWidget has gained the focus 1757 widgg.repaint(); //maybe changed outfit on focus gained. 1758 String htmlHelp = widgg.getHtmlHelp(); 1759 if(htmlHelp !=null && applAdapter !=null){ 1760 applAdapter.setHelpUrl(htmlHelp); 1761 } 1762 if(widgg.cfg.actionFocused !=null){ widgg.cfg.actionFocused.exec(KeyCode.focusGained, widgg); } 1763 } 1764 } 1765 1766 1767 /**This instance can be used if any other focus listener is necessary for any implementation widget. 1768 * The standard behavior for GralWidget is supported using this aggregate. 1769 * In Opposite a full ready to use focus listener based on this class in the implementation layer, 1770 * see {@link org.vishia.gral.swt.SwtMng.SwtMngFocusListener}. 1771 */ 1772 public GralMngFocusListener gralFocusListener = new GralMngFocusListener(); 1773 1774 /**This inner class is public only because the implementation uses it. It is not public for applications. 1775 * 1776 * 1777 */ 1778 public class InternalPublic{ 1779 public GralKeyListener gralKeyListener = new GralKeyListener(GralMng.this); 1780 } 1781 1782 /**Implementation specific fields. 1783 * 1784 */ 1785 public final InternalPublic _impl = new InternalPublic(); 1786 1787 1788 /**This class is used only for the implementation level of the graphic. It is not intent to use 1789 * by any application. It is public because the implementation level should accesses it. 1790 * It is the super class for several Graphic-Adapters (AWT/Swing, SWT etc.). 1791 * 1792 * 1793 */ 1794 public static abstract class ImplAccess { 1795 public GralMng mng; 1796 1797 1798 public ImplAccess(GralMng mng, GralGridProperties props){ 1799 this.mng = mng; 1800 mng.setProperties(props); 1801 mng.impl = this; 1802 } 1803 1804 protected GralPos pos(){ return mng.pos().pos; } 1805 1806 protected String sCurrPanel(){ return mng.sCurrPanel; } 1807 1808 protected void listVisiblePanels_add(GralTabbedPanel panel){ mng.listVisiblePanels.add(panel); } 1809 1810 public abstract Object getCurrentPanel(); 1811 1812 protected GralWidget indexNameWidgets(String name){ return mng.indexNameWidgets.get(name); } 1813 1814 protected GralUserAction userMainKeyAction(){ return mng.userMainKeyAction; } 1815 1816 1817 public abstract void createImplWidget_Gthread(GralWidget widgg); 1818 /**Creates the context menu for the given widget for right-mouse pressing. 1819 * This method is invoked only in {@link GralWidget#getContextMenu()} whereby an existing 1820 * context menu is stored in the {@link GralWidget#contextMenu} association. 1821 * The widget have to be set to panel already, an implementation widget have to be existing. 1822 * It means {@link GralWidget#getWidgetImplementation()} should be return that instance 1823 * where the menu is to be added. 1824 * This method is package protected because it should only be called internally. 1825 * @param widg The widget 1826 */ 1827 protected abstract GralMenu createContextMenu(GralWidget widgg); 1828 1829 1830 /**Creates a box inside the current panel to hold some widgets. 1831 * 1832 * @return 1833 * @since 2010-05-01 1834 */ 1835 protected abstract GralPanelContent createCompositeBox(String name); 1836 1837 /**Creates an independent grid panel which is managed by this. 1838 * The panel can be associated to any graphic frame. 1839 * @param namePanel 1840 * @param backGround 1841 * @param xG 1842 * @param yG 1843 * @param xS 1844 * @param yS 1845 * @return 1846 */ 1847 protected abstract GralPanelContent createGridPanel(String namePanel, GralColor backGround, int xG, int yG, int xS, int yS); 1848 1849 1850 public abstract boolean remove(GralPanelContent compositeBox); 1851 1852 /**Creates the menu bar for the given window. 1853 * This method is invoked only in {@link GralWindow#getMenuBar()} whereby an existing 1854 * menu bar is stored in the {@link GralWindow#menuBarGral} association. 1855 * @param windg The window 1856 */ 1857 protected abstract GralMenu createMenuBar(GralWindow windg); 1858 1859 1860 @Deprecated public abstract GralWindow createWindow(String name, String title, int windProps); 1861 1862 1863 protected abstract void createSubWindow(GralWindow windowGral); 1864 1865 public abstract GralTabbedPanel addTabbedPanel(String namePanel, GralPanelActivated_ifc user, int property); 1866 1867 @Deprecated public abstract GralWidget addText(String sText, char size, int color); 1868 1869 1870 public abstract GralHtmlBox addHtmlBox(String name); 1871 1872 public abstract Object addImage(String sName, InputStream imageStream, int height, int width, String sCmd); 1873 1874 public abstract GralWidget addSlider( 1875 String sName 1876 , GralUserAction action 1877 , String sShowMethod 1878 , String sDataPath 1879 ); 1880 1881 1882 public abstract GralCurveView addCurveViewY(String sName, int nrofXvalues, GralCurveView.CommonCurve common); 1883 1884 1885 public abstract GralWidget addFocusAction(String sName, GralUserAction action, String sCmdEnter, String sCmdRelease); 1886 1887 public abstract void addFocusAction(GralWidget widgetInfo, GralUserAction action, String sCmdEnter, String sCmdRelease); 1888 1889 1890 @Deprecated public abstract GralTable addTable(String sName, int height, int[] columnWidths); 1891 1892 public abstract GralFileDialog_ifc createFileDialog(); 1893 1894 protected abstract GralMenu XXXaddPopupMenu(String sName); 1895 1896 1897 /**Calculates the bounds of a widget with a given pos independent of this {@link #pos}. 1898 * This method is a part of the implementing GralMng because the GralPos is not implemented for 1899 * any underlying graphic system and the {@link #propertiesGuiSwt} are used. 1900 * This method is not intent to use from an application, only for implementing methods of Gral. 1901 * Therefore it isn't a member of the {@link GralWindowMng_ifc} and {@link GralMngBuild_ifc} 1902 * It is possible to tune the bounds after calculation, for example to enhance the width if a text 1903 * is larger then the intended position. 1904 * @param pos The position. 1905 * @param widthwidgetNat The natural size of the component. 1906 * @param heigthWidgetNat The natural size of the component. 1907 * @return A rectangle with position and size. 1908 */ 1909 public abstract GralRectangle calcWidgetPosAndSize(GralPos pos, int widthwidgetNat, int heigthWidgetNat); 1910 1911 @Deprecated public abstract String getValueFromWidget(GralWidget widgd); 1912 1913 /**Gets the color of the graphic implementation (swt.Color, swing.TODO) 1914 * Either the implementation color instance is stored already in the GralColor, 1915 * or it will be created, stored in GralColor and returned here. 1916 * @param color The Color. 1917 * @return Instance of the implementation color. 1918 */ 1919 public abstract Object getColorImpl(GralColor color); 1920 1921 /**Forces the redrawing for all set samples. It should be called after { @link #setSampleCurveViewY(String, float[])}. 1922 * @param sName The name of the widget. 1923 */ 1924 protected abstract void redrawWidget(String sName); 1925 1926 1927 1928 /**Forces the resizing of the given widged. 1929 * @param widgd the widget 1930 */ 1931 protected abstract void resizeWidget(GralWidget widgd, int xSizeParent, int ySizeParent); 1932 1933 1934 /**Adds a sampling value set. 1935 * @param sName The registered name 1936 * @param values The values. 1937 */ 1938 protected abstract void setSampleCurveViewY(String sName, float[] values); 1939 1940 /**Shows the context menu of any widget independent of the internal right-mouse invocation. 1941 * @param widg The widget. 1942 * @return true if the widget have a context menu. 1943 */ 1944 protected abstract boolean showContextMenuGthread(GralWidget widg); 1945 1946 1947 /**Sets a given and registered window visible at the given position and size or set it invisible. 1948 * <br> 1949 * A window can be created by invoking {@link org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(String, boolean)} 1950 * in the build phase of the gui. It can be hidden because it is not necessary to show and operate with them. 1951 * In a adequate phase of operate it can be shown and focused. 1952 * <br> 1953 * The position is given relative to that panel, 1954 * which is stored in {@link GralPos#panel}. To get a position instance, 1955 * you can set a position invoking 1956 * <ul> 1957 * <li>{@link org.vishia.gral.ifc.GralMngBuild_ifc#selectPanel(String)} 1958 * <li>{@link org.vishia.gral.ifc.GralMngBuild_ifc#setPosition(float, float, float, float, int, char)} 1959 * <li>GralGridPos pos = {@link org.vishia.gral.ifc.GralMngBuild_ifc#getPositionInPanel()}. 1960 * </ul> 1961 * That can be done in the build phase of the graphic. The position can be stored. It is possible to adjust 1962 * the position relative to the unchanged panel by changing the values of {@link GralPos#x} etc. 1963 * It is possible too to change the Panel which relates to the position. Then the grid managing instance 1964 * have to be known via the {@link org.vishia.gral.ifc.GralMngBuild_ifc} to select a panel. 1965 * The panels may be moved or resized. With the knowledge of the relative position of the window in respect to a panel 1966 * of the parent window, the window can be placed onto a proper position of the whole display. 1967 * 1968 * @param window the instance of the window wrapper. 1969 * @param atPos If null then hide the window. If not null then show the window. 1970 * The position and size of the window is given related to any panel of any other window. 1971 * 1972 * @return true if it is visible. 1973 * @deprecated 1974 */ 1975 @Deprecated 1976 protected abstract boolean XXXsetWindowsVisible(GralWindow_ifc window, GralPos atPos); 1977 1978 } 1979 1980 1981 1982 1983 void stop(){} 1984 1985 1986 protected GralMenu createContextMenu(GralWidget widg){ return impl.createContextMenu(widg); } 1987 1988 protected GralMenu createMenuBar(GralWindow windg){ return impl.createMenuBar(windg); } 1989 1990 1991 @Override public GralTabbedPanel addTabbedPanel(String namePanel, GralPanelActivated_ifc user, 1992 int properties) 1993 { 1994 return impl.addTabbedPanel(namePanel, user, properties); 1995 } 1996 1997 @Override public GralWidget addSlider(String sName, GralUserAction action, String sShowMethod, 1998 String sDataPath) 1999 { 2000 // TODO Auto-generated method stub 2001 return impl.addSlider(sName, action, sShowMethod, sDataPath); 2002 } 2003 2004 @Override @Deprecated public GralTable addTable(String sName, int height, int[] columnWidths) 2005 { 2006 // TODO Auto-generated method stub 2007 return impl.addTable(sName, height, columnWidths); 2008 } 2009 2010 @Override @Deprecated public GralWidget addText(String sText, char size, int color) 2011 { 2012 // TODO Auto-generated method stub 2013 return impl.addText(sText, size, color); 2014 } 2015 2016 @Override public Object addImage(String sName, InputStream imageStream, int height, int width, String sCmd) 2017 { 2018 // TODO Auto-generated method stub 2019 return impl.addImage(sName, imageStream, height, width, sCmd); 2020 } 2021 2022 @Override public GralHtmlBox addHtmlBox(String name) 2023 { 2024 // TODO Auto-generated method stub 2025 return impl.addHtmlBox(name); 2026 } 2027 2028 @Override public GralCurveView addCurveViewY(String sName, int nrofXvalues, CommonCurve common) 2029 { 2030 // TODO Auto-generated method stub 2031 return impl.addCurveViewY(sName, nrofXvalues, common); 2032 } 2033 2034 @Override public GralWidget addFocusAction(String sName, GralUserAction action, String sCmdEnter, 2035 String sCmdRelease) 2036 { 2037 // TODO Auto-generated method stub 2038 return addFocusAction(sName, action, sCmdEnter, sCmdRelease); 2039 } 2040 2041 @Override public void addFocusAction(GralWidget widgetInfo, GralUserAction action, String sCmdEnter, 2042 String sCmdRelease) 2043 { 2044 // TODO Auto-generated method stub 2045 impl.addFocusAction(widgetInfo, action, sCmdEnter, sCmdRelease); 2046 } 2047 2048 @Override public GralPanelContent createCompositeBox(String name) 2049 { 2050 // TODO Auto-generated method stub 2051 return impl.createCompositeBox(name); 2052 } 2053 2054 @Override public GralPanelContent createGridPanel(String namePanel, GralColor backGround, int xG, int yG, 2055 int xS, int yS) 2056 { 2057 // TODO Auto-generated method stub 2058 return impl.createGridPanel(namePanel, backGround, xG, yG, xS, yS); 2059 } 2060 2061 @Override public boolean remove(GralPanelContent compositeBox) 2062 { 2063 // TODO Auto-generated method stub 2064 return impl.remove(compositeBox); 2065 } 2066 2067 2068 /**Must only invoke from the Main window close listener. */ 2069 public static void closeGral() { 2070 singleton.gralDevice.bExit = true; 2071 } 2072 2073 2074 2075 /* (non-Javadoc) 2076 * @see org.vishia.gral.ifc.GralMngBuild_ifc#createWindow(java.lang.String, java.lang.String, int) 2077 * @deprecated use {@link GralWindow#GralWindow(String, String, String, int)} and then {@link GralWidget#createImplWidget_Gthread()} 2078 * with this window. 2079 */ 2080 @Override @Deprecated public GralWindow createWindow(String name, String title, int windProps) 2081 { GralPos pos = pos().pos; //without clone. 2082 String sPos = pos.posString(); 2083 GralWindow windowGral = new GralWindow(sPos, name, title, windProps); 2084 impl.createSubWindow(windowGral); 2085 return windowGral; 2086 } 2087 2088 @Override public GralFileDialog_ifc createFileDialog() 2089 { 2090 // TODO Auto-generated method stub 2091 return impl.createFileDialog(); 2092 } 2093 2094 @Override public void redrawWidget(String sName) 2095 { 2096 // TODO Auto-generated method stub 2097 impl.redrawWidget(sName); 2098 } 2099 2100 @Override public void resizeWidget(GralWidget widgd, int xSizeParent, int ySizeParent) 2101 { 2102 // TODO Auto-generated method stub 2103 impl.resizeWidget(widgd, xSizeParent, ySizeParent); 2104 } 2105 2106 @Override public boolean XXXsetWindowsVisible(GralWindow_ifc window, GralPos atPos) 2107 { 2108 // TODO Auto-generated method stub 2109 return false; 2110 } 2111 2112 @Override public void setSampleCurveViewY(String sName, float[] values) 2113 { 2114 impl.setSampleCurveViewY(sName, values); 2115 } 2116 2117 2118 2119}