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.
"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. |
IGB Context Menu
package org.lorainelab.igb.menu.api; import java.util.List; import java.util.Optional; import org.lorainelab.igb.menu.api.model.AnnotationContextEvent; import org.lorainelab.igb.menu.api.model.ContextMenuItem; public interface AnnotationContextMenuProvider { public Optional<List<ContextMenuItem>> buildMenuItem(AnnotationContextEvent event); } |
package org.lorainelab.igb.menu.api.model; import com.affymetrix.genometry.symmetry.impl.SeqSymmetry; import java.util.List; public class AnnotationContextEvent { private final List<SeqSymmetry> selectedItems; public AnnotationContextEvent(List<SeqSymmetry> selectedItems) { this.selectedItems = selectedItems; } public List<SeqSymmetry> getSelectedItems() { return selectedItems; } } |
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; } } |
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
package org.lorainelab.igb.menu.api.model; public enum ContextMenuSection { INFORMATION, SEQUENCE, APP, UI_ACTION; } |
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.menu.api.AnnotationContextMenuProvider; import org.lorainelab.igb.menu.api.model.AnnotationContextEvent; import org.lorainelab.igb.menu.api.model.ContextMenuItem; import org.lorainelab.igb.menu.api.model.ContextMenuSection; import org.lorainelab.igb.menu.api.model.MenuIcon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(immediate = true) public class ContextMenuExtension implements AnnotationContextMenuProvider { private static final Logger LOG = LoggerFactory.getLogger(ContextMenuExtension.class); private static final String ICONPATH = "terminal.png"; @Override public Optional<List<ContextMenuItem>> buildMenuItem(AnnotationContextEvent event) { ContextMenuItem contextMenuItem = new ContextMenuItem("Log Selection ids", (Void t) -> { event.getSelectedItems().stream().map(selectedSym -> selectedSym.getID()).forEach(LOG::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)); } } |
<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> <goals> <goal> index </goal> </goals> <phase>package</phase> <configuration> <obrRepository>${project.build.directory}</obrRepository> <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
# 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.api.quickstart; import aQute.bnd.annotation.component.Component; import java.io.InputStream; import java.util.Optional; import org.lorainelab.igb.context.menu.AnnotationContextMenuProvider; import org.lorainelab.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 */ @Component(immediate = true) public class ContextMenuExtension implements AnnotationContextMenuProvider { private static final Logger logger = LoggerFactory.getLogger(ContextMenuExtension.class); private static final String ICONPATH = "terminal.png"; @Override public Optional<ContextMenuItem> buildMenuItem(AnnotationContextEvent event) { ContextMenuItem contextMenuItem = new ContextMenuItem("Log Selection ids", (Void t) -> { event.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 MenuSection getMenuSection() { return MenuSection.INFORMATION; } } ``` |
mvn clean install |