From e96a375e3387f2b7659df30eb4350d9ba6feeccb Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Fri, 1 Jun 2012 11:50:51 +0200 Subject: [PATCH] extracted quick help interface to a separate file, moved plugin-specific quick help from quickhelp.txt to the plugins themselves --- .../plugins/collectview/CollectView.java | 2 +- .../se/sics/cooja/mspmote/plugins/MspCLI.java | 12 ++- tools/cooja/config/quickhelp.txt | 76 ++----------------- tools/cooja/java/se/sics/cooja/GUI.java | 9 --- .../java/se/sics/cooja/HasQuickHelp.java | 38 ++++++++++ .../se/sics/cooja/plugins/LogListener.java | 49 ++++++++---- .../cooja/plugins/MoteInterfaceViewer.java | 6 +- .../se/sics/cooja/plugins/SimControl.java | 65 ++++++++++++---- .../java/se/sics/cooja/plugins/TimeLine.java | 26 ++++++- .../se/sics/cooja/plugins/Visualizer.java | 23 +++++- 10 files changed, 187 insertions(+), 119 deletions(-) create mode 100755 tools/cooja/java/se/sics/cooja/HasQuickHelp.java diff --git a/tools/cooja/apps/collect-view/java/se/sics/cooja/plugins/collectview/CollectView.java b/tools/cooja/apps/collect-view/java/se/sics/cooja/plugins/collectview/CollectView.java index a7d40a6d0..3bc18ce14 100644 --- a/tools/cooja/apps/collect-view/java/se/sics/cooja/plugins/collectview/CollectView.java +++ b/tools/cooja/apps/collect-view/java/se/sics/cooja/plugins/collectview/CollectView.java @@ -51,7 +51,7 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; -import se.sics.cooja.GUI.HasQuickHelp; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.MotePlugin; import se.sics.cooja.PluginType; diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java index 69cba5f15..cfa08dcca 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java @@ -48,6 +48,7 @@ import javax.swing.JTextField; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.MotePlugin; import se.sics.cooja.PluginType; @@ -63,7 +64,7 @@ import se.sics.mspsim.cli.LineOutputStream; @ClassDescription("Msp CLI") @PluginType(PluginType.MOTE_PLUGIN) @SupportedArguments(motes = {MspMote.class}) -public class MspCLI extends VisPlugin implements MotePlugin { +public class MspCLI extends VisPlugin implements MotePlugin, HasQuickHelp { private static final long serialVersionUID = 2833218439838209672L; @@ -222,4 +223,13 @@ public class MspCLI extends VisPlugin implements MotePlugin { return mspMote; } + public String getQuickHelp() { + return + "MSPSim's Command Line Interface" + + "

help
lists available commands" + + "

info CC2420
shows radio chip details" + + "

log CC2420 > mylog.txt
logs radio chip details to file" + + "

stacktrace
shows current stacktrace"; + } + } diff --git a/tools/cooja/config/quickhelp.txt b/tools/cooja/config/quickhelp.txt index 6822113d2..18786b82d 100644 --- a/tools/cooja/config/quickhelp.txt +++ b/tools/cooja/config/quickhelp.txt @@ -1,74 +1,3 @@ -se.sics.cooja.plugins.Visualizer = \ -Visualizer \ -

The visualizer shows the positions of simulated motes as viewed from above (XY-plane). \ -It is possible to zoom (CRTL+Mouse drag) and pan (Shift+Mouse drag) the current view. Motes can be moved by dragging them (ALT+Mouse drag). \ -Mouse right-click a mote or unoccupied space for a popup menu with more options. \ -

The visualizer supports "visualizer skins". \ -Each skin provides some specific information, such as ongoing simulated radio traffic, or the IP addresses of motes. \ -Multiple skins can be active at the same time. \ -Click the upper "Select visualizer skin" button to select or deselect skins. \ -

Useful skins \ -
Mote IDs: prints the unique mote IDs inside motes. \ -
Log output: prints the last printf message above motes. \ -
Radio traffic: displays inter-mote radio communication. \ -
Radio environment (UDGM): enables configurating the UDGM radio medium. \ -

Tip
\ -Right-click visualizer to show the popup menu, and click "Hide window decorations". - -se.sics.cooja.plugins.LogListener = \ -Log Listener\ -

Listens to log output from all simulated motes. \ -Right-click the main area for a popup menu with more options. \ -

You may filter shown logs by entering regular expressions in the bottom text field. \ -Filtering is performed on both the Mote and the Data columns.\ -

Filter examples: \ -

Hello
logs containing the string 'Hello'\ -

^Contiki
logs starting with 'Contiki'\ -

^[CR]
logs starting either a C or an R\ -

Hello$
logs ending with 'Hello'\ -

^ID:[2-5]$
logs from motes 2 to 5\ -

^ID:[2-5] Contiki
logs from motes 2 to 5 starting with 'Contiki' - -se.sics.cooja.plugins.TimeLine = \ -Timeline\ -

The timeline arranges historical simulation events into a graphical timeline. \ -The timeline can for example be used to overview the behavior of complex power-saving MAC protocols.\ -

Events appear as colored rectangles in the timeline. For more information about a particular event, hover the mouse above it.\ -

The checkboxes in the left pane control what event types are shown in the timeline. \ -Currently, four event types are supported (see below). Note that the control pane can be hidden to save space. \ -

All simulated motes are by default added to the timeline, however, any unwanted motes can be removed by mouse clicking the node ID (left).\ -

To display a vertical time marker on the timeline, press and hold the mouse on the time ruler (top).\ -

For more options, such as zooming and saving raw data to file, right-click the mouse for a popup menu.\ -

Radio RX/TX\ -
Shows radio connection events. Transmissions are painted blue, receptions are green, and interfered radios are red.\ -

Radio ON/OFF\ -
Shows whether the mote radio is on or off. Turned on radios are indicated with gray color.\ -

LEDs\ -
Shows LED state: red, green, and blue. (Assumes all mote types have exactly three LEDs.)\ -

Watchpoints\ -
Shows triggered watchpoints, currently only supported by MSPSim-based motes. To add watchpoints, use the Msp Code Watcher plugin. - -se.sics.cooja.plugins.SimControl = \ -Control Panel\ -

The control panel controls the simulation. \ -

Start starts the simulation. \ -

Pause stops the simulation. \ -

The keyboard shortcut for starting and pausing the simulation is Ctrl+S. \ -

Step runs the simulation for one millisecond. \ -

Reload reloads and restarts the simulation. \ -

Writing simulation time in milliseconds in the Stop at field causes the simulation to pause at the given time. \ -

Simulation speed is controlled via the bottom slider. \ -If the slider value is zero, simulation runs at full speed. \ -

Setting the slider to Real time, simulation speed is capped to not run faster than real time. \ -The Real time slider value is to the right of No simulation delay: click on the slider button and press the right arrow key on the keyboard. \ - -se.sics.cooja.mspmote.plugins.MspCLI = \ -MSPSim's Command Line Interface\ -

help
lists available commands\ -

info CC2420
shows radio chip details\ -

log CC2420 > mylog.txt
logs radio chip details to file\ -

stacktrace
shows current stacktrace - KEYBOARD_SHORTCUTS = \ Keyboard shortcuts
\
Ctrl+N: New simulation\ @@ -79,3 +8,8 @@ KEYBOARD_SHORTCUTS = \
\
F1: Toggle quick help +GETTING_STARTED = \ +Getting started
\ +
\ +
F1: Toggle quick help + diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index d525d5f61..5c0688453 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -391,7 +391,6 @@ public class GUI extends Observable { BorderFactory.createEmptyBorder(0, 3, 0, 0) )); quickHelpScroll.setVisible(false); - loadQuickHelp("KEYBOARD_SHORTCUTS"); loadQuickHelp("GETTING_STARTED"); // Load default and overwrite with user settings (if any) @@ -4217,14 +4216,6 @@ public class GUI extends Observable { } } - public interface HasQuickHelp { - /** - * @return Quick help. May be HTML formatted, but must not include the - * document html-tags. - */ - public String getQuickHelp(); - } - /** * Load quick help for given object or identifier. Note that this method does not * show the quick help pane. diff --git a/tools/cooja/java/se/sics/cooja/HasQuickHelp.java b/tools/cooja/java/se/sics/cooja/HasQuickHelp.java new file mode 100755 index 000000000..80fdbdd26 --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/HasQuickHelp.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +package se.sics.cooja; + +public interface HasQuickHelp { + /** + * @return Quick help. May be HTML formatted, but must not include the + * document html-tags. + */ + public String getQuickHelp(); +} diff --git a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java index 35b684e87..89b44ef7b 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java @@ -84,13 +84,14 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.Plugin; import se.sics.cooja.PluginType; -import se.sics.cooja.Simulation; -import se.sics.cooja.VisPlugin; import se.sics.cooja.SimEventCentral.LogOutputEvent; import se.sics.cooja.SimEventCentral.LogOutputListener; +import se.sics.cooja.Simulation; +import se.sics.cooja.VisPlugin; import se.sics.cooja.dialogs.TableColumnAdjuster; import se.sics.cooja.dialogs.UpdateAggregator; import se.sics.cooja.util.ArrayQueue; @@ -103,7 +104,7 @@ import se.sics.cooja.util.ArrayQueue; */ @ClassDescription("Log Listener") @PluginType(PluginType.SIM_STANDARD_PLUGIN) -public class LogListener extends VisPlugin { +public class LogListener extends VisPlugin implements HasQuickHelp { private static final long serialVersionUID = 3294595371354857261L; private static Logger logger = Logger.getLogger(LogListener.class); @@ -124,7 +125,7 @@ public class LogListener extends VisPlugin { private boolean formatTimeString = false; private boolean hasHours = false; - + private final JTable logTable; private TableRowSorter logFilter; private ArrayQueue logs = new ArrayQueue(); @@ -147,9 +148,9 @@ public class LogListener extends VisPlugin { private boolean hideDebug = false; private JCheckBoxMenuItem hideDebugCheckbox; - + private JCheckBoxMenuItem appendCheckBox; - + private static final int UPDATE_INTERVAL = 250; private UpdateAggregator logUpdateAggregator = new UpdateAggregator(UPDATE_INTERVAL) { private Runnable scroll = new Runnable() { @@ -187,7 +188,7 @@ public class LogListener extends VisPlugin { } } }; - + /** * @param simulation Simulation * @param gui GUI @@ -394,7 +395,7 @@ public class LogListener extends VisPlugin { } }); - + logTable.setComponentPopupMenu(popupMenu); /* Fetch log output history */ @@ -515,7 +516,7 @@ public class LogListener extends VisPlugin { } private void updateTitle() { - setTitle("Log Listener listening on " + setTitle("Log Listener listening on " + simulation.getEventCentral().getLogOutputObservationsCount() + " log interfaces"); } @@ -655,7 +656,7 @@ public class LogListener extends VisPlugin { return; } } - }); + }); } private class LogData { @@ -726,8 +727,8 @@ public class LogListener extends VisPlugin { PrintWriter outStream = new PrintWriter(new FileWriter(saveFile)); for(LogData data : logs) { outStream.println( - data.getTime() + "\t" + - data.getID() + "\t" + + data.getTime() + "\t" + + data.getID() + "\t" + data.ev.getMessage()); } outStream.close(); @@ -817,7 +818,7 @@ public class LogListener extends VisPlugin { } } }; - + private Action timeLineAction = new AbstractAction("Timeline") { private static final long serialVersionUID = -6358463434933029699L; public void actionPerformed(ActionEvent e) { @@ -833,7 +834,7 @@ public class LogListener extends VisPlugin { if (!(p instanceof TimeLine)) { continue; } - + /* Select simulation time */ TimeLine plugin = (TimeLine) p; plugin.trySelectTime(time); @@ -856,7 +857,7 @@ public class LogListener extends VisPlugin { if (!(p instanceof RadioLogger)) { continue; } - + /* Select simulation time */ RadioLogger plugin = (RadioLogger) p; plugin.trySelectTime(time); @@ -891,7 +892,7 @@ public class LogListener extends VisPlugin { model.fireTableRowsDeleted(0, size - 1); } } - + private Action copyAction = new AbstractAction("Selected") { private static final long serialVersionUID = -8433490108577001803L; @@ -953,4 +954,20 @@ public class LogListener extends VisPlugin { } }; + public String getQuickHelp() { + return + "Log Listener" + + "

Listens to log output from all simulated motes. " + + "Right-click the main area for a popup menu with more options. " + + "

You may filter shown logs by entering regular expressions in the bottom text field. " + + "Filtering is performed on both the Mote and the Data columns." + + "

Filter examples: " + + "

Hello
logs containing the string 'Hello'" + + "

^Contiki
logs starting with 'Contiki'" + + "

^[CR]
logs starting either a C or an R" + + "

Hello$
logs ending with 'Hello'" + + "

^ID:[2-5]$
logs from motes 2 to 5" + + "

^ID:[2-5] Contiki
logs from motes 2 to 5 starting with 'Contiki'"; + } + } diff --git a/tools/cooja/java/se/sics/cooja/plugins/MoteInterfaceViewer.java b/tools/cooja/java/se/sics/cooja/plugins/MoteInterfaceViewer.java index b42c2812f..792a1f3b9 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/MoteInterfaceViewer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/MoteInterfaceViewer.java @@ -51,13 +51,13 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; import se.sics.cooja.MotePlugin; import se.sics.cooja.PluginType; import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; -import se.sics.cooja.GUI.HasQuickHelp; /** * Mote Interface Viewer views information about a specific mote interface. @@ -208,7 +208,7 @@ public class MoteInterfaceViewer extends VisPlugin implements HasQuickHelp, Mote setSelectedInterface(element.getText()); } else if (element.getName().equals("scrollpos")) { String[] scrollPos = element.getText().split(","); - final Point pos = new Point(Integer.parseInt(scrollPos[0]), Integer.parseInt(scrollPos[1])); + final Point pos = new Point(Integer.parseInt(scrollPos[0]), Integer.parseInt(scrollPos[1])); EventQueue.invokeLater(new Runnable() { public void run() { mainScrollPane.getViewport().setViewPosition(pos); @@ -222,7 +222,7 @@ public class MoteInterfaceViewer extends VisPlugin implements HasQuickHelp, Mote public String getQuickHelp() { String help = "" + GUI.getDescriptionOf(this) + ""; help += "

Lists mote interfaces, and allows mote inspection and interaction via mote interface visualizers."; - + MoteInterface intf = selectedMoteInterface; if (intf != null) { if (intf instanceof HasQuickHelp) { diff --git a/tools/cooja/java/se/sics/cooja/plugins/SimControl.java b/tools/cooja/java/se/sics/cooja/plugins/SimControl.java index 63d741c47..091cb812e 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/SimControl.java +++ b/tools/cooja/java/se/sics/cooja/plugins/SimControl.java @@ -31,19 +31,41 @@ package se.sics.cooja.plugins; -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.NumberFormat; -import java.util.*; -import javax.swing.*; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.event.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import org.apache.log4j.Logger; -import se.sics.cooja.*; +import se.sics.cooja.ClassDescription; +import se.sics.cooja.GUI; +import se.sics.cooja.HasQuickHelp; +import se.sics.cooja.PluginType; +import se.sics.cooja.Simulation; +import se.sics.cooja.TimeEvent; +import se.sics.cooja.VisPlugin; /** * Control panel for starting and pausing the current simulation. @@ -53,7 +75,7 @@ import se.sics.cooja.*; */ @ClassDescription("Control Panel") @PluginType(PluginType.SIM_STANDARD_PLUGIN) -public class SimControl extends VisPlugin { +public class SimControl extends VisPlugin implements HasQuickHelp { private static final long serialVersionUID = 8452253637624664192L; private static Logger logger = Logger.getLogger(SimControl.class); @@ -84,7 +106,7 @@ public class SimControl extends VisPlugin { /* Update current time label when simulation is running */ if (simulation.isRunning()) { - updateLabelTimer.start(); + updateLabelTimer.start(); } /* Container */ @@ -197,9 +219,9 @@ public class SimControl extends VisPlugin { smallPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); sliderDelay = new JSlider( - JSlider.HORIZONTAL, - SLIDE_MIN, - SLIDE_MAX, + JSlider.HORIZONTAL, + SLIDE_MIN, + SLIDE_MAX, convertTimeToSlide(simulation.getDelayTime())); sliderDelay.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { @@ -285,9 +307,9 @@ public class SimControl extends VisPlugin { return Integer.MIN_VALUE; } if (slide <= 0) { - return slide-2; /* Ignore special cases */ + return slide-2; /* Ignore special cases */ } - return slide; + return slide; } private int convertTimeToSlide(int time) { @@ -341,7 +363,7 @@ public class SimControl extends VisPlugin { + " ms"); long systemTimeDiff = System.currentTimeMillis() - lastSystemTimeTimestamp; - + if(systemTimeDiff > 1000) { long simulationTimeDiff = simulation.getSimulationTimeMillis() - lastSimulationTimeTimestamp; @@ -382,4 +404,19 @@ public class SimControl extends VisPlugin { simulation.getGUI().reloadCurrentSimulation(simulation.isRunning()); } }; + + public String getQuickHelp() { + return "Control Panel" + + "

The control panel controls the simulation. " + + "

Start starts the simulation. " + + "

Pause stops the simulation. " + + "

The keyboard shortcut for starting and pausing the simulation is Ctrl+S. " + + "

Step runs the simulation for one millisecond. " + + "

Reload reloads and restarts the simulation. " + + "

Writing simulation time in milliseconds in the Stop at field causes the simulation to pause at the given time. " + + "

Simulation speed is controlled via the bottom slider. " + + "If the slider value is zero, simulation runs at full speed. " + + "

Setting the slider to Real time, simulation speed is capped to not run faster than real time. " + + "The Real time slider value is to the right of No simulation delay: click on the slider button and press the right arrow key on the keyboard. "; + } } diff --git a/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java b/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java index 42059b0d4..255f99d9c 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java +++ b/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java @@ -86,6 +86,7 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.Plugin; import se.sics.cooja.PluginType; @@ -107,7 +108,7 @@ import se.sics.cooja.motes.AbstractEmulatedMote; */ @ClassDescription("Timeline") @PluginType(PluginType.SIM_STANDARD_PLUGIN) -public class TimeLine extends VisPlugin { +public class TimeLine extends VisPlugin implements HasQuickHelp { private static final long serialVersionUID = -883154261246961973L; public static final int LED_PIXEL_HEIGHT = 2; public static final int EVENT_PIXEL_HEIGHT = 4; @@ -242,7 +243,7 @@ public class TimeLine extends VisPlugin { JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); timelineScrollPane.getHorizontalScrollBar().setUnitIncrement(50); - + timelineMoteRuler = new MoteRuler(); timelineScrollPane.setRowHeaderView(timelineMoteRuler); timelineScrollPane.setBackground(Color.WHITE); @@ -2386,4 +2387,25 @@ public class TimeLine extends VisPlugin { } }); + public String getQuickHelp() { + return + "Timeline" + + "

The timeline arranges historical simulation events into a graphical timeline. " + + "The timeline can for example be used to overview the behavior of complex power-saving MAC protocols." + + "

Events appear as colored rectangles in the timeline. For more information about a particular event, hover the mouse above it." + + "

The checkboxes in the left pane control what event types are shown in the timeline. " + + "Currently, four event types are supported (see below). Note that the control pane can be hidden to save space. " + + "

All simulated motes are by default added to the timeline, however, any unwanted motes can be removed by mouse clicking the node ID (left)." + + "

To display a vertical time marker on the timeline, press and hold the mouse on the time ruler (top)." + + "

For more options, such as zooming and saving raw data to file, right-click the mouse for a popup menu." + + "

Radio RX/TX" + + "
Shows radio connection events. Transmissions are painted blue, receptions are green, and interfered radios are red." + + "

Radio ON/OFF" + + "
Shows whether the mote radio is on or off. Turned on radios are indicated with gray color." + + "

LEDs" + + "
Shows LED state: red, green, and blue. (Assumes all mote types have exactly three LEDs.)" + + "

Watchpoints" + + "
Shows triggered watchpoints, currently only supported by MSPSim-based motes. To add watchpoints, use the Msp Code Watcher plugin."; + } + } diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java index ca69ea6df..ecba403e1 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java @@ -71,7 +71,6 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; -import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -89,6 +88,7 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; import se.sics.cooja.GUI.MoteRelation; +import se.sics.cooja.HasQuickHelp; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; import se.sics.cooja.PluginType; @@ -127,7 +127,7 @@ import se.sics.cooja.plugins.skins.UDGMVisualizerSkin; */ @ClassDescription("Simulation visualizer") @PluginType(PluginType.SIM_STANDARD_PLUGIN) -public class Visualizer extends VisPlugin { +public class Visualizer extends VisPlugin implements HasQuickHelp { private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(Visualizer.class); @@ -1434,5 +1434,24 @@ public class Visualizer extends VisPlugin { } return true; } + } + + public String getQuickHelp() { + return + "Visualizer " + + "

The visualizer shows the positions of simulated motes as viewed from above (XY-plane). " + + "It is possible to zoom (CRTL+Mouse drag) and pan (Shift+Mouse drag) the current view. Motes can be moved by dragging them (ALT+Mouse drag). " + + "Mouse right-click a mote or unoccupied space for a popup menu with more options. " + + "

The visualizer supports \"visualizer skins\". " + + "Each skin provides some specific information, such as ongoing simulated radio traffic, or the IP addresses of motes. " + + "Multiple skins can be active at the same time. " + + "Click the upper \"Select visualizer skin\" button to select or deselect skins. " + + "

Useful skins " + + "
Mote IDs: prints the unique mote IDs inside motes. " + + "
Log output: prints the last printf message above motes. " + + "
Radio traffic: displays inter-mote radio communication. " + + "
Radio environment (UDGM): enables configurating the UDGM radio medium. " + + "

Tip
" + + "Right-click visualizer to show the popup menu, and click \"Hide window decorations\"."; }; }