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 ecf440142..e46407ecb 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/timestamp b/sources/net.sf.j2s.core/dist/swingjs/timestamp index e4c793229..af3b20978 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/timestamp @@ -1 +1 @@ -20190315122942 +20190316185356 diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/SwingJS-site.zip index ecf440142..e46407ecb 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/timestamp b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/timestamp index e4c793229..af3b20978 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.2.4/timestamp @@ -1 +1 @@ -20190315122942 +20190316185356 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 ecf440142..e46407ecb 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/src/java/awt/Container.java b/sources/net.sf.j2s.java.core/src/java/awt/Container.java index d2ff05239..d4e1ea279 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/Container.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/Container.java @@ -1070,9 +1070,13 @@ protected void addImpl(Component comp, Object constraints, int index) { addImplCont(comp, constraints, index); } + @SuppressWarnings("unused") protected void addImplCont(Component comp, Object constraints, int index) { synchronized (getTreeLock()) { - + + if (/** @j2sNative comp.getWrap$ && !this.isWrapper$ || */ false) { + comp = ((A2SWrappedComponent) comp).getWrap$(); + } // SwingJS used for all add methods /* @@ -1246,8 +1250,15 @@ public void remove(int index) { * @see #validate * @see #remove(int) */ - public void remove(Component comp) { + @SuppressWarnings("unused") + public void remove(Component comp) { synchronized (getTreeLock()) { + + if (/** @j2sNative comp.getWrap$ && !this.isWrapper$ || */ false) { + comp = ((A2SWrappedComponent) comp).getWrap$(); + } + + if (comp.parent == this) { int index = component.indexOf(comp); if (index >= 0) { diff --git a/sources/net.sf.j2s.java.core/src/java/awt/JSComponent.java b/sources/net.sf.j2s.java.core/src/java/awt/JSComponent.java index 1e762d703..e9b418bde 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/JSComponent.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/JSComponent.java @@ -27,7 +27,6 @@ */ package java.awt; -import java.applet.JSApplet; import java.awt.event.KeyListener; import java.awt.peer.ComponentPeer; import java.beans.PropertyChangeListener; @@ -67,6 +66,32 @@ */ public abstract class JSComponent extends Component { + /** + * A marker for the SwingJS version of JViewPort to indicate that it + * can add an A2SWrappedComponent, not pass it back for wrapping. + * + * @author hansonr + * + */ + public interface A2SComponentWrapper { + + public void isWrapper$(); + } + + /** + * For JViewPort. + * + * Implementations of java.awt.List require a JScrollPane/JViewPort + * wrapper. + * + * @author hansonr + * + */ + public interface A2SWrappedComponent { + + public Component getWrap$(); + + } /** * overridden in Applet * diff --git a/sources/net.sf.j2s.java.core/src/java/awt/JSDialog.java b/sources/net.sf.j2s.java.core/src/java/awt/JSDialog.java index 34f91a1ae..fb6f506f7 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/JSDialog.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/JSDialog.java @@ -27,6 +27,7 @@ */ package java.awt; +import java.awt.Dialog.ModalityType; import java.awt.event.ComponentEvent; import java.awt.event.HierarchyEvent; import java.awt.event.WindowEvent; @@ -35,6 +36,8 @@ import java.util.ArrayList; import java.util.Iterator; +import swingjs.plaf.JSDialogUI; + /** * A Dialog is a top-level window with a title and a border * that is typically used to take some form of input from the user. @@ -839,10 +842,14 @@ private boolean conditionalShow(Component toFocus, Long time) { closeSplashScreen(); - // synchronized (getTreeLock()) { + if (ui != null && ((JSDialogUI) ui).isDisposed) + addNotify(); + // synchronized (getTreeLock()) { // if (peer == null) { // addNotify(); // } + + validate(); if (visible) { toFront(); diff --git a/sources/net.sf.j2s.java.core/src/java/awt/Window.java b/sources/net.sf.j2s.java.core/src/java/awt/Window.java index 294069f2d..9c4e600cb 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/Window.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/Window.java @@ -58,6 +58,7 @@ //import java.util.logging.Logger; import swingjs.JSUtil; import swingjs.plaf.JSComponentUI; +import swingjs.plaf.JSWindowUI; /** * @@ -842,7 +843,7 @@ public void printAll(Graphics g) { @Override public Dimension getPreferredSize() { - return preferredSizeContainer(); + return preferredSize();// for AWT classes } @@ -890,6 +891,9 @@ public void setVisible(boolean b) { @Override @Deprecated public void show() { + + if (ui != null && ((JSWindowUI) ui).isDisposed) + addNotify(); // if (peer == null) { // addNotify(); // } diff --git a/sources/net.sf.j2s.java.core/src/javax/swing/JComponent.java b/sources/net.sf.j2s.java.core/src/javax/swing/JComponent.java index 07fef6583..efa667dc8 100644 --- a/sources/net.sf.j2s.java.core/src/javax/swing/JComponent.java +++ b/sources/net.sf.j2s.java.core/src/javax/swing/JComponent.java @@ -1470,7 +1470,7 @@ public Dimension getPreferredSize() { public Dimension getPrefSizeJComp() { Dimension size = (!isPreferredSizeSet() && ui != null ? ui .getPreferredSize(this) : null); - return (size == null ? super.preferredSize() : size); + return (size == null ? preferredSize() : size); } /** diff --git a/sources/net.sf.j2s.java.core/src/javax/swing/JTree.java b/sources/net.sf.j2s.java.core/src/javax/swing/JTree.java index ab73d8209..20625cbb5 100644 --- a/sources/net.sf.j2s.java.core/src/javax/swing/JTree.java +++ b/sources/net.sf.j2s.java.core/src/javax/swing/JTree.java @@ -40,6 +40,7 @@ import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import javax.swing.event.EventListenerList; import javax.swing.event.TreeExpansionEvent; @@ -62,6 +63,9 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; +import sun.swing.SwingUtilities2; +import sun.swing.SwingUtilities2.Section; + /** * @@ -326,137 +330,137 @@ public class JTree extends JComponent implements Scrollable /** If true, mouse presses on selections initiate a drag operation. */ private boolean dragEnabled; -// /** -// * The drop mode for this component. -// */ -// private DropMode dropMode = DropMode.USE_SELECTION; -// -// /** -// * The drop location. -// */ -// private transient DropLocation dropLocation; -// -// /** -// * A subclass of TransferHandler.DropLocation representing -// * a drop location for a JTree. -// * -// * @see #getDropLocation -// * @since 1.6 -// */ -// public static final class DropLocation extends TransferHandler.DropLocation { -// private final TreePath path; -// private final int index; -// -// private DropLocation(Point p, TreePath path, int index) { -// super(p); -// this.path = path; -// this.index = index; -// } -// -// /** -// * Returns the index where the dropped data should be inserted -// * with respect to the path returned by getPath(). -// *

-// * For drop modes DropMode.USE_SELECTION and -// * DropMode.ON, this index is unimportant (and it will -// * always be -1) as the only interesting data is the -// * path over which the drop operation occurred. -// *

-// * For drop mode DropMode.INSERT, this index -// * indicates the index at which the data should be inserted into -// * the parent path represented by getPath(). -// * -1 indicates that the drop occurred over the -// * parent itself, and in most cases should be treated as inserting -// * into either the beginning or the end of the parent's list of -// * children. -// *

-// * For DropMode.ON_OR_INSERT, this value will be -// * an insert index, as described above, or -1 if -// * the drop occurred over the path itself. -// * -// * @return the child index -// * @see #getPath -// */ -// public int getChildIndex() { -// return index; -// } -// -// /** -// * Returns the path where dropped data should be placed in the -// * tree. -// *

-// * Interpretation of this value depends on the drop mode set on the -// * component. If the drop mode is DropMode.USE_SELECTION -// * or DropMode.ON, the return value is the path in the -// * tree over which the data has been (or will be) dropped. -// * null indicates that the drop is over empty space, -// * not associated with a particular path. -// *

-// * If the drop mode is DropMode.INSERT, the return value -// * refers to the path that should become the parent of the new data, -// * in which case getChildIndex() indicates where the -// * new item should be inserted into this parent path. A -// * null path indicates that no parent path has been -// * determined, which can happen for multiple reasons: -// *

-// * It is up to the developer to decide if and how they wish to handle -// * the null case. -// *

-// * If the drop mode is DropMode.ON_OR_INSERT, -// * getChildIndex can be used to determine whether the -// * drop is on top of the path itself (-1) or the index -// * at which it should be inserted into the path (values other than -// * -1). -// * -// * @return the drop path -// * @see #getChildIndex -// */ -// public TreePath getPath() { -// return path; -// } -// -// /** -// * Returns a string representation of this drop location. -// * This method is intended to be used for debugging purposes, -// * and the content and format of the returned string may vary -// * between implementations. -// * -// * @return a string representation of this drop location -// */ -// public String toString() { -// return getClass().getName() -// + "[dropPoint=" + getDropPoint() + "," -// + "path=" + path + "," -// + "childIndex=" + index + "]"; -// } -// } + /** + * The drop mode for this component. + */ + private DropMode dropMode = DropMode.USE_SELECTION; + + /** + * The drop location. + */ + private transient DropLocation dropLocation; + + /** + * A subclass of TransferHandler.DropLocation representing + * a drop location for a JTree. + * + * @see #getDropLocation + * @since 1.6 + */ + public static final class DropLocation extends TransferHandler.DropLocation { + private final TreePath path; + private final int index; + + private DropLocation(Point p, TreePath path, int index) { + super(p); + this.path = path; + this.index = index; + } + + /** + * Returns the index where the dropped data should be inserted + * with respect to the path returned by getPath(). + *

+ * For drop modes DropMode.USE_SELECTION and + * DropMode.ON, this index is unimportant (and it will + * always be -1) as the only interesting data is the + * path over which the drop operation occurred. + *

+ * For drop mode DropMode.INSERT, this index + * indicates the index at which the data should be inserted into + * the parent path represented by getPath(). + * -1 indicates that the drop occurred over the + * parent itself, and in most cases should be treated as inserting + * into either the beginning or the end of the parent's list of + * children. + *

+ * For DropMode.ON_OR_INSERT, this value will be + * an insert index, as described above, or -1 if + * the drop occurred over the path itself. + * + * @return the child index + * @see #getPath + */ + public int getChildIndex() { + return index; + } + + /** + * Returns the path where dropped data should be placed in the + * tree. + *

+ * Interpretation of this value depends on the drop mode set on the + * component. If the drop mode is DropMode.USE_SELECTION + * or DropMode.ON, the return value is the path in the + * tree over which the data has been (or will be) dropped. + * null indicates that the drop is over empty space, + * not associated with a particular path. + *

+ * If the drop mode is DropMode.INSERT, the return value + * refers to the path that should become the parent of the new data, + * in which case getChildIndex() indicates where the + * new item should be inserted into this parent path. A + * null path indicates that no parent path has been + * determined, which can happen for multiple reasons: + *

+ * It is up to the developer to decide if and how they wish to handle + * the null case. + *

+ * If the drop mode is DropMode.ON_OR_INSERT, + * getChildIndex can be used to determine whether the + * drop is on top of the path itself (-1) or the index + * at which it should be inserted into the path (values other than + * -1). + * + * @return the drop path + * @see #getChildIndex + */ + public TreePath getPath() { + return path; + } + + /** + * Returns a string representation of this drop location. + * This method is intended to be used for debugging purposes, + * and the content and format of the returned string may vary + * between implementations. + * + * @return a string representation of this drop location + */ + public String toString() { + return getClass().getName() + + "[dropPoint=" + getDropPoint() + "," + + "path=" + path + "," + + "childIndex=" + index + "]"; + } + } /** * The row to expand during DnD. */ -// private int expandRow = -1; + private int expandRow = -1; + + private class TreeTimer extends Timer { + public TreeTimer() { + super(2000, null); + setRepeats(false); + } + + public void fireActionPerformed(ActionEvent ae) { + JTree.this.expandRow(expandRow); + } + } + + /** + * A timer to expand nodes during drop. + */ + private TreeTimer dropTimer; -// private class TreeTimer extends Timer { -// public TreeTimer() { -// super(2000, null); -// setRepeats(false); -// } -// -// public void fireActionPerformed(ActionEvent ae) { -// JTree.this.expandRow(expandRow); -// } -// } -// -// /** -// * A timer to expand nodes during drop. -// */ -// private TreeTimer dropTimer; -// /** * When addTreeExpansionListener is invoked, * and settingUI is true, this ivar gets set to the passed in @@ -1204,277 +1208,278 @@ public boolean getDragEnabled() { return dragEnabled; } -// /** -// * Sets the drop mode for this component. For backward compatibility, -// * the default for this property is DropMode.USE_SELECTION. -// * Usage of one of the other modes is recommended, however, for an -// * improved user experience. DropMode.ON, for instance, -// * offers similar behavior of showing items as selected, but does so without -// * affecting the actual selection in the tree. -// *

-// * JTree supports the following drop modes: -// *

-// *

-// * The drop mode is only meaningful if this component has a -// * TransferHandler that accepts drops. -// * -// * @param dropMode the drop mode to use -// * @throws IllegalArgumentException if the drop mode is unsupported -// * or null -// * @see #getDropMode -// * @see #getDropLocation -// * @see #setTransferHandler -// * @see TransferHandler -// * @since 1.6 -// */ -// public final void setDropMode(DropMode dropMode) { -// if (dropMode != null) { -// switch (dropMode) { -// case USE_SELECTION: -// case ON: -// case INSERT: -// case ON_OR_INSERT: -// this.dropMode = dropMode; -// return; -// } -// } -// -// throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for tree"); -// } -// -// /** -// * Returns the drop mode for this component. -// * -// * @return the drop mode for this component -// * @see #setDropMode -// * @since 1.6 -// */ -// public final DropMode getDropMode() { -// return dropMode; -// } -// -// /** -// * Calculates a drop location in this component, representing where a -// * drop at the given point should insert data. -// * -// * @param p the point to calculate a drop location for -// * @return the drop location, or null -// */ -// DropLocation dropLocationForPoint(Point p) { -// DropLocation location = null; -// -// int row = getClosestRowForLocation(p.x, p.y); -// Rectangle bounds = getRowBounds(row); -// TreeModel model = getModel(); -// Object root = (model == null) ? null : model.getRoot(); -// TreePath rootPath = (root == null) ? null : new TreePath(root); -// -// TreePath child = null; -// TreePath parent = null; -// boolean outside = row == -1 -// || p.y < bounds.y -// || p.y >= bounds.y + bounds.height; -// -// switch(dropMode) { -// case USE_SELECTION: -// case ON: -// if (outside) { -// location = new DropLocation(p, null, -1); -// } else { -// location = new DropLocation(p, getPathForRow(row), -1); -// } -// -// break; -// case INSERT: -// case ON_OR_INSERT: -// if (row == -1) { -// if (root != null && !model.isLeaf(root) && isExpanded(rootPath)) { -// location = new DropLocation(p, rootPath, 0); -// } else { -// location = new DropLocation(p, null, -1); -// } -// -// break; -// } -// -// boolean checkOn = dropMode == DropMode.ON_OR_INSERT -// || !model.isLeaf(getPathForRow(row).getLastPathComponent()); -// -// Section section = SwingUtilities2.liesInVertical(bounds, p, checkOn); -// if(section == LEADING) { -// child = getPathForRow(row); -// parent = child.getParentPath(); -// } else if (section == TRAILING) { -// int index = row + 1; -// if (index >= getRowCount()) { -// if (model.isLeaf(root) || !isExpanded(rootPath)) { -// location = new DropLocation(p, null, -1); -// } else { -// parent = rootPath; -// index = model.getChildCount(root); -// location = new DropLocation(p, parent, index); -// } -// -// break; -// } -// -// child = getPathForRow(index); -// parent = child.getParentPath(); -// } else { -// assert checkOn; -// location = new DropLocation(p, getPathForRow(row), -1); -// break; -// } -// -// if (parent != null) { -// location = new DropLocation(p, parent, -// model.getIndexOfChild(parent.getLastPathComponent(), -// child.getLastPathComponent())); -// } else if (checkOn || !model.isLeaf(root)) { -// location = new DropLocation(p, rootPath, -1); -// } else { -// location = new DropLocation(p, null, -1); -// } -// -// break; -// default: -// assert false : "Unexpected drop mode"; -// } -// -// if (outside || row != expandRow) { -// cancelDropTimer(); -// } -// -// if (!outside && row != expandRow) { -// if (isCollapsed(row)) { -// expandRow = row; -// startDropTimer(); -// } -// } -// -// return location; -// } -// -// /** -// * Called to set or clear the drop location during a DnD operation. -// * In some cases, the component may need to use it's internal selection -// * temporarily to indicate the drop location. To help facilitate this, -// * this method returns and accepts as a parameter a state object. -// * This state object can be used to store, and later restore, the selection -// * state. Whatever this method returns will be passed back to it in -// * future calls, as the state parameter. If it wants the DnD system to -// * continue storing the same state, it must pass it back every time. -// * Here's how this is used: -// *

-// * Let's say that on the first call to this method the component decides -// * to save some state (because it is about to use the selection to show -// * a drop index). It can return a state object to the caller encapsulating -// * any saved selection state. On a second call, let's say the drop location -// * is being changed to something else. The component doesn't need to -// * restore anything yet, so it simply passes back the same state object -// * to have the DnD system continue storing it. Finally, let's say this -// * method is messaged with null. This means DnD -// * is finished with this component for now, meaning it should restore -// * state. At this point, it can use the state parameter to restore -// * said state, and of course return null since there's -// * no longer anything to store. -// * -// * @param location the drop location (as calculated by -// * dropLocationForPoint) or null -// * if there's no longer a valid drop location -// * @param state the state object saved earlier for this component, -// * or null -// * @param forDrop whether or not the method is being called because an -// * actual drop occurred -// * @return any saved state for this component, or null if none -// */ -// Object setDropLocation(TransferHandler.DropLocation location, -// Object state, -// boolean forDrop) { -// -// Object retVal = null; -// DropLocation treeLocation = (DropLocation)location; -// -// if (dropMode == DropMode.USE_SELECTION) { -// if (treeLocation == null) { -// if (!forDrop && state != null) { -// setSelectionPaths(((TreePath[][])state)[0]); -// setAnchorSelectionPath(((TreePath[][])state)[1][0]); -// setLeadSelectionPath(((TreePath[][])state)[1][1]); -// } -// } else { -// if (dropLocation == null) { -// TreePath[] paths = getSelectionPaths(); -// if (paths == null) { -// paths = new TreePath[0]; -// } -// -// retVal = new TreePath[][] {paths, -// {getAnchorSelectionPath(), getLeadSelectionPath()}}; -// } else { -// retVal = state; -// } -// -// setSelectionPath(treeLocation.getPath()); -// } -// } -// -// DropLocation old = dropLocation; -// dropLocation = treeLocation; -// firePropertyChange("dropLocation", old, dropLocation); -// -// return retVal; -// } + /** + * Sets the drop mode for this component. For backward compatibility, + * the default for this property is DropMode.USE_SELECTION. + * Usage of one of the other modes is recommended, however, for an + * improved user experience. DropMode.ON, for instance, + * offers similar behavior of showing items as selected, but does so without + * affecting the actual selection in the tree. + *

+ * JTree supports the following drop modes: + *

+ *

+ * The drop mode is only meaningful if this component has a + * TransferHandler that accepts drops. + * + * @param dropMode the drop mode to use + * @throws IllegalArgumentException if the drop mode is unsupported + * or null + * @see #getDropMode + * @see #getDropLocation + * @see #setTransferHandler + * @see TransferHandler + * @since 1.6 + */ + public final void setDropMode(DropMode dropMode) { + if (dropMode != null) { + switch (dropMode) { + case USE_SELECTION: + case ON: + case INSERT: + case ON_OR_INSERT: + this.dropMode = dropMode; + return; + } + } -// /** -// * Called to indicate to this component that DnD is done. -// * Allows for us to cancel the expand timer. -// */ -// void dndDone() { -// cancelDropTimer(); -// dropTimer = null; -// } -// -// /** -// * Returns the location that this component should visually indicate -// * as the drop location during a DnD operation over the component, -// * or {@code null} if no location is to currently be shown. -// *

-// * This method is not meant for querying the drop location -// * from a {@code TransferHandler}, as the drop location is only -// * set after the {@code TransferHandler}'s canImport -// * has returned and has allowed for the location to be shown. -// *

-// * When this property changes, a property change event with -// * name "dropLocation" is fired by the component. -// * -// * @return the drop location -// * @see #setDropMode -// * @see TransferHandler#canImport(TransferHandler.TransferSupport) -// * @since 1.6 -// */ -// public final DropLocation getDropLocation() { -// return dropLocation; -// } + throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for tree"); + } -// private void startDropTimer() { -// if (dropTimer == null) { -// dropTimer = new TreeTimer(); -// } -// dropTimer.start(); -// } -// -// private void cancelDropTimer() { -// if (dropTimer != null && dropTimer.isRunning()) { -// expandRow = -1; -// dropTimer.stop(); -// } -// } + /** + * Returns the drop mode for this component. + * + * @return the drop mode for this component + * @see #setDropMode + * @since 1.6 + */ + public final DropMode getDropMode() { + return dropMode; + } + + /** + * Calculates a drop location in this component, representing where a + * drop at the given point should insert data. + * + * @param p the point to calculate a drop location for + * @return the drop location, or null + */ + DropLocation dropLocationForPoint(Point p) { + DropLocation location = null; + + int row = getClosestRowForLocation(p.x, p.y); + Rectangle bounds = getRowBounds(row); + TreeModel model = getModel(); + Object root = (model == null) ? null : model.getRoot(); + TreePath rootPath = (root == null) ? null : new TreePath(root); + + TreePath child = null; + TreePath parent = null; + boolean outside = row == -1 + || p.y < bounds.y + || p.y >= bounds.y + bounds.height; + + switch(dropMode) { + case USE_SELECTION: + case ON: + if (outside) { + location = new DropLocation(p, null, -1); + } else { + location = new DropLocation(p, getPathForRow(row), -1); + } + + break; + case INSERT: + case ON_OR_INSERT: + if (row == -1) { + if (root != null && !model.isLeaf(root) && isExpanded(rootPath)) { + location = new DropLocation(p, rootPath, 0); + } else { + location = new DropLocation(p, null, -1); + } + + break; + } + + boolean checkOn = dropMode == DropMode.ON_OR_INSERT + || !model.isLeaf(getPathForRow(row).getLastPathComponent()); + + Section section = SwingUtilities2.liesInVertical(bounds, p, checkOn); + if(section == Section.LEADING) { + child = getPathForRow(row); + parent = child.getParentPath(); + } else if (section == Section.TRAILING) { + int index = row + 1; + if (index >= getRowCount()) { + if (model.isLeaf(root) || !isExpanded(rootPath)) { + location = new DropLocation(p, null, -1); + } else { + parent = rootPath; + index = model.getChildCount(root); + location = new DropLocation(p, parent, index); + } + + break; + } + + child = getPathForRow(index); + parent = child.getParentPath(); + } else { + assert checkOn; + location = new DropLocation(p, getPathForRow(row), -1); + break; + } + + if (parent != null) { + location = new DropLocation(p, parent, + model.getIndexOfChild(parent.getLastPathComponent(), + child.getLastPathComponent())); + } else if (checkOn || !model.isLeaf(root)) { + location = new DropLocation(p, rootPath, -1); + } else { + location = new DropLocation(p, null, -1); + } + + break; + default: + assert false : "Unexpected drop mode"; + } + + if (outside || row != expandRow) { + cancelDropTimer(); + } + + if (!outside && row != expandRow) { + if (isCollapsed(row)) { + expandRow = row; + startDropTimer(); + } + } + + return location; + } + + /** + * Called to set or clear the drop location during a DnD operation. + * In some cases, the component may need to use it's internal selection + * temporarily to indicate the drop location. To help facilitate this, + * this method returns and accepts as a parameter a state object. + * This state object can be used to store, and later restore, the selection + * state. Whatever this method returns will be passed back to it in + * future calls, as the state parameter. If it wants the DnD system to + * continue storing the same state, it must pass it back every time. + * Here's how this is used: + *

+ * Let's say that on the first call to this method the component decides + * to save some state (because it is about to use the selection to show + * a drop index). It can return a state object to the caller encapsulating + * any saved selection state. On a second call, let's say the drop location + * is being changed to something else. The component doesn't need to + * restore anything yet, so it simply passes back the same state object + * to have the DnD system continue storing it. Finally, let's say this + * method is messaged with null. This means DnD + * is finished with this component for now, meaning it should restore + * state. At this point, it can use the state parameter to restore + * said state, and of course return null since there's + * no longer anything to store. + * + * @param location the drop location (as calculated by + * dropLocationForPoint) or null + * if there's no longer a valid drop location + * @param state the state object saved earlier for this component, + * or null + * @param forDrop whether or not the method is being called because an + * actual drop occurred + * @return any saved state for this component, or null if none + */ + Object setDropLocation(TransferHandler.DropLocation location, + Object state, + boolean forDrop) { + + Object retVal = null; + DropLocation treeLocation = (DropLocation)location; + + if (dropMode == DropMode.USE_SELECTION) { + if (treeLocation == null) { + if (!forDrop && state != null) { + setSelectionPaths(((TreePath[][])state)[0]); + setAnchorSelectionPath(((TreePath[][])state)[1][0]); + setLeadSelectionPath(((TreePath[][])state)[1][1]); + } + } else { + if (dropLocation == null) { + TreePath[] paths = getSelectionPaths(); + if (paths == null) { + paths = new TreePath[0]; + } + + retVal = new TreePath[][] {paths, + {getAnchorSelectionPath(), getLeadSelectionPath()}}; + } else { + retVal = state; + } + + setSelectionPath(treeLocation.getPath()); + } + } + + DropLocation old = dropLocation; + dropLocation = treeLocation; + firePropertyChange("dropLocation", old, dropLocation); + + return retVal; + } + + /** + * Called to indicate to this component that DnD is done. + * Allows for us to cancel the expand timer. + * @return + */ + public void dndDone() { + cancelDropTimer(); + dropTimer = null; + } + + /** + * Returns the location that this component should visually indicate + * as the drop location during a DnD operation over the component, + * or {@code null} if no location is to currently be shown. + *

+ * This method is not meant for querying the drop location + * from a {@code TransferHandler}, as the drop location is only + * set after the {@code TransferHandler}'s canImport + * has returned and has allowed for the location to be shown. + *

+ * When this property changes, a property change event with + * name "dropLocation" is fired by the component. + * + * @return the drop location + * @see #setDropMode + * @see TransferHandler#canImport(TransferHandler.TransferSupport) + * @since 1.6 + */ + public final DropLocation getDropLocation() { + return dropLocation; + } + + private void startDropTimer() { + if (dropTimer == null) { + dropTimer = new TreeTimer(); + } + dropTimer.start(); + } + + private void cancelDropTimer() { + if (dropTimer != null && dropTimer.isRunning()) { + expandRow = -1; + dropTimer.stop(); + } + } /** * Returns isEditable. This is invoked from the UI before diff --git a/sources/net.sf.j2s.java.core/src/javax/swing/JViewport.java b/sources/net.sf.j2s.java.core/src/javax/swing/JViewport.java index 77720aafd..20519f197 100644 --- a/sources/net.sf.j2s.java.core/src/javax/swing/JViewport.java +++ b/sources/net.sf.j2s.java.core/src/javax/swing/JViewport.java @@ -114,9 +114,14 @@ * @author Philip Milne * @see JScrollPane */ -public class JViewport extends JComponent +public class JViewport extends JComponent implements JSComponent.A2SComponentWrapper { - /** Property used to indicate window blitting should not be done. + + // BH for SwingJS + public void isWrapper$() {}; + + + /** Property used to indicate window blitting should not be done. */ static final Object EnableWindowBlit = "EnableWindowBlit"; diff --git a/sources/net.sf.j2s.java.core/src/swingjs/a2s/A2SContainer.java b/sources/net.sf.j2s.java.core/src/swingjs/a2s/A2SContainer.java index 79cb39765..02bce81d3 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/a2s/A2SContainer.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/a2s/A2SContainer.java @@ -1,5 +1,6 @@ package swingjs.a2s; +// Applet, Dialog, Frame public interface A2SContainer { public A2SListener getA2SListener(); diff --git a/sources/net.sf.j2s.java.core/src/swingjs/a2s/Dialog.java b/sources/net.sf.j2s.java.core/src/swingjs/a2s/Dialog.java index 92d856818..77593eaaa 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/a2s/Dialog.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/a2s/Dialog.java @@ -136,4 +136,5 @@ public A2SListener getA2SListener() { return listener; } + } diff --git a/sources/net.sf.j2s.java.core/src/swingjs/a2s/List.java b/sources/net.sf.j2s.java.core/src/swingjs/a2s/List.java index 0f884e7da..9a6187733 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/a2s/List.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/a2s/List.java @@ -2,6 +2,7 @@ import java.awt.AWTEvent; import java.awt.AWTEventMulticaster; +import java.awt.Component; import java.awt.Dimension; import java.awt.ItemSelectable; import java.awt.event.ActionEvent; @@ -13,12 +14,11 @@ import javax.swing.DefaultListModel; import javax.swing.JList; +import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.border.LineBorder; - -import com.sun.prism.paint.Color; - -public class List extends JList implements ItemSelectable { +import java.awt.JSComponent; +public class List extends JList implements ItemSelectable, JSComponent.A2SWrappedComponent { public void isAWT() {} // for SwingJS isAWT$ @@ -34,6 +34,10 @@ public void isAWT() {} // for SwingJS isAWT$ final static int DEFAULT_VISIBLE_ROWS = 4; + @Override + public Component getWrap$() { + return new JScrollPane(this); + } public List(int rows, boolean multipleMode) { this(); @@ -493,12 +497,12 @@ public Dimension getPreferredSize(int rows) { */ @Deprecated public Dimension preferredSize(int rows) { - synchronized (getTreeLock()) { +// synchronized (getTreeLock()) { ListPeer peer = (ListPeer)this.peer; - return (peer != null) ? - peer.getPreferredSize(rows) : - super.preferredSize(); - } + if (peer != null) + return peer.getPreferredSize(rows); + return preferredSize(); +// } } /** @@ -511,18 +515,21 @@ public Dimension getPreferredSize() { return preferredSize(); } - /** - * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). - */ - @Deprecated - public Dimension preferredSize() { - // synchronized (getTreeLock()) { - int rows = awtmodel.getSize(); - return (rows > 0) ? - preferredSize(rows) : - super.preferredSize(); - } + /** + * @deprecated As of JDK version 1.1, replaced by + * getPreferredSize(). + */ + @Deprecated + public Dimension preferredSize() { + // synchronized (getTreeLock()) { + int rows = awtmodel.getSize(); + if (rows > 0) { + ListPeer peer = (ListPeer) this.peer; + if (peer != null) + return peer.getPreferredSize(rows); + } + return super.preferredSize(); + } // } /** diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/ButtonListener.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/ButtonListener.java index 8d10d4e44..8a826ba80 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/ButtonListener.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/ButtonListener.java @@ -303,7 +303,7 @@ private static boolean checkHideMenus(AbstractButton b) { if (s == "MenuUI") return true; if (s.indexOf("MenuItemUI") >= 0) - JSComponentUI.hideAllMenus(); + JSComponentUI.hideMenusAndToolTip(); return false; } @@ -393,7 +393,7 @@ public void actionPerformed(ActionEvent e) { case SELECT: JMenu menu = getMenu(e); if (menu.isTopLevelMenu()) { - JSComponentUI.hideAllMenus(); + JSComponentUI.hideMenusAndToolTip(); JPopupMenu p = menu.getPopupMenu(); menu.setPopupMenuVisible(!p.isVisible()); return; diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSComponentUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSComponentUI.java index 80b562c92..a9da0c6b6 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSComponentUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSComponentUI.java @@ -15,6 +15,7 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; +import java.awt.Window; import java.awt.dnd.DropTarget; import java.awt.dnd.peer.DropTargetPeer; import java.awt.event.KeyEvent; @@ -571,6 +572,11 @@ public void setDraggable(JSFunction f) { protected static JQuery jquery = JSUtil.getJQuery(); + /** + * A static flag indicating that we have a menu open + */ + protected static boolean isMenuOpen; + /** * JavaScript menu timer id */ @@ -637,7 +643,7 @@ public void installJS() { */ private void uninstallJS() { - System.out.println("uninstallJS " + id); + //System.out.println("uninstallJS " + id); // window closing will fire this with c == null @@ -653,7 +659,7 @@ private void uninstallJS() { if (outerNode != null) { DOMNode.dispose(outerNode); outerNode = null; - } + } } protected JQueryObject $(Object node) { @@ -760,8 +766,9 @@ protected void ignoreAllMouseEvents(DOMNode node) { } @SuppressWarnings("unused") - protected static void hideAllMenus() { - JSUtil.jQuery.$(".ui-j2smenu").hide(); + protected static void hideMenusAndToolTip() { + if (isMenuOpen) + JSPopupMenuUI.closeAllMenus(); if (/** @j2sNative javax.swing.ToolTipManager ||*/false) ToolTipManager.j2sHideToolTip(); } @@ -1139,32 +1146,6 @@ private void updatePropertyAncestor(boolean fromButtonListener) { p = (JComponent) p.getParent(); } } - - -// -// @Override -// public void propertyChange(PropertyChangeEvent e) { -// // old -// String prop = e.getPropertyName(); -// if (prop == "ancestor") { -// JComponent p = (JComponent) jc.getParent(); -// while (p != null) { -// JSComponentUI parentui = (JSComponentUI) (p == null ? null : p.getUI()); -// if (parentui != null) -// parentui.setTainted(); -// p = (JComponent) p.getParent(); -// } -// -// if (e.getNewValue() == null) -// return; -// if (isDisposed && c.visible && e.getNewValue() != null) -// setVisible(true); -// } -// propertyChangedCUI(prop); -// } -// -// - @Override public void propertyChange(PropertyChangeEvent e) { @@ -1325,7 +1306,7 @@ protected void setMnemonic(int newValue) { * has been disposed; will need to reattach it if it ever becomes visible again. * */ - private boolean isDisposed; + public boolean isDisposed; /** * table cell renderer component @@ -2710,6 +2691,7 @@ public FontMetrics getFontMetrics(Font font) { @Override public void dispose() { + //System.out.println("JSCUI dispose " + id); if (isUIDisabled) return; if (cellComponent != null) { @@ -2717,6 +2699,8 @@ public void dispose() { return; } isDisposed = true; + // notice that we do not delete domNode, only detach it + // and remove its listeners. DOMNode.dispose(domNode); if (domNode != outerNode) DOMNode.dispose(outerNode); @@ -2728,19 +2712,22 @@ public void dispose() { * This control has been added back to some other node after being disposed of. * So now we need to undo that. * - * @param node + * @param nodef */ - private void undisposeUI(DOMNode node) { - if (c.getParent() != null) { + protected void undisposeUI(DOMNode node) { + Container parent = c.getParent(); + // node will be null for Window, including Dialog + if (node != null && parent != null) { JSComponentUI ui = (JSComponentUI) c.getParent().getUI(); if (ui.containerNode != null) appendChild(ui.containerNode, node); } - // menu separators have domNode == outerNode // cell renderers will set their domNode to null; - if (outerNode != null && domNode != null && domNode != outerNode) + if (outerNode != null && domNode != null && domNode != outerNode) { appendChild(outerNode, domNode); + //System.out.println("JSCUI undispose reattached"); + } isDisposed = false; } @@ -2971,8 +2958,7 @@ public Insets getInsets() { @Override public void beginValidate() { - // TODO Auto-generated method stub - + System.out.println("JSCUI beginValidate " + id); } @Override @@ -3178,7 +3164,15 @@ public void setRenderer(JSComponent rendererComponent, int width, int height) { public void reinstallUI(JComponent oldC, JComponent newC) { uninstallUI(oldC); uninstallJS(); - if (newC != null) { + if (newC== null) { +// // Frame or Dialog.dispose() +// if (outerNode != null) { +// DOMNode.dispose(outerNode); +// outerNode = null; +// domNode = null; +// isDisposed = true; +// } + } else { // JPopupMenu installJS(); installUI(newC); diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSFrameUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSFrameUI.java index 55bf50ec0..051b98a84 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSFrameUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSFrameUI.java @@ -89,7 +89,6 @@ public DOMNode updateDOMNode() { h = defaultHeight; DOMNode.setSize(frameNode, w, h); DOMNode.setTopLeftAbsolute(frameNode, 0, 0); - setJ2sMouseHandler(); titleBarNode = newDOMObject("div", id + "_titlebar"); DOMNode.setTopLeftAbsolute(titleBarNode, 0, 0); DOMNode.setStyles(titleBarNode, "background-color", "#E0E0E0", "height", "20px", "font-size", "14px", @@ -106,12 +105,13 @@ public DOMNode updateDOMNode() { DOMNode.setTopLeftAbsolute(closerWrap, 0, 0); DOMNode.setStyles(closerWrap, "text-align", "right"); - closerNode = newDOMObject("label", id + "_closer", "innerHTML", "X"); - DOMNode.setStyles(closerNode, "width", "20px", "height", "20px", "position", "absolute", "text-align", - "center", "right", "0px"); - bindJQueryEvents(closerNode, "click mouseenter mouseout", SOME_MOUSE_EVENT); - if (!frame.isUndecorated()) + if (!frame.isUndecorated()) { + closerNode = newDOMObject("label", id + "_closer", "innerHTML", "X"); + DOMNode.setStyles(closerNode, "width", "20px", "height", "20px", "position", "absolute", "text-align", + "center", "right", "0px"); frameNode.appendChild(titleBarNode); + } + bindWindowEvents(); if (isModal) { modalNode = DOMNode.createElement("div", id + "_modaldiv"); Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); @@ -177,7 +177,7 @@ public DOMNode updateDOMNode() { * referenced by j2sNative, above */ /*not private*/ void hideMenu() { - hideAllMenus(); + hideMenusAndToolTip(); } @@ -332,18 +332,20 @@ public void propertyChange(PropertyChangeEvent e) { public void setVisible(boolean b) { if (isDummyFrame) b = false; - super.setVisible(b); - if (isModal) { - if (b) { - $(body).after(modalNode); - addClass(modalNode, "swingjs-window"); // so as to slip into z-index ranking - String sz = DOMNode.getStyle(domNode, "z-index"); - int z = (( /** @j2sNative +sz || */getZIndex(null))) - 1; - DOMNode.setZ(modalNode, z); - } - DOMNode.setVisible(modalNode, b); - } - DOMNode.setVisible(domNode, b); + super.setVisible(b); + if (isModal) { + if (b) { + $(body).after(modalNode); + addClass(modalNode, "swingjs-window"); // so as to slip into z-index ranking + @SuppressWarnings("unused") + String sz = DOMNode.getStyle(domNode, "z-index"); + int z = (( /** @j2sNative +sz || */ + getZIndex(null))) - 1; + DOMNode.setZ(modalNode, z); + } + DOMNode.setVisible(modalNode, b); + } + DOMNode.setVisible(domNode, b); } } diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSInternalFrameUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSInternalFrameUI.java index 72854ace3..4ff333d0a 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSInternalFrameUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSInternalFrameUI.java @@ -461,7 +461,7 @@ public void windowGainedFocus(WindowEvent e) { @Override public void windowLostFocus(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); // Cancel a resize which may be in progress, when a // WINDOW_LOST_FOCUS event occurs, which may be // caused by an Alt-Tab or a modal dialog popup. @@ -471,7 +471,7 @@ public void windowLostFocus(WindowEvent e) { // InternalFrameListener @Override public void internalFrameClosed(InternalFrameEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); iframe.removeInternalFrameListener(getHandler()); } @@ -494,13 +494,13 @@ public void internalFrameDeactivated(InternalFrameEvent e) { } @Override - public void internalFrameClosing(InternalFrameEvent e) { hideAllMenus(); } + public void internalFrameClosing(InternalFrameEvent e) { hideMenusAndToolTip(); } @Override - public void internalFrameOpened(InternalFrameEvent e) { hideAllMenus();} + public void internalFrameOpened(InternalFrameEvent e) { hideMenusAndToolTip();} @Override - public void internalFrameIconified(InternalFrameEvent e) { hideAllMenus();} + public void internalFrameIconified(InternalFrameEvent e) { hideMenusAndToolTip();} @Override - public void internalFrameDeiconified(InternalFrameEvent e) { hideAllMenus();} + public void internalFrameDeiconified(InternalFrameEvent e) { hideMenusAndToolTip();} diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java index 12d42aaa4..00eeb3b4f 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java @@ -118,16 +118,10 @@ public class JSListUI extends JSLightweightUI //true, but unnecessary implements String itemHTML = null; - private JScrollPane scrollPane; - @Override public DOMNode updateDOMNode() { list = (JList) jc; if (domNode == null) { - - - /**@j2sNative xxL = this.jc; */ - focusNode = enableNode = newDOMObject("div", id); // maybe DOMNode.setAttrInt(domNode, "tabIndex", 1); @@ -143,15 +137,16 @@ public DOMNode updateDOMNode() { fillDOM(); } - if (isAWT && scrollPane == null && list.getParent() != null) { - JComponent parent = (JComponent) list.getParent(); - scrollPane = new JScrollPane(); - scrollPane.getViewport().setView(list); - parent.add(scrollPane); - } return updateDOMNodeCUI(); } + @Override + protected void undisposeUI(DOMNode node) { + super.undisposeUI(node); + bindJSKeyEvents(focusNode, true); + } + + @Override public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { switch (eventType) { @@ -2245,7 +2240,7 @@ private void changeSelection(JList list, int type, int index, int direction) { type = CHANGE_SELECTION; } - // IMPORTANT - This needs to happen before the index is changed. + // importANT - This needs to happen before the index is changed. // This is because JFileChooser, which uses JList, also scrolls // the selected item into view. If that happens first, then // this method becomes a no-op. diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSMenuUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSMenuUI.java index ca52654fd..fc41c8bf9 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSMenuUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSMenuUI.java @@ -8,6 +8,7 @@ import javax.swing.JMenu; import javax.swing.UIManager; +import swingjs.JSUtil; import swingjs.api.js.DOMNode; public class JSMenuUI extends JSMenuItemUI { @@ -51,28 +52,6 @@ public DOMNode updateDOMNode() { return domNode; } -// @Override -// public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { -// System.out.println("JSMenuUI this is not working, right? ");// RIGHT -// // we use == here because this will be JavaScript -// if (target == domNode && eventType == -1) { -// String type = (/** @j2sNative jQueryEvent.type || */ ""); -// if (type.equals("mouseenter")) { -// if (!jm.getParent().getUIClassID().equals("MenuBarUI")) -// stopPopupMenuTimer(); -// jm.setSelected(true); -// return HANDLED; -// } -// if (type.equals("mouseleave")) { -// jm.setSelected(false); -// if (jm.getParent().getUIClassID().equals("MenuBarUI")) -// startPopupMenuTimer(); -// return HANDLED; -// } -// } -// return super.handleJSEvent(target, eventType, jQueryEvent); -// } - @Override public void propertyChangedFromListener(PropertyChangeEvent e, String prop) { // System.out.println("JSMenuUI prop = " + prop + " " + jm.getText()); diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSPopupMenuUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSPopupMenuUI.java index 53eea3620..5217a7083 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSPopupMenuUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSPopupMenuUI.java @@ -183,6 +183,7 @@ public void setVisible(boolean b) { // TODO: We are not setting vis false when closing //if (b && menu != null && menu.isVisible()) //b = false; + closeAllMenus(); if (b) { if (isTainted || menu == null || outerNode == null || DOMNode.firstChild(outerNode) == null) { if (menu == null) { @@ -201,8 +202,7 @@ public void setVisible(boolean b) { int x = /** @j2sNative this.menu.desiredLocationX || */0; int y = /** @j2sNative this.menu.desiredLocationY || */0; j2sSwingMenu.showMenu(menu, x, y); - } else { - hideAllMenus(); +// } else { // hideMenu(); } } @@ -507,7 +507,7 @@ public void menuKeyPressed(MenuKeyEvent e) { } else if (item instanceof JMenuItem) { ((JMenuItem) item).doClick(); e.consume(); - hideAllMenus(); + hideMenusAndToolTip(); } } @@ -1134,6 +1134,11 @@ public boolean isJSPopupVisible() { private static int np=0; + /** + * from j2sMenu.js + * + * @param data + */ @SuppressWarnings("unused") public static void processJ2SMenuCmd(Object[] data) { String trigger = (String) data[0]; @@ -1146,16 +1151,18 @@ public static void processJ2SMenuCmd(Object[] data) { System.out.println("JSPopupMenuUI processing " + (np++) + " " + trigger + " for " + mid); switch (trigger) { case "_activate": - case "_close": + case "_closeSubmenus": case "_hide": - case "_open": + case "_move": + case "_openSubmenu": case "_show": case "_startOpening": case "blur": + case "clearOut": case "collapse": case "expand": - case "focus": case "keyActivate": + case "noclickout": case "onblur": case "onclick": case "onclick_out": @@ -1166,11 +1173,16 @@ public static void processJ2SMenuCmd(Object[] data) { case "onover2": case "onover3": case "onpress": + case "onrelease": case "refresh": case "select": break; + case "focus": + isMenuOpen = true; + break; case "collapseAll": - hideAllMenus(); + closeAllMenus(); + isMenuOpen = false; j2smenu.options.jPopupMenu.visible = false; ((JComponent) j2smenu.options.jPopupMenu.getInvoker()).getRootPane().requestFocus(); break; @@ -1180,5 +1192,15 @@ public static void processJ2SMenuCmd(Object[] data) { public boolean isPopupTrigger(MouseEvent e) { return e.isPopupTrigger(); } + + public static void closeAllMenus() { + if (isMenuOpen) { + // top-level or submenu: + JSUtil.jQuery.$(".ui-j2smenu").hide(); + JSUtil.jQuery.$(".ui-j2smenu-node").removeClass("ui-state-active").removeClass("ui-state-focus"); + } + } + + } diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextFieldUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextFieldUI.java index 013e0f060..760579417 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextFieldUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextFieldUI.java @@ -41,6 +41,12 @@ public DOMNode updateDOMNode() { return super.updateDOMNode(); } + @Override + protected void undisposeUI(DOMNode node) { + super.undisposeUI(node); + bindJSKeyEvents(focusNode, true); + } + @Override protected Dimension getCSSAdjustment(boolean addingCSS) { return new Dimension(0, addingCSS ? 0 : -2); diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextViewUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextViewUI.java index 857b18a88..2632ddab1 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextViewUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextViewUI.java @@ -30,9 +30,16 @@ protected void setupViewNode() { focusNode = enableNode = textNode = domNode; DOMNode.setStyles(domNode, "resize", "none", "margin", "0px", "padding", "0px","scrollbar-width", "thin"); // otherwise it overflows DOMNode.setStyles(domNode, "box-sizing", "border-box"); - bindJSKeyEvents(domNode, true); + bindJSKeyEvents(focusNode, true); } + @Override + protected void undisposeUI(DOMNode node) { + super.undisposeUI(node); + bindJSKeyEvents(focusNode, true); + } + + // AS_NEEDED NEVER ALWAYS private final String[] overflows = new String[] { "auto", "hidden", "scroll" }; diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSWindowUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSWindowUI.java index 75f8bb536..4a013d541 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSWindowUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSWindowUI.java @@ -15,6 +15,7 @@ import java.awt.image.BufferedImage; import java.awt.peer.WindowPeer; +import javax.swing.JComponent; import javax.swing.JWindow; import swingjs.JSAppletViewer; @@ -83,6 +84,7 @@ public DOMNode updateDOMNode() { if (domNode == null) { containerNode = domNode = newDOMObject("div", id); setWindowClass(); + bindWindowEvents(); } return domNode; } @@ -202,10 +204,46 @@ public void repositionSecurityWarning() { @Override public void dispose() { + System.out.println("window disposed"); J2S.unsetMouse(domNode); - DOMNode.dispose(outerNode); if (modalNode != null) DOMNode.dispose(modalNode); + super.dispose(); + } + + @Override + public void beginValidate() { + if (isDisposed) { + setChildVisibilities(window); + } + } + + @Override + public void endValidate() { + if (isDisposed) { + undisposeUI(null); + bindWindowEvents(); + isDisposed = false; + } + } + + protected void bindWindowEvents() { + setJ2sMouseHandler(); + if (closerNode != null) + bindJQueryEvents(closerNode, "click mouseenter mouseout", SOME_MOUSE_EVENT); + } + + private static void setChildVisibilities(JComponent jc) { + for (int i = jc.getComponentCount(); --i >= 0;) { + JComponent c = (JComponent) jc.getComponent(i); + setChildVisibilities(c); + } + JSComponentUI ui = (JSComponentUI) jc.ui; +// ui.isTainted = true; +// ui.domNode = null; +// ui.updateDOMNode(); + if (jc.isVisible()) + ui.setVisible(true); } @Override @@ -216,7 +254,7 @@ public Insets getInsets() { @Override public void setVisible(boolean b) { if (!isPopup) - hideAllMenus(); + hideMenusAndToolTip(); super.setVisible(b); } @@ -231,25 +269,25 @@ public void windowOpened(WindowEvent e) { @Override public void windowClosing(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void windowClosed(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void windowIconified(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void windowDeiconified(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @@ -262,31 +300,31 @@ public void windowActivated(WindowEvent e) { @Override public void windowDeactivated(WindowEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void componentResized(ComponentEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void componentMoved(ComponentEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void componentShown(ComponentEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } @Override public void componentHidden(ComponentEvent e) { - hideAllMenus(); + hideMenusAndToolTip(); } } diff --git a/sources/net.sf.j2s.java.core/src/test/JalviewJSTest.java b/sources/net.sf.j2s.java.core/src/test/JalviewJSTest.java index be6075f8e..c68d0db39 100644 --- a/sources/net.sf.j2s.java.core/src/test/JalviewJSTest.java +++ b/sources/net.sf.j2s.java.core/src/test/JalviewJSTest.java @@ -34,6 +34,7 @@ import javax.swing.JPopupMenu; import javax.swing.JRadioButton; import javax.swing.JRadioButtonMenuItem; +import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; @@ -59,7 +60,14 @@ public static void main(String[] args) { private JMenuItem testbtn; JMenuBar mb = new JMenuBar(); - JFrame frame = new JFrame("JalviewJSTest"); + JFrame frame = new JFrame("JalviewJSTest") { + + public void invalidate() { + System.out.println("frame invalidate"); + super.invalidate(); + } + + }; JMenu mRight = new JMenu("right") { @Override public void processKeyEvent(KeyEvent e, MenuElement[] path, MenuSelectionManager m) { @@ -174,8 +182,9 @@ public void keyReleased(KeyEvent e) { @Override public void mouseClicked(MouseEvent e) { - System.out.println(menu.getHeight() + " " + menu.getMargin()); - + frame.dispose(); + System.out.println("frame after dispose " + frame.isValid()); + frame.show(); } @@ -248,6 +257,18 @@ Container getVisualPaneContent(JMenu menu, JMenu menu1, JMenu menu2) { firstColumn.setLayout(new GridLayout(13, 1)); firstColumn.setBorder(new TitledBorder("column 1")); + JTextField t1 = new JTextField("testing"); + t1.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("t1 is " + t1.getText()); + } + + }); + + + JLabel l1 = new JLabel(getImage("test2.png")); l1.setText("trailing right"); l1.setHorizontalTextPosition(SwingConstants.TRAILING); @@ -298,6 +319,7 @@ Container getVisualPaneContent(JMenu menu, JMenu menu1, JMenu menu2) { rb3.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); rb3.setHorizontalTextPosition(SwingConstants.RIGHT); + firstColumn.add(t1); firstColumn.add(l1); firstColumn.add(l2); firstColumn.add(b1); @@ -315,7 +337,7 @@ Container getVisualPaneContent(JMenu menu, JMenu menu1, JMenu menu2) { cb3m.setHorizontalTextPosition(SwingConstants.LEADING); cb3m.addActionListener(listener); - JCheckBoxMenuItem cb4m = new JCheckBoxMenuItem("XXleading,right-to-leftXX") { + JCheckBoxMenuItem cb4m = new JCheckBoxMenuItem("CB4XXleading,right-to-leftXX") { @Override public void doClick() { super.doClick();