0

I'm developing an app which for some time will probably just use the command line. It may one day be appropriate to give it the whole JavaFX visual treatment: windows, dialogs, etc.

What I do currently need to do is allow the users to select files/directories from anywhere in the file system. The way I've done this is to make my main class, ConsoleHandler, subclass from JavaFX Application, and to run start() at the start of the run, so in fact the app is running on the JavaFX thread. This means, among other things, that the thread allows the JavaFX FileChooser to be displayed, and also waits while the user selects the file(s)/directories...

But this seems so WRONG! This is not (not yet anyway) a "visual" application. I would rather handle the "waiting for user input" by something simple, like an ExecutorService, and use normal Threads.

I appreciate that a file chooser is indeed a "visual" feature in its own right, and obviously an "event" such as the clicking of a "Select" button, is involved: but having to use the whole JavaFX infrastructure for this purpose seems silly. I'm wondering whether something somehow more typing-based might exist.

NB I have no desire to use Swing's JFileChooser: similar thoughts apply, and Swing is the past.

The thing I'm currently planning to do is to work around by hiving off all the FileChooser functionality into an isolated module... but I just thought I'd ask if anyone knows of a way to avoid JavaFX completely for this use case.

mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • There's no way to avoid running the JavaFX toolkit if you want to use a JavaFX file chooser. I would move your non-UI application logic to a separate class, and run it from a background thread, which you can start from the `Application.start()` method. If you need to show the file chooser from the background thread, wrap the calls to it in `Platform.runLater()`. This should give you more flexibility to migrate to a full UI app (or even to a completely non-UI app) later. – James_D Apr 12 '18 at 21:12

2 Answers2

0

You could try to replicate a console such as CMD or the Linux console; where you start at a folder and can then move to folders within it or to the parent folder by using a command much like cd on the CMD. You could do this by simply creating a File object with the starting path and then go back if a certain command is inputted or go into a folder if it exists.

File currDir = new File("starting path");
String input = //INPUT FROM CONSOLE
if(input.equals("back")){
    //GO BACK TO PARENT FOLDER
    currDir = currDir.getParentFile();
}else{
    for(File file : currDir.listFiles()){
        if(file.isDirectory()){
            if(file.getName().equals(input)){
                //GO INTO SELECTED FOLDER
                currDir = file;
            }
        }else if(file.isFile()){
            /*SINCE file.getName() INCLUDES THE FILE EXTENSION YOU'D HAVE TO 
            EITHER PROVIDE THE FILE EXTENSION ALONG THE NAME OF THE FILE 
            WHEN YOU INPUT IT OR SPLIT THE FILE NAME AND EXTENSION FROM 
            THE INPUT BEFORE COMPARING*/
            if(file.getName().equals(input)){
                //THIS IS THE SELECTED FILE, DO WHAT YOU WANT WITH IT
            }
        }
    }
}

Although from past experience I honestly believe that using either the default FileChooser or JFileChooser would work best.

PabloJ
  • 199
  • 1
  • 9
  • Thanks... yes, this idea of "replicating" BASH navigation and file selection and so on had occurred to me. My thinking is that rather than "roll my own" functionality there might hopefully be a downloadable library out there somewhere... or that somehow it might be possible to use a limited set of BASH commands from within the app itself (well there is `Runtime.exec`, of course...). Looks like a separate JavaFX module is probably the way to go. – mike rodent Apr 13 '18 at 05:44
0

PabloJ's answer made me think a bit.

Especially with Groovy the option of using Runtime gets quite practical:

def process = Runtime.runtime.exec( userInputLine )
println "system response: $process.inputStream.text"

NB for non-Groovy people, runtime comes from getRuntime(), inputStream comes from getInputStream(), and text comes from the enhanced (GDK) Groovy version of InputStream which very conveniently has added a method getText() to InputStream. Using pure Java you have to get involved with StringBuffer, checked Exceptions, etc.

... the only problem now is that presumably this userInputLine will have to be a DOS-style command on Windoze (dir etc.) but a BASH command on Linux (ls etc.) (or is there a way of getting Runtime to use Cygwin on W10? hmmm... 2 mins later: yes)

... so obviously you can then implement your own permitted, limited set of BASH commands which are allowed, including cd ... and then add a few "convenience" navigation shortcuts and your own "select" command which says "hoover up all the files/directories listed by this selection pattern and process them..."

Finally, there is a problem here to do with the fact that it appears impossible to change Java/Groovy's working directory... so how to run cd? You keep a "synthetic" working directory File, and instead of going exec( command ) you go exec( command, null, synthWD ). cd commands must be intercepted and processed accordingly (i.e. change synthWD).

mike rodent
  • 14,126
  • 11
  • 103
  • 157