// $Id: TinyViz.java,v 1.21.4.4 2003/09/18 22:25:47 mdwelsh Exp $ /* tab:2 * * * "Copyright (c) 2000 and The Regents of the University * of California. All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose, without fee, and without written * agreement is hereby granted, provided that the above copyright * notice and the following two paragraphs appear in all copies of * this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, * UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Authors: Phil Levis, Nelson Lee * Date: November 27, 2002 * Desc: Base GUI; plugins connect to this one * */ /** * @author Phil Levis * @author Nelson Lee */ package net.tinyos.sim; import java.awt.*; import javax.swing.*; import java.util.*; import java.io.*; import net.tinyos.sim.event.*; import java.net.URL; public class TinyViz implements SimConst { private JFrame mainFrame; private MainMenuBar menuBar; private MotePanel motePanel; private SimState simState; private SimComm simComm; private SimEventBus simEventBus; private CoordinateTransformer cT; private PluginPanel pluginPanel; private AutoRun autorun; private Vector loadedPlugins = new Vector(); private boolean run_serial_forward = true; private Hashtable options = new Hashtable(); private int pauseCount = 0; public static final Font defaultFont = new Font("Helvetica", Font.PLAIN, 10); public static final Font labelFont = new Font("Helvetica", Font.BOLD, 11); public static final Font smallFont = new Font("Helvetica", Font.PLAIN, 9); public static final Font constFont = new Font("Courier", Font.PLAIN, 9); public static final Font constBoldFont = new Font("Courier", Font.BOLD, 9); public static final Font boldFont = new Font("Helvetica", Font.BOLD, 10); public static final Color paleBlue = new Color(0x97, 0x97, 0xc8); public Frame getMainFrame() { return mainFrame; } public double getTosTime() { return Double.valueOf(menuBar.timeLabel.getText()).doubleValue(); } public SimState getSimState() { return simState; } public SimComm getSimComm() { return simComm; } public AutoRun getAutoRun() { return autorun; } public MainMenuBar getMenuBar() { return menuBar; } public SimEventBus getEventBus() { return simEventBus; } public CoordinateTransformer getCoordTransformer() { return cT; } public MotePanel getMotePanel() { return motePanel; } public PluginPanel getPluginPanel() { return pluginPanel; } public void setStatus(String s) { pluginPanel.setStatus(s); } public synchronized void pause() { pauseCount++; //System.err.println("PAUSE: "+pauseCount); if (pauseCount == 1) { simComm.pause(); menuBar.refreshPausePlayButton(); this.notifyAll(); } } public synchronized void resume() { pauseCount--; //System.err.println("RESUME: "+pauseCount); if (pauseCount <= 0) { pauseCount = 0; simComm.resume(); menuBar.refreshPausePlayButton(); this.notifyAll(); } } public synchronized boolean isPaused() { return simComm.isPaused(); } public void stop() { if (autorun != null) { autorun.stop(); autorun.join(); } //reset(); } public void setSimDelay(long delay_ms) { simComm.setSimDelay(delay_ms); } // Called by SimComm when its internal state changes void simCommUpdate() { menuBar.refreshPausePlayButton(); } public void exit(int errcode) { // Need to send command to sim to quit this.stop(); System.err.println("Goodbye!"); simComm.stop(); System.exit(errcode); } public String getOption(String optionName) { return (String)options.get(optionName); } public void setOption(String optionName, String optionVal) { options.put(optionName, optionVal); if (simEventBus != null) simEventBus.addEvent(new net.tinyos.sim.event.OptionSetEvent(optionName, optionVal)); } public void log(String msg) { if (autorun != null) autorun.log(msg); } public Enumeration getOptions() { return options.keys(); } // Reset visualization and communication state public synchronized void reset() { simComm.stop(); menuBar.refreshPausePlayButton(); simEventBus.pause(); simEventBus.clear(); simState.removeAllObjects(); motePanel.repaint(); pluginPanel.reset(); simComm.start(); menuBar.refreshPausePlayButton(); simEventBus.resume(); this.notifyAll(); } private void help() { System.err.println("TinyViz: Usage:"); System.err.println(" java -jar tinyviz.jar [options] "); System.err.println("Options:"); System.err.println(" -help\n\tPrint this help"); System.err.println(" -nosf\n\tDo not start SerialForwarder"); System.err.println(" -plugins [path]\n\tSpecify colon-delimited directories to search for plugin classes"); System.err.println(" -run \n\tRun simulation"); System.err.println(" -autorun \n\tRun in batch mode"); System.err.println(" -nolaf\n\tUse default look and feel (ugly!)"); System.err.println(" \n\tSet name=value options for plugins"); } public TinyViz(String initargs[]) throws IOException { /* Parse options */ String plugin_path = null; String autorun_exec = null; int autorun_nummotes = 1; String autorun_config = null; boolean pause_on_init = true; boolean no_lookandfeel = false; try { for (int n = 0; n < initargs.length; n++) { if (initargs[n].equals("-help")) { help(); return; } else if (initargs[n].equals("-nosf")) { run_serial_forward = false; } else if (initargs[n].equals("-plugins")) { plugin_path = initargs[n+1]; n++; } else if (initargs[n].equals("-nolaf")) { no_lookandfeel = true; } else if (initargs[n].equals("-run")) { if (autorun_config != null) throw new RuntimeException("Cannot use -run and -autorun together"); autorun_exec = initargs[n+1]; autorun_nummotes = Integer.parseInt(initargs[n+2]); pause_on_init = false; n += 2; } else if (initargs[n].equals("-autorun")) { if (autorun_exec != null) throw new RuntimeException("Cannot use -run and -autorun together"); autorun_config = initargs[n+1]; n++; pause_on_init = false; } else if (initargs[n].indexOf('-') != 0 && initargs[n].indexOf('=') != 0) { StringTokenizer st = new StringTokenizer(initargs[n],"="); String optionName = st.nextToken(); String optionValue = st.nextToken(); if (optionName == null || optionValue == null) { help(); return; } setOption(optionName, optionValue); } else { help(); return; } } } catch (Exception e) { System.err.println("Got exception parsing arguments: "+e); help(); return; } if (autorun_exec != null) { autorun = new AutoRun(this, autorun_exec, autorun_nummotes); } else if (autorun_config != null) { autorun = new AutoRun(this, autorun_config); } /* Set up look and feel */ if (!no_lookandfeel) { try { //UIManager.setLookAndFeel("com.oyoaha.swing.plaf.oyoaha.OyoahaLookAndFeel"); Class oclass = Class.forName("com.oyoaha.swing.plaf.oyoaha.OyoahaLookAndFeel"); Object olnf = oclass.newInstance(); URL otm_res = this.getClass().getResource("ui/slushy8.otm"); if(otm_res != null) { Class params[] = new Class[1]; params[0] = otm_res.getClass(); Object args[] = new Object[1]; args[0] = otm_res; java.lang.reflect.Method meth = oclass.getMethod("setOyoahaTheme", params); meth.invoke(olnf, args); } UIManager.setLookAndFeel((javax.swing.LookAndFeel)olnf); } catch (Exception e) { System.err.println("Got exception loading Oyoaha: "+e); System.err.println("Using default look and feel"); } } /* Create GUI */ mainFrame = new JFrame("TinyViz"); mainFrame.setFont(defaultFont); menuBar = new MainMenuBar(this); menuBar.setFont(defaultFont); mainFrame.setJMenuBar(menuBar); simEventBus = new SimEventBus(this); simState = new SimState(this); simComm = new SimComm(this, run_serial_forward, pause_on_init); cT = new CoordinateTransformer(MOTE_SCALE_WIDTH, MOTE_SCALE_HEIGHT, MOTE_PANEL_WIDTH, MOTE_PANEL_HEIGHT); motePanel = new MotePanel(this); pluginPanel = new PluginPanel(this, plugin_path); /* Finish creating GUI */ menuBar.addToolbar(); mainFrame.getContentPane().setLayout(new GridLayout(1,2)); mainFrame.getContentPane().add(motePanel); mainFrame.getContentPane().add(pluginPanel); mainFrame.pack(); mainFrame.addWindowListener(new CloseListener(this)); if (autorun != null) { mainFrame.setVisible(autorun.visible_flag); } else { mainFrame.setVisible(true); } simComm.start(); menuBar.refreshPausePlayButton(); simEventBus.start(); /* Run autorun */ if (autorun != null) { autorun.run(); exit(0); } } /** * listener to do proper cleanup on shutdown */ protected class CloseListener extends java.awt.event.WindowAdapter { TinyViz m_tv = null; public CloseListener(TinyViz parent) { m_tv = parent; } public void windowClosing(java.awt.event.WindowEvent e) { if(m_tv != null) { m_tv.stop(); } } } public static void main(String[] args) throws IOException { new TinyViz(args); } }