Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


These notes are for Java developers who want to convert their Java applets or Java applications to
JavaScript, allowing continued one-source development of both Java and JavaScript.
JavaScript, allowing continued, simultaneous one-source development of both Java and JavaScript.

Developers of java2script/SwingJS itself should read README-developers.md

Expand Down Expand Up @@ -32,9 +32,9 @@ See https://github.com/BobHanson/java2script/tree/master/dist and the README fil

https://github.com/BobHanson/java2script (development master)

Current development "Version 3 development master" involving a completely rewritten transpiler (2017) that nearly perfectly emulates the Java Virtual Machine, including fully qualified methods, compile-time method binding, generic methods and classes, Java reflection for efficient modular just-in-time class loading, Java Swing components, modal and nonmodel dialogs, audio, jpdf, the AWT event thread, and many other added packages. Java applications and applets can both be run in JavaScript in a browser.
Current development "Version 3 development master" involve a completely rewritten transpiler (2017) “CompilationParticipant” that follows the Eclipse Java compiler. The implementation nearly perfectly emulates the Java Virtual Machine. It includes fully qualified methods, compile-time method binding, generic methods and classes, Java 8 lambda functions and streams, Java reflection and dynamic class loading for efficient modular just-in-time performance, Java Swing components, modal and nonmodel dialogs, audio, jpdf, the AWT event thread, and many other added packages. Java applications and applets can both be run in JavaScript in any browser.

Version 3 also implements real-time creation of HTML test files for immediate JavaScript testing of any changes made to the Java code. Basically, when the source file is saveed in Eclipse, the JavaScript updates automatically, and a reload of the page in the browser shows the changes directly. This makes for very easy side-by-side Java and JavaScript debugging.
Version 3 also implements real-time creation of HTML test files for immediate JavaScript testing of any changes made to the Java code. Basically, when the source file is saved in Eclipse (Photon), the JavaScript updates automatically, and a reload of the page in the browser shows the changes immediately. This makes for very easy side-by-side Java and JavaScript debugging.

Unlike Version 2, Version 3 requires minimal reworking of Java classes - primarily just for performance and threading* reasons, maximizing JavaScript performance without compromising any Java performance and making Java-to-JavaScript conversion almost trivial. (Of course, we are still finding occasional bugs in the transpiler and run-time "JavaScript-JVM.")

Expand All @@ -52,7 +52,7 @@ Varna https://github.com/BobHanson/VARNA and https://chemapps.stolaf.edu/swingjs

https://github.com/java2script/java2script (stable master)

Ported from SourceForge by Zhou Renjian, developed further by Zhou Renjian and Udo Borkowski (primariy) as "Version 2.0".
Ported from SourceForge by Zhou Renjian, developed further by Zhou Renjian and Udo Borkowski (primarily) as "Version 2.0".

Extensively used by Bob Hanson in 2012-2016 for the conversion of Jmol/java to JSmol/javascript (http://jmol.sourceforge.net/), leading to extensive distribution and widespread use on the web. As of 3/2018, still the
only known widely-available java2sript application.
Expand All @@ -61,7 +61,7 @@ Developed further in 2016 by zhou Renjian, Udo Borkowski, Bob Hanson, Andrew Rad
dubbed "SwingJS". Used by Bob Hanson during 11/2016 for conversion of the PhET gas applications applets.

Version 2 allowed extensive development of JavaScript versions of Java applets, including JSmol, Falstad applets, and PhET applets.
However, this version did not produce "fully qualified" method signatures, resulting in error-prone and performance-reducing run-time binding of methods. Java class loading procedures were not consistent with the seqence of events used by the Java class loader, and parameter and array typing was minimal. Thus, while functional, Version 2 was not fully generalizable and required extensive reworking of Java code to be "java2script compliant."
However, this version did not produce "fully qualified" method signatures, resulting in error-prone and performance-reducing run-time binding of methods. Java class loading procedures were not consistent with the sequence of events used by the Java class loader, and parameter and array typing was minimal. Thus, while functional, Version 2 was not fully generalizable and required extensive reworking of Java code to be "java2script compliant."

Synchronized with https://github.com/BobHanson/java2script as the stable master version in 2018.

Expand Down
Binary file modified sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion sources/net.sf.j2s.core/dist/swingjs/timestamp
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20181117145755
20181120221948
Binary file modified sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/SwingJS-site.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/timestamp
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20181117145755
20181120221948
Binary file modified sources/net.sf.j2s.java.core/dist/SwingJS-site.zip
Binary file not shown.
3 changes: 2 additions & 1 deletion sources/net.sf.j2s.java.core/src/java/awt/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -2884,7 +2884,8 @@ final void updateCursorImmediately() {
// cPeer.updateCursorImmediately();
// }
// } else if (peer != null) {
peer.updateCursorImmediately();
if (peer != null)
peer.updateCursorImmediately();
// }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ public void run() {
}
};
JSThread me = this;
JSFunction f = /** @j2sNative function() {r.run$();me.run1$I(mode)} || */ null;
int mode = LOOP;
JSFunction f = /** @j2sNative function() {r.run$();me.run1$I(mode)} || */ null;
JSToolkit.dispatch(f, 0, 0);
// handling sleepAndReturn myself
// and once through only
Expand Down
5 changes: 5 additions & 0 deletions sources/net.sf.j2s.java.core/src/javax/swing/JFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ public JFrame(String title, GraphicsConfiguration gc, String uiid) {
rootPane.addNotify(); // builds a peer for the root pane
}

