Capture a snapshot of the active View/Editor in a RCP application

Screenshot tools are nice, no doubt, but they are still a brake in the workflow. Meanwhile, it’s necessary to activate the screenshot application, take a snapshot of the requested part, edit the image to paste it into OpenOffice/LibreOffice or Microsoft Word. Is there no easier way? Can’t we use a toolbar extension to capture and store an image of the active view/editor automatically in the system clipboard? Yes, we can! The feature will be also part of the next OpenChrom release (0.5.0 “Martin”) coming soon in October 2011!

First of all, we need to retrieve the active shell:

Display display = Display.getCurrent();
Shell shell = display.getActiveShell();
parseComposites(shell);

Afterwards, let’s check each composite and sub controls, if one of them is activated:

private void parseComposites(Shell shell) {

  Control[] controls = shell.getChildren();
  exitloop:
  for(Control control : controls) {
    if(control instanceof Composite) {
      Composite composite = (Composite)control;
      if(findActivePartCompositeAndTakeSnapshot(composite)) {
        break exitloop;
      }
    }
  }
}

If the actual composite contains an activated control, take a snapshot.

private boolean findActivePartCompositeAndTakeSnapshot(Composite composite) {

  boolean isSnapshot = false;
  if(checkNextComposite(composite)) {
    Control[] controls = composite.getChildren();
    for(Control control : controls) {
      if(control instanceof Composite) {
        Composite nextComposite = (Composite)control;
        isSnapshot = findActivePartCompositeAndTakeSnapshot(nextComposite);
      }
    }
  } else {
    copyCompositeToClipboard(composite);
    isSnapshot = true;
  }
  return isSnapshot;
}

Otherwise check the next composite in the same way.

private boolean checkNextComposite(Composite composite) {

  boolean checkNextComposite = true;
  Composite parent = composite.getParent();
  if(parent != null) {
    Object object = parent.getData();
    if(object instanceof ContributionInfo) {
      ContributionInfo contributionInfo = (ContributionInfo)object;
      if(viewOrEditorIsFocused(composite, contributionInfo)) {
        checkNextComposite = false;
      }
    }
  }
  return checkNextComposite;
}

But how do we determine if the selected composite is a view or an editor instead of being something else? Each “view” and “editor” has an element type entry, which can be retrieved by the contribution info object of the parent composite of the tested composite.

private boolean viewOrEditorIsFocused(Composite composite, ContributionInfo contributionInfo) {

  boolean isFocused = false;
  String elementType = contributionInfo.getElementType();
  if(elementType.equals("view") || elementType.equals("editor")) {
    if(compositeOrSubcomponentIsFocused(composite)) {
      isFocused = true;
    }
  }
  return isFocused;
}

If the composite is a view or an editor, check if one of its subcontrols is focused.

private boolean compositeOrSubcomponentIsFocused(Control control) {

  boolean isFocused = false;
  if(control.isFocusControl()) {
    isFocused = true;
  } else {
    if(control instanceof Composite) {
      Control[] controls = ((Composite)control).getChildren();
      exitloop:
      for(Control controlx : controls) {
        if(compositeOrSubcomponentIsFocused(controlx)) {
          isFocused = true;
          break exitloop;
        }
      }
    }
  }
  return isFocused;
}

If yes, copy the composite to the clipboard and show a message.

private void copyCompositeToClipboard(Composite composite) {

  String message;
  Image image = getImage(composite);
  if(image == null) {
    message = "The focus of the selected view/editor couldn't be retrieved.";
  } else {
    ImageTransfer imageTransfer = ImageTransfer.getInstance();
    Object[] data = new Object[]{image.getImageData()};
    Transfer[] dataTypes = new Transfer[]{imageTransfer};
    clipboard.setContents(data, dataTypes);
    message = "The selected view/editor has been copied to clipboard.";
  }
  openMessageBox(message);
}

The clipboard has been still initialized in the constructor of the class.

public class CreateSnapshot extends AbstractHandler {

  private Clipboard clipboard;

  public CreateSnapshot() {

    clipboard = new Clipboard(Display.getDefault());
  }

An image of the composite can be retrieved by using the gc.copyArea() method:

private Image getImage(Composite composite) {

  GC gc = null;
  Image image = null;
  Display display = Display.getCurrent();
  try {
    gc = new GC(composite);
    image = new Image(display, composite.getBounds());
    gc.copyArea(image, 0, 0);
  } finally {
    if(gc != null) {
      gc.dispose();
    }
  }
  return image;
}

The message box informs the user in case of a success or failure.

private void openMessageBox(String message) {

  Display display = Display.getCurrent();
  String text = "Copy Selection To Clipboard";
  Shell shell = display.getActiveShell();
  MessageBox messageBox = new MessageBox(shell, SWT.NONE);
  messageBox.setText(text);
  messageBox.setMessage(message);
  messageBox.open();
}

The result looks for example like this:

The class can be viewed here:

http://openchrom.git.sourceforge.net/git/gitweb.cgi?p=openchrom/openchrom;a=blob;f=openchrom/plugins/net.openchrom.chromatogram.msd.ui.perspective/src/net/openchrom/chromatogram/msd/ui/perspective/handlers/CreateSnapshot.java;h=4ba8262d404874bfbc0cbc29f778b3049fe49759;hb=refs/heads/develop

About Philip Wenig

Founder of OpenChrom
This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to Capture a snapshot of the active View/Editor in a RCP application

  1. Pingback: Blog bookmarks 08/19/2011 « My Diigo bookmarks

  2. philk says:

    Nice one! Could come in handy sometime. Could also imagine to combine it with my “CopyTo” eclipse extension to post screenshots of the current active view to image hosters.

  3. Nabab says:

    Hello there, I know this is an old post but I would be very interested in getting the full code of this.
    Sadly the link you posted is now dead, could you send the full classes to me please ? Or post it again ?
    Thank you very much for your site anyway.

  4. Philip Wenig says:

    Hi Nabab,

    please keep in mind that OpenChrom is a big framework. In case you’d like to build OpenChrom from scratch, please follow the developer guideline:
    https://wiki.openchrom.net/index.php/Development

Leave a comment