Initial commit.
authorMarco Yuen <marcoy@gmail.com>
Fri, 21 May 2010 17:03:17 +0000 (10:03 -0700)
committerMarco Yuen <marcoy@gmail.com>
Fri, 21 May 2010 17:03:17 +0000 (10:03 -0700)
20 files changed:
.gitignore [new file with mode: 0644]
Configure.py [new file with mode: 0644]
Identities.py [new file with mode: 0644]
Info.py [new file with mode: 0644]
OpenCirrus.py [new file with mode: 0644]
PlanetLab.py [new file with mode: 0644]
SfaBrowser.py [new file with mode: 0644]
SfaData.py [new file with mode: 0644]
SfaGUI.py [new file with mode: 0644]
Sink.py [new file with mode: 0644]
SinkList.py [new file with mode: 0644]
Slices.py [new file with mode: 0644]
VINI.py [new file with mode: 0644]
build.sh [new file with mode: 0755]
public/SfaGUI.css [new file with mode: 0644]
public/SfaGUI.html [new file with mode: 0644]
public/SplitPanel.css [new file with mode: 0644]
public/images/hborder.png [new file with mode: 0644]
public/images/vborder.png [new file with mode: 0644]
public/splitPanelThumb.png [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ea1472e
--- /dev/null
@@ -0,0 +1 @@
+output/
diff --git a/Configure.py b/Configure.py
new file mode 100644 (file)
index 0000000..ef7fd76
--- /dev/null
@@ -0,0 +1,90 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.Composite import Composite
+from pyjamas.ui.RootPanel import RootPanel
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.HorizontalPanel import HorizontalPanel
+from pyjamas.ui.CaptionPanel import CaptionPanel
+from pyjamas.ui.TextBox import TextBox
+from pyjamas.ui.Button import Button
+from pyjamas.ui.HTML import HTML
+from pyjamas.ui.Grid import Grid
+from pyjamas.ui import HasAlignment
+from SfaData import SfaData
+
+class TopPanel(Composite):
+    panel = None
+
+    def __init__(self):
+        TopPanel.panel = self
+        Composite.__init__(self)
+        self.data = SfaData()
+
+        self.outer = HorizontalPanel()
+        self.inner = VerticalPanel()
+
+        self.outer.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT)
+        self.inner.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT)
+
+        # No links right now...
+        self.links = HorizontalPanel()
+        self.links.setSpacing(4)
+
+        self.outer.add(self.inner)
+        self.refresh()
+
+        self.initWidget(self.outer)
+
+    def onClick(self, sender):
+        pass
+
+    def refresh(self):
+        self.inner.clear()
+        self.inner.add(HTML("<b>User: %s</b>" % self.data.getUser()))
+        self.inner.add(HTML("<b>Slice: %s</b>" % self.data.getSlice()))
+        self.inner.add(self.links)
+
+class LabeledTextBox:
+    def __init__(self, label, initialText):
+        self.hp = CaptionPanel(label)
+        self.tb = TextBox()
+        self.tb.setWidth("100%")
+        self.tb.setText(initialText)
+        self.hp.add(self.tb)
+
+    def getText(self):
+        return self.tb.getText()
+
+    def getWidget(self):
+        return self.hp
+
+class Configure(Sink):
+    def __init__(self):
+        Sink.__init__(self)
+        self.data = SfaData()
+
+        panel = VerticalPanel()
+        panel.setWidth("100%")
+        panel.setWidth("100%")
+
+        self.userBox = LabeledTextBox("User HRN:", SfaData.user)
+        panel.add(self.userBox.getWidget())
+        self.sliceBox = LabeledTextBox("Slice HRN:", SfaData.slice)
+        panel.add(self.sliceBox.getWidget())
+
+        hp = HorizontalPanel()
+        applyButton = Button("Apply", self.apply)
+        hp.add(applyButton)
+        panel.add(hp)
+
+        self.initWidget(panel)
+
+    def apply(self, sender):
+        self.data.setUser(self.userBox.getText())
+        self.data.setSlice(self.sliceBox.getText())
+        TopPanel.panel.refresh()
+
+    def onShow(self):
+        pass
+
+def init():
+    return SinkInfo("Configure", "Configure SFA Federation GUI", Configure)
diff --git a/Identities.py b/Identities.py
new file mode 100644 (file)
index 0000000..a6a6f39
--- /dev/null
@@ -0,0 +1,17 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.HTML import HTML
+
+class Identities(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+
+        text="Not implemented yet"
+        self.initWidget(HTML(text, True))
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("Identities", "Manage SFA Identities", Identities)
diff --git a/Info.py b/Info.py
new file mode 100644 (file)
index 0000000..4fcf72a
--- /dev/null
+++ b/Info.py
@@ -0,0 +1,20 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.HTML import HTML
+
+class Info(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+
+        text="<div class='infoProse'>This is the SFA Federation GUI. "
+        text+="It allows users to manage their SFA identities and slices, "
+        text+="add resources from various testbeds to their slices, "
+        text+="and browse the SFA Registry.</p></div>"
+        self.initWidget(HTML(text, True))
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("Info", "Introduction to the SFA Federation GUI", Info)
diff --git a/OpenCirrus.py b/OpenCirrus.py
new file mode 100644 (file)
index 0000000..537f20b
--- /dev/null
@@ -0,0 +1,17 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.HTML import HTML
+
+class OpenCirrus(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+
+        text="Not implemented yet"
+        self.initWidget(HTML(text, True))
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("OpenCirrus", "Specify OpenCirrus Resources", OpenCirrus)
diff --git a/PlanetLab.py b/PlanetLab.py
new file mode 100644 (file)
index 0000000..50407c7
--- /dev/null
@@ -0,0 +1,31 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.TextArea import TextArea
+from pyjamas.ui.HTML import HTML
+from SfaData import PlanetLabData
+
+class PlanetLab(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+        self.panel = VerticalPanel()
+        self.panel.setSize("100%", "100%")
+        self.data = PlanetLabData()
+        self.rspec = self.data.getRSpec()
+
+        # Just to show that we can retrieve the RSpec
+        ta = TextArea()
+        ta.setSize("100%", "100%")
+        ta.setText(self.rspec)
+        self.panel.add(ta)
+
+        self.initWidget(self.panel)
+
+    def onShow(self):
+        # Do we want to refresh the RSpec?
+        pass
+        
+
+
+def init():
+    return SinkInfo("PlanetLab", "Specify PlanetLab Resources", PlanetLab)
diff --git a/SfaBrowser.py b/SfaBrowser.py
new file mode 100644 (file)
index 0000000..778b448
--- /dev/null
@@ -0,0 +1,17 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.HTML import HTML
+
+class SfaBrowser(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+
+        text="Not implemented yet"
+        self.initWidget(HTML(text, True))
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("Browse SFA", "SFA Hierarchy Browser", SfaBrowser)
diff --git a/SfaData.py b/SfaData.py
new file mode 100644 (file)
index 0000000..a26aaf9
--- /dev/null
@@ -0,0 +1,68 @@
+import os
+from subprocess import call
+from sfa.util.rspecHelper import RSpec
+
+class SfaData:
+    authority = "plc.princeton"
+    user = "plc.princeton.acb"
+    slice = "plc.princeton.iias"
+
+    def __init__(self):
+        self.registry = None
+        self.slicemgr = None
+
+    def getAuthority(self):
+        return SfaData.authority
+
+    def getUser(self):
+        return SfaData.user
+
+    def setUser(self, user):
+        SfaData.user = user
+
+        # Should probably get authority from user record instead...
+        a = SfaData.user.split('.')
+        SfaData.authority = '.'.join(a[:len(a)-1])
+
+    def getSlice(self):
+        return SfaData.slice
+
+    def setSlice(self, slice):
+        SfaData.slice = slice
+
+    def getRecord(self):
+        pass
+
+    def getRSpec(self):
+        slice = self.getSlice()
+        call(["sfi.py", "-u", self.getUser(), "-a", self.getAuthority(), 
+              "-r", self.registry, "-s", self.slicemgr, "resources", 
+              "-o", slice, slice])
+        filename = os.path.expanduser("~/.sfi/" + slice + ".rspec")
+        f = open(filename, "r")
+        xml = f.read()
+        f.close()
+        return xml
+
+class ViniData(SfaData):
+    def __init__(self):
+        SfaData.__init__(self)
+        self.registry = "http://www.planet-lab.org:12345"
+        self.slicemgr = "http://www.vini-veritas.net:12347"
+
+    def getRSpec(self):
+        xml = SfaData.getRSpec(self)
+        return RSpec(xml)
+
+class PlanetLabData(SfaData):
+    def __init__(self):
+        SfaData.__init__(self)
+        self.registry = "http://www.planet-lab.org:12345"
+        self.slicemgr = "http://www.planet-lab.org:12347"
+
+class OpenCirrusData(SfaData):
+    def __init__(self):
+        SfaData.__init__(self)
+        self.registry = "http://www.planet-lab.org:12345"
+        self.slicemgr = "http://www.planet-lab.org:12347"
+
diff --git a/SfaGUI.py b/SfaGUI.py
new file mode 100644 (file)
index 0000000..8cd7cc1
--- /dev/null
+++ b/SfaGUI.py
@@ -0,0 +1,111 @@
+import pyjd # this is dummy in pyjs
+
+from pyjamas.ui.Button import Button
+from pyjamas.ui.RootPanel import RootPanel
+from pyjamas.ui.HTML import HTML
+from pyjamas.ui.DockPanel import DockPanel
+from pyjamas.ui import HasAlignment
+from pyjamas.ui.Hyperlink import Hyperlink
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas import Window
+from SinkList import SinkList
+from Configure import TopPanel
+from pyjamas import History
+import Info
+import Slices
+import Identities
+import PlanetLab
+import VINI
+import OpenCirrus
+import SfaBrowser
+import Configure
+
+class SfaGUI:
+    def onHistoryChanged(self, token):
+        info = self.sink_list.find(token)
+        if info:
+            self.show(info, False)
+        else:
+            self.showInfo()
+
+    def onModuleLoad(self):
+        self.tp = TopPanel()
+        self.tp.setWidth("100%")
+
+        self.curInfo=''
+        self.curSink=None
+        self.description=HTML()
+        self.sink_list=SinkList()
+        self.panel=DockPanel()
+        self.loadSinks()
+        self.sinkContainer = DockPanel()
+        self.sinkContainer.setStyleName("ks-Sink")
+
+        vp=VerticalPanel()
+        vp.setWidth("100%")
+        vp.setHeight("100%")
+        vp.add(self.description)
+        vp.add(self.sinkContainer)
+
+        self.description.setStyleName("ks-Info")
+
+        self.panel.add(self.sink_list, DockPanel.WEST)
+        self.panel.add(vp, DockPanel.CENTER)
+
+        self.panel.setCellVerticalAlignment(self.sink_list, HasAlignment.ALIGN_TOP)
+        self.panel.setCellWidth(vp, "100%")
+        self.panel.setCellHeight(vp, "100%")
+
+        History.addHistoryListener(self)
+        RootPanel().add(self.tp)
+        RootPanel().add(self.panel)
+
+        #Show the initial screen.
+        initToken = History.getToken()
+        if len(initToken):
+            self.onHistoryChanged(initToken)
+        else:
+            self.showInfo()
+
+    def show(self, info, affectHistory):
+        if info == self.curInfo: return
+        self.curInfo = info
+
+        if self.curSink <> None:
+            self.curSink.onHide()
+            self.sinkContainer.remove(self.curSink)
+
+        self.curSink = info.getInstance()
+        self.sink_list.setSinkSelection(info.getName())
+        self.description.setHTML(info.getDescription())
+
+        if (affectHistory):
+            History.newItem(info.getName())
+
+        self.sinkContainer.add(self.curSink, DockPanel.CENTER)
+        self.sinkContainer.setCellWidth(self.curSink, "100%")
+        self.sinkContainer.setCellHeight(self.curSink, "100%")
+        self.sinkContainer.setCellVerticalAlignment(self.curSink, HasAlignment.ALIGN_TOP)
+        self.curSink.onShow()
+        
+    def loadSinks(self):
+        self.sink_list.addSink(Info.init())
+        self.sink_list.addSink(Identities.init())
+        self.sink_list.addSink(Slices.init())
+        self.sink_list.addSink(PlanetLab.init())
+        self.sink_list.addSink(VINI.init())
+        self.sink_list.addSink(OpenCirrus.init())
+        self.sink_list.addSink(SfaBrowser.init())
+        self.sink_list.addSink(Configure.init())
+
+    def showInfo(self):
+        self.show(self.sink_list.find("Info"), False)
+
+
+
+
+if __name__ == '__main__':
+    pyjd.setup("public/SfaGUI.html")
+    app = SfaGUI()
+    app.onModuleLoad()
+    pyjd.run()
diff --git a/Sink.py b/Sink.py
new file mode 100644 (file)
index 0000000..8032d90
--- /dev/null
+++ b/Sink.py
@@ -0,0 +1,36 @@
+from pyjamas.ui.Composite import Composite
+
+class Sink(Composite):
+    def __init__(self):
+        Composite.__init__(self)
+    
+    def onHide(self):
+        pass
+        
+    def onShow(self):
+        pass
+
+    def baseURL(self):
+        return ""
+
+class SinkInfo:
+    def __init__(self, name, desc, object_type):
+        self.name=name
+        self.description=desc
+        self.object_type=object_type
+        self.instance=None
+
+    def createInstance(self):
+        return self.object_type()
+
+    def getDescription(self):
+        return self.description
+
+    def getInstance(self):
+        if self.instance==None:
+            self.instance=self.createInstance()
+        return self.instance
+    
+    def getName(self):
+        return self.name
+    
diff --git a/SinkList.py b/SinkList.py
new file mode 100644 (file)
index 0000000..129a26f
--- /dev/null
@@ -0,0 +1,41 @@
+from pyjamas.ui.Composite import Composite
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.Hyperlink import Hyperlink
+
+class SinkList(Composite):
+    def __init__(self):
+        Composite.__init__(self)
+
+        self.vp_list=VerticalPanel()
+        self.sinks=[]
+        self.selectedSink=-1
+        
+        self.initWidget(self.vp_list)
+        self.setStyleName("ks-List")
+
+    def addSink(self, info):
+        name = info.getName()
+        link = Hyperlink(name, False, name)
+        link.setStyleName("ks-SinkItem")
+        self.vp_list.add(link)
+        self.sinks.append(info)
+
+    def find(self, sinkName):
+        for info in self.sinks:
+            if info.getName()==sinkName:
+                return info
+        return None
+
+    def setSinkSelection(self, name):
+        if self.selectedSink <> -1:
+            self.vp_list.getWidget(self.selectedSink).removeStyleName("ks-SinkItem-selected")
+
+        for i in range(len(self.sinks)):
+            info = self.sinks[i]
+            if (info.getName()==name):
+                self.selectedSink = i
+                widget=self.vp_list.getWidget(self.selectedSink)
+                widget.addStyleName("ks-SinkItem-selected")
+                return
+
+
diff --git a/Slices.py b/Slices.py
new file mode 100644 (file)
index 0000000..706e8b7
--- /dev/null
+++ b/Slices.py
@@ -0,0 +1,17 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.HTML import HTML
+
+class Slices(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+
+        text="Not implemented yet"
+        self.initWidget(HTML(text, True))
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("Slices", "Manage SFA Slices", Slices)
diff --git a/VINI.py b/VINI.py
new file mode 100644 (file)
index 0000000..c82c7fd
--- /dev/null
+++ b/VINI.py
@@ -0,0 +1,46 @@
+from Sink import Sink, SinkInfo
+from pyjamas.ui.horizsplitpanel import HorizontalSplitPanel
+from pyjamas.ui.CaptionPanel import CaptionPanel
+from pyjamas.ui.ListBox import ListBox
+from pyjamas.ui.HTML import HTML
+from SfaData import ViniData
+
+class VINI(Sink):
+    def __init__(self):
+
+        Sink.__init__(self)
+        self.panel = HorizontalSplitPanel()
+        self.panel.setSize("100%", "100%")
+        self.panel.setSplitPosition("50%")
+        self.data = ViniData()
+        self.rspec = self.data.getRSpec()
+
+        leftcap = CaptionPanel("Available nodes")
+        leftcap.setSize("90%", "90%")
+        leftlist = ListBox(MultipleSelect=True)
+        leftlist.setSize("100%", "100%")
+        available = self.rspec.get_node_list()
+        for i in available:
+            leftlist.addItem(i)
+        leftcap.add(leftlist)
+
+        rightcap = CaptionPanel("Selected nodes")
+        rightcap.setSize("90%", "90%")
+        rightlist = ListBox(MultipleSelect=True)
+        rightlist.setSize("100%", "100%")
+        slivers = self.rspec.get_sliver_list()
+        for i in slivers:
+            rightlist.addItem(i)
+        rightcap.add(rightlist)
+
+        self.panel.setLeftWidget(leftcap)
+        self.panel.setRightWidget(rightcap)
+
+        self.initWidget(self.panel)
+
+    def onShow(self):
+        pass
+
+
+def init():
+    return SinkInfo("VINI", "Specify VINI Resources", VINI)
diff --git a/build.sh b/build.sh
new file mode 100755 (executable)
index 0000000..b29cee9
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../bin/pyjsbuild $@ SfaGUI
diff --git a/public/SfaGUI.css b/public/SfaGUI.css
new file mode 100644 (file)
index 0000000..5c3f69c
--- /dev/null
@@ -0,0 +1,292 @@
+body {
+  background-color: white;
+  color: black;
+  font-family: Arial, sans-serif;
+  font-size: smaller;
+  margin: 20px 20px 20px 20px;
+}
+
+code {
+  font-size: small;
+}
+
+a {
+  color: darkblue;
+}
+
+a:visited {
+  color: darkblue;
+}
+
+.gwt-BorderedPanel {
+}
+
+.gwt-Button {
+}
+
+.gwt-Canvas {
+}
+
+.gwt-CheckBox {
+  font-size: smaller;
+}
+
+.gwt-DialogBox {
+  sborder: 8px solid #C3D9FF;
+  border: 2px outset;
+  background-color: white;
+}
+
+.gwt-DialogBox .Caption {
+  background-color: #C3D9FF;
+  padding: 3px;
+  margin: 2px;
+  font-weight: bold;
+  cursor: default;
+}
+
+.gwt-FileUpload {
+}
+
+.gwt-Frame {
+}
+
+.gwt-HorizontalSplitter .Bar {
+  width: 8px;
+  background-color: #C3D9FF;
+}
+
+.gwt-VerticalSplitter .Bar {
+  height: 8px;
+  background-color: #C3D9FF;
+}
+
+.gwt-HTML {
+  font-size: smaller;
+}
+
+.gwt-Hyperlink {
+}
+
+.gwt-Image {
+}
+
+.gwt-Label {
+  font-size: smaller;
+}
+
+.gwt-ListBox {
+}
+
+.gwt-MenuBar {
+  background-color: #C3D9FF;
+  border: 1px solid #87B3FF;
+  cursor: default;
+}
+
+.gwt-MenuBar .gwt-MenuItem {
+  padding: 1px 4px 1px 4px;
+  font-size: smaller;
+  cursor: default;
+}
+
+.gwt-MenuBar .gwt-MenuItem-selected {
+  background-color: #E8EEF7;
+}
+
+.gwt-PasswordTextBox {
+}
+
+.gwt-RadioButton {
+  font-size: smaller;
+}
+
+.gwt-TabPanel {
+}
+
+.gwt-TabPanelBottom {
+  border-left: 1px solid #87B3FF;
+}
+
+.gwt-TabBar {
+  background-color: #C3D9FF;
+  font-size: smaller;
+}
+
+.gwt-TabBar .gwt-TabBarFirst {
+  height: 100%;
+  border-bottom: 1px solid #87B3FF;
+  padding-left: 3px;
+}
+
+.gwt-TabBar .gwt-TabBarRest {
+  border-bottom: 1px solid #87B3FF;
+  padding-right: 3px;
+}
+
+.gwt-TabBar .gwt-TabBarItem {
+  border-top: 1px solid #C3D9FF;
+  border-bottom: 1px solid #87B3FF;
+  padding: 2px;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.gwt-TabBar .gwt-TabBarItem-selected {
+  font-weight: bold;
+  background-color: #E8EEF7;
+  border-top: 1px solid #87B3FF;
+  border-left: 1px solid #87B3FF;
+  border-right: 1px solid #87B3FF;
+  border-bottom: 1px solid #E8EEF7;
+  padding: 2px;
+  cursor: default;
+}
+
+.gwt-TextArea {
+}
+
+.gwt-TextBox {
+}
+
+.gwt-Tree {
+}
+
+.gwt-Tree .gwt-TreeItem {
+  font-size: smaller;
+}
+
+.gwt-Tree .gwt-TreeItem-selected {
+  background-color: #C3D9FF;
+}
+
+.gwt-StackPanel {
+}
+
+.gwt-StackPanel .gwt-StackPanelItem {
+  background-color: #C3D9FF;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.gwt-StackPanel .gwt-StackPanelItem-selected {
+}
+
+/* -------------------------------------------------------------------------- */
+.ks-Sink {
+  border: 8px solid #C3D9FF;
+  background-color: #E8EEF7;
+  width: 100%;
+  height: 24em;
+}
+
+.ks-Info {
+  background-color: #C3D9FF;
+  padding: 10px 10px 2px 10px;
+  font-size: smaller;
+}
+
+.ks-List {
+  margin-top: 8px;
+  margin-bottom: 8px;
+  font-size: smaller;
+}
+
+.ks-List .ks-SinkItem {
+  width: 100%;
+  padding: 0.3em;
+  padding-right: 16px;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.ks-List .ks-SinkItem-selected {
+  background-color: #C3D9FF;
+}
+
+.ks-images-Image {
+  margin: 8px;
+}
+
+.ks-images-Button {
+  margin: 8px;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.ks-layouts {
+  margin: 8px;
+}
+
+.ks-layouts-Label {
+  background-color: #C3D9FF;
+  font-weight: bold;
+  margin-top: 1em;
+  padding: 2px 0px 2px 0px;
+  width: 100%;
+}
+
+.ks-layouts-Scroller {
+  height: 128px;
+  border: 2px solid #C3D9FF;
+  padding: 8px;
+  margin: 8px;
+}
+
+.ks-popups-Popup {
+  background-color: white;
+  border: 1px solid #87B3FF;
+  padding: 4px;
+}
+
+.infoProse {
+  margin: 8px;
+}
+
+/******************************************************
+*                                              DisclosurePanel         
+******************************************************/
+.gwt-DisclosurePanel
+{
+       background-color                        :       #ddf;
+       border                                          :       1px solid #009;
+}
+.gwt-DisclosurePanel .header
+{
+       font-size                                       :       70%;
+       cursor                                          :       pointer;
+       cursor                                          :       hand;
+}
+.gwt-DisclosurePanel-closed
+{
+}
+.gwt-DisclosurePanel-closed .header
+{
+}
+.gwt-DisclosurePanel-open
+{
+}
+.gwt-DisclosurePanel-open .header
+{
+}
+.gwt-DisclosurePanel-open .content
+{
+}
+
+.gwt-HorizontalSplitPanel {
+}
+
+.gwt-HorizontalSplitPanel .hsplitter {
+    cursor: move;
+    border: 0px; 
+    background: #91c0ef url(images/vborder.png) repeat-x;
+}
+
+.gwt-VerticalSplitPanel {
+}
+
+.gwt-VerticalSplitPanel .vsplitter {
+    cursor: move;
+    border: 0px; 
+    background: #91c0ef url(images/hborder.png) repeat-x;
+}
diff --git a/public/SfaGUI.html b/public/SfaGUI.html
new file mode 100644 (file)
index 0000000..d50c334
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+    <head>
+        <meta name="pygwt:module" content="SfaGUI">
+        <link rel='stylesheet' href='SfaGUI.css'>
+        <title>SFA Federation GUI</title>
+    </head>
+    <body bgcolor="white">
+        <script language="javascript" src="bootstrap.js"></script>
+
+       <iframe id='__pygwt_historyFrame' style='width:0;height:0;border:0'></iframe>
+    </body>
+</html>
+
diff --git a/public/SplitPanel.css b/public/SplitPanel.css
new file mode 100644 (file)
index 0000000..4706eb7
--- /dev/null
@@ -0,0 +1,16 @@
+.gwt-HorizontalSplitPanel {
+}
+
+.gwt-HorizontalSplitPanel .hsplitter {
+    cursor: move;
+    border: 0px; 
+    background: #91c0ef url(images/vborder.png) repeat-x;
+}
+.gwt-VerticalSplitPanel {
+}
+
+.gwt-VerticalSplitPanel .vsplitter {
+    cursor: move;
+    border: 0px; 
+    background: #91c0ef url(images/hborder.png) repeat-x;
+}
diff --git a/public/images/hborder.png b/public/images/hborder.png
new file mode 100644 (file)
index 0000000..509eb1b
Binary files /dev/null and b/public/images/hborder.png differ
diff --git a/public/images/vborder.png b/public/images/vborder.png
new file mode 100644 (file)
index 0000000..435b816
Binary files /dev/null and b/public/images/vborder.png differ
diff --git a/public/splitPanelThumb.png b/public/splitPanelThumb.png
new file mode 100644 (file)
index 0000000..d2ef025
Binary files /dev/null and b/public/splitPanelThumb.png differ