Example #1
0
  @edu.umd.cs.findbugs.annotations.SuppressWarnings({
    "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD",
    "SC_START_IN_CTOR"
  }) // "only one application at a time. The thread is only called to help improve user experiance
  // when opening the preferences, it is not critical for it to be run at this stage"
  public Apps(JFrame frame) {

    super(true);
    long start = System.nanoTime();

    splash(false);
    splash(true, true);
    setButtonSpace();
    setJynstrumentSpace();

    jmri.Application.setLogo(logo());
    jmri.Application.setURL(line2());

    // Enable proper snapping of JSliders
    SliderSnap.init();

    // Prepare font lists
    prepareFontLists();

    // install shutdown manager
    InstanceManager.setShutDownManager(new DefaultShutDownManager());

    // add the default shutdown task to save blocks
    // as a special case, register a ShutDownTask to write out blocks
    InstanceManager.shutDownManagerInstance()
        .register(
            new AbstractShutDownTask("Writing Blocks") {
              @Override
              public boolean execute() {
                // Save block values prior to exit, if necessary
                log.debug("Start writing block info");
                try {
                  new BlockValueFile().writeBlockValues();
                } // catch (org.jdom2.JDOMException jde) { log.error("Exception writing blocks: {}",
                // jde); }
                catch (IOException ioe) {
                  log.error("Exception writing blocks: {}", ioe);
                }

                // continue shutdown
                return true;
              }
            });

    // Get configuration profile
    // Needs to be done before loading a ConfigManager or UserPreferencesManager
    FileUtil.createDirectory(FileUtil.getPreferencesPath());
    // Needs to be declared final as we might need to
    // refer to this on the Swing thread
    final File profileFile;
    profileFilename = configFilename.replaceFirst(".xml", ".properties");
    // decide whether name is absolute or relative
    if (!new File(profileFilename).isAbsolute()) {
      // must be relative, but we want it to
      // be relative to the preferences directory
      profileFile = new File(FileUtil.getPreferencesPath() + profileFilename);
    } else {
      profileFile = new File(profileFilename);
    }
    ProfileManager.getDefault().setConfigFile(profileFile);
    // See if the profile to use has been specified on the command line as
    // a system property jmri.profile as a profile id.
    if (System.getProperties().containsKey(ProfileManager.SYSTEM_PROPERTY)) {
      ProfileManager.getDefault()
          .setActiveProfile(System.getProperty(ProfileManager.SYSTEM_PROPERTY));
    }
    // @see jmri.profile.ProfileManager#migrateToProfiles JavaDoc for conditions handled here
    if (!ProfileManager.getDefault().getConfigFile().exists()) { // no profile config for this app
      try {
        if (ProfileManager.getDefault()
            .migrateToProfiles(configFilename)) { // migration or first use
          // notify user of change only if migration occured
          // TODO: a real migration message
          JOptionPane.showMessageDialog(
              sp,
              Bundle.getMessage("ConfigMigratedToProfile"),
              jmri.Application.getApplicationName(),
              JOptionPane.INFORMATION_MESSAGE);
        }
      } catch (IOException | IllegalArgumentException ex) {
        JOptionPane.showMessageDialog(
            sp,
            ex.getLocalizedMessage(),
            jmri.Application.getApplicationName(),
            JOptionPane.ERROR_MESSAGE);
        log.error(ex.getMessage());
      }
    }
    try {
      ProfileManagerDialog.getStartingProfile(sp);
      // Manually setting the configFilename property since calling
      // Apps.setConfigFilename() does not reset the system property
      configFilename = FileUtil.getProfilePath() + Profile.CONFIG_FILENAME;
      System.setProperty("org.jmri.Apps.configFilename", Profile.CONFIG_FILENAME);
      log.info("Starting with profile {}", ProfileManager.getDefault().getActiveProfile().getId());
    } catch (IOException ex) {
      log.info(
          "Profiles not configurable. Using fallback per-application configuration. Error: {}",
          ex.getMessage());
    }

    // Install configuration manager and Swing error handler
    ConfigureManager cm = new JmriConfigurationManager();
    InstanceManager.store(cm, ConfigureManager.class);
    InstanceManager.setDefault(ConfigureManager.class, cm);

    // Install a history manager
    InstanceManager.store(new FileHistory(), FileHistory.class);
    // record startup
    InstanceManager.getDefault(FileHistory.class).addOperation("app", nameString, null);

    // Install a user preferences manager
    InstanceManager.store(
        DefaultUserMessagePreferences.getInstance(), UserPreferencesManager.class);
    InstanceManager.store(new NamedBeanHandleManager(), NamedBeanHandleManager.class);
    // Install an IdTag manager
    InstanceManager.store(new DefaultIdTagManager(), IdTagManager.class);
    // Install Entry Exit Pairs Manager
    InstanceManager.store(new EntryExitPairs(), EntryExitPairs.class);

    // install preference manager
    InstanceManager.store(new TabbedPreferences(), TabbedPreferences.class);

    // Install abstractActionModel
    InstanceManager.store(new apps.CreateButtonModel(), apps.CreateButtonModel.class);

    // find preference file and set location in configuration manager
    // Needs to be declared final as we might need to
    // refer to this on the Swing thread
    final File file;
    File singleConfig;
    File sharedConfig = null;
    // decide whether name is absolute or relative
    if (!new File(configFilename).isAbsolute()) {
      // must be relative, but we want it to
      // be relative to the preferences directory
      singleConfig = new File(FileUtil.getUserFilesPath() + configFilename);
    } else {
      singleConfig = new File(configFilename);
    }
    try {
      // get preferences file
      sharedConfig = FileUtil.getFile(FileUtil.PROFILE + Profile.SHARED_CONFIG);
      if (!sharedConfig.canRead()) {
        sharedConfig = null;
      }
    } catch (FileNotFoundException ex) {
      // ignore - sharedConfig will remain null in this case
    }
    // load config file if it exists
    if (sharedConfig != null) {
      file = sharedConfig;
    } else {
      file = singleConfig;
    }
    log.debug("Using config file(s) {}", file.getPath());
    if (file.exists()) {
      log.debug("start load config file {}", file.getPath());
      try {
        configOK = InstanceManager.configureManagerInstance().load(file, true);
      } catch (JmriException e) {
        log.error("Unhandled problem loading configuration", e);
        configOK = false;
      }
      log.debug("end load config file, OK={}", configOK);
    } else {
      log.info(
          "No saved preferences, will open preferences window.  Searched for {}", file.getPath());
      configOK = false;
    }

    // Add actions to abstractActionModel
    // Done here as initial non-GUI initialisation is completed
    // and UI L&F has been set
    addToActionModel();

    // populate GUI
    log.debug("Start UI");
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    // Create a WindowInterface object based on the passed-in Frame
    JFrameInterface wi = new JFrameInterface(frame);
    // Create a menu bar
    menuBar = new JMenuBar();

    // Create menu categories and add to the menu bar, add actions to menus
    createMenus(menuBar, wi);

    // done
    long end = System.nanoTime();

    long elapsedTime = (end - start) / 1000000;
    /*
    This ensures that the message is displayed on the screen for a minimum of 2.5seconds, if the time taken
    to get to this point in the code is longer that 2.5seconds then the wait is not invoked.
    */
    long sleep = 2500 - elapsedTime;
    if (sleep > 0) {
      log.debug(
          "Debug message was displayed for less than 2500ms ({}ms). Sleeping for {}ms to allow user sufficient time to do something.",
          elapsedTime,
          sleep);
      try {
        Thread.sleep(sleep);
      } catch (InterruptedException e) {
        log.error(e.getLocalizedMessage(), e);
      }
    }

    FileUtil.logFilePaths();

    splash(false);
    splash(true, false);
    Toolkit.getDefaultToolkit().removeAWTEventListener(debugListener);
    while (debugmsg) {
      /*The user has pressed the interupt key that allows them to disable logixs
      at start up we do not want to process any more information until the user
      has answered the question */
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        log.error(e.getLocalizedMessage(), e);
      }
    }
    // Now load deferred config items
    if (file.exists() && file.equals(singleConfig)) {
      // To avoid possible locks, deferred load should be
      // performed on the Swing thread
      if (SwingUtilities.isEventDispatchThread()) {
        configDeferredLoadOK = doDeferredLoad(file);
      } else {
        try {
          // Use invokeAndWait method as we don't want to
          // return until deferred load is completed
          SwingUtilities.invokeAndWait(
              new Runnable() {
                @Override
                public void run() {
                  configDeferredLoadOK = doDeferredLoad(file);
                }
              });
        } catch (InterruptedException | InvocationTargetException ex) {
          log.error("Exception creating system console frame", ex);
        }
      }
    } else {
      configDeferredLoadOK = false;
    }
    // If preferences need to be migrated, do it now
    if (sharedConfig == null && configOK == true && configDeferredLoadOK == true) {
      log.info("Migrating preferences to new format...");
      // migrate preferences
      InstanceManager.tabbedPreferencesInstance().init();
      InstanceManager.tabbedPreferencesInstance().saveContents();
      InstanceManager.configureManagerInstance().storePrefs();
      // notify user of change
      log.info("Preferences have been migrated to new format.");
      log.info("New preferences format will be used after JMRI is restarted.");
      if (!GraphicsEnvironment.isHeadless()) {
        JOptionPane.showMessageDialog(
            sp,
            Bundle.getMessage(
                "SingleConfigMigratedToSharedConfig",
                ProfileManager.getDefault().getActiveProfile().getName()),
            jmri.Application.getApplicationName(),
            JOptionPane.INFORMATION_MESSAGE);
      }
    }

    /*Once all the preferences have been loaded we can initial the preferences
    doing it in a thread at this stage means we can let it work in the background*/
    Runnable r =
        new Runnable() {
          @Override
          public void run() {
            try {
              InstanceManager.tabbedPreferencesInstance().init();
            } catch (Exception ex) {
              log.error("Error trying to setup preferences {}", ex.getLocalizedMessage(), ex);
            }
          }
        };
    Thread thr = new Thread(r, "initialize preferences");
    thr.start();
    // Initialise the decoderindex file instance within a seperate thread to help improve first use
    // perfomance
    r =
        new Runnable() {
          @Override
          public void run() {
            try {
              DecoderIndexFile.instance();
            } catch (Exception ex) {
              log.error("Error in trying to initialize decoder index file {}", ex.toString());
            }
          }
        };
    Thread thr2 = new Thread(r, "initialize decoder index");
    thr2.start();

    if (Boolean.getBoolean("org.jmri.python.preload")) {
      r =
          new Runnable() {
            public void run() {
              try {
                JmriScriptEngineManager.getDefault().initializeAllEngines();
              } catch (Exception ex) {
                log.error("Error in trying to initialize python interpreter {}", ex.toString());
              }
            }
          };
      Thread thr3 = new Thread(r, "initialize python interpreter");
      thr3.start();
    }
    // if the configuration didn't complete OK, pop the prefs frame and help
    log.debug("Config go OK? {}", (configOK || configDeferredLoadOK));
    if (!configOK || !configDeferredLoadOK) {
      HelpUtil.displayHelpRef("package.apps.AppConfigPanelErrorPage");
      doPreferences();
    }
    log.debug("Done with doPreferences, start statusPanel");

    add(statusPanel());
    log.debug("Done with statusPanel, start buttonSpace");
    add(buttonSpace());
    add(_jynstrumentSpace);
    long eventMask = AWTEvent.MOUSE_EVENT_MASK;

    Toolkit.getDefaultToolkit()
        .addAWTEventListener(
            new AWTEventListener() {
              @Override
              public void eventDispatched(AWTEvent e) {
                if (e instanceof MouseEvent) {
                  MouseEvent me = (MouseEvent) e;
                  if (me.isPopupTrigger() && me.getComponent() instanceof JTextComponent) {
                    final JTextComponent component = (JTextComponent) me.getComponent();
                    final JPopupMenu menu = new JPopupMenu();
                    JMenuItem item;
                    item = new JMenuItem(new DefaultEditorKit.CopyAction());
                    item.setText("Copy");
                    item.setEnabled(component.getSelectionStart() != component.getSelectionEnd());
                    menu.add(item);
                    item = new JMenuItem(new DefaultEditorKit.CutAction());
                    item.setText("Cut");
                    item.setEnabled(
                        component.isEditable()
                            && component.getSelectionStart() != component.getSelectionEnd());
                    menu.add(item);
                    item = new JMenuItem(new DefaultEditorKit.PasteAction());
                    item.setText("Paste");
                    item.setEnabled(component.isEditable());
                    menu.add(item);
                    menu.show(me.getComponent(), me.getX(), me.getY());
                  }
                }
              }
            },
            eventMask);

    // do final activation
    InstanceManager.logixManagerInstance().activateAllLogixs();
    InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager.class)
        .initializeLayoutBlockPaths();
    // Loads too late - now started from ItemPalette
    //        new jmri.jmrit.catalog.configurexml.DefaultCatalogTreeManagerXml().readCatalogTrees();

    log.debug("End constructor");
  }
Example #2
0
 /** Adds the development menu to the default main menu bar. */
 @Override
 protected void createMenus(JMenuBar menuBar, WindowInterface wi) {
   super.createMenus(menuBar, wi);
   developmentMenu(menuBar, wi);
   menuBar.add(new jmri.jmris.ServerMenu());
 }