|
From: <ian...@us...> - 2007-08-19 20:41:06
|
Revision: 245
http://ogoglio.svn.sourceforge.net/ogoglio/?rev=245&view=rev
Author: iansmith
Date: 2007-08-19 13:01:35 -0700 (Sun, 19 Aug 2007)
Log Message:
-----------
Basic support for context menus has been added. Summary of how to
create and use context menus can be seen in TestCube.js.
No support yet for nested menus or different types of menu items.
Minor hack: return value from the handler for completing a context click is checked to see if it is a URL. If it is, that URL is sent to the client. This may be a bad idea.
Modified Paths:
--------------
spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java
spaces/trunk/src/com/ogoglio/client/ClientTests.java
spaces/trunk/src/com/ogoglio/client/MultiuserTests.java
spaces/trunk/src/com/ogoglio/client/SpaceClient.java
spaces/trunk/src/com/ogoglio/client/UserInputListener.java
spaces/trunk/src/com/ogoglio/persist/resources/TestCube.js
spaces/trunk/src/com/ogoglio/sim/SpaceSimulator.java
spaces/trunk/src/com/ogoglio/sim/script/SpaceScriptEngine.java
spaces/trunk/src/com/ogoglio/viewer/applet/AppletTestWindow.java
spaces/trunk/src/com/ogoglio/viewer/applet/MotionInputHandler.java
spaces/trunk/src/com/ogoglio/viewer/applet/ViewerApplet.java
spaces/trunk/src/com/ogoglio/xml/SpaceEvent.java
Added Paths:
-----------
spaces/trunk/src/com/ogoglio/sim/script/ScriptContextMenuInfo.java
spaces/trunk/src/com/ogoglio/util/ContextMenuInfo.java
Modified: spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java
===================================================================
--- spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -36,4 +36,6 @@
suite.addTest(TemplateSyncTestSuite.suite());
return suite;
}
+
+
}
Modified: spaces/trunk/src/com/ogoglio/client/ClientTests.java
===================================================================
--- spaces/trunk/src/com/ogoglio/client/ClientTests.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/client/ClientTests.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -705,6 +705,15 @@
public void receivedBrowserMessage(long sourceThingID, String message) {
}
+ public void receivedContextMenuRequest(Thing thing,String shapeName, int x, int y, long nonce) {
+ }
+
+ public void receivedContextMenuData(long nonce, String errorIfAny, Vector contextMenu) {
+ }
+
+ public void contextItemChosen(Thing thing, long nonce, String id) {
+ }
+
}
private class TestListener implements Space.Listener {
Modified: spaces/trunk/src/com/ogoglio/client/MultiuserTests.java
===================================================================
--- spaces/trunk/src/com/ogoglio/client/MultiuserTests.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/client/MultiuserTests.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -9,6 +9,7 @@
import javax.vecmath.Vector3d;
import com.ogoglio.client.model.SplinePath;
+import com.ogoglio.client.model.Thing;
import com.ogoglio.client.model.User;
import com.ogoglio.viewer.applet.MotionInputHandler;
import com.ogoglio.viewer.j3d.J3DRenderer;
@@ -103,6 +104,15 @@
public void receivedBrowserMessage(long sourceThingID, String message) {
}
+ public void receivedContextMenuRequest(Thing thing,String shapeName, int x, int y,long nonce) {
+ }
+
+ public void receivedContextMenuData(long nonce, String errorIfAny, Vector contextMenu) {
+ }
+
+ public void contextItemChosen(Thing thing, long nonce, String id) {
+ }
+
}
private class WanderThread extends Thread {
Modified: spaces/trunk/src/com/ogoglio/client/SpaceClient.java
===================================================================
--- spaces/trunk/src/com/ogoglio/client/SpaceClient.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/client/SpaceClient.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -188,12 +188,11 @@
}
public void mouseClickedThing(Thing thing, String shapeName, Point3d intersection) {
- SpaceEvent event = new SpaceEvent(SpaceEvent.THING_CLICKED_EVENT);
- event.setProperty(SpaceEvent.USERNAME, accountDoc.getUsername());
- event.setProperty(SpaceEvent.THING_ID, new Long(thing.getThingID()));
- if (shapeName != null) {
- event.setProperty(SpaceEvent.SHAPE_NAME, shapeName);
- }
+ SpaceEvent event = createSpaceEventForThing(thing, shapeName,SpaceEvent.THING_CLICKED_EVENT);
+ attemptToSendSpaceEventToServer(event);
+ }
+
+ private void attemptToSendSpaceEventToServer(SpaceEvent event) {
try {
Message message = new Message(messageChannel.getLocalLocator(), messageChannel.getRemoteLocator(), space.getSpaceID(), new PayloadFactory.SpaceEventPayload(event));
messageChannel.sendMessage(message);
@@ -202,6 +201,35 @@
}
}
+ private SpaceEvent createSpaceEventForThing(Thing thing, String shapeName, String /*yuck*/eventType) {
+ SpaceEvent event = new SpaceEvent(eventType);
+ event.setProperty(SpaceEvent.USERNAME, accountDoc.getUsername());
+ event.setProperty(SpaceEvent.THING_ID, new Long(thing.getThingID()));
+ if (shapeName != null) {
+ event.setProperty(SpaceEvent.SHAPE_NAME, shapeName);
+ }
+ return event;
+ }
+
+ public void mouseContextClickedThing(Thing thing, String shapeName, int x, int y) {
+ // we should be asking the thing for the info about it's menu
+ long now=System.currentTimeMillis();
+ listener.receivedContextMenuRequest(thing,shapeName,x,y,now);
+ SpaceEvent event = createSpaceEventForThing(thing, shapeName,SpaceEvent.THING_CONTEXT_CLICKED_EVENT);
+ event.setProperty(SpaceEvent.NONCE,new Long(now));
+ attemptToSendSpaceEventToServer(event);
+ }
+
+ public void mouseContextItemChosen(Thing thing, long nonce, String id) {
+ listener.contextItemChosen(thing,nonce,id);
+ SpaceEvent event = createSpaceEventForThing(thing, null, SpaceEvent.THING_CONTEXT_SELECTION_MADE_EVENT);
+ event.setProperty(SpaceEvent.NONCE,new Long(nonce));
+ event.setProperty(SpaceEvent.CONTEXT_MENU_DATA_ITEM_ID, id);
+ attemptToSendSpaceEventToServer(event);
+ }
+
+
+
public void mouseClickedPage(Page page, Point3d intersection) {
System.out.println("User clicked the page. Ignoring");
}
@@ -262,7 +290,6 @@
if (SpaceEvent.ADD_USER_EVENT.equals(event.getName())) {
User user = new User(space, event.getStringProperty(SpaceEvent.USERNAME), event.getTransform(), event.getLongProperty(SpaceEvent.BODY_ID).longValue());
space.addUser(user);
-
} else if (SpaceEvent.REMOVE_USER_EVENT.equals(event.getName())) {
User user = space.getUser(event.getStringProperty(SpaceEvent.USERNAME));
if (user == null) {
@@ -513,7 +540,10 @@
}
thing.stopMotion(position);
thing.setName(displayName);
-
+ } else if (SpaceEvent.CONTEXT_MENU_DATA_EVENT.equals(event.getName())) {
+ listener.receivedContextMenuData(event.getLongProperty(SpaceEvent.NONCE).longValue(),
+ event.getStringProperty(SpaceEvent.CONTEXT_MENU_DATA_GENERATION_ERROR),
+ event.getContextMenu());
} else if (SpaceEvent.MESSAGE_BROWSER_EVENT.equals(event.getName())) {
long thingID = event.getLongProperty(SpaceEvent.THING_ID).longValue();
@@ -620,6 +650,12 @@
public interface Listener {
public void receivedChatMessage(String username, String message);
+ public void contextItemChosen(Thing thing, long nonce, String id);
+
+ public void receivedContextMenuData(long nonce, String errorIfAny, Vector contextMenu);
+
+ public void receivedContextMenuRequest(Thing thing, String shapeName, int x, int y,long nonce);
+
public void receivedLink(String displayName, String link);
public void receivedBrowserMessage(long sourceThingID, String message);
Modified: spaces/trunk/src/com/ogoglio/client/UserInputListener.java
===================================================================
--- spaces/trunk/src/com/ogoglio/client/UserInputListener.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/client/UserInputListener.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -23,4 +23,6 @@
public void mouseClickedPage(Page page, Point3d intersection);
public void focusCommandField();
+
+ public void mouseContextClickedThing(Thing thing, String name, int x, int y);
}
Modified: spaces/trunk/src/com/ogoglio/persist/resources/TestCube.js
===================================================================
--- spaces/trunk/src/com/ogoglio/persist/resources/TestCube.js 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/persist/resources/TestCube.js 2007-08-19 20:01:35 UTC (rev 245)
@@ -16,3 +16,27 @@
space.startThingMotion(thingID, path);
}
+
+function onContextClick(person, shapeName){
+ space.log(person + " context clicked " + thingID + " on its " + shapeName);
+
+ i1 = new ContextMenuInfo("Google",true,"google");
+ i2 = new ContextMenuInfo("Yahoo",true,"yahoo");
+ i3 = new ContextMenuInfo("Altavista",false,"NOTUSED");
+ i4 = new ContextMenuInfo("Transmutable",true,"transmutable");
+
+ return new Array(i1,i2,i3,i4);
+}
+
+function onContextMenuItemChosen(username,id)
+{
+ var key = "favoriteSite";
+ var preferred = space.getSetting(key);
+
+ space.putSetting(key,id);
+
+ //causes browser to jump to that page!
+ return "http://www."+id+".com/";
+}
+
+
Modified: spaces/trunk/src/com/ogoglio/sim/SpaceSimulator.java
===================================================================
--- spaces/trunk/src/com/ogoglio/sim/SpaceSimulator.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/sim/SpaceSimulator.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -392,7 +392,10 @@
listener.generatedSpaceEvent(markedUpEvent, SpaceSimulator.this);
- } else if (SpaceEvent.THING_CLICKED_EVENT.equals(event.getName())) {
+ } else if (((SpaceEvent.THING_CLICKED_EVENT.equals(event.getName()))) ||
+ ((SpaceEvent.THING_CONTEXT_CLICKED_EVENT.equals(event.getName()))) ||
+ ((SpaceEvent.THING_CONTEXT_SELECTION_MADE_EVENT.equals(event.getName())))
+ ){
String username = event.getStringProperty(SpaceEvent.USERNAME);
User user = space.getUser(username);
if (user == null) {
@@ -400,7 +403,6 @@
continue;
}
scriptEngine.handleSpaceEvent(event);
-
} else if (SpaceEvent.UPDATE_THING_EVENT.equals(event.getName())) {
listener.generatedSpaceEvent(event, SpaceSimulator.this);
scriptEngine.handleSpaceEvent(event);
@@ -410,7 +412,6 @@
} else if (SpaceEvent.MESSAGE_BROWSER_EVENT.equals(event.getName())) {
listener.generatedSpaceEvent(event, SpaceSimulator.this);
-
} else {
System.err.println("Received a space event " + event.getName() + ", and dropping it on the floor.");
}
@@ -1042,6 +1043,9 @@
public void focusCommandField() {
}
+
+ public void mouseContextClickedThing(Thing thing, String name, int x, int y) {
+ }
}
}
Added: spaces/trunk/src/com/ogoglio/sim/script/ScriptContextMenuInfo.java
===================================================================
--- spaces/trunk/src/com/ogoglio/sim/script/ScriptContextMenuInfo.java (rev 0)
+++ spaces/trunk/src/com/ogoglio/sim/script/ScriptContextMenuInfo.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -0,0 +1,41 @@
+package com.ogoglio.sim.script;
+
+import org.mozilla.javascript.ScriptableObject;
+
+import com.ogoglio.util.ContextMenuInfo;
+
+public class ScriptContextMenuInfo extends ScriptableObject {
+
+ public static final String JS_CLASS_NAME="ContextMenuInfo";
+
+ //required by superclass
+ public String getClassName() {
+ return JS_CLASS_NAME;
+ }
+
+ //this object has to be here (aggregation) b/c it is used on the client side of the wire and we don't
+ //want the client linked against JS machinery
+ private ContextMenuInfo info;
+
+
+ public void jsConstructor(String textToShow, boolean notGrayedOut, String forCallback) {
+
+ info=new ContextMenuInfo();
+ info.setValues(textToShow, notGrayedOut, forCallback);
+ }
+
+
+ public String getUserVisibleString() {
+ return info.getUserVisibleString();
+ }
+
+
+ public boolean getEnabled() {
+ return info.getEnabled();
+ }
+
+
+ public String getId() {
+ return info.getId();
+ }
+}
Modified: spaces/trunk/src/com/ogoglio/sim/script/SpaceScriptEngine.java
===================================================================
--- spaces/trunk/src/com/ogoglio/sim/script/SpaceScriptEngine.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/sim/script/SpaceScriptEngine.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -15,6 +15,10 @@
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Vector;
import javax.media.j3d.Transform3D;
@@ -33,6 +37,7 @@
import com.ogoglio.client.model.User;
import com.ogoglio.sim.SpaceSimulator;
import com.ogoglio.util.ArgumentUtils;
+import com.ogoglio.util.ContextMenuInfo;
import com.ogoglio.util.TwoWayMap;
import com.ogoglio.xml.SpaceEvent;
@@ -52,6 +57,9 @@
public static final String ONCLICK_SCRIPT_PREFIX = "if(typeof onClick == \"function\") { onClick(";
+ public static final String ONCONTEXTCLICK_SCRIPT_PREFIX = "if(typeof onContextClick == \"function\") { onContextClick(";
+
+ public static final String CONTEXT_ITEM_SELECTED = "if(typeof onContextMenuItemChosen == \"function\") { onContextMenuItemChosen(";
public static final String ONCLICK_SCRIPT_SUFFIX = "); }";
public SpaceScriptEngine(SpaceSimulator spaceSimulator) {
@@ -69,7 +77,8 @@
ScriptableObject.defineClass(globalScope, ScriptSpace.class);
ScriptableObject.defineClass(globalScope, ScriptMath.class);
ScriptableObject.defineClass(globalScope, ScriptHTTPRequest.class);
-
+ ScriptableObject.defineClass(globalScope, ScriptContextMenuInfo.class);
+
scriptSpace = (ScriptSpace) constructorContext.newObject(globalScope, "Space", new Object[0]);
scriptSpace.setSpaceSimulator(spaceSimulator);
globalScope.put("space", globalScope, scriptSpace);
@@ -120,7 +129,7 @@
}
public void handleSpaceEvent(SpaceEvent event) {
- if (SpaceEvent.THING_CLICKED_EVENT.equals(event.getName())) {
+ if ((SpaceEvent.THING_CLICKED_EVENT.equals(event.getName())) || (SpaceEvent.THING_CONTEXT_CLICKED_EVENT.equals(event.getName()))) {
Long thingID = event.getLongProperty(SpaceEvent.THING_ID);
if (thingID == null) {
return;
@@ -132,20 +141,60 @@
String shapeName = event.getStringProperty(SpaceEvent.SHAPE_NAME);
String script = null;
+ String prefix = ONCLICK_SCRIPT_PREFIX;
+
+ if (SpaceEvent.THING_CONTEXT_CLICKED_EVENT.equals(event.getName())) {
+ prefix = ONCONTEXTCLICK_SCRIPT_PREFIX;
+ }
+ String username = event.getStringProperty(SpaceEvent.USERNAME);
if (shapeName != null) {
- script = ONCLICK_SCRIPT_PREFIX + "\"" + event.getStringProperty(SpaceEvent.USERNAME) + "\", \"" + event.getStringProperty(SpaceEvent.SHAPE_NAME) + "\"" + ONCLICK_SCRIPT_SUFFIX;
+ script = prefix + "\"" + username + "\", \"" + event.getStringProperty(SpaceEvent.SHAPE_NAME) + "\"" + ONCLICK_SCRIPT_SUFFIX;
} else {
- script = ONCLICK_SCRIPT_PREFIX + "\"" + event.getStringProperty(SpaceEvent.USERNAME) + "\", null" + ONCLICK_SCRIPT_SUFFIX;
+ script = prefix + "\"" + username + "\", null" + ONCLICK_SCRIPT_SUFFIX;
}
Context context = Context.enter();
try {
- spaceSimulator.log("Click script: " + evaluateScript(context, thingScope, script));
+ String isContextClick = "no";
+ if (SpaceEvent.THING_CONTEXT_CLICKED_EVENT.equals(event.getName())) {
+ isContextClick = "yes";
+ }
+
+ //the context click is called for value, the regular click for effect
+ if (SpaceEvent.THING_CONTEXT_CLICKED_EVENT.equals(event.getName())) {
+ String errorToClient = processScriptForContextMenuInfo(thingScope,username, event.getLongProperty(SpaceEvent.NONCE).longValue(),
+ script, context);
+
+ if (errorToClient!=null) {
+ spaceSimulator.log("Error in contextmenuclick handler:"+errorToClient);
+ }
+ } else {
+ spaceSimulator.log("Click script : " + evaluateScript(context, thingScope, script));
+ }
} finally {
- context.exit();
+ Context.exit();
}
-
+ } else if (SpaceEvent.THING_CONTEXT_SELECTION_MADE_EVENT.equals(event.getName())) {
+ Long thingID = event.getLongProperty(SpaceEvent.THING_ID);
+ if (thingID == null) {
+ return;
+ }
+ ScriptableObject thingScope = (ScriptableObject) thingScopes.getForward(thingID);
+ if (thingScope == null) {
+ return;
+ }
+ Context context = Context.enter();
+ String username = event.getStringProperty(SpaceEvent.USERNAME);
+ String script = CONTEXT_ITEM_SELECTED + "\"" + username + "\", \"" + event.getStringProperty(SpaceEvent.CONTEXT_MENU_DATA_ITEM_ID) + "\"" + ONCLICK_SCRIPT_SUFFIX ;
+ String result = evaluateScript(context, thingScope, script);
+ spaceSimulator.log("Item selected script : " + result);
+ try {
+ new URL(result); //for effect of parsing it to determine if ok
+ spaceSimulator.showLinkToUser(username, result, result);
+ } catch (MalformedURLException e) {
+ //not a URL, so we are done, assume the call was for effect
+ }
} else if (SpaceEvent.ADD_THING_EVENT.equals(event.getName())) {
- try {
+ try {
Thing thing = spaceSimulator.getSpace().getThing(event.getLongProperty(SpaceEvent.THING_ID).longValue());
if (thing != null) {
constructThingScript(thing);
@@ -163,6 +212,41 @@
}
+ private String processScriptForContextMenuInfo(ScriptableObject thingScope, String username, long nonce, String script, Context context) {
+ Vector arrayOfObjects=new Vector();
+ String result = evaluateScriptForArray(context, thingScope, script, arrayOfObjects);
+ String errorToClient = null;
+ if (result!=null) {
+ spaceSimulator.log("Error in script:"+result);
+ errorToClient = result;
+ } else {
+ for (int i=0; i<arrayOfObjects.size();++i) {
+ ScriptableObject candidate = (ScriptableObject)arrayOfObjects.get(i);
+ if (!(candidate.getClassName().equals(ScriptContextMenuInfo.JS_CLASS_NAME))) {
+ errorToClient = "Should be an array of ContextMenuInfo items but had "+candidate.getClassName() +" in the array1";
+ }
+ }
+ }
+ SpaceEvent event = new SpaceEvent(SpaceEvent.CONTEXT_MENU_DATA_EVENT);
+ event.setProperty(SpaceEvent.NONCE, new Long(nonce));
+ if (errorToClient!=null) {
+ event.setProperty(SpaceEvent.CONTEXT_MENU_DATA_GENERATION_ERROR,errorToClient);
+ } else {
+ //this is so we can use the same types on the client side
+ Vector changedTypeObjects=new Vector();
+ for (int i=0; i<arrayOfObjects.size();++i) {
+ ScriptContextMenuInfo infoWithJSBaggage=(ScriptContextMenuInfo)arrayOfObjects.get(i);
+ ContextMenuInfo infoNoJS=new ContextMenuInfo();
+ infoNoJS.setValues(infoWithJSBaggage.getUserVisibleString(),
+ infoWithJSBaggage.getEnabled(), infoWithJSBaggage.getId());
+ changedTypeObjects.add(infoNoJS);
+ }
+ event.setContextMenu(changedTypeObjects);
+ }
+ spaceSimulator.getListener().generatedSpaceEventForUser(username, event, spaceSimulator);
+ return errorToClient;
+ }
+
private ScriptableObject createThingScope(Context context) {
ScriptableObject scriptScope = (ScriptableObject) context.newObject(globalScope);
scriptScope.setPrototype(globalScope);
@@ -186,7 +270,39 @@
return "Error: " + e;
}
}
-
+
+ // dodgy: this returns an error message or null if things are ok
+ private String evaluateScriptForArray(Context context, ScriptableObject scriptScope, String script, Vector valuesFound) {
+ try {
+ Object result = context.evaluateString(scriptScope, script, "<cmd>", 1, null);
+ if (result == null) {
+ return "null returned by javascript";
+ } else if (result instanceof Undefined) {
+ return "undefined value returned from javascript";
+ } else if (!(result instanceof ScriptableObject)) {
+ return "unexpected return type from javascript";
+ }
+
+ ScriptableObject obj=(ScriptableObject)result;
+ if (!(obj.getClassName().equals("Array"))) {
+ return "Expected Array result but got "+obj.getClassName();
+ }
+ Object length_raw = obj.get("length", obj);
+ if ((length_raw==null) || (!(length_raw instanceof java.lang.Number))){
+ return "Internal error! Can't understand length of array in javascript!";
+ }
+ Number length= (Number)length_raw;
+ for (int i=0; i<length.intValue();++i) {
+ valuesFound.add(obj.get(i, obj));
+ }
+ return null;
+ } catch (EcmaError error) {
+ return "Javascript Error:"+error.getMessage();
+ } catch (Throwable e) {
+ spaceSimulator.log("Caught a throwabe when evaluating script for array:"+e.getMessage());
+ return "(Internal) Error:"+e.getMessage();
+ }
+ }
public static String getMessage(EcmaError e) {
return "Error at line " + e.lineNumber() + " column " + e.columnNumber() + (e.lineSource() == null ? " " : "(" + e.lineSource() + ")") + e.getErrorMessage();
}
Added: spaces/trunk/src/com/ogoglio/util/ContextMenuInfo.java
===================================================================
--- spaces/trunk/src/com/ogoglio/util/ContextMenuInfo.java (rev 0)
+++ spaces/trunk/src/com/ogoglio/util/ContextMenuInfo.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -0,0 +1,23 @@
+package com.ogoglio.util;
+
+public class ContextMenuInfo {
+ private String userVisibleString;
+ private String id;
+ private boolean enabled;
+
+ public String getUserVisibleString() {
+ return userVisibleString;
+ }
+ public String getId() {
+ return id;
+ }
+ public boolean getEnabled() {
+ return enabled;
+ }
+ public void setValues(String textToShow, boolean notGrayedOut, String forCallback) {
+ userVisibleString=textToShow;
+ enabled=notGrayedOut;
+ id=forCallback;
+ }
+
+}
Modified: spaces/trunk/src/com/ogoglio/viewer/applet/AppletTestWindow.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/applet/AppletTestWindow.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/viewer/applet/AppletTestWindow.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -68,7 +68,7 @@
}
//parameters1.put("loginCookie", "guestApplet_Test_Window2");
- parameters1.put("spaceID", "" + 1);
+ parameters1.put("spaceID", "" + 3);
parameters1.put("serviceURI", serviceURI);
//parameters1.put("x", "0");
Modified: spaces/trunk/src/com/ogoglio/viewer/applet/MotionInputHandler.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/applet/MotionInputHandler.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/viewer/applet/MotionInputHandler.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -15,20 +15,21 @@
package com.ogoglio.viewer.applet;
import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.media.j3d.Transform3D;
+import javax.swing.JPopupMenu;
+import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;
import com.ogoglio.client.UserInputListener;
import com.ogoglio.client.model.SplinePath;
+import com.ogoglio.client.model.Thing;
import com.ogoglio.util.ArgumentUtils;
-import com.ogoglio.viewer.j3d.J3DShapeRenderable;
import com.ogoglio.viewer.j3d.J3DSplineKeyFrame;
import com.ogoglio.viewer.j3d.J3DSplinePath;
import com.ogoglio.viewer.render.ClickTarget;
@@ -311,8 +312,11 @@
reevaluate();
}
- public void mouseClicked(MouseEvent e) {
- ClickTarget clickTarget = renderer.getClickTarget(e.getX(), e.getY());
+ public void mouseClicked(MouseEvent event) {
+ if (event.isControlDown() || event.getButton()!=MouseEvent.BUTTON1) {
+ return;
+ }
+ ClickTarget clickTarget = renderer.getClickTarget(event.getX(), event.getY());
if (clickTarget == null) {
return;
}
@@ -323,19 +327,30 @@
ShapeRenderable shapeRenderable = (ShapeRenderable) clickTarget.getRenderable();
Renderable renderable = shapeRenderable.getRenderable();
if (renderable instanceof ThingRenderable) {
- userInputListener.mouseClickedThing(((ThingRenderable) renderable).getThing(), shapeRenderable.getName(), clickTarget.getIntersection());
+ Thing thing = ((ThingRenderable) renderable).getThing();
+ clickedOnAThing(event, thing, shapeRenderable.getName(), clickTarget.getIntersection());
} else if (renderable instanceof DoorRenderable) {
userInputListener.mouseClickedDoor(((DoorRenderable) renderable).getDoor(), shapeRenderable.getName(), clickTarget.getIntersection());
+ } else {
+ throw new IllegalStateException("Clicked on a type of renderable who has a parent we don't understand");
}
} else if (clickTarget.getRenderable() instanceof ThingRenderable) {
- userInputListener.mouseClickedThing(((ThingRenderable) clickTarget.getRenderable()).getThing(), null, clickTarget.getIntersection());
+ clickedOnAThing(event, ((ThingRenderable) clickTarget.getRenderable()).getThing(), null, clickTarget.getIntersection());
} else if (clickTarget.getRenderable() instanceof DoorRenderable) {
userInputListener.mouseClickedDoor(((DoorRenderable) clickTarget.getRenderable()).getDoor(), null, clickTarget.getIntersection());
} else if (clickTarget.getRenderable() instanceof PageRenderable) {
userInputListener.mouseClickedPage(((PageRenderable) clickTarget.getRenderable()).getPage(), clickTarget.getIntersection());
+ } else {
+ throw new IllegalStateException("Clicked on a type of renderable we don't understand");
}
+
}
+ private void clickedOnAThing(MouseEvent event, Thing thing, String name, Point3d intersection) {
+ userInputListener.mouseClickedThing(thing, name, intersection);
+
+ }
+
public void mouseDragged(MouseEvent e) {
}
@@ -348,9 +363,50 @@
public void mouseExited(MouseEvent e) {
}
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(MouseEvent event) {
+ System.out.println("POPUP TRIGGER FART:"+event.isPopupTrigger()+","+new JPopupMenu().isPopupTrigger(event)+","+
+ event.isControlDown()+","+event.paramString()+","+event.getButton());
+ ClickTarget clickTarget = renderer.getClickTarget(event.getX(), event.getY());
+ if (clickTarget == null) {
+ return;
+ }
+ ThingRenderable renderable;
+ String name = null;
+
+ if (clickTarget.getRenderable() instanceof ThingRenderable) {
+ renderable = (ThingRenderable) clickTarget.getRenderable();
+ } else if (clickTarget.getRenderable() instanceof ShapeRenderable) {
+ ShapeRenderable shape = (ShapeRenderable) clickTarget.getRenderable();
+ renderable = (ThingRenderable) shape.getRenderable();
+ name = shape.getName();
+ } else {
+ return;
+ }
+ if (event.isPopupTrigger()) {
+ userInputListener.mouseContextClickedThing(renderable.getThing(), name, event.getX(), event.getY());
+ event.consume();
+ }
}
- public void mouseReleased(MouseEvent e) {
+ public void mouseReleased(MouseEvent event) {
+ ClickTarget clickTarget = renderer.getClickTarget(event.getX(), event.getY());
+ if (clickTarget == null) {
+ return;
+ }
+ ThingRenderable renderable;
+ String name = null;
+
+ if (clickTarget.getRenderable() instanceof ThingRenderable) {
+ renderable = (ThingRenderable) clickTarget.getRenderable();
+ } else if (clickTarget.getRenderable() instanceof ShapeRenderable) {
+ ShapeRenderable shape = (ShapeRenderable) clickTarget.getRenderable();
+ renderable = (ThingRenderable) shape.getRenderable();
+ name = shape.getName();
+ } else {
+ return;
+ }
+ if (event.isPopupTrigger()) {
+ userInputListener.mouseContextClickedThing(renderable.getThing(), name, event.getX(), event.getY());
+ }
}
}
Modified: spaces/trunk/src/com/ogoglio/viewer/applet/ViewerApplet.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/applet/ViewerApplet.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/viewer/applet/ViewerApplet.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -18,18 +18,27 @@
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Panel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
import javax.media.j3d.Transform3D;
import javax.swing.JLabel;
+import javax.swing.JMenuItem;
import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
import javax.vecmath.Vector3d;
import netscape.javascript.JSObject;
import com.ogoglio.client.SpaceClient;
+import com.ogoglio.client.model.Thing;
+import com.ogoglio.util.ContextMenuInfo;
import com.ogoglio.viewer.j3d.J3DRenderer;
import com.ogoglio.viewer.render.Renderer;
@@ -47,6 +56,8 @@
private String authCookie = null;
+ private Map popupMap = new HashMap();
+
public ViewerApplet() {
setBackground(Color.WHITE);
setLayout(new BorderLayout());
@@ -159,7 +170,34 @@
e.printStackTrace();
}
}
+
+
+ private void showPopup(Thing thing, int x, int y, long nonce) {
+ ThingGeneratedPopup popup=new ThingGeneratedPopup(thing,nonce);
+ popup.show(this,x,y);
+ popupMap.put(new Long(nonce),popup);
+ }
+
+ private void sendServerSelectionMessage(Thing thing, long nonce,String id) {
+ spaceClient.mouseContextItemChosen(thing,nonce,id);
+ }
+
+
+ public void populatePopup(long nonce, String errorIfAny, Vector contextMenu) {
+ if (!popupMap.containsKey(new Long(nonce))) {
+ System.err.println("[Internal Error] context menu data ("+nonce+") couldn't be matched to a menu!");
+ return;
+ }
+ if (errorIfAny!=null) {
+ System.err.println("[Javascript Error]:"+errorIfAny);
+ } else {
+ ThingGeneratedPopup popup = (ThingGeneratedPopup)popupMap.get(new Long(nonce));
+ popup.populate(contextMenu);
+ }
+ popupMap.remove(new Long(nonce));
+ }
+
private void showLink(String displayName, String link) {
try {
JSObject win = JSObject.getWindow(this); // get handle to a window.
@@ -233,7 +271,7 @@
//add(new ErrorPanel("Unfortunately, I lost the connection to the server."), BorderLayout.CENTER);
//validate();
}
-
+
public void receivedChatMessage(String username, String message) {
addChatMessage(username + ":" + message);
}
@@ -261,8 +299,64 @@
public void receivedBrowserMessage(long sourceThingID, String message) {
messageBrowser(sourceThingID, message);
}
+
+ public void receivedContextMenuRequest(Thing thing, String shapeName, int x, int y, long nonce) {
+ showPopup(thing,x, y, nonce);
+ }
+
+ public void receivedContextMenuData(long nonce, String errorIfAny, Vector contextMenu) {
+ populatePopup(nonce,errorIfAny,contextMenu);
+ }
+
+ public void contextItemChosen(Thing thing, long nonce, String id) {
+ }
+
+
}
+ private class ThingGeneratedPopup extends JPopupMenu {
+
+ JMenuItem waitingItem;
+ Thing thing;
+ long startTime;
+ long nonce;
+
+ public ThingGeneratedPopup(Thing theThing, long theNonce) {
+ waitingItem=add("Retreiving menu...");
+ thing=theThing;
+ nonce=theNonce;
+ startTime=System.currentTimeMillis();
+ }
+
+ public boolean populate(final Vector items) {
+ if (!this.isVisible()) {
+ return false;
+ }
+ remove(waitingItem);
+ for (int i=0; i<items.size();++i) {
+ ContextMenuInfo info = (ContextMenuInfo)items.get(i);
+ JMenuItem item=new JMenuItem(info.getUserVisibleString());
+ item.setEnabled(info.getEnabled());
+ add(item);
+ final String id=info.getId();
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ sendSelection(id);
+ }
+ });
+ }
+ //IES: I have no idea why this causes a relayout that works properle. ugh. totally broken.
+ this.setVisible(false);
+ this.setVisible(true);
+ return true;
+ }
+
+ public void sendSelection(String id) {
+ sendServerSelectionMessage(thing,nonce,id);
+ }
+
+ }
+
//TODO make the error panel less ugly
private class ErrorPanel extends Panel {
public ErrorPanel(String errorMessage) {
@@ -285,4 +379,5 @@
}
}
+
}
Modified: spaces/trunk/src/com/ogoglio/xml/SpaceEvent.java
===================================================================
--- spaces/trunk/src/com/ogoglio/xml/SpaceEvent.java 2007-08-16 19:33:40 UTC (rev 244)
+++ spaces/trunk/src/com/ogoglio/xml/SpaceEvent.java 2007-08-19 20:01:35 UTC (rev 245)
@@ -17,16 +17,16 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
+import java.util.Vector;
import javax.media.j3d.Transform3D;
-import javax.vecmath.Point3f;
import javax.vecmath.Quat4d;
import javax.vecmath.Vector3d;
import nanoxml.XMLElement;
import com.ogoglio.client.model.SplinePath;
-import com.ogoglio.viewer.j3d.J3DSplineKeyFrame;
+import com.ogoglio.util.ContextMenuInfo;
import com.ogoglio.viewer.j3d.J3DSplinePath;
public class SpaceEvent {
@@ -82,7 +82,7 @@
public static final String USERNAME = "userID";
public static final String BODY_ID = "bodyID";
-
+
public static final String THING_ID = "thingID";
public static final String TEMPLATE_ID = "templateID";
@@ -125,6 +125,8 @@
public static final String THING_CLICKED_EVENT = "thingClicked";
+ public static final String THING_CONTEXT_CLICKED_EVENT = "thingContextClicked";
+
public static final String SCRIPT_REQUEST_EVENT = "scriptRequest";
public static final String SRE_SCRIPT = "script";
@@ -194,11 +196,27 @@
public static final String MESSAGE_BROWSER_EVENT = "MessageBrowser";
public static final String MESSAGE_TO_BROWSER = "message";
-
+
public static final String PLAY_ANIMATION_EVENT = "PlayAnimation";
-
+
public static final String ANIMATION_ID = "animationID";
+ public static final String NONCE = "nonce";
+
+ public static final String CONTEXT_MENU_DATA_EVENT = "menuContent";
+
+ public static final String CONTEXT_MENU_DATA_GENERATION_ERROR = "contextMenuScriptIsHosed";
+
+ public static final String CONTEXT_MENU_DATA_ITEM = "contextMenuItem";
+
+ public static final String CONTEXT_MENU_DATA_ITEM_TEXT = "contextMenuItemText";
+
+ public static final String CONTEXT_MENU_DATA_ITEM_ENABLED = "contextMenuItemEnabled";
+
+ public static final String CONTEXT_MENU_DATA_ITEM_ID = "contextMenuItemId";
+
+ public static final String THING_CONTEXT_SELECTION_MADE_EVENT = "contextMenuItemChosen";
+
private String name = null;
private HashMap properties = new HashMap();
@@ -207,6 +225,8 @@
private String html = null;
+ private Vector contextMenu = new Vector();
+
public SpaceEvent(String name) {
this.name = name;
}
@@ -245,8 +265,33 @@
HtmlElement ele = new HtmlElement(htmlElement);
html = ele.getHtml();
}
+
+ XMLElement[] allMenuItems = element.getChildren(CONTEXT_MENU_DATA_ITEM);
+ if (allMenuItems != null) {
+ Vector result = new Vector();
+ for (int i = 0; i < allMenuItems.length; ++i) {
+ XMLElement item = allMenuItems[i];
+ String text = item.getStringAttribute(CONTEXT_MENU_DATA_ITEM_TEXT);
+ boolean enabled = item.getBooleanAttribute(CONTEXT_MENU_DATA_ITEM_ENABLED);
+ String id = item.getStringAttribute(CONTEXT_MENU_DATA_ITEM_ID);
+
+ //go through front door!
+ ContextMenuInfo info = new ContextMenuInfo();
+ info.setValues(text, enabled, id);
+ result.add(info);
+ }
+ setContextMenu(result);
+ }
}
+ public void setContextMenu(Vector arrayOfObjs) {
+ contextMenu = arrayOfObjs;
+ }
+
+ public Vector getContextMenu() {
+ return contextMenu;
+ }
+
public String getName() {
return name;
}
@@ -335,6 +380,17 @@
if (html != null) {
element.addChild(new HtmlElement(html).toElement());
}
+ if (contextMenu!=null) {
+ for (int i=0; i<contextMenu.size();++i) {
+ ContextMenuInfo info=(ContextMenuInfo)contextMenu.get(i);
+ XMLElement item = new XMLElement();
+ item.setName(CONTEXT_MENU_DATA_ITEM);
+ item.setAttribute(CONTEXT_MENU_DATA_ITEM_TEXT, info.getUserVisibleString());
+ item.setAttribute(CONTEXT_MENU_DATA_ITEM_ENABLED, info.getEnabled());
+ item.setAttribute(CONTEXT_MENU_DATA_ITEM_ID, info.getId());
+ element.addChild(item);
+ }
+ }
return element;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|