Skip to content

Latest commit

 

History

History
402 lines (274 loc) · 10.8 KB

PLUGIN_GUIDE.md

File metadata and controls

402 lines (274 loc) · 10.8 KB

Plugin guide

Incomplete and not reliable yet!

List of contents

Intro

Boomega allows you to develop plugins in order to add more features/functionality to the app.
Plugins can be written in both java and kotlin.

The recommended language for writing plugins is kotlin because most of the Plugin API entities are written in it. This guide will provide you both kotlin and java examples tough.

You can view the loaded plugins and their impact on the app. Read about the plugin manager in the user guide.

How is it work?

On the JVM (Java Virtual Machine) it's possible to load classes dynamically at runtime with the help of Class Loaders.
Since Boomega is a JVM application, it takes full advantage of this.

The plugin directory

Boomega automatically loads plugin archives (.jars) from the default plugin directory.

  • Path on Windows: %APPDATA%\Dansoftware\boomega\plugin
  • Path on Linux & macOS: <User directory>/boomega/plugin

If you want to load your plugin into Boomega, you should place the jar file into this directory.

You can open the plugin directory from the Boomega menu-bar: File > Open plugin directory

API overview

The root of the Boomega plugin hierarchy is: com.dansoftware.boomega.plugin.api.BoomegaPlugin .

All other plugin classes should implement this interface.

BoomegaPlugin subtypes:

The DisabledPlugin annotation:

The @DisabledPlugin annotation can be used for preventing Boomega to load a plugin class.

Example:

Kotlin Java
@DisabledPlugin // make Boomega ignore this plugin
class MonokaiThemePlugin : ThemePlugin {
    ...
}
@DisabledPlugin // make Boomega ignore this plugin
public class MonokaiThemePlugin implements ThemePlugin {
    ...
}

Plugin lifecycle

When the application starts running, it searches for all BoomegaPlugin implementations and instantiates them. Every plugin class will be instantiated only once during the application lifetime, meaning they behave practically as singletons. After a BoomegaPlugin is instantiated, Boomega invokes the init() method on it. When the application shuts down, the destroy() method is invoked on the plugin instance.

Required plugin metadata

Every BoomegaPlugin should provide this information:

  • name: String - defines the plugin's name
  • author: Person - information about the plugin's author
  • version: String - defines the plugin's version
  • Optional: icon: Image - the plugin's icon (as a JavaFX image)

Example:

Kotlin Java
class MonokaiThemePlugin : ThemePlugin {

  // General BoomegaPlugin meta-data
  override val name: String = "Mononokai Theme Plugin"
  override val author = Person(firstName = "FirstName", lastName = "LastName", "myemail@example.com")
  override val version: String = "1.0.0"
  override val description: String? = "Adds a Monokai Theme scheme."

  ...
}
public class MonokaiThemePlugin implements ThemePlugin {
  
  @Override
  public @NotNull String getName() {
        return "Monokai Theme Plugin";
  }
  
  @Override
  public @NotNull Person getAuthor() {
        return new Person("LastName", "FirstName", "myemail@example.com");
  }
  
  @Override
  public @NotNull String getVersion() {
        return "1.0.0";
  }
  
  @Override
  public @Nullable String getDescription() {
        return "Adds a Monokai Theme scheme.";
  }
  
  ...
}

Setting up a plugin project

Requirements:

Including the plugin-kit dependency

Not available yet

Running test application

For testing your plugins in action, you can run a test application instance easily.

Not available yet

Building your archive

If your plugin project doesn't include additional dependencies, you can use the basic gradle jar task.

Handling dependencies

If your plugin requires dependencies, you might use an additional gradle plugin like Shadow for building a fat jar. But in this case you have to make sure that the fat jar doesn't include the Boomega (plugin-kit) binaries, because it might reduce performance when Boomega loads the plugin.

An alternative solution is to simply place the dependency jars also into the plugin directory.

Note: Don't include dependencies already present in Boomega itself.
You can view the dependencies used by Boomega in the acknowledgements.

Plugin development tutorials & examples

Language plugins

Before we start, make sure you have read the language guide that helps you understand the basic concepts.

The LanguagePlugin interface

To make your LanguagePack recognized by Boomega you have to supply it in your LanguagePlugin implementation:

Kotlin Java
class PortugueseLanguagePlugin : LanguagePlugin {

    ...
  
    // Here you have to return your LanguagePack
    override val languagePack get() = PortugueseLanguagePack()
  
}
public class PortugueseLanguagePlugin implements LanguagePlugin {

    ...
    
    @NotNull
    @Override
    public LanguagePack getLanguagePack() {
        return new PortugueseLanguagePack();
    }
    
}

Theme plugins

Before we start, make sure you have read the theme guide that helps you understand the basic concepts.

The ThemePlugin interface

To make Boomega recognize your theme, you have to implement the ThemePlugin interface and provide your previously created Theme.

Kotlin Java
class NordThemePlugin : ThemePlugin {
    ...
    
    // Here, you have to return your instantiated theme
    override val theme get() = NordTheme()
}
public class NordThemePlugin implements ThemePlugin {
    ...
    
    @NotNull
    @Override
    public Theme getTheme() {
        // Here, you have to return your instantiated theme
        return new NordTheme();
    }
}

Module plugins

Read the ui module guide before you go forward.

The ModulePlugin interface

To make Boomega recognize the plugin, you have to implement the ModulePlugin interface where you supply your newly created Module:

Kotlin Java
class HelloModule : ModulePlugin {
    // Here you have to supply your module's instance
    override fun getModule(context: Context, database: Database): Module = HelloModule()
}
public class HelloModule extends ModulePlugin {
    @NotNull
    @Override
    public Module getModule(@NotNull Context context, @NotNull Database database) {
        // Here you have to supply your module's instance
        return new HelloModule();
    }
}

You might have noticed that the getModule method takes two arguments:

  • context: Context - you can use it for interacting with the UI (making alerts, notifications, etc..)
  • database: Database - the object can be used to communicate with the opened database; might be just read-only

If your module doesn't need these, you can simply ignore them.

Record exporting plugins

Read the record export guide before you go forward.

The RecordExporterPlugin interface

If you want to add your record-exporter through a plugin, you have to implement the RecordExporterPlugin interface.

Example plugin

Look at the txt-table-export-plugin, a record export plugin allows to export records into text tables.

Database provider plugins

Read the databases guide before you continue.

Documentation in progress