001package org.vishia.gral.area9; 002 003import java.io.File; 004import java.io.FileWriter; 005import java.io.IOException; 006import java.io.Writer; 007import java.util.List; 008 009import org.vishia.communication.InterProcessCommFactorySocket; 010import org.vishia.gral.base.GralGraphicTimeOrder; 011import org.vishia.gral.base.GralShowMethods; 012import org.vishia.gral.base.GralWidget; 013import org.vishia.gral.base.GralMng; 014import org.vishia.gral.base.GralPanelContent; 015import org.vishia.gral.base.GralTabbedPanel; 016import org.vishia.gral.cfg.GralCfgData; 017import org.vishia.gral.cfg.GralCfgDesigner; 018import org.vishia.gral.cfg.GralCfgZbnf; 019import org.vishia.gral.ifc.GralMngBuild_ifc; 020import org.vishia.gral.ifc.GralMng_ifc; 021import org.vishia.gral.ifc.GralPlugUser2Gral_ifc; 022import org.vishia.gral.ifc.GralPlugUser_ifc; 023import org.vishia.gral.ifc.GralUserAction; 024import org.vishia.gral.ifc.GralWidget_ifc; 025import org.vishia.inspectorTarget.Inspector; 026import org.vishia.mainCmd.MainCmd_ifc; 027import org.vishia.mainCmd.Report; 028import org.vishia.msgDispatch.MsgDispatchSystemOutErr; 029import org.vishia.util.KeyCode; 030 031/**This class is the basic class for configurable GUI applications with 9-Area Main window. 032 * It works without any derivation, if only simple widgets are necessary. 033 * If additional capabilities are need, this class can uses as the super class. 034 * Some protected methods support overriding, especially: 035 * <ul> 036 * <li>{@link #initMain()}: initializes the GUI 037 * <li>{@link #stepMain()}: Will be invoked in the main loop. 038 * <li>{@link #finishMain()}: invoked on exit. 039 * </ul> 040 * Hint: call super.stepMain() etc. in an overridden method if necessary. 041 * <br><br> 042 * The class contains a {@link #main(String[])}. It is a complete ready to run application. 043 * The content of the GUI can be controlled by a script. The command line arguments are parsed in 044 * {@link GralArea9MainCmd}, the universal or basic MainCmd for gral-GUI applications. 045 * <br><br> 046 * The configuration is done with {@link GralCfgZbnf} in the {@link #initMain()} routine. 047 * 048 * <br><br> 049 * <br><br> 050 * <br><br> 051 * 052 * <br> 053 * Registered user action can be used by script. 054 * <ul> 055 * <li>"cmdInvoke": The given parameter 'cmd' of the widget will be executed as command line. 056 * It is usefull to start commands from this GUI for example with a button. 057 * </ul> 058 * A user plugin class can be plugged which can register some more user actions etc. 059 * @author Hartmut Schorrig. 060 * 061 */ 062public class GuiCfg 063{ 064 065 /**The version, history and license. 066 * <ul> 067 * <li>2013-12-02 Hartmut new Parameter for {@link #GuiCfg(GuiCallingArgs, GralArea9MainCmd, GralPlugUser_ifc, GralPlugUser2Gral_ifc, List)}: 068 * cfgConditions. 069 * <li>2012-09-17 Hartmut new: {@link #showMethods} 070 * <li>2011-10-12 Hartmut chg: ctor needs a {@link GralPlugUser_ifc} which may be null: A plugin may be instantiated 071 * by reflection with String given class name. It may be possible to give it as parameter too. 072 * <li>2011-10-20 Hartmut chg: ctor needs a {@link GralPlugUser2Gral_ifc} which may be null. 073 * Idea: a derived class should support it. Other Idea: either both via reflection or both maybe direct. 074 * <li>2011-10-11 Hartmut new: Switches MainCmd-output to OutputBox. 075 * <li>2011-09-30 Hartmut new: menu 'Design/...' to edit fields and work with the {@link GralCfgDesigner}. 076 * <li>2011-09-18 Hartmut new: The main tab panel has the name 'mainTab' and it is registered in the {@link #_gralMng} now. 077 * Generally an application may have more as one tabbed panels. 078 * <li>2011-09-10 Hartmut del: Remove dialogZbnfConfigurator, it was not used. It is the old solution. 079 * <li>2011-09-08 Hartmut del: Remove the message panel. It was a special solution. 080 * <li>2011-08-08 Hartmut new: {@link #initMain()} as override-able method instead direct call of initializing. 081 * <li>2011-08-07 Hartmut chg: Now {@link GuiCallingArgs} as primary class, not an inner class here. 082 * <li>2011-08-07 Hartmut chg: Now {@link GralArea9MainCmd} as extra primary class. 083 * <li>2011-08-04 Hartmut chg: rename and move from org/vishia/guiCmdMenu/CmdMenu.java to org/vishia/gral/area9/GuiCfg.java. 084 * It is a universal GUI which is configurable in content. Also it is a base class for some configurable GUI applications. 085 * <li>2011-08-04 Hartmut chg: Use {@link GralPanelContent} instead the special InspcGuiPanelContent. 086 * <li>2011-08-04 Hartmut new: {@link #userInit()} as override-able method instead direct call of user.init(). 087 * Advantage: User can do anything in the derived class. 088 * <li>2011-08-04 Hartmut new: Use first key of argument --size: to determine the size. TODO parseArgs 089 * <li>2011-07-31 Hartmut new: First usage as super class. 090 * <li>2010-01-01 Hartmut new: The base of this class was created with some applications. 091 * </ul> 092 * 093 * <b>Copyright/Copyleft</b>: 094 * For this source the LGPL Lesser General Public License, 095 * published by the Free Software Foundation is valid. 096 * It means: 097 * <ol> 098 * <li> You can use this source without any restriction for any desired purpose. 099 * <li> You can redistribute copies of this source to everybody. 100 * <li> Every user of this source, also the user of redistribute copies 101 * with or without payment, must accept this license for further using. 102 * <li> But the LPGL is not appropriate for a whole software product, 103 * if this source is only a part of them. It means, the user 104 * must publish this part of source, 105 * but don't need to publish the whole source of the own product. 106 * <li> You can study and modify (improve) this source 107 * for own using or for redistribution, but you have to license the 108 * modified sources likewise under this LGPL Lesser General Public License. 109 * You mustn't delete this Copyright/Copyleft inscription in this source file. 110 * </ol> 111 * If you are intent to use this sources without publishing its usage, you can get 112 * a second license subscribing a special contract with the author. 113 * 114 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 115 * 116 * 117 */ 118 public final static int version = 0x20120303; 119 120 /**Composition of a Inspector-Target instance. This is only to visit this application for debugging. 121 * Not necessary for functionality. */ 122 private final Inspector inspector; 123 124 /**To Output log informations. The ouput will be done in the output area of the graphic. */ 125 public final Report console; 126 127 //protected final GralPanelContent panelContent; 128 129 130 131 132 133 134 135 136/**The calling arguments of this class. It may be filled by command line invocation 137 * but maybe given in a direct way too while calling this class in a Java environment. */ 138final GuiCallingArgs cargs; 139 140/**The configuration data for graphical appearance. */ 141public final GralCfgData guiCfgData; 142 143 144 145 146/**This instance helps to create the Dialog Widget as part of the whole window. It is used only in the constructor. 147 * Therewith it may be defined stack-locally. But it is better to show and explain if it is access-able at class level. */ 148//GuiDialogZbnfControlled dialogZbnfConfigurator; 149 150 151 152/**Some actions may be processed by a user implementation. */ 153protected GralPlugUser_ifc user; 154 155protected final GralPlugUser2Gral_ifc plugUser2Gui; 156 157 158 159 160 161 162public final GralArea9_ifc gui; 163 164public final GralArea9Window guiW; 165 166public final MainCmd_ifc mainCmd; 167 168/**Especially for debug access to the singleton instance, start with _ to present on top of variables. */ 169public GralMng _gralMng; 170 171 172/**Panel-Management-interface for the panels. */ 173public GralMngBuild_ifc panelBuildIfc; 174 175public GralMng_ifc guiAccess; 176 177protected GralTabbedPanel mainTabPanel; 178 179 180private static GuiCfg singleton; 181 182/**ctor for the main class of the application. 183 * The main class can be created in some other kinds as done in static main too. 184 * But it needs the {@link MainCmdWin}. 185 * <br><br> 186 * The ctor checks whether a gUI-configuration file is given. If not then the default configuration is used. 187 * It is especially for the Sample. 188 * <br><br> 189 * The the GUI will be completed with the content of the GUI-configuration file. 190 * 191 * @param cargs The given calling arguments. 192 * @param cmdGui The GUI-organization. 193 * @param plugUser2Gui maybe possible a instances which plugs the user instance to the GUI. 194 * This instance may be defined in the context which calls this constructor. 195 * Note: A user instance may be instantiated with the cmd line calling argument "-plugin=JAVACLASSPATH" 196 */ 197public GuiCfg(GuiCallingArgs cargs, GralArea9MainCmd cmdGui 198 , GralPlugUser_ifc plugUser, GralPlugUser2Gral_ifc plugUser2Gui 199 , List<String> cfgConditions) 200{ if(singleton !=null) throw new IllegalArgumentException("class GuiCfg can instantiate only one time, a singleton!"); 201 this.mainCmd = cmdGui; 202 this.gui = cmdGui.gui; 203 guiW = (GralArea9Window)gui; 204 this.cargs = cargs; 205 this.plugUser2Gui = plugUser2Gui; 206 this.console = gui.getMainCmd(); 207 this.guiCfgData = new GralCfgData(cfgConditions); 208 209 if(plugUser !=null){ 210 this.user = plugUser; 211 } else if(cargs.sPluginClass !=null){ 212 try{ 213 Class<?> pluginClass = Class.forName(cargs.sPluginClass); 214 Object oUser = pluginClass.newInstance(); 215 if(oUser instanceof GralPlugUser_ifc){ 216 user = (GralPlugUser_ifc) oUser; 217 } else { 218 console.writeError("user-plugin - fault type: " + cargs.sPluginClass 219 + "; it should be type of GuiPlugUser_ifc"); 220 } 221 } catch (Exception exc){ 222 user = null; 223 console.writeError("user-plugin - cannot instantiate: " + cargs.sPluginClass + "; " 224 + exc.getMessage()); 225 } 226 } 227 228 if(cargs.sInspectorOwnPort !=null){ 229 inspector = new Inspector(cargs.sInspectorOwnPort); 230 inspector.start(this); 231 } else { 232 inspector = null; //don't use. 233 } 234 235 _gralMng = cmdGui.gralMng; //cargs.graphicFactory.createPanelMng(null, 120,80, propertiesGui, null, log); 236 panelBuildIfc = _gralMng; 237 guiAccess = _gralMng; 238 userInit(); 239 //panelContent = new PanelContent(user); 240 241 if(user !=null){ 242 user.registerMethods(panelBuildIfc); 243 } 244 245 //Register any user action. This should be done before the GUI-configuration is read. 246 panelBuildIfc.registerUserAction("cmdInvoke", cmdInvoke); 247 singleton = this; 248} 249 250 251public static GuiCfg get(){ return singleton; } 252 253public GralPlugUser_ifc getPluggedUser(){ return user; } 254 255 256 257/**Will be overridden... TODO InspcGui 258 * 259 */ 260protected void userInit() 261{ 262 if(user !=null){ 263 user.init(plugUser2Gui, _gralMng, guiCfgData.dataReplace, this.cargs, console.getLogMessageOutputConsole()); 264 } 265 266 267} 268 269 270 271/**Code snippet for initializing the GUI area (panel). This snippet will be executed 272 * in the GUI-Thread if the GUI is created. 273 */ 274GralGraphicTimeOrder initGraphic = new GralGraphicTimeOrder("GuiCfg.initGraphic") 275{ 276 @Override public void executeOrder() 277 { 278 _gralMng.selectPanel("primaryWindow"); 279 _gralMng.setPosition(10, 16,5,20,0,'.'); 280 initGuiAreas("A1C1"); 281 //gralMng.gralDevice.removeDispatchListener(this); 282 //countExecution(); 283 } 284}; 285 286 287/**Code snippet to run the ZBNF-configurator (text controlled GUI) 288 * 289 */ 290GralGraphicTimeOrder configGuiWithZbnf = new GralGraphicTimeOrder("GuiCfg.configGuiWithZbnf") 291{ 292 293 @Override public void executeOrder(){ 294 panelBuildIfc.buildCfg(guiCfgData, cargs.fileGuiCfg); 295 _gralMng.initCfgDesigner(); 296 297 //gralMng.gralDevice.removeDispatchListener(this); 298 299 //countExecution(); 300 301 } 302//// 303}; 304 305 306 307/**Initializes the areas for the panels and configure the panels. 308 * This routine can be overridden if other areas are need. 309 */ 310protected void initGuiAreas(String sMainArea) 311{ 312 gui.setFrameAreaBorders(20, 80, 60, 85); 313 gui.setStandardMenusGThread(new File("."), actionFile); 314 initMenuGralDesigner(); 315 _gralMng.selectPanel("primaryWindow"); 316 mainTabPanel = _gralMng.addTabbedPanel("mainTab", null, 0); 317 gui.addFrameArea(sMainArea, mainTabPanel); //dialogPanel); 318 Appendable out = gui.getOutputBox(); 319 mainCmd.setOutputChannels(out, out); 320 321} 322 323 324protected void initMenuGralDesigner() 325{ 326 gui.addMenuBarArea9ItemGThread("GralDesignEnable", "&Design/e&Nable", _gralMng.actionDesignEditField); 327 gui.addMenuBarArea9ItemGThread("GralDesignEditField", "&Design/Edit &field", _gralMng.actionDesignEditField); 328 gui.addMenuBarArea9ItemGThread("GralDesignUpdatePanel", "&Design/update &Panel from cfg-file", _gralMng.actionReadPanelCfg); 329 330} 331 332 333 334protected void initMain() 335{ 336 //create the basic appearance of the GUI. The execution sets dlgAccess: 337 System.out.println("GuiCfg.initMain() - addDispatchOrder initGraphic, wait for execution;"); 338 _gralMng.gralDevice.addDispatchOrder(initGraphic); 339 340 if(!initGraphic.awaitExecution(1, 0)){ 341 System.out.println("GuiCfg.initMain() - initGraphic does not respond;"); 342 throw new RuntimeException("unexpected fail of execution initGuiDialog"); 343 } 344 System.out.println("GuiCfg.initMain() - await initGraphic ok;"); 345 346 347 /**Creates the dialog elements while reading a config-file. */ 348 // 349 //dialogVellMng.re 350 boolean bConfigDone = false; 351 if(cargs.fileGuiCfg != null){ 352 //configGuiWithZbnf.ctDone(0); //counter for done initialized. 353 if(cargs.fileGuiCfg.exists()) 354 { 355 File fileSyntax = new File(cargs.sPathZbnf + "/dialog.zbnf"); 356 GralCfgZbnf cfgZbnf = new GralCfgZbnf(console, fileSyntax); 357 System.out.println("GuiCfg - start parsing cfg file; " + cargs.fileGuiCfg.getAbsolutePath()); 358 String sError = cfgZbnf.configureWithZbnf(cargs.fileGuiCfg, guiCfgData); 359 System.out.println("GuiCfg - finish parsing cfg file; "); 360 if(sError !=null){ 361 console.writeError(sError); 362 } else { 363 //dialogZbnfConfigurator = new GuiDialogZbnfControlled((MainCmd_ifc)gui, fileSyntax); 364 //cfgBuilder = new GuiCfgBuilder(guiCfgData, panelBuildIfc, fileGui.getParentFile()); 365 //panelBuildIfc.setCfgBuilder(cfgBuilder); 366 _gralMng.gralDevice.addDispatchOrder(configGuiWithZbnf); 367 bConfigDone = configGuiWithZbnf.awaitExecution(1, 10000); 368 if(!bConfigDone){ 369 console.writeError("No configuration"); 370 } 371 } 372 } else { 373 console.writeError("Config file not found: " + cargs.fileGuiCfg.getAbsolutePath()); 374 } 375 } 376 try{ Thread.sleep(10);} catch(InterruptedException exc){} 377 //The GUI-dispatch-loop should know the change worker of the panel manager. Connect both: 378 try{ Thread.sleep(10);} catch(InterruptedException exc){} 379 //gets all prepared fields to show informations. 380 //oamShowValues.setFieldsToShow(panelBuildIfc.getShowFields()); 381 382} 383 384protected void stepMain(){} 385 386/**This routine is called on end of main-execution. This default implementation calls 387 * {@link GralPlugUser_ifc#close()}. 388 * 389 */ 390protected void finishMain(){ 391 if(user !=null){ try{ user.close(); } catch(IOException exc ){} } 392} 393 394 395public final void execute() 396{ 397 initMain(); 398 //guiAccess.insertInfo("msgOfDay", Integer.MAX_VALUE, "Test\tMsg"); 399 //msgReceiver.start(); 400 while(_gralMng.gralDevice.isRunning()) 401 { stepMain(); 402 try{ Thread.sleep(100);} 403 catch (InterruptedException e) 404 { //dialogZbnfConfigurator.terminate(); 405 } 406 } 407 408 if(inspector !=null) { 409 inspector.shutdown(); 410 } 411 finishMain(); 412} 413 414 415 416public void showInfoBox(CharSequence text) { 417 GralMng mng = GralMng.get(); 418 mng.showInfo(text); 419} 420 421public void setTextInfoBox(CharSequence text) { 422 GralMng.get().setInfo(text); 423} 424 425public void appendTextInfoBox(CharSequence text) { 426 GralMng.get().addInfo(text, false); 427} 428 429 430 431 432/**Registered as user action. 433 * 434 */ 435private final GralUserAction cmdInvoke = new GralUserAction("cmdInvoke") 436{ 437 ProcessBuilder processBuilder = new ProcessBuilder("pwd"); 438 439 StringBuilder output = new StringBuilder(); 440 StringBuilder error = new StringBuilder(); 441 442 @Override 443 public boolean exec(int cmd, GralWidget_ifc wdgi, Object... values) 444 { 445 if(KeyCode.isControlFunctionMouseUpOrMenu(cmd)){ 446 GralWidget wdg = (GralWidget)wdgi; 447 output.setLength(0); 448 error.setLength(0); 449 mainCmd.executeCmdLine(processBuilder, wdg.sCmd, null, Report.info, output, error); 450 stop(); 451 guiAccess.addText("output", output); //adds the result to any widget with name "output" 452 //gui.executeCmdLine(widgetInfos.sCmd, 0, null, null); 453 return true; 454 } else return false; 455 } 456}; 457 458 459protected GralUserAction actionFile = new GralUserAction("actionFile") 460{ @Override public boolean userActionGui(int key, GralWidget widg, Object... params) 461 { 462 if(KeyCode.isControlFunctionMouseUpOrMenu(key)){ 463 String sError = null; 464 try{ 465 Writer writer = new FileWriter(cargs.fileGuiCfg); //"save.cfg"); 466 sError = _gralMng.saveCfg(writer); 467 writer.close(); 468 } catch(java.io.IOException exc){ 469 sError = "Problem open file "; 470 } 471 if(sError !=null){ 472 console.writeError(sError); 473 } 474 } 475 return true; 476 } 477}; 478 479 480 481/**The command-line-invocation (primary command-line-call). 482 * @param args Some calling arguments are taken. This is the GUI-configuration especially. 483 */ 484public static void main(String[] args){ 485 boolean bOk = true; 486 // 487 //Uses the commonly GuiCallingArgs class because here are not extra arguments. 488 GuiCallingArgs cargs = new GuiCallingArgs(); 489 490 //Redirect all outputs from System.out 491 MsgDispatchSystemOutErr.create("D:/DATA/msg/log$yyyy-MMM-dd-HH_mm$.log", 10000, 40000, 10000, 100); 492 //Initializes the GUI till a output window to show information. 493 GralArea9MainCmd cmdGui = new GralArea9MainCmd(cargs, args); //implements MainCmd, parses calling arguments 494 //Initializes the graphic window and parse the parameter of args (command line parameter). 495 //Parameter errors will be output in the graphic window in its given output area. 496 bOk = cmdGui.parseArgumentsAndInitGraphic("Gui-Cfg", "3A3C"); 497 498 if(bOk){ 499 //loads the named class, so it is existent as factory. 500 new InterProcessCommFactorySocket(); 501 // 502 //the third parameter may be a plugin, use it in your application if necessary. 503 GuiCfg main = new GuiCfg(cargs, cmdGui, null, null, null); 504 // 505 //starts execution. 506 main.execute(); 507 } 508 cmdGui.exit(); 509} 510 511 512 513void stop(){} //debug helper 514 515 516 517 518}