@@ -0,0 +1,32 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
public class BooleanVariable extends Variable { | |||
private boolean value = true; | |||
public BooleanVariable(Component owner, String name, String id) { | |||
super(owner, name, id); | |||
} | |||
void update() { | |||
owner.getClient().updateVariable(this); | |||
if(immediate) | |||
owner.getClient().flushVariables(); | |||
} | |||
public boolean getValue() { | |||
return value; | |||
} | |||
public void setValue(boolean value) { | |||
this.value = value; | |||
} | |||
public String getEncodedValue() { | |||
return ( value ? "true" : "false" ); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.Node; | |||
public abstract class Component { | |||
private ContainerComponent parent; | |||
protected GwtClient client; | |||
private final int id; | |||
public Component(int id, GwtClient c) { | |||
client = c; | |||
this.id = id; | |||
} | |||
public abstract void updateFromUidl(Node n); | |||
public abstract Widget getWidget(); | |||
public static boolean isComponent(String nodeName) { | |||
if( | |||
nodeName.equals("label") || | |||
nodeName.equals("button") || | |||
nodeName.equals("textfield") || | |||
nodeName.equals("select") || | |||
nodeName.equals("orderedlayout") | |||
) return true; | |||
return false; | |||
} | |||
public static Component createComponent(Node uidl, GwtClient cli) { | |||
Component c = null; | |||
String nodeName = uidl.getNodeName(); | |||
if(nodeName.equals("label")) { | |||
c = new TkLabel(uidl, cli); | |||
} else if(nodeName.equals("orderedlayout")) { | |||
c = new TkOrderedLayout(uidl, cli); | |||
} else if(nodeName.equals("button")) { | |||
c = new TkButton(uidl, cli); | |||
} else if(nodeName.equals("textfield")) { | |||
c = new TkTextField(uidl, cli); | |||
} else if(nodeName.equals("select")) { | |||
c = new TkLegacyComponent(uidl, cli); | |||
} else { | |||
c = new TkUnknown(uidl, cli); | |||
} | |||
return c; | |||
} | |||
public void appendTo(ContainerComponent cont) { | |||
this.parent = cont; | |||
getClient().registerComponent(this); | |||
cont.appendChild(this); | |||
} | |||
public ContainerComponent getParent() { | |||
return parent; | |||
} | |||
public GwtClient getClient() { | |||
if(client == null) | |||
client = parent.getClient(); | |||
return client; | |||
} | |||
public static int getIdFromUidl(Node uidl) { | |||
Node pid = uidl.getAttributes().getNamedItem("id"); | |||
return Integer.parseInt(pid.getNodeValue().substring(3)); | |||
} | |||
public int getId() { | |||
return id; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
public final class Console { | |||
private RootPanel rp; | |||
public Console(RootPanel rp) { | |||
this.rp = rp; | |||
} | |||
public void log(String msg) { | |||
rp.add(new Label(msg)); | |||
} | |||
public void error(String msg) { | |||
rp.add((new Label(msg))); | |||
} | |||
public void printObject(Object msg) { | |||
rp.add((new Label(msg.toString()))); | |||
} | |||
// public native void log(String msg) | |||
///*-{ | |||
// console.log(msg); | |||
//}-*/; | |||
// | |||
// public native void warn(String msg) | |||
// /*-{ | |||
// console.warn(msg); | |||
// }-*/; | |||
// | |||
// public native void error(String msg) | |||
// /*-{ | |||
// console.error(msg); | |||
// }-*/; | |||
// | |||
// public native void printObject(Object msg) | |||
// /*-{ | |||
// console.dir(msg); | |||
// }-*/; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
abstract class ContainerComponent extends Component { | |||
public ContainerComponent(int id, GwtClient c) { | |||
super(id, c); | |||
} | |||
abstract void appendChild(Component c); | |||
public void renderChildNodes(Node n, GwtClient cli) { | |||
NodeList children = n.getChildNodes(); | |||
for(int i = 0; i < children.getLength(); i++) { | |||
Node child = children.item(i); | |||
if(Component.isComponent(child.getNodeName())) { | |||
Component c = Component.createComponent(child, cli); | |||
c.appendTo(this); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,177 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import java.util.HashMap; | |||
import java.util.Vector; | |||
import com.google.gwt.core.client.EntryPoint; | |||
import com.google.gwt.http.client.Request; | |||
import com.google.gwt.http.client.RequestBuilder; | |||
import com.google.gwt.http.client.RequestCallback; | |||
import com.google.gwt.http.client.RequestException; | |||
import com.google.gwt.http.client.Response; | |||
import com.google.gwt.http.client.URL; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.xml.client.Document; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
import com.google.gwt.xml.client.XMLParser; | |||
/** | |||
* Entry point classes define <code>onModuleLoad()</code>. | |||
*/ | |||
public class GwtClient implements EntryPoint { | |||
private String appUri = "http://localhost:8080/tk/HelloWorld"; | |||
// TODO remove repaintAll things start to pile up | |||
private RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, appUri + "/UIDL/?repaintAll=1&"); | |||
private Console console; | |||
private RootWindow rw; | |||
private Vector pendingVariables = new Vector(); | |||
private HashMap components = new HashMap(); | |||
private int requestCount = 0; | |||
private LegacyClientWrapper lClient; | |||
/** | |||
* This is the entry point method. | |||
*/ | |||
public void onModuleLoad() { | |||
console = new Console(RootPanel.get("itmtk-loki")); | |||
console.log("muutos"); | |||
console.log("Starting app"); | |||
console.log("Makin fake UIDL Request to fool servlet of an app init"); | |||
RequestBuilder rb2 = new RequestBuilder(RequestBuilder.GET, appUri); | |||
try { | |||
rb2.sendRequest("", new RequestCallback() { | |||
public void onResponseReceived(Request request, Response response) { | |||
console.log("Got fake response... sending initial UIDL request"); | |||
makeUidlRequest("repaintAll=1"); | |||
} | |||
public void onError(Request request, Throwable exception) { | |||
// TODO Auto-generated method stub | |||
} | |||
}); | |||
} catch (RequestException e1) { | |||
// TODO Auto-generated catch block | |||
e1.printStackTrace(); | |||
} | |||
} | |||
private void makeUidlRequest(String requestData) { | |||
console.log("Making UIDL Request"); | |||
rb = new RequestBuilder(RequestBuilder.GET, appUri + "/UIDL/?requestId=" + (++requestCount) + "&" + requestData); | |||
try { | |||
rb.sendRequest(requestData, new RequestCallback() { | |||
public void onError(Request request, Throwable exception) { | |||
console.error("Got error"); | |||
} | |||
public void onResponseReceived(Request request, Response response) { | |||
console.log("Got response:"); | |||
Document doc = XMLParser.parse(response.getText()); | |||
console.log(doc.toString()); | |||
handleUIDL(doc); | |||
} | |||
}); | |||
console.log("Request sent"); | |||
} catch (RequestException e) { | |||
console.error(e.getMessage()); | |||
} | |||
} | |||
private void handleUIDL(Document doc) { | |||
NodeList changes = doc.getElementsByTagName("change"); | |||
for(int i = 0; i < changes.getLength(); i++) { | |||
applyChange(changes.item(i).getFirstChild()); | |||
} | |||
} | |||
private void applyChange(Node n) { | |||
if(n.getNodeName().equals("window")) { | |||
console.log("Rendering main window"); | |||
rw = new RootWindow(n, this); | |||
rw.setClient(this); | |||
} else { | |||
int pid = Component.getIdFromUidl(n); | |||
console.log("Updating node: " + n.getNodeName() + ", PID:"+pid); | |||
Component c = getPaintable(pid); | |||
c.updateFromUidl(n); | |||
} | |||
} | |||
/** | |||
* Queues a changed variable to be sent to server | |||
* | |||
* @param variable | |||
*/ | |||
public void updateVariable(Variable variable) { | |||
// remove variable first so we will maintain the correct order (in case of "double change") | |||
pendingVariables.remove(variable); | |||
pendingVariables.add(variable); | |||
} | |||
/** | |||
* Sends queued variables to server | |||
* | |||
*/ | |||
public void flushVariables() { | |||
StringBuffer sb = new StringBuffer(); | |||
int i = 0; | |||
while (!pendingVariables.isEmpty()) { | |||
Variable v = (Variable) pendingVariables.lastElement(); | |||
pendingVariables.removeElement(v); | |||
if (i > 0) { | |||
sb.append("&"); | |||
} | |||
// encode the characters in the name | |||
String encodedName = URL.encodeComponent(v.getId()); | |||
sb.append(encodedName); | |||
sb.append("="); | |||
// encode the characters in the value | |||
String encodedValue = URL.encodeComponent(v.getEncodedValue()); | |||
sb.append(encodedValue); | |||
} | |||
String buf = sb.toString(); | |||
console.log("Making following request to server:"); | |||
console.log(buf); | |||
makeUidlRequest(buf); | |||
} | |||
public void registerComponent(Component component) { | |||
components.put(""+component.getId(), component ); | |||
} | |||
public Component getPaintable(int pid) { | |||
return (Component) components.get(""+pid); | |||
} | |||
public LegacyClientWrapper getLegacyClient() { | |||
if(lClient == null) | |||
lClient = new LegacyClientWrapper(); | |||
return lClient; | |||
} | |||
} | |||
@@ -0,0 +1,39 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.core.client.JavaScriptObject; | |||
import com.google.gwt.user.client.Element; | |||
import com.google.gwt.xml.client.Node; | |||
public class LegacyClientWrapper { | |||
JavaScriptObject lClient; | |||
LegacyClientWrapper() { | |||
instantiateLegacyClient(); | |||
} | |||
private native void instantiateLegacyClient()/*-{ | |||
var client = new $wnd.itmill.Client(); | |||
client.start(); | |||
this.@com.itmill.gwtclient.client.LegacyClientWrapper::lClient = client; | |||
debugger; | |||
}-*/; | |||
public native void renderUidl(Element e, Node n)/*-{ | |||
// var uidlNode = n.hE; //sneeked obf. reference to DOM-node, changes on almost every change | |||
// should fork GWT and make method for getting jsObject | |||
// var uidlNode = cQ.gE; | |||
eval('var uidlNode = cQ.gE;'); | |||
//ok so in eval compiler don't look | |||
var client = this.@com.itmill.gwtclient.client.LegacyClientWrapper::lClient; | |||
debugger; | |||
client.renderUIDL(uidlNode,e); | |||
}-*/; | |||
} |
@@ -0,0 +1,43 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.Node; | |||
public class RootWindow extends ContainerComponent { | |||
private RootPanel rp; | |||
private GwtClient client; | |||
public RootWindow(Node uidl, GwtClient c) { | |||
super(0,c); | |||
// root panel must be attached to client before childs can be rendered | |||
setClient(c); | |||
rp = RootPanel.get("itmtk-ajax-window"); | |||
rp.clear(); | |||
renderChildNodes(uidl, client); | |||
} | |||
void appendChild(Component c) { | |||
rp.add(c.getWidget()); | |||
} | |||
public void updateFromUidl(Node n) { | |||
// TODO Auto-generated method stub | |||
} | |||
public Widget getWidget() { | |||
return rp; | |||
} | |||
public void setClient(GwtClient client) { | |||
this.client = client; | |||
} | |||
public GwtClient getClient() { | |||
return this.client; | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.Button; | |||
import com.google.gwt.user.client.ui.ClickListener; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.NamedNodeMap; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
public class TkButton extends Component { | |||
private Button b; | |||
private BooleanVariable state; | |||
public TkButton(Node uidl, GwtClient c) { | |||
super(getIdFromUidl(uidl), c); | |||
b = new Button(); | |||
updateFromUidl(uidl); | |||
b.addClickListener(new ButtonClickListener()); | |||
} | |||
public void updateFromUidl(Node n) { | |||
String text = ""; | |||
String description = null; | |||
NamedNodeMap attributes = n.getAttributes(); | |||
Node caption = attributes.getNamedItem("caption"); | |||
if(caption != null) | |||
text = caption.getNodeValue(); | |||
NodeList children = n.getChildNodes(); | |||
for (int i = 0; i < children.getLength(); i++) { | |||
Node child = children.item(i); | |||
String nName = child.getNodeName(); | |||
if(nName.equals("description")) | |||
description = child.getFirstChild().toString(); | |||
if(nName.equals("boolean")) { | |||
state = (BooleanVariable) VariableFactory.getVariable(child,this); | |||
state.setImmediate(true); // button always immediate | |||
} | |||
} | |||
b.setText(text); | |||
if(description != null) | |||
b.setTitle(description); | |||
} | |||
public Widget getWidget() { | |||
return b; | |||
} | |||
public class ButtonClickListener implements ClickListener { | |||
public void onClick(Widget sender) { | |||
TkButton.this.state.setValue(true); | |||
TkButton.this.state.update(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.NamedNodeMap; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
public class TkLabel extends Component { | |||
private Label l; | |||
public TkLabel(Node uidl, GwtClient cli) { | |||
super(getIdFromUidl(uidl), cli); | |||
l = new Label(); | |||
updateFromUidl(uidl); | |||
} | |||
public void updateFromUidl(Node n) { | |||
NodeList children = n.getChildNodes(); | |||
String text = ""; | |||
String description = null; | |||
for (int i = 0; i < children.getLength(); i++) { | |||
Node child = children.item(i); | |||
if(child.getNodeName().equals("description")) | |||
description = child.getNodeValue(); | |||
else if(child.getNodeType() == Node.TEXT_NODE) | |||
text = child.toString(); | |||
} | |||
NamedNodeMap attributes = n.getAttributes(); | |||
Node caption = attributes.getNamedItem("caption"); | |||
if(caption != null) | |||
text = caption.getNodeValue(); | |||
l.setText(text); | |||
if(description != null) | |||
l.setTitle(description); | |||
} | |||
public Widget getWidget() { | |||
return l; | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.Element; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.Panel; | |||
import com.google.gwt.user.client.ui.VerticalPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.Node; | |||
public class TkLegacyComponent extends Component { | |||
private Label l; | |||
public TkLegacyComponent(Node uidl, GwtClient cli) { | |||
super(getIdFromUidl(uidl), cli); | |||
// TODO Check if client has legacy client instantiated | |||
l = new Label(); | |||
// updateFromUidl(uidl); | |||
} | |||
public void updateFromUidl(Node n) { | |||
LegacyClientWrapper lc = client.getLegacyClient(); | |||
Element e = l.getElement(); | |||
lc.renderUidl(e,n); | |||
} | |||
public Widget getWidget() { | |||
return l; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.FlowPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.Node; | |||
public class TkOrderedLayout extends ContainerComponent { | |||
private FlowPanel p; | |||
public TkOrderedLayout(Node uidl, GwtClient cli) { | |||
super(getIdFromUidl(uidl), cli); | |||
p = new FlowPanel(); | |||
updateFromUidl(uidl); | |||
} | |||
void appendChild(Component c) { | |||
p.add(c.getWidget()); | |||
} | |||
public Widget getWidget() { | |||
return p; | |||
} | |||
public void updateFromUidl(Node n) { | |||
p.clear(); | |||
renderChildNodes(n, getClient()); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.TextBox; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.NamedNodeMap; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
public class TkTextField extends Component { | |||
private TextBox tb; | |||
public TkTextField(Node uidl, GwtClient cli) { | |||
super(getIdFromUidl(uidl),cli); | |||
tb = new TextBox(); | |||
updateFromUidl(uidl); | |||
} | |||
public void updateFromUidl(Node n) { | |||
NodeList children = n.getChildNodes(); | |||
String text = ""; | |||
String description = null; | |||
for (int i = 0; i < children.getLength(); i++) { | |||
Node child = children.item(i); | |||
if(child.getNodeName().equals("description")) | |||
description = child.getNodeValue(); | |||
else if(child.getNodeType() == Node.TEXT_NODE) | |||
text = child.toString(); | |||
} | |||
NamedNodeMap attributes = n.getAttributes(); | |||
Node caption = attributes.getNamedItem("caption"); | |||
if(caption != null) | |||
text = caption.getNodeValue(); | |||
tb.setText(text); | |||
if(description != null) | |||
tb.setTitle(description); | |||
} | |||
public Widget getWidget() { | |||
return tb; | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.gwt.xml.client.Node; | |||
public class TkUnknown extends Component { | |||
private Label l; | |||
public TkUnknown(Node uidl, GwtClient cli) { | |||
super(getIdFromUidl(uidl),cli); | |||
l = new Label("No client side component found for " + uidl.getNodeName()); | |||
} | |||
public void updateFromUidl(Node n) { | |||
} | |||
public Widget getWidget() { | |||
return l; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
public abstract class Variable { | |||
protected Component owner; | |||
protected boolean immediate = false; | |||
protected String name; | |||
protected String id; | |||
public Variable(Component owner, String name, String id) { | |||
this.owner = owner; | |||
this.name = name; | |||
this.id = id; | |||
} | |||
abstract void update(); | |||
public boolean isImmediate() { | |||
return immediate; | |||
} | |||
public void setImmediate(boolean immediate) { | |||
this.immediate = immediate; | |||
} | |||
public String getId() { | |||
return id; | |||
} | |||
public void setId(String id) { | |||
this.id = id; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public abstract String getEncodedValue(); | |||
} |
@@ -0,0 +1,37 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import java.util.HashMap; | |||
import com.google.gwt.xml.client.NamedNodeMap; | |||
import com.google.gwt.xml.client.Node; | |||
import com.google.gwt.xml.client.NodeList; | |||
public class VariableFactory { | |||
public static Variable getVariable(Node n, Component owner) { | |||
String nName = n.getNodeName(); | |||
NamedNodeMap attr = n.getAttributes(); | |||
if(nName.equals("boolean")) { | |||
String name = attr.getNamedItem("name").getNodeValue(); | |||
String id = attr.getNamedItem("id").getNodeValue(); | |||
boolean b = attr.getNamedItem("value").getNodeValue().equals("true"); | |||
BooleanVariable v = new BooleanVariable(owner,name,id); | |||
v.setValue(b); | |||
return v; | |||
} else { | |||
return null; | |||
} | |||
} | |||
public static HashMap getAllVariables(Node n, Component owner) { | |||
HashMap v = new HashMap(); | |||
NodeList children = n.getChildNodes(); | |||
for (int i = 0; i < children.getLength(); i++) { | |||
Variable var = getVariable(children.item(i), owner); | |||
if(var != null) | |||
v.put(var.getName(), var); | |||
} | |||
return v; | |||
} | |||
} |