General Modularity Example Module Projects & Files Commands & Scripting
Windows Menus Charts Tables Buttons & tools
Trees and Taxa Characters & Models Documentation General Utilities
Introduction The module's source code Employing other modules Menus
Commands & snapshots Automatic documentation generation Windows

An example module: making and using menus

(updated August 2005)

see menus

This source code may not be the latest version. Check the newest source code in mesquite.examples.BabyTreeWindow


package mesquite.examples.BabyTreeWindow;

import java.applet.*;
import java.awt.*;
import mesquite.lib.*;
import mesquite.lib.duties.*;

/*========================================*/
/*A simple example module that displays a tree window that depends on a tree in a standard tree window*/
public class BabyTreeWindow extends TreeWindowAssistantN {
    DrawTreeCoordinator treeDrawCoordTask;
    NumberForTree numberTask;
    BTreeWindow bTreeWindow;
    
    /*--------------------------------------*/
    /*The basic substitute for a constructor for modules  (overrides method of MesquiteModule)*/
    public boolean startJob(String arguments, Object condition, CommandRecord commandRec, boolean hiredByName) {
        treeDrawCoordTask= (DrawTreeCoordinator)hireEmployee(commandRec, DrawTreeCoordinator.class, null);
        if (treeDrawCoordTask == null)
            return false;
        numberTask= (NumberForTree)hireEmployee(commandRec, NumberForTree.class, "Number to calculate");
        /* A call to makeMenu causes a menu to appear in the menu bar for this module.
        Here, a menu named Baby will appear.  This menu will contain all of the menu items
        of this module, as well as the menu items of any employee modules (up until an
        employee module that has its own menu or window).  [Secondary menus for a 
        module can also be created as "auxiliary" menus.]
        Note: One should not use the standard Java calls to make menus.  The calls
        to makeMenu, addMenuItem, addSubmenu and so on do not directly make Java menu items,
        but rather make specifications for building menu items.  One reason for doing this is that
        some of these menu items need to appear in the menu bars of more than one window.
        makeMenu("Baby");


        The method addSubmenu is one of several to add menu items.  Others include
        addMenuItem, addItemToSubmenu, and addCheckMenuItem.  Generally each is passed
        the menu in which the item is to be added, the label of the menu item, and
        a command to be executed if the menu item is selected.  Here, the menu is listed
        as null, which signals to Mesquite that it can choose the most appropriate place.
        (Because this module has defined its own menu named "Baby", the submenu will
        appear there.)  The command passed has the name "setNumberTask", and is directed
        at this module.  This version of addSubmenu is also passed a subclass of
        MesquiteModule (in this case, NumberForTree.class).  In response, Mesquite 
        fills the submenu with a list of available modules of that subclass.
        When the user selects an item in the submenu, Mesquite sends the command
        "setNumberTask" to this module, passing as an argument the name of the submenu item
        selected, that is the name of the module.  As can be seen below, this module
        responds to the command by hiring that chosen module as the new calculator
        of the number for the tree.
        addSubmenu(null, "Number to calculate", makeCommand("setNumberTask",  this), NumberForTree.class);


        /* Here a menu item is requested that is merely a separator line.  The second
        parameter, passed as null, would be a Mesquite Command were the menu item to be
        used.*/
        addMenuItem( "-", null);
        bTreeWindow= new BTreeWindow( this, treeDrawCoordTask, numberTask);
        setModuleWindow(bTreeWindow);
        if (!commandRec.scripting())
             bTreeWindow.setVisible(true);
        /* Because calls to add menus and menu items in Mesquite don't instantly
        add real menu items, but rather create menu specifications, means that at some
        point a request must be made to update all of the real menus using the
        new specifications.  resetAllMenuBars does that; it redoes all menu bars for
        all of the windows.  It is a bit heavy handed here given that the only reason 
        to update the menu bar for most windows is for the Windows menu to show
        the new Baby Tree Window as an option.  (a method resetWindowsMenus
        is planned for the future.)  This method does not necessarily update the
        menu bars instantly, because that could cause multiple updates unnecessarily.
        (The methods incrementMenuResetSuppression() and decrementMenuResetSuppression()
        control when the menu bars are updated.) */
        resetAllMenuBars();
        return true;
    }

