Commit a0faebc8 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Make the new node selector applet live, since no more feedback was

forthcoming ...
parent 12eeadb1
......@@ -14,8 +14,7 @@ include $(OBJDIR)/Makeconf
ifeq ($(JAVAC),)
JARS =
else
JARS = $(TESTBED_SRCDIR)/www/robotrack/tracker.jar \
$(TESTBED_SRCDIR)/www/robotrack/selector.jar
JARS = $(TESTBED_SRCDIR)/www/robotrack/tracker.jar
endif
all:
......
......@@ -30,9 +30,11 @@ public class NodeSelect extends JApplet {
private Selector selector;
int myHeight, myWidth;
String uid, auth, pid, eid;
double pixels_per_meter = 1.0;
double pixels_per_meter = 100.0;
URL urlServer;
static final DecimalFormat FORMATTER = new DecimalFormat("0.00");
static final int INCH =
Toolkit.getDefaultToolkit().getScreenResolution();
/* From the floormap generation code. */
int X_ADJUST = 60;
......@@ -43,6 +45,7 @@ public class NodeSelect extends JApplet {
int FONT_WIDTH = 10;
Font OurFont = null;
Font BoldFont = null;
Font RulerFont = null;
// The width of the list boxes.
int LISTBOX_WIDTH = 150;
......@@ -50,6 +53,10 @@ public class NodeSelect extends JApplet {
// For zooming ...
double scale = 1.0;
// rulers
int HORIZONTAL = 0;
int VERTICAL = 1;
/*
* A little class to hold info we need to get data from the server
* about buildings, floors, nodes.
......@@ -150,8 +157,9 @@ public class NodeSelect extends JApplet {
myHeight = appletSize.height;
myWidth = appletSize.width;
}
OurFont = new Font("Helvetica", Font.BOLD, 16);
BoldFont = new Font("Helvetica", Font.BOLD, 20);
OurFont = new Font("Helvetica", Font.BOLD, 12);
BoldFont = new Font("Helvetica", Font.BOLD, 20);
RulerFont = new Font("SansSerif", Font.PLAIN, 10);
/*
* Now add my one object to the contentpane.
......@@ -559,26 +567,28 @@ public class NodeSelect extends JApplet {
this.revalidate();
}
public void mousePressed(MouseEvent e) {
int button = e.getButton();
int modifier = e.getModifiersEx();
int x = e.getX() + xoff;
int y = e.getY() - yoff;
Node node = null;
int button = e.getButton();
int modifier = e.getModifiersEx();
int x = e.getX() + xoff;
int y = e.getY() - yoff;
PhysNode pnode = null;
System.out.println("Clicked on " + e.getX() + "," + e.getY());
System.out.println("Clicked on " + x + "," + y);
if (x > 0 && y > 0 && x <= width && y <= height)
node = FindNode(this, (int)(x / scale), (int)(y / scale));
pnode = (PhysNode)
FindNode(this, (int)(x / scale), (int)(y / scale));
if (!e.isPopupTrigger()) {
if (node != null) {
SelectNode(node, modifier);
if (pnode != null) {
if (!pnode.allocated)
SelectNode(pnode, modifier);
return;
}
}
// Forward to outer event handler, including the node
selector.doPopupMenu(e, node);
selector.doPopupMenu(e, pnode);
}
public void mouseReleased(MouseEvent e) {
PhysMapPanel.mouseReleased(e);
......@@ -688,7 +698,7 @@ public class NodeSelect extends JApplet {
ListPanel.add(ToplistScroller);
// add a label for the lower list box
ListPanel.add(new JLabel("Selected Nodes"));
ListPanel.add(new JLabel("Assigned Nodes"));
// And add the lower listbox.
ListPanel.add(BotlistScroller);
......@@ -790,6 +800,9 @@ public class NodeSelect extends JApplet {
DefaultListModel model;
PhysNode pnode = (PhysNode) a.nextElement();
if (pnode.allocated)
continue;
if (pnode.selected)
model = (DefaultListModel) SelectList.getModel();
else
......@@ -801,11 +814,33 @@ public class NodeSelect extends JApplet {
}
/*
* Create a surrounding scroll pane.
* We need to force the physmappanel to layout now, so we
* figure out how big the ruler bars need to be. If we do not
* do that, the rulers will be 0 sized, and really hard to see!
*/
PhysMapPanel.getLayout().layoutContainer(PhysMapPanel);
Dimension physmapdim =
PhysMapPanel.getLayout().minimumLayoutSize(PhysMapPanel);
/*
* Create a surrounding scroll pane.
*/
PhysMapScrollPane = new JScrollPane(PhysMapPanel);
PhysMapScrollPane.setPreferredSize(new Dimension(mapwidth,
mapheight));
// Create the row and column headers (rulers, sortof).
Ruler columnView = new Ruler(HORIZONTAL);
Ruler rowView = new Ruler(VERTICAL);
// Make sure the rulers know how big they need to be.
columnView.setPreferredWidth(physmapdim.width);
rowView.setPreferredHeight(physmapdim.height);
PhysMapScrollPane.setColumnHeaderView(columnView);
PhysMapScrollPane.setRowHeaderView(rowView);
// Now we can add the scrollpane.
MapPanel.add(PhysMapScrollPane);
// Add add our two inner panels to the outer panel
......@@ -1487,11 +1522,23 @@ public class NodeSelect extends JApplet {
map.rescale();
}
// Force everything to layout again before getSize().
// Force everything to layout again.
revalidate();
validate();
repaint();
// Tell rulers to recompute their size.
Ruler ruler =
(Ruler) PhysMapScrollPane.getColumnHeader().getView();
ruler.reset();
ruler =
(Ruler) PhysMapScrollPane.getRowHeader().getView();
ruler.reset();
// Force everything to layout again.
revalidate();
validate();
/*
* Okay scale P so that it moves (thereby keeping the
* original position more or less centered).
......@@ -1543,6 +1590,118 @@ public class NodeSelect extends JApplet {
repaint();
}
}
/*
* This class and code comes from one of the examples on the Sun
* Java site.
*/
public class Ruler extends JComponent {
private int SIZE = 30;
private int orientation;
private int increment;
private int units;
public Ruler(int or) {
orientation = or;
// Tick every meter at any scale.
increment = (int) (pixels_per_meter * scale);
units = increment * 5;
}
public void reset () {
setsizes();
// Tick every meter at any scale.
increment = (int) (pixels_per_meter * scale);
units = increment * 5;
}
private void setsizes() {
int width;
int height;
if (orientation == HORIZONTAL) {
width = PhysMapPanel.getWidth();
height = SIZE;
}
else {
width = SIZE;
height = PhysMapPanel.getHeight();
}
System.out.println(orientation + ": " + width + "," + height);
setPreferredSize(new Dimension(width, height));
}
public int getIncrement() {
return increment;
}
public void setPreferredHeight(int ph) {
setPreferredSize(new Dimension(SIZE, ph));
}
public void setPreferredWidth(int pw) {
setPreferredSize(new Dimension(pw, SIZE));
}
protected void paintComponent(Graphics g) {
Rectangle drawHere = g.getClipBounds();
//System.out.println(drawHere);
// Fill clipping area with dirty brown/orange.
g.setColor(new Color(230, 163, 4));
g.fillRect(drawHere.x, drawHere.y,
drawHere.width, drawHere.height);
// Do the ruler labels in a small font that's black.
g.setFont(RulerFont);
g.setColor(Color.black);
// Some vars we need.
int end = 0;
int start = 0;
int tickLength = 0;
String label = null;
// Use clipping bounds to calculate first and last locations.
if (orientation == HORIZONTAL) {
start = (drawHere.x / increment) * increment;
end = (((drawHere.x + drawHere.width) / increment) + 1)
* increment;
}
else {
start = (drawHere.y / increment) * increment;
end = (((drawHere.y + drawHere.height) / increment) + 1)
* increment;
}
//System.out.println("Rulers Painting(" + orientation + "): " +
// start + "," + end);
// Draw ticks
for (int i = start; i < end; i += increment) {
if (i != 0 && i % units == 0) {
tickLength = 10;
label = Integer.toString(i/increment);
}
else {
tickLength = 7;
label = null;
}
if (tickLength != 0) {
if (orientation == HORIZONTAL) {
g.drawLine(i, SIZE-1, i, SIZE-tickLength-1);
if (label != null)
g.drawString(label, i-4, 15);
}
else {
g.drawLine(SIZE-1, i, SIZE-tickLength-1, i);
if (label != null)
g.drawString(label, 2, i+5);
}
}
}
}
}
}
/*
......
......@@ -334,13 +334,13 @@ elsif (@ARGV == 1) {
my $path_col = ($scale_arg == 0 ? "thumb_path" : "image_path");
my $db_scale = max($scale_arg, 1);
# Nozoom signals a call by robotmap. Don't use robots "building" otherwise.
my $robo_bldg = "b.building ". ($nozoom ? "" : "not "). "like '%ROBOTS%'";
my $robo_bldg = ($nozoom ? "" : "b.building not like '%ROBOTS%' and ");
my $query_result =
DBQueryFatal("select b.building,b.title,f.floor,f.$path_col,".
"f.pixels_per_meter ".
" from buildings as b ".
"left join floorimages as f on f.building=b.building ".
"where $robo_bldg and f.scale=$db_scale");
"where $robo_bldg f.scale=$db_scale");
if (!$query_result->numrows) {
die("*** $0:\n".
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -126,13 +126,13 @@ if (!(defined $min_x)) {
# adjust each node's position so topleftmost node is at (60,60) * $zoom.
foreach $i (keys %nodes) {
$nodes{$i}{"x"} = ($nodes{$i}{"x"} - $min_x + 60) * $zoom;
$nodes{$i}{"y"} = ($nodes{$i}{"y"} - $min_y + 60) * $zoom;
$nodes{$i}{"x"} = (($nodes{$i}{"x"} - $min_x) * $zoom) + 60;
$nodes{$i}{"y"} = (($nodes{$i}{"y"} - $min_y) * $zoom) + 60;
}
# adjust max x,y appropriately.
$max_x = ($max_x - $min_x + 120) * $zoom;
$max_y = ($max_y - $min_y + 120) * $zoom;
$max_x = (($max_x - $min_x) * $zoom) + 120;
$max_y = (($max_y - $min_y) * $zoom) + 120;
}
# get vlan list.
......
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# Copyright (c) 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
include("defs.php3");
......@@ -440,6 +440,9 @@ echo " Click on the dots below to see information about the node.\n";
echo " <br>\n";
echo " Click elsewhere on the map to set the center point for a zoomed-in view.\n";
echo " <br>\n";
echo " Check out the nifty new <a href=robotrack/selector.php3?building=MEB>";
echo "Java Applet</a> for selecting wireless nodes\n";
echo " <br>\n";
# Couldn't get JavaScript submit on checkbox to be portable to IE with map in form.
# Just use image buttons to show and invert the checkbox state. That works.
if ($ghost) {
......
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
chdir("..");
include("defs.php3");
#
# Only known and logged in users.
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
#
# Verify page arguments. Allow user to optionally specify building/floor.
#
if (isset($building) && $building != "") {
# Sanitize for the shell.
if (!preg_match("/^[-\w]+$/", $building)) {
PAGEARGERROR("Invalid building argument.");
}
}
else {
PAGEARGERROR("Must supply a building.");
}
if (isset($floor) && $floor != "") {
if (!preg_match("/^[-\w]+$/", $floor)) {
PAGEARGERROR("Invalid floor argument.");
}
}
else {
PAGEARGERROR("Must supply a floor.");
}
#
# Make sure it exists in the DB.
#
$query_result =
DBQueryFatal("select pixels_per_meter from floorimages ".
"where building='$building' and floor='$floor'");
if (!mysql_num_rows($query_result)) {
PAGEARGERROR("No such building/floor $building/$floor");
}
#
# Need cleanup "handler" to make sure temp files get deleted!
#
function CLEANUP()
{
global $prefix, $uid;
#
# The backend script (vis/floormap.in) removes all the temp files
# with the -c option. Yucky, but file perms and owners make this
# the easiest way to do it.
#
if (isset($prefix)) {
SUEXEC($uid, "nobody", "webfloormap -o $prefix -k ");
# This file does belong to the web server.
unlink($prefix);
}
exit();
}
register_shutdown_function("CLEANUP");
#
# Create a tempfile to use as a unique prefix; it is not actually used but
# serves the same purpose (The script uses ${prefix}.jpg and ${prefix}.map .)
#
$prefix = tempnam("/tmp", "floormap");
#
# Build the image.
#
$perl_args = "-o $prefix -t -z -n -x -v -y -f $floor $building";
$retval = SUEXEC($uid, "nobody", "webfloormap $perl_args",
SUEXEC_ACTION_IGNORE);
if ($retval) {
SUEXECERROR(SUEXEC_ACTION_USERERROR);
# Never returns.
die("");
}
#
# Now spit it back.
#
if (($fp = fopen("${prefix}.jpg", "r"))) {
header("Content-type: image/jpg");
fpassthru($fp);
}
else {
# No Data. Spit back a stub image.
header("Content-type: image/gif");
readfile("coming-soon-thumb.gif");
}
?>
......@@ -72,8 +72,18 @@ while ($row = mysql_fetch_array($query_result)) {
$or = $row["orientation"];
$mobile = ($class == "robot" ? 1 : 0);
# In meters.
$size = ($class == "robot" ? 0.27 : 0.07);
$radius = ($class == "robot" ? 0.18 : 0.04);
if ($class == "robot") {
$size = 0.27;
$radius = 0.18;
}
elseif ($class == "pc" || $class == "pcwireless") {
$size = 1.0;
$radius = 0.5;
}
else {
$size = 0.07;
$radius = 0.04;
}
$alloc = (isset($pid) ? 1 : 0);
if (!isset($vname))
......
......@@ -21,52 +21,59 @@ if (isset($building) && $building != "") {
PAGEARGERROR("Invalid building argument.");
}
# Optional floor argument. Sanitize for the shell.
if (isset($floor) && !preg_match("/^[-\w]+$/", $floor)) {
PAGEARGERROR("Invalid floor argument.");
if (isset($floor) && $floor != "") {
if (!preg_match("/^[-\w]+$/", $floor)) {
PAGEARGERROR("Invalid floor argument.");
}
}
else
unset($floor);
}
else {
$building = "MEB-ROBOTS";
$floor = 4;
}
if (!isset($pid) ||
strcmp($pid, "") == 0) {
PAGEARGERROR("You must provide a Project ID.");
}
if (!isset($eid) ||
strcmp($eid, "") == 0) {
PAGEARGERROR("You must provide an Experiment ID.");
}
if (!preg_match("/^[-\w]+$/", $pid)) {
PAGEARGERROR("Invalid pid argument.");
}
if (!preg_match("/^[-\w]+$/", $eid)) {
PAGEARGERROR("Invalid eid argument.");
if (isset($pid) && $pid != "" && isset($eid) && $eid != "") {
if (!preg_match("/^[-\w]+$/", $pid)) {
PAGEARGERROR("Invalid pid argument.");
}
if (!preg_match("/^[-\w]+$/", $eid)) {
PAGEARGERROR("Invalid eid argument.");
}
#
# Check to make sure this is a valid PID/EID tuple.
#
if (! TBValidExperiment($pid, $eid)) {
USERERROR("Experiment $pid/$eid is not a valid experiment.", 1);
}
}
#
# Check to make sure this is a valid PID/EID tuple.
#
if (! TBValidExperiment($pid, $eid)) {
USERERROR("Experiment $pid/$eid is not a valid experiment.", 1);
else {
unset($pid);
unset($eid);
}
$ppm = 1;
#
# Grab pixel_per_meters for above map.
# Grab map info. Might be more then a single floor of course.
#
$query_result =
DBQueryFatal("select pixels_per_meter from floorimages ".
"where building='$building' and floor='$floor'");
if (mysql_num_rows($query_result)) {
$row = mysql_fetch_array($query_result);
$ppm = $row["pixels_per_meter"];
if (isset($floor)) {
$query_result =
DBQueryFatal("select floor,pixels_per_meter from floorimages ".
"where building='$building' and scale=1 and ".
"floor='$floor'");
}
else {
USERERROR("No such building/floor $building/$floor", 1);
$query_result =
DBQueryFatal("select distinct fl.floor,fl.pixels_per_meter ".
" from location_info as loc ".
"left join floorimages as fl on ".
" loc.building=fl.building and loc.floor=fl.floor ".
"where fl.building='$building' and fl.scale=1 ".
"order by floor");
}
if (! mysql_num_rows($query_result)) {
USERERROR("No such building/floor", 1);
}
#
......@@ -78,83 +85,94 @@ echo "<table cellspacing=5 cellpadding=5 border=0 class=\"stealth\">
<table>
<tr><th colspan=2>Legend</th></tr>
<tr>
<td><img src='/autostatus-icons/redball.gif' alt=down></td>
<td nowrap=1>Dead Node</td>
<td><img src='/autostatus-icons/redball.gif' alt=allocated></td>
<td nowrap=1>Unavailable Node</td>
</tr>
<tr>
<td><img src='/autostatus-icons/greenball.gif' alt=down></td>
<td><img src='/autostatus-icons/greenball.gif'
alt=unassigned></td>
<td nowrap=1>Unassigned Node</td>
</tr>
<tr>
<td><img src='/autostatus-icons/yellowball.gif' alt=down></td>
<td><img src='/autostatus-icons/blueball.gif' alt=assigned></td>
<td nowrap=1>Assigned Node</td>
</tr>
<tr>
<td><img src='/autostatus-icons/yellowball.gif' alt=selected></td>
<td nowrap=1>Selected Node</td>
</tr>
</table>
</td>
<td class=stealth>This applet allows you to assign your virual nodes
to physical nodes. See below for instructions.
<td class=stealth>This applet allows you to select physical nodes
for your experiment. See below for instructions.
</td>
</tr>
</table><hr>\n";
#
# Create a tempfile to use as a unique prefix; it is not actually used but
# serves the same purpose (The script uses ${prefix}.jpg and ${prefix}.map .)
#
$prefix = tempnam("/tmp", "floormap");
#
# Get the unique part to send back.
#
if (!preg_match("/^\/tmp\/([-\w]+)$/", $prefix, $matches)) {
TBERROR("Bad tempnam: $prefix", 1);
}
$uniqueid = $matches[1];
$perl_args = "-o $prefix -t -z -n -x -v -y -f $floor $building";
$retval = SUEXEC($uid, "nobody", "webfloormap $perl_args",
SUEXEC_ACTION_IGNORE);
if ($retval) {
SUEXECERROR(SUEXEC_ACTION_USERERROR);
# Never returns.
die("");
}
$auth = $HTTP_COOKIE_VARS[$TBAUTHCOOKIE];
$baseurl = "../floormap_aux.php3?prefix=$uniqueid";
$auth = $HTTP_COOKIE_VARS[$TBAUTHCOOKIE];
$floorcount = mysql_num_rows($query_result);
$ppm = 1;
$index = 0;
echo "<applet name='selector' code='NodeSelect.class'
archive='selector.jar'
width='1025' height='1050'
archive='NodeSelect.jar'
width='1025' height='700'
alt='You need java to run this applet'>