The goal of this quickstart is to introduce you to the the context menu api, so you will be able to add context menu extensions in your IGB Apps.
- Clone the quickstart project
Info |
---|
|
"A context menu (also called contextual, shortcut, and popup or pop-up menu) is a menu in a graphical user interface (GUI) that appears upon user interaction, such as a right-click mouse operation. A context menu offers a limited set of choices that are available in the current state, or context, of the operating system or application. Usually the available choices are actions related to the selected object. |
Image Added
IGB Context Menu
Image Added
Image Added
...
Image Added
Image Removed
Code Block |
---|
|
package org.lorainelab.igb.context.menumenu.api;
import java.util.List;
import java.util.Optional;
import org.lorainelab.igb.contextmenu.menuapi.model.AnnotationContextEvent;
import org.lorainelab.igb.contextmenu.menuapi.model.ContextMenuItem;
/**
*
* @author dcnorris
*/
public interface AnnotationContextMenuProvider {public interface AnnotationContextMenuProvider {
public Optional<ContextMenuItem>Optional<List<ContextMenuItem>> buildMenuItem(AnnotationContextEvent event);
public MenuSection getMenuSection();
}}
|
Code Block |
---|
|
package org.lorainelab.igb.contextmenu.menuapi.model;
import com.affymetrix.genometry.symmetry.impl.SeqSymmetry;
import java.util.List;
/**
*
* @author dcnorris
*/
public class AnnotationContextEvent {
private final List<SeqSymmetry> selectedItems;
public AnnotationContextEvent(List<SeqSymmetry> selectedItems) {
this.selectedItems = selectedItems;
}
public List<SeqSymmetry> getSelectedItems() {
return selectedItems;
}
}
|
Code Block |
---|
|
package org.lorainelab.igb.menu.api.model;
import java.util.Set;
import java.util.function.Function;
public class ContextMenuItem extends MenuItem {
private ContextMenuSection menuSection = ContextMenuSection.APP;
public ContextMenuItem(String menuLabel, Set<MenuItem> subMenuItems) {
super(menuLabel, subMenuItems);
}
public ContextMenuItem(String menuLabel, Function<Void, Void> action) {
super(menuLabel, action);
}
public void setMenuSection(ContextMenuSection menuSection) {
this.menuSection = menuSection;
}
public ContextMenuSection getMenuSection() {
return menuSection;
}
}
|
Code Block |
---|
|
package org.lorainelab.igb.menu.api.model;
import com.google.common.io.BaseEncoding;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MenuIcon {
private String encodedImage;
private static final Logger logger = LoggerFactory.getLogger(MenuIcon.class);
public MenuIcon(InputStream resourceAsStream) {
try {
encodedImage = BaseEncoding.base64().encode(IOUtils.toByteArray(resourceAsStream));
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
public byte[] getEncodedImage() {
return BaseEncoding.base64().decode(encodedImage);
}
}
|
ContextMenuSection
Code Block |
---|
|
package org.lorainelab.igb.menu.api.model;
public enum ContextMenuSection {
INFORMATION,
SEQUENCE,
APP,
UI_ACTION;
}
|
Image Added
Code Block |
---|
|
package org.lorainelab.igb.context.menu.api.quickstart;
import aQute.bnd.annotation.component.Component;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.lorainelab.igb.contextmenu.menuapi.AnnotationContextMenuProvider;
import org.lorainelab.igb.context.menu.MenuSectionmenu.api.model.AnnotationContextEvent;
import org.lorainelab.igb.menu.api.model.ContextMenuItem;
import org.lorainelab.igb.contextmenu.menuapi.model.AnnotationContextEventContextMenuSection;
import org.lorainelab.igb.contextmenu.menuapi.model.ContextMenuItemMenuIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author dcnorris
*/
@Component(immediate = true)
public class ContextMenuExtension implements AnnotationContextMenuProvider {
private static final Logger loggerLOG = LoggerFactory.getLogger(ContextMenuExtension.class);
private static final String ICONPATH = "terminal.png";
@Override
public Optional<ContextMenuItem>Optional<List<ContextMenuItem>> buildMenuItem(AnnotationContextEvent event) {
ContextMenuItem contextMenuItem = new ContextMenuItem("Log Selection ids", (Void t) -> {
event.getSelectedItems().stream().map(selectedSym -> selectedSym.getID()).forEach(loggerLOG::info);
return t;
});
try (InputStream resourceAsStream = ContextMenuExtension.class.getClassLoader().getResourceAsStream(ICONPATH)) {
contextMenuItem.setMenuIcon(new MenuIcon(resourceAsStream));
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
}
contextMenuItem.setMenuSection(ContextMenuSection.INFORMATION);
return Optional.ofNullable(Arrays.asList(contextMenuItem));
}
}
|
Code Block |
---|
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.lorainelab.igb</groupId>
<artifactId>igb-project</artifactId>
<version>9.0.0</version>
</parent>
<groupId>org.lorainelab.igb</groupId>
<artifactId>org.lorainelab.igb.menu.api.quickstart</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<name>Context Menu Extension Quickstart</name>
<dependencies>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bndlib</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.lorainelab.igb</groupId>
<artifactId>genometry</artifactId>
<scope>provided</scope>
</dependency>
<!--Start of logging dependencies-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<!--End of logging dependencies-->
<dependency>
<groupId>org.lorainelab.igb</groupId>
<artifactId>org.lorainelab.igb.menu.api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>build plugin repository</id>
@Override
public MenuSection getMenuSection() {
<goals>
<goal>
index
</goal>
</goals>
<phase>package</phase>
<configuration>
<obrRepository>${project.build.directory}</obrRepository>
return MenuSection.INFORMATION;
}
}
|
Code Block |
---|
|
<mavenRepository>${project.build.directory}</mavenRepository>
</configuration>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Import-Package>*</Import-Package>
<Export-Package/>
<Service-Component>*</Service-Component>
<Bundle-Description>${bundleDescription}</Bundle-Description>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.lorainelab</groupId>
<artifactId>bundle-markdown-encoder</artifactId>
<executions>
<execution>
<goals>
<goal>encodeMarkdown</goal>
</goals>
</execution>
</executions>
<configuration>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
|
Add a README.md markdown file to the root of the project for a customized APP manager display of your new app.
Example
Code Block |
---|
|
# Context Menu API Quickstart
A small example context menu extension that logs the ids of all selected SeqSymmetry objects
```java
package org.lorainelab.igb.context.menu.modelapi.quickstart;
import comaQute.googlebnd.commonannotation.iocomponent.BaseEncodingComponent;
import java.io.InputStream;
import java.util.Optional;
import org.lorainelab.igb.context.menu.AnnotationContextMenuProvider;
import org.apache.commons.io.IOUtilslorainelab.igb.context.menu.MenuSection;
import org.lorainelab.igb.context.menu.model.AnnotationContextEvent;
import org.lorainelab.igb.context.menu.model.ContextMenuItem;
import org.lorainelab.igb.context.menu.model.MenuIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author dcnorris
*/
public@Component(immediate class MenuIcon {
private String encodedImage;= true)
public class ContextMenuExtension implements AnnotationContextMenuProvider {
private static final Logger logger = LoggerFactory.getLogger(MenuIconContextMenuExtension.class);
private static final String public MenuIcon(InputStream resourceAsStreamICONPATH = "terminal.png";
@Override
public Optional<ContextMenuItem> buildMenuItem(AnnotationContextEvent event) {
tryContextMenuItem contextMenuItem = new ContextMenuItem("Log Selection ids", (Void t) -> {
encodedImage = BaseEncoding.base64().encode(IOUtils.toByteArrayevent.getSelectedItems().stream().map(selectedSym -> selectedSym.getID()).forEach(logger::info);
return t;
});
try (InputStream resourceAsStream = ContextMenuExtension.class.getClassLoader().getResourceAsStream(ICONPATH)) {
contextMenuItem.setMenuIcon(new MenuIcon(resourceAsStream));
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return Optional.ofNullable(contextMenuItem);
}
@Override
public byte[]MenuSection getEncodedImagegetMenuSection() {
return BaseEncoding.base64().decode(encodedImage)MenuSection.INFORMATION;
}
}
```
|
- Navigate to the root of the project (e.g. the cloned repository https://bitbucket.org/lorainelab/context-menu-api-quickstart.git)
- use maven to build the project
Code Block |
---|
mvn clean install |
- The build process will result in a new folder being added into your project directory (i.e. the target folder)
- Add the target directory as a new IGB App repository
- IGB App Manger Tab -> Launch App Manager -> Manage Repositories -> Add...
- Image Added
- Image Added
- Select and add the target directory
- Use the IGB App Manager to Install the new plugin
- Image Added
Image Added