public final boolean closeModule(WorkbenchModule module) {
        LOGGER.trace("closeModule - " + module);
        LOGGER.trace("closeModule - List of open modules: " + openModules);
        Objects.requireNonNull(module);
        int i = openModules.indexOf(module);
        if (i == -1) {
            throw new IllegalArgumentException("Module has not been opened yet.");
        }
        // set new active module
        WorkbenchModule oldActive = getActiveModule();
        WorkbenchModule newActive;
        if (oldActive != module) {
            // if we are not closing the currently active module, stay at the current
            newActive = oldActive;
        } else if (openModules.size() == 1) {
            // go to home screen
            newActive = null;
            LOGGER.trace("closeModule - Next active: Home Screen");
        } else if (i == 0) {
            // multiple modules open, leftmost is active
            newActive = openModules.get(i + 1);
            LOGGER.trace("closeModule - Next active: Next Module - " + newActive);
        } else {
            newActive = openModules.get(i - 1);
            LOGGER.trace("closeModule - Next active: Previous Module - " + newActive);
        }
        // if the currently active module is the one that is being closed, deactivate first
        if (oldActive == module) {
            LOGGER.trace("closeModule - " + module + " was deactivated");
            module.deactivate();
        }
    /*
      If module has previously been closed and can now safely be closed, calling destroy() is not
      necessary anymore, simply remove the module
      If this module is being closed the first time or cannot be safely closed yet, attempt to
      destroy module.
      Note: destroy() will not be called if moduleCloseable was completed with true!
     */
        if (getModuleCloseable(module).getNow(false) || module.destroy()) {
            LOGGER.trace("closeModule - Destroy: Success - " + module);
            boolean removal = openModules.remove(module);
            moduleCloseableMap.remove(module);
            LOGGER.trace("closeModule - Destroy, Removal successful: " + removal + " - " + module);
            if (oldActive != newActive) {
                // only log if the active module has been changed
                LOGGER.trace("closeModule - Set active module to: " + newActive);
            }
            activeModule.setValue(newActive);
            return removal;
        } else {
      /*
        If moduleCloseable wasn't completed yet but closeModule was called, there are two cases:
        1. The stage is calling closeModule() => since thenRun will be set on moduleCloseable after
           closeModule() returns "false", we need to reset moduleCloseable so that repeating stage
           closes without completing moduleClosable won't lead to multiple thenRun actions being
           layered with each stage close.
        2. The tab is being closed, calling closeModule() => if there was a stage close beforehand
           (and thus a thenRun from the stage closing process is still active) we need to
           reset moduleCloseable so that the stage closing process will not be triggered again.
       */
            resetModuleCloseable(module);
            // module should or could not be destroyed
            LOGGER.trace("closeModule - Destroy: Fail - " + module);
            // if the module that has failed to be destroyed is already open, activate it again
            if (getActiveModule() == module) {
                module.activate();
            }
            openModule(module); // set focus to new module
            return false;
        }
    }
Closes the {@code module}.

@param module to be closed
@return true if closing was successful
workbenchfx-core/src/main/java/com/dlsc/workbenchfx/Workbench.java