JMRI: Plug-in mechanisms
The original goal of the JMRI project was to produce a library upon which people could use to build their own applications. Although some people do that, more use the existing applications such as DecoderPro and PanelPro. We want to make this more flexible by providing a way to extend those programs without having to rebuild them from scratch. This note describes mechanisms for that which will is included in JMRI 2.4 and later.- CLASSPATH
DecoderPro et al are run via a java command which sets the CLASSPATH and various options. How that's actually done varies with the platform: csh scripts on Unix, a launcher application on Windows, application bundles on MacOS X, etc.
To make it easy to add plug-ins, these include all .jar files in the application directory, and in its "lib/" subdirectory, in the CLASSPATH.
If you create a jar file including your code, it will automatically be found. You can also put your classes in the "classes" directory of the startup directory, which is searched first.
For more information, see the page on startup scripts.
- Replacement of existing classes
Note that you can directly replace any of the files in the jmri.jar distribution with your own versions by putting them in a jar file that's searched first. For example, including a modified version of a .properties file would allow you to include customized versions of menu strings. This can also be done with a .class file, for example changing the order of menu items by replacing the DecoderPro class.
- Plugin classes
Replacing a class can cause extra work in the long term, as the replaced class may be modified as JMRI evolves. So we also provide a hook on which to hang new code. After initialization is complete, the programs will attempt to invoke a static member of the form:
package jmri; public class JmriPlugin { public static void start(javax.swing.JFrame mainFrame, javax.swing.JMenuBar menuBar) {} }This method can modify the menubar by inserting, modifying or removing menus or menu items, add buttons to the main panel, etc.As people use this capability, we'll probably want to refactor some existing classes to make them easier to extend. For example, a monolithic formatting class like llnmon should be broken up into smaller pieces to make it easier to add new formats.
Other Mechanisms
It's also possible to customize your version of JMRI using scripts, and by using the advanced preferences.Scripts can locate and access any open window, for example. The AddButton.py sample script is an example of adding a script button to the main window. The DisableOpsMode.py sample script shows how how to modify the main window to remove the ops-mode programming button. The ReporterFontControl.py sample script is an even more advanced example that changes the appearance of items on panel screens.