    001package org.vishia.commander;
    002
    003import java.io.Closeable;
    004import java.io.File;
    005import java.io.IOException;
    006import java.util.ArrayList;
    007import java.util.Iterator;
    008import java.util.LinkedList;
    009import java.util.List;
    010import java.util.Map;
    011import java.util.TreeMap;
    012
    013import org.vishia.cmd.CmdGetterArguments;
    014import org.vishia.cmd.JZtxtcmdScript;
    015import org.vishia.cmd.JZtxtcmdScript.JZcmdClass;
    016import org.vishia.cmd.JZtxtcmdScript.Subroutine;
    017import org.vishia.commander.target.FcmdtTarget;
    018import org.vishia.commander.target.FcmdtTarget_ifc;
    019import org.vishia.communication.InterProcessCommFactorySocket;
    020import org.vishia.fileLocalAccessor.FileAccessorLocalJava7;
    021import org.vishia.fileRemote.FileCluster;
    022import org.vishia.fileRemote.FileRemote;
    023import org.vishia.gral.area9.GuiCallingArgs;
    024import org.vishia.gral.area9.GuiCfg;
    025import org.vishia.gral.area9.GralArea9MainCmd;
    026import org.vishia.gral.base.GralMenu;
    027import org.vishia.gral.base.GralMng;
    028import org.vishia.gral.base.GralPanelContent;
    029import org.vishia.gral.base.GralWidget;
    030import org.vishia.gral.ifc.GralMngBuild_ifc;
    031import org.vishia.gral.ifc.GralUserAction;
    032import org.vishia.gral.ifc.GralWidget_ifc;
    033import org.vishia.gral.widget.GralFileSelector;
    034import org.vishia.jztxtcmd.JZtxtcmd;
    035import org.vishia.msgDispatch.MsgRedirectConsole;
    036import org.vishia.util.DataAccess;
    037import org.vishia.util.Debugutil;
    038import org.vishia.util.KeyCode;
    039
    040/**This class is the main class of the-File-commander.
    041 * @author Hartmut Schorrig
    042 *
    043 */
    044public class Fcmd extends GuiCfg
    045{
    046
    047
    048  /**Version, history and license. This String is visible in the about info.
    049   * <ul>
    050   * <li>2017-08-27 {@link FcmdFavorPathSelector#actionDeselectDirtree} now removes all FileRemote instances of children
    051   *   because a selection is not necessary furthermore. This is a 'refresh'. But the 'refresh' (F5, ctrl-R) should not change selection,
    052   *   it must not delete this children-FileRemote. Only deselection is the key action for that.
    053   * <li>2016-08-28 see {@link FcmdExecuter#sVersion}, {@link FcmdSettings#sVersion}
    054   * <li>2015-07-18 Hartmut chg: Now the output of script errors while executing the JZcmd cmd script is visible
    055   *   in the output window.
    056   * <li>2015-07-12 Hartmut new: Many fixes in the base classes for functionality. See all commit messages of the component.
    057   * <li>2014-12-26 Hartmut new: {@link #refreshFilePanel(FileRemote)} can be called in any callback thread.
    058   * <li>2011-2013 some changes, see source files.
    059   * <li>2011-10-00 Hartmut created
    060   * </ul>
    061   *
    062   * <b>Copyright/Copyleft</b>:<br>
    063   * For this source the LGPL Lesser General Public License,
    064   * published by the Free Software Foundation is valid.
    065   * It means:
    066   * <ol>
    067   * <li> You can use this source without any restriction for any desired purpose.
    068   * <li> You can redistribute copies of this source to everybody.
    069   * <li> Every user of this source, also the user of redistribute copies
    070   *    with or without payment, must accept this license for further using.
    071   * <li> But the LPGL is not appropriate for a whole software product,
    072   *    if this source is only a part of them. It means, the user
    073   *    must publish this part of source,
    074   *    but doesn't need to publish the whole source of the own product.
    075   * <li> You can study and modify (improve) this source
    076   *    for own using or for redistribution, but you have to license the
    077   *    modified sources likewise under this LGPL Lesser General Public License.
    078   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
    079   * </ol>
    080   * If you intent to use this source without publishing its usage, you can get
    081   * a second license subscribing a special contract with the author.
    082   *
    083   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
    084   */
    085  //@SuppressWarnings("hiding")
    086  public static final String version = "2018-11-02";
    087
    088
    089  static class CallingArgs extends GuiCallingArgs
    090  {
    091    File fileCfgCmds;
    092
    093    File fileCmdsForExt;
    094
    095    File fileCfgButtonCmds;
    096
    097    File fileSelectTabPaths;
    098
    099    File dirCfg;
    100
    101  }
    102
    103  /**
    104   * This action is invoked for all general key pressed actions. It tests the
    105   * key and switches to the concretely action for the pressed key. General keys
    106   * are [F1] for help, [F4] for edit etc.
    107   */
    108  GralUserAction actionTest = new GralUserAction("actionTest")
    109  {
    110    @Override public boolean userActionGui(int key, GralWidget infos, Object... params)
    111    {
    112      GralMng.get().addInfo("Test\n", true);
    113      return true;
    114    }
    115  };
    116
    117  /**
    118   * This action is invoked for all general key pressed actions. It tests the
    119   * key and switches to the concretely action for the pressed key. General keys
    120   * are [F1] for help, [F4] for edit etc.
    121   */
    122  GralUserAction actionKey = new GralUserAction("actionKey")
    123  {
    124    @Override
    125    public boolean userActionGui(String sIntension, GralWidget infos,
    126        Object... params)
    127    {
    128      Debugutil.stop();
    129      return true;
    130    }
    131  };
    132
    133  /**Key alt-F1 to select a directory/cmd list in a list of directories for the
    134   * left panel. The original Norton Commander approach is to select a drive
    135   * letter for windows. Selection of paths instead are adequate.
    136   */
    137  GralUserAction actionReadMsgConfig = new GralUserAction("actionReadMsgConfig")
    138  {
    139    @Override public boolean exec(int key, GralWidget_ifc widgi, Object... params){
    140      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){  //supress both mouse up and down reaction
    141        if(cargs.msgConfig !=null && cargs.msgConfig.exists()){
    142          msgDisp.readConfig(cargs.msgConfig);
    143        }
    144        return true;
    145      } else return false;
    146    }
    147  };
    148
    149  /**Key alt-F1 to select a directory/cmd list in a list of directories for the
    150   * left panel. The original Norton Commander approach is to select a drive
    151   * letter for windows. Selection of paths instead are adequate.
    152   */
    153  GralUserAction selectCardThemesLeft = new GralUserAction("selectCardThemesLeft")
    154  {
    155    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    156      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){  //supress both mouse up and down reaction
    157        favorPathSelector.panelLeft.cardFavorThemes.wdgdTable.setFocus();
    158        return true;
    159      } else return false;
    160    }
    161  };
    162
    163  /**Key alt-F2 to select a directory/cmd list in a list of directories for the
    164   * middle panel.
    165   */
    166  GralUserAction selectCardThemesMiddle = new GralUserAction("selectCardThemesMiddle")
    167  {
    168    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    169      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){  //supress both mouse up and down reaction
    170        favorPathSelector.panelMid.cardFavorThemes.wdgdTable.setFocus();
    171        return true;
    172      } else return false;
    173    }
    174  };
    175
    176  /**Key alt-F3 to select a directory/cmd list in a list of directories for the
    177   * right panel.
    178   */
    179  GralUserAction selectCardThemesRight = new GralUserAction("selectCardThemesRight")
    180  {
    181    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    182      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    183        favorPathSelector.panelRight.cardFavorThemes.wdgdTable.setFocus();
    184        return true;
    185      } else return false;
    186    }
    187  };
    188
    189  /**Key sh-F1 to select a directory/cmd list in a list of directories for the
    190   * right panel.
    191   */
    192  GralUserAction selectFileCardLeft = new GralUserAction("selectFileCardLeft")
    193  {
    194    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    195      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    196        favorPathSelector.panelLeft.setFocus();
    197        return true;
    198      } else return false;
    199    }
    200  };
    201
    202  /**Key sh-F2 to select a directory/cmd list in a list of directories for the
    203   * right panel.
    204   */
    205  GralUserAction selectFileCardMid = new GralUserAction("selectFileCardMid")
    206  {
    207    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    208      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    209        favorPathSelector.panelMid.setFocus();
    210        return true;
    211      } else return false;
    212    }
    213  };
    214
    215  /**Key sh-F3 to select a directory/cmd list in a list of directories for the
    216   * right panel.
    217   */
    218  GralUserAction selectFileCardRight = new GralUserAction("selectFileCardRight")
    219  {
    220    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    221      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    222        favorPathSelector.panelRight.setFocus();
    223        return true;
    224      } else return false;
    225    }
    226  };
    227
    228  /**Key sh-F3 to select a directory/cmd list in a list of directories for the
    229   * right panel.
    230   */
    231  GralUserAction selectFileCardOther = new GralUserAction("selectFileCardOther")
    232  {
    233    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    234      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){
    235        if(lastFilePanels.size() >=2){
    236          FcmdLeftMidRightPanel otherPanel = lastFilePanels.get(1);
    237          otherPanel.setFocus();
    238        }
    239        return true;
    240      } else return false;
    241    }
    242  };
    243
    244
    245  GralUserAction actionFocusPanelToLeft = new GralUserAction("FcmdLeftMidRightPanel.actionRightCard"){
    246    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    247      FcmdLeftMidRightPanel actPanel = lastFilePanels.get(0);
    248      if(actPanel.cc == 'm'){ favorPathSelector.panelLeft.setFocus(); }
    249      else if(actPanel.cc == 'r'){ favorPathSelector.panelMid.setFocus(); }
    250      return true;
    251    }
    252  };
    253
    254
    255  GralUserAction actionFocusPanelToRight = new GralUserAction("FcmdLeftMidRightPanel.actionRightCard"){
    256    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    257      FcmdLeftMidRightPanel actPanel = lastFilePanels.get(0);
    258      if(actPanel.cc == 'm'){ favorPathSelector.panelRight.setFocus(); }
    259      else if(actPanel.cc == 'l'){ favorPathSelector.panelMid.setFocus(); }
    260      return true;
    261    }
    262  };
    263
    264
    265  GralUserAction actionFocusFileCard = new GralUserAction("FcmdLeftMidRightPanel.actionFileCard"){
    266    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    267      return true;
    268    }
    269  };
    270
    271
    272  GralUserAction actionFocusThemeCard = new GralUserAction("FcmdLeftMidRightPanel.actionThemeCard"){
    273    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    274      return true;
    275    }
    276  };
    277
    278
    279
    280
    281
    282  /**Action to focus the cmd card.
    283   */
    284  GralUserAction actionFocusCmdCard = new GralUserAction("actionFocusCmdCard")
    285  {
    286    @Override public boolean userActionGui(int key, GralWidget infos, Object... params){
    287      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){  //supress both mouse up and down reaction
    288      executer.cmdSelector.wdgdTable.setFocus();
    289      return true;
    290      } else return false;
    291    }
    292  };
    293
    294
    295
    296  GralUserAction actionFocusCardInPanelToLeft = new GralUserAction("FcmdLeftMidRightPanel.actionLeftCard"){
    297    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    298      lastFilePanels.get(0).focusLeftCard();
    299      return true;
    300    }
    301  };
    302
    303
    304  GralUserAction actionFocusCardInPanelToRight = new GralUserAction("FcmdLeftMidRightPanel.actionRightCard"){
    305    @Override public boolean userActionGui(int actionCode, GralWidget widgd, Object... params){
    306      //sets focus to right
    307      lastFilePanels.get(0).focusRightCard();
    308      return true;
    309    }
    310  };
    311
    312
    313
    314
    315  void openExtEditor(File file){
    316    JZtxtcmdScript.Subroutine jzsub = buttonCmds.get("edit");
    317    if( jzsub == null ) {
    318      mainCmd.writeError("internal problem - don't find 'edit' command. ");
    319    } else {
    320      String sMsg = "GralCommandSelector - put cmd;" + jzsub.toString();
    321      System.out.println(sMsg);
    322      List<DataAccess.Variable<Object>> args = new LinkedList< DataAccess.Variable<Object>>();
    323      DataAccess.Variable<Object> var = new DataAccess.Variable<>('O', "file1", file, true);
    324      args.add(var);
    325      //executer.cmdQueue.addCmd(jzsub, args, file.getParentFile()); // to execute.
    326      executer.cmdExecuter.addCmd(jzsub, args, Fcmd.this.gui.getOutputBox(), file.getParentFile());
    327    }
    328
    329  }
    330
    331
    332
    333  /**
    334   * Key F4 for edit command. Its like Norton Commander.
    335   */
    336  GralUserAction actionEdit = new GralUserAction("actionEdit")
    337  {
    338    @Override public boolean exec(int key, GralWidget_ifc wdg, Object... params) {
    339      if(KeyCode.isControlFunctionMouseUpOrMenu(key)){  //supress both mouse up and down reaction
    340        JZtxtcmdScript.Subroutine jzsub = buttonCmds.get("edit");
    341        if (jzsub == null) {
    342          mainCmd.writeError("internal problem - don't find 'edit' command. ");
    343        } else {
    344
    345          String sMsg = "GralCommandSelector - put cmd;" + jzsub.toString();
    346          System.out.println(sMsg);
    347          List<DataAccess.Variable<Object>> args = main.getterFileArguments.getArguments(jzsub);
    348          //executer.cmdQueue.addCmd(jzsub, args, Fcmd.this.currentFileCard.currentDir());  //to execute.
    349          executer.cmdExecuter.addCmd(jzsub, args, Fcmd.this.gui.getOutputBox(), Fcmd.this.currentFileCard.currentDir());
    350        }
    351      }
    352      return true;
    353    }
    354  };
    355
    356
    357
    358  /**This callback will be invoked in the drag event while the mouse is released in the destination.
    359   */
    360  GralUserAction actionDragFileFromStatusLine = new GralUserAction("actionDragFileFromStatusLine"){
    361    @Override public boolean userActionGui(int key, GralWidget widgd, Object... params) {
    362      if(key == KeyCode.dragFiles){
    363        String path = widgd.getValue();
    364        String[][] sFiles = (String[][])params[0];  //sFiles has lenght 1
    365        sFiles[0] = new String[1];
    366        sFiles[0][0] = path;
    367        Debugutil.stop();
    368      }
    369      return true;
    370    }
    371  };
    372
    373  /**This implementation resolves the arguments for invoked commands with the capabilities of the Fcmd.
    374   * Especially the following argument strings are supported:
    375   * <ul>
    376   * <li>
    377   * </ul>
    378   * This instance is used only locally (private). It is designated as protected for documentation.
    379   */
    380  protected CmdGetterArguments getterFileArguments = new CmdGetterArguments()
    381  {
    382    @Override public List<DataAccess.Variable<Object>> getArguments(JZtxtcmdScript.Subroutine subRoutine) {
    383      FileRemote[] selFiles = getLastSelectedFiles(true, 1);  //The selected 3 files, maybe in one card too.
    384      List<DataAccess.Variable<Object>> args = new LinkedList<DataAccess.Variable<Object>>();
    385      if(subRoutine !=null) {
    386        if(subRoutine.formalArgs !=null) {
    387          for(JZtxtcmdScript.DefVariable arg :subRoutine.formalArgs){
    388            String name1 = arg.getVariableIdent();
    389            if(name1.equals("file1")){ args.add(new DataAccess.Variable<Object>('O', "file1", selFiles[0], true)); }
    390            else if(name1.equals("file2")){ args.add(new DataAccess.Variable<Object>('O', "file2", selFiles[1], true)); }
    391            else if(name1.equals("file3")){ args.add(new DataAccess.Variable<Object>('O', "file3", selFiles[2], true)); }
    392            else if(name1.equals("dir1")){ args.add(new DataAccess.Variable<Object>('O', "dir1", selFiles[0] ==null ? null : selFiles[0].getParentFile(), true)); }
    393            else if(name1.equals("dir2")){
    394              FileRemote dir = null;
    395              if(lastFilePanels.size() >=2){
    396                FcmdFileCard fileCard = lastFilePanels.get(1).actFileCard;
    397                if(fileCard !=null){ dir = fileCard.getCurrentDir(); }
    398              }
    399              args.add(new DataAccess.Variable<Object>('O', "dir2", dir, true));
    400            }
    401            else if(name1.equals("dir3")){
    402              FileRemote dir = null;
    403              if(lastFilePanels.size() >=3){
    404                FcmdFileCard fileCard = lastFilePanels.get(2).actFileCard;
    405                if(fileCard !=null){ dir = fileCard.getCurrentDir(); }
    406              }
    407              args.add(new DataAccess.Variable<Object>('O', "dir3", dir, true));
    408            }
    409            else if(name1.equals("listfiles1")) {
    410              List<FileRemote> files = null;
    411              if(lastFilePanels.size() >=1){
    412                FcmdLeftMidRightPanel filePanel = lastFilePanels.get(0);
    413                FcmdFileCard fileCard = filePanel.actFileCard;
    414                if(fileCard !=null){
    415                  files = fileCard.getSelectedFiles(true, 1);
    416                }
    417              }
    418              args.add(new DataAccess.Variable<Object>('L', "listfiles1", files, true));
    419            }
    420            else if(name1.equals("listfiles2")) {
    421              List<FileRemote> files = null;
    422              if(lastFilePanels.size() >=2){
    423                FcmdFileCard fileCard = lastFilePanels.get(1).actFileCard;
    424                if(fileCard !=null){ files = fileCard.getSelectedFiles(true, 1); }
    425              }
    426              args.add(new DataAccess.Variable<Object>('L', "listfiles2", files, true));
    427            }
    428            else {
    429              System.err.println("failded argument name: " + name1);
    430            }
    431          }
    432        }
    433      } else {
    434
    435      }
    436      return args;
    437    }
    438
    439    @Override public final File getCurrDir(){ return Fcmd.this.currentFileCard.currentDir(); }
    440  };
    441
    442
    443
    444  //MsgDispatchSystemOutErr msgDisp;
    445
    446  /**Set the singleton reference before other instances are initialized which uses main. */
    447  { Fcmd.main = this;
    448  }
    449
    450
    451  public JZtxtcmdScript.AddSub2List addButtonCmd = new JZtxtcmdScript.AddSub2List() {
    452
    453
    454    @Override public void clear() { buttonCmds.clear(); }
    455
    456    @Override public void add2List(JZcmdClass jzclass, int level){} //not used
    457
    458    @Override public void add2List(Subroutine jzsub, int level)
    459    {
    460      buttonCmds.put(jzsub.name, jzsub);
    461    }
    462
    463  };
    464
    465
    466
    467  final CallingArgs cargs;
    468
    469  final MsgRedirectConsole msgDisp;
    470
    471  final FileCluster fileCluster = FileRemote.clusterOfApplication;
    472
    473  // GralTabbedPanel tabbedPanelsLeft, tabbedPanelsMid, tabbedPanelsRight;
    474
    475  final FcmdWindowMng windMng = new FcmdWindowMng(this);
    476
    477  final FcmdButtons fButtons = new FcmdButtons(this);
    478
    479  final FcmdStatusLine statusLine = new FcmdStatusLine(this);
    480
    481  final String nameTextFieldInfo = "file-info";
    482
    483  final String nameTextFieldFilePath = "file-path";
    484
    485  final String nameTextFieldRunInfo = "run-info";
    486
    487  GralPanelContent panelButtons;
    488
    489
    490  final FcmdFavorPathSelector favorPathSelector = new FcmdFavorPathSelector(mainCmd, this);
    491
    492  final FcmdExecuter executer = new FcmdExecuter(mainCmd, gui.getOutputBox(), this);
    493
    494  final FcmdSettings settings = new FcmdSettings(this);
    495
    496  final FcmdStatus status = new FcmdStatus(this);
    497
    498  final FcmdFileProps filePropsCmd = new FcmdFileProps(this);
    499
    500  final FcmdView viewCmd = new FcmdView(this);
    501
    502  final FcmdEdit editWind = new FcmdEdit(this);
    503
    504  final FcmdCopyCmprDel copyCmd = new FcmdCopyCmprDel(this, FcmdCopyCmprDel.Ecmd.copy);
    505
    506  final FcmdCopyCmprDel delCmd = new FcmdCopyCmprDel(this, FcmdCopyCmprDel.Ecmd.delete);
    507
    508  final FcmdCopyCmprDel compareCmd = new FcmdCopyCmprDel(this, FcmdCopyCmprDel.Ecmd.compare);
    509
    510  final FcmdMkDirFile mkCmd = new FcmdMkDirFile(this);
    511
    512  final FcmdDelete deleteCmd = new FcmdDelete(this);
    513
    514  final FcmdFilesCp filesCp = new FcmdFilesCp(this);
    515
    516  final FcmdKeyActions keyActions = new FcmdKeyActions(this);
    517
    518  /**
    519   * Note: this should be the last aggregate of Fcmd because it uses some other ones. */
    520  final FcmdIdents idents = new FcmdIdents(this);
    521
    522
    523  /**The current directory of the last selected file. */
    524  //FileRemote currentFile;
    525
    526  /**The last selected files of the three panels, [0] for left .. [2] for right. */
    527  final File[] selectedFiles123 = new File[3];
    528
    529
    530  /**The last selected file panels in its order of selection.
    531   * This list contains max 3 entries.
    532   * To get the last selected files: The panel knows the last used file card there.
    533   */
    534  List<FcmdLeftMidRightPanel> lastFilePanels = new LinkedList<FcmdLeftMidRightPanel>();
    535
    536  /**The last used favor card or its last used file card.
    537   * It is used for delete tab. */
    538  FcmdFavorCard lastFavorCard;
    539
    540  FcmdFileCard currentFileCard;
    541
    542
    543  final Map<String, GralFileSelector> idxFileSelector = new TreeMap<String, GralFileSelector>();
    544
    545
    546  FcmdtTarget_ifc target;
    547
    548
    549  /**
    550   * The commands which are used for some buttons or menu items from the
    551   * JavaCommander itself.
    552   */
    553  final Map<String, JZtxtcmdScript.Subroutine> buttonCmds;
    554
    555
    556  final List<Closeable> threadsToClose = new LinkedList<Closeable>();
    557
    558  /**Static reference for the main instance to access from any class in the package.
    559   * This static instance is set firstly in constructor, all other constructors in this package
    560   * can be used it therefore. Use {@link #main()}*/
    561  private static Fcmd main;
    562
    563
    564  public Fcmd(CallingArgs cargs, GralArea9MainCmd cmdgui)
    565  {
    566    super(cargs, cmdgui, null, null, null);
    567    this.cargs = cargs;
    568    //redirect all outputs to System.out, System.err and MainCmd to System.out and System.err with timestamp.
    569    msgDisp = new MsgRedirectConsole(cmdgui, 0, null);
    570    msgDisp.setIdThreadForMsgDispatching(Thread.currentThread().getId());
    571    //msgDisp.msgDispatcher.setOutputRoutine(4, "MainLogFile", true, true, cmdgui.getLogMessageOutputFile());
    572    //msgDisp.msgDispatcher.setOutputRange(0, 100000, 4, MsgDispatcher.mAdd, 0);
    573    actionReadMsgConfig.exec(KeyCode.menuEntered, null);
    574
    575    target = new FcmdtTarget();  //create the target itself, one process TODO experience with remote target.
    576    buttonCmds = new TreeMap<String, JZtxtcmdScript.Subroutine>();
    577    //executer.cmdQueue.setOutput(gui.getOutputBox(), null);
    578  }
    579
    580
    581  /**Access the static instance of Fcmd.
    582   * This static instance is set firstly in constructor, all other constructors in this package
    583   * can be used it therefore.
    584   */
    585  static Fcmd main(){ return main; }
    586
    587
    588  /**
    589   * Initializes the areas for the panels and configure the panels. Note that
    590   * the window is initialized with an output area already. This is used for
    591   * output messages if problems occurs while build the rest of the GUI.
    592   */
    593  @Override
    594  protected void initGuiAreas(String sAreaMainPanel)
    595  {
    596    //panelBuildIfc.registerUserAction("KeyAction",
    597      //  keyActions.commanderKeyActions); // all key actions, registered central
    598
    599    gui.setFrameAreaBorders(30, 65, 70, 85); // x1, x2, y1, y2
    600    //gui.setStandardMenusGThread(new File("."), actionFile);
    601    //gui.addMenuItemGThread("menuBarFavorsLeft", idents.menuBarNavigationLeft, selectCardThemesLeft);
    602    //gui.addMenuItemGThread("menuBarFavorsMiddle", idents.menuBarNavigationMiddle, selectCardThemesMiddle);
    603    //gui.addMenuItemGThread("menuBarFavorsRight", idents.menuBarNavigationRight, selectCardThemesRight);
    604    //gui.addMenuItemGThread("menuBarNavigatonCmd", idents.menuBarNavigatonCmd, actionFocusCmdCard);
    605
    606    // gui.set
    607
    608    // Creates tab-Panels for the file lists and command lists.
    609    _gralMng.selectPanel("primaryWindow");
    610    favorPathSelector.panelLeft.tabbedPanelFileCards = _gralMng.addTabbedPanel("File0Tab", null, GralMngBuild_ifc.propZoomedPanel);
    611    gui.addFrameArea("A1A1", favorPathSelector.panelLeft.tabbedPanelFileCards); // dialogPanel);
    612
    613    favorPathSelector.panelLeft.buildInitialTabs();
    614    _gralMng.selectPanel("primaryWindow");
    615    favorPathSelector.panelMid.tabbedPanelFileCards = _gralMng.addTabbedPanel("File1Tab", null, GralMngBuild_ifc.propZoomedPanel);
    616    gui.addFrameArea("B1B1", favorPathSelector.panelMid.tabbedPanelFileCards); // dialogPanel);
    617    favorPathSelector.panelMid.buildInitialTabs();
    618
    619    _gralMng.selectPanel("primaryWindow");
    620    favorPathSelector.panelRight.tabbedPanelFileCards = _gralMng.addTabbedPanel("File2Tab", null, GralMngBuild_ifc.propZoomedPanel);
    621    gui.addFrameArea("C1C1", favorPathSelector.panelRight.tabbedPanelFileCards); // dialogPanel);
    622    favorPathSelector.panelRight.buildInitialTabs();
    623
    624    _gralMng.selectPanel("primaryWindow");
    625    panelButtons = _gralMng.createGridPanel("Buttons", _gralMng.getColor("gr"), 1, 1, 10, 10);
    626    gui.addFrameArea("A3C3", panelButtons); // dialogPanel);
    627
    628    filesCp.buildGraphic();
    629    settings.buildWindow();  //F2
    630    status.buildWindow();  //F2
    631    filePropsCmd.buildWindow();  //F2
    632    viewCmd.buildWindowView();   //F3
    633    editWind.buildWindow();   //F3
    634    copyCmd.buildWindowConfirmCopy("confirm copy / move / compare");
    635    delCmd.buildWindowConfirmCopy("confirm delete");
    636    compareCmd.buildWindowConfirmCopy("confirm compare");
    637    mkCmd.buildWindowConfirmMk();
    638    executer.buildWindowConfirmExec();
    639    deleteCmd.buildWindowConfirmDelete(); //F8
    640    favorPathSelector.buildWindowAddFavorite();
    641
    642    fButtons.initPanelButtons();
    643    GralMenu menu = gui.getMenuBar();
    644    menu.addMenuItem("MenuSetWorkingDir", "&Command/Set&WorkingDir", executer.actionSetCmdWorkingDir); // /
    645    menu.addMenuItem("MenuCommandAbort", "&Command/&Abort", executer.actionCmdAbort); // /
    646    // gui.addMenuItemGThread("&Command/E&xecute", actionSetCmdCurrentDir); ///
    647    menu.addMenuItem("MenuCmdCfgSet", "&Command/CmdCf&g - read current file", executer.actionSetCmdCfg); // /
    648
    649    menu.addMenuItem("menuHelp", idents.menuHelpBar, gui.getActionHelp());
    650    menu.addMenuItem("menuAbout", idents.menuBarAbout, gui.getActionAbout());
    651    menu.addMenuItem("MenuTestInfo", "&Help/&Infobox", actionTest);
    652    guiW.outputBox.setActionChange(executer.actionCmdFromOutputBox);
    653    String sHelpUrlDir = cargs.dirHtmlHelp.getAbsolutePath();
    654    gui.setHelpUrl(sHelpUrlDir + "/Fcmd.html");
    655    lastFilePanels.clear();
    656    lastFilePanels.add(favorPathSelector.panelMid);
    657    lastFilePanels.add(favorPathSelector.panelRight);
    658    lastFilePanels.add(favorPathSelector.panelLeft);
    659    favorPathSelector.panelMid.cardFavorThemes.setFocus();
    660  }
    661
    662  @Override
    663  protected final void initMain()
    664  {
    665    if (cargs.fileCfgCmds == null) {
    666      mainCmd.writeError("Argument cmdcfg:CONFIGFILE should be given.");
    667      // mainCmd.e
    668    } else if (cargs.fileCmdsForExt == null) {
    669      mainCmd.writeError("Argument cmdext:CONFIGFILE should be given.");
    670      // mainCmd.e
    671    } else if (cargs.fileCfgButtonCmds == null) {
    672      mainCmd.writeError("Argument cmdButton:CONFIGFILE should be given.");
    673      // mainCmd.e
    674    } else if (cargs.fileSelectTabPaths == null) {
    675      mainCmd.writeError("Argument sel:SELECTFILE should be given.");
    676      // mainCmd.e
    677    } else {
    678      String sError;
    679      File fileCfg;
    680      sError = executer.readCmdCfgSelectList(executer.cmdSelector.addJZsub2SelectTable, fileCfg = cargs.fileCfgCmds, console);
    681      if(sError !=null) {
    682        showInfoBox(sError);
    683      } else {
    684        appendTextInfoBox("read config cmd");
    685      }
    686      if (sError == null) {
    687        //sError = executer.readCmdFile(fileCfg = cargs.fileCmdsForExt);
    688        sError = executer.readCfgExt(new File(cargs.dirCfg, "extjz.cfg"));
    689      }
    690      if (sError == null) {
    691        sError = JZtxtcmd.readJZcmdCfg(addButtonCmd, fileCfg = cargs.fileCfgButtonCmds, console, executer.cmdExecuter);
    692      }
    693      if (sError == null) {
    694        sError = favorPathSelector.readCfg(fileCfg = cargs.fileSelectTabPaths);
    695      }
    696      if (sError != null) {
    697        mainCmd.writeError("Error reading " + fileCfg.getAbsolutePath() + ": "
    698            + sError);
    699      }
    700    }
    701    super.initMain(); // starts initializing of graphic. Do it after config
    702                      // command selector!
    703
    704  }
    705
    706  /**
    707   * Executing in the main thread loop. It handles commands.
    708   *
    709   * @see org.vishia.gral.area9.GuiCfg#stepMain()
    710   */
    711  @Override public void stepMain()
    712  {
    713    Appendable writeStatusCmd = new Appendable(){
    714
    715      @Override public Appendable append(CharSequence csq) throws IOException
    716      { statusLine.widgRunInfo.setText(csq);
    717        return this;
    718      }
    719
    720      @Override public Appendable append(char c) throws IOException
    721      { if(c == '\0') statusLine.widgRunInfo.setText(" ");
    722        else statusLine.widgRunInfo.setText("" + c);
    723        return this;
    724      }
    725
    726      @Override public Appendable append(CharSequence csq, int start, int end) throws IOException
    727      { statusLine.widgRunInfo.setText(csq.subSequence(start, end));
    728        return null;
    729      }
    730
    731    };
    732
    733    //executer.cmdQueue.execCmds(writeStatusCmd);
    734    executer.cmdExecuter.executeCmdQueue(false);
    735    long time = System.currentTimeMillis();
    736    favorPathSelector.panelLeft.checkRefresh(time);
    737    favorPathSelector.panelMid.checkRefresh(time);
    738    favorPathSelector.panelRight.checkRefresh(time);
    739  }
    740
    741
    742
    743  /**
    744   * Executing in the main thread loop. It handles commands.
    745   *
    746   * @see org.vishia.gral.area9.GuiCfg#stepMain()
    747   */
    748  @Override public void finishMain()
    749  {
    750    try{
    751      executer.cmdExecuter.close();  //finishes threads.
    752      target.close();
    753      FileAccessorLocalJava7.getInstance().close();
    754    } catch(IOException exc){
    755
    756    }
    757  }
    758
    759
    760  void setLastSelectedPanel(FcmdLeftMidRightPanel panel){
    761    if(lastFilePanels.size() == 0){
    762      lastFilePanels.add(0, panel);  //first time only
    763    }
    764    else if(lastFilePanels.get(0) != panel) {  //do nothing if the panel is the first one.
    765      if(!lastFilePanels.remove(panel)){  //if it is in list on higher position
    766        System.err.println("Fcmd - setLastSelectedPanel() faulty; try remove panel=" + panel.toString());
    767        //The file panel should be known!
    768      }
    769      lastFilePanels.add(0, panel);
    770    }
    771
    772  }
    773
    774  /**Get the last selected files in order of selection of the file panels.
    775   * If the current file of any panel is marked, then all other marked files (but not directories)
    776   * of this panel are taken as next files. But only 3 at all.
    777   * It is possible to mark two files in one file panel to execute an application with them.
    778   * New method since 2011-12-23
    779   * @return array[3] of the last selected files in the file panels. It has always a length of 3
    780   *   but not all elements are set ( they are ==null) if no files were selected before.
    781   *   The returned instance is a new one, not referenced elsewhere. It can be stored
    782   *   and it remains the situation of selection files independently of further user actions.
    783   */
    784  FileRemote[] getLastSelectedFiles(boolean bAlsoDirs, int mask){
    785    FileRemote[] ret = new FileRemote[3];
    786    int ix = -1;
    787    Iterator<FcmdLeftMidRightPanel> iterPanel = lastFilePanels.iterator();
    788    while(ix < 2 && iterPanel.hasNext() ){
    789      FcmdLeftMidRightPanel panel = iterPanel.next();
    790      //for(FcmdLeftMidRightPanel panel: lastFilePanels){
    791      FcmdFileCard fileCard = panel.actFileCard;
    792      if(fileCard !=null){
    793        ret[++ix] = fileCard.currentFile();
    794        if(fileCard.currentFile() !=null && fileCard.currentFile().isMarked(0x1)){
    795          //if the current file is marked, use all marked files.
    796          List<FileRemote> listFiles = fileCard.getSelectedFiles(bAlsoDirs, mask);
    797          //NOTE: the currentFile was marked, but it was not existing after delete. In this case all is okay but listFiles is empty.
    798          assert(listFiles !=null); // && listFiles.size() > 0);  //at least the current file is marked.
    799          Iterator<FileRemote> iter= listFiles.iterator();
    800          while(ix < 2 && iter.hasNext()){
    801            FileRemote file = iter.next();
    802            if(file != fileCard.currentFile()){
    803              ret[++ix] = file;
    804            }
    805          }
    806        }
    807      } else {
    808        //ret[++ix] = null;  //the panel hasn't a file selected now.
    809      }
    810    }
    811    //Note: There may be less than 3 file panels, rest of files are null.
    812    return ret;
    813  }
    814
    815
    816  /**Get the last selected file cards in order of selection of the file panels.
    817   * @return array[3] of the last selected file cards in the file panels. It has always a length of 3
    818   *   but not all elements are set ( they are ==null) if the file cards are not opened before
    819   *   in the panel.
    820   *   The returned instance is a new one, not referenced elsewhere. It can be stored
    821   *   and it remains the situation of selection files independently of further user actions.
    822   */
    823  FcmdFileCard[] getLastSelectedFileCards(){
    824    FcmdFileCard[] ret = new FcmdFileCard[3];
    825    int ix = -1;
    826    for(FcmdLeftMidRightPanel panel: lastFilePanels){
    827      FcmdFileCard fileCard = panel.actFileCard;
    828      if(fileCard !=null){
    829        ret[++ix] = fileCard;
    830      } else {
    831        ret[++ix] = null;  //the panel hasn't a file selected now.
    832      }
    833      if(ix >=2) break;  //prevent exception because older error
    834    }
    835    //Note: There may be less than 3 file panels, rest of files are null.
    836    return ret;
    837  }
    838
    839
    840
    841  /**Get the last selected file cards in order of selection of the file panels.
    842   * @return array[3] of the last selected file cards in the file panels. It has always a length of 3
    843   *   but not all elements are set ( they are ==null) if the file cards are not opened before
    844   *   in the panel.
    845   *   The returned instance is a new one, not referenced elsewhere. It can be stored
    846   *   and it remains the situation of selection files independently of further user actions.
    847   */
    848  List<File>[] getLastSelectedFilesPerCard(){
    849    @SuppressWarnings("unchecked")
    850    List<File>[] ret = new List[3];
    851    int ix = -1;
    852    for(FcmdLeftMidRightPanel panel: lastFilePanels){
    853      FcmdFileCard fileCard = panel.actFileCard;
    854      if(fileCard !=null){
    855        List<FileRemote> list = fileCard.getSelectedFiles(true, 0x1);
    856        ret[++ix] = new ArrayList<File>();
    857        for(File file: list) { ret[ix].add(file); }
    858      } else {
    859        ret[++ix] = null;  //the panel hasn't a file selected now.
    860      }
    861      if(ix >=2) break;  //prevent exception because older error
    862    }
    863    //Note: There may be less than 3 file panels, rest of files are null.
    864    return ret;
    865  }
    866
    867
    868
    869
    870
    871  /**Get the last selected file card in order of selection of the file panels.
    872   * @return The file card reference.   */
    873  FcmdFileCard getLastSelectedFileCard(){
    874
    875    if(lastFavorCard!=null){
    876      return lastFavorCard.fileTable;
    877    } else {
    878      return null;
    879    }
    880  }
    881
    882
    883
    884
    885  FileRemote currentFile(){
    886    if(this.currentFileCard == null) return null;
    887    else return this.currentFileCard.currentFile();
    888  }
    889
    890
    891  FileRemote currentDir(){
    892    if(this.currentFileCard == null) return null;
    893    else return this.currentFileCard.currentDir();
    894  }
    895
    896
    897  /**Refreshes the {@link FcmdFileCard} if the dir is the current one.
    898   * This method can be invoked in any for example callback routine in any thread, which changes the content of directories.
    899   * Note: It starts {@link GralFileSelector#fillIn(FileRemote, boolean)} which refreshes the files
    900   * @param fileOrDir The changed file or its directory.
    901   *   it is checked whether the directory is shown currently in one of the three file panels, then the panel will be refreshed.
    902   *   If the directory is not shown yet then nothing is done.
    903   *   Note that a directory will be refreshed whenever it will be activated in a panel.
    904   */
    905  protected void refreshFilePanel(FileRemote fileOrDir)
    906  {
    907    FileRemote dir = fileOrDir.isDirectory() ? fileOrDir: fileOrDir.getParentFile();
    908    for(FcmdLeftMidRightPanel panel: lastFilePanels) {
    909      if(panel !=null && panel.actFileCard !=null && panel.actFileCard.currentDir() == dir) {
    910        panel.actFileCard.fillInCurrentDir();
    911      }
    912    }
    913  }
    914
    915
    916
    917
    918
    919  /**
    920   * This class is instantiated in the static main routine and builds a command
    921   * line interface and the graphical frame. The mainly functionality is
    922   * contained in the super class.
    923   */
    924  private static class FcmdMainCmd extends GralArea9MainCmd
    925  {
    926
    927    private final CallingArgs cargs;
    928
    929    public FcmdMainCmd(CallingArgs cargs, String[] args)
    930    {
    931      super(cargs, args);
    932      this.cargs = cargs;
    933      super.addAboutInfo("The.file.Commander");
    934      super.addAboutInfo("made by Hartmut Schorrig, www.vishia.org, hartmut.schorrig@vishia.de");
    935      super.addAboutInfo("Version-date: " + Fcmd.version);
    936    }
    937
    938    @Override protected boolean testArgument(String arg, int nArg)
    939    {
    940      boolean bOk = true;
    941      if (arg.startsWith("cfg:")) {
    942        cargs.dirCfg = new File(arg.substring(4));
    943      } else if (arg.startsWith("cmdcfg:")) {
    944        cargs.fileCfgCmds = new File(arg.substring(7));
    945      } else if (arg.startsWith("cmdext:")) {
    946        cargs.fileCmdsForExt = new File(arg.substring(7));
    947      } else if (arg.startsWith("cmdButton:")) {
    948        cargs.fileCfgButtonCmds = new File(arg.substring(10));
    949      } else if (arg.startsWith("sel:")) {
    950        cargs.fileSelectTabPaths = new File(arg.substring(4));
    951      } else {
    952        bOk = super.testArgument(arg, nArg);
    953      }
    954      return bOk;
    955    }
    956
    957    @Override protected boolean checkArguments(){
    958      boolean bOk = true;
    959      if(cargs.dirCfg == null) { bOk = false; writeError("cmdline argument cfg:PATHCFG is missing"); }
    960      if(bOk){
    961        if(!cargs.dirCfg.exists()){ bOk = false; writeError("cmdline argument cfg is faulty:" + cargs.dirCfg.getAbsolutePath());}
    962      }
    963      if(bOk){
    964        if(cargs.dirHtmlHelp ==null){ cargs.dirHtmlHelp = new File(cargs.dirCfg, "../help"); }
    965        if(cargs.fileCfgCmds ==null){ cargs.fileCfgCmds = new File(cargs.dirCfg, "cmd.cfg"); }
    966        if(cargs.fileCmdsForExt ==null){ cargs.fileCmdsForExt = new File(cargs.dirCfg, "ext.cfg"); }
    967        if(cargs.fileCfgButtonCmds ==null){ cargs.fileCfgButtonCmds = new File(cargs.dirCfg, "cmdi.cfg"); }
    968        if(cargs.fileSelectTabPaths ==null){ cargs.fileSelectTabPaths = new File(cargs.dirCfg, "path.cfg"); }
    969      }
    970      return bOk;
    971    }
    972
    973  } // class MainCmd
    974
    975
    976  static void testT1()
    977  {
    978    float R = 10000.0f;
    979    float C = 0.000000001f;
    980    float tStep = 0.0000001f;
    981    float uc = 0.0f;
    982    float ue = 1.0f;
    983    for (int step = 0; step < 100; ++step) {
    984      float iR = (ue - uc) / R;
    985      uc = uc + iR / C * tStep;
    986    }
    987
    988  }
    989
    990  /**
    991   * The command-line-invocation (primary command-line-call.
    992   *
    993   * @param args
    994   *          Some calling arguments are taken. This is the GUI-configuration
    995   *          especially.
    996   */
    997  public static void main(String[] args)
    998  {
    999    testT1();
    1000    boolean bOk = true;
    1001    CallingArgs cargs = new CallingArgs();
    1002    // Initializes the GUI till a output window to show information.
    1003    // Uses the commonly GuiMainCmd class because here are not extra arguments.
    1004    GralArea9MainCmd cmdgui = new FcmdMainCmd(cargs, args); // implements MainCmd, parses
    1005    //new GralMng(null, cmdgui);
    1006
    1007    // calling arguments
    1008    bOk = cmdgui.parseArgumentsAndInitGraphic("The.file.Commander", "2A2C", '.', "0+50,0+150");
    1009
    1010    /*
    1011    try {
    1012      cmdgui.parseArguments();
    1013    } catch (Exception exception) {
    1014      cmdgui.writeError("Cmdline argument error:", exception);
    1015      cmdgui.setExitErrorLevel(MainCmd_ifc.exitWithArgumentError);
    1016      bOk = false; // not exiting, show error in GUI
    1017    }
    1018    */
    1019    if (bOk) {
    1020      // Uses socket communication for InterprocessComm, therefore load the
    1021      // factory.
    1022      new InterProcessCommFactorySocket();
    1023      //
    1024      // Initialize this main class and execute.
    1025      Fcmd main = new Fcmd(cargs, cmdgui);
    1026      //main.msgDisp = MsgDispatchSystemOutErr.create();
    1027      main.execute();
    1028    }
    1029    cmdgui.exit();
    1030  }
    1031
    1032
    1033
    1034
    1035}