    /*--------------------------------------*/
    /*A method necessary with modules of subclass TreeWindowAssistantN; allows standard tree window
    on which this module depends to indicate tree has changed  (overrides method of TreeWindowAssistantN)*/
    public void setTree(Tree tree, CommandRecord commandRec) {
        bTreeWindow.setTree(tree, commandRec);
    }
    /*--------------------------------------*/
    /*Makes the module shut down when the go-away box of the window is touched  (overrides method of MesquiteModule)*/
     public void windowGoAway(MesquiteWindow whichWindow) {
        whichWindow.hide();
        whichWindow.dispose();
        iQuit();
    }
    /*--------------------------------------*/
    /*Returns the snapshot necessary to get this module back to the current state.  Note that it incorporates
      a snapshot from its window  (overrides method of MesquiteModule)*/
    public Snapshot getSnapshot(MesquiteFile file) {
        if (bTreeWindow ==null)
           return null;
        Snapshot fromWindow = bTreeWindow.getSnapshot(file);
        if (fromWindow == null || fromWindow.getNumLines() ==0)
            return null;
        Snapshot sn = new Snapshot();
        sn.addLine("getWindow");
        sn.addLine("tell It");
        sn.incorporate(fromWindow, true);
        sn.addLine("endTell");
        sn.addLine("getTreeDrawCoordinator", treeDrawCoordTask);
        sn.addLine("setNumberTask", numberTask);
        sn.addLine("showWindow");
        return sn;
    }
    /*--------------------------------------*/
    /*The standard method for Commandable interface; receives commands either for snapshotting purposes
      or from menu actions  (overrides method of MesquiteModule)*/
    public Object doCommand(String commandName, String arguments, CommandRecord commandRec, CommandChecker checker) {
        if (checker.compare(this.getClass(), "Returns the module serving as the window's draw tree coordinator", null, commandName, "getTreeDrawCoordinator"))
            return treeDrawCoordTask;
        /* Here the command "setNumberTask" is received.  It may be coming either
        from a script (note its use in the Snapshot above) or by the user choosing
        a menu item in the Number to Calculate submenu.  The module responds by
        attempting to hire the module indicated in the command's arguments */
        else if (checker.compare(this.getClass(), "Sets which module class should calculate a number for the tree", "[name of module]", commandName, "setNumberTask")) {
            NumberForTree temp= (NumberForTree)replaceEmployee(commandRec, NumberForTree.class, arguments, null, numberTask);
            if (temp!=null) {
                numberTask = temp;
                bTreeWindow.setNumberTask(numberTask, commandRec);
                resetContainingMenuBar();
                return numberTask;
            }
        }
        else 
            return super.doCommand(commandName, arguments, commandRec, checker);
        return null;
    }
    /*--------------------------------------*/
    /*Receives message from employees that their parameters have changed an recalculation may be needed  (overrides method of MesquiteModule)*/
    public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, CommandRecord commandRec) {
        if (employee== numberTask)
            bTreeWindow.recalculate(commandRec);
    }
    /*--------------------------------------*/
    /*Indicates to the name of this module for purposes of menu listings and documentation.  (overrides method of MesquiteModule)*/
    public String getName() {
        return "Baby Tree Window";
    }
    /*--------------------------------------*/
    /*Returns the version of this module.  (overrides method of MesquiteModule)*/
    public String getVersion() {
        return "0.9";
    }
    /*--------------------------------------*/
    /*Returns an explanation of what the module does.  (overrides method of MesquiteModule)*/
    public String getExplanation() {
        return "Displays a single tree (the same as in a tree window)." ;
    }
    /*--------------------------------------*/
    /*Returns the authors of the module.  (overrides method of MesquiteModule)*/
    public String getAuthors() {
        return "Wayne Maddison";
    }
}
    
