IJC Plugin tutorial - MyAddField plugin

    Overview

    This tutorial will introduce you to the basics of IJC plugin development and using Instant JChem APIs. It will walk you step by step through the process of creating 'Add Field' IJC plugin included in IJC API Examples suite.

    In this tutorial we expect that you have made yourself familiar with the development tools and set up your environment as it is described in IJC Plugin Quick Start and IJC Hello World Plugin tutorials. If you haven't done so, we strongly recommend you to read these two tutorials first before you proceed with the 'Add Field' plugin tutorial.

    During this tutorial we are going to create our own version of the 'Add Field' plugin, which is available as part of IJC API Examples suite. This gives you chance to choose how exactly you want to follow this tutorial. You can either recreate the plugin step by step as described here or you can use this tutorial as a guide for exploring the 'Instant JChem API Examples - Add Field' project that you have downloaded as part of api-examples-suite in IJC Plugin Quick Start tutorial.

    By the end of this tutorial, you will understand the basic process of creating new extensions for IJC and you will also have been introduced to various resources that you can use to further develop your knowledge and skill in extending IJC. In particular, in this tutorial you will learn the following:

    • How to add a context-aware menu item and toolbar button

    • How to create and open new dialogs

    • How to create new fields in a JChem table

    • How to read data from a JChem table

    • How to write data to a JChem table

    • How to use asynchronous tasks running in the background

    Contents:

    Exploring 'Add Field' plugin example

    Before we begin creating our module, let's look at the sample that we will build in this tutorial. Once we have tried it out, we will know for ourselves what the result of this tutorial will be.

    1. Start api-examples-suite project as described in IJC Plugin Quick Start

    1. In the started Instant JChem create a new IJC project by going to the main menu File -> New Project... and choosing General -> IJC Project (local database with demo data) in the 'New Project' wizard.

    1. In the 'Projects' explorer open localdb -> Pubchem demo -> Pubchem tabular form view.

    1. Now, add the atom count field by selecting the Add Atom count field menu item in the main menu Help -> API Examples.

    1. You should now see the new Atom Count field added to the JChem table.

    Note: In this tutorial, you will learn, among many other things, how to create a progress bar to enable asynchronous tasks to run in the background, so that the user interface remains enabled while the field is being added to the table. In this tutorial we are going to implement the same functionality from scratch.

    Creating 'MyAddField' plugin

    If you followed the IJC Hello World Plugin tutorial you should have 'IJC Extensions' module suite and 'HelloWorldPlugin' module already available. Open 'IJC Extensions' suite project in NetBeans IDE, we will add a new module to it.

    In your IDE go to main menu File -> New Project... and create a new NetBeans Modules -> Module project. Call the project MyAddFieldPlugin and don't forget to add it to IJC-Extensions module suite. As the module's 'Code Name Base' enter org.myplugin.myaddfieldplugin.

    Setting up module libraries

    Our next step is to specify which APIs we want to use. Each API is provided by a module. Some of the APIs belong to the NetBeans API, while others belong to the Instant JChem API. Because our module is deployed to Instant JChem (ie. 'IJC Platform' that we set up earlier), which itself makes use of all NetBeans and Instant JChem APIs that we need, we can simply just set dependencies on modules available in 'IJC Platform'.

    1. In 'Projects' explorer r-click the MyAddFieldPlugin project's node and in the popup menu choose Properties. The 'Project Properties' dialog will appear.

    1. In the 'Project Properties' dialog go to Libraries -> Module Dependencies and click Add Dependency... button to specify modules that 'MyAddFieldPlugin' module will use.

    1. In the 'Add Module Dependency' dialog choose the modules shown here:

    <img src="images/download/attachments/1802771/add-dependencies.png" alt="images/download/attachments/1802771/add-dependencies.png"/>

    1. Click OK button and close the 'Properties' dialog by OK button as well.

    Creating the Context-Aware Toolbar Button and Menu Item

    In this section, we use the 'New Action' wizard to create a menu item and toolbar button that will be context-aware, which means that they will only be enabled when needed. In this tutorial's scenario, the menu item and toolbar button will only be enabled when a table, also known as an 'entity', is selected in IJC. Once we have completed the wizard, we will have a skeleton "action", which the user will be able to invoke either from the menu item or from the toolbar button, if enabled. Later on we will fill out this action with additional functionality needed for this module.

    1. Right-click the module project node in the 'Projects' explorer and choose New -> Action.

    1. In the first panel, specify that you want to create a Conditionally Enabled action that will be sensitive to 'EntityCookie', which represent tables in IJC. Type com.im.ijc.core.api.cookie.EntityCookie into 'Cookie Class' field as shown here:

    <img src="images/download/attachments/1802771/add-action1.png"/>
    
    Click `Next` button.

    1. In the next panel, specify that the action will appear in the Edit menu and in the Edit toolbar, as shown below:

    <img src="images/download/attachments/1802771/add-action2.png"/>
    
    Click `Next` button.

    1. In the final panel, type AddAtomCountFieldAction in 'Class Name' field. Type Add Atom Count Field in 'Display Name' field.

    Click `Browse...` button for action's icon. Browse to a 16x16 pixel icon, which will be displayed in the toolbar button. If there is a 24x24 pixel icon with the same name scheme, the IDE will recognize it. For example, if the first icon is named 'icon-16.png', the IDE will assume the second icon is named 'icon-24.png'. Ideally, you will have a small icon (16x16 pixels) and a large icon (24x24 pixels) available. If not, here are two icons that you can use for this purpose these icons: <img src="images/download/attachments/1802771/icon-16.png"/> <img src="images/download/attachments/1802771/icon-24.png"/>
    
    You should now see the following configuration:
    
    <img src="images/download/attachments/1802771/add-action3.png"/>    

    1. Click Finish button.

    The wizard creates a new 'AddAtomCountFieldAction' class. In addition, the icons are copied into the module. You should see the action class in NetBeans 'Projects' explorer:

    As you can see the action class and its parent nodes are marked with the red error badge. This indicates that something is broken in the class. Let's open the class and examine it. You will notice that the line referring to EntityCookie is underlined in red, which means that the java compiler does not know EntityCookie class. In this case, we need to add an import statement for the EntityCookie. Right-click in the editor and choose Fix Imports (Ctrl-Shift-I). The IDE adds the import statement and the red underline disappears:

    Examining the Generated Code

    Before launching the generated action, let's examine the artifacts that the 'New Action' wizard generated for us. The generated action class looks as follows:

    package org.myplugin.myaddfieldplugin;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import org.openide.awt.ActionID;
    import org.openide.awt.ActionReference;
    import org.openide.awt.ActionReferences;
    import org.openide.awt.ActionRegistration;
    import org.openide.util.NbBundle.Messages;
    
    import com.im.ijc.core.api.cookie.EntityCookie;
    
    @ActionID(
            category = "Edit",
            id = "org.myplugin.myaddfieldplugin.AddAtomCountFieldAction"
    )
    @ActionRegistration(
            iconBase = "org/myplugin/myaddfieldplugin/icon-16.png",
            displayName = "/display/lts-neon/instant-jchem_ijc-plugin-tutorial-myaddfield-plugin.md#CTL_AddAtomCountFieldAction"
    )
    @ActionReferences({
        @ActionReference(path = "Menu/Edit", position = 1500, separatorBefore = 1450),
        @ActionReference(path = "Toolbars/Edit", position = 600)
    })
    @Messages("CTL_AddAtomCountFieldAction=Add Atom Count Field")
    public final class AddAtomCountFieldAction implements ActionListener {
    
        private final EntityCookie context;
    
        public AddAtomCountFieldAction(EntityCookie context) {
            this.context = context;
        }
    
        @Override
        public void actionPerformed(ActionEvent ev) {
            // TODO use context
        }
    }

    Let's put a dummy message inside actionPerformed method to see if it works. Edit the method like this:

        @Override
        public void actionPerformed(ActionEvent ev) {
            javax.swing.JOptionPane.showMessageDialog(null, "This is AddAtomCountFieldAction!");
        }

    Save the changes (Ctrl + S).

    Running the Module

    We can now try out the module and see if the action works. The action's menu item and toolbar button should be enabled and disabled depending on what is selected in Instant JChem.

    1. Right-click the MyAddFieldPlugin project's node and choose Run. The IDE will deploy the plugin and start Instant JChem. You should see the action's toolbar button and also the Add Atom Count Field menu item in the main menu Edit.

    1. Open an IJC project or create a new one if you don't have any (use localdb with demo data).

    1. In the IJC project open Pubchem demo -> Pubchem grid view and both the toolbar button and the menu item for our action should become enabled.

    <img src="images/download/attachments/1802771/enabled.png"/>

    1. If you click the action, message box appears:

    <img src="images/download/attachments/1802771/message.png"/>

    1. If you click back to Instant JChems 'Projects' explorer and select its 'Pubchem demo' -> 'Pubchem grid view' node the button and the menu item will become disabled. This is because the selected node does not provide the EntityCookie while the opened 'Pubchem grid view' editor provides this cookie.

    Coding AddAtomCountFieldAction

    Currently performAction() method displays simple message. Let's open com.im.ijc.examples.addfield.AddAtomCountFieldAction from api-examples-suite. Examine the code and compare it with ours AddAtomCountFieldAction generated above. Start in performAction() method. The code creates new field (by using asynchronous tasks running in background). The 'field' means in IJC's case is a database column in the specified entity, which is a database table. Then it invokes a method that fills all the rows with data. If you code the action the same way as the action in API Examples is, then run it upon opened 'Pubchem grid view', you should see new column in the gridview called 'Atom count' and fill with values.

    Trying Out the Plugin

    1. Run the module again, as described in Running the Module.

    1. Make sure 'Pubchem grid view' is open in the editor area.

    1. Click the new toolbar button or invoke Edit -> Add Atom Count Field menu item. It will add a new field called "Atom Count" to 'Pubchem demo' entity and will fill it with the actual atoms count for each structure.

    Note: In the bottom right corner of the screenshot above there is a progress bar there that lets asynchronous tasks running in background give feedback to users. The user interface remains enabled while the field is being added and filled with data.

    Conclusion

    Congratulations! You have successfully completed an IJC plugin that adds a new field to an existing entity and fills it with the atom count for each structure in the entity. In this tutorial you have learned:

    • How to create a conditionally enabled action and install it in Instant JChem's UI.

    • How to find an existing structure field in an IJC entity.

    • How to add a new field to an existing entity

    • How to read data from and write data to fields in an entity.

    • How to create a background task and use the progress bar to give a user feedback about the task's progress.

    For other IJC plugin development related tutorials please see their complete list here.