Changes between Version 34 and Version 35 of DevelopersGuide/DevelopingPlugins


Ignore:
Timestamp:
2009-11-08T12:39:24+01:00 (16 years ago)
Author:
Gubaer
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DevelopersGuide/DevelopingPlugins

    v34 v35  
     1= Developing Plugins =
     2
    13This page gives a short introduction for developers how to create, deploy and develop plugins for JOSM.
    2 Any Questions left? Ask Frederick Ramm (or g'ol'[mailto:immanuel.scholz@gmx.de Imi], although he's a bit outdated).
     4Any Questions left? Ask Dirk Stöcker.
    35
    4 [[PageOutline]]
     6[[TOC(inline)]]
    57
    6 
    7 = Setting up the environment =
     8== Setting up the environment ==
    89
    910 * Check out the plugin environment into an empty directory called {{{josm}}}
     
    1718 * If you need other OSM resources you can check out the complete osm - trunk: {{{svn co http://svn.openstreetmap.org/}}}
    1819
    19 = The ''Plugin'' class =
     20== The ''Plugin'' class ==
    2021After setting everything up, you need to create the plugin main class specified in the jar's manifest. The only prerequisite of this class is, that it must have a standard constructor taking no arguments. The constructor of the plugin class will be called during the JOSM startup if the plugin is registered. Here, you have full access to the object tree within JOSM.
    2122
     
    2425The required minimum in naming is one individual part in the path structure of you plugin class names. The path of the base class is used to detect the source of exceptions. So when you base class is my.example.class.MyPlugin, then "my.example.class" is used to detect your plugin code. All important parts of your plugin should use that and also it should be unique for the plugin (i.e. add at least one part with the name of your plugin).
    2526
    26 = Callbacks =
     27== Callbacks ==
    2728Most of your plugin work will probably be tweaking the JOSM object tree at startup time, but there are a few callbacks that get automatically called on every plugin (whether you subclass Plugin or not, just the signature matters).
    2829
    29 == mapFrameInitialized ==
     30=== mapFrameInitialized ===
    3031This is called after the first data has been loaded and the mapFrame is initialized. Use this to change something on the new MapFrame (or more common: the MapView (THE map ;) behind the frame)- As example, you could add yourself as LayerChangeListener to newMapFrame.mapView (please don't forget to remove yourself from oldMapFrame, if newMapFrame is null). This way you can capture changes of the active layer or the addition/removal of layers.
    3132
    32 == getPreferenceSetting ==
     33=== getPreferenceSetting ===
    3334This will be called to retrieve an creator for GUI elements for the preferences dialog. The return is an interface with two methods: one to add the GUI elements to the dialog and on that is called when the preferences dialog finishes with ok. Be sure not to write preferences in your GUI code, but remember settings and only write them in the ok() method.
    3435
    35 == addDownloadSelection ==
     36=== addDownloadSelection ===
    3637This will be called whenever the user pops up the download dialog. The download dialog is prepared by first assembling a list of objects implementing the DownloadSelection interface, and after that giving each of them, via a call to their addGui method, the chance of adding a tab to the download dialog's tabpane. The DownloadSelection interface also has a method that is called by the download dialog if one of the other tabs changes the bounding box, and in turn the GUI elements created by addGui are expected to call boundingBoxChanged on the download dialog if they want to communicate a change to other tabs.
    3738The name addDownloadSelection is not 100% accurate as a plugin is also allowed to modify the existing list of DownloadSelection objects. For example, a plugin might want to replace the existing Bookmark handler; it can do so by finding the BookmarkSelection object in the list passed to addDownloadSelection and remove it.
    3839 
    39 = Some tips about the JOSM object tree or ''What is where?'' =
     40== Some tips about the JOSM object tree or ''What is where?'' ==
     41The initial JOSM author preferred public fields in Java classes over public methods, including public getters and setters. He justified this decision as follows:
     42
    4043''First some words about my style of accessing public variables. Most people find this annoying and bad coding style in Java. If this would be an enterprise project, where most of the code is glue code and had to work with objects in a generic way, I would agree with them. But as JOSM is not, I like to keep the classes as simple as possible, which includes, that I don't add standard getter/setter but make the variable public. Also, there are no or very few so-called ''singleton-factories'' in JOSM that became popular in the past years. I use to reference singleton objects as global statics. This is unusual but equivalent to having stuff like Dependency Injection or Factory Methods (except you want to make complex things like auto-distributing stuff as seen in some enterprise programs).''
    4144
    42 Most objects are accessible through the class org.openstreetmap.josm.Main. There are numerous entry points for various parts of JOSM here.
     45Most of the current JOSM authors don't follow this approach and in 2008 and 2009 large parts of the JOSM code base have been refactored in order to improve the maintenability and stability of the code. In particular, this holds for the [source:/trunk/src/org/openstreetmap/josm/data/osm data classes]. In plugins, you're encouraged to follow the well-established principles of encapsulation and information hiding, too.
    4346
    44 == Main.parent ==
     47There are still a couple of global objects accessible through [source:/trunk/src/org/openstreetmap/josm/Main Main], though.
     48
     49=== Main.parent ===
    4550This is the parent of all GUI elements. Use this as first parameter to JOptionPane.show* if you want to popup a message.
    4651
    47 == Main.pref ==
     52=== Main.pref ===
    4853This is the (ONLY!) access to the global preferences file, located in .josm/preferences. Use Main.pref.get(...) and Main.pref.put(...) to access the preferences. They will be saved immediately after a put, so don't put anything you dont want to have there ;).
    4954
    5055Please, prefix custom plugin preferences with your plugin name.
    5156
    52 == Main.ds ==
    53 The data layer of the current edit layer, which is usually the current selected layer in the layer list.
    54 
    55 == Main.proj ==
     57=== Main.proj ===
    5658If you want to translate between Lat/Lon and East/North, use Main.proj.latlon2eastnorth and Main.proj.eastnorth2latlon.
    5759
    58 == Main.map.mapView ==
     60=== Main.map.mapView ===
    5961This is the GUI class of the map. You usually access this to call stuff like getCenter, getScale or zoomTo.
    6062
    6163''BEWARE'': Main.map can be null, in which case no data is loaded yet.
    6264
    63 == Main.main.editLayer() ==
    64 Call this to get the current OsmDataLayer. If there is no such layer, an empty will be created, so you never get null returned from this.
     65=== Main.main.editLayer() ===
     66Call this to get the current OsmDataLayer. If there is no such layer, null is returned.
    6567
    66 == Plugin.getPluginDir() and Plugin.copy() ==
     68=== Plugin.getPluginDir() and Plugin.copy() ===
    6769If you subclass from the plugin class (see above), then you can call this functions to get your plugin directory or copy data into your plugin directory. This is a directory where you can freely store/read data from. It is located at ~/.josm/plugins/''youpluginname''.
    6870
    69 
    70 = The MANIFEST.MF =
     71== The MANIFEST.MF ==
    7172
    7273You have to put some information into the manifest file of your jar. If you use ant, you can set these values within the build.xml file.
    7374
    74  '''Plugin-Class''' ''(required)''::
    75    Points to the main plugin file
    76  '''Plugin-Description''' ''(required)''::
    77    Gives the description of the plugin visible in the preferences page. For line breaks, you have to use <br>, ''not'' <br/> (blame Swing ;).
    78  '''Author'''::
    79    An Email-Adress of the author of this plugin. This is used in the error report window, if an error is detected within the plugin code.
    80  '''Plugin-Date'''::
    81    The creation date of the plugin in ISO format.
    82  '''Plugin-Early'''::
    83    Can be set to {{{true}}}, in which case the plugin is loaded as early as possible, more specific before the GUI classes are loaded. This is usefull if your plugin alters the GUI or the JOSM-startup process in any way.
    84  '''Plugin-Link'''::
    85    Informational URL to a webpage or other information source about that plugin. Is also used in the [wiki:Plugins plugins] information page.
    86  '''Plugin-Requires'''::
    87    A list of other plugins which are required before plugin works. The list is separated by semi colons.
    88  '''Plugin-Stage'''::
    89    An number of the order relative to other plugins, when the plugin is loaded. Smaller numbers gets loaded first, so if you have conflicts with other plugins, you can increase or decrease this number to get some control on the loading order. Defaults to 50.
    90  '''Plugin-Version'''::
    91    Just mapped to the string PluginInformation.version. Use this as example to pass versioning informations to other plugins.
    92  '''Class-Path'''::
    93    An space-seperated list of additional classpaths your plugin wants to use when looking for ressources and classes. The plugin itself is added automatically. Don't forget to provide the additional jar's as well, if you add dependencies here. Note that all loaded plugins are in the class-path automatically, so don't specify plugin-dependencies here.
    94  '''<xxx>_Plugin-Url'''::
    95    To support older JOSM version special entries may be added to supply older versions. This information is used by the internal plugin handler to select only matching version when updating. The entries are made like this ''<josm_version>_Plugin-Url: <plugin_version>;<url>''
    96    * '''josm_version''' is the minimum version of JOSM this plugin works with,
    97    * '''plugin_version''' is the version of this plugin and
    98    * '''url''' is the link to the download.
    99  '''<lang>_Plugin-Description'''::
    100    The translated description text for the plugin. E.g. ''de_Plugin-Description'' contains the German translation.
     75||'''Plugin-Mainversion'''||required|| The lowest JOSM versison required by this plugin.||
     76||'''Plugin-Version'''||required||The SVN revision of the plugin SVN repository the plugin was built against||
     77||'''Plugin-Class'''||required||Points to the main class of the plugin||
     78||'''Plugin-Description'''||required||Gives the description of the plugin visible in the preferences page. For line breaks, you have to use {{{<br>}}}, ''not'' {{{<br/>}}}||
     79||'''Author'''||optional|| The name and or email address of the author of this plugin. This is used in the error report window, if an error is detected within the plugin code.||
     80||'''Plugin-Date'''||optional||The creation date of the plugin in ISO format.||
     81||'''Plugin-Early'''||optional||Can be set to {{{true}}}, in which case the plugin is loaded as early as possible, more specific before the GUI classes are loaded. This is usefull if your plugin alters the GUI or the JOSM-startup process in any way.||
     82||'''Plugin-Link'''||optional||Informational URL to a webpage or other information source about that plugin. Is also used in the [wiki:Plugins plugins] information page.||
     83||'''Plugin-Requires'''||optional||A list of other plugins which are required before plugin works. The list is separated by semi colons.||
     84||'''Plugin-Stage'''||optional||An number of the order relative to other plugins, when the plugin is loaded. Smaller numbers gets loaded first, so if you have conflicts with other plugins, you can increase or decrease this number to get some control on the loading order. Defaults to 50.||
     85||'''Class-Path'''||optional||An space-seperated list of additional classpaths your plugin wants to use when looking for ressources and classes. The plugin itself is added automatically. Don't forget to provide the additional jar's as well, if you add dependencies here. Note that all loaded plugins are in the class-path automatically, so don't specify plugin-dependencies here.||
     86||'''<xxx>_Plugin-Url'''||optional||To support older JOSM version special entries may be added to supply older versions. This information is used by the internal plugin handler to select only matching version when updating. The entries are made like this ''<josm_version>_Plugin-Url: <plugin_version>;<url>''||
     87|| '''<lang>_Plugin-Description'''||optional||The translated description text for the plugin. E.g. ''de_Plugin-Description'' contains the German translation.||
    10188
    10289For SVN managed plugins, the links to old versions and the translation texts are automatically added to the [http://josm.openstreetmap.de/plugin plugin information], so JOSM can use that in plugin dialog.
    10390
    104 = Updating the plugin =
     91== Updating a plugin ==
    10592
    10693You have found a bug in a plugin and you are able to fix it. Then your next steps are:
    107   1. check for an existing JOSM trac-ticket
    108   1. improve the source of the plugin
    109   1. check the new dependencies and change the ''Plugin-Mainversion'' in the ''build.xml'' if needed
    110   1. compile the plugin in your environment
    111   1. test it
    112   1. commit the changes of the source to the OSM SVN (edited files get new revision)
    113   1. compile the plugin again (with the new SVN revision number)
    114   1. update the ''.jar'' file in the ''dist'' directory
    115 Ready. The new plugin version will be send out to all JOSM users while there next update.
    11694
    117 = Legal stuff (Imis opinion) =
     95'''Fixing the bug'''
     96  1. fix the bug in the plugin, compile it, run it locally in JOSM, and test it
     97
     98'''Publishing the new plugin'''
     99  1. Did you change something which will not work with every JOSM version? Then you should update '''Plugin-Mainversion''' in {{{build.xml}}}
     100     * look for the line {{{<attribute name="Plugin-Mainversion" value="..."/>}}}
     101     * replace the value by the lowest JOSM version required for the plugin after you've applied your fix [[BR]]Do not increase '''Plugin-Mainversion''' if not necessary, though. If you do, JOSM ''requires'' users to update to the new version, otherwise users can ''choose'' whether they want to upgrade. {{{Plugin-Mainversion}}} should always consist of the ''lowest possible revision''.
     102  1. commit the new modified source
     103  1. '''counter intuitive, but important - update again from the SVN''' - after having commited you '''must''' update the source again from the SVN. This ensures that {{{Plugin-Version}}} in the plugin {{{MANIFEST}}} will reflect the plugins SVN revision number
     104  1. build the plugin using {{{ant clean}}} and {{{ant dist}}}. This creates the plugin jar file in the {{{/dist}}} directory.
     105  1. commit the {{{.jar}}} file in the {{{dist}}} directory
     106
     107'''Closing trac ticket'''
     108  1. Did you fix the bug based on a trac ticket? Please close it and leave a note. You can refer to the new plugin version using the macro {{{[o12345]}}}, where 12345 is a plugin revision number.
     109
     110Ready. The new plugin version is now available. If necessary, JOSM asks users to upgrade to the new version, when JOSM is started up.
     111
     112The steps describe above can be automated, see [http://svn.openstreetmap.org/applications/editors/josm/plugins/tageditor/build.xml build.xml of the tageditor plugin]. It includes an ant target {{{publish}}}.
     113
     114
     115== Legal stuff (Imis opinion) ==
    118116
    119117Just because I have been asked: JOSM is licensed under GPL and if any code is a "derived work" of JOSM, then it has to be under GPL too. It is my believe, that any JOSM-Plugin is a derived work of JOSM, so GPL is the only possible license for a JOSM-Plugin. If you want to include non-GPL code into a plugin, it has to be seperated from the classes that use JOSM. "Use" as in "import org.openstreetmap.josm...". See the 'Class-Path' - MANIFEST.MF attribute for a way to include other jar files.