User commands in OpenAstexViewer

OpenAstexViewer provides support for extending the scripting language with arbitrary commands. This document covers an example of this.

If the command part of a scripting command is not recognized a class file of that name is search for. If this is found an instance is created using reflection, and the static method handleCommand is called with a reference to the MoleculeViewer, the MoleculeRenderer and the argument list.

The command can do quite complicated things. The example below creates an instance of itself which is a subclass of GraphicalObject. This starts a thread which will animate the renderer. The object steps through the atoms that were passed as part of the command, and draws a green sphere in turn at the position of each atom.

The command would be used something like

animated -name calpha -atoms { atom CA };

Note the '{' and '}' characters that enclose the atom selection. These are important for the parser in commands that have arbitrary argument lists.

// Source code for the class animated
import astex.*;

public class animated extends GraphicalObject implements Runnable {
    /** The MoleculeRenderer we will animate. */
    public MoleculeRenderer moleculeRenderer = null;

    /** The atoms. */
    public DynamicArray atoms = null;

    /** The step we are on. */
    public int step = 0;

    /** The Thread that animates us. */
    public Thread thread = null;

    /** Handle a command. */
    public static void handleCommand(MoleculeViewer mv,
                                     MoleculeRenderer mr,
                                     Arguments args){

        if(args.defined("-atoms")){
            animated animationObject = new animated();

            animationObject.atoms = (DynamicArray)args.get("-atoms");

            String name = args.getString("-name", "animationObject");

            animationObject.setName(name);

            animationObject.moleculeRenderer = mr;

            mr.renderer.addTmesh(animationObject);

            animationObject.thread = new Thread(animationObject);

            animationObject.thread.start();
        }else{
            System.out.println("animated: no atoms specified");
        }
    }

    /** Extend the render method. */
    public void render(){
        Renderer renderer = getRenderer();

        // if we get deleted, our Renderer will get set to null
        // and we should stop the thread
        if(renderer == null){
            thread.stop();
            return;
        }

        if(atoms != null){
            Atom atom = (Atom)atoms.get(step);

            renderer.drawSphere(atom.x, atom.y, atom.z, 2.0, Color32.green, 128);
        }
    }

    /** Implement the Runnable interface. */
    public void run(){
        while(true){
            if(atoms != null){
                if(step >= atoms.size()){
                    step = 0;
                }

                moleculeRenderer.repaint();

                step++;
            }

            try {
                Thread.sleep(2000);
            }catch(InterruptedException e){
            }
        }
    }
}

AstexViewer™ Copyright (C) 1999-2007 Astex Therapeutics Ltd.
OpenAstexViewer Copyright (C) 2007-2017 Mike Hartshorn