It's possible to create plug-ins for jGnash. So you can add a new functionality or a new report, without recompile the whole software. There's a folder in jGnash installation directory called "plugins", in this folder you can add a JAR file containing the new plug-in and next time you start jGnash, it will load your plug-in.
Requirements to build a new plug-in
For build a new plug-in you will need Java programing knowledge, and some specifics thing depending on the kind of functionalities that you are trying to extend. For building new graph charts or reports, I will suggest experience related to: Java Swing, JFreeChart, DynamicJasper and JasperReports. There is not good documentation about packages and source code of jGnash, but you can download the source code and will find is not hard to read, also you will find help on email lists.
According to jGnash help menu, these are the external libraries they use, so could be good also know a little bit about them: args4j, db4o, JasperReports, DynamicJasper, JFreeChart, JGoodies Animation, JGoodies Forms, JGoodies Looks, Apache MINA, XStream and SwingX.
I like Eclipse IDE, so I will use it, but any Java IDE should be good.
Of course, you must have installed jGnash, to link the jars files to your new plugin project.
Architecture
jGnash provides a plug-in system that is easy to understand. The jgnash2.jar provides a interface called: jgnash.plugin.Plugin and a abstract class called: jgnash.plugin.AbstractEnabledAction, to create a new plugin, inside the new plugin jar, just implement the Plugin interface and extend the AbstractEnabledAction.
Also it will be needed to write a couple of lines inside the jar MANIFEST file.
Steps to create a basic plugin
1- Start a new Java Project, this is a normal Java project in Eclipse IDE.
3- Inside the project, create a new file called: MANIFEST.MF
This file must contain something similar to this:
Manifest-Version: 1.0
Plugin-Activator: myplugin.mypackage.MyPlugin
Plugin-Version: 1.0
Plugin-Activator: myplugin.mypackage.MyPlugin
Plugin-Version: 1.0
Where "Plugin-Activator:" points to the class that implements the jgnash.plugin.Plugin interface.
4- Create the Plugin implementation class, that indicate, which menus will be added to the user interface and which actions will be executed. This is a simple example:
package myplugin.mypackage;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import jgnash.plugin.Plugin;
public class MyPlugin implements Plugin{
@Override
public JMenuItem[] getMenuItems() {
JMenuItem menuItem = new JMenuItem();
menuItem.putClientProperty(Plugin.PRECEDINGMENUIDREF, "new-command");
menuItem.setAction(new MyAction());
return new JMenuItem[] { menuItem };
}
@Override
public String getName() {
return "My Plugin";
}
@Override
public JPanel getOptionsPanel() {
return null;
}
@Override
public void start() {
}
@Override
public void stop() {
}
}
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import jgnash.plugin.Plugin;
public class MyPlugin implements Plugin{
@Override
public JMenuItem[] getMenuItems() {
JMenuItem menuItem = new JMenuItem();
menuItem.putClientProperty(Plugin.PRECEDINGMENUIDREF, "new-command");
menuItem.setAction(new MyAction());
return new JMenuItem[] { menuItem };
}
@Override
public String getName() {
return "My Plugin";
}
@Override
public JPanel getOptionsPanel() {
return null;
}
@Override
public void start() {
}
@Override
public void stop() {
}
}
The line menuItem.putClientProperty(Plugin.PRECEDINGMENUIDREF, "new-command"); will tell to jGnash where to add the new menuItem, the preceding code, indicate before New Command menuItem. Other places you can choose are listed in the source code of jGnash, check this file:
/jgnash2/jgnash-resources/src/main/resources/jgnash/resource/main-frame-actions.xml
Another important line is: menuItem.setAction(new MyAction()); it says, when user clicks this menuItem execute the code inside MyAction class, that we must create later.
5- Implementing AbstractEnabledAction.
package myplugin.mypackage;
import java.awt.event.ActionEvent;
import javax.swing.Action;
import javax.swing.JOptionPane;
import jgnash.ui.actions.AbstractEnabledAction;
public class MyAction extends AbstractEnabledAction {
public MyAction(){
putValue(NAME, "Title");
putValue(Action.SHORT_DESCRIPTION, "Description");
}
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Hello World");
}
}
import java.awt.event.ActionEvent;
import javax.swing.Action;
import javax.swing.JOptionPane;
import jgnash.ui.actions.AbstractEnabledAction;
public class MyAction extends AbstractEnabledAction {
public MyAction(){
putValue(NAME, "Title");
putValue(Action.SHORT_DESCRIPTION, "Description");
}
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Hello World");
}
}
It's important to set the "NAME" and "Action.SHORT_DESCRIPTION" values, they will be shown as the title and tool tip text of the menuItem.
The actionPerformed method will be executed when the menuItem is clicked by the user, in this example will show a simple dialog window saying "Hello World".
6- Creating the jar file. In Eclipse, right click over your project, select Export, and then Jar File.
7- Copy the generated jar file inside "plugins" folder of jGnash, run jGnash and you will see the message "Hello World" when you click the new menu "Title" inside "File" menu.
Thanks to jGnash developers for this great software. My hope is that lots of jGnash plug-ins come alive to make it a better software for all.