Système de plugin - plaa/Modular GitHub Wiki
Dans de nombreux cas on desire ajouter une fonctionalité à openrocket qui est utile dans un contexte bien specifique, mais pas vraiment approprié pour l'inclure dans le code de base d'OpenRocket. Pour cette raison il est desirable d'avoir une sorte de systeme de plugin, comme recontré dans de nombreuses autres applications.
Dans notre cas nous appelons plugins quelque chose qui est installé sur l'ordinateur de l'utilisateur, qui est reconnu par OR et fourni des fonctionalités additionnelles. La fonctionalité peut etre des ecouteurs de simulations, nouveaux type de moteurs etc.
- Configuration : Il devrait etre possible de configurer les plugins via l'interface utilisateur d'OpenRocket. Ceci devrait etre fait de façon consitante depuis un menu plugin listant tout les plugins. Cela devrait etre clair pour l'utilisateur quelle fonctionnalité fait partie d'un plugin et ce qui fait parti du corps d'Openrocket.
- Decouverte automatique : Les utilisateurs ne devraient pas avoir à changer le classpath ou quoi que ce soit d'autre pour utiliser les plugins. La solution probablement la plus simple serai que l'utilisateur puisse télécharger les plugins et les placer dans un répertoire de plugins de maniere à ce qu'ils soient automatiquement chargés au démarage. At a later stage, some automatic functionality might be added to the openrocket GUI.
- Prise en compte de l'internationalisation
- Modification de la simulation : as currently with simulation listeners, but more extensively and with extra data better integrated.
- Modification des composants de la fusée listés dans l'arbre : changes automatically applied to rocket figure, other helpers as necessary
- Custom components (Discuss) :
- Dependency management : Some plugins may depend on others and be able to automatically load them. This in turn requires that plugins have a consistent identifier / URI and version number.
- Plugins implementés dans d'autres langues (à discuter)
- Simplification de l'accès aux documents openrocket : plugin author should have relatively straightforward access to useful elements of the openrocket document. For example, things such as the currently selected rocket component, or bringing up a custom dialogue. These things should be possible without having to navigate through a complex structure of classes; this may require occasional helper methods.
(à discuter)
Various plug-in frameworks exist for java, and may significantly reduce the time required to implement the plugin feature.
Directly coding the plug-in just requires the new interface to extend the Plugin interface and to add the annotations to the implementation class. This is a simple and light-weight solution which may well be quite suitable.
Of the alternative plug-in frameworks which exist, the most interesting is JSPF (http://code.google.com/p/jspf/). Here you can just say "load all JAR files from this directory as plug-ins" and "add all plug-ins from the current classpath". You can then query for plug-ins using a variety of methods. It seems very simple to use, it uses pojos and pure interfaces, and plug-ins themselves are made just by implementing the interface and adding some annotations.
JSPF also seems to work on Android, though the discovery system is somewhat dysfunctional, and you need to list all of the plug-in classes explicitly (http://code.google.com/p/jspf/wiki/RunningOnAndroid). This should be okay, we just need to have an additional implementation for Android that lists the necessary plug-ins for the basic functionality. I don't see it as a problem if some of the extensibility is missing on Android.
Other frameworks that have been considered:
- ServiceLoader class + startup scripting. Simple, built-in, but we
- JPF (http://jpf.sourceforge.net/), seems more customizable and
- OSGi (http://en.wikipedia.org/wiki/OSGi), even more heavy-weight
- Java Module System (JSR 277), slated for inclusion to Java 7, but
General operation:
The name for each plugin will correspond to an item in the plugins menu. Subitems of each item in the plugins menu will be automatically generated as follows:
- About plugin : makes an about box, present for all plugins.
- for each 'enableable' modifier, a check box of the form [X] Enable ModifierName will be generated. When enabled, the enable method of the modifier will be called. This would then do what is necessary to modify OR to always run the plugin code, for example: make the simulation always load the simulation modifier.
- for each 'configurable' modifier, an item which opens the configuration window
- any additional menu items as defined in each modifier. For example, a rocket modifier might have an item which changes the selected component in some way.
interface Plugin: - name, version, URI, date, author, licence, description - list of dependent plugin URI's and versions - list of conflicting plugin URI's and versions - list of modifiers
abstract class AbstractPlugin implements Plugin: * everything required for loading, setting menu, translations etc - getSetting(key), setSetting(key, value) : a simple mechanism for locally storing various settings - getFile(name), storeFile(file), rmfile(name) : a simple mechanism for locally storing cache files etc
static class MyPlugin extends AbstractPlugin: * the users implementation
files: messages_?.properties : translations to use, inside plugin jar
interface Modifier: - plugin this modifier is a member of - enableable boolean - enable(), disable() - configurable boolean - configurator - additional menu items and actions
abstract class RocketModifier implements Modifier: - enable(), disable() : - getSelectedComponent() : returns currently selected rocket component - onChange() : called when a component is changed * various other helper methods as necessary
static class MyRocketModifier: * the users implementation of something that works with or modifies the rocket design
abstract class SimulationModifier implements Modifier: * basically everything currently in simulation listeners, possibly simplified (do we need 3 separate interfaces?)
static class MySimulationModifier extends AbstractSimulationModifier: * the users implementation
abstract class configurator: a class which automatically generates a standardised configuration dialog box based on just a simple list of variables and selectors. Variables would be saved automatically when the OK button is clicked using plugin setSettings().