diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..4824b8026 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/old/sources/net.sf.j2s/.settings/org.eclipse.core.resources.prefs b/old/sources/net.sf.j2s/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..4824b8026 --- /dev/null +++ b/old/sources/net.sf.j2s/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/sources/net.sf.j2s.core/.classpath b/sources/net.sf.j2s.core/.classpath index 021596729..64ed6b379 100644 --- a/sources/net.sf.j2s.core/.classpath +++ b/sources/net.sf.j2s.core/.classpath @@ -1,7 +1,7 @@ - + diff --git a/sources/net.sf.j2s.core/.settings/org.eclipse.jdt.core.prefs b/sources/net.sf.j2s.core/.settings/org.eclipse.jdt.core.prefs index e1ebc4e85..518636fda 100644 --- a/sources/net.sf.j2s.core/.settings/org.eclipse.jdt.core.prefs +++ b/sources/net.sf.j2s.core/.settings/org.eclipse.jdt.core.prefs @@ -8,17 +8,8 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.APILeak=warning org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=warning org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning org.eclipse.jdt.core.compiler.problem.deadCode=warning @@ -27,7 +18,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled @@ -72,6 +63,7 @@ org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=igno org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled @@ -108,5 +100,3 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip index 53a881f5d..ec81fff01 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/_j2sclasslist.txt b/sources/net.sf.j2s.core/dist/swingjs/_j2sclasslist.txt index 6190ec887..b91ce26be 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/_j2sclasslist.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/_j2sclasslist.txt @@ -350,6 +350,7 @@ swingjs/a2s/ScrollPane.js swingjs/a2s/TextArea.js swingjs/a2s/TextField.js swingjs/api/Interface.js +swingjs/api/JSUtilI.js swingjs/api/js/DOMNode.js swingjs/api/js/HTML5CanvasContext2D.js swingjs/api/js/JSInterface.js diff --git a/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core-j11.jar b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core-j11.jar new file mode 100644 index 000000000..303fea511 Binary files /dev/null and b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core-j11.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar index e469030a7..dd5b90436 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar and b/sources/net.sf.j2s.core/dist/swingjs/net.sf.j2s.core.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/timestamp b/sources/net.sf.j2s.core/dist/swingjs/timestamp index 2d695572c..f3fc744f2 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/timestamp @@ -1 +1 @@ -20200315182226 +20200321085805 diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/DEV_NOTES.txt b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/DEV_NOTES.txt new file mode 100644 index 000000000..ffbc7bf86 --- /dev/null +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/DEV_NOTES.txt @@ -0,0 +1,10 @@ +This is sources/net.sf.j2s.java.core/dist/DEV_NOTES.txt + +_j2sclasslist.txt + +the list of .js files concatenated into coreswingjs.js and minified to coreswingjs.z.js + + +SwingJS-site.zip + +the full site directory for SwingJS including all files not in the test/ directory. diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/SwingJS-site.zip new file mode 100644 index 000000000..f644a9fe5 Binary files /dev/null and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/_j2sclasslist.txt b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/_j2sclasslist.txt new file mode 100644 index 000000000..6190ec887 --- /dev/null +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/_j2sclasslist.txt @@ -0,0 +1,412 @@ +java/applet/Applet.js +java/applet/AppletContext.js +java/applet/AppletStub.js +java/applet/JSApplet.js +java/awt/ActiveEvent.js +java/awt/Adjustable.js +java/awt/AWTEvent.js +java/awt/AWTEventMulticaster.js +java/awt/AWTKeyStroke.js +java/awt/BasicStroke.js +java/awt/BorderLayout.js +java/awt/Button.js +java/awt/Color.js +java/awt/color/ColorSpace.js +java/awt/Component.js +java/awt/ComponentOrientation.js +java/awt/ContainerOrderFocusTraversalPolicy.js +java/awt/Container.js +java/awt/Cursor.js +java/awt/DefaultFocusTraversalPolicy.js +java/awt/DefaultKeyboardFocusManager.js +java/awt/Dialog.js +java/awt/Dimension.js +java/awt/dnd/peer/DropTargetPeer.js +java/awt/event/ActionListener.js +java/awt/event/AdjustmentEvent.js +java/awt/event/AdjustmentListener.js +java/awt/event/AWTEventListener.js +java/awt/event/ComponentAdapter.js +java/awt/event/ComponentEvent.js +java/awt/event/ComponentListener.js +java/awt/event/ContainerListener.js +java/awt/event/FocusEvent.js +java/awt/event/FocusListener.js +java/awt/event/HierarchyBoundsListener.js +java/awt/event/HierarchyListener.js +java/awt/event/InputEvent.js +java/awt/event/InputMethodListener.js +java/awt/event/InvocationEvent.js +java/awt/event/ItemEvent.js +java/awt/event/ItemListener.js +java/awt/event/KeyListener.js +java/awt/event/MouseEvent.js +java/awt/event/MouseListener.js +java/awt/event/MouseMotionListener.js +java/awt/event/MouseWheelListener.js +java/awt/event/TextListener.js +java/awt/event/WindowAdapter.js +java/awt/event/WindowEvent.js +java/awt/event/WindowFocusListener.js +java/awt/event/WindowListener.js +java/awt/event/WindowStateListener.js +java/awt/EventDispatchThread.js +java/awt/EventFilter.js +java/awt/EventQueue.js +java/awt/EventQueueItem.js +java/awt/FlowLayout.js +java/awt/FocusTraversalPolicy.js +java/awt/Font.js +java/awt/font/FontRenderContext.js +java/awt/FontMetrics.js +java/awt/Frame.js +java/awt/geom/AffineTransform.js +java/awt/geom/Dimension2D.js +java/awt/geom/Path2D.js +java/awt/geom/PathIterator.js +java/awt/geom/Point2D.js +java/awt/geom/Rectangle2D.js +java/awt/geom/RectangularShape.js +java/awt/geom/RectIterator.js +java/awt/GraphicsCallback.js +java/awt/GraphicsConfiguration.js +java/awt/GraphicsDevice.js +java/awt/GraphicsEnvironment.js +java/awt/Image.js +java/awt/image/ImageObserver.js +java/awt/Insets.js +java/awt/ItemSelectable.js +java/awt/JSComponent.js +java/awt/JSDialog.js +java/awt/JSFrame.js +java/awt/JSPanel.js +java/awt/KeyboardFocusManager.js +java/awt/KeyEventDispatcher.js +java/awt/KeyEventPostProcessor.js +java/awt/Label.js +java/awt/LayoutManager.js +java/awt/LayoutManager2.js +java/awt/LightweightDispatcher.js +java/awt/Paint.js +java/awt/Panel.js +java/awt/peer/ComponentPeer.js +java/awt/peer/ContainerPeer.js +java/awt/peer/FramePeer.js +java/awt/peer/KeyboardFocusManagerPeer.js +java/awt/peer/LightweightPeer.js +java/awt/peer/WindowPeer.js +java/awt/Point.js +java/awt/Queue.js +java/awt/Rectangle.js +java/awt/RenderingHints.js +java/awt/Scrollbar.js +java/awt/ScrollPane.js +java/awt/Shape.js +java/awt/Stroke.js +java/awt/TextArea.js +java/awt/TextComponent.js +java/awt/TextField.js +java/awt/Toolkit.js +java/awt/Transparency.js +java/awt/Window.js +java/beans/ChangeListenerMap.js +java/beans/PropertyChangeEvent.js +java/beans/PropertyChangeListener.js +java/beans/PropertyChangeSupport.js +java/lang/AbstractStringBuilder.js +java/lang/Class.js +java/lang/Enum.js +java/lang/Iterable.js +java/lang/reflect/Constructor.js +java/lang/reflect/Method.js +java/lang/StringBuffer.js +java/lang/StringBuilder.js +java/lang/Thread.js +java/lang/ThreadGroup.js +java/math/RoundingMode.js +java/net/URL.js +java/net/URLStreamHandlerFactory.js +java/net/HttpURLConnection.js +java/net/URLStreamHandler.js +javax/net/ssl/HttpsUrlConnection.js +java/text/CharacterIterator.js +java/text/DecimalFormat.js +java/text/DecimalFormatSymbols.js +java/text/DigitList.js +java/text/FieldPosition.js +java/text/Format.js +java/text/NumberFormat.js +java/util/AbstractCollection.js +java/util/AbstractList.js +java/util/AbstractMap.js +java/util/AbstractSequentialList.js +java/util/AbstractSet.js +java/util/ArrayList.js +java/util/Arrays.js +java/util/Collection.js +java/util/Collections.js +java/util/Comparator.js +java/util/Deque.js +java/util/Dictionary.js +java/util/Enumeration.js +java/util/EventListener.js +java/util/EventObject.js +java/util/HashMap.js +java/util/HashSet.js +java/util/Hashtable.js +java/util/IdentityHashMap.js +java/util/Iterator.js +java/util/LinkedHashMap.js +java/util/LinkedList.js +java/util/List.js +java/util/ListResourceBundle.js +java/util/Locale.js +java/util/Map.js +java/util/Objects.js +java/util/Queue.js +java/util/Random.js +java/util/RandomAccess.js +java/util/ResourceBundle.js +java/util/Set.js +java/util/TimSort.js +java/util/Vector.js +javajs/api/JSFunction.js +javajs/util/AjaxURLConnection.js +javajs/util/AjaxURLStreamHandlerFactory.js +javajs/util/AU.js +javajs/util/JSThread.js +javajs/util/Lst.js +javajs/util/PT.js +javajs/util/Rdr.js +javajs/util/SB.js +javax/swing/AbstractAction.js +javax/swing/AbstractButton.js +javax/swing/AbstractListModel.js +javax/swing/Action.js +javax/swing/ActionMap.js +javax/swing/AncestorNotifier.js +javax/swing/ArrayTable.js +javax/swing/border/AbstractBorder.js +javax/swing/border/BevelBorder.js +javax/swing/border/Border.js +javax/swing/border/CompoundBorder.js +javax/swing/border/EmptyBorder.js +javax/swing/border/EtchedBorder.js +javax/swing/border/LineBorder.js +javax/swing/border/TitledBorder.js +javax/swing/BorderFactory.js +javax/swing/BoundedRangeModel.js +javax/swing/BoxLayout.js +javax/swing/ButtonGroup.js +javax/swing/ButtonModel.js +javax/swing/ClientPropertyKey.js +javax/swing/ComboBoxModel.js +javax/swing/DefaultBoundedRangeModel.js +javax/swing/DefaultButtonModel.js +javax/swing/DefaultComboBoxModel.js +javax/swing/DefaultSingleSelectionModel.js +javax/swing/DropMode.js +javax/swing/event/AncestorEvent.js +javax/swing/event/AncestorListener.js +javax/swing/event/CaretEvent.js +javax/swing/event/CaretListener.js +javax/swing/event/ChangeEvent.js +javax/swing/event/ChangeListener.js +javax/swing/event/DocumentEvent.js +javax/swing/event/DocumentListener.js +javax/swing/event/EventListenerList.js +javax/swing/event/ListDataEvent.js +javax/swing/event/ListDataListener.js +javax/swing/event/UndoableEditEvent.js +javax/swing/event/UndoableEditListener.js +javax/swing/FocusManager.js +javax/swing/InternalFrameFocusTraversalPolicy.js +javax/swing/LayoutComparator.js +javax/swing/LayoutFocusTraversalPolicy.js +javax/swing/SortingFocusTraversalPolicy.js +javax/swing/SwingContainerOrderFocusTraversalPolicy.js +javax/swing/SwingDefaultFocusTraversalPolicy.js +javax/swing/Icon.js +javax/swing/ImageIcon.js +javax/swing/InputMap.js +javax/swing/JApplet.js +javax/swing/JButton.js +javax/swing/JCheckBox.js +javax/swing/JCheckBoxMenuItem.js +javax/swing/JComboBox.js +javax/swing/JComponent.js +javax/swing/JFrame.js +javax/swing/JLabel.js +javax/swing/JLayeredPane.js +javax/swing/JMenu.js +javax/swing/JMenuBar.js +javax/swing/JMenuItem.js +javax/swing/JPanel.js +javax/swing/JPopupMenu.js +javax/swing/JRadioButtonMenuItem.js +javax/swing/JRootPane.js +javax/swing/JScrollBar.js +javax/swing/JScrollPane.js +javax/swing/JSeparator.js +javax/swing/JTextArea.js +javax/swing/JTextField.js +javax/swing/JToggleButton.js +javax/swing/JViewport.js +javax/swing/KeyboardManager.js +javax/swing/KeyStroke.js +javax/swing/ListModel.js +javax/swing/LookAndFeel.js +javax/swing/MenuElement.js +javax/swing/MutableComboBoxModel.js +javax/swing/plaf/ActionMapUIResource.js +javax/swing/plaf/basic/BasicBorders.js +javax/swing/plaf/BorderUIResource.js +javax/swing/plaf/ColorUIResource.js +javax/swing/plaf/ComponentUI.js +javax/swing/plaf/DimensionUIResource.js +javax/swing/plaf/FontUIResource.js +javax/swing/plaf/InputMapUIResource.js +javax/swing/plaf/InsetsUIResource.js +javax/swing/plaf/UIResource.js +javax/swing/RepaintManager.js +javax/swing/RootPaneContainer.js +javax/swing/Scrollable.js +javax/swing/ScrollPaneConstants.js +javax/swing/ScrollPaneLayout.js +javax/swing/SingleSelectionModel.js +javax/swing/SizeRequirements.js +javax/swing/SwingConstants.js +javax/swing/SwingPaintEventDispatcher.js +javax/swing/SwingUtilities.js +javax/swing/text/AbstractDocument.js +javax/swing/text/AttributeSet.js +javax/swing/text/Caret.js +javax/swing/text/DefaultCaret.js +javax/swing/text/DefaultEditorKit.js +javax/swing/text/Document.js +javax/swing/text/EditorKit.js +javax/swing/text/Element.js +javax/swing/text/GapContent.js +javax/swing/text/GapVector.js +javax/swing/text/JTextComponent.js +javax/swing/text/MutableAttributeSet.js +javax/swing/text/PlainDocument.js +javax/swing/text/PlainView.js +javax/swing/text/Position.js +javax/swing/text/Segment.js +javax/swing/text/SegmentCache.js +javax/swing/text/SimpleAttributeSet.js +javax/swing/text/Style.js +javax/swing/text/StyleConstants.js +javax/swing/text/StyleContext.js +javax/swing/text/TabExpander.js +javax/swing/text/TextAction.js +javax/swing/text/Utilities.js +javax/swing/text/View.js +javax/swing/tree/TreeNode.js +javax/swing/UIDefaults.js +javax/swing/UIManager.js +javax/swing/undo/AbstractUndoableEdit.js +javax/swing/undo/CompoundEdit.js +javax/swing/undo/UndoableEdit.js +javax/swing/ViewportLayout.js +javax/swing/WindowConstants.js +sun/awt/AppContext.js +sun/awt/AWTAutoShutdown.js +sun/awt/CausedFocusEvent.js +sun/awt/ComponentFactory.js +sun/awt/KeyboardFocusManagerPeerProvider.js +sun/awt/MostRecentKeyValue.js +sun/awt/MostRecentThreadAppContext.js +sun/awt/PaintEventDispatcher.js +sun/awt/PostEventQueue.js +sun/awt/RequestFocusController.js +sun/awt/SunToolkit.js +sun/awt/WindowClosingListener.js +sun/awt/WindowClosingSupport.js +sun/awt/image/DataStealer.js +sun/awt/image/IntegerComponentRaster.js +sun/awt/image/IntegerInterleavedRaster.js +sun/awt/image/SunWritableRaster.js +sun/font/FontDesignMetrics.js +sun/swing/DefaultLookup.js +sun/swing/SwingLazyValue.js +sun/text/resources/FormatData.js +sun/text/resources/en/FormatData_en.js +sun/util/resources/LocaleData.js +sun/util/locale/BaseLocale.js +sun/util/locale/LocaleUtils.js +sun/util/locale/provider/LocaleProviderAdapter.js +sun/util/locale/provider/LocaleDataMetaInfo.js +swingjs/a2s/A2SContainer.js +swingjs/a2s/A2SEvent.js +swingjs/a2s/A2SListener.js +swingjs/a2s/Applet.js +swingjs/a2s/Button.js +swingjs/a2s/Label.js +swingjs/a2s/Panel.js +swingjs/a2s/Scrollbar.js +swingjs/a2s/ScrollPane.js +swingjs/a2s/TextArea.js +swingjs/a2s/TextField.js +swingjs/api/Interface.js +swingjs/api/js/DOMNode.js +swingjs/api/js/HTML5CanvasContext2D.js +swingjs/api/js/JSInterface.js +swingjs/jquery/JQueryUI.js +swingjs/JSApp.js +swingjs/JSAppletThread.js +swingjs/JSAppletViewer.js +swingjs/JSFocusPeer.js +swingjs/JSFontMetrics.js +swingjs/JSFrameViewer.js +swingjs/JSGraphics2D.js +swingjs/JSGraphicsConfiguration.js +swingjs/JSGraphicsEnvironment.js +swingjs/JSImage.js +swingjs/JSImagekit.js +swingjs/JSMouse.js +swingjs/JSNullComponentPeer.js +swingjs/JSScreenDevice.js +swingjs/JSThreadGroup.js +swingjs/JSToolkit.js +swingjs/JSUtil.js +swingjs/plaf/ButtonListener.js +swingjs/plaf/DefaultMenuLayout.js +swingjs/plaf/HTML5LookAndFeel.js +swingjs/plaf/JSAppletUI.js +swingjs/plaf/JSButtonUI.js +swingjs/plaf/JSCheckBoxMenuItemUI.js +swingjs/plaf/JSCheckBoxUI.js +swingjs/plaf/JSComboBoxUI.js +swingjs/plaf/JSComponentUI.js +swingjs/plaf/JSEventHandler.js +swingjs/plaf/JSFrameUI.js +swingjs/plaf/JSGraphicsUtils.js +swingjs/plaf/JSLabelUI.js +swingjs/plaf/JSLayeredPaneUI.js +swingjs/plaf/JSLightweightUI.js +swingjs/plaf/JSMenuBarUI.js +swingjs/plaf/JSMenuItemUI.js +swingjs/plaf/JSMenuUI.js +swingjs/plaf/JSPanelUI.js +swingjs/plaf/JSPopupMenuSeparatorUI.js +swingjs/plaf/JSPopupMenuUI.js +swingjs/plaf/JSRadioButtonMenuItemUI.js +swingjs/plaf/JSRadioButtonUI.js +swingjs/plaf/JSRootPaneUI.js +swingjs/plaf/JSScrollBarUI.js +swingjs/plaf/JSScrollPaneUI.js +swingjs/plaf/JSSeparatorUI.js +swingjs/plaf/JSSliderUI.js +swingjs/plaf/JSTextAreaUI.js +swingjs/plaf/JSTextFieldUI.js +swingjs/plaf/JSTextUI.js +swingjs/plaf/JSTextViewUI.js +swingjs/plaf/JSViewportUI.js +swingjs/plaf/JSWindowUI.js +swingjs/plaf/LazyActionMap.js +swingjs/plaf/Resizer.js +swingjs/plaf/TextListener.js + + diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/net.sf.j2s.core.jar b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/net.sf.j2s.core.jar new file mode 100644 index 000000000..2a1593d56 Binary files /dev/null and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/net.sf.j2s.core.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/timestamp b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/timestamp new file mode 100644 index 000000000..743ed1ed3 --- /dev/null +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9-j11/timestamp @@ -0,0 +1 @@ +20200317182149 diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip index 53a881f5d..ec81fff01 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/_j2sclasslist.txt b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/_j2sclasslist.txt index 6190ec887..b91ce26be 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/_j2sclasslist.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/_j2sclasslist.txt @@ -350,6 +350,7 @@ swingjs/a2s/ScrollPane.js swingjs/a2s/TextArea.js swingjs/a2s/TextField.js swingjs/api/Interface.js +swingjs/api/JSUtilI.js swingjs/api/js/DOMNode.js swingjs/api/js/HTML5CanvasContext2D.js swingjs/api/js/JSInterface.js diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core-j11.jar b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core-j11.jar new file mode 100644 index 000000000..303fea511 Binary files /dev/null and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core-j11.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar index e469030a7..dd5b90436 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/net.sf.j2s.core.jar differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp index 2d695572c..f3fc744f2 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/timestamp @@ -1 +1 @@ -20200315182226 +20200321085805 diff --git a/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java b/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java index ffd0d8525..9b2af887e 100644 --- a/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java +++ b/sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java @@ -30,6 +30,9 @@ public class CorePlugin extends Plugin { // if you change the x.x.x number, be sure to also indicate that in // j2sApplet.js and also (Bob only) update.bat, update-clean.bat + // BH 2020.03.21 -- 3.2.9-v1e better v1c + // BH 2020.03.20 -- 3.2.9-v1d proper check for new String("x") == "x" (should be false), but new integer(3) == 3 (true) + // BH 2020.03.20 -- 3.2.9-v1c more efficient static call from 3.2.9-v1a // BH 2020.02.26 -- 3.2.9-v1b allows (byte) = (byte) to not use |0 // BH 2020.02.20 -- 3.2.9-v1a reverses c,args order in new_(c,args,...) when both have expressions // BH 2020.02.18 -- 3.2.8-v2 fixes import static missing $I$ defs. diff --git a/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java b/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java index a468f524d..d576f0f5a 100644 --- a/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java +++ b/sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java @@ -135,6 +135,9 @@ // TODO: superclass inheritance for JAXB XmlAccessorType +//BH 2020.03.21 -- 3.2.9-v1e better v1c +//BH 2020.03.20 -- 3.2.9-v1d proper check for new String("x") == "x" (should be false), but new integer(3) == 3 (true) +//BH 2020.03.20 -- 3.2.9-v1c more efficient static call from 3.2.9-v1a //BH 2020.02.26 -- 3.2.9-v1b allows (byte) = (byte) to not use |0 //BH 2020.02.20 -- 3.2.9-v1a order of 1st two parameters in new_ should be reversed //BH 2020.02.18 -- 3.2.8-v2 fixes no-argument call to varargs constructor @@ -344,7 +347,7 @@ public class Java2ScriptVisitor extends ASTVisitor { // private static Map>> syntheticClassMethodNameMap = new HashMap>>(); // private static Map> genericClassTypes = new HashMap>(); - private static Map htStrLitCache = new Hashtable<>(); + private static Map htStringLiteralCache = new Hashtable<>(); /** * includes @j2sDebug blocks; from j2s.compiler.mode=debug in .j2s @@ -368,7 +371,7 @@ public static void setAnnotating(String ignoredAnnotations) { } static void startCleanBuild() { - htStrLitCache = new Hashtable<>(); + htStringLiteralCache = new Hashtable<>(); } /** @@ -466,6 +469,7 @@ private Java2ScriptVisitor setInnerGlobals(Java2ScriptVisitor parent, ASTNode no package_htIncludeNames = parent.package_htIncludeNames; package_includeCount = parent.package_includeCount; package_includes = parent.package_includes; + package_haveStaticArgsReversal = parent.package_haveStaticArgsReversal; package_mapBlockJavadoc = parent.package_mapBlockJavadoc; // final and effectively final references @@ -633,6 +637,15 @@ int getPrimitiveDefaultType(Code code) { private ArrayList applets, apps; + private boolean isUserApplet; + + private int class_localType = NOT_LOCAL; + + /** + * flag to indicate that we need the $I$(i,n,m) definition. + */ + private boolean[] package_haveStaticArgsReversal = new boolean[] {false}; + private void addApplication() { if (apps == null) apps = new ArrayList(); @@ -663,10 +676,6 @@ public ArrayList getAppList(boolean isApplets) { return (isApplets ? applets : apps); } - private boolean isUserApplet; - - private int class_localType = NOT_LOCAL; - public boolean visit(CompilationUnit node) { resetPrivateVars(); return true; @@ -846,22 +855,22 @@ private void addConstructor(ITypeBinding javaClass, IMethodBinding constructorMethodDeclaration = (constructorMethodBinding == null ? null : constructorMethodBinding.getMethodDeclaration()); addMethodParameterList(arguments, constructorMethodDeclaration, prefix, postfix, METHOD_CONSTRUCTOR); - checkStaticParams(pt, pt1, true); + checkStaticParams2(pt, pt1, true); } buffer.append(")"); } /** - * 3.2.9.v1 + * 3.2.9.v1a * * Static method invocations must process parameters before initializing the method's class * if any parameter either calls a method or defines a static variable. We do this by changing * - * $I(3).xxxx(x,y,z) + * $I$(3).xxxx(x,y,z) * * to * - * (function(a,b){b.apply(null,a)})([x,y,z],$I(3).xxxx) + * (function(a,b){b.apply(null,a)})([x,y,z],$I$(3).xxxx) * * In addition, for constructors, Clazz.new_ needs to have the parameters as the first * parameter and the constructor method as the second parameter: @@ -875,10 +884,10 @@ private void addConstructor(ITypeBinding javaClass, */ private void checkStaticParams(int pt, int pt1, boolean isConstructor) { String args; - // must switch from Clazz.new_($I(3).xxxx,[x,y,z] to Clazz.new([x,y,z],$I(3).xxxx - // ............................^pt.......^pt1 - // must switch from $I(3).xxxx(x,y,z to (function(a,f){return f.apply(null,a)})([x,y,z],$I(3).xxxx - // .................^pt.......^pt1 + // must switch from Clazz.new_($I$(3).xxxx,[x,y,z] to Clazz.new([x,y,z],$I$(3).xxxx + // ............................^pt........^pt1 + // must switch from $I$(3).xxxx(x,y,z to (function(a,f){return f.apply(null,a)})([x,y,z],$I$(3).xxxx + // .................^pt........^pt1 if (pt1 == pt || buffer.charAt(pt) != '$' || (args = buffer.substring(pt1 + 1)).indexOf("(") < 0 && args.indexOf("=") < 0) @@ -891,6 +900,53 @@ private void checkStaticParams(int pt, int pt1, boolean isConstructor) { buffer.append(args).append(",").append(f); } + + /** + * 3.2.9.v1c + * + * Static method invocations must process parameters before initializing the method's class + * if any parameter either calls a method or defines a static variable. We do this by changing + * + * $I$(3).xxxx(x,y,z) + * + * to + * + * $I$(3,"xxxx",[x,y,z]) + * + * In addition, for constructors, Clazz.new_ needs to have the parameters as the first + * parameter and the constructor method as the second parameter: + * + * Clazz.new_([args],constr) + * + * The method invocation has not been closed at this point. + * + * @param pt start of method name + * @param pt1 end of method name + */ + private void checkStaticParams2(int pt, int pt1, boolean isConstructor) { + String args; + // must switch from Clazz.new_($I$(3).xxxx,[x,y,z] to Clazz.new([x,y,z],$I$(3).xxxx + // ............................^pt........^pt1 + // must switch from $I$(3).xxxx(x,y,z to $I$(3,"xxxx",[x,y,z]) + // .................fffffffffff + // .................^pt..^fpt..^pt1 + if (pt1 == pt + || buffer.charAt(pt) != '$' + || (args = buffer.substring(pt1 + 1)).indexOf("(") < 0 && args.indexOf("=") < 0) + return; + String f = buffer.substring(pt, pt1); + buffer.setLength(pt); + if (isConstructor) { + buffer.append(args).append(",").append(f); + } else { + package_haveStaticArgsReversal[0] = true; + int fpt = f.indexOf(")"); + buffer.append(f.substring(0, fpt)) + .append(",\"").append(f.substring(fpt+2)).append("\",[") + .append(args).append("]"); + } + } + /** * Start a new Clazz.new_(cl,[args],innerClass) call for class creation or inner classes * and adds the construtor reference. @@ -1592,7 +1648,7 @@ private boolean addMethodInvocation(SimpleName javaQualifier, List arguments, buffer.append("("); addMethodParameterList(arguments, mBinding, null, null, isIndexOf ? METHOD_INDEXOF : METHOD_NOTSPECIAL); if (isStatic && lambdaArity < 0 && term == ")") { - checkStaticParams(pt, pt1, false); + checkStaticParams2(pt, pt1, false); } buffer.append(term); return true; @@ -2726,6 +2782,9 @@ private boolean addFieldDeclaration(FieldDeclaration field, boolean isStatic) { VariableDeclarationFragment fragment = (VariableDeclarationFragment) iter.next(); Expression initializer = fragment.getInitializer(); IVariableBinding fbinding = fragment.resolveBinding(); + if (fbinding == null) { + System.out.println(">>> null binding for fragment in " + field); + } String name = getFinalFieldName(fbinding); if (initializer != null) { if (checkFinalConstant && getConstantValue(initializer, false)) @@ -2786,7 +2845,7 @@ private void addInnerTypeInstance(ASTNode node, ITypeBinding binding, ITypeBindi METHOD_CONSTRUCTOR); } buffer.append("]"); - checkStaticParams(pt, pt1, true); + checkStaticParams2(pt, pt1, true); // an anonymous class will be calling a constructor in another // class, so we need to indicate its actual call explicitly with a third parameter @@ -3202,7 +3261,7 @@ public boolean visit(Assignment node) { } } else { // just add the right operand - addOperandWithDoc(right, leftIsString); + addOperandWithJ2SDoc(right, leftIsString); } if (needNewStaticParenthesis) { buffer.append(")"); @@ -3507,6 +3566,7 @@ public boolean visit(InfixExpression node) { boolean isToString = (expTypeName.indexOf("String") >= 0); String operator = node.getOperator().toString(); + boolean isBitwise = isBitwiseBinaryOperator(node); boolean isComparison = (!isBitwise && "!==<=>=".indexOf(operator) >= 0); ITypeBinding leftTypeBinding = left.resolveTypeBinding(); @@ -3534,9 +3594,14 @@ public boolean visit(InfixExpression node) { post = ')'; buffer.append("!!("); } - + boolean isDirect = isBitwise && !toBoolean && leftIsInt && rightIsInt; - if (isDirect || isComparison) { + // string literal comparison check in 3.2.9.v1d + boolean isStringComparison = (isComparison + && !(left instanceof NullLiteral) && !(right instanceof NullLiteral) + && isInternOrLiteral(left) != isInternOrLiteral(right) + ); + if (isDirect || isComparison && !isStringComparison) { // we do not have to do a full conversion // possibilities include @@ -3584,7 +3649,7 @@ public boolean visit(InfixExpression node) { // left - addOperandWithDoc(left, isToString && !isBitwise); + addOperandWithJ2SDoc(left, isToString && !isBitwise); buffer.append(' '); // op buffer.append(operator); @@ -3594,7 +3659,12 @@ public boolean visit(InfixExpression node) { } buffer.append(' '); // right - if (right instanceof ParenthesizedExpression || getJ2sJavadoc(right, DOC_CHECK_ONLY) != null) { + boolean parenthesize = ( + //isStringComparison || + right instanceof ParenthesizedExpression || getJ2sJavadoc(right, DOC_CHECK_ONLY) != null); +// if (isStringComparison) +// buffer.append("new String"); + if (parenthesize) { buffer.append("("); addJ2SDoc(right); if (right instanceof ParenthesizedExpression) @@ -3620,7 +3690,11 @@ public boolean visit(InfixExpression node) { return false; } - private void addOperandWithDoc(Expression exp, boolean toString) { + private boolean isInternOrLiteral(Expression e) { + return e instanceof StringLiteral || (e instanceof MethodInvocation) &&(((MethodInvocation) e).resolveMethodBinding().getName().equals("intern")); + } + + private void addOperandWithJ2SDoc(Expression exp, boolean toString) { if (exp instanceof ParenthesizedExpression) { buffer.append("("); addJ2SDoc(exp); @@ -3845,9 +3919,9 @@ public boolean visit(StringLiteral node) { buffer.append(s); } else { // \1 doesn't work for JavaScript strict mode - String v = htStrLitCache.get(s); + String v = htStringLiteralCache.get(s); if (v == null) { - htStrLitCache.put(s, v = !po0.matcher(s).find() ? s : replaceOctal(s)); + htStringLiteralCache.put(s, v = !po0.matcher(s).find() ? s : replaceOctal(s)); } buffer.append(v); } @@ -5052,7 +5126,7 @@ String getFinalJ2SClassNameQualifier(Name methodQualifier, ITypeBinding declarin * * For Clazz.newClass we want an array if the superclass is an inner class so * that the outer class is guaranteed to be loaded first. The same goes for - * $I$[] dynamic class loading and interfaces, (but interfaces are handled + * I$[] dynamic class loading and interfaces, (but interfaces are handled * differently). * * @param packageName Java package name or "_" @@ -5958,6 +6032,13 @@ private boolean checkAnnotations(BodyDeclaration node, int mode) { return true; } + /** + * + * @param annotation + * @param node + * @param mode one of {CHECK_ANNOTATIONS_ONLY} + * @return true if successful + */ private boolean addAnnotation(Annotation annotation, ASTNode node, int mode) { String name = annotation.getTypeName().getFullyQualifiedName(); int idx = name.indexOf("J2S"); @@ -5967,7 +6048,12 @@ private boolean addAnnotation(Annotation annotation, ASTNode node, int mode) { if (global_ignoredAnnotations == null || global_ignoredAnnotations.indexOf(";" + name + ";") >= 0) { return true; } - String qname = getFinalJ2SClassName(annotation.resolveTypeBinding().getQualifiedName(), FINAL_RAW); + String qname = name; + try { + qname = getFinalJ2SClassName(annotation.resolveTypeBinding().getQualifiedName(), FINAL_RAW); + } catch (NullPointerException e) { + System.out.println("J2S could not resolve annotation " + annotation); + } if (class_annotations == null) class_annotations = new ArrayList(); class_annotations.add(new ClassAnnotation(qname, annotation, node)); @@ -6089,9 +6175,20 @@ public List getElementList() { header = header .replace(",I$=[]", privateVarString + (package_includes.length() == 0 ? "" - : package_includes.append("]]," + "$I$=function(i,n){return" - + "(i=(I$[i]||(I$[i]=Clazz.load(I$[0][i]))))," - + "!n&&i.$load$&&Clazz.load(i,2)," + "i}"))); + : package_includes.append("]]," + + "$I$=function" + //3.2.9-v1e: + + (package_haveStaticArgsReversal[0] ? + "(i,n,m){return m?$I$(i)[n].apply(null,m):" + : "(i,n){return" + ) + //3.2.9-v1a: + //+ "(i,n){return" + + "((i=(I$[i]||(I$[i]=Clazz.load(I$[0][i]))))" + + ",!n&&i.$load$&&Clazz.load(i,2)" + + ",i)" + + "}" + ))); for (int i = 1; i < parts.length; i++) { js = parts[i]; int pt = js.indexOf("\n"); diff --git a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip index 53a881f5d..ec81fff01 100644 Binary files a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip and b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.java.core/dist/_j2sclasslist.txt b/sources/net.sf.j2s.java.core/dist/_j2sclasslist.txt index 6190ec887..b91ce26be 100644 --- a/sources/net.sf.j2s.java.core/dist/_j2sclasslist.txt +++ b/sources/net.sf.j2s.java.core/dist/_j2sclasslist.txt @@ -350,6 +350,7 @@ swingjs/a2s/ScrollPane.js swingjs/a2s/TextArea.js swingjs/a2s/TextField.js swingjs/api/Interface.js +swingjs/api/JSUtilI.js swingjs/api/js/DOMNode.js swingjs/api/js/HTML5CanvasContext2D.js swingjs/api/js/JSInterface.js diff --git a/sources/net.sf.j2s.java.core/doc/Differences.txt b/sources/net.sf.j2s.java.core/doc/Differences.txt new file mode 100644 index 000000000..a987969a3 --- /dev/null +++ b/sources/net.sf.j2s.java.core/doc/Differences.txt @@ -0,0 +1,1382 @@ +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 overridden by subclasses. As 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 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. 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"); + + +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. + + +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 +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: + + [HashSet] makes no guarantees as to the iteration order of the set. + +JavaScript's Map object is different. It is basically a LinkedHashMap, so it guarantees iteration +in order of object addition. + +Starting with java2script 3.2.9.v1, these classes use the JavaScript Map object rather than hash codes +whenever all keys are strictly of JavaScript typeof "string". If any key is introduced that is not a string, the +implementation falls back to using hash codes, the same as Java. + +Note strings created using new String("xxxx") are NOT typeof "string"; they are typeof "object". + +The result is significantly faster performance (3-12 x faster) than originally, and up to 3 x faster +performance in JavaScript than in Java itself. Right. Faster than Java. + +The JavaScript Map implementation is implemented UNLESS the constructor used is the one that +specifies both initial capacity and load factor in their constructor. Thus, + +new Hashtable() +new HashMap() +new HashMap(16) +new HashSet() + +all use the JavaScript Map. But + +new Hashtable(11, 0.75f) +new HashMap(16, 0.75f) +new HashSet(16, 0.75f) + +do not. + +This design allows for opting out of the JavaScript Map use in order to retain the exact behavior of +iterators in JavaScript as in Java. + + +interning, new String("xxx") vs "xxx" +------------------------------------- + +Note that the following are true in JavaScript: + +typeof new String("xxxx") == "object" +typeof "xxxx" == "string" +var s = "x";typeof ("xxx" + s) == "string" + +There is no equivalence to this behavior in Java, where a String is a String is a String. + +Be aware that SwingJS does not always create a JavaScript String object using JavaScript's +new String(...) constructor. It only does this for Java new String("xxxx") or new String(new String()). + +In all other cases, new String(...) (in Java) results in a simple "xxxx" string in JavaScript. +That is, it will be JavaScript typeof "string", not typeof "object". + +The reason for this design is that several classes in the Java core use toString() +methods that return new String(), and those classes that do that would cause a JavaScript error +if implicitly stringified if new String() returned a JavaScript String object. + +This is fine in JavaScript + +test1 = function() { return { toString:function(){ return "OK" } } } +"testing" + new test1() +>> "testingOK" + +But for whatever reason in JavaScript: + +test2 = function() { return { toString:function(){ return new String("OK") } } } +"testing" + new test2() +>> Uncaught TypeError: Cannot convert object to primitive value + +The lesson here is never to use + + return new String("..."); + +in a Java toString() method. In Java it will be fine; in JavaScript it will also be fine as long as +that method is never called in JavaScript implicitly in the context of string concatenation. + +A note about interning. Consider the following six Java constructions, where we have a == "x"; + +"xxx" +"xx" + "x" +new String("xxx").intern() + +new String("xxx") +"xx" + a.toString() +"xx" + a + +All six of these will return java.lang.String for .getClass().getName(). +However, the first three are String literals, while the last three are String objects. +Thus: + "xxx" == "xxx" + "xxx" == "xx" + "x" + "xxx" == new String("xxx").intern() + +but none of the other three are equivalent to "xxx" or each other: + + "xxx" != new String("xxx") + "xxx" != "xx" + a.toString() + "xxx" != "xx" + a + new String("xxx") != new String("xxx") + "xx" + a != new String("xxx") + +etc. + +As in Java, in SwingJS, all of the following Java assertions pass as true: + + assert("xxx" == "xx" + "x"); + assert("xxx" == ("xx" + a).intern()); + assert("xxx" === new String("xxx").intern()); + +and both of these do as well: + + assert(new String("xxx") != "xxx"); + assert(new String("xxx") != new String("xxx")); + +But the following two fail to assert true: + + assert("xxx" != "xx" + a); + assert("xxx" != "xx" + a.toString()); + +because in JavaScript, both of these right-side expressions evaluate to a simple "interned" string. + +In Java, however, these assertions are true because Java implicitly "boxes" String +concatentaion as a String object, not a literal. + +Most of us know not to generally use == with Strings unless they are explicitly interned. +Where this problem may arise, though, is in IdentityHashMap, which compares objects using +System.identityHashCode(), which is not the same for different objects or their string literal equivalents. + +My recommendation, if you need to use IdentityHashMap with strings is to always use an explicit String.intern() +for any keys -- unless you really want to keep every string as separate keys even if they are the same sequence, +in which case, use new String(). This will work in Java and in JavaScript. + +Be aware when working with strings that come from SwingJS and are being used by other JavaScript modules +that those that are String objects will return "object" for the JavaScript typeof operator, not "string". + +The easy way to ensure this is no problem is to concatenate strings with "" to force immediate interning: + + var x = aJavaObject.getString() + ""; + +unless you are certain that the string is being returned is a raw JavaScript string. + +Names with "$" and "_" +---------------------- + +For the most part, this should be no problem. + +Note that the use of $ and _ in Java field names has always been discouraged: +[https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html] + + You may find some situations where auto-generated names will contain the dollar sign, + but your variable names should always avoid using it. A similar convention + exists for the underscore character; while it's technically legal to begin your + variable's name with "_", this practice is discouraged. + +Some impacts of transpiling method names with full qualification: + +1) SwingJS will introduce fields that start with $ or _. These will not conflict + if the above convention is followed. + +2) Fields that have the same Java name as a method are not an issue. + +3) Fields that have a Java name with $ that matches a transpiled method name, + such as toString$, will need to be refactored in Java to not have that name collision. + +4) Fields in a subclass that have the same name as private fields in a superclass + represent a name collision, because the superclass method needs to call its private + field even if invoked from a subclass. The solution was to modify the subclass field + name using one or more prepended $. + +5) Use of Class.getDeclaredMethods() reflection will return Method objects having the transpiled + name, not the Java name. This could require some j2sNative adjustment + to strip the $... parameters from the name if that is needed. + +6) Use of Method.getParameterTypes() should work fine, provided class names + do not contain "_". This is because the transpiler converts "." to "_" when + creating the fully qualified JavaScript name. + + +positive integers do not add to give negative numbers +----------------------------------------------------- + +In Java, the following is true: + + 2000000000 + 2000000000 == -294967296 + +But in SwingJS, that will be 4000000000. So, for example, the following +strategy will fail in SwingJS: + + int newLength = lineBuf.length * 2; + if (newLength < 0) { + newLength = Integer.MAX_VALUE; + } + +"-1" in JavaScript is not 0xFFFFFFFF. + +And one must take care to not compare a negative number with a 32-bit mask. So + +(b & 0xFF000000) == 0xFF000000 + +is true in Java for (int) b = -1, but is false in JavaScript, because 0xFF000000 is 4278190080, +while (-1 & 0xFF000000) is, strangely enough, -16777216, and, in fact, + +(0xFF000000 & 0xFF000000) != 0xFF000000 + +because -16777216 is not 4278190080. + +The fix is that one must compare similar operations: + +if ((b & 0xFF000000) == (0xFF000000 & 0xFF000000)) ..... + +Importantly, the JavaScript Int32Array does behave properly. From +the Firefox developer console: + +>> x = new Int32Array(1) +<- Int32Array(1) [ 0 ] +>> x[0] = 4000000000 +<- 4000000000 +>> x[0] +<- -294967296 + +Notice that, perhaps unexpectedly, the following two constructs produce +different results in JavaScript: + +x = new Int32Array(1); +b = x[0] = 4000000000; + +(b will be 4000000000) + +and + +x = new Int32Array(1); +x[0] = 4000000000; +b = x[0]; + +(b will be -294967296) + + +SwingJS leverages array typing to handle all byte and short arithmetic so as +to ensure that any byte or short operation in JavaScript does give the same +result in Java. The design decision to not also do this with integer math was +a trade-off between performance and handling edge cases. + + +ArrayIndexOutOfBounds +--------------------- + +You cannot implicitly throw an ArrayIndexOutOfBoundsException in JavaScript. +JavaScript will simply return "undefined", not throw an Exception. So: + +boolean notAGoodIdeaIsOutOfBounds(String[] sa, int i) { + try { + return (sa[i] == sa[i]); + } catch (ArrayIndexOutOfBoundsException e) { + return false; + } +} + +will work in Java but not in JavaScript. Code should not depend upon this sort +of trap anyway, if you ask me. + +Throwable vs Error vs Exception +------------------------------- + +True JavaScript errors are trapped as Throwable, whereas you can still trap +Error and Exception as well. So if you want to be sure to catch any JavaScript +error, use try{}catch (Throwable t){}, not try{}catch (Exception e){}. + +j +ava.awt.Color +-------------- + +ColorSpace: only "support" CS_sRGB. + + TODO -- any volunteers?? + + +javax.swing.JFileDialog +----------------------- + +HTML5 cannot expose a file reading directory structure. But you certainly +can still do file reading and writing. It just works a little differently. +It's a simple modification: + + b = new JButton("FileOpenDialog"); + b.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fc = new JFileChooser(); + Test_Dialog.this.onDialogReturn(fc.showOpenDialog(Test_Dialog.this)); + // Java will wait until the dialog is closed, then enter the onDialogReturn method. + // JavaScript will exit with NaN immediately, and then call back with its actual value + // asynchronously. + } + + }); + + public void onDialogReturn(int value) { + if (value != Math.floor(value)) + return; // in JavaScript, this will be NaN, indicating the dialog has been opened + // If we are here, the dialog has closed, in both Java and JavaScript. + System.out.println("int value is " + value); + } + + + @Override + public void propertyChange(PropertyChangeEvent event) { + Object val = event.getNewValue(); + String name = event.getPropertyName(); + System.out.println(name); + switch (event.getSource().getClass().getName()) { + case "javax.swing.JOptionPane": + switch (name) { + case "inputValue": + onDialogReturn(val); + return; + case "value": + if (val instanceof Integer) + onDialogReturn(((Integer) val).intValue()); + else + onDialogReturn(val); + return; + } + break; + case "javax.swing.ColorChooserDialog": + switch (name) { + case "SelectedColor": + onDialogReturn(val); + return; + } + break; + case "javax.swing.JFileChooser": + switch (name) { + case "SelectedFile": + File file = (File) val; + byte[] array = (val == null ? null : /** @j2sNative file.秘bytes || */ + null); + onDialogReturn("fileName is '" + file.getName() + "'\n\n" + new String(array)); + return; + } + break; + } + System.out.println( + event.getSource().getClass().getName() + " " + event.getPropertyName() + ": " + event.getNewValue()); + } + + +Developers are encouraged to create a separate class that handles general calls to JFileDialog. +An example class can be found in the SwingJS distribution as + +/sources/net.sf.j2s.java.core/src/javajs/async/AsyncFileChooser.java. + + +javax.swing.JOptionPane dialogs +------------------------------- + +For this action to work, the parentComponent must implement +propertyChangeListener, and any call to JOptionPanel should allow for +an asynchronous response, meaning that there is no actionable code following the +call to the dialog opening. + +In addition, for compatibility with the Java version, implementation should +wrap the call to getConfirmDialog or getOptionDialog in a method call to +handle the Java: + +onDialogReturn(JOptionPane.showConfirmDialog(parentFrame, +messageOrMessagePanel, "title", JOptionPane.OK_CANCEL_OPTION)); + +Then parentFrame.propertyChange(event) should also call onDialogReturn. + +This will then work in both Java and JavaScript. + +Note that there is an int and an Object version of onDialogReturn(). + + +In JavaScript: + +The initial return from JOptionPane.showConfirmDialog and showMessageDialog +will be (SwingJS) JDialog.ASYNCHRONOUS_INTEGER (NaN), testable as an impossible +Java int value using ret != -(-ret) if the parent implements PropertyChangeListener, or -1 +(CLOSE_OPTION) if not. + +For showOptionDialog (which returns Object) or showInputDialog (which returns +String), the initial return will be (SwingJS) JDialog.ASYNCHRONOUS_OBJECT, testable as +((Object) ret) instanceof javax.swing.plaf.UIResource if the parent implements +PropertyChangeListeneer, or null if not. + +The second return will be the desired return. + +In Java: + +The initial return will be the one and only modal final return. + + + +For full compatibility, The calling method must not continue beyond this +call. + +All of the standard Java events associated with Components are also +available. + +Certain fall back mechanisms are possible, where onReturn does not exist, but +only for the following cases: + + +For showMessageDialog, for WARNING_MESSAGE and ERROR_MESSAGE, a simple +JavaScript alert() is used, returning 0 (OK_OPTION) or -1 (CLOSED_OPTION). + +For showInputDialog, if the message is a string, a simple JavaScript prompt() +with input box is used, returning the entered string or null. + +For showConfirmDialog, a simple JavaScript confirm() is used, in which case: + +for YES_NO_OPTION: YES_OPTION or NO_OPTION + +for YES_NO_CANCEL_OPTION: YES_OPTION or CANCEL_OPTION + +for OK_CANCEL_OPTION or any other: OK_OPTION or CANCEL_OPTION + +Note that you should implement a response for CLOSED_OPTION for +showConfirmDialog. For other dialogs, a null return indicates the dialog was +closed, just as for Java. + +Developers are encouraged to create a separate class that handles general calls. +An example class can be found in the SwingJS distribution as src/javajs/async/AsyncDialog.java. +Very simple modifications to the Java allows asynchronous operation using AsyncDialog. Here +is a simple "do you want to close this frame" example, where you can see that what we have +done is to set the reply into an ActionListener that is defined in the constructor of +the AsyncDisplay object: + +// Original: +// +// private void promptQuit() { +// int sel = JOptionPane.showConfirmDialog(null, PROMPT_EXIT, NAME, JOptionPane.YES_NO_OPTION); +// switch (sel) { +// case JOptionPane.YES_OPTION: +// resultsTab.clean(); +// seqs.dispose(); +// if (fromMain) { +// System.exit(0); +// } +// break; +// } +// } + + private void promptQuitAsync() { + new AsyncDialog(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + int sel = ((AsyncDialog)e.getSource()).getOption(); + switch (sel) { + case JOptionPane.YES_OPTION: + resultsTab.clean(); + seqs.dispose(); + if (fromMain) { + System.exit(0); + } + break; + } + }}).showConfirmDialog(null, PROMPT_EXIT, NAME, JOptionPane.YES_NO_OPTION); + } + +Very simple! + + +native methods +-------------- + +The J2S compiler ignores all static native method declarations. +Anything of this nature needs to be implemented in JavaScript if it is needed, +using j2sNative blocks: + +/** + * @j2sNative + * + * var putYourJavaScriptCodeHere + * + */ + + Note that if you follow that directly with a {...} block, then + the javadoc code will run in JavaScript, and the {...} code will run in Java. + + +key Focus +--------- + +As of June, 2019, the keyboard focus manager is fully implemented. +The one catch is that JTextPane and JTextArea, which already consume +VK_TAB in Java, cannot use CTRL-TAB to continue a tabbing cycle around +the components in a window. Instead, CTRL-TAB is absorbed by the browser. + + +LookAndFeel and UI Classes +-------------------------- + +SwingJS implements the native browser look and feel as swingjs.plaf.HTML5LookAndFeel. +There are small differences between all look and feels -- MacOS, Windows, SwingJS. + +Expert developers know how to coerce changes in the UI by subclassing the UI for a +component. This probably will not work in SwingJS. + +Note that LookAndFeel in Java usually determines canvas size in a Frame because +different operating systems (Mac OS vs Windows vs HTML5) will have +different edge sizes on their frames. If you want to ensure a component size, +use getContentPane().setPreferredSize(). + + +System.exit(0) does not stop all processes +------------------------------------------ + +Although System.ext(int) has been implemented in JavaScript, it just closes the +frames, stops all pending javax.swing.Timer objects in the queue, and runs any +threads added using Runtime.getRuntime().addShutdownHook(Thread). +It may not stop all "threads." So don't rely on that. +Applications are responsible for shutting down prior to executing System.exit(0). + + +myClass.getField not implemented +-------------------------------- + +java.lang.reflect.Field is implemented minimally. It is not +certain that Field.getDeclaringClass() will work. If you just want a +value of a field, you can do this: + +/** + *@j2sNative + * + * return myClass[name] + */ + +But that is not a java.lang.reflection.Field object. + + +"window" and other reserved JavaScript names +-------------------------------------------- + +No reserved top-level JavaScript name is allowed for a package name. So, for example, +one must rename packages such as "window" or "document" to names such as "win" or "doc". + +qualified field and method names +-------------------------------- + +In order to minimize the chance of added SwingJS field and method names colliding with ones +developers might use in subclassing Java classes, we have added U+79D8 (first character of Mandarin +"secret") to the characters already disrecommended by Java documentation ("$" and "_"). The only problem +would be if you use that character followed by certain English words in certain classes. For example +\u79D8canvas for JComponents (in java.awt.JSComponent) and \u79D8byte (in java.io.File). + +missing Math methods +-------------------- + +java.lang.Math is worked out, but some methods are missing, either because they +involve long integer value that are inaccessible in JavaScript, or because I just +didn't implement them. This is a result of continued Java development. +It is easy enough to add these methods if you have the source. They go into j2sClazz.js, +which is combined with other initial libraries into swingjs2.js by build_site.xml + + +Component.getGraphics(), Graphics.dispose() +------------------------------------------- + +Use of component.getGraphics() is discouraged in Java and in SwingJS. +Specifically in SwingJS, any call to component.getGraphics() or +BufferedImage.createGraphics() or Graphics.create(...) should be matched with graphics.dispose(), +particularly when it is called outside the context of a paint(Graphics) +call from the system. + +If you see your graphics scrolling down the page with each repaint, +look for where you have used Component.getGraphics() and not Graphics.dispose(). +For example, this will definitely NOT work in SwingJS: + + this.paint(getGraphics()) + +and really should not work in Java, either, as it is technically a resource memory leak. + +Instead, if you really do not want to use repaint(), use this: + + Graphics g = getGraphics(); + paint(g); + g.dispose(); + + + +Graphics.setClip() +------------------ + +The HTML5 canvas.clip() method is permanent. You can only reset the clip using +save/restore. This is different from Java, where you can temporarily change it using + + Shape oldClip = Graphics.getClip(); + Graphics.setClip(newClip); + ... + Graphics.setClip(oldClip); + +If you need to do something like this, you must schedule the paints +to not have overlapping clip needs. + + +MAJOR ISSUES--for Bob and Udo within SwingJS +============================================ + +fonts +----- + +Fonts and FontMetrics will all be handled in JavaScript. Font matching will +not be exact, and composite (drawn) fonts will not be supported. + +SwingJS handles calls such as font.getFontMetrics(g).stringWidth("xxx") by +creating a
containing that text, placing it in an obscure location on +the page, and reading div.getBoundingClientRect(). This is a VERY precise +value, but can be a pixel or two off from what Java reports for the same font. + + +OS-dependent classes +-------------------- + +Static classes such as: + + java.awt.Toolkit + java.awt.GraphicsEnvironment + + +which are created using Class.forName are implemented using classes in the swingjs package. + +AWTAccessor is not implemented. + + +AWT component peers and component "ui" user interfaces +------------------------------------------------------ + +ComponentPeer is a class that represents a native AWT component. +Components with such peers are called "heavy-weight" components. +They are expected to do the dirty work of graphics drawing. + +Java Swing implements peers only for JApplet, JDialog, JFrame, and JWindow. +References to such objects have been removed, but clearly there must be +some connection to similar DOM objects, even for "light-weight" components. + + + +MAJOR ISSUES--to be resolved by implementers +============================================ + +fonts +----- + +Glyph/composite/outline fonts are not supported. + + + +threads +------- + +Thread locking and synchronization are not relevant to JavaScript. +Thus, anything requiring "notify.." or "waitFor.." could be a serious issue. + +All threading must be "faked" in JavaScript. Specifically not available is: + + Thread.sleep() + +javax.swing.AbstractButton#doClick(pressTime) will not work, as it requires Thread.sleep(); + +However, java.lang.Thread itself is implemented and used extensively. + +Methods thread.start() and thread.run() both work fine. + +For simple applications that use Thread.sleep() just to have a delay, as in a frame rate, for +example, one can use javax.swing.Timer instead. That is fully implemented. + +Likewise, java.util.Timer can be replaced with no loss of performance with javax.Swing.Timer. +Note that java.util.TimerTask is implemented, but it can also be replaced by an implementation of Runnable. + +task = new TimerTask(){....}; +t = new java.util.Timer(); +t.schedule(task, 0, 1); + +becomes + +task = new TimerTask(){....}; // or task = new Runnable() {...} +t = new javax.swing.Timer(1, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + task.run(); + } +}; +t.setInitialDelay(0); // not particularly necessary +t.start(); + +In addition, SwingJS provides swingjs.JSThread, which can be subclassed +if desired. This class allows simple + + while(!interrupted()){ + wait() + ... + } + +action through an asynchronous function run1(mode). For example: + + protected void run1(int mode) { + try { + while (true) + switch (mode) { + case INIT: + // once-through stuff here + mode = LOOP; + break; + case LOOP: + if (!doDispatch || isInterrupted()) { + mode = DONE; + } else { + Runnable r = new Runnable() { + public void run() { + // put the loop code here + } + }; + dispatchAndReturn(r); + if (isJS) + return; + } + break; + // add more cases as needed + case DONE: + // finish up here + if (isInterrupted()) + return; + // or here + break; + } + } finally { + // stuff here to be executed after each loop in JS or at the end in Java + } + } + +image loading +------------- +- All image loading in SwingJS is synchronous. A MediaTracker call will immediately return "complete". + However, it still may take one system clock tick to fully load images. Thus, it is recommended that + images be preloaded in the static block of the applet if it is necessary that they be available in init(). + This is only an issue if you are trying to access the pixel buffer of the image in JavaScript. + +- Applet.getImage(path, name) will return null if the image does not exist. + +- BufferedImage: only "support" imageType RGB and ARGB + + -BH: This is a temporary edit, just to get us started. Certainly GRAY will be needed + + +BigInteger and BigDecimal +------------------------- + +java.math.BigInteger is fully supported; java.math.BigDecimal is roughed +in and not fully tested (07/2019). + +Both classes present significant issues for JavaScript, as they are based in +Java's 64-bit long for all their operations. Here is the JavaDoc note I added +to BigInteger: + + * SwingJS note: Because of the limitations of JavaScript with regard + * to long-integer bit storage as a double, this implementation drops + * the integer storage bit length to 24, giving 48 for long and leaving + * the last 16 bits clear for the exponent of the double number. This should + * not affect performance significantly. It does increase the storage + * size by about 33%. By bringing an "int" to 3 bytes, we can easily construct + * and use byte[] data intended for the original BitSet. + +"Easily" may be a bit strong there. This was a serious challenge. + +BigDecimal seems to run normally, but in order to do that, my hack involves +reducing the size of an integer that is allowed to be stored as such and not +in byte[] as a BigInteger. I'm sure there is a performance hit, but it does work. + +no format internationalization +------------------------------ + +For now, just en for number and date formatters + +no winding rules +---------------- + + When filling a graphic, only nonzero winding rule is implemented in HTML5 Canvas2D. + + + +text-related field implementation +--------------------------------- + +Text fields are: + +JTextField (JavaScript ) +JTextArea (JavaScript