methods = cache.cache.get(method);
if (methods != null) methodSearch: for (Method m : methods) {
{ if (!(m.isVarArgs())) continue; }
Object[] newArgs = massageArgsForVarArgsCall(m, args);
if (newArgs != null)
return invokeMethod(m, o, newArgs);
}
return null;
}
} catch (Exception __e) { throw rethrow(__e); } }
static double toDouble(Object o) {
if (o instanceof Number)
return ((Number) o).doubleValue();
if (o instanceof BigInteger)
return ((BigInteger) o).doubleValue();
if (o instanceof String)
return parseDouble((String) o);
if (o == null) return 0.0;
throw fail(o);
}
static String dropSuffix(String suffix, String s) {
return nempty(suffix) && endsWith(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static double parseDouble(String s) {
return empty(s) ? 0.0 : Double.parseDouble(s);
}
final static class Rect implements IFieldsToList{
static final String _fieldOrder = "x y w h";
int x;
int y;
int w;
int h;
Rect() {}
Rect(int x, int y, int w, int h) {
this.h = h;
this.w = w;
this.y = y;
this.x = x;}
public boolean equals(Object o) {
if (!(o instanceof Rect)) return false;
Rect __1 = (Rect) o;
return x == __1.x && y == __1.y && w == __1.w && h == __1.h;
}
public int hashCode() {
int h = 2543108;
h = boostHashCombine(h, _hashCode(x));
h = boostHashCombine(h, _hashCode(y));
h = boostHashCombine(h, _hashCode(w));
h = boostHashCombine(h, _hashCode(h));
return h;
}
public Object[] _fieldsToList() { return new Object[] {x, y, w, h}; }
Rect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
Rect(Pt p, int w, int h) {
this.h = h;
this.w = w; x = p.x; y = p.y; }
Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; }
Rectangle getRectangle() {
return new Rectangle(x, y, w, h);
}
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
int x1() { return x; }
int y1() { return y; }
int x2() { return x + w; }
int y2() { return y + h; }
boolean contains(Pt p) {
return contains(p.x, p.y);
}
boolean contains(int _x, int _y) {
return _x >= x && _y >= y && _x < x+w && _y < y+h;
}
boolean contains(Rectangle r) {
return rectContains(this, r);
}
boolean empty() { return w <= 0 || h <= 0; }
int getWidth() { return w; }
int getHeight() { return h; }
}
/**
* A class that provides scrolling capabilities to a long menu dropdown or
* popup menu. A number of items can optionally be frozen at the top and/or
* bottom of the menu.
*
* Implementation note: The default number of items to display
* at a time is 15, and the default scrolling interval is 125 milliseconds.
*
*
* @version 1.5.0 04/05/12
* @author Darryl
* https://tips4java.wordpress.com/2009/02/01/menu-scroller/
*/
static class JMenuScroller {
VF1 fillMenu;
private JPopupMenu menu;
private Component[] menuItems;
private MenuScrollItem upItem;
private MenuScrollItem downItem;
private final MenuScrollListener menuListener = new MenuScrollListener();
private int scrollCount;
private int interval;
private int topFixedCount;
private int bottomFixedCount;
private int firstIndex = 0;
private int keepVisibleIndex = -1;
/**
* Registers a menu to be scrolled with the default number of items to
* display at a time and the default scrolling interval.
*
* @param menu the menu
* @return the JMenuScroller
*/
public static JMenuScroller setScrollerFor(JMenu menu) {
return new JMenuScroller(menu);
}
/**
* Registers a popup menu to be scrolled with the default number of items to
* display at a time and the default scrolling interval.
*
* @param menu the popup menu
* @return the JMenuScroller
*/
public static JMenuScroller setScrollerFor(JPopupMenu menu) {
return new JMenuScroller(menu);
}
/**
* Registers a menu to be scrolled with the default number of items to
* display at a time and the specified scrolling interval.
*
* @param menu the menu
* @param scrollCount the number of items to display at a time
* @return the JMenuScroller
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount) {
return new JMenuScroller(menu, scrollCount);
}
/**
* Registers a popup menu to be scrolled with the default number of items to
* display at a time and the specified scrolling interval.
*
* @param menu the popup menu
* @param scrollCount the number of items to display at a time
* @return the JMenuScroller
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount) {
return new JMenuScroller(menu, scrollCount);
}
/**
* Registers a menu to be scrolled, with the specified number of items to
* display at a time and the specified scrolling interval.
*
* @param menu the menu
* @param scrollCount the number of items to be displayed at a time
* @param interval the scroll interval, in milliseconds
* @return the JMenuScroller
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount, int interval) {
return new JMenuScroller(menu, scrollCount, interval);
}
/**
* Registers a popup menu to be scrolled, with the specified number of items to
* display at a time and the specified scrolling interval.
*
* @param menu the popup menu
* @param scrollCount the number of items to be displayed at a time
* @param interval the scroll interval, in milliseconds
* @return the JMenuScroller
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount, int interval) {
return new JMenuScroller(menu, scrollCount, interval);
}
/**
* Registers a menu to be scrolled, with the specified number of items
* to display in the scrolling region, the specified scrolling interval,
* and the specified numbers of items fixed at the top and bottom of the
* menu.
*
* @param menu the menu
* @param scrollCount the number of items to display in the scrolling portion
* @param interval the scroll interval, in milliseconds
* @param topFixedCount the number of items to fix at the top. May be 0.
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
* negative or if topFixedCount or bottomFixedCount is negative
* @return the JMenuScroller
*/
public static JMenuScroller setScrollerFor(JMenu menu, int scrollCount, int interval,
int topFixedCount, int bottomFixedCount) {
return new JMenuScroller(menu, scrollCount, interval,
topFixedCount, bottomFixedCount);
}
/**
* Registers a popup menu to be scrolled, with the specified number of items
* to display in the scrolling region, the specified scrolling interval,
* and the specified numbers of items fixed at the top and bottom of the
* popup menu.
*
* @param menu the popup menu
* @param scrollCount the number of items to display in the scrolling portion
* @param interval the scroll interval, in milliseconds
* @param topFixedCount the number of items to fix at the top. May be 0
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
* negative or if topFixedCount or bottomFixedCount is negative
* @return the JMenuScroller
*/
public static JMenuScroller setScrollerFor(JPopupMenu menu, int scrollCount, int interval,
int topFixedCount, int bottomFixedCount) {
return new JMenuScroller(menu, scrollCount, interval,
topFixedCount, bottomFixedCount);
}
/**
* Constructs a JMenuScroller
that scrolls a menu with the
* default number of items to display at a time, and default scrolling
* interval.
*
* @param menu the menu
*/
public JMenuScroller(JMenu menu) {
this(menu, 15);
}
/**
* Constructs a JMenuScroller
that scrolls a popup menu with the
* default number of items to display at a time, and default scrolling
* interval.
*
* @param menu the popup menu
*/
public JMenuScroller(JPopupMenu menu) {
this(menu, 15);
}
/**
* Constructs a JMenuScroller
that scrolls a menu with the
* specified number of items to display at a time, and default scrolling
* interval.
*
* @param menu the menu
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
public JMenuScroller(JMenu menu, int scrollCount) {
this(menu, scrollCount, 150);
}
/**
* Constructs a JMenuScroller
that scrolls a popup menu with the
* specified number of items to display at a time, and default scrolling
* interval.
*
* @param menu the popup menu
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
public JMenuScroller(JPopupMenu menu, int scrollCount) {
this(menu, scrollCount, 150);
}
/**
* Constructs a JMenuScroller
that scrolls a menu with the
* specified number of items to display at a time, and specified scrolling
* interval.
*
* @param menu the menu
* @param scrollCount the number of items to display at a time
* @param interval the scroll interval, in milliseconds
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public JMenuScroller(JMenu menu, int scrollCount, int interval) {
this(menu, scrollCount, interval, 0, 0);
}
/**
* Constructs a JMenuScroller
that scrolls a popup menu with the
* specified number of items to display at a time, and specified scrolling
* interval.
*
* @param menu the popup menu
* @param scrollCount the number of items to display at a time
* @param interval the scroll interval, in milliseconds
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public JMenuScroller(JPopupMenu menu, int scrollCount, int interval) {
this(menu, scrollCount, interval, 0, 0);
}
/**
* Constructs a JMenuScroller
that scrolls a menu with the
* specified number of items to display in the scrolling region, the
* specified scrolling interval, and the specified numbers of items fixed at
* the top and bottom of the menu.
*
* @param menu the menu
* @param scrollCount the number of items to display in the scrolling portion
* @param interval the scroll interval, in milliseconds
* @param topFixedCount the number of items to fix at the top. May be 0
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
* negative or if topFixedCount or bottomFixedCount is negative
*/
public JMenuScroller(JMenu menu, int scrollCount, int interval,
int topFixedCount, int bottomFixedCount) {
this(menu.getPopupMenu(), scrollCount, interval, topFixedCount, bottomFixedCount);
}
/**
* Constructs a JMenuScroller
that scrolls a popup menu with the
* specified number of items to display in the scrolling region, the
* specified scrolling interval, and the specified numbers of items fixed at
* the top and bottom of the popup menu.
*
* @param menu the popup menu
* @param scrollCount the number of items to display in the scrolling portion
* @param interval the scroll interval, in milliseconds
* @param topFixedCount the number of items to fix at the top. May be 0
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
* negative or if topFixedCount or bottomFixedCount is negative
*/
public JMenuScroller(JPopupMenu menu, int scrollCount, int interval,
int topFixedCount, int bottomFixedCount) {
if (scrollCount <= 0 || interval <= 0) {
throw new IllegalArgumentException("scrollCount and interval must be greater than 0");
}
if (topFixedCount < 0 || bottomFixedCount < 0) {
throw new IllegalArgumentException("topFixedCount and bottomFixedCount cannot be negative");
}
upItem = new MenuScrollItem(UP, -1);
downItem = new MenuScrollItem(DOWN, +1);
setScrollCount(scrollCount);
setInterval(interval);
setTopFixedCount(topFixedCount);
setBottomFixedCount(bottomFixedCount);
this.menu = menu;
menu.addPopupMenuListener(menuListener);
}
/**
* Returns the scroll interval in milliseconds
*
* @return the scroll interval in milliseconds
*/
public int getInterval() {
return interval;
}
/**
* Sets the scroll interval in milliseconds
*
* @param interval the scroll interval in milliseconds
* @throws IllegalArgumentException if interval is 0 or negative
*/
public void setInterval(int interval) {
if (interval <= 0) {
throw new IllegalArgumentException("interval must be greater than 0");
}
upItem.setInterval(interval);
downItem.setInterval(interval);
this.interval = interval;
}
/**
* Returns the number of items in the scrolling portion of the menu.
*
* @return the number of items to display at a time
*/
public int getscrollCount() {
return scrollCount;
}
/**
* Sets the number of items in the scrolling portion of the menu.
*
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
public void setScrollCount(int scrollCount) {
if (scrollCount <= 0) {
throw new IllegalArgumentException("scrollCount must be greater than 0");
}
this.scrollCount = scrollCount;
// XXX the following line closes all menus then this menu is made.
// That doesn't seem right.
// MenuSelectionManager.defaultManager().clearSelectedPath();
}
/**
* Returns the number of items fixed at the top of the menu or popup menu.
*
* @return the number of items
*/
public int getTopFixedCount() {
return topFixedCount;
}
/**
* Sets the number of items to fix at the top of the menu or popup menu.
*
* @param topFixedCount the number of items
*/
public void setTopFixedCount(int topFixedCount) {
if (firstIndex <= topFixedCount) {
firstIndex = topFixedCount;
} else {
firstIndex += (topFixedCount - this.topFixedCount);
}
this.topFixedCount = topFixedCount;
}
/**
* Returns the number of items fixed at the bottom of the menu or popup menu.
*
* @return the number of items
*/
public int getBottomFixedCount() {
return bottomFixedCount;
}
/**
* Sets the number of items to fix at the bottom of the menu or popup menu.
*
* @param bottomFixedCount the number of items
*/
public void setBottomFixedCount(int bottomFixedCount) {
this.bottomFixedCount = bottomFixedCount;
}
/**
* Scrolls the specified item into view each time the menu is opened. Call this method with
* null
to restore the default behavior, which is to show the menu as it last
* appeared.
*
* @param item the item to keep visible
* @see #keepVisible(int)
*/
public void keepVisible(JMenuItem item) {
if (item == null) {
keepVisibleIndex = -1;
} else {
int index = menu.getComponentIndex(item);
keepVisibleIndex = index;
}
}
/**
* Scrolls the item at the specified index into view each time the menu is opened. Call this
* method with -1
to restore the default behavior, which is to show the menu as
* it last appeared.
*
* @param index the index of the item to keep visible
* @see #keepVisible(javax.swing.JMenuItem)
*/
public void keepVisible(int index) {
keepVisibleIndex = index;
}
/**
* Removes this JMenuScroller from the associated menu and restores the
* default behavior of the menu.
*/
public void dispose() {
if (menu != null) {
menu.removePopupMenuListener(menuListener);
menu = null;
}
}
/**
* Ensures that the dispose
method of this JMenuScroller is
* called when there are no more refrences to it.
*
* @exception Throwable if an error occurs.
* @see JMenuScroller#dispose()
*/
@Override
public void finalize() throws Throwable {
dispose();
}
private void refreshMenu() {
if (menuItems != null && menuItems.length > 0) {
firstIndex = Math.max(topFixedCount, firstIndex);
firstIndex = Math.min(menuItems.length - bottomFixedCount - scrollCount, firstIndex);
upItem.setEnabled(firstIndex > topFixedCount);
downItem.setEnabled(firstIndex + scrollCount < menuItems.length - bottomFixedCount);
menu.removeAll();
for (int i = 0; i < topFixedCount; i++) {
menu.add(menuItems[i]);
}
if (topFixedCount > 0) {
menu.addSeparator();
}
menu.add(upItem);
for (int i = firstIndex; i < scrollCount + firstIndex; i++) {
menu.add(menuItems[i]);
}
menu.add(downItem);
if (bottomFixedCount > 0) {
menu.addSeparator();
}
for (int i = menuItems.length - bottomFixedCount; i < menuItems.length; i++) {
menu.add(menuItems[i]);
}
JComponent parent = (JComponent) upItem.getParent();
parent.revalidate();
parent.repaint();
}
}
private class MenuScrollListener implements PopupMenuListener {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
if (fillMenu != null) {
clearPopupMenu(menu);
callF(fillMenu, menu);
}
setMenuItems();
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
if (fillMenu != null) clearPopupMenu(menu);
else restoreMenuItems();
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
if (fillMenu != null) clearPopupMenu(menu);
else restoreMenuItems();
}
private void setMenuItems() {
menuItems = menu.getComponents();
if (keepVisibleIndex >= topFixedCount
&& keepVisibleIndex <= menuItems.length - bottomFixedCount
&& (keepVisibleIndex > firstIndex + scrollCount
|| keepVisibleIndex < firstIndex)) {
firstIndex = Math.min(firstIndex, keepVisibleIndex);
firstIndex = Math.max(firstIndex, keepVisibleIndex - scrollCount + 1);
}
if (menuItems.length > topFixedCount + scrollCount + bottomFixedCount) {
refreshMenu();
}
}
private void restoreMenuItems() {
menu.removeAll();
for (Component component : menuItems) {
menu.add(component);
}
}
}
private class MenuScrollTimer extends javax.swing.Timer {
public MenuScrollTimer(final int increment, int interval) {
super(interval, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
firstIndex += increment;
refreshMenu();
}
});
}
}
private class MenuScrollItem extends JMenuItem
implements ChangeListener {
private MenuScrollTimer timer;
public MenuScrollItem(MenuIcon icon, int increment) {
setIcon(icon);
setDisabledIcon(icon);
timer = new MenuScrollTimer(increment, interval);
addChangeListener(this);
}
public void setInterval(int interval) {
timer.setDelay(interval);
}
@Override
public void stateChanged(ChangeEvent e) {
if (isArmed() && !timer.isRunning()) {
timer.start();
}
if (!isArmed() && timer.isRunning()) {
timer.stop();
}
}
}
static MenuIcon UP = new MenuIcon(9, 1, 9);
static MenuIcon DOWN = new MenuIcon(1, 9, 1);
private static class MenuIcon implements Icon {
final int[] xPoints = {1, 5, 9};
final int[] yPoints;
MenuIcon(int... yPoints) {
this.yPoints = yPoints;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Dimension size = c.getSize();
Graphics g2 = g.create(size.width / 2 - 5, size.height / 2 - 5, 10, 10);
g2.setColor(Color.GRAY);
g2.drawPolygon(xPoints, yPoints, 3);
if (c.isEnabled()) {
g2.setColor(Color.BLACK);
g2.fillPolygon(xPoints, yPoints, 3);
}
g2.dispose();
}
@Override
public int getIconWidth() {
return 0;
}
@Override
public int getIconHeight() {
return 10;
}
}
}
static class Pt implements Comparable, IDoublePt {
int x, y;
Pt() {}
Pt(Point p) {
x = p.x;
y = p.y;
}
Pt(int x, int y) {
this.y = y;
this.x = x;}
Point getPoint() {
return new Point(x, y);
}
public boolean equals(Object o) {
return o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y;
}
public int hashCode() {
return boostHashCombine(x, y);
}
// compare in scan order
public int compareTo(Pt p) {
if (y != p.y) return cmp(y, p.y);
return cmp(x, p.x);
}
public String toString() {
return x + ", " + y;
}
double length() { return sqrt(x*x+y*y); }
Pt minus(Pt p) { return ptMinus(this, p); }
public double x_double() { return x; }
public double y_double() { return y; }
}
// a variant of thread where you can get the Runnable target later.
// Also notes its existence on the VM bus.
// We should use this exclusively instead of Thread.
static class BetterThread extends Thread {
Runnable target;
BetterThread(Runnable target) {
this.target = target; _created(); }
BetterThread(Runnable target, String name) { super(name);
this.target = target; _created(); }
void _created() { vmBus_send("threadCreated", this); }
public void run() { try {
try {
vmBus_send("threadStarted", this);
if (target != null) target.run();
} finally {
vmBus_send("threadEnded", this);
}
} catch (Exception __e) { throw rethrow(__e); } }
Runnable getTarget() { return target; }
}
interface IDoublePt {
public double x_double();
public double y_double();
}
static int boostHashCombine(int a, int b) {
return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2));
}
static void clearPopupMenu(final JPopupMenu menu) {
if (menu != null) { swing(() -> { menu.removeAll(); }); }
}
static double sqrt(double x) {
return Math.sqrt(x);
}
static List minus(Collection a, Object... b) {
Set set = asSet(b);
List l = new ArrayList();
for (Object s : unnull(a))
if (!set.contains(s))
l.add(s);
return l;
}
static BigInteger minus(BigInteger a, BigInteger b) {
return a.subtract(b);
}
static Complex minus(Complex c) {
return c == null ? null : complex(-c.re(), -c.im());
}
static Pt ptMinus(Pt a, Pt b) {
if (b == null) return a;
return new Pt(a.x-b.x, a.y-b.y);
}
static Set asSet(Object[] array) {
HashSet set = new HashSet();
for (Object o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(String[] array) {
TreeSet set = new TreeSet();
for (String o : array)
if (o != null)
set.add(o);
return set;
}
static Set asSet(Iterable l) {
if (l instanceof Set) return (Set) l;
HashSet set = new HashSet();
for (A o : unnull(l))
if (o != null)
set.add(o);
return set;
}
static Complex complex(double re, double im) {
return new Complex(re, im);
}
static Complex complex(double re) {
return new Complex(re, 0.0);
}
static Complex complex(double[] reIm) {
if (empty(reIm)) return null;
if (l(reIm) != 2) throw fail("Need 2 doubles to make complex number");
return complex(reIm[0], reIm[1]);
}
static class Complex implements IFieldsToList{
static final String _fieldOrder = "re im";
double re;
double im;
Complex() {}
Complex(double re, double im) {
this.im = im;
this.re = re;}
public boolean equals(Object o) {
if (!(o instanceof Complex)) return false;
Complex __1 = (Complex) o;
return re == __1.re && im == __1.im;
}
public int hashCode() {
int h = -1679819632;
h = boostHashCombine(h, _hashCode(re));
h = boostHashCombine(h, _hashCode(im));
return h;
}
public Object[] _fieldsToList() { return new Object[] {re, im}; }
double abs() { return sqrt(re*re+im*im); }
double re() { return re; }
double im() { return im; }
final double angle(){ return phase(); }
double phase() { return Math.atan2(im, re); }
double fracAngle() { return fracNonNeg(angle()/twoPi()); } // angle as 0 to 1
public String toString() {
if (im != 0)
return re == 0 ? im + "i" : re + plusPrefixUnlessMinus(str(im)) + "i";
else
return str(re);
}
}
static double fracNonNeg(double d) {
return frac_nonNeg(d);
}
static double twoPi() {
return Math.PI*2;
}
static String plusPrefixUnlessMinus(String s) {
return startsWith(s, "-") ? s : "+" + s;
}
static double frac_nonNeg(double d) {
return mod(d, 1);
}
// better modulo that gives positive numbers always
static int mod(int n, int m) {
return (n % m + m) % m;
}
static long mod(long n, long m) {
return (n % m + m) % m;
}
static BigInteger mod(BigInteger n, int m) {
return n.mod(bigint(m));
}
static double mod(double n, double m) {
return (n % m + m) % m;
}
static BigInteger bigint(String s) {
return new BigInteger(s);
}
static BigInteger bigint(long l) {
return BigInteger.valueOf(l);
}
}