X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=swingjs%2Fver%2F3.2.9-j11%2Fdifferences.txt;fp=swingjs%2Fver%2F3.2.9-j11%2Fdifferences.txt;h=46e49ec1a16ebb1b20290830c256a4cf7d19e07f;hb=6c27b7864ec61c420326a75e7cce476cf8d60395;hp=0000000000000000000000000000000000000000;hpb=5d501d5230ad1c42f1e17a485cb86a04ba8b538a;p=jalview.git diff --git a/swingjs/ver/3.2.9-j11/differences.txt b/swingjs/ver/3.2.9-j11/differences.txt new file mode 100644 index 0000000..46e49ec --- /dev/null +++ b/swingjs/ver/3.2.9-j11/differences.txt @@ -0,0 +1,1484 @@ +Notes +===== + +---IMPORTANT CHARACTER SET NOTE--- + +It is critical that all development work in Java2Script +be done in UTF-8. This means: + +- making sure your Eclipse project is set up for UTF-8 (not the Eclipse default?) +- making sure your server can serve up UTF-8 by default for any browser-loaded files +- making sure you don't edit a Java2Script class file or one of the site .js files + using a non-UTF-8 editor. It may replace non-Latin characters with "?" or garbage. +- making sure that your web pages are delivered with proper headings indicating HTML5 and UTF-8 + + + +
+ + +Note that the DOCTYPE tag is critical for some browsers to switch into HTML5 mode. (MSIE?) + + + + +In particular, the Mandarin character ç§ (mi; "secret") is used extensively throughout +the SwingJS class files to distinguish j2s-specific fields and methods that must not +ever be shadowed or overridden by subclasses. For example, we see in java.lang.Thread.java: + + public static JSThread ç§thisThread; + +---------------------------------- + + +updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering +updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx" +updated 2/26/2020 -- adds Graphics.setClip issue +updated 12/22/19 -- additional issues +updated 11/03/19 -- adds information about File.exists() and points to src/javajs/async +updated 10/26/19 -- adds information about File.createTempFile() +updated 8/16/19 -- minor typos and added summary paragraph +updated 7/19/19 -- clarification that AWT and Swing classes are supported directly +updated 5/13/19 -- Mandarin U+79D8 reserved character; Missing Math methods; int and long +updated 5/10/19 -- adds a section on static issues in multi-(duplicate)-applet pages +updated 1/4/19 -- nio +updated 9/15/18 -- adds integer 1/0 == Infinity +updated 7/24/18 -- most classes replaced with https://github.com/frohoff/jdk8u-jdk +updated 6/5/17 -- reserved package name "window" +updated 3/11/17 -- myClass.getField +updated 3/7/17 -- overloading of JSplitPane.setDividerLocation +updated 3/2/17 -- more indication of classes not implemented (KeyListener) + +============================================================================= +SwingJS and OpenJDK 8+ +============================================================================= + +SwingJS implements a wide range of the Java language in JavaScript. The base +version for this implementation is OpenJDK8. some classes are implemented using +older source code, and there are some missing methods. For the most part, this is +no real problem. You can add or modify any java class just be adding it as source +in your project. Or (preferably) you can contact me, and I can get it into the +distribution. Or (even more preferably) you can do that via a patch submission. + +================= +DESIGN PHILOSOPHY +================= + +The java2script/SwingJS design goal is to recreate a recognizable, easily debuggable +equivalent in JavaScript for as much of Java as practical. This means, for example, +that one can call in JavaScript + + new java.util.Hashtable() + +and for all practical purposes it will appear that Java is running. + + +Method and Field Disambiguation +------------------------------- + +SwingJS has no problem with the overloading of methods, for example: + + public void print(int b); + public void print(float b); + +JavaScript does not allow overloading of methods, and the common practice in +Java of naming a field the same as a method -- isAllowed and isAllowed() -- is +not possible in JavaScript. As a result, SwingJS implements "fully-qualified" +method names using "$" parameter type separation. Thus, these methods in SwingJS +will be referred to as print$I and print$F. The rules for this encoding are +relatively simple: + +1. The seven primitive types in Java are encoded $I (int), $L (long), $F (float), +$D (double), $B (byte) $Z (boolean), and $H (short). + +2. String and Object are encoded as $S and $O, respectively. + +3. "java_lang_" is dropped for all other classes in the java.lang package (as in Java). + For example: $StringBuffer, not $java_lang_StringBuffer + +4. All other classes are encoded as + + "$" + Class.getName().replace(".","_") + +For example, in Java we see: + + public void equals(Object o) {...} + +Whereas in SwingJS we have: + + Clazz.newMeth(C$, 'equals$O', function (o) {...} + +And + + this.getContentPane().add(bar, "North"); + +becomes + + this.getContentPane$().add$java_awt_Component$O(bar, "North"); + +5. Arrays are indicated with appended "A" for each level. So + + setDataVector(Object[][] dataVector, Object[] columnIdentifiers) + +becomes + + setDataVector$OAA$OA(dataVector, columnIdentifiers) + +(It is recognized that this design does introduce a bit of ambiguity, in that + in principal there could be user class named XA and X in the same package, + and methods a(X[]) and a(XA) in the same class that cannot be distinguished. + The benefit of this simple system, however, triumphed over the unlikelyhood + of that scenario.) The transpiler could be set to flag this possibility. + +6. Constructors are prepended with "c$". So + + public JLabel(String text) {...} + +becomes: + + Clazz.newMeth(C$, 'c$$S', function (text) {...}); + +Field disambiguation involves prepending. In Java, a class and its subclass +can both have the same field name, such as + + boolean visible; + +When this happens, it is called "shadowing", and though not recommended, Java allows +it. The Java2Script transpiler will prepend such shadowing fields with "$" so that the +subclass instance has both "visible" (for use in its methods inherited from its +superclass) and "$visible" (for its own methods). Thus, we might see in Java: + + this.visible = super.visible; + +while in SwingJS we will see: + + this.$visible=this.visible; + +since JavaScript does not have the "super" keyword. + + + +Parameterless methods such as toString() are appended with "$" to become toString$(). +The one exception to this rule is private methods, which are saved in (truly) private +array in the class (and are not accessible by reflection). Private parameterless +methods retain their simple Java name, since they cannot conflict with field names. + +This renaming of methods has a few consequences, which are discussed more fully below. +See particularly the section on "qualified field and method names", where it is described +how you can use packages or classes or interfaces with ".api.js" in them to represent JavaScript +objects for which all method names are to be left unqualified. Note that it is not +possible to cherry-pick methods to be unqualified; only full packages, classes or +interfaces can hold this status. + +The swingjs.api.js package in particular contains a number of useful interfaces that +you can import into your project for JavaScript-specific capabilities. + + +Applet vs. Application +---------------------- + +One of the very cool aspects of SwingJS is that it doesn't particularly matter if a browser-based +Java app is an "applet" or an "application". We don't need JNLP (Java Network Launch Protocol) +because now we can just start up any Java application in a browser just as easily as any applet. +The associative array that passes information to the SwingJS applet (information that formerly +might have been part of the APPLET tag, such as width, height, and codebase, always referred to +in our writing as "the Info array") allows the option to specify the JApplet/Applet "code" +class or the application "main" class. Either one will run just fine. + + +Performance +----------- + +Obviously, there are limitations. One is performance, but we have seen reproducible +performance at 1/6 - 1/3 the speed of Java. Achieving this performance may require +some refactoring of the Java to make it more efficient in both Java and JavaScript. +"for" loops need to be more carefully crafted; use of "new" and "instanceof" need to be +minimized in critical areas. Note that method overloading -- that is, the same method name +with different parameters, such as read(int) and read(byte) -- is no longer any problem. + + +Threads +------- + +Although there is only a single thread in JavaScript, meaning Thread.wait(), Thread.sleep(int) and +Thread.notify() cannot be reproduced, we have found that this is not a serious limitation. +For example, javax.swing.Timer() works perfectly in JavaScript. All it means is that threads +that use sleep(int) or notify() must be refactored to allow Timer-like callbacks. That is, +they must allow full exit and re-entry of Thread.run(), not the typical while/sleep motif. + +The key is to create a state-based run() that can be exited and re-entered in JavaScript. + + +Static fields +------------- + +Final static primitive "constant" fields (String, boolean, int, etc.) such as + +static final int TEST = 3; +static final String MY_STRING = "my " + "string"; + +are converted to their primitive form automatically by the Eclipse Java compiler +and do not appear in the JavaScript by their names. + +Other static fields are properties of their class and can be used as expected. + +Note, however, that SwingJS runs all "Java" code on a page in a common "jvm" +(like older versions of Java). So, like the older Java schema, the JavaScript +equivalents of both applets and applications will share all of their static +fields and methods. This includes java.lang.System. + +Basically, SwingJS implementations of Java run in a browser page-based sandbox +instead of an applet-specific one. + +In general, this is no problem. But if we are to implement pages with +multiple applets present, we must be sure to only have static references +that are "final" or specifically meant to be shared in a JavaScript +environment only (since they will not be shared in Java). + +A simple solution, if static non-constant references are needed, is to attach the +field to Thread.currentThread.threadGroup(), which is an applet-specific reference. +Be sure, if you do this, that you use explicit setters and getters: + +For example, + +private static String myvar; + +... + +public void setMyVar(String x) { + ThreadGroup g = Thread.currentThread().threadGroup(); + /** + * @j2sNative g._myvar = x; + * + */ + { + myvar = x; + } +} + +public String getMyVar() { + ThreadGroup g = Thread.currentThread().threadGroup(); + /** + * @j2sNative return g._myvar || null; + * + */ + { + return myvar; + } +} + + in Java will get and set x the same in JavaScript and in Java. + + +A convenient way to do this in general is to supply a singleton class with +explicitly private-only constructors and then refer to it in Java and in JavaScript +instead of using static field, referring to myclass.getIntance().xxx instead of +myclass.xxx in Java (and JavaScript). + +This was done extensively in the Jalview project. See jalview.bin.Instance. + + +Helper Packages -- swingjs/ and javajs/ +--------------------------------------- + +The SwingJS library is the swingjs/ package. There are interfaces that may be of assistance +in swingjs/api, but other than that, it is not recommended that developers access classes in +this package. The "public" nature of their methods is really an internal necessity. + +In addition to swingjs/, though, there are several useful classes in the javajs/ package +that could be very useful. This package is a stand-alone package that can be +cloned in any Java project that also would be great to have in any JavaScript project +-- SwingJS-related or not. Functionality ranges from reading and writing various file +formats, including PDF, BMP, PNG, GIF, JPG, JSON, ZIP, and CompoundDocument formats. + +A variety of highly efficient three- and four-dimensional point, vector, matrix, and +quaternion classes are included, as they were developed for JSmol and inherited from that +project. + +Of particular interest should be javajs/async/, which includes + +javajs.async.Async +javajs.async.AsyncColorChooser +javajs.async.AsyncDialog +javajs.async.AsyncFileChooser + +See javajs.async.Async JavaDoc comments for a full description of +these useful classes. + + +Modal Dialogs +------------- + +Although true modal dialogs are not possible with only one thread, a functional equivalent -- +asynchronous modal dialogs -- is relatively easy to set up. All the JOptionPane dialogs will +return PropertyChangeEvents to signal that they have been disposed of and containing the results. +See below and classes in the javajs.async package. + + +Native calls +------------ + +Native calls in Java are calls to operating system methods that are not in Java. JavaScript +has no access to these, of course, and they must all be replaced by JavaScript equivalents. +Fortunately, they are not common, and those that are present in Java (for example, in calculating +checksums in ZIP file creation) are at a low enough level that most developers do not utilize them +or do not even have access to them. All native calls in Java classes have been replaced by +Java equivalents. + + +Swing GUI Peers and UIClasses +----------------------------- + +One of the biggest adaptations introduced in SwingJS is in the area of the graphical +user interface. The issue here is complex but workable. In Java there are two background +concepts -- the Component "peer" (one per "heavy-weight" component, such as a Frame) and the +component "uiClass" (one per component, such as JButton or JTextField). + +Peers are native objects of the operating system. These are the virtual buttons and text areas +that the user is interacting with at a very base level. Their events are being passed on to +Java or the browser by the operating system. UI classes provide a consistent "look and feel" +for these native objects, rendering them onto the native window canvas and handling all +user-generated events. They paint the borders, the backgrounds, the highlights, of every +control you see in Java. There is one-to-one correspondence of Swing classes and UI classes. +Setting the Look and Feel for a project amounts to selecting the directory from which to draw +these UI classes. The UI classes can be found in the javax.swing.plaf ("platform look and feel") +package. + +Early on in the development of SwingJS, we decided not to fully reproduce the painfully detailed +bit-by-bit painting of controls as is done in Java. Instead, we felt it was wiser to utilize the standard +HTML5 UI capabilities as much as possible, using DIV, and INPUT especially, with extensive use +of CSS and sometimes jQuery (menus, and sliders, for example). Thus, we have created a new +set of UIs -- the "HTML5 Look and Feel". These classes can be found in swingjs.plaf. Besides being +more adaptable, this approach allows far more versatility to SwingJS developers, allowing them +to modify the GUI to suit their needs if desired. + +In SwingJS, since we have no access to native peers except through the browser DOM, +it seemed logical to merge the peer and UI idea. So instead of having one peer per heavy-weight control and +one UI class instance for each control type, we just have one UI class instance per control, and +that UI class instance is what is being referred to when a "peer" is notified. + +In some ways this is a throw back to when all of Swing's components were subclasses of +specific AWT components such as Button and List. These "heavy-weight components" all had their +own individual native peers and thus automatically took on the look and feel provided by the OS. +Later Swing versions implemented full look and feel for all peers, leaving only JDialog, JFrame, +and a few other classes to have native peers. But in SwingJS we have again a 1:1 map of component +and UI class/peer instance. + +The origin of most issues (read "bugs") in relation to the GUI will probably be found in the +swingjs.plaf JSxxxxUI.java code. + + +Swing-only Components -- no longer an issue +------------------------------------------- + +Swing was introduced into Java well after the Java Abstract Window Toolkit (AWT) was well +established. As such, its designers chose to allow AWT controls such as Button and List to be used +alongside their Swing counterparts JButton and JList. Reading the code, it is clear that this +design choice posed a huge headache for Swing class developers. + +For SwingJS, we decided from the beginning NOT to allow this mixed-mode programming and +instead to require that all components be Swing components. + +However, this is no longer an issue. All AWT components in SwingJS are now subclasses of +javax.swing.JComponent. So far, we have found no problem with this. + + +The a2s Adapter Package +----------------------- + +Originally, we thought that we would restrict ourselves to JApplets only. That is, only +Swing-based applets. But as we worked, we discovered that there are a lot of great +applets out there that are pre-Swing pure-AWT java.applet.Applet applets. Our problem was +that we also wanted it to be possible to quickly adapt these applets to JavaScript as well. + +The solution turned out to be simple: Write a package (a2s) that recreates the interface for +non-Swing components as subclasses of Swing components. Thus, a2s.Button subclasses javax.swing.JButton +but also accepts all of the methods of java.awt.Button. This works amazingly well, with a few +special adaptations to the core javax.swing to be "AWT-aware." All AWT components now subclass +a2s components, which in turn subclass JComponents. So no changes in code are necessary. We have +successfully transpiled over 500 applets using this strategy. (Kind of surprising, actually, that +the original Java developers did not see that option. But we have a hindsight advantage here.) + + +Working with Files +================== + +Simple String file names are not optimal for passing information about +read files within SwingJS applications. + +All work with files should either use Path or File objects exclusively. +These objects, after a file is read or checked for existence, will already +contain the file byte[] data. Doing something like this: + +File f = File("./test.dat"); +boolean isOK = f.exists(); + +will load f with its byte[] data, if the file exists. + +But if after that, we use: + +File f2 = new File(f.getAbsolutePath()); + +f2 will not contain that data. Such copying should be done as: + +File f2 = new File(f); + +in which case, the byte[] data will be transferred. + + +SwingJS uses the following criteria to determine if File.exists() returns true: + +(1) if this File object has been used directly to read data, or +(2) if reading data using this File object is successful. + +Note that you cannot check to see if a file exists before input or if it +was actually written or if it already exists prior to writing in SwingJS. + +Thus, you should check each use of file.exists() carefully, and if necessary, provide a J2sNative +block that gives an appropriate "OK" message, for example: + +(/** @j2sNative 1 ? false : */ outputfile.exits()) + +or + +(/** @j2sNative 1 ? true : */ inputfile.exits()) + +Temporary files can be created in SwingJS. SwingJS will maintain a pseudo-filesystem for files +created with File.createTempFile(). This is useful in that closure of writing to a temporary file +does not generate a pseudo-download to the user's machine. + + +UNIMPLEMENTED CLASSES BY DESIGN +=============================== + +The SwingJS implementation of the following classes are present +in a way that gracefully bypasses their functionality: + +accessibility +security +serialization + + + +TODO LIST FOR UNIMPLEMENTED CLASSES +=================================== + +JEditorPane (minimal implementation) - DONE 12/2018; some issues still +JSplitPane - DONE 8/2018 +JTabbedPane - DONE 10/2018 +JTree - done 12/2019 + + +MINOR ISSUES--required some rewriting/refactoring by Bob and Udo +================================================================ + +Thread.currentThread() == dispatchThread + + +MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS +===================================================================== + +See below for a full discussion. + +HashMap, Hashtable, and HashSet iterator ordering +interning, new String("xxx") vs "xxx" +Names with "$" and "_" +positive integers do not add to give negative numbers +ArrayIndexOutOfBounds +java.awt.Color +native methods +javax.swing.JFileDialog +key focus +LookAndFeel and UI Classes +System.exit(0) does not stop all processes +list cell renderers must be JComponents +myClass.getField not implemented +"window" and other reserved JavaScript names +reserved field and method names +qualified field and method names +missing Math methods +Component.getGraphics(), Graphics.dispose() +Graphics.setClip() + +MAJOR ISSUES--for Bob and Udo within SwingJS +============================================ + +fonts +OS-dependent classes +AWT component peers +some aspects of reflection + +MAJOR ISSUES--to be resolved by implementers +============================================ + +fonts +threads +modal dialogs +image loading +BigDecimal not fully implemented +no format internationalization +no winding rules +text-related field implementation +Formatter/Regex limitations +integer 1/0 == Infinity + +======================================================================== + +DISCUSS +======= + +Table row/col sorter needs checking after removal of java.text.Collator references + +I had to move all of SunHints class to RenderingHints, or the +two classes could not be loaded. Shouldn't be a problem, I think. The sun classes are +not accessible to developers in Java anyway, since they are generally package private. + +========================================================================== + +////////////////////////////////////////////////////////////////////////////// + +UNIMPLEMENTED CLASSES +===================== + +accessibility +------------- + +All Accessibility handling has been commented out to save the download footprint. +This removes the need for sun.misc.SharedSecrets as well. +Nothing says we could not implement accessibility. We just didn't. + + +security +-------- + +All JavaScript security is handled by the browser natively. +Thus, Java security checking is no longer necessary, and +java.security.AccessController has been simplified to work without +native security checking. + +Note that private methods in a class are REALLY private. + + +serialization +------------- + +All serialization has been removed. It was never very useful for Swing anyway, +because one needs exactly the same Java version to save and restore serialized objects. + + +keyboard accelerators and mnemonics +----------------------------------- + +This work was completed in the spring of 2019. Note that in a browser, some +key strokes, particularly CTRL-keys, are not available. Bummer. + + +MINOR ISSUES--required some rewriting/refactoring by Bob and Udo +================================================================ + + +Thread.currentThread() == dispatchThread +---------------------------------------- + +changed to JSToolkit.isDispatchThread() + + +MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS +===================================================================== + +HashMap, Hashtable, and HashSet iterator ordering +------------------------------------------------- + +In Java, iterators for HashMap, Hashtable, and HashSet do not guarantee any particular order. +From the HashMap documentation for Java 8: + + This class makes no guarantees as to the order of the map; in particular, it does not + guarantee that the order will remain constant over time. + +Likewise, for HashSet (because it is simply a convenience method for HashMap