Custom Tools

This documentation is for an unreleased (still in testing) version of Cornerstone Tools. Until it is released, its API may experience frequent breaking changes. The current stable release can be found here.

This guide will give you an overview of creating a new Tool. This is applicable for Tools being built within the library as well as Tools for 3rd party plugins. For the specifics on setting up a Tool for a plugin, check the third party tool guide.

Choosing A Base Class

There are 3 base classes to choose from when building a tool:

BaseTool

The BaseTool is the fundamental base class, with just the functionality required to function within the Cornerstone Tools framework. This is the base class to choose if the Tool you wish to create won't have its own annotation data (.e.g MagnifyTool), or only interacts with a different Tool's data (e.g. FreehandMouseSculpterTool). The other two base classes BaseAnnotationTool and BaseBrushTool both inherit from BaseTool.

BaseAnnotationTool

The BaseAnnotationTool inherits from BaseTool, and is intended for any Tool that will create/modify and display its own annotation data on the canvas (e.g. LengthTool).

BaseBrushTool

The BaseBrushTool inherits from BaseTool and is intended specifically for Tools that want to create/modify/delete segmentation data (e.g. BrushTool). Potential subclasses could include adaptive brush Tools, or region growing Tools that require a seed area to be drawn.

Creating Your Tool

Once you have an appropriate base class chosen (we will use the BaseTool in this example), you can extend it to start building your Tool. In this example we shall make a Tool that logs 'Hello cornerstoneTools!' to the console on every mouse click.

Class Definition

By convention the class name should be in PascalCase, and suffixed with:

  • Tool - If it supports both mouse and touch input.
  • MouseTool - If it only supports mouse input.
  • TouchTool - If it only supports touch input.

For example, our example is going to support mouse, so we shall call it the HelloWorldMouseTool:

import external from './../externalModules.js';
import BaseTool from './../base/BaseTool.js';

export default class HelloWorldMouseTool extends BaseTool {
  constructor (name = 'HelloWorldMouse') {
    super({
      name,
      supportedInteractionTypes: ['mouse']
    });
  }
}

The constructor must call super(), which passes an object to the constructor of the superclass (BaseTool, in this case, but the same object is passed to BaseAnnotationTool or BaseBrushTool). The object passed may have the following properties:

Property Requirement description
name Mandatory The name of the Tool.
supportedInteractionTypes Mandatory An array of strings listing the interaction types, mouse and/or touch.
strategies Optional If your Tool has multiple strategies of operation, you may pass an array of functions for each strategy here (see the RotateTool for a good example).
defaultStrategy Optional If you have multiple strategies, this one should be used by default (pass a string identical to the strategy function name).
configuration Optional An object with configurable properties used by your Tool. It may include your Tool's sensitivity, how an annotation displays when rendered, etc.
mixins Optional An array of mixins (commonly used behaviours/functionality) to add to the Tool.

For our simple Tool we pass only the two mandatory fields to super. For the Tool's own constructor, it must at minimum take name as a parameter, and it must have a default value. By convention the default name is the same as the classname, minus the Tool suffix.

Adding Mixins

Next you can add any mixins you wish to add the Tool. These are passed to super, and initialized in BaseTool. For our example, our Tool only makes sense in Active or Disabled modes, as it has none of its own data, and logs 'Hello cornerstoneTools!' on click, as such we shall include the activeOrDisabledBinaryTool mixin:

import external from './../externalModules.js';
import BaseTool from './../base/BaseTool.js';

export default class HelloWorldMouseTool extends BaseTool {
  constructor (name = 'HelloWorldMouse') {
    super({
      name,
      supportedInteractionTypes: ['mouse'],
      mixins: [
        'activeOrDisabledBinaryTool'
      ]
    });
  }
}

You need not import any mixins to your class file; this is dealt with in BaseTool.

Mode Change Callbacks

In the Cornerstone Tools framework, if a Tool changes mode, an appropriate callback is called if the Tool has one. These are, quite simply:

  • Active - activeCallback (element)
  • Passive - passiveCallback (element)
  • Enabled - enabledCallback (element)
  • Disabled - enabledCallback (element)

Note that unlike a lot of the Tools, the element on which the Tool resides is passed to the callback, not evt.

For our example Tool, this gives us more chances to log hello to the console:

import external from './../externalModules.js';
import BaseTool from './../base/BaseTool.js';

export default class HelloWorldMouseTool extends BaseTool {
  constructor (name = 'HelloWorldMouse') {
    super({
      name,
      supportedInteractionTypes: ['mouse'],
      mixins: [
        'activeOrDisabledBinaryTool'
      ]
    });
  }

  activeCallback (element) {
    console.log(`Hello element ${element.uuid}!`);
  }

  disabledCallback (element) {
    console.log(`Goodbye element ${element.uuid}!`);
  }
}

Event Dispatcher Callbacks

Here we can add the meat of our Tool. Event dispatchers check for methods on Tools and fire them when appropriate.

TODO: List them all?? Or just link to api? Not sure yet. TODO: An actual useful description.

For our Tool we want to log to the console on mouse click. BaseTool has two appropriate methods: preMouseDownCallback and postMouseDownCallback. These fire before or after other annotation data on the canvas has a chance to claim the mouse click. for our Tool we shall choose preMouseDownCallback, as it's always nice to say hello before doing anything else. The method can simply be defined and it shall be called when appropriate via the mouseToolEventDispatcher:

import BaseTool from './../base/BaseTool.js';

export default class HelloWorldMouseTool extends BaseTool {
  constructor (name = 'HelloWorldMouse') {
    super({
      name,
      supportedInteractionTypes: ['mouse'],
      mixins: [
        'activeOrDisabledBinaryTool'
      ]
    });
  }

  preMouseDownCallback (evt) {
    console.log('Hello cornerstoneTools!');
  }

  activeCallback (element) {
    console.log(`Hello element ${element.uuid}!`);
  }

  disabledCallback (element) {
    console.log(`Goodbye element ${element.uuid}!`);
  }
}

results matching ""

    No results matching ""