visualizer update: enabling selecting multiple visualizer skins

This commit is contained in:
fros4943 2009-04-14 15:40:26 +00:00
parent 3f205a1413
commit 906e341a65
7 changed files with 224 additions and 184 deletions

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: Visualizer.java,v 1.3 2009/04/01 13:51:50 fros4943 Exp $
* $Id: Visualizer.java,v 1.4 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins;
@ -56,9 +56,8 @@ import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.GUI.MoteRelation;
import se.sics.cooja.interfaces.*;
import se.sics.cooja.plugins.skins.BasicVisualizerSkin;
import se.sics.cooja.plugins.skins.IDVisualizerSkin;
import se.sics.cooja.plugins.skins.LEDVisualizerSkin;
import se.sics.cooja.plugins.skins.LogLEDVisualizerSkin;
import se.sics.cooja.plugins.skins.LogVisualizerSkin;
/**
@ -72,7 +71,6 @@ import se.sics.cooja.plugins.skins.LogVisualizerSkin;
* @see #registerMoteMenuAction(MoteMenuAction)
* @see #registerSimulationMenuAction(SimulationMenuAction)
* @see #registerVisualizerSkin(Class)
* @see BasicVisualizerSkin
* @see UDGMVisualizerSkin
* @author Fredrik Osterlind
*/
@ -86,6 +84,8 @@ public class Visualizer extends VisPlugin {
private static final int CANVAS_BORDER_WIDTH = 25;
public static final int MOTE_RADIUS = 8;
private static final Color[] DEFAULT_MOTE_COLORS = { Color.WHITE };
private GUI gui = null;
private Simulation simulation = null;
private final JPanel canvas;
@ -103,17 +103,16 @@ public class Visualizer extends VisPlugin {
private Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
/* Visualizer skins */
private final JButton skinButton = new JButton("Select visualizer skins");
private static ArrayList<Class<? extends VisualizerSkin>> visualizerSkins =
new ArrayList<Class<? extends VisualizerSkin>>();
static {
/* Register default visualizer skins */
registerVisualizerSkin(BasicVisualizerSkin.class);
registerVisualizerSkin(IDVisualizerSkin.class);
registerVisualizerSkin(LogVisualizerSkin.class);
registerVisualizerSkin(LEDVisualizerSkin.class);
registerVisualizerSkin(LogLEDVisualizerSkin.class);
}
private JComboBox skinBox = null;
private VisualizerSkin currentSkin = null;
private ArrayList<VisualizerSkin> currentSkins = new ArrayList<VisualizerSkin>();
/* Generic visualization */
private Observer simObserver = null;
@ -151,8 +150,9 @@ public class Visualizer extends VisPlugin {
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (currentSkin != null) {
currentSkin.paintSkin(g);
paintSkinGeneric(g);
for (VisualizerSkin skin: currentSkins) {
skin.paintSkin(g);
}
}
};
@ -160,19 +160,74 @@ public class Visualizer extends VisPlugin {
calculateTransformations();
/* Skin selector */
skinBox = new JComboBox();
skinBox.addActionListener(new ActionListener() {
skinButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (skinBox.getSelectedIndex() < 0 ||
skinBox.getSelectedIndex() > visualizerSkins.size()) {
Point mouse = MouseInfo.getPointerInfo().getLocation();
JCheckBoxMenuItem item;
JPopupMenu skinPopupMenu = new JPopupMenu();
for (Class<? extends VisualizerSkin> skinClass: visualizerSkins) {
String description = GUI.getDescriptionOf(skinClass);
item = new JCheckBoxMenuItem(description, false);
item.putClientProperty("skinclass", skinClass);
/* Select skin if active */
for (VisualizerSkin skin: currentSkins) {
if (skin.getClass() == skinClass) {
item.setSelected(true);
break;
}
}
item.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
JCheckBoxMenuItem menuItem = ((JCheckBoxMenuItem)e.getItem());
if (menuItem == null) {
logger.fatal("No menu item");
return;
}
Class<? extends VisualizerSkin> skinClass = visualizerSkins.get(skinBox.getSelectedIndex());
selectSkin(skinClass);
Class<VisualizerSkin> skinClass =
(Class<VisualizerSkin>) menuItem.getClientProperty("skinclass");
if (skinClass == null) {
logger.fatal("Unknown visualizer skin class: " + skinClass);
return;
}
if (menuItem.isSelected()) {
/* Create and activate new skin */
generateAndActivateSkin(skinClass);
} else {
/* Deactivate skin */
VisualizerSkin skinToDeactivate = null;
for (VisualizerSkin skin: currentSkins) {
if (skin.getClass() == skinClass) {
skinToDeactivate = skin;
break;
}
}
if (skinToDeactivate == null) {
logger.fatal("Unknown visualizer skin to deactivate: " + skinClass);
return;
}
skinToDeactivate.setInactive();
repaint();
currentSkins.remove(skinToDeactivate);
skinButton.setText("Select visualizer skins " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
}
}
});
this.add(BorderLayout.NORTH, skinBox);
skinPopupMenu.add(item);
}
skinPopupMenu.setLocation(mouse);
skinPopupMenu.setInvoker(skinButton);
skinPopupMenu.setVisible(true);
}
});
this.add(BorderLayout.NORTH, skinButton);
this.add(BorderLayout.CENTER, canvas);
/* Observe simulation and mote positions */
@ -405,71 +460,38 @@ public class Visualizer extends VisPlugin {
new DropTarget(canvas, DnDConstants.ACTION_COPY_OR_MOVE, dTargetListener, true, null)
);
repopulateSkinBox();
this.setSize(300, 300);
setLocation(gui.getDesktopPane().getWidth() - getWidth(), 0);
setVisible(true);
}
private void selectSkin(Class<? extends VisualizerSkin> skinClass) {
if (currentSkin != null &&
skinClass == currentSkin.getClass()) {
private void generateAndActivateSkin(Class<? extends VisualizerSkin> skinClass) {
for (VisualizerSkin skin: currentSkins) {
if (skinClass == skin.getClass()) {
logger.warn("Selected skin already active: " + skinClass);
return;
}
/* Deactive current skin */
if (currentSkin != null) {
currentSkin.setInactive();
}
/* Create and activate new skin */
try {
VisualizerSkin newSkin = skinClass.newInstance();
newSkin.setActive(Visualizer.this.simulation, Visualizer.this);
currentSkin = newSkin;
currentSkins.add(newSkin);
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
/* Update skin selector box */
for (int i=0; i < skinBox.getItemCount(); i++) {
String desc = (String) skinBox.getItemAt(i);
if (desc.equals(GUI.getDescriptionOf(skinClass))) {
if (skinBox.getSelectedIndex() != i) {
skinBox.setSelectedIndex(i);
}
break;
}
}
skinButton.setText("Select visualizer skins " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
repaint();
}
public VisualizerSkin getCurrentSkin() {
return currentSkin;
}
protected void repopulateSkinBox() {
String selected = (String) skinBox.getSelectedItem();
int previousSelectionIndex = -1;
/* Repopulate box */
skinBox.removeAllItems();
for (Class<? extends VisualizerSkin> skin: visualizerSkins) {
String description = GUI.getDescriptionOf(skin);
skinBox.addItem(description);
if (selected != null && selected.equals(description)) {
previousSelectionIndex = skinBox.getItemCount();
}
}
if (previousSelectionIndex >= 0) {
skinBox.setSelectedIndex(previousSelectionIndex);
}
public VisualizerSkin[] getCurrentSkins() {
VisualizerSkin[] skins = new VisualizerSkin[currentSkins.size()];
return currentSkins.toArray(skins);
}
/**
@ -504,7 +526,7 @@ public class Visualizer extends VisPlugin {
moteMenuActions.add(menuAction);
}
public void unregisterMoteMenuAction(Class<? extends SimulationMenuAction> menuAction) {
public void unregisterMoteMenuAction(Class<? extends MoteMenuAction> menuAction) {
moteMenuActions.remove(menuAction);
}
@ -681,7 +703,19 @@ public class Visualizer extends VisPlugin {
public void paintSkinGeneric(Graphics g) {
Mote[] allMotes = simulation.getMotes();
for (Mote mote: allMotes) {
Color moteColors[] = currentSkin.getColorOf(mote);
/* Use the first skin's non-null mote colors */
Color moteColors[] = null;
for (VisualizerSkin skin: currentSkins) {
moteColors = skin.getColorOf(mote);
if (moteColors != null) {
break;
}
}
if (moteColors == null) {
moteColors = DEFAULT_MOTE_COLORS;
}
Position motePos = mote.getInterfaces().getPosition();
Point pixelCoord = transformPositionToPixel(motePos);
@ -861,11 +895,10 @@ public class Visualizer extends VisPlugin {
}
public void closePlugin() {
skinBox.removeAllItems();
if (currentSkin != null) {
currentSkin.setInactive();
for (VisualizerSkin skin: currentSkins) {
skin.setInactive();
}
currentSkins.clear();
if (moteHighligtObserver != null) {
gui.deleteMoteHighlightObserver(moteHighligtObserver);
}
@ -897,9 +930,11 @@ public class Visualizer extends VisPlugin {
Vector<Element> config = new Vector<Element>();
Element element;
for (VisualizerSkin skin: currentSkins) {
element = new Element("skin");
element.setText(GUI.getDescriptionOf(currentSkin.getClass()));
element.setText(GUI.getDescriptionOf(skin.getClass()));
config.add(element);
}
return config;
}
@ -910,10 +945,14 @@ public class Visualizer extends VisPlugin {
String wanted = element.getText();
for (Class<? extends VisualizerSkin> skinClass: visualizerSkins) {
if (wanted.equals(GUI.getDescriptionOf(skinClass))) {
selectSkin(skinClass);
generateAndActivateSkin(skinClass);
wanted = null;
break;
}
}
if (wanted != null) {
logger.warn("Could not load skin: " + element.getText());
}
}
}
return true;

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: VisualizerSkin.java,v 1.1 2009/03/24 15:46:18 fros4943 Exp $
* $Id: VisualizerSkin.java,v 1.2 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins;
@ -84,4 +84,9 @@ public interface VisualizerSkin {
*/
public void paintSkin(Graphics g);
/**
* @return Visualizer plugin where this skin is showing
*/
public Visualizer getVisualizer();
}

View file

@ -26,34 +26,40 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: BasicVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
* $Id: IDVisualizerSkin.java,v 1.1 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.MoteID;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Basic visualizer skin. Paints all motes black.
* Visualizer skin for mote IDs.
*
* @author Fredrik Osterlind
*/
@ClassDescription("[select visualizer skin]")
public class BasicVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(BasicVisualizerSkin.class);
@ClassDescription("Mote IDs")
public class IDVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(IDVisualizerSkin.class);
private Simulation simulation = null;
private Visualizer visualizer = null;
public void setActive(Simulation simulation, Visualizer vis) {
this.simulation = simulation;
this.visualizer = vis;
}
@ -61,11 +67,30 @@ public class BasicVisualizerSkin implements VisualizerSkin {
}
public Color[] getColorOf(Mote mote) {
return new Color[] { Color.BLACK };
return null;
}
public void paintSkin(Graphics g) {
/* Just paint motes */
visualizer.paintSkinGeneric(g);
FontMetrics fm = g.getFontMetrics();
/* Paint ID inside each mote */
Mote[] allMotes = simulation.getMotes();
for (Mote mote: allMotes) {
MoteID id = mote.getInterfaces().getMoteID();
if (id == null) {
continue;
}
Position pos = mote.getInterfaces().getPosition();
Point pixel = visualizer.transformPositionToPixel(pos);
String msg = "" + id.getMoteID();
int msgWidth = fm.stringWidth(msg);
g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 5);
}
}
public Visualizer getVisualizer() {
return visualizer;
}
}

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: LEDVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
* $Id: LEDVisualizerSkin.java,v 1.2 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
@ -134,6 +134,9 @@ public class LEDVisualizerSkin implements VisualizerSkin {
}
public void paintSkin(Graphics g) {
visualizer.paintSkinGeneric(g);
}
public Visualizer getVisualizer() {
return visualizer;
}
}

View file

@ -1,75 +0,0 @@
/*
* Copyright (c) 2009, 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.
*
* $Id: LogLEDVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.Simulation;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
/**
* Visualizer skin for both Log output and LEDs.
*
* @see LEDVisualizerSkin
* @see LogVisualizerSkin
* @author Fredrik Osterlind
*/
@ClassDescription("printf()'s + LEDs")
public class LogLEDVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(LogLEDVisualizerSkin.class);
private LEDVisualizerSkin ledSkin = new LEDVisualizerSkin();
private LogVisualizerSkin logSkin = new LogVisualizerSkin();
public void setActive(Simulation simulation, Visualizer vis) {
ledSkin.setActive(simulation, vis);
logSkin.setActive(simulation, vis);
}
public void setInactive() {
ledSkin.setInactive();
logSkin.setInactive();
}
public Color[] getColorOf(Mote mote) {
return ledSkin.getColorOf(mote);
}
public void paintSkin(Graphics g) {
logSkin.paintSkin(g);
}
}

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: LogVisualizerSkin.java,v 1.1 2009/03/24 15:46:29 fros4943 Exp $
* $Id: LogVisualizerSkin.java,v 1.2 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
@ -100,12 +100,10 @@ public class LogVisualizerSkin implements VisualizerSkin {
}
public Color[] getColorOf(Mote mote) {
return new Color[] { Color.BLACK };
return null;
}
public void paintSkin(Graphics g) {
visualizer.paintSkinGeneric(g);
FontMetrics fm = g.getFontMetrics();
/* Paint last output below motes */
@ -127,4 +125,8 @@ public class LogVisualizerSkin implements VisualizerSkin {
g.drawString(msg, pixel.x - msgWidth/2, pixel.y - Visualizer.MOTE_RADIUS);
}
}
public Visualizer getVisualizer() {
return visualizer;
}
}

View file

@ -26,13 +26,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: UDGMVisualizerSkin.java,v 1.3 2009/03/26 16:24:31 fros4943 Exp $
* $Id: UDGMVisualizerSkin.java,v 1.4 2009/04/14 15:40:26 fros4943 Exp $
*/
package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
@ -65,7 +66,7 @@ import se.sics.cooja.radiomediums.UDGM;
* Allows a user to change the collective TX/interference ranges,
* and the TX/RX success ratio.
*
* Transmitting motes are painted blue.
* Transmitting motes are painted blue. XXXXXXXX
* Receiving motes are painted green.
* Interfered motes are painted red.
* Motes without radios are painted gray.
@ -118,6 +119,10 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
};
public void setActive(Simulation simulation, Visualizer vis) {
if (!(simulation.getRadioMedium() instanceof UDGM)) {
logger.fatal("Cannot activate UDGM skin for unknown radio medium: " + simulation.getRadioMedium());
return;
}
this.simulation = simulation;
this.visualizer = vis;
this.radioMedium = (UDGM) simulation.getRadioMedium();
@ -244,6 +249,11 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
}
public void setInactive() {
if (simulation == null) {
/* Skin was never activated */
return;
}
/* Remove mouse listener */
visualizer.getCurrentCanvas().removeMouseListener(selectMoteMouseListener);
@ -268,13 +278,18 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
}
public Color[] getColorOf(Mote mote) {
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == null) {
return new Color[] { Color.BLACK };
if (simulation == null) {
/* Skin was never activated */
return null;
}
if (mote.getState() == Mote.State.DEAD) {
return new Color[] { Color.BLACK };
return null;
}
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == null) {
return null;
}
if (selectedMote != null && mote == selectedMote) {
@ -297,12 +312,30 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
return new Color[] { Color.GREEN };
}
return new Color[] { Color.WHITE };
return null;
}
private static Color COLOR_INTERFERENCE = new Color(
Color.DARK_GRAY.getRed(),
Color.DARK_GRAY.getGreen(),
Color.DARK_GRAY.getBlue(),
100
);
private static Color COLOR_TX = new Color(
Color.GREEN.getRed(),
Color.GREEN.getGreen(),
Color.GREEN.getBlue(),
100
);
public void paintSkin(Graphics g) {
if (simulation == null) {
/* Skin was never activated */
return;
}
/* Paint transmission and interference range for select mote */
if (selectedMote != null) {
Graphics2D g2 = (Graphics2D) g;
Position motePos = selectedMote.getInterfaces().getPosition();
Point pixelCoord = visualizer.transformPositionToPixel(motePos);
@ -331,7 +364,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
translatedTransmission.y = Math.abs(translatedTransmission.y - translatedZero.y);
/* Interference range */
g.setColor(Color.DARK_GRAY);
g.setColor(COLOR_INTERFERENCE);
g.fillOval(
x - translatedInterference.x,
y - translatedInterference.y,
@ -339,7 +372,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
2 * translatedInterference.y);
/* Transmission range */
g.setColor(Color.GREEN);
g.setColor(COLOR_TX);
g.fillOval(
x - translatedTransmission.x,
y - translatedTransmission.y,
@ -348,9 +381,6 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
}
}
/* Skin generic visualization */
visualizer.paintSkinGeneric(g);
/* Paint active connections in black */
RadioConnection[] conns = radioMedium.getActiveConnections();
if (conns != null) {
@ -391,11 +421,15 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
}
public void doAction(Visualizer visualizer, Simulation simulation) {
UDGMVisualizerSkin skin = (UDGMVisualizerSkin) visualizer.getCurrentSkin();
skin.txRangeSpinner.setVisible(true);
skin.interferenceRangeSpinner.setVisible(true);
VisualizerSkin[] skins = visualizer.getCurrentSkins();
for (VisualizerSkin skin: skins) {
if (skin instanceof UDGMVisualizerSkin) {
((UDGMVisualizerSkin)skin).txRangeSpinner.setVisible(true);
((UDGMVisualizerSkin)skin).interferenceRangeSpinner.setVisible(true);
visualizer.repaint();
}
}
}
};
public static class SuccessRatioMenuAction implements SimulationMenuAction {
@ -408,11 +442,18 @@ public class UDGMVisualizerSkin implements VisualizerSkin {
}
public void doAction(Visualizer visualizer, Simulation simulation) {
UDGMVisualizerSkin skin = (UDGMVisualizerSkin) visualizer.getCurrentSkin();
skin.successRatioTxSpinner.setVisible(true);
skin.successRatioRxSpinner.setVisible(true);
VisualizerSkin[] skins = visualizer.getCurrentSkins();
for (VisualizerSkin skin: skins) {
if (skin instanceof UDGMVisualizerSkin) {
((UDGMVisualizerSkin)skin).successRatioTxSpinner.setVisible(true);
((UDGMVisualizerSkin)skin).successRatioRxSpinner.setVisible(true);
visualizer.repaint();
}
}
}
};
public Visualizer getVisualizer() {
return visualizer;
}
}