From a69b580778d8662b6f2cc08063a2a2ff84fdf3dd Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Wed, 9 May 2012 13:47:03 +0200 Subject: [PATCH] Added new annonation with which Cooja components (e.g. mote plugins) can be activated or deactivated depending on the given argument (e.g. mote). This may for example be used by a mote plugin that only accepts emulated motes, and that consequently should be hidden in other non-emulated motes' plugin menues. The new annotation is currently only used by the MspCodeWatcher and the DGRM visualizer skin. --- .../cooja/mspmote/plugins/MspCodeWatcher.java | 4 +- tools/cooja/java/se/sics/cooja/GUI.java | 30 +++++++++ .../se/sics/cooja/SupportedArguments.java | 64 +++++++++++++++++++ .../se/sics/cooja/plugins/Visualizer.java | 19 ++++++ .../plugins/skins/DGRMVisualizerSkin.java | 6 +- 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 tools/cooja/java/se/sics/cooja/SupportedArguments.java diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java index 4221035f8..0358720f4 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java @@ -71,6 +71,7 @@ import se.sics.cooja.Mote; import se.sics.cooja.MotePlugin; import se.sics.cooja.PluginType; import se.sics.cooja.Simulation; +import se.sics.cooja.SupportedArguments; import se.sics.cooja.VisPlugin; import se.sics.cooja.Watchpoint; import se.sics.cooja.WatchpointMote; @@ -85,6 +86,7 @@ import se.sics.mspsim.util.ELFDebug; @ClassDescription("Msp Code Watcher") @PluginType(PluginType.MOTE_PLUGIN) +@SupportedArguments(motes = {MspMote.class}) public class MspCodeWatcher extends VisPlugin implements MotePlugin { private static final long serialVersionUID = -8463196456352243367L; @@ -314,7 +316,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } currentFileAction.setEnabled(true); currentFileAction.putValue(Action.NAME, file.getName() + ":" + line); - currentFileAction.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath() + ":" + line); + currentFileAction.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath() + ":" + line + ", PC:" + String.format("0x%04x", mspMote.getCPU().getPC())); fileComboBox.setSelectedItem(file.getName()); displaySourceFile(file, line, true); diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index c35492fb0..a14d5d184 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -1852,6 +1852,8 @@ public class GUI extends Observable { return false; } + /* TODO Check if plugin specifies supported arguments here */ + /* Check if plugin was imported by a project directory */ File project = getProjectConfig().getUserProjectDefining(GUI.class, "PLUGINS", newPluginClass.getName()); @@ -1934,6 +1936,34 @@ public class GUI extends Observable { JMenuItem menuItem = new JMenuItem(guiAction); menuItem.putClientProperty("class", motePluginClass); menuItem.putClientProperty("mote", mote); + + /* Check if mote plugin depends on any particular type of mote */ + boolean enableMenuItem = true; + if (motePluginClass.getAnnotation(SupportedArguments.class) != null) { + enableMenuItem = false; + Class[] motes = motePluginClass.getAnnotation(SupportedArguments.class).motes(); + StringBuilder sb = new StringBuilder(); + sb.append( + "
This plugin:\n" +
+            motePluginClass.getName() +
+            "\ndoes not support motes of type:\n" +
+            mote.getClass().getName() +
+            "\n\nIt only supports motes of types:\n"
+        );
+        for (Class o: motes) {
+          sb.append(o.getName() + "\n");
+          if (o.isAssignableFrom(mote.getClass())) {
+            enableMenuItem = true;
+            break;
+          }
+        }
+        sb.append("");
+        if (!enableMenuItem) {
+          menuItem.setToolTipText(sb.toString());
+        }
+      }
+
+      menuItem.setEnabled(enableMenuItem);
       menuMotePlugins.add(menuItem);
     }
     return menuMotePlugins;