/*========================================*/
/*The window (Frame) itself shown on the screen, containing a tree that is the same as the one in the standard tree window*/
public class BTreeWindow extends MesquiteWindow  {
    TreeDisplay treeDisplay;
    DrawTreeCoordinator treeDrawCoordTask;
    TextField p;
    MesquiteNumber num = new MesquiteNumber();
    NumberForTree numberTask;
    Tree tree;
    
    public BTreeWindow (BabyTreeWindow ownerModule, DrawTreeCoordinator treeDrawCoordTask, NumberForTree numberTask){
        super(ownerModule, true); 
        this.treeDrawCoordTask = treeDrawCoordTask;
        this.numberTask = numberTask;
        setWindowSize(500,400);
        setBackground(Color.white);
        p = new TextField();
        p.setBackground(Color.yellow);
        addToWindow(p);
        resetTitle();
    }
    /*--------------------------------------*/
    /* Used to get the title for window (overrides abstract method of MesquiteWindow)*/
    public void resetTitle(){
        setTitle("Baby Tree Window"); 
    }
    /*--------------------------------------*/
    /* Resize the tree display and other components.*/
    public void sizeDisplays(){
        if (treeDisplay==null) return;
        int totalWidth = getWidth();
        int totalHeight = getHeight() - 30;
        treeDisplay.setSize(totalWidth,totalHeight);
        treeDisplay.setFieldSize(totalWidth,totalHeight);
        if (p!=null)
            p.setBounds(0,totalHeight, totalWidth, 30);
    }
    /*--------------------------------------*/
    /*Sets the tree to be shown in the window.*/
    public void setTree(Tree newTree, CommandRecord commandRec){
        if (treeDisplay == null) {
            Taxa taxa = newTree.getTaxa();
            treeDisplay =treeDrawCoordTask.createOneTreeDisplay(taxa, this); 
            addToWindow(treeDisplay);
            treeDisplay.setLocation(0,0);
            sizeDisplays();
        }
        
        if (treeDisplay.getTree()!=null)
            treeDisplay.getTree().dispose();
        if (newTree!=null) {
            tree = newTree.cloneTree();
            treeDrawCoordTask.setTreeOfOneDisplay(tree);
            recalculate(commandRec);
            treeDisplay.suppressDrawing(false);
            treeDisplay.setVisible(true);
            treeDisplay.repaint();
        }
    }
    /*--------------------------------------*/
    /*Sets what module is to be used for calculating the number for the tree*/
    public void setNumberTask(NumberForTree numTask, CommandRecord commandRec){
        numberTask = numTask;
        recalculate(commandRec);
    }
    /*--------------------------------------*/
    /*Recalculates the number for the tree*/
    public void recalculate(CommandRecord commandRec){
        if (numberTask!=null && tree !=null){
            numberTask.calculateNumber(tree, num, commandRec);
            p.setText(numberTask.getName() + " " + num);
        }
        else
            p.setText("");
    }
    /*--------------------------------------*/
    /*Sets the size of the window (setSize and setBounds should not be used!!!>  (overrides method of MesquiteWindow)*/
    public void setWindowSize(int w, int h){
        super.setWindowSize(w,h);
        sizeDisplays();
    }
    /*--------------------------------------*/
    /* Called when the window has been resized, e.g. by user. (overrides method of MesquiteWindow)*/
    public void windowResized(){
        sizeDisplays();
    }
    /*--------------------------------------*/
    /*Disposes of the window*/
    public void dispose(){
        if (treeDisplay!=null){
            if (treeDisplay.getTree()!=null)
                treeDisplay.getTree().dispose();
            treeDisplay.dispose();
        }
        super.dispose();
    }
}


© W. Maddison & D. Maddison 2000-2005