beryx / text-io

A library for creating interactive console applications in Java
http://text-io.beryx.org/
Apache License 2.0
342 stars 45 forks source link

How to restart gracefully #23

Open mokun opened 4 years ago

mokun commented 4 years ago

How do I restart a SwingTextTerminal gracefully without quitting the application ?

I have a main application running side-by-side with a SwingTextTerminal console in Windows.

e.g. I have a while loop that set up a menu for querying things.

        while (keepRunning) {

            BiConsumer<TextIO, RunnerData> menu = chooseMenu(textIO);
            terminal.printf(System.lineSeparator());

            // Set up the prompt for the menu
            menu.accept(textIO, null);

            // if the sim is being saved, enter this while loop
            while (masterClock.isSavingSimulation()) {
                delay(500L);
            }
        }
    }
   /**
     * Presents choices in the console menu
     * 
     * @param textIO
     * @return {@link BiConsumer}
     */
    private static BiConsumer<TextIO, RunnerData> chooseMenu(TextIO textIO) {
        List<BiConsumer<TextIO, RunnerData>> apps = Arrays.asList(
                chatMenu,
                new AutosaveMenu(),
                new SaveMenu(),
                new TimeRatioMenu(),
                new LogMenu(),
                new ExitMenu()
        );

        BiConsumer<TextIO, RunnerData> app = textIO.<BiConsumer<TextIO, RunnerData>>newGenericInputReader(null)
            .withNumberedPossibleValues(apps)
            .read(System.lineSeparator() 
                    + "-------------------  C O N S O L E   M E N U  -------------------" 
                    + System.lineSeparator());
        String propsFileName = app.getClass().getSimpleName() + ".properties";
        System.setProperty(AbstractTextTerminal.SYSPROP_PROPERTIES_FILE_LOCATION, propsFileName);
//        profile.term().moveToLineStart();     
        return app;
    }

Previously, when I call terminal.dispose(null) to end the SwingTextTerminal instance, it would crash.

So I end up always calling system.exit(0) to end everything (the main application and the beryx terminal).

But what if I simply want to quit the existing terminal that has been corrupted and restart it since I want to keep the main application running ?

How do I do that ?

siordache commented 4 years ago

How does terminal.dispose(null) crash? Can you post the stack trace?

mokun commented 4 years ago

Sorry. not crashing. I meant the JFrame was disposed before I can save up some objects.

So I'm hoping not to dispose the JFrame.

But if I set the keepRunning to false, the beryx console would just halt and no longer work.

So my question is how can I make the console work again without disposing/rebuilding the whole JFrame ?

siordache commented 4 years ago

I'm not sure if it helps, but try to replace this line with:

((MarsTerminal)InteractiveTerm.getTextIO().getTextTerminal()).getFrame().setVisible(false);
mokun commented 4 years ago

My first objective is to find out how to exit the text-io properly.

In my case in a class called MarsTerminal that extends SwingTextTerminal, I attach a listener to the top-right corner exit button to ask for confirmation if I want to exit as follows :

  private void configureMainMenu() {
        frame = getFrame();

    frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent event) {
                // Save simulation and UI configuration when window is closed.
                int reply = JOptionPane.showConfirmDialog(null, "Are you sure you want to quit?", "Exit", JOptionPane.YES_NO_OPTION);
                if (reply == JOptionPane.YES_OPTION) {
                    printf("Exiting the Simulation..." + System.lineSeparator());
                    Simulation sim = Simulation.instance();
                    sim.endSimulation(); 
                    sim.getSimExecutor().shutdownNow();
                    if (sim.getMasterClock() != null)
                        sim.getMasterClock().exitProgram();
                    logger.info("Exiting the Simulation.");
                    InteractiveTerm.setKeepRunning(false);
                    System.exit(0);
                    frame.setVisible(false);
                    dispose(null);
                }
            }
        });

When I choose the Yes button to quit, I have the following stacktrace :

java.lang.RuntimeException: read interrupted
    at org.beryx.textio.swing.SwingTextTerminal.read(SwingTextTerminal.java:378)
    at org.beryx.textio.InputReader.readWithPrompt(InputReader.java:437)
    at org.beryx.textio.InputReader.lambda$read$3(InputReader.java:382)
    at org.beryx.textio.TextTerminal.applyWithPropertiesConfigurator(TextTerminal.java:243)
    at org.beryx.textio.InputReader.executeWithTerminal(InputReader.java:461)
    at org.beryx.textio.InputReader.read(InputReader.java:380)
    at org.beryx.textio.InputReader.read(InputReader.java:368)
    at org.mars.sim.console.SwingHandler$Task.run(SwingHandler.java:188)
    at org.mars.sim.console.SwingHandler.executeOneTask(SwingHandler.java:345)
    at org.mars.sim.console.InteractiveTerm.selectMode(InteractiveTerm.java:165)
    at org.mars.sim.console.InteractiveTerm.startModeSelection(InteractiveTerm.java:136)
    at org.mars_sim.main.MarsProject.handleNewSimulation(MarsProject.java:418)
    at org.mars_sim.main.MarsProject.initializeSimulation(MarsProject.java:191)
    at org.mars_sim.main.MarsProject$SimulationTask.run(MarsProject.java:164)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.InterruptedException
    at java.base/java.lang.Object.wait(Native Method)
    at java.base/java.lang.Object.wait(Object.java:328)
    at org.beryx.textio.swing.SwingTextTerminal.read(SwingTextTerminal.java:355)
    ... 18 more