public JFrame(Object object, Object object2, Object object3, Object object4) {
uiClassID = "FrameUI";

}

private static int frameCount;

/**
Expand Down
6 changes: 3 additions & 3 deletions sources/net.sf.j2s.java.core/src/javax/swing/JMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -823,9 +823,9 @@ public void remove(int pos) {
*/
@Override
public void remove(Component c) {
if (c instanceof JMenuItem)
if (popupMenu != null)
popupMenu.remove(c);
// why did I add this? BH 2018 if (c instanceof JMenuItem)
// if (popupMenu != null)
// popupMenu.remove(c);
if (popupMenu != null)
popupMenu.remove(c);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1765,7 +1765,7 @@ public static ActionMap getUIActionMap(JComponent component) {
static class SharedOwnerFrame extends JFrame implements WindowListener {

SharedOwnerFrame() {
super(); // required by SwingJS
super(null, null, null, null); // required by SwingJS
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion sources/net.sf.j2s.java.core/src/javax/swing/Timer.java
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ private ArrayList<Object> timerQueue() {
public void restart() {
// getLock().lock();
// try {
// stop();
stop();
start();
// } finally {
// getLock().unlock();
Expand Down
7 changes: 5 additions & 2 deletions sources/net.sf.j2s.java.core/src/swingjs/JSFrameViewer.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,12 @@ public Graphics getGraphics() {
public Graphics getGraphics(int wNew, int hNew, RootPaneContainer window) {
if (window == null) // from, for example, a resize of the browser page
window = top;
if (window == null)
return null; // will be null from j2sApplet.js

// technically, a JApplet is not a Window, but it is a Container and it is a
// RootPaneContainer
JSComponent c = (JSComponent) window; // will be null from j2sApplet.js
JSComponent c = (JSComponent) window;
if (wNew == 0) {
wNew = Math.max(0, window.getContentPane().getWidth());
hNew = Math.max(0, window.getContentPane().getHeight());
Expand Down Expand Up @@ -227,7 +230,7 @@ private HTML5Canvas newCanvas(int width, int height, RootPaneContainer window) {
}
DOMNode rootNode = (root == null ? null : ((JSComponentUI) root.getUI()).domNode);
if (rootNode != null)
DOMNode.remove(canvas);
DOMNode.dispose(canvas);
display = canvasId = appletViewer.appletName + "_canvas" + ++canvasCount;
canvas = (HTML5Canvas) DOMNode.createElement("canvas", canvasId);
if (userFramedApplet != null) {
Expand Down
4 changes: 3 additions & 1 deletion sources/net.sf.j2s.java.core/src/swingjs/JSKeyEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ public static JSKeyEvent newJSKeyEvent(JComponent source, Object jQueryEvent, bo
: evType == "keypress" ? KEY_TYPED
: evType == "keyup" ? KEY_RELEASED
: 0);
if (id == 0)
return null;
int keyCode = getJavaKeyCode(jskeyCode, jskey);
char keyChar = getJavaKeyChar(keyCode, jskey);
return (id == 0 || keyChar == CHAR_UNDEFINED && id == KEY_TYPED ? null
return (keyChar == CHAR_UNDEFINED && id == KEY_TYPED ? null
: new JSKeyEvent(source, jQueryEvent, id,
(id == KEY_TYPED ? JSKeyEvent.VK_UNDEFINED : keyCode),
keyChar,
Expand Down
4 changes: 2 additions & 2 deletions sources/net.sf.j2s.java.core/src/swingjs/JSMouse.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private void clicked(long time, int x, int y, int modifiers, int clickCount) {
// clearKeyBuffer();
// clickedCount is not reliable on some platforms
// so we will just deal with it ourselves
mouseAction(MouseEvent.MOUSE_CLICKED, time, x, y, 1, modifiers, 0);
mouseAction(MouseEvent.MOUSE_CLICKED, time, x, y, clickCount, modifiers, 0);
}

private boolean isCtrlShiftMouseDown; // Macintosh may not recognize CTRL-SHIFT-LEFT as
Expand Down Expand Up @@ -278,7 +278,7 @@ private void mouseAction(int id, long time, int x, int y, int xcount,
extended == InputEvent.META_DOWN_MASK ||
JSToolkit.isMac && extended == (InputEvent.CTRL_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK));
int button = getButton(modifiers);
int count = updateClickCount(id, time, x, y);
int count = (xcount > 1 && id == MouseEvent.MOUSE_CLICKED ? xcount : updateClickCount(id, time, x, y));

Component source = viewer.getTopComponent(); // may be a JFrame
MouseEvent e;
Expand Down
4 changes: 2 additions & 2 deletions sources/net.sf.j2s.java.core/src/swingjs/JSToolkit.java
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,8 @@ private static void invokeAndWait(JSFunction f, int id) {
* var id0 = SwingJS.eventID || 0;
* SwingJS.eventID = id;
* java.lang.Thread.thisThread = thread;
* if (f.run)
* f.run();
* if (f.run$)
* f.run$();
* else
* f();
* SwingJS.eventID = id0;
Expand Down
27 changes: 11 additions & 16 deletions sources/net.sf.j2s.java.core/src/swingjs/JSUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static Object getCachedFileData(String path) {

/**
* This could be a simple String, a javajs.util.SB, or unsigned or signed bytes
* depending upon the browser and the file type.
* depending upon the browser and the file type.
*
* It will not be cached, but it might come from a cache;
*
Expand All @@ -78,24 +78,19 @@ private static Object getCachedFileData(String path) {
@SuppressWarnings("unused")
private static Object getFileContents(Object uriOrJSFile) {
if (uriOrJSFile instanceof File) {
byte[] bytes = /** @j2sNative uriOrJSFile.bytes ||*/ null;
if (bytes != null)
return bytes;
byte[] bytes = /** @j2sNative uriOrJSFile.bytes || */
null;
if (bytes != null)
return bytes;
}
String uri = uriOrJSFile.toString();
Object data = getCachedFileData(uri);
if (data == null) {

// for reference -- not used in JavaScript

/**
* @j2sNative
*
*/
try {
data = Rdr.streamToUTF8String((BufferedInputStream) new URL(uri).getContent());
} catch (Exception e) {
}
if (data == null && !uri.startsWith("./")) {
// Java applications may use "./" here
try {
data = Rdr.streamToUTF8String((BufferedInputStream) new URL(uri).getContent());
} catch (Exception e) {
}
// bypasses AjaxURLConnection
data = JSUtil.J2S.getFileData(uri, null, false, false);
}
Expand Down
6 changes: 4 additions & 2 deletions sources/net.sf.j2s.java.core/src/swingjs/a2s/A2SEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public void run() {
Event e = this.e;
Component target = (Component) this.target;
if (target instanceof Container) {
target = ((Container)target).getMouseEventTarget(e.x, e.y, true, null, false);
Component parent = target;
Component parent = ((Container)target).getMouseEventTarget(e.x, e.y, true, null, false);
// on a focus-out event, e.x or e.y may be negative
if (parent != null)
target = parent;
while (parent != null && parent != this.target) {
e.x -= parent.getX();
e.y -= parent.getY();
Expand Down
29 changes: 27 additions & 2 deletions sources/net.sf.j2s.java.core/src/swingjs/api/js/DOMNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public abstract class DOMNode {
// "abstract" in the sense that these are the exact calls to JavaScript

public abstract void appendChild(DOMNode node);

public abstract DOMNode removeChild(DOMNode node);

public abstract boolean hasFocus();

Expand Down Expand Up @@ -249,10 +251,32 @@ public static int getWidth(DOMNode node) {
* @param node
* @return parent or null
*/
public static void remove(DOMNode node) {
public static void dispose(DOMNode node) {
if (node != null)
JSUtil.jQuery.$(node).remove();
}

/**
* Just remove the node; don't
* @param node
*/
public static void remove(DOMNode node) {

// NOTE: IE does not have node.remove()

DOMNode p = getParent(node);
if (p != null)
p.removeChild(node);
}

public static void detachAll(DOMNode node) {
/**
* @j2sNative
* if(node)
* while(node.lastChild)
* node.removeChild(node.lastChild);
*/
}

/**
* jQuery detach() + append()
Expand All @@ -266,7 +290,8 @@ public static DOMNode transferTo(DOMNode node, DOMNode container) {
return null;
DOMNode p = getParent(node);
try {
JSUtil.jQuery.$(node).detach();
if (p != null)
JSUtil.jQuery.$(node).detach();
} catch (Throwable e) {
// ignore
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public interface JSSwingMenu {
void hideMenu(JPopupMenu menu);
void setMenu(JPopupMenu menu);
void showMenu(JPopupMenu menu, int x, int y);
void updateMenu(JPopupMenu menu);
void updateMenu(JPopupMenu menu, boolean andShow);
void updateMenuItem(JPopupMenu menu, DOMNode domNode);


Expand Down
20 changes: 11 additions & 9 deletions sources/net.sf.j2s.java.core/src/swingjs/jquery/j2sMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ Swing.__getMenuStyle = function(applet) { return '\
.swingjsPopupMenu .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;position:absolute;top:.2em;left:.2em}\
.swingjsPopupMenu .ui-menu-icon{position:static;float:right}\
.swingjsPopupMenu .ui-icon-carat-1-e{min-width:10ex;text-align:right;background-image:none;background-position:0 0}\
.swingjsPopupMenu .ui-icon-carat-1-e:after{content:"\\23F5"}\
.swingjsPopupMenu .ui-icon-carat-1-e:after{content:"\\0023F5"}\
.swingjsPopupMenu .ui-state-default{border:1px solid #c5dbec;background:#dfeffc;color:#2e6e9e}\
.swingjsPopupMenu .ui-state-default a{color:#2e6e9e;text-decoration:none}\
.swingjsPopupMenu .ui-state-hover,.swingjsPopupMenu .ui-state-focus{border:1px solid #79b7e7;background:#d0e5f5;color:#1d5987}\
Expand Down Expand Up @@ -204,7 +204,7 @@ Swing.initMenuItem = function(item) {
item.icon && (item.icon = '<img src="' + item._applet._j2sPath + '/' + item.icon + '" style="max-height: 20px;" />')
}

Swing.updateMenu = function(menu) {
Swing.updateMenu = function(menu, andShow) {
if (menu.uiClassID) {
// for SwingJS the top node is domNode itself, which is already <ul>
var node = menu.ui.domNode;
Expand All @@ -217,7 +217,9 @@ Swing.updateMenu = function(menu) {
J2S.$(node).addClass("swingjsPopupMenu");
}
J2S.$after("body",node);
node.style.display = "block";
if (andShow) {
node.style.display = "block";
}
} else {
menu.$ulTop.html(menu.toHTML());
bindMenuActionCommands(menu._actionEvent, menu, true);
Expand Down Expand Up @@ -253,12 +255,12 @@ Swing.showMenu = function(menu, x, y) {
menu._visible = true;
menu.timestamp = System.currentTimeMillis$();
menu.dragBind(true);
// menu.$ulTop.unbind('clickoutjsmol mousemoveoutjsmol');
// if (!J2S._persistentMenu)
// menu.$ulTop.bind('clickoutjsmol mousemoveoutjsmol', function(evspecial, target, ev) {
// if (System.currentTimeMillis$() - menu.timestamp > 500)
// Swing.hideMenu(menu);
// });
menu.$ulTop.unbind('clickoutjsmol mousemoveoutjsmol');
if (!J2S._persistentMenu)
menu.$ulTop.bind('clickoutjsmol mousemoveoutjsmol', function(evspecial, target, ev) {
if (System.currentTimeMillis$() - menu.timestamp > 500)
Swing.hideMenu(menu);
});
menu.$ulTop.bind("contextmenu", function() {return false;});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
};

var fDrag = function(xye, id) {
if (me.options.disabled)
if (id != 506 || me.options.disabled)
return;
var event = xye.ev;
var position = me._getPosition(event);
Expand Down Expand Up @@ -250,8 +250,6 @@
return false;
}

this.elementOffset = this.element.offset();

var position = this._getPosition(event);

index = event.target.index;
Expand Down Expand Up @@ -620,12 +618,13 @@
},

_getPixelMouse : function(position, offsetHandle) {
var offset = this.element.offset;
var p = (this.orientation === "horizontal" ?
position.x
- this.elementOffset.left
- offset.left
- (this._clickOffset ? this._clickOffset.left : 0)
: position.y
- this.elementOffset.top
- offset.top
- (this._clickOffset ? this._clickOffset.top : 0));
return p - this.handleSize / 2;
},
Expand Down
Loading