Commit fedf874f authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Another checkpoint. More stuff working ...

parent 35488b0e
......@@ -29,7 +29,7 @@ public class NodeSelect extends JApplet {
private boolean shelled = false;
private Selector selector;
int myHeight, myWidth;
String uid, auth, pid, eid, floor, building;
String uid, auth, pid, eid;
double pixels_per_meter = 1.0;
URL urlServer;
static final DecimalFormat FORMATTER = new DecimalFormat("0.00");
......@@ -39,44 +39,78 @@ public class NodeSelect extends JApplet {
int Y_ADJUST = 60;
// The font width/height adjustment, for drawing labels.
int FONT_HEIGHT = 14;
int FONT_WIDTH = 6;
int FONT_HEIGHT = 16;
int FONT_WIDTH = 10;
Font OurFont = null;
Font BoldFont = null;
// The width of the list boxes.
int LISTBOX_WIDTH = 150;
public void init() {
URL phyURL = null;
String phyurl;
// For zooming ...
double scale = 1.0;
OurFont = new Font("Arial", Font.PLAIN, 14);
/*
* A little class to hold info we need to get data from the server
* about buildings, floors, nodes.
*/
private class FloorInfo {
String building;
String floor;
URL icon_url;
}
public void init() {
String building;
/*
* An array of floorinfo thingies.
*/
int floorcount;
FloorInfo floorinfo[] = null;
try
{
/* Get our parameters */
uid = this.getParameter("uid");
auth = this.getParameter("auth");
pid = this.getParameter("pid");
eid = this.getParameter("eid");
floor = this.getParameter("floor");
building = this.getParameter("building");
phyurl = this.getParameter("floorurl");
uid = this.getParameter("uid");
auth = this.getParameter("auth");
pid = this.getParameter("pid");
eid = this.getParameter("eid");
floorcount = Integer.parseInt(this.getParameter("floorcount"));
building = this.getParameter("building");
pixels_per_meter = Double.parseDouble(this.getParameter("ppm"));
// form the URL that we use to get the physical layout icon
phyURL = new URL(this.getCodeBase(),
phyurl
+ "&nocookieuid="
+ URLEncoder.encode(uid)
+ "&nocookieauth="
+ URLEncoder.encode(auth));
// Now we can create this ...
floorinfo = new FloorInfo[floorcount];
for (int i = 0; i < floorcount; i++) {
String paramname = "floor_" + i;
String floorname;
if ((floorname = this.getParameter(paramname)) == null)
continue;
floorinfo[i] = new FloorInfo();
floorinfo[i].floor = floorname;
floorinfo[i].building = building;
// form the URL that we use to get the physical layout icon
floorinfo[i].icon_url = new URL(this.getCodeBase(),
"flooricon.php3?building="
+ building
+ "&floor="
+ floorname
+ "&nocookieuid="
+ URLEncoder.encode(uid)
+ "&nocookieauth="
+ URLEncoder.encode(auth));
}
}
catch(Throwable th)
{
th.printStackTrace();
}
init(false, phyURL);
init(false, floorinfo);
}
public void start() {
......@@ -86,7 +120,28 @@ public class NodeSelect extends JApplet {
}
// For the benefit of running from the shell for testing.
public void init(boolean fromshell, URL phyURL) {
public void init(boolean fromshell, URL url) {
FloorInfo floorinfo[] = new FloorInfo[3];
floorinfo[0] = new FloorInfo();
floorinfo[0].floor = "1";
floorinfo[0].building = "MEB";
floorinfo[0].icon_url = url;
floorinfo[1] = new FloorInfo();
floorinfo[1].floor = "2";
floorinfo[1].building = "MEB";
floorinfo[1].icon_url = url;
floorinfo[2] = new FloorInfo();
floorinfo[2].floor = "3";
floorinfo[2].building = "MEB";
floorinfo[2].icon_url = url;
init(fromshell, floorinfo);
}
public void init(boolean fromshell, FloorInfo floorinfo[]) {
shelled = fromshell;
if (!shelled) {
......@@ -95,33 +150,22 @@ public class NodeSelect extends JApplet {
myHeight = appletSize.height;
myWidth = appletSize.width;
}
JLayeredPane MyLPane = getLayeredPane();
JPanel MyJPanel = new JPanel(true);
/*
* Specify vertical placement of components inside my JPanel.
*/
MyJPanel.setLayout(new BoxLayout(MyJPanel, BoxLayout.Y_AXIS));
/*
* Now add the basic objects to the JPanel.
*/
selector = new Selector(phyURL);
MyJPanel.add(selector);
OurFont = new Font("Helvetica", Font.BOLD, 16);
BoldFont = new Font("Helvetica", Font.BOLD, 20);
/*
* Add the JPanel to the layeredPane, but give its size since
* there is no layout manager.
* Now add my one object to the contentpane.
*/
MyLPane.add(MyJPanel, JLayeredPane.DEFAULT_LAYER);
MyJPanel.setBounds(0, 0, myWidth, myHeight);
selector = new Selector(floorinfo);
getContentPane().setLayout(new BoxLayout(getContentPane(),
BoxLayout.Y_AXIS));
getContentPane().add(selector);
}
/*
* A container for stuff that is common to both virtnodes and physnodes.
*/
private class Node {
private class Node implements Comparable {
String vname;
String pname;
int radius = 15; // Radius of circle, in pixels
......@@ -129,6 +173,7 @@ public class NodeSelect extends JApplet {
int x, y; // Current x,y coords in pixels
int listindex; // Where it sits in its listbox.
boolean picked; // Node is within a selection
boolean mouseover; // currently mousedover
Object map; // Pointer back to activemap.
/*
......@@ -148,6 +193,20 @@ public class NodeSelect extends JApplet {
this.y = y;
this.y_meters = FORMATTER.format(y / pixels_per_meter);
}
public int scaledX() {
return (int) (x * scale);
}
public int scaledY() {
return (int) (y * scale);
}
// Comparator interface for sorting below.
public int compareTo(Object o) {
Node other = (Node) o;
return this.pname.compareTo(other.pname);
}
}
/*
......@@ -208,7 +267,9 @@ public class NodeSelect extends JApplet {
/*
* The actual object.
*/
private class Selector extends JPanel implements ActionListener {
private class Selector extends JPanel implements ActionListener,
MouseListener
{
JLabel MessageArea;
// Indexed by the virtual name, points to VirtNode struct above.
Dictionary VirtNodes;
......@@ -219,16 +280,13 @@ public class NodeSelect extends JApplet {
// For the menu items.
Dictionary MenuHandlers = new Hashtable();
// Not sure how I am going to use this yet. Zooming eventually ...
double scale = 0.5;
// The lists boxes, one for all nodes and one for selected nodes.
JList AllPhysList;
JList SelectList;
// The physmap scroll pane.
JScrollPane PhysMapScrollPane;
// The panel behind the scroll pane.
ScrollablePanel PhysMapPanel;
// The root menu.
JPopupMenu RootPopupMenu;
......@@ -237,6 +295,127 @@ public class NodeSelect extends JApplet {
// For the node menu, need to know what the node was!
Node PopupNode;
// Last centering target.
Rectangle LastCenter = null;
private class ScrollablePanel extends JPanel
implements Scrollable, MouseMotionListener {
private int maxUnitIncrement = 5;
public ScrollablePanel() {
super();
// enable synthetic drag events
setAutoscrolls(true);
addMouseMotionListener(this);
}
private Point lastpoint = null;
// I do not want to be heap allocating points every event!
private Point Ptemp = new Point();
private Point Pview = new Point();
public void mouseReleased(MouseEvent e) {
lastpoint = null;
}
// Methods required by MouseMotionListener
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
// Current view position. I hate to heap allocate a point.
Rectangle view = PhysMapScrollPane.getViewport().getViewRect();
// Map the current event to screen coordinates.
Ptemp.x = e.getX();
Ptemp.y = e.getY();
javax.swing.SwingUtilities.convertPointToScreen(Ptemp,
e.getComponent());
// So we can track how far the user moved the mouse since
// the last event came in.
if (lastpoint == null)
lastpoint = new Point(Ptemp.x, Ptemp.y);
// Move the current view point in the direction the user moved.
view.x = view.x + (lastpoint.x - Ptemp.x);
view.y = view.y + (lastpoint.y - Ptemp.y);
//System.out.println("view 1 " + view);
//System.out.println("x,y " + getWidth() +
// "," + getHeight());
// But make sure we do not scroll it off screen.
if (view.x + view.width > getWidth())
view.x = getWidth() - view.width;
if (view.y + view.height > getHeight())
view.y = getHeight() - view.height;
if (view.x < 0)
view.x = 0;
if (view.y < 0)
view.y = 0;
// Save for next event.
lastpoint.x = Ptemp.x;
lastpoint.y = Ptemp.y;
// System.out.println("view 2 " + view);
// And move the viewport. I use setviewposition instead of
// scrollrect cause it appears to do (exactly) what I want.
Pview.x = view.x;
Pview.y = view.y;
PhysMapScrollPane.getViewport().setViewPosition(Pview);
repaint();
}
// Methods required by the Scrollable.
public Dimension getPreferredSize() {
return super.getPreferredSize();
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
public boolean getScrollableTracksViewportWidth() {
return false;
}
public boolean getScrollableTracksViewportHeight() {
return false;
}
public void setMaxUnitIncrement(int pixels) {
maxUnitIncrement = pixels;
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation,
int direction) {
if (orientation == SwingConstants.HORIZONTAL)
return visibleRect.width - maxUnitIncrement;
else
return visibleRect.height - maxUnitIncrement;
}
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation,
int direction) {
// Get the current position.
int currentPosition = 0;
if (orientation == SwingConstants.HORIZONTAL)
currentPosition = visibleRect.x;
else
currentPosition = visibleRect.y;
// Return the number of pixels between currentPosition
// and the nearest tick mark in the indicated direction.
if (direction < 0) {
int newPosition = currentPosition -
(currentPosition / maxUnitIncrement) *
maxUnitIncrement;
return (newPosition == 0) ? maxUnitIncrement : newPosition;
}
else {
return ((currentPosition / maxUnitIncrement) + 1)
* maxUnitIncrement - currentPosition;
}
}
}
/*
* This is a subclass of Icon, that draws the nodes in where they
* are supposed to be, superimposed over the base icon.
......@@ -253,22 +432,26 @@ public class NodeSelect extends JApplet {
myicon = icon;
NodeList = nodelist;
iconWidth = icon.getIconWidth();
iconHeight = icon.getIconHeight();
iconWidth = (int) (icon.getIconWidth() * scale);
iconHeight = (int) (icon.getIconHeight() * scale);
}
public int getIconHeight() {
return (int) (iconHeight * scale);
return iconHeight;
}
public int getIconWidth() {
return (int) (iconWidth * scale);
return iconWidth;
}
public void rescale() {
iconWidth = (int) (myicon.getIconWidth() * scale);
iconHeight = (int) (myicon.getIconHeight() * scale);
}
/*
* The paint method sticks the little dots in.
* Note X,Y in here do not need to be scaled since the G2
* will apply the scaling to all the coords used.
*/
public void paintIcon(Component c, Graphics g, int x, int y) {
System.out.println("Icon Painting at " + x + "," + y);
Graphics2D g2 = (Graphics2D) g;
g2.scale(scale, scale);
myicon.paintIcon(c, g2, x, y);
......@@ -279,16 +462,20 @@ public class NodeSelect extends JApplet {
Enumeration e = NodeList.elements();
while (e.hasMoreElements()) {
Node node = (Node)e.nextElement();
PhysNode node = (PhysNode) e.nextElement();
String label = node.pname;
/*
* Draw a little circle where the node lives.
*/
if (node.picked)
g.setColor(Color.green);
else
if (node.allocated)
g.setColor(Color.red);
else if (node.picked)
g.setColor(Color.yellow);
else if (node.selected)
g.setColor(Color.blue);
else
g.setColor(Color.green);
g.fillOval(node.x - node.radius,
node.y - node.radius,
......@@ -301,28 +488,39 @@ public class NodeSelect extends JApplet {
int lx = node.x - ((FONT_WIDTH * label.length()) / 2);
int ly = node.y + node.radius + FONT_HEIGHT;
g.setColor(Color.black);
if (node.mouseover) {
g.setColor(Color.blue);
g2.setFont(BoldFont);
}
else {
g.setColor(Color.black);
g2.setFont(OurFont);
}
g.drawString(label, lx, ly);
}
// Restore Graphics object
g2.scale(1.0 - scale, 1.0 - scale);
//g2.scale(1.0 - scale, 1.0 - scale);
}
}
/*
* A little class that creates an active map for clicking on.
*/
private class ActiveMap extends JLabel implements MouseListener {
private class ActiveMap extends JLabel
implements MouseListener, MouseMotionListener
{
int width, height, xoff = 0, yoff = 0;
boolean isvirtmap;
Dictionary NodeList;
FloorIcon flooricon;
Node mousedover = null;
public ActiveMap(FloorIcon flooricon, Dictionary nodelist,
int thiswidth, int thisheight, boolean virtmap) {
super(flooricon);
this.flooricon = flooricon;
this.addMouseListener(this);
this.addMouseMotionListener(this);
NodeList = nodelist;
isvirtmap = virtmap;
......@@ -344,8 +542,15 @@ public class NodeSelect extends JApplet {
yoff = ((thisheight / 2) / 2) - (height / 2);
}
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public void rescale() {
flooricon.rescale();
// Pick up new scale.
width = flooricon.getIconWidth();
height = flooricon.getIconHeight();
......@@ -376,19 +581,49 @@ public class NodeSelect extends JApplet {
selector.doPopupMenu(e, node);
}
public void mouseReleased(MouseEvent e) {
PhysMapPanel.mouseReleased(e);
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
// MouseMotionListener interface methods.
public void mouseDragged(MouseEvent e) {
// Drag panel on left-click and hold.
if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0)
PhysMapPanel.mouseDragged(e);
}
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Node node = null;
node = FindNode(this, (int)(x / scale), (int)(y / scale));
if (node != null) {
node.mouseover = true;
if (mousedover != null) {
if (node == mousedover)
return;
mousedover.mouseover = false;
}
mousedover = node;
repaint();
return;
}
// Not over anything; be sure to clear the current one.
if (mousedover != null) {
mousedover.mouseover = false;
mousedover = null;
repaint();
}
}
}
public Selector(URL phyURL) {
public Selector(FloorInfo floorinfo[]) {
ActiveMap activemap;
Dictionary PhysNodes;
......@@ -434,6 +669,10 @@ public class NodeSelect extends JApplet {
ListSelectionHandler mylsh = new ListSelectionHandler();
AllPhysList.getSelectionModel().addListSelectionListener(mylsh);
SelectList.getSelectionModel().addListSelectionListener(mylsh);
// So we get mouse events in the lists panels.
AllPhysList.addMouseListener(this);
SelectList.addMouseListener(this);
AllPhysList.setLayoutOrientation(JList.VERTICAL);
SelectList.setLayoutOrientation(JList.VERTICAL);
......@@ -463,20 +702,24 @@ public class NodeSelect extends JApplet {
/*
* And a panel to put all the little scroll panes in.
*/
JPanel ScrolledPanel = new JPanel(true);
PhysMapPanel = new ScrollablePanel();
/*
* Specify vertical placement of components inside this panel
*/
ScrolledPanel.setLayout(new BoxLayout(ScrolledPanel,
PhysMapPanel.setLayout(new BoxLayout(PhysMapPanel,
BoxLayout.Y_AXIS));
/*
* Get the physnodes info. Each submap is added to a large
* panel, which we then add to a scroll pane.
*/
for (int i = 0; i < 3; i++) {
if ((PhysNodes = GetNodeInfo()) == null) {
for (int i = 0; i < floorinfo.length; i++) {
String floor = floorinfo[i].floor;
String building = floorinfo[i].building;
URL icon_url = floorinfo[i].icon_url;
if ((PhysNodes = GetNodeInfo(building, floor)) == null) {
MyDialog("GetNodeInfo",
"Failed to get physical node list from server");
}
......@@ -493,15 +736,15 @@ public class NodeSelect extends JApplet {
* Stick in a title to let the user know what floor/building.
*/
JLabel TitleArea =
new JLabel("Here is where the building/floor name goes");
new JLabel(building + ", " + floor);
TitleArea.setAlignmentX(Component.CENTER_ALIGNMENT);
ScrolledPanel.add(TitleArea);
PhysMapPanel.add(TitleArea);
activemap = new
ActiveMap(new FloorIcon(getImageIcon(phyURL), PhysNodes),
ActiveMap(new FloorIcon(getImageIcon(icon_url), PhysNodes),
PhysNodes, mapwidth, mapheight, false);
activemap.setAlignmentX(Component.CENTER_ALIGNMENT);
ScrolledPanel.add(activemap);
PhysMapPanel.add(activemap);
// Remember them all in a list.
PhysMaps.insertElementAt(activemap, i);
......@@ -560,7 +803,7 @@ public class NodeSelect extends JApplet {
/*
* Create a surrounding scroll pane.
*/
PhysMapScrollPane = new JScrollPane(ScrolledPanel);
PhysMapScrollPane = new JScrollPane(PhysMapPanel);
PhysMapScrollPane.setPreferredSize(new Dimension(mapwidth,
mapheight));
MapPanel.add(PhysMapScrollPane);
......@@ -616,6 +859,18 @@ public class NodeSelect extends JApplet {
MenuHandlers.put("ZoomOut", new ZoomMenuHandler(menuitem));
RootPopupMenu.add(menuitem);
menuitem = new JMenuItem("Recenter");
menuitem.setActionCommand("Recenter");
menuitem.addActionListener(this);
MenuHandlers.put("Recenter", new RecenterMenuHandler(menuitem));
RootPopupMenu.add(menuitem);
menuitem = new JMenuItem("Reset Zoom/Center");
menuitem.setActionCommand("Reset");
menuitem.addActionListener(this);
MenuHandlers.put("Reset", new ZoomMenuHandler(menuitem));
RootPopupMenu.add(menuitem);
RootPopupMenu.addSeparator();
menuitem = new JMenuItem("Close This Menu");