Commit 5babfc66 authored by Matt Strum's avatar Matt Strum
Browse files

Cleaned and optimized interface

parent e47cf26a
......@@ -4,7 +4,7 @@
xmlns:pgmap="pgmap.*"
layout="vertical" paddingRight="0" paddingLeft="0" paddingTop="0" paddingBottom="0"
backgroundColor="#D2E1F0"
preinitialize="preinit()"
preinitialize="preinit();"
creationComplete="init();">
<mx:Script>
......@@ -48,7 +48,8 @@
private var chooseCMWindow:ChooseComponentManagerWindow;
private function preinit():void {
Security.allowInsecureDomain('maps.googleapis.com');
Security.allowDomain("*");
Security.allowInsecureDomain("*");
}
// Start out by asking the user for the CM URL
......
package pgmap
{
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.controls.Button;
import mx.core.Application;
import mx.managers.PopUpManager;
public class Common
{
......@@ -17,15 +22,28 @@ package pgmap
public static var notAvailableIcon:Class;
[Bindable]
[Embed(source="../../images/computer.png")]
[Embed(source="../../images/drive_network.png")]
public static var ownedIcon:Class;
[Bindable]
[Embed(source="../../images/link.png")]
public static var linkIcon:Class;
public static function assignIcon(val:Boolean):Class {
if (val)
return Common.availableIcon;
else
return Common.notAvailableIcon;
}
if (val)
return availableIcon;
else
return notAvailableIcon;
}
public static function assignAvailabilityIcon(val:Node):Class {
if(val.slice != null)
return ownedIcon;
else if (val.available)
return availableIcon;
else
return notAvailableIcon;
}
public static function kbsToString(bandwidth:Number):String {
var bw:String = "";
......@@ -42,5 +60,64 @@ package pgmap
public static function Main():pgmap {
return mx.core.Application.application as pgmap;
}
public static function firstToUpper (phrase : String) : String {
return phrase.substring(1, 0).toUpperCase()+phrase.substring(1);
}
public static function shortenString(phrase : String, size : int) : String {
if(phrase.length < size)
return phrase;
var removeChars:int = phrase.length - size + 3;
var upTo:int = (phrase.length / 2) - (removeChars / 2);
return phrase.substring(0, upTo) + "..." + phrase.substring(upTo + removeChars);
}
public static function getNodeButton(n:Node):Button {
var nodeButton:Button = new Button();
nodeButton.label = n.name;
nodeButton.setStyle("icon", Common.assignAvailabilityIcon(n));
nodeButton.addEventListener(MouseEvent.CLICK,
function openNode(event:MouseEvent):void {
viewNode(n);
}
);
return nodeButton;
}
public static function getLinkButton(ni:NodeInterface, nl:Link):Button {
var linkButton:Button = new Button();
linkButton.label = ni.id;
linkButton.setStyle("icon", Common.linkIcon);
linkButton.addEventListener(MouseEvent.CLICK,
function openLink(event:MouseEvent):void {
viewLink(nl);
}
);
return linkButton;
}
public static function viewLink(l:Link):void {
var lgWindow:LinkGroupAdvancedWindow = new LinkGroupAdvancedWindow();
lgWindow.main = Main();
PopUpManager.addPopUp(lgWindow, Main(), false);
PopUpManager.centerPopUp(lgWindow);
var ac:ArrayCollection = new ArrayCollection();
ac.addItem(l);
lgWindow.loadCollection(ac);
}
public static function viewNode(n:Node):void {
var ngWindow:NodeGroupAdvancedWindow = new NodeGroupAdvancedWindow();
ngWindow.main = Main();
PopUpManager.addPopUp(ngWindow, Main(), false);
PopUpManager.centerPopUp(ngWindow);
var ac:ArrayCollection = new ArrayCollection();
ac.addItem(n);
ngWindow.loadCollection(ac);
}
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@
<mx:Script>
<![CDATA[
import mx.managers.CursorManager;
import com.google.maps.View;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
......@@ -35,7 +36,6 @@
title = "Link Information";
}
loadLink(links[0]);
}
......@@ -46,6 +46,8 @@
public function loadLink(l:Link):void {
link = l;
txtBandwidth.text = Common.kbsToString(l.bandwidth);
interface1Button.setStyle("icon",Common.assignAvailabilityIcon(l.interface1.owner));
interface2Button.setStyle("icon",Common.assignAvailabilityIcon(l.interface2.owner));
}
public function viewRspec():void {
......@@ -54,17 +56,6 @@
PopUpManager.centerPopUp(rspecView);
rspecView.loadXml(link.rspec);
}
public function viewNode(n:Node):void {
var ngWindow:NodeGroupAdvancedWindow = new NodeGroupAdvancedWindow();
ngWindow.main = main;
PopUpManager.addPopUp(ngWindow, main, false);
PopUpManager.centerPopUp(ngWindow);
var ac:ArrayCollection = new ArrayCollection();
ac.addItem(n);
ngWindow.loadCollection(ac);
}
]]>
</mx:Script>
<mx:HDividedBox width="100%" height="100%">
......@@ -113,12 +104,11 @@
<mx:GridItem>
<mx:VBox horizontalAlign="right" width="100%">
<mx:Label text="Connects" fontWeight="bold"/>
<mx:Button label="View" click="viewNode(link.interface1.owner);"/>
</mx:VBox>
</mx:GridItem>
<mx:GridItem width="100%">
<mx:VBox width="100%">
<mx:Label text="{link.interface1.owner.name}"/>
<mx:Button id="interface1Button" label="{link.interface1.owner.name}" click="Common.viewNode(link.interface1.owner);"/>
<mx:Label text="on {link.interface1.id}"/>
</mx:VBox>
</mx:GridItem>
......@@ -127,12 +117,11 @@
<mx:GridItem>
<mx:VBox horizontalAlign="right" width="100%">
<mx:Label text="to" fontWeight="bold"/>
<mx:Button label="View" click="viewNode(link.interface2.owner);"/>
</mx:VBox>
</mx:GridItem>
<mx:GridItem width="100%">
<mx:VBox width="100%">
<mx:Label text="{link.interface2.owner.name}"/>
<mx:Button id="interface2Button" label="{link.interface2.owner.name}" click="Common.viewNode(link.interface2.owner);"/>
<mx:Label text="on {link.interface2.id}"/>
</mx:VBox>
</mx:GridItem>
......
......@@ -38,7 +38,9 @@
public var exclusive:Boolean;
public var slice : Slice = null;
public var status : String;
[Bindable]
public var status : String = "N/A";
[Bindable]
public var types:ArrayCollection = new ArrayCollection();
......@@ -65,5 +67,20 @@
}
return ac;
}
public function GetNodes():ArrayCollection {
var ac:ArrayCollection = new ArrayCollection();
for each(var i:NodeInterface in interfaces.collection) {
for each(var l:Link in i.links) {
if(l.interface1.owner != this && !ac.contains(l.interface1.owner)) {
ac.addItem(l.interface1.owner);
}
if(l.interface2.owner != this && !ac.contains(l.interface2.owner)) {
ac.addItem(l.interface2.owner);
}
}
}
return ac;
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ResizeWindow xmlns="pgmap.*" xmlns:mx="http://www.adobe.com/2006/mxml"
width="700" height="400" showCloseButton="true" layout="vertical"
width="900" height="400" showCloseButton="true" layout="vertical"
borderAlpha=".9" borderColor="#D2E1F0"
resizable="true"
title="Node Group Information"
......@@ -8,6 +8,9 @@
<mx:Script>
<![CDATA[
import mx.controls.Spacer;
import mx.containers.HBox;
import mx.controls.Button;
import com.google.maps.View;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
......@@ -51,46 +54,107 @@
public function loadNode(n:Node):void {
node = n;
imgAvailable.source = assignIcon(n);
imgAvailable.source = Common.assignAvailabilityIcon(n);
imgExclusive.source = Common.assignIcon(n.exclusive);
linkedNodes = new ArrayCollection();
linksEndpointVbox.removeAllChildren();
var endpointArray:ArrayCollection = new ArrayCollection();
var startpointArray:ArrayCollection = new ArrayCollection();
for each(var i:NodeInterface in n.interfaces.collection) {
for each(var l:Link in i.links) {
var ns:String;
var ins:String;
var n:Node;
var iEnd:NodeInterface;
var iStart:NodeInterface;
if(l.interface1 == i) {
ns = l.interface2.owner.name;
ins = l.interface1.id;
n = l.interface2.owner;
iEnd = l.interface2;
iStart = l.interface1;
} else {
ns = l.interface1.owner.name;
ins = l.interface2.id;
n = l.interface1.owner;
iEnd = l.interface1;
iStart = l.interface2;
}
// Build up endpoint
var nodeFound:Boolean = false;
for each(var na:Object in endpointArray) {
if(na.node == n) {
nodeFound = true;
na.links.addItem({i: iEnd, l: l});
break;
}
}
if(!nodeFound) {
var newLinks:ArrayCollection = new ArrayCollection();
newLinks.addItem({i: iEnd, l: l});
endpointArray.addItem({node: n, links: newLinks});
}
linkedNodes.addItem({name: ns + " on " + ins, link: l});
// Build up startpoint
var interfaceFound:Boolean = false;
for each(var ia:Object in startpointArray) {
if(ia.link.i == iStart) {
interfaceFound = true;
if(!ia.nodes.contains(n))
ia.nodes.addItem(n);
break;
}
}
if(!interfaceFound) {
var newNodes:ArrayCollection = new ArrayCollection();
newNodes.addItem(n);
startpointArray.addItem({link: {i: iStart, l: l}, nodes: newNodes});
}
}
}
// Build endpoint interface
for each(var nodeInfo:Object in endpointArray) {
linksEndpointVbox.addChild(Common.getNodeButton(nodeInfo.node));
for each(var nodeLink:Object in nodeInfo.links) {
var linkHbox:HBox = new HBox();
var space:Spacer = new Spacer();
space.width = 16;
linkHbox.addChild(space);
linkHbox.addChild(Common.getLinkButton(nodeLink.i, nodeLink.l));
linksEndpointVbox.addChild(linkHbox);
}
}
// Build startpoint interface
for each(var linkInfo:Object in startpointArray) {
linksStartpointVbox.addChild(Common.getLinkButton(linkInfo.link.i, linkInfo.link.l));
for each(var node:Node in linkInfo.nodes) {
var linkHbox2:HBox = new HBox();
var space2:Spacer = new Spacer();
space2.width = 16;
linkHbox2.addChild(space2);
linkHbox2.addChild(Common.getNodeButton(node));
linksStartpointVbox.addChild(linkHbox2);
}
}
}
public function viewLink(l:Link):void {
public function viewLinks():void {
var lgWindow:LinkGroupAdvancedWindow = new LinkGroupAdvancedWindow();
lgWindow.main = main;
PopUpManager.addPopUp(lgWindow, main, false);
PopUpManager.centerPopUp(lgWindow);
var ac:ArrayCollection = new ArrayCollection();
ac.addItem(l);
lgWindow.loadCollection(ac);
lgWindow.title = node.name + "'s Links";
lgWindow.loadCollection(node.GetLinks());
}
public function viewLinks():void {
var lgWindow:LinkGroupAdvancedWindow = new LinkGroupAdvancedWindow();
lgWindow.main = main;
PopUpManager.addPopUp(lgWindow, main, false);
PopUpManager.centerPopUp(lgWindow);
public function viewNodes():void {
var hgWindow:NodeGroupAdvancedWindow = new NodeGroupAdvancedWindow();
hgWindow.main = main;
PopUpManager.addPopUp(hgWindow, main, false);
PopUpManager.centerPopUp(hgWindow);
lgWindow.loadCollection(node.GetLinks());
hgWindow.loadCollection(node.GetNodes());
}
public function viewRspec():void {
......@@ -101,16 +165,7 @@
}
private function assignAvailableIcon(item:Object):Class {
return assignIcon(item as Node);
}
private function assignIcon(val:Node):Class {
if(val.slice != null)
return Common.ownedIcon;
else if (val.available)
return Common.availableIcon;
else
return Common.notAvailableIcon;
return Common.assignAvailabilityIcon(item as Node);
}
]]>
</mx:Script>
......@@ -134,8 +189,11 @@
<mx:Label text="Exclusive" fontWeight="bold"/>
<mx:Image id="imgExclusive"/>
<mx:VRule height="16"/>
<mx:Label text="Available" fontWeight="bold"/>
<mx:Label text="Availability" fontWeight="bold"/>
<mx:Image id="imgAvailable"/>
<mx:VRule height="16"/>
<mx:Label text="Status" fontWeight="bold"/>
<mx:Label text="{node.status}" fontWeight="normal"/>
</mx:GridItem>
</mx:GridRow>
<mx:GridRow width="100%">
......@@ -154,7 +212,7 @@
<mx:Label text="{node.manager}"/>
</mx:GridItem>
</mx:GridRow>
<mx:GridRow width="100%" height="100%">
<mx:GridRow width="100%" height="86">
<mx:GridItem>
<mx:Label text="Types" fontWeight="bold"/>
</mx:GridItem>
......@@ -172,11 +230,19 @@
<mx:GridItem>
<mx:VBox horizontalAlign="right">
<mx:Label text="Links to" fontWeight="bold"/>
<mx:Button label="All" click="viewLinks();" width="100%"/>
<mx:HRule width="32"/>
<mx:Label text="View all" fontWeight="normal"/>
<mx:Button label="Links" click="viewLinks();" width="100%"/>
<mx:Button label="Nodes" click="viewNodes();" width="100%"/>
</mx:VBox>
</mx:GridItem>
<mx:GridItem width="100%">
<mx:List width="100%" height="100%" id="listInterfaces" dataProvider="{linkedNodes}" labelField="name" change="viewLink(listInterfaces.selectedItem.link);"></mx:List>
<mx:TabNavigator width="100%" height="100%" paddingTop="2" paddingRight="2" paddingLeft="2" paddingBottom="2">
<mx:VBox label="Endpoint" width="100%" height="100%" id="linksEndpointVbox">
</mx:VBox>
<mx:VBox label="Startpoint" width="100%" height="100%" id="linksStartpointVbox">
</mx:VBox>
</mx:TabNavigator>
</mx:GridItem>
</mx:GridRow>
</mx:Grid>
......
......@@ -14,6 +14,8 @@
package pgmap
{
import mx.collections.ArrayCollection;
public class ProtoGeniHandler
{
public var main : pgmap;
......@@ -24,10 +26,12 @@
[Bindable]
public var map : ProtoGeniMapHandler;
public var CurrentUser:User = new User();
public var Nodes:NodeGroupCollection = new NodeGroupCollection();
public var Links:LinkGroupCollection = new LinkGroupCollection();
public var slice:Slice = new Slice();
public var Slices:ArrayCollection = new ArrayCollection();
public function ProtoGeniHandler(m:pgmap)
{
......@@ -42,6 +46,7 @@
{
Nodes = new NodeGroupCollection();
Links = new LinkGroupCollection();
Slices = new ArrayCollection();
}
public function getCredential(afterCompletion : Function):void {
......@@ -50,7 +55,7 @@
}
public function guarenteeCredential(afterCompletion : Function):void {
if(rpc.hasCredential())
if(CurrentUser.credential != null)
afterCompletion();
else
getCredential(afterCompletion);
......@@ -168,10 +173,12 @@
afterCompletion();
}
public function addSliceNode(urn:String):void {
public function addSliceNode(urn:String, status:String, sl:Slice):void {
var n : Node = Nodes.GetByUUID(urn);
if(n != null)
n.slice = slice;
if(n != null) {
n.slice = sl;
n.status = Common.firstToUpper(status);
}
}
}
}
\ No newline at end of file
......@@ -64,7 +64,8 @@ package pgmap
function(event:GeocodingEvent):void {
//Alert.show("Geocoding failed");
});
geocoder.reverseGeocode(new LatLng(g.latitude, g.longitude));
//geocoder.reverseGeocode(new LatLng(g.latitude, g.longitude));
m.addEventListener(MapMouseEvent.CLICK, function(e:Event):void {
m.openInfoWindow(
......
/* GENIPUBLIC-COPYRIGHT
* Copyright (c) 2009 University of Utah and the Flux Group.
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. THE UNIVERSITY OF UTAH DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
package pgmap
{
import com.mattism.http.xmlrpc.MethodFault;
import flash.events.ErrorEvent;
import flash.utils.ByteArray;
import mx.utils.Base64Decoder;
public class ProtoGeniRpcHandler
{
public var op : Operation;
public var opName : String;
public var slice : Slice;
[Bindable]
public var useCompression : Boolean = true;
public var sliceNodes : Array;
public var sliceNodesStatus : Array;
public var main : pgmap;
public var ComponentManagerURL:String = "https://boss.emulab.net:443/protogeni/xmlrpc/cm";
public var Rspec:XML = null;
[Bindable]
public var Components:Array = null;
public var AfterCall:Function;
public function ProtoGeniRpcHandler()
{
op = new Operation(null);
opName = null;
}
public function clearAll() : void
{
Components = null;
Rspec = null;
}
public function postCall() : void {
main.console.appendText("Seeing if there are any other method to call...\n");
if(AfterCall != null) {
main.console.appendText("Doing a post call...\n");
AfterCall();
}
}
public function failure(event : ErrorEvent, fault : MethodFault) : void
{
main.openConsole();
main.setProgress("Operation failed!", Common.failColor);
main.stopWaiting();
main.console.appendText("****fail****");
if (fault != null)
{
main.console.appendText("\nFAILURE fault: " + opName + ": "
+ fault.getFaultString());
}
else
{
main.console.appendText("\nFAILURE event: " + opName + ": "
+ event.toString());