diff --git a/tools/cooja/java/se/sics/cooja/SupportedArguments.java b/tools/cooja/java/se/sics/cooja/SupportedArguments.java
new file mode 100644
index 000000000..fa09710cb
--- /dev/null
+++ b/tools/cooja/java/se/sics/cooja/SupportedArguments.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.swing.MenuElement;
+
+import se.sics.cooja.plugins.Visualizer;
+import se.sics.cooja.plugins.skins.DGRMVisualizerSkin;
+
+/**
+ * With this annotation, Cooja components (e.g. mote plugins) can be activated
+ * or deactivated depending on the given argument (e.g. mote). This may for
+ * example be used by a mote plugin that only accepts emulated motes, and that
+ * consequently should be hidden in other non-emulated motes' plugin menues.
+ *
+ * See below code usage examples.
+ *
+ * @see GUI#createMotePluginsSubmenu(Mote)
+ * @see Visualizer#populateSkinMenu(MenuElement)
+ * @see DGRMVisualizerSkin
+ *
+ * @author Fredrik Osterlind
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SupportedArguments {
+
+  /**
+   * @return List of accepted mote classes.
+   */
+  Class[] motes() default { Mote.class };
+
+  /**
+   * @return List of accepted radio medium classes.
+   */
+  Class[] radioMediums() default { RadioMedium.class };
+}
diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java
index 00b3d1ade..bc5769381 100644
--- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java
+++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java
@@ -92,8 +92,10 @@ import se.sics.cooja.GUI.MoteRelation;
 import se.sics.cooja.Mote;
 import se.sics.cooja.MoteInterface;
 import se.sics.cooja.PluginType;
+import se.sics.cooja.RadioMedium;
 import se.sics.cooja.SimEventCentral.MoteCountListener;
 import se.sics.cooja.Simulation;
+import se.sics.cooja.SupportedArguments;
 import se.sics.cooja.VisPlugin;
 import se.sics.cooja.interfaces.LED;
 import se.sics.cooja.interfaces.Position;
@@ -705,6 +707,23 @@ public class Visualizer extends VisPlugin {
         }
       });
 
+
+      /* Check if skin depends on any particular radio medium */
+      boolean showMenuItem = true;
+      if (skinClass.getAnnotation(SupportedArguments.class) != null) {
+        showMenuItem = false;
+        Class[] radioMediums = skinClass.getAnnotation(SupportedArguments.class).radioMediums();
+        for (Class o: radioMediums) {
+          if (o.isAssignableFrom(simulation.getRadioMedium().getClass())) {
+            showMenuItem = true;
+            break;
+          }
+        }
+      }
+      if (!showMenuItem) {
+        continue;
+      }
+
       if (skinMenu instanceof JMenu) {
         ((JMenu)skinMenu).add(item);
       }
diff --git a/tools/cooja/java/se/sics/cooja/plugins/skins/DGRMVisualizerSkin.java b/tools/cooja/java/se/sics/cooja/plugins/skins/DGRMVisualizerSkin.java
index ae4f69a20..df2d86900 100644
--- a/tools/cooja/java/se/sics/cooja/plugins/skins/DGRMVisualizerSkin.java
+++ b/tools/cooja/java/se/sics/cooja/plugins/skins/DGRMVisualizerSkin.java
@@ -41,6 +41,7 @@ import org.apache.log4j.Logger;
 import se.sics.cooja.ClassDescription;
 import se.sics.cooja.Mote;
 import se.sics.cooja.Simulation;
+import se.sics.cooja.SupportedArguments;
 import se.sics.cooja.interfaces.Position;
 import se.sics.cooja.interfaces.Radio;
 import se.sics.cooja.plugins.Visualizer;
@@ -50,6 +51,7 @@ import se.sics.cooja.radiomediums.DestinationRadio;
 import se.sics.cooja.radiomediums.DirectedGraphMedium;
 
 @ClassDescription("Radio environment (DGRM)")
+@SupportedArguments(radioMediums = {DirectedGraphMedium.class})
 public class DGRMVisualizerSkin implements VisualizerSkin {
 	private static Logger logger = Logger.getLogger(DGRMVisualizerSkin.class);
 
@@ -82,7 +84,7 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
 
 	public void paintBeforeMotes(Graphics g) {
           Mote selectedMote = visualizer.getSelectedMote();
-		if (simulation == null 
+		if (simulation == null
 				|| selectedMote == null
 				|| selectedMote.getInterfaces().getRadio() == null) {
 			return;
@@ -100,7 +102,7 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
 		g.setColor(Color.BLACK);
 
 		DirectedGraphMedium radioMedium = (DirectedGraphMedium) simulation.getRadioMedium();
-		
+
 		/* Print transmission success probabilities */
 		DestinationRadio[] dests = radioMedium.getPotentialDestinations(selectedRadio);
 		if (dests == null || dests.length == 0) {