values(MultiMap mm) {
return mm == null ? emptyList() : concatLists(values(mm.data));
}
static Object nuObject(String className, Object... args) { try {
return nuObject(classForName(className), args);
} catch (Exception __e) { throw rethrow(__e); } }
// too ambiguous - maybe need to fix some callers
/*static O nuObject(O realm, S className, O... args) {
ret nuObject(_getClass(realm, className), args);
}*/
static A nuObject(Class c, Object... args) { try {
if (args.length == 0) return nuObjectWithoutArguments(c); // cached!
Constructor m = nuObject_findConstructor(c, args);
makeAccessible(m);
return (A) m.newInstance(args);
} catch (Exception __e) { throw rethrow(__e); } }
static Constructor nuObject_findConstructor(Class c, Object... args) {
for (Constructor m : c.getDeclaredConstructors()) {
if (!nuObject_checkArgs(m.getParameterTypes(), args, false))
continue;
return m;
}
throw fail("Constructor " + c.getName() + getClasses(args) + " not found"
+ (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : ""));
}
static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) {
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static JTextArea jTextAreaWithUndo() {
return jTextAreaWithUndo("");
}
static JTextArea jTextAreaWithUndo(final String text) {
return jenableUndoRedo(swingNu(JTextArea.class, text));
}
static boolean swic(String a, String b) {
return startsWithIgnoreCase(a, b);
}
static boolean swic(String a, String b, Matches m) {
if (!swic(a, b)) return false;
m.m = new String[] {substring(a, l(b))};
return true;
}
static boolean containsNewLines(String s) {
return containsNewLine(s);
}
static String jlabel_textAsHTML_center(String text) {
return ""
+ replace(htmlencode2(text), "\n", "
")
+ "
";
}
static boolean headless() {
return isHeadless();
}
static Throwable innerException2(Throwable e) {
if (e == null) return null;
while (empty(e.getMessage()) && e.getCause() != null)
e = e.getCause();
return e;
}
static String getSelectedItem(JList l) {
return (String) l.getSelectedValue();
}
static String getSelectedItem(JComboBox cb) {
return strOrNull(cb.getSelectedItem());
}
static JPanel jpanel(LayoutManager layout) {
return swingNu(JPanel.class, layout);
}
static JPanel jpanel() {
return swingNu(JPanel.class);
}
static Rect toRect(Rectangle r) {
return r == null ? null : new Rect(r);
}
static Rect toRect(RectangularShape r) {
return r == null ? null : toRect(r.getBounds());
}
static Rect toRect(DoubleRect r) {
if (r == null) return null;
int x = iround(r.x), y = iround(r.y);
return new Rect(x, y, iround(r.x2())-x, iround(r.y2())-y);
}
static Rect toRect(Rect r) { return r; }
static List screenDevices() {
return asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices());
}
static Object pcallFunction(Object f, Object... args) {
try { return callFunction(f, args); } catch (Throwable __e) { printStackTrace(__e); }
return null;
}
static A getWeakRef(Reference ref) {
return ref == null ? null : ref.get();
}
static x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl;
static x30_pkg.x30_util.BetterThreadLocal dm_current_generic_tl() {
if (dm_current_generic_tl == null)
dm_current_generic_tl = vm_generalMap_getOrCreate("currentModule", () -> new x30_pkg.x30_util.BetterThreadLocal());
return dm_current_generic_tl;
}
static int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(long a, long b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(Object a, Object b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return ((Comparable) a).compareTo(b);
}
static A popLast(List l) {
return liftLast(l);
}
static List popLast(int n, List l) {
return liftLast(n, l);
}
static boolean isInstance(Class type, Object arg) {
return type.isInstance(arg);
}
static boolean nempty(Collection c) {
return !empty(c);
}
static boolean nempty(CharSequence s) {
return !empty(s);
}
static boolean nempty(Object[] o) { return !empty(o); }
static boolean nempty(byte[] o) { return !empty(o); }
static boolean nempty(int[] o) { return !empty(o); }
static boolean nempty(BitSet bs) { return !empty(bs); }
static boolean nempty(Map m) {
return !empty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static boolean nempty(MultiMap mm) { return mm != null && !mm.isEmpty(); }
static boolean nempty(Object o) { return !empty(o); }
static boolean nempty(IntRange r) { return !empty(r); }
static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; }
static boolean nempty(MultiSet ms) { return ms != null && !ms.isEmpty(); }
static A[] makeArray(Class type, int n) {
return (A[]) Array.newInstance(type, n);
}
static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) {
return a != null && a.regionMatches(true, offsetA, b, offsetB, len);
}
static File programDir_mine; // set this to relocate program's data
static File programDir() {
return programDir(getProgramID());
}
static File programDir(String snippetID) {
boolean me = sameSnippetID(snippetID, programID());
if (programDir_mine != null && me)
return programDir_mine;
File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID));
if (me) {
String c = caseID();
if (nempty(c)) dir = newFile(dir, c);
}
return dir;
}
static File programDir(String snippetID, String subPath) {
return new File(programDir(snippetID), subPath);
}
static String formatSnippetIDOpt(String s) {
return isSnippetID(s) ? formatSnippetID(s) : s;
}
static String formatSnippetID(String id) {
return "#" + parseSnippetID(id);
}
static String formatSnippetID(long id) {
return "#" + id;
}
static Class getMainClass() {
return mc();
}
static Class getMainClass(Object o) { try {
if (o == null) return null;
if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o;
ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader();
if (cl == null) return null;
String name = mainClassNameForClassLoader(cl);
return loadClassFromClassLoader_orNull(cl, name);
} catch (Exception __e) { throw rethrow(__e); } }
static Map vm_threadInterruptionReasonsMap() {
return vm_generalWeakSubMap("Thread interruption reasons");
}
static String strOr(Object o, String ifNull) {
return o == null ? ifNull : str(o);
}
static void lockOrFail(Lock lock, long timeout) { try {
ping();
vmBus_send("locking", lock, "thread" , currentThread());
if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) {
String s = "Couldn't acquire lock after " + timeout + " ms.";
if (lock instanceof ReentrantLock) {
ReentrantLock l = (ReentrantLock) lock;
s += " Hold count: " + l.getHoldCount() + ", owner: " + call(l, "getOwner");
}
throw fail(s);
}
vmBus_send("locked", lock, "thread" , currentThread());
ping();
} catch (Exception __e) { throw rethrow(__e); } }
static ReentrantLock fairLock() {
return new ReentrantLock(true);
}
static AutoCloseable tempSetTL(ThreadLocal tl, A a) {
return tempSetThreadLocal(tl, a);
}
static List concatLists(Iterable... lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static List concatLists(Collection extends Iterable> lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static Map classForName_cache = synchroHashMap();
static Class classForName(String name) { return classForName(name, null); }
static Class classForName(String name, Object classFinder) {
// first clause is when we're in class init
if (classForName_cache == null || classFinder != null)
return classForName_uncached(name, classFinder);
Class c = classForName_cache.get(name);
if (c == null)
classForName_cache.put(name, c = classForName_uncached(name, null));
return c;
}
static Class classForName_uncached(String name, Object classFinder) { try {
if (classFinder != null) return (Class) callF(classFinder, name);
return Class.forName(name);
} catch (Exception __e) { throw rethrow(__e); } }
static Map nuObjectWithoutArguments_cache = newDangerousWeakHashMap();
static Object nuObjectWithoutArguments(String className) { try {
return nuObjectWithoutArguments(classForName(className));
} catch (Exception __e) { throw rethrow(__e); } }
static A nuObjectWithoutArguments(Class c) { try {
if (nuObjectWithoutArguments_cache == null)
// in class init
return (A) nuObjectWithoutArguments_findConstructor(c).newInstance();
Constructor m = nuObjectWithoutArguments_cache.get(c);
if (m == null)
nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c));
return (A) m.newInstance();
} catch (Exception __e) { throw rethrow(__e); } }
static Constructor nuObjectWithoutArguments_findConstructor(Class c) {
for (Constructor m : c.getDeclaredConstructors())
if (empty(m.getParameterTypes())) {
makeAccessible(m);
return m;
}
throw fail("No default constructor found in " + c.getName());
}
static A jenableUndoRedo(final A textcomp) {
{ swing(() -> {
final UndoManager undo = new UndoManager();
vm_generalWeakSet("Undo Managers").add(undo);
textcomp.getDocument().addUndoableEditListener(new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent evt) {
undo.addEdit(evt.getEdit());
}
});
textcomp.getActionMap().put("Undo", abstractAction("Undo", new Runnable() { public void run() { try {
if (undo.canUndo()) undo.undo()
;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canUndo()) undo.undo()"; }}));
textcomp.getActionMap().put("Redo", abstractAction("Redo", new Runnable() { public void run() { try {
if (undo.canRedo()) undo.redo()
;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canRedo()) undo.redo()"; }}));
textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");
textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
}); }
return textcomp;
}
static A swingNu(final Class c, final Object... args) {
return swingConstruct(c, args);
}
static boolean startsWithIgnoreCase(String a, String b) {
return regionMatchesIC(a, 0, b, 0, b.length());
}
static boolean containsNewLine(String s) {
return contains(s, '\n'); // screw \r, nobody needs it
}
static List replace(List l, A a, A b) {
for (int i = 0; i < l(l); i++)
if (eq(l.get(i), a))
l.set(i, b);
return l;
}
static List replace(A a, A b, List l) {
return replace(l, a, b);
}
// replace all occurrences of a in s with b
static String replace(String s, String a, String b) {
return s == null ? null : a == null || b == null ? s : s.replace(a, b);
}
static String replace(String s, char a, char b) {
return s == null ? null : s.replace(a, b);
}
static String htmlencode2(String s) {
return htmlencode_noQuotes(s);
}
static A liftLast(List l) {
if (empty(l)) return null;
int i = l(l)-1;
A a = l.get(i);
l.remove(i);
return a;
}
static List liftLast(int n, List l) {
int i = l(l)-n;
List part = cloneSubList(l, i);
removeSubList(l, i);
return part;
}
static boolean sameSnippetID(String a, String b) {
if (!isSnippetID(a) || !isSnippetID(b)) return false;
return parseSnippetID(a) == parseSnippetID(b);
}
static String programID() {
return getProgramID();
}
static String programID(Object o) {
return getProgramID(o);
}
static volatile String caseID_caseID;
static String caseID() { return caseID_caseID; }
static void caseID(String id) {
caseID_caseID = id;
}
public static boolean isSnippetID(String s) {
try {
parseSnippetID(s);
return true;
} catch (RuntimeException e) {
return false;
}
}
public static long parseSnippetID(String snippetID) {
long id = Long.parseLong(shortenSnippetID(snippetID));
if (id == 0) throw fail("0 is not a snippet ID");
return id;
}
static String mainClassNameForClassLoader(ClassLoader cl) {
return or((String) callOpt(cl, "mainClassName"), "main");
}
static Class loadClassFromClassLoader_orNull(ClassLoader cl, String name) {
try {
return cl == null ? null : cl.loadClass(name);
} catch (ClassNotFoundException e) {
return null;
}
}
static Map vm_generalWeakSubMap(Object name) {
synchronized(vm_generalMap()) {
Map map = (Map) (vm_generalMap_get(name));
if (map == null)
vm_generalMap_put(name, map = newWeakMap());
return map;
}
}
static AutoCloseable tempSetThreadLocalIfNecessary(ThreadLocal tl, A a) {
if (tl == null) return null;
A prev = tl.get();
if (eq(prev, a)) return null;
tl.set(a);
return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }};
}
static void addAll(Collection c, Iterable b) {
if (c != null && b != null) for (A a : b) c.add(a);
}
static boolean addAll(Collection c, Collection b) {
return c != null && b != null && c.addAll(b);
}
static boolean addAll(Collection c, B... b) {
return c != null && b != null && c.addAll(Arrays.asList(b));
}
static Map addAll(Map a, Map extends A,? extends B> b) {
if (a != null && b != null) a.putAll(b);
return a;
}
static Set vm_generalWeakSet(Object name) {
synchronized(vm_generalMap()) {
Set set = (Set) (vm_generalMap_get(name));
if (set == null)
vm_generalMap_put(name, set = newWeakHashSet());
return set;
}
}
static String htmlencode_noQuotes(String s) {
if (s == null) return "";
int n = s.length();
StringBuilder out = null;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (c == '<') {
if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s));
out
.append("<");
}
else if (c == '>') {
if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s));
out
.append(">");
}
else if (c > 127 || c == '&') {
int cp = s.codePointAt(i);
if (out == null) out = new StringBuilder(Math.max(16, n)).append(takeFirst(i, s));
out
.append("");
out.append(intToHex_flexLength(cp));
out.append(';');
i += Character.charCount(cp)-1;
} else
{ if (out != null) out.append(c); }
}
return out == null ? s : out.toString();
}
static List cloneSubList(List l, int startIndex, int endIndex) {
return newSubList(l, startIndex, endIndex);
}
static List cloneSubList(List l, int startIndex) {
return newSubList(l, startIndex);
}
static void removeSubList(List l, int from, int to) {
if (l != null) subList(l, from, to).clear();
}
static void removeSubList(List l, int from) {
if (l != null) subList(l, from).clear();
}
static String shortenSnippetID(String snippetID) {
if (snippetID.startsWith("#"))
snippetID = snippetID.substring(1);
String httpBlaBla = "http://tinybrain.de/";
if (snippetID.startsWith(httpBlaBla))
snippetID = snippetID.substring(httpBlaBla.length());
return "" + parseLong(snippetID);
}
static Map newWeakMap() {
return newWeakHashMap();
}
static Set newWeakHashSet() {
return synchroWeakHashSet();
}
static List takeFirst(List l, int n) {
return l(l) <= n ? l : newSubListOrSame(l, 0, n);
}
static List takeFirst(int n, List l) {
return takeFirst(l, n);
}
static String takeFirst(int n, String s) { return substring(s, 0, n); }
static String takeFirst(String s, int n) { return substring(s, 0, n); }
static CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); }
static List takeFirst(int n, Iterator it) {
if (it == null) return null;
List l = new ArrayList();
for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; }
return l;
}
static List takeFirst(int n, Iterable i) {
if (i == null) return null;
return i == null ? null : takeFirst(n, i.iterator());
}
static List takeFirst(int n, IterableIterator i) {
return takeFirst(n, (Iterator) i);
}
static int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); }
static short[] takeFirst(int n, short[] a) { return takeFirstOfShortArray(n, a); }
static byte[] takeFirst(int n, byte[] a) { return takeFirstOfByteArray(n, a); }
static byte[] takeFirst(byte[] a, int n) { return takeFirstOfByteArray(n, a); }
static double[] takeFirst(int n, double[] a) { return takeFirstOfDoubleArray(n, a); }
static double[] takeFirst(double[] a, int n) { return takeFirstOfDoubleArray(n, a); }
static String intToHex_flexLength(int i) {
return Integer.toHexString(i);
}
static List newSubList(List l, int startIndex, int endIndex) {
return cloneList(subList(l, startIndex, endIndex));
}
static List newSubList(List l, int startIndex) {
return cloneList(subList(l, startIndex));
}
static List subList(List l, int startIndex) {
return subList(l, startIndex, l(l));
}
static List subList(int startIndex, List l) {
return subList(l, startIndex);
}
static List subList(int startIndex, int endIndex, List l) {
return subList(l, startIndex, endIndex);
}
static List subList(List l, int startIndex, int endIndex) {
if (l == null) return null;
int n = l(l);
startIndex = Math.max(0, startIndex);
endIndex = Math.min(n, endIndex);
if (startIndex > endIndex) return ll();
if (startIndex == 0 && endIndex == n) return l;
return l.subList(startIndex, endIndex);
}
static List subList(List l, IntRange r) {
return subList(l, r.start, r.end);
}
static long parseLong(String s) {
if (empty(s)) return 0;
return Long.parseLong(dropSuffix("L", s));
}
static long parseLong(Object s) {
return Long.parseLong((String) s);
}
static Set synchroWeakHashSet() {
return Collections.newSetFromMap((Map) newWeakHashMap());
}
static List newSubListOrSame(List l, int startIndex) {
return newSubListOrSame(l, startIndex, l(l));
}
static List newSubListOrSame(List l, int startIndex, int endIndex) {
if (l == null) return null;
int n = l(l);
startIndex = max(0, startIndex);
endIndex = min(n, endIndex);
if (startIndex >= endIndex) return ll();
if (startIndex == 0 && endIndex == n) return l;
return cloneList(l.subList(startIndex, endIndex));
}
static List newSubListOrSame(List l, IntRange r) {
return newSubListOrSame(l, r.start, r.end);
}
static CharSequence subCharSequence(CharSequence s, int x) {
return subCharSequence(s, x, s == null ? 0 : s.length());
}
static CharSequence subCharSequence(CharSequence s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
if (x >= s.length()) return "";
if (y < x) y = x;
if (y > s.length()) y = s.length();
return s.subSequence(x, y);
}
static int[] takeFirstOfIntArray(int[] b, int n) {
return subIntArray(b, 0, n);
}
static int[] takeFirstOfIntArray(int n, int[] b) {
return takeFirstOfIntArray(b, n);
}
static short[] takeFirstOfShortArray(short[] b, int n) {
return subShortArray(b, 0, n);
}
static short[] takeFirstOfShortArray(int n, short[] b) {
return takeFirstOfShortArray(b, n);
}
static byte[] takeFirstOfByteArray(byte[] b, int n) {
return subByteArray(b, 0, n);
}
static byte[] takeFirstOfByteArray(int n, byte[] b) {
return takeFirstOfByteArray(b, n);
}
static double[] takeFirstOfDoubleArray(double[] b, int n) {
return subDoubleArray(b, 0, n);
}
static double[] takeFirstOfDoubleArray(int n, double[] b) {
return takeFirstOfDoubleArray(b, n);
}
static String dropSuffix(String suffix, String s) {
return nempty(suffix) && endsWith(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static int[] subIntArray(int[] b, int start) {
return subIntArray(b, start, l(b));
}
static int[] subIntArray(int[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start == 0 && end == l(b)) return b;
if (start >= end) return new int[0];
int[] x = new int[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static int[] subIntArray(int[] a, IntRange r) {
return r == null ? null : subIntArray(a, r.start, r.end);
}
static short[] subShortArray(short[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start == 0 && end == l(b)) return b;
if (start >= end) return new short[0];
short[] x = new short[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static byte[] subByteArray(byte[] b, int start) {
return subByteArray(b, start, l(b));
}
static byte[] subByteArray(byte[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start == 0 && end == l(b)) return b;
if (start >= end) return new byte[0];
byte[] x = new byte[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static byte[] subByteArray(byte[] b, IntRange r) {
return r == null ? null : subByteArray(b, r.start, r.end);
}
static double[] subDoubleArray(double[] b, int start) { return subDoubleArray(b, start, l(b)); }
static double[] subDoubleArray(double[] b, int start, int end) {
start = max(start, 0); end = min(end, l(b));
if (start == 0 && end == l(b)) return b;
if (start >= end) return new double[0];
double[] x = new double[end-start];
System.arraycopy(b, start, x, 0, end-start);
return x;
}
static boolean endsWith(String a, String b) {
return a != null && a.endsWith(b);
}
static boolean endsWith(String a, char c) {
return nempty(a) && lastChar(a) == c;
}
static boolean endsWith(String a, String b, Matches m) {
if (!endsWith(a, b)) return false;
m.m = new String[] {dropLast(l(b), a)};
return true;
}
static char lastChar(String s) {
return empty(s) ? '\0' : s.charAt(l(s)-1);
}
static A[] dropLast(A[] a) { return dropLast(a, 1); }
static A[] dropLast(A[] a, int n) {
if (a == null) return null;
n = Math.min(n, a.length);
A[] b = arrayOfSameType(a, a.length-n);
System.arraycopy(a, 0, b, 0, b.length);
return b;
}
static List dropLast(List l) {
return subList(l, 0, l(l)-1);
}
static List dropLast(int n, List l) {
return subList(l, 0, l(l)-n);
}
static List dropLast(Iterable l) {
return dropLast(asList(l));
}
static String dropLast(String s) {
return substring(s, 0, l(s)-1);
}
static String dropLast(String s, int n) {
return substring(s, 0, l(s)-n);
}
static String dropLast(int n, String s) {
return dropLast(s, n);
}
static A[] arrayOfSameType(A[] a, int n) {
return newObjectArrayOfSameType(a, n);
}
static A[] newObjectArrayOfSameType(A[] a) { return newObjectArrayOfSameType(a, a.length); }
static A[] newObjectArrayOfSameType(A[] a, int n) {
return (A[]) Array.newInstance(a.getClass().getComponentType(), n);
}
interface IVarWithNotify extends IVar, IF0WithChangeListeners {
default IVarWithNotify onChange(IVF1 r) {
if (r == null) return this;
onChange(() -> r.get(get()));
return this;
}
default IVarWithNotify onChangeAndNow(IVF1 r) {
if (r == null) return this;
onChangeAndNow(() -> r.get(get()));
return this;
}
}
// immutable, has strong refs
// Do not run in a synchronized block - it goes wrong in the presence
// of elaborate classloaders (like in Gazelle BEA)
// see #1102990 and #1102991
final static class _MethodCache {
final Class c;
final HashMap> cache = new HashMap();
_MethodCache(Class c) {
this.c = c; _init(); }
void _init() {
Class _c = c;
java.lang.Module myModule = getClass().getModule();
boolean anyHiddenClasses = false;
while (_c != null) {
boolean exported = classIsExportedTo(_c, myModule);
if (!exported)
anyHiddenClasses = true;
else
for (Method m : _c.getDeclaredMethods())
if ((anyHiddenClasses || !isAbstract(m))
&& !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
_c = _c.getSuperclass();
}
// add default methods - this might lead to a duplication
// because the overridden method is also added, but it's not
// a problem except for minimal performance loss.
// If any classes in the hierarchy were inaccessible, we add
// all interface methods (see test_callForbiddenMethodByReflection for a test)
for (Class intf : allInterfacesImplementedBy(c))
for (Method m : intf.getDeclaredMethods())
if ((anyHiddenClasses || m.isDefault()) && !reflection_isForbiddenMethod(m))
multiMapPut(cache, m.getName(), makeAccessible(m));
}
// Returns only matching methods
Method findMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
Method findStaticMethod(String method, Object[] args) { try {
List m = cache.get(method);
if (m == null) return null;
int n = m.size();
for (int i = 0; i < n; i++) {
Method me = m.get(i);
if (isStaticMethod(me) && call_checkArgs(me, args, false))
return me;
}
return null;
} catch (Exception __e) { throw rethrow(__e); } }
}
static abstract class VF1 implements IVF1 {
public abstract void get(A a);
}
// Meta - a "minimal" approach to adding meta-level to Java objects
static class Meta implements IMeta {
// Meta - a "minimal" approach to adding meta-level to Java objects
// (implementing the interface IMeta)
// We allocate one extra field for each Java object to make it
// reasoning-compatible (reasoning-compatible = extensible with
// fields of any name at runtime).
//
// We couldn't go for 0 extra fields (meta values must be linked
// directly from the object) and there are no half fields in
// Java... so there you go.
//
// Also, if you don't use any meta data, you are probably not
// reasoning about anything. The point of reasoning in JavaX is
// to attach information to objects directly used in the program.
// Possible information contained in the meta field:
// Origin, destination, security level, sender, cost center,
// purpose, list of reifications, ...
// So here it is. THE FIELD YOU HAVE BEEN WAITING FOR!
// [We also have IMeta to retrofit foreign classes (rare but
// probably useful).]
//////////////////////
// The "meta" field //
//////////////////////
// Generic meta value of any kind, but the typical case is it's a
// Map with extra field values for the object etc.
// "meta" is volatile to avoid synchronization; but you can also synchronize on
// _tempMetaMutex() which is usually the object itself. Collections
// and maps are exempt from using the collections's monitor as the meta
// mutex because their monitor tends to be held for long operations
// (e.g. cloneList). For those we use a substantially more complex
// algorithm using a weakMap. Probably overkill. I may reconsider.
volatile Object meta;
// The meta field is not transient, thus by default it will be
// persisted like anything else unless you customize your object
// to suppress or modulate this.
// ...and the interface methods
public void _setMeta(Object meta) { this.meta = meta; }
public Object _getMeta() { return meta; }
// MOST functions are implemented in IMeta (default implementations)
// Scaffolding convenience functions
final boolean scaffolding(){ return scaffoldingEnabled(); }
boolean scaffoldingEnabled() { return main.scaffoldingEnabled(this); }
boolean scaffoldingEnabled(Object o) { return main.scaffoldingEnabled(o); }
}
static class Matches {
String[] m;
Matches() {}
Matches(String... m) {
this.m = m;}
String get(int i) { return i < m.length ? m[i] : null; }
String unq(int i) { return unquote(get(i)); }
String tlc(int i) { return unq(i).toLowerCase(); }
boolean bool(int i) { return "true".equals(unq(i)); }
String rest() { return m[m.length-1]; } // for matchStart
int psi(int i) { return Integer.parseInt(unq(i)); }
public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; }
public int hashCode() { return _hashCode(toList(m)); }
public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); }
}
// for the version with MasterSymbol (used WAY back in "Smart Bot"!) see #1010608
static class Symbol implements CharSequence {
String text;
Symbol() {}
Symbol(String text, boolean dummy) {
this.text = text;} // weird signature to prevent accidental calling
public int hashCode() { return _hashCode(text); }
public String toString() { return text; }
public boolean equals(Object o) {
return this == o;
}
// implementation of CharSequence methods
public int length() { return text.length(); }
public char charAt(int index) { return text.charAt(index); }
public CharSequence subSequence(int start, int end) {
return text.substring(start, end);
}
}
static class Var implements IVar, ISetter {
Var() {}
Var(A v) {
this.v = v;}
A v; // you can access this directly if you use one thread
public synchronized void set(A a) {
if (v != a) {
v = a;
notifyAll();
}
}
public synchronized A get() { return v; }
public synchronized boolean has() { return v != null; }
public void clear() { set(null); }
public String toString() { return str(this.get()); }
}
static interface IMeta {
// see class "Meta" for the bla bla
public void _setMeta(Object meta);
public Object _getMeta();
default public IAutoCloseableF0 _tempMetaMutex() {
return new IAutoCloseableF0() {
public Object get() { return IMeta.this; }
public void close() {}
};
}
// actually query another object
default public Object getMeta(Object obj, Object key){ return metaGet(obj, key); }
default public Object metaGet(Object obj, Object key) {
// call global function
return metaMapGet(obj, key);
}
default public Object metaGet(String key, Object obj) {
// call global function
return metaMapGet(obj, key);
}
default public Object getMeta(Object key){ return metaGet(key); }
default public Object metaGet(Object key) {
if (key == null) return null;
Object meta = _getMeta();
if (meta instanceof Map) return ((Map) meta).get(key);
return null;
}
default public void metaSet(IMeta obj, Object key, Object value){ metaPut(obj, key, value); }
default public void metaPut(IMeta obj, Object key, Object value) {
// call global function
metaMapPut(obj, key, value);
}
default public void metaSet(Object key, Object value){ metaPut(key, value); }
default public void metaPut(Object key, Object value) {
if (key == null) return;
Map map = convertObjectMetaToMap(this);
syncMapPutOrRemove(map, key, value);
}
}
static class JSyntaxTextFileEditor extends JTextFileEditor {
JSyntaxTextFileEditor(File file) { super(file); }
RSyntaxTextAreaWithSearch textAreaWithSearch;
@Override
public RSyntaxTextArea textArea() { return (RSyntaxTextArea) textArea; }
@Override
JTextArea makeTextArea() {
textAreaWithSearch = makeSyntaxTextAreaWithSearch();
var ta = textAreaWithSearch.textArea();
adaptSyntaxTextArea(ta);
return ta;
}
transient IF0 makeSyntaxTextAreaWithSearch;
RSyntaxTextAreaWithSearch makeSyntaxTextAreaWithSearch() { return makeSyntaxTextAreaWithSearch != null ? makeSyntaxTextAreaWithSearch.get() : makeSyntaxTextAreaWithSearch_base(); }
final RSyntaxTextAreaWithSearch makeSyntaxTextAreaWithSearch_fallback(IF0 _f) { return _f != null ? _f.get() : makeSyntaxTextAreaWithSearch_base(); }
RSyntaxTextAreaWithSearch makeSyntaxTextAreaWithSearch_base() {
return rSyntaxTextAreaWithSearch();
}
transient IVF1 adaptSyntaxTextArea;
void adaptSyntaxTextArea(RSyntaxTextArea textArea) { if (adaptSyntaxTextArea != null) adaptSyntaxTextArea.get(textArea); else adaptSyntaxTextArea_base(textArea); }
final void adaptSyntaxTextArea_fallback(IVF1 _f, RSyntaxTextArea textArea) { if (_f != null) _f.get(textArea); else adaptSyntaxTextArea_base(textArea); }
void adaptSyntaxTextArea_base(RSyntaxTextArea textArea) {}
public JSyntaxTextFileEditor autoSave(boolean b) { super.autoSave(b); return this; }
}
// I think tokens should not cross lines, it messes about
// RSyntaxTextArea's hyperlink finding.
static class HashRefTokenMaker extends TokenMakerBase {
/**
* Returns a list of tokens representing the given text.
*
* @param text The text to break into tokens.
* @param startTokenType The token with which to start tokenizing.
* @param startOffset The offset at which the line of tokens begins.
* @return A linked list of tokens representing text.
*/
@Override
public org.fife.ui.rsyntaxtextarea.Token getTokenList(Segment text, int startTokenType, final int startOffset) {
resetTokenList();
char[] array = text.array;
int offset = text.offset;
int count = text.count;
int end = offset + count;
int newStartOffset = startOffset - offset;
String src = str(array, offset, count);
List tok = hashRefTok(src);
int ofs = offset;
for (int i = 0; i < l(tok); i++) { var t = tok.get(i);
if (empty(t)) continue;
boolean isHyperlink = odd(i);
var tokenType = isHyperlink ? org.fife.ui.rsyntaxtextarea.Token.VARIABLE : org.fife.ui.rsyntaxtextarea.Token.WHITESPACE; // ??
// split at line breaks
for (var part : singlePredTok(c -> c == '\n', t))
if (nempty(part)) {
int l = l(part);
addToken(array, ofs, ofs+l-1, tokenType, ofs+newStartOffset, isHyperlink);
ofs += l;
}
}
addNullToken();
// Return the first token in our linked list.
return firstToken;
}
}
// Some of the functions are dependent on the concepts field,
// others are global.
static class G22Utils {
final public G22Utils setBackgroundProcessesUI(BackgroundProcessesUI backgroundProcessesUI){ return backgroundProcessesUI(backgroundProcessesUI); }
public G22Utils backgroundProcessesUI(BackgroundProcessesUI backgroundProcessesUI) { this.backgroundProcessesUI = backgroundProcessesUI; return this; } final public BackgroundProcessesUI getBackgroundProcessesUI(){ return backgroundProcessesUI(); }
public BackgroundProcessesUI backgroundProcessesUI() { return backgroundProcessesUI; }
BackgroundProcessesUI backgroundProcessesUI;
final public G22Utils setModule(Enterable module){ return module(module); }
public G22Utils module(Enterable module) { this.module = module; return this; } final public Enterable getModule(){ return module(); }
public Enterable module() { return module; }
Enterable module;
final public G22Utils setMasterStuff(G22MasterStuff masterStuff){ return masterStuff(masterStuff); }
public G22Utils masterStuff(G22MasterStuff masterStuff) { this.masterStuff = masterStuff; return this; } final public G22MasterStuff getMasterStuff(){ return masterStuff(); }
public G22MasterStuff masterStuff() { return masterStuff; }
G22MasterStuff masterStuff;
final public G22Utils setConcepts(Concepts concepts){ return concepts(concepts); }
public G22Utils concepts(Concepts concepts) { this.concepts = concepts; return this; } final public Concepts getConcepts(){ return concepts(); }
public Concepts concepts() { return concepts; }
Concepts concepts;
final public G22Utils setProjectActions(G22ProjectActions projectActions){ return projectActions(projectActions); }
public G22Utils projectActions(G22ProjectActions projectActions) { this.projectActions = projectActions; return this; } final public G22ProjectActions getProjectActions(){ return projectActions(); }
public G22ProjectActions projectActions() { return projectActions; }
G22ProjectActions projectActions;
final public CombinedStringifier getStringifier(){ return stringifier(); }
public CombinedStringifier stringifier() { return stringifier; }
CombinedStringifier stringifier = new CombinedStringifier(
o -> o instanceof BufferedImage ? "Image (" + ((BufferedImage) o).getWidth() + "*" + ((BufferedImage) o).getHeight() + " px)" : null
);
ImageSurface stdImageSurface() {
var is = pixelatedImageSurface().setAutoZoomToDisplay(true).repaintInThread(false);
is.specialPurposed = true;
new ImageSurface_PositionToolTip(is);
return is;
}
ImageSurface stdImageSurface(MakesBufferedImage img) { return stdImageSurface(toBufferedImage(img)); }
ImageSurface stdImageSurface(BufferedImage img) {
var is = stdImageSurface();
is.setImage(img);
return is;
}
String stringify(Object o) { return stringifier.toString(o); }
transient Set> onSettingUpParser;
public G22Utils onSettingUpParser(IVF1 f) { onSettingUpParser = createOrAddToSyncLinkedHashSet(onSettingUpParser, f); return this; }
public G22Utils removeSettingUpParserListener(IVF1 f) { main.remove(onSettingUpParser, f); return this; }
public void settingUpParser(GazelleV_LeftArrowScriptParser parser) { pcallFAll(onSettingUpParser, parser); }
GazelleV_LeftArrowScriptParser leftArrowParser() {
GazelleV_LeftArrowScriptParser parser = new GazelleV_LeftArrowScriptParser();
parser.g22utils(this);
settingUpParser(parser);
return parser;
}
void basicParserTest() {
var parser = leftArrowParser();
print("classContainerPrefixes" , parser.classContainerPrefixes());
assertEquals(pair(1, 2), parser.parse("new Pair 1 2").get());
}
File byteCodePath() {
return assertNotNull(getBytecodePathForClass(this));
}
ClassNameResolver classNameResolver_cache;
ClassNameResolver classNameResolver() { if (classNameResolver_cache == null) classNameResolver_cache = classNameResolver_load(); return classNameResolver_cache;}
ClassNameResolver classNameResolver_load() {
return new ClassNameResolver().byteCodePath(byteCodePath()).init();
}
File databasesMotherDir() {
return javaxDataDir("Gazelle-22");
}
AutoCloseable enter() { return module == null ? null : module.enter(); }
String defaultDBName() { return "Default"; }
File lastOpenedDBsFile() {
return newFile(databasesMotherDir(), "Last Opened");
}
File autoUpdateFile() {
return newFile(databasesMotherDir(), "Auto-Update");
}
boolean autoUpdateEnabled() {
return fileExists(autoUpdateFile());
}
void setAutoUpdate(boolean b) {
createOrRemoveFile(autoUpdateFile(), b);
}
List dbsToOpen() {
List dbNames = new ArrayList();
for (String name : tlft(loadTextFile(lastOpenedDBsFile())))
if (fileExists(newFile(databasesMotherDir(), name)))
dbNames.add(name);
if (empty(dbNames)) dbNames.add(defaultDBName());
return dbNames;
}
void setOpenDBs(Collection dbDirs) {
List dbNames = new ArrayList();
for (File dbDir : dbDirs)
if (sameFile(databasesMotherDir(), dirOfFile(dbDir)))
dbNames.add(fileName(dbDir));
saveTextFile(lastOpenedDBsFile(), lines(dbNames));
}
Map scriptToMap(G22LeftArrowScript c) {
return litorderedmap(
"Description" , str(c),
"Status" , renderScriptStatus(c),
"LoC" , renderScriptLoC(c));
}
String renderScriptStatus(G22LeftArrowScript c) {
return or2_rev("Empty", joinNemptiesWithSpacedPlus(
c.isClearForAutoRun() ? "Clear for auto-run" : null,
c.isSavedDistinctFromAutoRunVersion() ? "Saved (not cleared)" : null,
c.isEditing() ? "Editing" : null
));
}
String renderScriptLoC(G22LeftArrowScript c) {
return n2(intMax(mapLL(__58 -> linesOfCode_javaTok(__58),
c.editingText,
c.text,
c.codeForAutoRun())));
}
// e.g. for an image file
List labelsForFile(File file) {
if (file == null) return null;
File labelsFile = appendToFileName(file, ".labels");
List labels = tlft(loadTextFile(labelsFile));
return map(__59 -> getLabel(__59), labels);
}
File labelsFile(File file) {
if (file == null) return null;
return appendToFileName(file, ".labels");
}
void setLabelsForFile(File file, List labels) {
List list = map(labels, label -> label.name);
File f = labelsFile(file);
saveTextFile(f, lines(list));
print("Saved " + nLabels(list) + " (" + joinWithComma(list) + ") to " + f);
}
G22Label getLabel(String name) {
if (empty(name)) return null;
if (containsNewLine(name)) throw fail("No newlines in label names allowed: " + name);
return uniqCI(concepts, G22Label.class, "name", name);
}
File dbDir() { return conceptsDir(concepts); }
File fileInDbDir(String name) { return newFile(dbDir(), name); }
class GazelleDB implements IFieldsToList{
String name;
File dir;
GazelleDB() {}
GazelleDB(String name, File dir) {
this.dir = dir;
this.name = name;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + name + ", " + dir + ")"; }
public boolean equals(Object o) {
if (!(o instanceof GazelleDB)) return false;
GazelleDB __0 = (GazelleDB) o;
return eq(name, __0.name) && eq(dir, __0.dir);
}
public int hashCode() {
int h = 1669530526;
h = boostHashCombine(h, _hashCode(name));
h = boostHashCombine(h, _hashCode(dir));
return h;
}
public Object[] _fieldsToList() { return new Object[] {name, dir}; }
Boolean loaded_cache;
boolean loaded() { if (loaded_cache == null) loaded_cache = loaded_load(); return loaded_cache;}
Boolean loaded_load() {
return containsFile(masterStuff.openConceptDirs(), dir);
}
File conceptsFile() { return conceptsFileIn(dir); }
}
List gazelleDBs() {
List dbs = new ArrayList();
for (File dir : listDirsContainingFileNamed(databasesMotherDir(),
"concepts.structure.gz"))
dbs.add(new GazelleDB(fileName(dir), dir));
return dbs;
}
RSyntaxTextAreaWithSearch newSyntaxTextArea() { return newSyntaxTextArea(null); }
RSyntaxTextAreaWithSearch newSyntaxTextArea(IF1 wrapStatusLabel) {
RSyntaxTextAreaWithSearch ta = new RSyntaxTextAreaWithSearch(wrapStatusLabel);
ta.textArea().setHighlightCurrentLine(false);
ta.menuLessOperation();
return ta;
}
File projectStoryTextFile() { return newFile(dbDir(), "story.txt"); }
}
static class RSyntaxTextAreaWithSearch implements SearchListener, Swingable {
JPanel panel;
final public RSyntaxTextArea getTextArea(){ return textArea(); }
public RSyntaxTextArea textArea() { return textArea; }
RSyntaxTextArea textArea;
CollapsibleSectionPanel csp;
FindDialog findDialog;
ReplaceDialog replaceDialog;
FindToolBar findToolBar;
ReplaceToolBar replaceToolBar;
StatusBar statusBar;
RSyntaxTextAreaWithSearch() { init(); }
RSyntaxTextAreaWithSearch(IF1 wrapStatusLabel) {
this.wrapStatusLabel = wrapStatusLabel; init(); }
RSyntaxTextAreaWithSearch(String text) { init(); setText(text); }
RSyntaxTextAreaWithSearch(RSyntaxTextArea textArea) {
this.textArea = textArea; init(); }
public JComponent visualize() { return panel; }
void init() { swing(() -> {
rsyntaxTextArea_fixNumPad();
initSearchDialogs();
panel = new JPanel(new BorderLayout());
csp = new CollapsibleSectionPanel();
panel.add(csp);
if (textArea == null) textArea = javaxSyntaxTextArea();
RTextScrollPane sp = new RTextScrollPane(textArea);
csp.add(sp);
ErrorStrip errorStrip = new ErrorStrip(textArea);
panel.add(errorStrip, BorderLayout.LINE_END);
statusBar = new StatusBar();
panel.add(statusBar, BorderLayout.SOUTH);
}); }
transient IF1 wrapStatusLabel;
JComponent wrapStatusLabel(JComponent label) { return wrapStatusLabel != null ? wrapStatusLabel.get(label) : wrapStatusLabel_base(label); }
final JComponent wrapStatusLabel_fallback(IF1 _f, JComponent label) { return _f != null ? _f.get(label) : wrapStatusLabel_base(label); }
JComponent wrapStatusLabel_base(JComponent label) { return label; }
void addItem(Action a, ButtonGroup bg, JMenu menu) {
JRadioButtonMenuItem item = new JRadioButtonMenuItem(a);
bg.add(item);
menu.add(item);
}
// register keystrokes if we don't have a menu bar
void menuLessOperation() { swing(() -> {
//print("menuLessOperation");
var mb = createMenuBar();
for (var menu : getMenus(mb))
for (var menuItem : getMenuItems(menu)) {
var ks = menuItem.getAccelerator();
//printVars(+ks, +menuItem);
if (ks != null) {
var action = menuItem.getAction();
//print("Registering keystroke: " + ks + " => " + action);
textArea.getInputMap().put(ks, action);
}
}
}); }
JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("Search");
menu.add(new JMenuItem(new ShowFindDialogAction()));
menu.add(new JMenuItem(new ShowReplaceDialogAction()));
menu.add(new JMenuItem(new GoToLineAction()));
menu.addSeparator();
int ctrl = getToolkit().getMenuShortcutKeyMask();
int shift = InputEvent.SHIFT_MASK;
KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F, ctrl|shift);
Action a = csp.addBottomComponent(ks, findToolBar);
a.putValue(Action.NAME, "Show Find Search Bar");
menu.add(new JMenuItem(a));
ks = KeyStroke.getKeyStroke(KeyEvent.VK_H, ctrl|shift);
a = csp.addBottomComponent(ks, replaceToolBar);
a.putValue(Action.NAME, "Show Replace Search Bar");
menu.add(new JMenuItem(a));
mb.add(menu);
return mb;
}
public String getSelectedText() {
return textArea.getSelectedText();
}
/**
* Creates our Find and Replace dialogs.
*/
public void initSearchDialogs() {
findDialog = new FindDialog((java.awt.Dialog) null, this);
replaceDialog = new ReplaceDialog((java.awt.Dialog) null, this);
// This ties the properties of the two dialogs together (match case,
// regex, etc.).
SearchContext context = findDialog.getSearchContext();
replaceDialog.setSearchContext(context);
// Create tool bars and tie their search contexts together also.
findToolBar = new FindToolBar(this);
findToolBar.setSearchContext(context);
replaceToolBar = new ReplaceToolBar(this);
replaceToolBar.setSearchContext(context);
}
/**
* Listens for events from our search dialogs and actually does the dirty
* work.
*/
@Override
public void searchEvent(SearchEvent e) {
SearchEvent.Type type = e.getType();
SearchContext context = e.getSearchContext();
SearchResult result = null;
switch (type) {
default: // Prevent FindBugs warning later
case MARK_ALL:
result = SearchEngine.markAll(textArea, context);
break;
case FIND:
result = SearchEngine.find(textArea, context);
if (!result.wasFound())
{
//Try to wrap the result...
Caret c = textArea.getCaret();
int pos = c.getDot();
if (context.getSearchForward())
{
c.setDot(0);
}
else
{
c.setDot(textArea.getDocument().getLength());
}
result = SearchEngine.find(textArea, context);
if (!result.wasFound())
{
c.setDot(pos);
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
}
}
break;
case REPLACE:
result = SearchEngine.replace(textArea, context);
if (!result.wasFound()) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
}
break;
case REPLACE_ALL:
result = SearchEngine.replaceAll(textArea, context);
JOptionPane.showMessageDialog(null, result.getCount() +
" occurrences replaced.");
break;
}
String text = null;
if (result.wasFound()) {
text = "Text found; occurrences marked: " + result.getMarkedCount();
}
else if (type==SearchEvent.Type.MARK_ALL) {
if (result.getMarkedCount()>0) {
text = "Occurrences marked: " + result.getMarkedCount();
}
else {
text = "";
}
}
else {
text = "Text not found";
}
setStatus(text);
}
class GoToLineAction extends AbstractAction {
GoToLineAction() {
super("Go To Line...");
int c = getToolkit().getMenuShortcutKeyMask();
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_L, c));
}
public void actionPerformed(ActionEvent e) {
findDialog.setVisible(false);
replaceDialog.setVisible(false);
GoToDialog dialog = new GoToDialog((java.awt.Dialog) null);
dialog.setMaxLineNumberAllowed(textArea.getLineCount());
showDialogOnSameScreen(dialog, panel);
int line = dialog.getLineNumber();
if (line>0) {
try {
textArea.setCaretPosition(textArea.getLineStartOffset(line-1));
} catch (BadLocationException ble) { // Never happens
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
ble.printStackTrace();
}
}
}
}
class ShowFindDialogAction extends AbstractAction {
ShowFindDialogAction() {
super("Find...");
int c = getToolkit().getMenuShortcutKeyMask();
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, c));
}
public void actionPerformed(ActionEvent e) {
replaceDialog.setVisible(false);
showDialogOnSameScreen(findDialog, panel);
}
}
class ShowReplaceDialogAction extends AbstractAction {
ShowReplaceDialogAction() {
super("Replace...");
int c = getToolkit().getMenuShortcutKeyMask();
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, c));
}
public void actionPerformed(ActionEvent e) {
findDialog.setVisible(false);
showDialogOnSameScreen(replaceDialog, panel);
}
}
class StatusBar extends JPanel {
JLabel label;
StatusBar() {
label = new JLabel(" ");
setLayout(new BorderLayout());
add(wrapStatusLabel(label), BorderLayout.CENTER);
add(new JLabel(new SizeGripIcon()), BorderLayout.EAST);
}
public void setText(String label) {
main.setText(this.label, label);
}
}
void setStatus(String text) {
statusBar.setText(text);
}
void setText(String text) {
main.setText(textArea, text);
}
String getText() {
return main.getText(textArea);
}
void setEditorFont(final Font font) { swing(() -> {
SyntaxScheme ss = textArea.getSyntaxScheme();
ss = (SyntaxScheme) ss.clone();
for (int i = 0; i < ss.getStyleCount(); i++)
if (ss.getStyle(i) != null)
ss.getStyle(i).font = font;
textArea.setSyntaxScheme(ss);
textArea.setFont(font);
}); }
Font getEditorFont() {
return swing(new F0() { public Font get() { try { return textArea.getFont(); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "return textArea.getFont();"; }});
}
int getEditorFontSize() {
return getEditorFont().getSize();
}
void setEditorFontSize(int size) {
setEditorFont(deriveFont(getEditorFont(), size));
}
RSyntaxDocument getDocument() {
return (RSyntaxDocument) textArea.getDocument();
}
Toolkit getToolkit() { return panel.getToolkit(); }
}
static class MultiMap {
Map> data = new HashMap>();
int fullSize;
MultiMap() {}
MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); }
MultiMap(MultiMap map) { putAll(map); }
MultiMap(Map> data) {
this.data = data;}
void put(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
list.add(value);
++fullSize;
}}
void add(A key, B value) { put(key, value); }
void addAll(A key, Collection values) { putAll(key, values); }
void addAllIfNotThere(A key, Collection values) { synchronized(data) {
for (B value : values)
setPut(key, value);
}}
void setPut(A key, B value) { synchronized(data) {
if (!containsPair(key, value))
put(key, value);
}}
boolean containsPair(A key, B value) { synchronized(data) {
return get(key).contains(value);
}}
void putAll(Collection keys, B value) { synchronized(data) {
for (A key : unnullForIteration(keys))
put(key, value);
}}
void putAll(A key, Collection values) { synchronized(data) {
if (nempty(values)) getActual(key).addAll(values);
}}
void putAll(Iterable> pairs) { synchronized(data) {
for (Pair p : unnullForIteration(pairs))
put(p.a, p.b);
}}
void removeAll(A key, Collection values) { synchronized(data) {
for (B value : values)
remove(key, value);
}}
List get(A key) { synchronized(data) {
List list = data.get(key);
return list == null ? Collections. emptyList() : list;
}}
List getOpt(A key) { synchronized(data) {
return data.get(key);
}}
List getAndClear(A key) { synchronized(data) {
List l = cloneList(data.get(key));
remove(key);
return l;
}}
// returns actual mutable live list
// creates the list if not there
List getActual(A key) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
return list;
}}
void clean(A key) { synchronized(data) {
List list = data.get(key);
if (list != null && list.isEmpty()) {
fullSize -= l(list);
data.remove(key);
}
}}
Set keySet() { synchronized(data) {
return data.keySet();
}}
Set keys() { synchronized(data) {
return data.keySet();
}}
void remove(A key) { synchronized(data) {
fullSize -= l(this.getOpt(key));
data.remove(key);
}}
final void remove(Pair p){ removePair(p); }
void removePair(Pair p) {
if (p != null) remove(p.a, p.b);
}
void remove(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list != null) {
if (list.remove(value))
fullSize--;
if (list.isEmpty())
data.remove(key);
}
}}
void clear() { synchronized(data) {
data.clear();
}}
boolean containsKey(A key) { synchronized(data) {
return data.containsKey(key);
}}
B getFirst(A key) { synchronized(data) {
List list = get(key);
return list.isEmpty() ? null : list.get(0);
}}
void addAll(MultiMap map) { putAll(map); }
void putAll(MultiMap map) { synchronized(data) {
for (A key : map.keySet())
putAll(key, map.get(key));
}}
void putAll(Map map) { synchronized(data) {
if (map != null) for (Map.Entry e : map.entrySet())
put(e.getKey(), e.getValue());
}}
final int keyCount(){ return keysSize(); }
int keysSize() { synchronized(data) { return l(data); }}
// full size - note: expensive operation
final int fullSize(){ return size(); }
int size() { synchronized(data) {
return fullSize;
}}
// expensive operation
List reverseGet(B b) { synchronized(data) {
List l = new ArrayList();
for (A key : data.keySet())
if (data.get(key).contains(b))
l.add(key);
return l;
}}
Map> asMap() { synchronized(data) {
return cloneMap(data);
}}
boolean isEmpty() { synchronized(data) { return data.isEmpty(); }}
// override in subclasses
List _makeEmptyList() {
return new ArrayList();
}
// returns live lists
Collection> allLists() {
synchronized(data) {
return new ArrayList(data.values());
}
}
Collection> values() { return allLists(); }
List allValues() {
return concatLists(data.values());
}
Object mutex() { return data; }
public String toString() { return "mm" + str(data); }
}
/*
* @(#)WeakHashMap.java 1.5 98/09/30
*
* Copyright 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
// From https://github.com/mernst/plume-lib/blob/df0bfafc3c16848d88f4ea0ef3c8bf3367ae085e/java/src/plume/WeakHasherMap.java
static final class WeakHasherMap extends AbstractMap implements Map {
private Hasher hasher = null;
/*@Pure*/
private boolean keyEquals(Object k1, Object k2) {
return (hasher==null ? k1.equals(k2)
: hasher.equals(k1, k2));
}
/*@Pure*/
private int keyHashCode(Object k1) {
return (hasher==null ? k1.hashCode()
: hasher.hashCode(k1));
}
// The WeakKey class can't be static because it depends on the hasher.
// That in turn means that its methods can't be static.
// However, I need to be able to call the methods such as create() that
// were static in the original version of this code.
// This finesses that.
private /*@Nullable*/ WeakKey WeakKeyCreate(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private /*@Nullable*/ WeakKey WeakKeyCreate(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
// Cannot be a static class: uses keyHashCode() and keyEquals()
private final class WeakKey extends WeakReference {
private int hash; /* Hashcode of key, stored here since the key
may be tossed by the GC */
private WeakKey(K k) {
super(k);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private WeakKey(K k, ReferenceQueue super K> q) {
super(k, q);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
/* A WeakKey is equal to another WeakKey iff they both refer to objects
that are, in turn, equal according to their own equals methods */
/*@Pure*/
@Override
public boolean equals(/*@Nullable*/ Object o) {
if (o == null) return false; // never happens
if (this == o) return true;
// This test is illegal because WeakKey is a generic type,
// so use the getClass hack below instead.
// if (!(o instanceof WeakKey)) return false;
if (!(o.getClass().equals(WeakKey.class))) return false;
Object t = this.get();
@SuppressWarnings("unchecked")
Object u = ((WeakKey)o).get();
if ((t == null) || (u == null)) return false;
if (t == u) return true;
return keyEquals(t, u);
}
/*@Pure*/
@Override
public int hashCode() {
return hash;
}
}
/* Hash table mapping WeakKeys to values */
private HashMap hash;
/* Reference queue for cleared WeakKeys */
private ReferenceQueue super K> queue = new ReferenceQueue();
/* Remove all invalidated entries from the map, that is, remove all entries
whose keys have been discarded. This method should be invoked once by
each public mutator in this class. We don't invoke this method in
public accessors because that can lead to surprising
ConcurrentModificationExceptions. */
@SuppressWarnings("unchecked")
private void processQueue() {
WeakKey wk;
while ((wk = (WeakKey)queue.poll()) != null) { // unchecked cast
hash.remove(wk);
}
}
/* -- Constructors -- */
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the given load factor.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @param loadFactor the load factor of the WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero, or if the load factor is
* nonpositive
*/
public WeakHasherMap(int initialCapacity, float loadFactor) {
hash = new HashMap(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the default load factor, which is
* 0.75.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero
*/
public WeakHasherMap(int initialCapacity) {
hash = new HashMap(initialCapacity);
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
*/
public WeakHasherMap() {
hash = new HashMap();
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
* The WeakHashMap uses the specified hasher for hashing
* keys and comparing them for equality.
* @param h the Hasher to use when hashing values for this map
*/
public WeakHasherMap(Hasher h) {
hash = new HashMap();
hasher = h;
}
/* -- Simple queries -- */
/**
* Returns the number of key-value mappings in this map.
* Note: In contrast to most implementations of the
* Map interface, the time required by this operation is
* linear in the size of the map.
*/
/*@Pure*/
@Override
public int size() {
return entrySet().size();
}
/**
* Returns true if this map contains no key-value mappings.
*/
/*@Pure*/
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
/**
* Returns true if this map contains a mapping for the
* specified key.
*
* @param key the key whose presence in this map is to be tested
*/
/*@Pure*/
@Override
public boolean containsKey(Object key) {
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.containsKey(WeakKeyCreate(kkey));
}
/* -- Lookup and modification operations -- */
/**
* Returns the value to which this map maps the specified key.
* If this map does not contain a value for this key, then return
* null.
*
* @param key the key whose associated value, if any, is to be returned
*/
/*@Pure*/
@Override
public /*@Nullable*/ V get(Object key) { // type of argument is Object, not K
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.get(WeakKeyCreate(kkey));
}
/**
* Updates this map so that the given key maps to the given
* value. If the map previously contained a mapping for
* key then that mapping is replaced and the previous value is
* returned.
*
* @param key the key that is to be mapped to the given
* value
* @param value the value to which the given key is to be
* mapped
*
* @return the previous value to which this key was mapped, or
* null if if there was no mapping for the key
*/
@Override
public V put(K key, V value) {
processQueue();
return hash.put(WeakKeyCreate(key, queue), value);
}
/**
* Removes the mapping for the given key from this map, if
* present.
*
* @param key the key whose mapping is to be removed
*
* @return the value to which this key was mapped, or null if
* there was no mapping for the key
*/
@Override
public V remove(Object key) { // type of argument is Object, not K
processQueue();
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.remove(WeakKeyCreate(kkey));
}
/**
* Removes all mappings from this map.
*/
@Override
public void clear() {
processQueue();
hash.clear();
}
/* -- Views -- */
/* Internal class for entries */
// This can't be static, again because of dependence on hasher.
@SuppressWarnings("TypeParameterShadowing")
private final class Entry implements Map.Entry {
private Map.Entry ent;
private K key; /* Strong reference to key, so that the GC
will leave it alone as long as this Entry
exists */
Entry(Map.Entry ent, K key) {
this.ent = ent;
this.key = key;
}
/*@Pure*/
@Override
public K getKey() {
return key;
}
/*@Pure*/
@Override
public V getValue() {
return ent.getValue();
}
@Override
public V setValue(V value) {
return ent.setValue(value);
}
/*@Pure*/
private boolean keyvalEquals(K o1, K o2) {
return (o1 == null) ? (o2 == null) : keyEquals(o1, o2);
}
/*@Pure*/
private boolean valEquals(V o1, V o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
/*@Pure*/
@SuppressWarnings("NonOverridingEquals")
public boolean equals(Map.Entry e /* Object o*/) {
// if (! (o instanceof Map.Entry)) return false;
// Map.Entry e = (Map.Entry)o;
return (keyvalEquals(key, e.getKey())
&& valEquals(getValue(), e.getValue()));
}
/*@Pure*/
@Override
public int hashCode() {
V v;
return (((key == null) ? 0 : keyHashCode(key))
^ (((v = getValue()) == null) ? 0 : v.hashCode()));
}
}
/* Internal class for entry sets */
private final class EntrySet extends AbstractSet> {
Set> hashEntrySet = hash.entrySet();
@Override
public Iterator> iterator() {
return new Iterator>() {
Iterator> hashIterator = hashEntrySet.iterator();
Map.Entry next = null;
@Override
public boolean hasNext() {
while (hashIterator.hasNext()) {
Map.Entry ent = hashIterator.next();
WeakKey wk = ent.getKey();
K k = null;
if ((wk != null) && ((k = wk.get()) == null)) {
/* Weak key has been cleared by GC */
continue;
}
next = new Entry(ent, k);
return true;
}
return false;
}
@Override
public Map.Entry next() {
if ((next == null) && !hasNext())
throw new NoSuchElementException();
Map.Entry e = next;
next = null;
return e;
}
@Override
public void remove() {
hashIterator.remove();
}
};
}
/*@Pure*/
@Override
public boolean isEmpty() {
return !(iterator().hasNext());
}
/*@Pure*/
@Override
public int size() {
int j = 0;
for (Iterator> i = iterator(); i.hasNext(); i.next()) j++;
return j;
}
@Override
public boolean remove(Object o) {
processQueue();
if (!(o instanceof Map.Entry,?>)) return false;
@SuppressWarnings("unchecked")
Map.Entry e = (Map.Entry)o; // unchecked cast
Object ev = e.getValue();
WeakKey wk = WeakKeyCreate(e.getKey());
Object hv = hash.get(wk);
if ((hv == null)
? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) {
hash.remove(wk);
return true;
}
return false;
}
/*@Pure*/
@Override
public int hashCode() {
int h = 0;
for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) {
Map.Entry ent = i.next();
WeakKey wk = ent.getKey();
Object v;
if (wk == null) continue;
h += (wk.hashCode()
^ (((v = ent.getValue()) == null) ? 0 : v.hashCode()));
}
return h;
}
}
private /*@Nullable*/ Set> entrySet = null;
/**
* Returns a Set view of the mappings in this map.
*/
/*@SideEffectFree*/
@Override
public Set> entrySet() {
if (entrySet == null) entrySet = new EntrySet();
return entrySet;
}
// find matching key
K findKey(Object key) {
processQueue();
K kkey = (K) key;
// TODO: use replacement for HashMap to avoid reflection
WeakKey wkey = WeakKeyCreate(kkey);
WeakKey found = hashMap_findKey(hash, wkey);
return found == null ? null : found.get();
}
}
static class SingleComponentPanel extends JPanel {
SingleComponentPanel() { super(new BorderLayout()); }
SingleComponentPanel(Component component) {
this();
if (component != null) setComponent(component);
}
void set(Swingable component) {
set(wrap(component));
}
final void set(Component component){ setComponent(component); }
void setComponent(Component component) {
{ swing(() -> {
if (getComponent() == component) return;
removeAll();
if (component != null)
add(BorderLayout.CENTER, wrap(component));
_revalidate(SingleComponentPanel.this);
}); }
}
// Sometimes we need this?
void setComponentAndRevalidateParent(Component component) {
setComponent(component);
_revalidate(_getParent(this));
}
final void clear(){ noComponent(); }
void noComponent() { setComponent(null); }
Component getComponent() {
return swing( () -> getComponentCount() == 0 ? null : getComponent(0));
}
boolean isEmpty() { return getComponent() == null; }
}
static class TypedVirtualVar extends VirtualVar {
Class type;
TypedVirtualVar(Class type, IF0 getter, IVF1 setter) {
this.setter = setter;
this.getter = getter;
this.type = type;}
public Class getType() { return type; }
}
static class Fail extends RuntimeException implements IFieldsToList{
Object[] objects;
Fail() {}
Fail(Object... objects) {
this.objects = objects;}public Object[] _fieldsToList() { return new Object[] {objects}; }
Fail(Throwable cause, Object... objects) {
super(cause);
this.objects = objects;
}
public String toString() { return joinNemptiesWithColon("Fail", commaCombine(getCause(), objects)); }
}
static class Pair implements Comparable> {
A a;
B b;
Pair() {}
Pair(A a, B b) {
this.b = b;
this.a = a;}
public int hashCode() {
return hashCodeFor(a) + 2*hashCodeFor(b);
}
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Pair)) return false;
Pair t = (Pair) o;
return eq(a, t.a) && eq(b, t.b);
}
public String toString() {
return "<" + a + ", " + b + ">";
}
public int compareTo(Pair p) {
if (p == null) return 1;
int i = ((Comparable) a).compareTo(p.a);
if (i != 0) return i;
return ((Comparable) b).compareTo(p.b);
}
}
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; }
}
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; }
}
static abstract class F0 {
abstract A get();
}
static abstract class F1 {
abstract B get(A a);
}
// you still need to implement hasNext() and next()
static abstract class IterableIterator implements Iterator, Iterable {
public Iterator iterator() {
return this;
}
public void remove() {
unsupportedOperation();
}
}
static class BetterLabel extends JLabel {
boolean autoToolTip = true;
BetterLabel() {
// Listeners given out to componentPopupMenu must not directly
// reference the outer object (-> weak map problem).
final WeakReference < BetterLabel > me = new WeakReference<>(this);
componentPopupMenu(this, BetterLabel_menuItems(me));
}
BetterLabel(String text) {
this();
this.setText(text);
}
public void setText(String text) {
super.setText(text);
if (autoToolTip)
if (!swic(text, "")) // HTML labels make super-huge, confusing tool tips
setToolTipText(nullIfEmpty(text));
}
}
// moved outside of class for GC reasons (see above)
static VF1 BetterLabel_menuItems(final WeakReference me) {
return new VF1() { public void get(JPopupMenu menu) { try {
addMenuItem(menu, "Copy text to clipboard", new Runnable() { public void run() { try {
copyTextToClipboard(me.get().getText());
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(me.get().getText());"; }});
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "addMenuItem(menu, \"Copy text to clipboard\", r {\r\n copyTextToClipboard(me..."; }};
}
public static interface IF0 {
A get();
}
static interface Hasher {
int hashCode(A a);
boolean equals(A a, A b);
}
static List _stickyLibs_1400546 = ll("#1400546", "#1400547", "#1400548");
// RSyntaxTextArea
// AutoComplete
// RSTAUI
static interface IFieldsToList {
Object[] _fieldsToList();
}
static interface IF1 {
B get(A a);
}
static class PersistableThrowable extends DynamicObject {
String className;
String msg;
String stacktrace;
PersistableThrowable() {}
PersistableThrowable(Throwable e) {
if (e == null)
className = "Crazy Null Error";
else {
className = getClassName(e).replace('/', '.');
msg = e.getMessage();
stacktrace = getStackTrace_noRecord(e);
}
}
public String toString() {
return nempty(msg) ? className + ": " + msg : className;
}
RuntimeException asRuntimeException() {
return new Fail(this);
}
}
static interface IVF1 {
void get(A a);
}
static interface Swingable {
JComponent visualize();
}
interface Enterable {
AutoCloseable enter();
}
static class BackgroundProcessesUI {
Set processes = setWithNotify(syncLinkedHashSet(), () -> updateCount());
SimpleLiveValue lvCount = new SimpleLiveValue(Integer.class, 0);
class Entry implements AutoCloseable , IFieldsToList{
String name;
Entry() {}
Entry(String name) {
this.name = name;}
public boolean equals(Object o) {
if (!(o instanceof Entry)) return false;
Entry __0 = (Entry) o;
return eq(name, __0.name);
}
public int hashCode() {
int h = 67115090;
h = boostHashCombine(h, _hashCode(name));
return h;
}
public Object[] _fieldsToList() { return new Object[] {name}; }
final public Entry setMenuItem(JMenuItem menuItem){ return menuItem(menuItem); }
public Entry menuItem(JMenuItem menuItem) { this.menuItem = menuItem; return this; } final public JMenuItem getMenuItem(){ return menuItem(); }
public JMenuItem menuItem() { return menuItem; }
JMenuItem menuItem;
public String toString() { return name; }
public void close() { try { processes.remove(this); } catch (Exception __e) { throw rethrow(__e); } }
}
JLabel shortLabel() {
var lbl = bindToolTipToTransformedLiveValue(
n -> makeToolTip(), lvCount,
simpleTransformedLiveValueLabel(n -> n2(n), lvCount));
onMouseDown_anyButton(lbl, e -> {
var l = cloneList(processes);
// make sure title is displayed fully
JPopupMenu menu = new JPopupMenu();/* {
public Dimension getMinimumSize() {
TitledBorder border = optCast TitledBorder(getBorder());
_print(+border);
ret maxDimension(super.getMinimumSize(), border?.getMinimumSize(this));
}
};*/
int n = componentCount(menu);
for (Entry a : l)
addMenuItem(menu, processToMenuItem(a));
if (componentCount(menu) != n) {
var border = jRaisedSectionBorder("Background Processes");
setBorder(menu, border);
showPopupMenu(menu, e);
var size = menu.getSize();
var borderSize = dimensionPlus(10 /* hack */, 0, border.getMinimumSize(menu));
printVars("size", size, "borderSize", borderSize);
menu.setPopupSize(maxDimension(size, borderSize));
}
});
return lbl;
}
void add(Entry process) {
processes.add(process);
}
void remove(Entry process) {
processes.remove(process);
}
void addOrRemove(boolean add, Entry process) {
if (add) add(process); else remove(process);
}
Entry tempAdd(String name) {
return tempAdd(new Entry(or2(name, "Unnamed process")));
}
Entry tempAdd(Entry process) {
if (process == null) return null;
processes.add(process);
return process;
}
void updateCount() {
lvCount.set(l(processes));
}
String makeToolTip() {
var l = cloneList(processes);
return empty(l) ? "No background processes"
: n2(l, "background process", "background processes")
+ ": " + joinWithComma(processes);
}
transient IF1 processToMenuItem;
JMenuItem processToMenuItem(Entry process) { return processToMenuItem != null ? processToMenuItem.get(process) : processToMenuItem_base(process); }
final JMenuItem processToMenuItem_fallback(IF1 _f, Entry process) { return _f != null ? _f.get(process) : processToMenuItem_base(process); }
JMenuItem processToMenuItem_base(Entry process) {
return process.getMenuItem();
}
}
static interface ISetter {
void set(A a);
}
interface IF0WithChangeListeners extends IF0, IHasChangeListeners {}
// takes ~70 ms to set up, do it only once if possible
static class ClassNameResolver {
final public ClassNameResolver setByteCodePath(File byteCodePath){ return byteCodePath(byteCodePath); }
public ClassNameResolver byteCodePath(File byteCodePath) { this.byteCodePath = byteCodePath; return this; } final public File getByteCodePath(){ return byteCodePath(); }
public File byteCodePath() { return byteCodePath; }
File byteCodePath = byteCodePathForClass(getClass());
List importedPackages = itemPlusList("java.lang",
endingWith_dropSuffix(standardImports(), ".*"));
Set allFullyQualifiedClassNames_cache;
Set allFullyQualifiedClassNames() { if (allFullyQualifiedClassNames_cache == null) allFullyQualifiedClassNames_cache = allFullyQualifiedClassNames_load(); return allFullyQualifiedClassNames_cache;}
Set allFullyQualifiedClassNames_load() {
Set set = new HashSet();
assertNotNull(byteCodePath);
set.addAll(classNamesInJarOrDir(byteCodePath));
printVars("ClassNameResolver", "byteCodePath", byteCodePath, "classesFound" , l(set));
set.addAll(classNamesInLoadedJigsawModules());
return set;
}
ClassNameResolver init() { allFullyQualifiedClassNames(); return this; }
String findClass(String name) {
for (String pkg : importedPackages) {
String fullName = pkg + "." + name;
if (allFullyQualifiedClassNames().contains(fullName))
return fullName;
}
return null;
}
void printMe() {
printVars("ClassNameResolver", "byteCodePath", byteCodePath);
print("importedPackages", importedPackages);
}
}
static interface IAutoCloseableF0 extends IF0, AutoCloseable {}
interface G22ProjectActions {
void openObjectInProject(long id);
void openPathInProject(String path);
}
static class ImageSurface extends Surface {
BufferedImage image;
double zoomX = 1, zoomY = 1, zoomFactor = 1.5;
private Rectangle selection;
List tools = new ArrayList();
// use overlays now
Object overlay; // voidfunc(Graphics2D)
List overlays = syncL();
Runnable onSelectionChange;
final public ImageSurface setVerbose(boolean verbose){ return verbose(verbose); }
public ImageSurface verbose(boolean verbose) { this.verbose = verbose; return this; } final public boolean getVerbose(){ return verbose(); }
public boolean verbose() { return verbose; }
boolean verbose = false;
boolean noMinimumSize = true;
String titleForUpload;
Object onZoom;
boolean specialPurposed = false; // true = don't show image changing commands in popup menu
final public ImageSurface setZoomable(boolean zoomable){ return zoomable(zoomable); }
public ImageSurface zoomable(boolean zoomable) { this.zoomable = zoomable; return this; } final public boolean getZoomable(){ return zoomable(); }
public boolean zoomable() { return zoomable; }
boolean zoomable = true;
boolean noAlpha = false; // set to true to speed up drawing if you don't use alpha
Object interpolationMode = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
Object onNewImage;
BufferedImage imageToDraw; // if you want to draw a different image
File file; // where image was loaded from
boolean autoZoomToDisplay = false; // only works 100% when not in scrollpane
final public ImageSurface setRepaintInThread(boolean repaintInThread){ return repaintInThread(repaintInThread); }
public ImageSurface repaintInThread(boolean repaintInThread) { this.repaintInThread = repaintInThread; return this; } final public boolean getRepaintInThread(){ return repaintInThread(); }
public boolean repaintInThread() { return repaintInThread; }
boolean repaintInThread = false; // after setImage, repaint in same thread
BoolVar showingVar;
Pt mousePosition;
transient Set onMousePositionChanged;
public ImageSurface onMousePositionChanged(Runnable r) { onMousePositionChanged = createOrAddToSyncLinkedHashSet(onMousePositionChanged, r); return this; }
public ImageSurface removeMousePositionChangedListener(Runnable r) { main.remove(onMousePositionChanged, r); return this; }
public void mousePositionChanged() { pcallFAll(onMousePositionChanged); }
public ImageSurface() {
this(dummyImage());
}
static BufferedImage dummyImage() {
return whiteImage(1);
}
ImageSurface(MakesBufferedImage image) {
this(image != null ? image.getBufferedImage() : dummyImage());
}
ImageSurface(BufferedImage image) {
setImage(image);
clearSurface = false;
onResize(this, () -> performAutoZoom());
bindToComponent(this, () -> performAutoZoom(), null);
componentPopupMenu2(this, ImageSurface_popupMenuMaker());
new ImageSurfaceSelector(this);
jHandleFileDrop(this, new VF1