Software and Science

A blog on Metabolomics, Algorithms, and Software Development.

Creating screenshots of running applications is often required for tutorials and user guides. However, creating resolution independent screenshots is not always easy, especially for a complete application window.

Provided functionality

The NetBeans SVG screenshot plugin adds a globally enabled action that draws the currently visible content to an SVG-enabled canvas using the Apache Batik library.

Bitmap graphics within the application are embedded in the resulting xml file using Base64 encoding. They are not scalable. Embeddable TTF fonts are automatically embedded into the resulting svg for later editing.

Implementation

The current implementation is provided by an action registered using NetBeans’ action annotations:

1
2
3
4
5
6
7
8
9
10
@ActionID(category = "Window",
    id = "net.nilshoffmann.svg.actions.SvgScreenshot"
)
@ActionRegistration(displayName = "#CTL_SvgScreenshot")
@ActionReferences({
    //only register this action with a keyboard shortcut
    @ActionReference(path = "Shortcuts", name = "D-F10")
})
@Messages("CTL_SvgScreenshot=Svg Screenshot")
public final class SvgScreenshot implements ActionListener {

The action is run on the currently active window component of the application, if the action is enabled.

1
2
3
//retrieve the active window component
KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Window window = keyboardFocusManager.getActiveWindow();

It is easy to only save the contents of a child component of the containment hierarchy in a Swing-based application using the drop-in Batik Graphics2D replacement. It has to be passed to the method of interest (either paint or print), following these instructions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//set up the svg canvas and xml document
DOMImplementation impl
        = getDOMImplementation();
String svgNS = "http://www.w3.org/2000/svg";
Document document = impl.createDocument(svgNS, "svg", null);
SVGGeneratorContext ctx = createDefault(document);
//embed fonts used to render the UI
ctx.setEmbeddedFontsOn(true);
//add image handler to embed images (not scale invariant)
GenericImageHandler ihandler = new CachedImageHandlerBase64Encoder();
ctx.setGenericImageHandler(ihandler);
SVGGraphics2D g2d = new SVGGraphics2D(ctx, true);
//make sure everything is up to date
window.invalidate();
window.revalidate();

There are some additional options available, but the most prominent one allows to either use the paint or print methods to paint the components onto the SVGGraphics2D graphics context.

1
2
3
4
5
6
7
switch (paintMode) {
    case PRINT:
        window.print(g2d);
        break;
    default:
        window.paint(g2d);
}

The plugin provides an options panel to select the paint method, to set the output folder where screenshots are saved, and to selecte whether the svg file should be gzip compressed.

Known Issues

Due to the way NetBeans handles and activates Actions per Dialog and Window, the global keyboard shortcut is currently only active if the main window has the focus. Thus, it is currently not possible to create screenshots of the options and plugin management dialogs, as well as all other modal dialogs. If you are aware of any method to accomplish that functionality, please feel free to provide a hint or pull request for your changes.

The default Swing widgets seem to do fine when they are rendered to the svg canvas, however, some special widgets seem to have problems with an over-eager clipping. This can be seen when the NetBeans StartPage TopComponent is saved to svg, chopping of some parts within its layout.

Availability

The plugin is available from the NetBeans plugin page, while the source code is available at GitHub. Contributions are welcome!