import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.function.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import java.time.Duration;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandles;
import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.*;
import org.fife.ui.autocomplete.*;
import org.fife.rsta.ui.CollapsibleSectionPanel;
import org.fife.rsta.ui.GoToDialog;
import org.fife.rsta.ui.SizeGripIcon;
import org.fife.rsta.ui.search.FindDialog;
import org.fife.rsta.ui.search.ReplaceDialog;
import org.fife.rsta.ui.search.ReplaceToolBar;
import org.fife.rsta.ui.search.SearchEvent;
import org.fife.rsta.ui.search.SearchListener;
import org.fife.rsta.ui.search.FindToolBar;
import org.fife.ui.rsyntaxtextarea.ErrorStrip;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.fife.ui.rtextarea.SearchContext;
import org.fife.ui.rtextarea.SearchEngine;
import org.fife.ui.rtextarea.SearchResult;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
import static x30_pkg.x30_util.DynamicObject;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.Const;
import org.apache.bcel.generic.*;
import java.lang.reflect.Type;
import java.util.jar.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import javax.swing.border.TitledBorder;
import java.text.*;
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.Timer;
import java.nio.file.Path;
import org.fife.ui.rsyntaxtextarea.*;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.awt.geom.*;
import javax.swing.undo.UndoManager;
import javax.swing.border.*;
import java.text.NumberFormat;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.nio.charset.Charset;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.awt.datatransfer.UnsupportedFlavorException;
import javax.swing.Icon;
public class main {
static public class G22MaskUtils implements IFieldsToList {
public G22Utils g22utils;
public G22MaskUtils() {
}
public G22MaskUtils(G22Utils g22utils) {
this.g22utils = g22utils;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + g22utils + ")";
}
public Object[] _fieldsToList() {
return new Object[] { g22utils };
}
public IG22SimpleMasksHolder simpleMaskSet() {
return new G22HashedMasks();
}
public IG22MasksHolder optimizedMaskSet(IG22MasksHolder masks) {
var search = new G22CriticalPixelSearch(masks);
return search.bestTree();
}
}
static public String shortClassName_dropNumberPrefix(Object o) {
return dropNumberPrefix(shortClassName(o));
}
static public String dropNumberPrefix(String s) {
return dropFirst(s, indexOfNonDigit(s));
}
static public String shortClassName(Object o) {
if (o == null)
return null;
Class c = o instanceof Class ? (Class) o : o.getClass();
String name = c.getName();
return shortenClassName(name);
}
static public String[] dropFirst(int n, String[] a) {
return drop(n, a);
}
static public String[] dropFirst(String[] a) {
return drop(1, a);
}
static public Object[] dropFirst(Object[] a) {
return drop(1, a);
}
static public List dropFirst(List l) {
return dropFirst(1, l);
}
static public List dropFirst(int n, Iterable i) {
return dropFirst(n, toList(i));
}
static public List dropFirst(Iterable i) {
return dropFirst(toList(i));
}
static public List dropFirst(int n, List l) {
return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size()));
}
static public List dropFirst(List l, int n) {
return dropFirst(n, l);
}
static public String dropFirst(int n, String s) {
return substring(s, n);
}
static public String dropFirst(String s, int n) {
return substring(s, n);
}
static public String dropFirst(String s) {
return substring(s, 1);
}
static public Chain dropFirst(Chain c) {
return c == null ? null : c.next;
}
static public int indexOfNonDigit(String s) {
int n = l(s);
for (int i = 0; i < n; i++) if (!isDigit(s.charAt(i)))
return i;
return -1;
}
static public String shortenClassName(String name) {
if (name == null)
return null;
int i = lastIndexOf(name, "$");
if (i < 0)
i = lastIndexOf(name, ".");
return i < 0 ? name : substring(name, i + 1);
}
static public String[] drop(int n, String[] a) {
n = Math.min(n, a.length);
String[] b = new String[a.length - n];
System.arraycopy(a, n, b, 0, b.length);
return b;
}
static public Object[] drop(int n, Object[] a) {
n = Math.min(n, a.length);
Object[] b = new Object[a.length - n];
System.arraycopy(a, n, b, 0, b.length);
return b;
}
static public ArrayList toList(A[] a) {
return asList(a);
}
static public ArrayList toList(int[] a) {
return asList(a);
}
static public ArrayList toList(short[] a) {
return asList(a);
}
static public ArrayList toList(Set s) {
return asList(s);
}
static public ArrayList toList(Iterable s) {
return asList(s);
}
static public String substring(String s, int x) {
return substring(s, x, strL(s));
}
static public String substring(String s, int x, int y) {
if (s == null)
return null;
if (x < 0)
x = 0;
int n = s.length();
if (y < x)
y = x;
if (y > n)
y = n;
if (x >= y)
return "";
return s.substring(x, y);
}
static public String substring(String s, IntRange r) {
return r == null ? null : substring(s, r.start, r.end);
}
static public String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
static public int l(Object[] a) {
return a == null ? 0 : a.length;
}
static public int l(boolean[] a) {
return a == null ? 0 : a.length;
}
static public int l(byte[] a) {
return a == null ? 0 : a.length;
}
static public int l(short[] a) {
return a == null ? 0 : a.length;
}
static public int l(long[] a) {
return a == null ? 0 : a.length;
}
static public int l(int[] a) {
return a == null ? 0 : a.length;
}
static public int l(float[] a) {
return a == null ? 0 : a.length;
}
static public int l(double[] a) {
return a == null ? 0 : a.length;
}
static public int l(char[] a) {
return a == null ? 0 : a.length;
}
static public int l(Collection c) {
return c == null ? 0 : c.size();
}
static public int l(Iterator i) {
return iteratorCount_int_close(i);
}
static public int l(Map m) {
return m == null ? 0 : m.size();
}
static public int l(CharSequence s) {
return s == null ? 0 : s.length();
}
static public long l(File f) {
return f == null ? 0 : f.length();
}
static public int l(MultiSet ms) {
return ms == null ? 0 : ms.size();
}
static public int l(IMultiMap mm) {
return mm == null ? 0 : mm.size();
}
static public int l(IntRange r) {
return r == null ? 0 : r.length();
}
static public double l(DoubleRange r) {
return r == null ? 0 : r.length();
}
static public int l(IntBuffer b) {
return b == null ? 0 : b.size();
}
static public int l(LongBuffer b) {
return b == null ? 0 : b.size();
}
static public int l(IntSize o) {
return o == null ? 0 : o.size();
}
static public boolean isDigit(char c) {
return Character.isDigit(c);
}
static public int lastIndexOf(String a, String b) {
return a == null || b == null ? -1 : a.lastIndexOf(b);
}
static public int lastIndexOf(String a, char b) {
return a == null ? -1 : a.lastIndexOf(b);
}
static public int lastIndexOf(List l, int i, A a) {
if (l == null)
return -1;
for (i = min(l(l), i) - 1; i >= 0; i--) if (eq(l.get(i), a))
return i;
return -1;
}
static public int lastIndexOf(List l, A a) {
if (l == null)
return -1;
for (int i = l(l) - 1; i >= 0; i--) if (eq(l.get(i), a))
return i;
return -1;
}
static public ArrayList asList(A[] a) {
return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a));
}
static public ArrayList asList(byte[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (var i : a) l.add(i);
return l;
}
static public ArrayList asList(int[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static public ArrayList asList(long[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (long i : a) l.add(i);
return l;
}
static public ArrayList asList(float[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static public ArrayList asList(double[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static public ArrayList asList(short[] a) {
if (a == null)
return null;
ArrayList l = emptyList(a.length);
for (short i : a) l.add(i);
return l;
}
static public ArrayList asList(Iterator it) {
ArrayList l = new ArrayList();
if (it != null)
while (it.hasNext()) l.add(it.next());
return l;
}
static public ArrayList asList(IterableIterator s) {
return asList((Iterator) s);
}
static public ArrayList asList(Iterable s) {
if (s instanceof ArrayList)
return (ArrayList) s;
ArrayList l = new ArrayList();
if (s != null)
for (A a : s) l.add(a);
return l;
}
static public ArrayList asList(Producer p) {
ArrayList l = new ArrayList();
A a;
if (p != null)
while ((a = p.next()) != null) l.add(a);
return l;
}
static public ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements()) l.add(e.nextElement());
return l;
}
static public ArrayList asList(ReverseChain c) {
return c == null ? emptyList() : c.toList();
}
static public List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
static public int strL(String s) {
return s == null ? 0 : s.length();
}
static public int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static public int iteratorCount_int_close(Iterator i) {
try {
int n = 0;
if (i != null)
while (i.hasNext()) {
i.next();
++n;
}
if (i instanceof AutoCloseable)
((AutoCloseable) i).close();
return n;
} catch (Exception __e) {
throw rethrow(__e);
}
}
static public int min(int a, int b) {
return Math.min(a, b);
}
static public long min(long a, long b) {
return Math.min(a, b);
}
static public float min(float a, float b) {
return Math.min(a, b);
}
static public float min(float a, float b, float c) {
return min(min(a, b), c);
}
static public double min(double a, double b) {
return Math.min(a, b);
}
static public double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static public float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static public byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x)
x = d;
return x;
}
static public short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x)
x = d;
return x;
}
static public int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x)
x = d;
return x;
}
static public boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
static public boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
static public ArrayList emptyList() {
return new ArrayList();
}
static public ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
static public ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static public ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
static public ArrayList emptyList(Class c) {
return new ArrayList();
}
static public List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null)
for (A x : a) l.add(x);
return l;
}
static public RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static public RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static public String str(Object o) {
return o == null ? "null" : o.toString();
}
static public String str(char[] c) {
return new String(c);
}
static public String str(char[] c, int offset, int count) {
return new String(c, offset, count);
}
static public int max(int a, int b) {
return Math.max(a, b);
}
static public int max(int a, int b, int c) {
return max(max(a, b), c);
}
static public long max(int a, long b) {
return Math.max((long) a, b);
}
static public long max(long a, long b) {
return Math.max(a, b);
}
static public double max(int a, double b) {
return Math.max((double) a, b);
}
static public float max(float a, float b) {
return Math.max(a, b);
}
static public double max(double a, double b) {
return Math.max(a, b);
}
static public > A max(Iterable l) {
A max = null;
var it = iterator(l);
if (it.hasNext()) {
max = it.next();
while (it.hasNext()) {
A a = it.next();
if (cmp(a, max) > 0)
max = a;
}
}
return max;
}
static public double max(double[] c) {
if (c.length == 0)
return Double.MIN_VALUE;
double x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static public float max(float[] c) {
if (c.length == 0)
return Float.MAX_VALUE;
float x = c[0];
for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]);
return x;
}
static public byte max(byte[] c) {
byte x = -128;
for (byte d : c) if (d > x)
x = d;
return x;
}
static public short max(short[] c) {
short x = -0x8000;
for (short d : c) if (d > x)
x = d;
return x;
}
static public int max(int[] c) {
int x = Integer.MIN_VALUE;
for (int d : c) if (d > x)
x = d;
return x;
}
static public > A max(A a, A b) {
return cmp(a, b) >= 0 ? a : b;
}
static public void _handleError(Error e) {
}
static public Iterator iterator(Iterable c) {
return c == null ? emptyIterator() : c.iterator();
}
static public int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static public int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static public int cmp(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static public int cmp(long a, long b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static public 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 public Iterator emptyIterator() {
return Collections.emptyIterator();
}
static public interface IFieldsToList {
public Object[] _fieldsToList();
}
static public class G22CriticalPixelSearch implements Steppable {
final public G22CriticalPixelSearch setMasksHolder(IG22MasksHolder> masksHolder) {
return masksHolder(masksHolder);
}
public G22CriticalPixelSearch masksHolder(IG22MasksHolder> masksHolder) {
this.masksHolder = masksHolder;
return this;
}
final public IG22MasksHolder> getMasksHolder() {
return masksHolder();
}
public IG22MasksHolder> masksHolder() {
return masksHolder;
}
public IG22MasksHolder> masksHolder;
final public G22CriticalPixelSearch setKeepAllEntries(boolean keepAllEntries) {
return keepAllEntries(keepAllEntries);
}
public G22CriticalPixelSearch keepAllEntries(boolean keepAllEntries) {
this.keepAllEntries = keepAllEntries;
return this;
}
final public boolean getKeepAllEntries() {
return keepAllEntries();
}
public boolean keepAllEntries() {
return keepAllEntries;
}
public boolean keepAllEntries = false;
final public G22CriticalPixelSearch setSortPixelsFirst(boolean sortPixelsFirst) {
return sortPixelsFirst(sortPixelsFirst);
}
public G22CriticalPixelSearch sortPixelsFirst(boolean sortPixelsFirst) {
this.sortPixelsFirst = sortPixelsFirst;
return this;
}
final public boolean getSortPixelsFirst() {
return sortPixelsFirst();
}
public boolean sortPixelsFirst() {
return sortPixelsFirst;
}
public boolean sortPixelsFirst = true;
public int w, h;
public Iterator pixelIterator;
public Best bestPixel = new Best();
public Entry bestEntry;
public Pt lastPixelLookedAt;
public Entry lastEntry;
public Entry[] pixelEntries;
public float[] pixelScores;
public int nPixelsTested;
public CompactHashSet subSets;
public G22CriticalPixelSearch() {
}
public G22CriticalPixelSearch(IG22MasksHolder masksHolder) {
this.masksHolder = masksHolder;
}
public class Entry {
public Pt pixel;
final public List getDarkMasks() {
return darkMasks();
}
public List darkMasks() {
return darkMasks;
}
public List darkMasks;
final public List getBrightMasks() {
return brightMasks();
}
public List brightMasks() {
return brightMasks;
}
public List brightMasks;
public G22GhostImage darkGhost;
public G22GhostImage brightGhost;
public IG22MasksHolder darkHolder_cache;
public IG22MasksHolder darkHolder() {
if (darkHolder_cache == null)
darkHolder_cache = darkHolder_load();
return darkHolder_cache;
}
public IG22MasksHolder darkHolder_load() {
return new G22HashedMasks(darkMasks, darkGhost);
}
public IG22MasksHolder brightHolder_cache;
public IG22MasksHolder brightHolder() {
if (brightHolder_cache == null)
brightHolder_cache = brightHolder_load();
return brightHolder_cache;
}
public IG22MasksHolder brightHolder_load() {
return new G22HashedMasks(brightMasks, brightGhost);
}
public void calcGhosts() {
if (l(darkMasks) < l(brightMasks)) {
darkGhost = new G22GhostImage(lmapMethod(__91 -> __91.image(), darkMasks));
brightGhost = masksHolder().ghost().minus(darkGhost);
} else {
brightGhost = new G22GhostImage(lmapMethod(__92 -> __92.image(), brightMasks));
darkGhost = masksHolder().ghost().minus(brightGhost);
}
}
public String toString() {
return commaCombine("Split at " + pixel, "dark=" + darkHolder().renderCountAndCertainty(), "bright=" + brightHolder().renderCountAndCertainty());
}
}
public boolean step() {
if (w == 0) {
if (!masksHolder.canSplit())
return false;
w = masksHolder.maskSize().w();
h = masksHolder.maskSize().h();
pixelEntries = new Entry[w * h];
pixelScores = new float[w * h];
arrayfill(pixelScores, -1);
pixelIterator = makePixelIterator();
}
if (!pixelIterator.hasNext())
return false;
lastPixelLookedAt = pixelIterator.next();
testPixel(lastPixelLookedAt);
return true;
}
public int idx(Pt p) {
return p.y * w + p.x;
}
public void testPixel(Pt p) {
double score;
Entry e = null;
++nPixelsTested;
float ghostBrightness = masksHolder.ghost().getFloatPixel(p);
if (ghostBrightness == 0 || ghostBrightness == 1)
score = -2;
else {
e = new Entry();
e.pixel = p;
lastEntry = e;
if (keepAllEntries)
pixelEntries[idx(p)] = e;
List masks = wideningListCast(masksHolder.masks());
int n = l(masks);
byte[] brightBits = byteArrayForNBits(n);
for (int i = 0; i < n; i++) if (masks.get(i).image().getBoolPixel(p))
setBit(brightBits, i);
{
if (subSets != null)
subSets.add(new HashedByteArray(brightBits));
}
var splitMasks = filterAntiFilterByBitSet(masks, brightBits);
e.brightMasks = splitMasks.a;
e.darkMasks = splitMasks.b;
e.calcGhosts();
score = scoreEntry(e);
}
pixelScores[idx(p)] = (float) score;
if (score > 0 && bestPixel.put(p, score))
bestEntry = e;
}
transient public IF1 scoreEntry;
public double scoreEntry(Entry e) {
return scoreEntry != null ? scoreEntry.get(e) : scoreEntry_base(e);
}
final public double scoreEntry_fallback(IF1 _f, Entry e) {
return _f != null ? _f.get(e) : scoreEntry_base(e);
}
public double scoreEntry_base(Entry e) {
double c1 = e.darkGhost.certainty();
double c2 = e.brightGhost.certainty();
return min(c1, c2);
}
public double bestScore() {
return bestPixel.score();
}
public BWImage scoreImage() {
double min = masksHolder.certainty();
double max = bestPixel.score();
return bwImageFromFunction(w, h, (x, y) -> transformToZeroToOne(pixelScores[y * w + x], max, min));
}
public G22PixelSplitMasks> splitMasksHolder() {
if (!bestPixel.has())
return null;
return new G22PixelSplitMasks().splitPixel(bestPixel.get()).darkHolder(bestEntry.darkHolder()).brightHolder(bestEntry.brightHolder());
}
final public IG22MasksHolder bestTree() {
return makeBestTree();
}
public IG22MasksHolder makeBestTree() {
stepAll(this);
G22PixelSplitMasks> split = splitMasksHolder();
if (split == null)
return masksHolder;
split.transformSubHolders(subHolder -> new G22CriticalPixelSearch(subHolder).makeBestTree());
return split;
}
public void collectSubSets() {
if (subSets == null)
subSets = new CompactHashSet();
}
public Iterator makePixelIterator() {
if (sortPixelsFirst)
return iterator(pixelsByBrightness(masksHolder().ghost().certaintyImage()));
else
return new WeightlessShuffledIterator(pixelsInImage(w, h));
}
}
public interface IG22MasksHolder {
public WidthAndHeight maskSize();
public List maskImages();
public List extends IG22Mask> masks();
public G22GhostImage ghost();
public double certainty();
default public int nMasks() {
return l(masks());
}
default public String renderCountAndCertainty() {
return main.nMasks(nMasks()) + " with c=" + formatDouble3(certainty());
}
default public boolean canSplit() {
return nMasks() > 1;
}
default public List> subHolders() {
return null;
}
default public void transformSubHolders(IF1, IG22MasksHolder> f) {
}
default public PStackComputable findSimilarMasks(G22FindSimilarMasksTask task) {
return new FindSimilarMasks_BruteForce(this, task);
}
static public class FindSimilarMasks_BruteForce extends PStackComputableWithStep implements IFieldsToList {
public IG22MasksHolder masksHolder;
public G22FindSimilarMasksTask task;
public FindSimilarMasks_BruteForce() {
}
public FindSimilarMasks_BruteForce(IG22MasksHolder masksHolder, G22FindSimilarMasksTask task) {
this.task = task;
this.masksHolder = masksHolder;
}
public Object[] _fieldsToList() {
return new Object[] { masksHolder, task };
}
public IG22Mask maskBeingTested;
public String toString() {
return formatFunctionCall(shortClassName(this), masksHolder, "step=" + step);
}
public void step(IPStack stack) {
if (step == 0) {
++step;
stack.optionsOrReturn(this, map(masksHolder.masks(), mask -> self -> self.maskBeingTested = mask));
} else {
task.tryMask(maskBeingTested);
stack._return();
}
}
}
}
static public class G22Utils_Base {
transient public Set> onProjectFileChanged;
public G22Utils_Base onProjectFileChanged(IVF1 f) {
onProjectFileChanged = createOrAddToSyncLinkedHashSet(onProjectFileChanged, f);
return this;
}
public G22Utils_Base removeProjectFileChangedListener(IVF1 f) {
main.remove(onProjectFileChanged, f);
return this;
}
public void projectFileChanged(File file) {
if (onProjectFileChanged != null)
for (var listener : onProjectFileChanged) pcallF_typed(listener, file);
}
}
static public class G22Utils extends G22Utils_Base implements AutoCloseable, TransientObject {
final public G22Utils setBackgroundProcessesUI(IBackgroundProcesses backgroundProcessesUI) {
return backgroundProcessesUI(backgroundProcessesUI);
}
public G22Utils backgroundProcessesUI(IBackgroundProcesses backgroundProcessesUI) {
this.backgroundProcessesUI = backgroundProcessesUI;
return this;
}
final public IBackgroundProcesses getBackgroundProcessesUI() {
return backgroundProcessesUI();
}
public IBackgroundProcesses backgroundProcessesUI() {
return backgroundProcessesUI;
}
public IBackgroundProcesses 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;
}
public 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;
}
public 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;
}
public 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;
}
public G22ProjectActions projectActions;
final public G22AutoStarter getAutoStarter() {
return autoStarter();
}
public G22AutoStarter autoStarter() {
return autoStarter;
}
public G22AutoStarter autoStarter = new G22AutoStarter(this);
final public G22Utils setFunctionTimings(FunctionTimings functionTimings) {
return functionTimings(functionTimings);
}
public G22Utils functionTimings(FunctionTimings functionTimings) {
this.functionTimings = functionTimings;
return this;
}
final public FunctionTimings getFunctionTimings() {
return functionTimings();
}
public FunctionTimings functionTimings() {
return functionTimings;
}
public FunctionTimings functionTimings = new FunctionTimings();
public FileWatchService fileWatcher;
public boolean projectFileListenerInitiated = false;
final public CombinedStringifier getStringifier() {
return stringifier();
}
public CombinedStringifier stringifier() {
return stringifier;
}
public CombinedStringifier stringifier = new CombinedStringifier(o -> o instanceof BufferedImage ? "Image (" + ((BufferedImage) o).getWidth() + "*" + ((BufferedImage) o).getHeight() + " px)" : null);
public ILASClassLoader lasClassLoader() {
return masterStuff == null ? null : masterStuff.lasClassLoader();
}
public ImageSurface stdImageSurface_noToolTip() {
return stdImageSurface_noToolTip(imageSurface());
}
public ImageSurface stdImageSurface_noToolTip(ImageSurface is) {
imageSurface_pixelated(is);
is.setAutoZoomToDisplay(true).repaintInThread(false);
is.defaultImageDir = () -> dbDir();
is.specialPurposed = true;
return is;
}
public ImageSurface stdImageSurface() {
return stdImageSurface(imageSurface());
}
public ImageSurface stdImageSurface(ImageSurface is) {
stdImageSurface_noToolTip(is);
new ImageSurface_PositionToolTip(is);
return is;
}
public List stdImageSurfaces(Collection images) {
return map(__56 -> stdImageSurface(__56), toBufferedImages(images));
}
public ImageSurface stdImageSurface(MakesBufferedImage img) {
return stdImageSurface(toBufferedImage(img));
}
public ImageSurface stdImageSurface(BufferedImage img) {
var is = stdImageSurface();
is.setImage(img);
return is;
}
public ImageSurface stdImageSurface(File file) {
var is = stdImageSurface();
is.setImage(file);
return is;
}
public ImageSurface stdImageSurface(G22GalleryImage img) {
return stdImageSurface(img == null ? null : img.path);
}
public ImageSurface stdImageSurfaceWithSelection(MakesBufferedImage img, Rect selection) {
return stdImageSurfaceWithSelection(toBufferedImage(img), selection);
}
public ImageSurface stdImageSurfaceWithSelection(BufferedImage img, Rect selection) {
var is = stdImageSurface(img);
is.setSelection(selection);
return is;
}
public String stringify(Object o) {
return stringifier.toString(o);
}
transient public 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) {
if (onSettingUpParser != null)
for (var listener : onSettingUpParser) pcallF_typed(listener, parser);
}
transient public Set> onSettingUpScriptIDE;
public G22Utils onSettingUpScriptIDE(IVF1 f) {
onSettingUpScriptIDE = createOrAddToSyncLinkedHashSet(onSettingUpScriptIDE, f);
return this;
}
public G22Utils removeSettingUpScriptIDEListener(IVF1 f) {
main.remove(onSettingUpScriptIDE, f);
return this;
}
public void settingUpScriptIDE(JLeftArrowScriptIDE ide) {
if (onSettingUpScriptIDE != null)
for (var listener : onSettingUpScriptIDE) pcallF_typed(listener, ide);
}
public GazelleV_LeftArrowScriptParser leftArrowParser() {
GazelleV_LeftArrowScriptParser parser = new GazelleV_LeftArrowScriptParser();
parser.classNameResolver(classNameResolver());
parser.lasClassLoader(lasClassLoader());
settingUpParser(parser);
parser.addClassAlias("Freq", "Frequency");
parser.addClassAlias("MRUAndAllTimeTop", "MRUAndAllTimeTop_optimized");
return parser;
}
public Object leftArrow(String script) {
return leftArrowParser().parse(script).get();
}
public void basicParserTest() {
var parser = leftArrowParser();
print("classContainerPrefixes", parser.classContainerPrefixes());
assertEquals(pair(1, 2), parser.parse("new Pair 1 2").get());
}
public JLeftArrowScriptIDE leftArrowIDE() {
JLeftArrowScriptIDE ide = new JLeftArrowScriptIDE();
ide.g22utils(this);
ide.scriptTimeout(projectWideScriptTimeout());
settingUpScriptIDE(ide);
return ide;
}
public File byteCodePath() {
return assertNotNull(getBytecodePathForClass(this));
}
public ClassNameResolver classNameResolver_cache;
public ClassNameResolver classNameResolver() {
if (classNameResolver_cache == null)
classNameResolver_cache = classNameResolver_load();
return classNameResolver_cache;
}
public ClassNameResolver classNameResolver_load() {
return new ClassNameResolver().byteCodePath(byteCodePath()).init();
}
public File databasesMotherDir() {
return masterStuff.databasesMotherDir();
}
public File dirOfProjectNamed(String name) {
assertNempty(name);
return newFile(databasesMotherDir(), name);
}
public AutoCloseable enter() {
return module == null ? null : module.enter();
}
public String defaultDBName() {
return "Default";
}
public File lastOpenedDBsFile() {
return newFile(databasesMotherDir(), "Last Opened");
}
public File recentlyOpenedDBsFile() {
return newFile(databasesMotherDir(), "Recently Opened");
}
public File autoUpdateFile() {
return newFile(databasesMotherDir(), "Auto-Update");
}
public boolean autoUpdateEnabled() {
return fileExists(autoUpdateFile());
}
public void setAutoUpdate(boolean b) {
createOrRemoveFile(autoUpdateFile(), b);
}
public List dbsToOpen() {
return loadRecentProjectsFile(lastOpenedDBsFile());
}
public List dbNamesRecentlyOpened() {
return loadRecentProjectsFile(recentlyOpenedDBsFile());
}
public void addToRecentDBNames(String dbName, boolean hidden) {
List list = dbNamesRecentlyOpened();
List list2 = cloneList(list);
removeAll(list2, dbName, "*" + dbName);
list2.add(0, hidden ? "*" + dbName : dbName);
truncateList(list2, 100);
if (!eq(list, list2))
saveTextFile(recentlyOpenedDBsFile(), lines(list2));
}
public List loadRecentProjectsFile(File file) {
List dbNames = new ArrayList();
for (String name : tlft(loadTextFile(file))) {
String name2 = dropPrefix("*", name);
if (fileExists(newFile(databasesMotherDir(), name2)))
dbNames.add(name);
}
if (empty(dbNames))
dbNames.add(defaultDBName());
return dbNames;
}
public void setOpenDBs(Collection extends IG22LoadedDB> dbs) {
List dbNames = new ArrayList();
for (var db : dbs) {
var dbDir = conceptsDir(db.concepts());
if (sameFile(databasesMotherDir(), dirOfFile(dbDir)))
dbNames.add((db.hidden() ? "*" : "") + fileName(dbDir));
}
saveTextFile(lastOpenedDBsFile(), lines(dbNames));
}
public void setupScriptCRUD(SimpleCRUD_v2 crud) {
setupScriptCRUD(crud, false);
}
public void setupScriptCRUD(SimpleCRUD_v2 crud, boolean allowRunOnProjectOpen) {
crud.useNewChangeHandler(true);
crud.editableFieldsForItem = x -> llNonNulls("description", allowRunOnProjectOpen ? "runOnProjectOpen" : null, allowRunOnProjectOpen ? "runOrder" : null);
crud.multiLineField("text");
crud.multiLineField("editingText");
crud.makeTextArea = text -> jMinHeight(200, crud.makeTextArea_base(text));
crud.humanizeFieldNames = false;
crud.iconButtons(true);
crud.itemToMap_inner2 = c -> scriptToMap(c, allowRunOnProjectOpen);
crud.dontDuplicateFields = litset("runOnProjectOpen", "runOrder", "runCount", "lastResultByMode");
}
public Map scriptToMap(G22LeftArrowScript c) {
return scriptToMap(c, false);
}
public Map scriptToMap(G22LeftArrowScript c, boolean allowRunOnProjectOpen) {
return litorderedmap("Description", str(c), "Status", renderScriptStatus(c), "LoC", renderScriptLoC(c), "Import note", c.importNote, "Run on project open", c.renderRunOnProjectOpenStatus());
}
public 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));
}
public String renderScriptLoC(G22LeftArrowScript c) {
return n2(intMax(mapLL(__57 -> linesOfCode_javaTok(__57), c.editingText, c.text, c.codeForAutoRun())));
}
public List labelsForFile(File file) {
if (file == null)
return null;
File labelsFile = appendToFileName(file, ".labels");
List labels = tlft(loadTextFile(labelsFile));
return map(__58 -> getLabel(__58), labels);
}
public File labelsFile(File file) {
if (file == null)
return null;
return appendToFileName(file, ".labels");
}
public 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);
}
public 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);
}
final public File projectDir() {
return dbDir();
}
public File dbDir() {
return conceptsDir(concepts);
}
final public File projectFile(String name) {
return fileInDbDir(name);
}
public File fileInDbDir(String name) {
return newFile(dbDir(), name);
}
public class GazelleDB implements IFieldsToList {
public String name;
public File dir;
public GazelleDB() {
}
public 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 };
}
public String name() {
return name;
}
public File dir() {
return dir;
}
public boolean loaded() {
return loadedDB() != null;
}
public IG22LoadedDB loadedDB_cache;
public IG22LoadedDB loadedDB() {
if (loadedDB_cache == null)
loadedDB_cache = loadedDB_load();
return loadedDB_cache;
}
public IG22LoadedDB loadedDB_load() {
return masterStuff.getLoadedDBForConceptDir(dir);
}
public File conceptsFile() {
return conceptsFileIn(dir);
}
}
public List gazelleDBs() {
List dbs = new ArrayList();
for (File dir : listDirsContainingFileNamed(databasesMotherDir(), "concepts.structure.gz")) dbs.add(new GazelleDB(fileName(dir), dir));
return dbs;
}
public IterableIterator peekAllProjectsConcepts() {
var classFinder = masterStuff.makeClassFinder();
return mapI_pcall(gazelleDBs(), db -> {
var cc = newConceptsWithClassFinder(db.conceptsFile(), classFinder);
cc.loadFromDisk();
return cc;
});
}
public RSyntaxTextAreaWithSearch newSyntaxTextArea() {
return newSyntaxTextArea((IF1) null);
}
public RSyntaxTextAreaWithSearch newSyntaxTextArea(IF1 wrapStatusLabel) {
RSyntaxTextAreaWithSearch ta = new RSyntaxTextAreaWithSearch(wrapStatusLabel);
ta.textArea().setHighlightCurrentLine(false);
ta.menuLessOperation();
return ta;
}
public RSyntaxTextAreaWithSearch newSyntaxTextArea(String text) {
var ta = newSyntaxTextArea();
ta.setText(text);
return ta;
}
public File projectStoryTextFile() {
return newFile(dbDir(), "story.txt");
}
public String projectName() {
return fileName(dbDir());
}
public void close() {
try {
autoStarter.close();
{
cleanUp(fileWatcher);
fileWatcher = null;
}
} catch (Exception __e) {
throw rethrow(__e);
}
}
public G22Variable findProjectVar(String name) {
return conceptWhere(concepts, G22Variable.class, "name", name);
}
public Object getProjectVar(String name) {
G22Variable var = findProjectVar(name);
return var == null ? null : var.value();
}
public Object getProjectVarOrCallScript(String name, long scriptID) {
{
var __2 = getProjectVar(name);
if (__2 != null)
return __2;
}
return callScript(scriptID);
}
public Object getProjectVarSetByScript(String name, long scriptID) {
{
var __3 = getProjectVar(name);
if (__3 != null)
return __3;
}
callScript(scriptID);
return getProjectVar(name);
}
public List getVarFromAnyProject(String name) {
return nonNulls(masterStuff().openProjects(), project -> project.g22utils().getProjectVar(name));
}
public G22Variable projectVarConcept(String name) {
return optimizedUniq(concepts, G22Variable.class, "name", name);
}
public Object waitForProjectVar(String name) {
return waitForProjectVar(infinity(), name);
}
public Object waitForProjectVar(double timeoutSeconds, String name) {
G22Variable var = projectVarConcept(name);
return waitForCalculatedValueUsingChangeListener(timeoutSeconds, () -> var.value(), var);
}
public void setBigProjectVar(boolean persistent, String name, Object value) {
if (persistent)
setBigProjectVar(name, value);
else
setTransientProjectVar(name, value);
}
public G22Variable setProjectVar(boolean persistent, String name, Object value) {
G22Variable var = projectVarConcept(name);
if (!persistent)
var.persistent(persistent);
var.value(value);
if (persistent)
var.persistent(persistent);
return var;
}
public void unloadProjectVar(String name) {
var var = findProjectVar(name);
{
if (var != null)
var.unload();
}
}
public void setBigProjectVar(String name, Object value) {
setPersistentProjectVar(name, value);
G22Variable var = projectVarConcept(name);
var.makeBig();
}
public Object getCachedProjectVar(String name) {
var var = findProjectVar(name);
return var == null ? null : var.cachedValue();
}
public boolean isBigProjectVar(String name) {
var v = findProjectVar(name);
return v != null && v.big();
}
public void setPersistentProjectVar(String name, Object value) {
setProjectVar(true, name, value);
}
public G22Variable setTransientProjectVar(String name, Object value) {
return setProjectVar(false, name, value);
}
public void setAutoClosingProjectVar(String name, Object value) {
setTransientProjectVar(name, value).autoClose(true);
}
public void deleteProjectVar(String name) {
deleteConcept(findProjectVar(name));
}
public Object getOrCreateProjectVar(String name, IF0 maker) {
return getOrCreateProjectVar(projectVarConcept(name), maker);
}
public Object getOrCreatePersistentProjectVar(String name, IF0 maker) {
var var = projectVarConcept(name);
Object value = getOrCreateProjectVar(var, maker);
var.persistent(true);
return value;
}
public Object getOrCreateProjectVar(G22Variable var, IF0 maker) {
if (!var.has()) {
Object value = maker.get();
if (value != null)
var.setValueIfNull(value);
}
return var.get();
}
public IVarWithNotify liveProjectVar(String name) {
return liveProjectVar(name, null);
}
public IVarWithNotify liveProjectVar(String name, Object defaultValue) {
G22Variable var = projectVarConcept(name);
var.persistent(true);
var.setValueIfNull(defaultValue);
return var.varValue();
}
public IVarWithNotify liveTransientProjectVar(String name) {
return liveTransientProjectVar(name, null);
}
public IVarWithNotify liveTransientProjectVar(String name, Object defaultValue) {
G22Variable var = projectVarConcept(name);
var.persistent(false);
var.setValueIfNull(defaultValue);
return var.varValue();
}
public void replaceCloseableProjectVar(String name, IF0 extends AutoCloseable> calc) {
Object value = getProjectVar(name);
if (value instanceof AutoCloseable) {
main.close((AutoCloseable) value);
deleteProjectVar(name);
}
setTransientProjectVar(name, calc == null ? null : calc.get());
}
public void projectVarChanged(String name) {
var var = findProjectVar(name);
{
if (var != null)
var.changeInsideOfValue();
}
}
public Collection projectVarChanged(Object value) {
var vars = conceptsWhere(concepts, G22Variable.class, "value", value);
for (var var : vars) var.change();
return vars;
}
public double defaultScriptTimeout() {
return 10.0;
}
public double projectWideScriptTimeout() {
return or(toDoubleOrNull(getProjectVar("!Script Timeout")), defaultScriptTimeout());
}
public G22Analyzer getAnalyzer(long id) {
var a = getConcept(concepts, G22Analyzer.class, id);
if (a == null)
throw fail("Analyzer not found: " + id);
return a;
}
public G22LeftArrowScript getScript(long id) {
var a = getConcept(concepts, G22LeftArrowScript.class, id);
if (a == null)
throw fail("Script not found: " + id);
return a;
}
public Object callScript(long id) {
var script = getScript(id);
return script.evaluateWithoutTimeout();
}
public Object callAutoRunnableScript(long id) {
var script = getScript(id);
return script.evaluateAutoRunWithoutTimeout();
}
public double defaultTimeout() {
return infinity();
}
public A evalRegisteredCode(String processName, IF0 code) {
return evalRegisteredCode(defaultTimeout(), processName, code);
}
public A evalRegisteredCode(double timeoutSeconds, String processName, IF0 code) {
if (code == null)
return null;
return evalWithTimeoutOrTypedException(timeoutSeconds, () -> {
AutoCloseable __4 = enter();
try {
var process = backgroundProcessesUI.tempAdd(processName);
try {
Thread myThread = currentThread();
process.setInterruptAction(new Runnable() {
public void run() {
try {
cancelThread(myThread);
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "cancelThread(myThread)";
}
});
return code.get();
} finally {
_close(process);
}
} finally {
_close(__4);
}
});
}
public Object host() {
AutoCloseable __5 = enter();
try {
return dm_os();
} finally {
_close(__5);
}
}
public A timeFunction(String name, IF0 f) {
return functionTimings.get(name, f);
}
public boolean isConceptsDir(File dir) {
return isSameFile(conceptsDir(concepts), dir);
}
synchronized public FileWatchService fileWatcher() {
{
if (fileWatcher == null)
fileWatcher = new FileWatchService();
return fileWatcher;
}
}
synchronized public G22Utils onProjectFileChanged(IVF1 listener) {
super.onProjectFileChanged(listener);
if (!projectFileListenerInitiated) {
projectFileListenerInitiated = true;
fileWatcher().addRecursiveListener(dbDir(), __6 -> projectFileChanged(__6));
}
return this;
}
public G22ProjectInfo projectInfo_cache;
public G22ProjectInfo projectInfo() {
if (projectInfo_cache == null)
projectInfo_cache = projectInfo_load();
return projectInfo_cache;
}
public G22ProjectInfo projectInfo_load() {
return optimizedUniq(concepts, G22ProjectInfo.class);
}
public RunnablesReferenceQueue runnablesReferenceQueue() {
return masterStuff.runnablesReferenceQueue();
}
public EphemeralObjectIDs ephemeralObjectIDs() {
return masterStuff.ephemeralObjectIDs();
}
public Object eph(long id) {
return ephemeralObjectIDs().get(id);
}
public void openInBrowser(String url) {
if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
main.openInBrowser(url);
else {
String cmd;
if (projectInfo().useFirefox() && isOnPATH("firefox"))
cmd = "firefox";
else {
cmd = chromeCmd();
if (isRoot())
cmd += " -no-sandbox";
}
cmd += " " + platformQuote(url);
nohup(cmd);
}
}
public String compilationDate() {
return or2(compilationDateFromClassPath(this), "unknown");
}
public String projectID() {
return projectInfo().projectID();
}
public IG22LoadedDB getLoadedDB() {
return masterStuff.getLoadedDB(concepts);
}
public ConceptsComboBox galleryImagesComboBox() {
return swing(() -> new ConceptsComboBox(concepts, G22GalleryImage.class));
}
public IBackgroundProcess tempAddBackgroundProcess(String name) {
return backgroundProcessesUI == null ? null : backgroundProcessesUI.tempAdd(name);
}
public IF1 classFinder() {
return masterStuff.makeClassFinder();
}
public Object restructure(Object o) {
return unstructure(structure(o), false, concepts.classFinder);
}
public G22ProjectActions project() {
return projectActions();
}
public boolean openPathInProject(String path) {
return projectActions().openPathInProject(path);
}
final public boolean showUIURL(String url) {
return openUIURL(url);
}
public boolean openUIURL(String url) {
return projectActions().openUIURL(url);
}
public BufferedImage loadProjectImage(String fileName) {
return loadImage2(projectFile(fileName));
}
public IG22LoadedDB openDB(String name) {
return openDB(name, false);
}
public IG22LoadedDB openDB(String name, boolean hidden) {
return masterStuff().openDB(name, hidden);
}
public G22Utils getProject(String name) {
return openDB(name, true).g22utils();
}
public G22JavaObjectVisualizer visualizeObject(Object o) {
return new G22JavaObjectVisualizer(this, o);
}
transient public IF0 makeVariablesPanel;
public G22VariablesPanel makeVariablesPanel() {
return makeVariablesPanel != null ? makeVariablesPanel.get() : makeVariablesPanel_base();
}
final public G22VariablesPanel makeVariablesPanel_fallback(IF0 _f) {
return _f != null ? _f.get() : makeVariablesPanel_base();
}
public G22VariablesPanel makeVariablesPanel_base() {
return new G22VariablesPanel().g22utils(this);
}
transient public IF0 jGazelleLogo;
public JComponent jGazelleLogo() {
return jGazelleLogo != null ? jGazelleLogo.get() : jGazelleLogo_base();
}
final public JComponent jGazelleLogo_fallback(IF0 _f) {
return _f != null ? _f.get() : jGazelleLogo_base();
}
public JComponent jGazelleLogo_base() {
return main.jGazelleLogo();
}
public boolean devMode() {
return masterStuff().devMode();
}
public List list(Class type) {
return list(type, concepts());
}
public List list(Class type, Concepts cc) {
return main.list(cc, type);
}
public List list(Concepts concepts, Class type) {
return main.list(type, concepts);
}
public G22GalleryImage galleryImageForMD5(String md5) {
return firstThat(list(concepts, G22GalleryImage.class), img -> cic(fileName(img.path), md5));
}
public JComponent wrapImageSurface(ImageSurface is) {
return is == null ? null : jscroll_centered_borderless(is);
}
public JComponent wrap(Object o) {
var c = main.wrap(o);
if (c instanceof ImageSurface)
return wrapImageSurface((ImageSurface) c);
return c;
}
transient public IF0 byUser;
public String byUser() {
return byUser != null ? byUser.get() : byUser_base();
}
final public String byUser_fallback(IF0 _f) {
return _f != null ? _f.get() : byUser_base();
}
public String byUser_base() {
return "";
}
final public Collection extends IG22LoadedDB> openProjects() {
return getLoadedDBs();
}
public Collection extends IG22LoadedDB> getLoadedDBs() {
return masterStuff().openProjects();
}
public List listInOpenProjects(Class type) {
return concatMap(openProjects(), db -> db.g22utils().list(type));
}
transient public PicturesByMD5 picturesByMD5_cache;
public PicturesByMD5 picturesByMD5() {
if (picturesByMD5_cache == null)
picturesByMD5_cache = picturesByMD5_load();
return picturesByMD5_cache;
}
public PicturesByMD5 picturesByMD5_load() {
return new PicturesByMD5(projectFile("Images")).extension(".qoi");
}
}
static abstract public class IterableIterator implements Iterator, Iterable {
public Iterator iterator() {
return this;
}
public void remove() {
unsupportedOperation();
}
}
public interface IG22SimpleMasksHolder extends IG22MasksHolder {
}
static public class G22HashedMasks implements IG22SimpleMasksHolder> {
public G22HashedMasks() {
}
public class Mask implements IG22Mask>, IFieldsToList {
public Image2B image;
public Mask() {
}
public Mask(Image2B image) {
this.image = image;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + image + ")";
}
public Object[] _fieldsToList() {
return new Object[] { image };
}
final public MultiSet getLabels() {
return labels();
}
public MultiSet labels() {
return labels;
}
public MultiSet labels = new MultiSet();
public int hash;
public boolean equals(Object o) {
if (o instanceof G22HashedMasks.Mask)
return hashCode() == ((G22HashedMasks.Mask) o).hashCode() && binaryImagesIdentical(image, ((G22HashedMasks.Mask) o).image);
return false;
}
public int hashCode() {
if (hash == 0)
hash = (int) hashImage2B(image);
return hash;
}
public Image2B image() {
return image;
}
public MultiSet label() {
return labels;
}
}
public CompactHashSet masks = new CompactHashSet();
public G22HashedMasks(List>> masks) {
assertNempty(masks);
maskSize(imageSize(first(masks).image()));
for (var mask : unnullForIteration(masks)) this.masks.add(mask);
}
public G22HashedMasks(List>> masks, G22GhostImage ghost) {
this(masks);
ghost_cache = ghost;
}
public void addRegion(IImageRegion region, A label) {
addRegion(region, ll(label));
}
public void addRegion(IImageRegion region, Collection labels) {
if (empty(labels))
return;
var mask = new Mask(regionToMaskImage(region));
var existingMask = masks.find(mask);
if (existingMask != null)
mask = existingMask;
else
masks.add(mask);
mask.labels.addAll(labels);
ghost_cache = null;
certainty_cache = null;
this.labels.addAll(labels);
}
public List masks() {
return asList(masks);
}
final public G22HashedMasks setMaskSize(WidthAndHeight maskSize) {
return maskSize(maskSize);
}
public G22HashedMasks maskSize(WidthAndHeight maskSize) {
this.maskSize = maskSize;
return this;
}
final public WidthAndHeight getMaskSize() {
return maskSize();
}
public WidthAndHeight maskSize() {
return maskSize;
}
public WidthAndHeight maskSize;
public MultiSet labels = new MultiSet();
{
maskSize(g22defaultMaskSideLength());
}
public G22HashedMasks maskSize(int size) {
return maskSize(widthAndHeight(size));
}
public Image2B regionToMaskImage(IImageRegion region) {
return toImage2B(scaledIBinaryImage(maskSize, regionToIBinaryImage(region)));
}
public List maskImages() {
return map(masks(), mask -> mask.image());
}
public BufferedImage masksSquare() {
return mergeBufferedImagesAsSquare(allToBufferedImage(maskImages()));
}
public PatchworkImage masksPatchworkSquare() {
return patchworkImagesAsSquare(map(masks(), mask -> pair(toBufferedImage(mask.image()), mask)));
}
public String toString() {
return renderVars(shortClassName(this), "maskSize", maskSize, "masks", n2(masks()));
}
public G22GhostImage ghost_cache;
public G22GhostImage ghost() {
if (ghost_cache == null)
ghost_cache = ghost_load();
return ghost_cache;
}
public G22GhostImage ghost_load() {
return new G22GhostImage(maskImages());
}
public Double certainty_cache;
public double certainty() {
if (certainty_cache == null)
certainty_cache = certainty_load();
return certainty_cache;
}
public double certainty_load() {
return ghost().certainty();
}
}
public interface IVarWithNotify extends IVar, IF0WithChangeListeners {
default public IVarWithNotify onChange(IVF1 r) {
if (r == null)
return this;
onChange(() -> r.get(get()));
return this;
}
default public IVarWithNotify onChangeAndNow(IVF1 r) {
if (r == null)
return this;
onChangeAndNow(() -> r.get(get()));
return this;
}
}
static public 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;
}
public File byteCodePath = byteCodePathForClass(getClass());
public List importedPackages = itemPlusList("java.lang", endingWith_dropSuffix(standardImports(), ".*"));
public Set allFullyQualifiedClassNames_cache;
public Set allFullyQualifiedClassNames() {
if (allFullyQualifiedClassNames_cache == null)
allFullyQualifiedClassNames_cache = allFullyQualifiedClassNames_load();
return allFullyQualifiedClassNames_cache;
}
public 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;
}
public ClassNameResolver init() {
allFullyQualifiedClassNames();
return this;
}
public String findClass(String name) {
for (String pkg : importedPackages) {
String fullName = pkg + "." + name;
if (allFullyQualifiedClassNames().contains(fullName))
return fullName;
}
return null;
}
public void printMe() {
printVars("ClassNameResolver", "byteCodePath", byteCodePath);
print("importedPackages", importedPackages);
}
}
static public class G22GalleryImage extends ConceptWithChangeListeners {
public transient FieldVar varPath_cache;
public FieldVar varPath() {
if (varPath_cache == null)
varPath_cache = varPath_load();
return varPath_cache;
}
public FieldVar varPath_load() {
return new FieldVar(this, "path", () -> path(), path -> path(path));
}
final public G22GalleryImage setPath(File path) {
return path(path);
}
public G22GalleryImage path(File path) {
if (!eq(this.path, path)) {
this.path = path;
change();
}
return this;
}
final public File getPath() {
return path();
}
public File path() {
return path;
}
public File path;
public String toString() {
return fileName(path);
}
public boolean imageExists() {
return fileExists(path);
}
final public BufferedImage image() {
return load();
}
final public BufferedImage getImage() {
return load();
}
public BufferedImage load() {
return loadImage2(path);
}
public File imageFile() {
return path;
}
}
public interface IImageRegion extends INumberOfPixels, IPixelSet {
public Rect bounds();
public IterableIterator pixelIterator();
public boolean contains(int x, int y);
public default Img image() {
return null;
}
public default Object creator() {
return null;
}
public default int indexInCreator() {
return 0;
}
public default Boolean createdWithDiagonals() {
return null;
}
public default int numberOfPixels() {
return l(pixelIterator());
}
public default Pt firstPixel() {
return first(pixelIterator());
}
public default Color color() {
return null;
}
public default int brightness() {
return -1;
}
public default OnePathWithOrigin outline() {
return g22_regionOutline(this);
}
default public Image2B toImage2B() {
return new RegionToImage2B(this).get();
}
default public int[] pixelsAsIntArray() {
throw unimplemented();
}
}
static public class G22ProjectInfo extends Concept {
static final public String _fieldOrder = "projectID projectDir historicalProjectDirs useFirefox";
final public String getProjectID() {
return projectID();
}
public String projectID() {
return projectID;
}
public String projectID = aGlobalID();
public File projectDir;
public List historicalProjectDirs = new ArrayList();
final public boolean getUseFirefox() {
return useFirefox();
}
public boolean useFirefox() {
return useFirefox;
}
public boolean useFirefox = false;
public void addHistoricalProjectDir(File dir) {
if (syncSetAdd(historicalProjectDirs, dir))
change();
}
}
public interface G22ProjectActions {
public void openObjectInProject(long id);
public boolean openPathInProject(String path);
public void editProjectStory();
public void editScripts();
public void editScript(G22LeftArrowScript script);
public boolean openUIURL(String url);
public IVarWithNotify varShowCasedScript();
}
static public class ImageSurface extends Surface {
public BufferedImage image;
public double zoomX = 1, zoomY = 1, zoomFactor = 1.5;
public Rectangle selection;
public List tools = new ArrayList();
public Object overlay;
public List overlays = syncL();
public 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;
}
public boolean verbose = false;
public boolean noMinimumSize = true;
public String titleForUpload;
public Object onZoom;
public boolean specialPurposed = false;
final public ImageSurface setAllowPaste(boolean allowPaste) {
return allowPaste(allowPaste);
}
public ImageSurface allowPaste(boolean allowPaste) {
this.allowPaste = allowPaste;
return this;
}
final public boolean getAllowPaste() {
return allowPaste();
}
public boolean allowPaste() {
return allowPaste;
}
public boolean allowPaste = false;
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;
}
public boolean zoomable = true;
public boolean noAlpha = false;
public Object interpolationMode = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
public Object onNewImage;
public BufferedImage imageToDraw;
public File file;
public boolean autoZoomToDisplay = false;
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;
}
public boolean repaintInThread = false;
public BoolVar showingVar;
public Pt mousePosition;
transient public 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() {
if (onMousePositionChanged != null)
for (var listener : onMousePositionChanged) pcallF_typed(listener);
}
transient public Set onImageChanged;
public ImageSurface onImageChanged(Runnable r) {
onImageChanged = createOrAddToSyncLinkedHashSet(onImageChanged, r);
return this;
}
public ImageSurface removeImageChangedListener(Runnable r) {
main.remove(onImageChanged, r);
return this;
}
public void imageChanged() {
if (onImageChanged != null)
for (var listener : onImageChanged) pcallF_typed(listener);
}
transient public Set> onUserModifiedImage;
public ImageSurface onUserModifiedImage(IVF1 f) {
onUserModifiedImage = createOrAddToSyncLinkedHashSet(onUserModifiedImage, f);
return this;
}
public ImageSurface removeUserModifiedImageListener(IVF1 f) {
main.remove(onUserModifiedImage, f);
return this;
}
public void userModifiedImage(BufferedImage image) {
if (onUserModifiedImage != null)
for (var listener : onUserModifiedImage) pcallF_typed(listener, image);
}
public ImageSurface() {
this(dummyImage());
}
static public BufferedImage dummyImage() {
return whiteImage(1);
}
public ImageSurface(File file) {
setImage(file);
}
public ImageSurface(MakesBufferedImage image) {
this(image != null ? image.getBufferedImage() : dummyImage());
}
public ImageSurface(BufferedImage image) {
setImage(image);
clearSurface = false;
bindToComponent(this, () -> performAutoZoom(), null);
onResize(this, () -> performAutoZoom());
onEnclosingScrollPaneResize(this, () -> performAutoZoom());
componentPopupMenu2(this, ImageSurface_popupMenuMaker());
new ImageSurfaceSelector(this);
jHandleFileDrop(this, new VF1() {
public void get(File f) {
try {
setImage(loadBufferedImage(f));
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "setImage(loadBufferedImage(f))";
}
});
imageSurfaceOnHover(this, p -> {
mousePosition = p;
mousePositionChanged();
});
}
public ImageSurface(RGBImage image, double zoom) {
this(image);
setZoom(zoom);
}
public void fillPopupMenu(JPopupMenu menu, final Point point) {
if (zoomable) {
JMenuItem miZoomReset = new JMenuItem("Zoom 100%");
miZoomReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
setZoom(1.0);
centerPoint(point);
}
});
menu.add(miZoomReset);
JMenuItem miZoomIn = new JMenuItem("Zoom in");
miZoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomIn(zoomFactor);
centerPoint(point);
}
});
menu.add(miZoomIn);
JMenuItem miZoomOut = new JMenuItem("Zoom out");
miZoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomOut(zoomFactor);
centerPoint(point);
}
});
menu.add(miZoomOut);
menu.add(jMenuItemStayCheckedOnClick("Zoom to window", () -> autoZoomToDisplay, () -> setAutoZoomToDisplay(true)));
addMenuItem(menu, "Show full screen", new Runnable() {
public void run() {
try {
showFullScreen();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "showFullScreen()";
}
});
addMenuItem(menu, "Point: " + point.x + "," + point.y + " (image: " + w() + "*" + h() + ")", null);
menu.addSeparator();
}
if (!specialPurposed)
addMenuItem(menu, "Load image...", new Runnable() {
public void run() {
try {
selectFile("Load image", new VF1() {
public void get(File f) {
try {
setImage(loadImage2(f));
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "setImage(loadImage2(f))";
}
});
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "selectFile(\"Load image\",\r\n new VF1() { public void get(File f) c...";
}
});
addMenuItem(menu, "Save image...", new Runnable() {
public void run() {
try {
saveImage();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "saveImage()";
}
});
addMenuItem(menu, "Copy image to clipboard", new Runnable() {
public void run() {
try {
copyImageToClipboard(getImage());
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "copyImageToClipboard(getImage())";
}
});
if (!specialPurposed || allowPaste)
addMenuItem(menu, "Paste image from clipboard", new Runnable() {
public void run() {
try {
loadFromClipboard();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "loadFromClipboard()";
}
});
if (!specialPurposed)
addMenuItem(menu, "Load image snippet...", new Runnable() {
public void run() {
try {
selectImageSnippet(new VF1() {
public void get(String imageID) {
try {
setImage(loadImage2(imageID));
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "setImage(loadImage2(imageID))";
}
});
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "selectImageSnippet(new VF1() { public void get(String imageID) ctex {...";
}
});
if (selection != null)
addMenuItem(menu, "Crop", new Runnable() {
public void run() {
try {
crop();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "crop()";
}
});
if (!specialPurposed)
addMenuItem(menu, "No image", new Runnable() {
public void run() {
try {
noImage();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "noImage()";
}
});
}
public void noImage() {
setImage((BufferedImage) null);
}
public void crop() {
if (selection == null)
return;
BufferedImage img = cloneClipBufferedImage(getImage(), selection);
selection = null;
setUserModifiedImage(img);
}
public void setUserModifiedImage(BufferedImage img) {
setImage(img);
userModifiedImage(img);
}
public void loadFromClipboard() {
BufferedImage img = getImageFromClipboard();
if (img != null)
setUserModifiedImage(img);
}
transient public IF0 defaultImageDir;
public File defaultImageDir() {
return defaultImageDir != null ? defaultImageDir.get() : defaultImageDir_base();
}
final public File defaultImageDir_fallback(IF0 _f) {
return _f != null ? _f.get() : defaultImageDir_base();
}
public File defaultImageDir_base() {
return getProgramDir();
}
public void saveImage() {
var image = getImage();
JFileChooser fileChooser = new JFileChooser(defaultImageDir());
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
main.saveImage(image, file = fileChooser.getSelectedFile());
} catch (Throwable e) {
popup(e);
}
}
}
public void drawImageItself(int w, int h, Graphics2D g) {
int iw = getZoomedWidth(), ih = getZoomedHeight();
if (interpolationMode == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR || zoomX >= 1 || zoomY >= 1) {
g.drawImage(image, 0, 0, iw, ih, null);
} else
g.drawImage(resizeImage(image, iw, ih), 0, 0, null);
}
transient public IVF3 drawBackground;
public void drawBackground(int w, int h, Graphics2D g) {
if (drawBackground != null)
drawBackground.get(w, h, g);
else
drawBackground_base(w, h, g);
}
final public void drawBackground_fallback(IVF3 _f, int w, int h, Graphics2D g) {
if (_f != null)
_f.get(w, h, g);
else
drawBackground_base(w, h, g);
}
public void drawBackground_base(int w, int h, Graphics2D g) {
g.setColor(or(getBackground(), Color.white));
g.fillRect(0, 0, w, h);
}
public void render(int w, int h, Graphics2D g) {
if (verbose)
_print("render");
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolationMode);
drawBackground(w, h, g);
BufferedImage image = or(imageToDraw, this.image);
if (!hasImage())
drawBackground(w, h, g);
else {
boolean alpha = !noAlpha && hasTransparency(image);
if (alpha)
drawBackground(w, h, g);
drawImageItself(w, h, g);
int iw = getZoomedWidth(), ih = getZoomedHeight();
if (!alpha) {
g.fillRect(iw, 0, w - iw, h);
g.fillRect(0, ih, iw, h - ih);
}
}
if (overlay != null) {
if (verbose)
_print("render overlay");
pcallF(overlay, g);
}
for (var overlay : cloneList(overlays)) {
try {
overlay.drawOn(cloneGraphics(g));
} catch (Throwable __e) {
printStackTrace(__e);
}
}
if (selection != null) {
if (verbose)
_print("render selection");
drawSelectionRect(g, selection, Color.green, Color.white);
}
}
public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white) {
drawSelectionRect(g, selection, green, white, zoomX, zoomY);
}
public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white, double zoomX, double zoomY) {
g.setColor(green);
int top = (int) (selection.y * zoomY);
int bottom = (int) ((selection.y + selection.height) * zoomY);
int left = (int) (selection.x * zoomX);
int right = (int) ((selection.x + selection.width) * zoomX);
g.drawRect(left - 1, top - 1, right - left + 1, bottom - top + 1);
g.setColor(white);
g.drawRect(left - 2, top - 2, right - left + 3, bottom - top + 3);
}
public ImageSurface setZoom(double zoom) {
setZoom(zoom, zoom);
return this;
}
public void setZoom(double zoomX, double zoomY) {
autoZoomToDisplay = false;
setZoom_dontChangeAutoZoom(zoomX, zoomY);
}
public void setZoom_dontChangeAutoZoom(double zoomX) {
setZoom_dontChangeAutoZoom(zoomX, zoomX);
}
public void setZoom_dontChangeAutoZoom(double zoomX, double zoomY) {
if (this.zoomX == zoomX && this.zoomY == zoomY)
return;
if (verbose)
_print("Setting zoom");
this.zoomX = zoomX;
this.zoomY = zoomY;
revalidateMe();
repaint();
centerPoint(new Point(getImage().getWidth() / 2, getImage().getHeight() / 2));
pcallF(onZoom);
}
public Dimension getMinimumSize() {
if (metaGet("scaffolding") != null)
scaffoldCalled(this, "getMinimumSize");
if (noMinimumSize)
return new Dimension(1, 1);
int w = getZoomedWidth();
int h = getZoomedHeight();
Dimension min = super.getMinimumSize();
return printIfScaffoldingEnabled(this, new Dimension(Math.max(w, min.width), Math.max(h, min.height)));
}
public int getZoomedHeight() {
return (int) (h() * zoomY);
}
public int getZoomedWidth() {
return (int) (w() * zoomX);
}
public boolean isShowing_quick() {
if (showingVar == null) {
swing(() -> {
if (showingVar == null)
showingVar = componentShowingVar(ImageSurface.this);
});
}
return showingVar.get();
}
public void setImageIfShowing_thisThread(MakesBufferedImage image) {
setImageIfShowing_thisThread(toBufferedImage(image));
}
public void setImageIfShowing_thisThread(BufferedImage image) {
if (isShowing_quick())
setImage_thisThread(image);
}
public void setImage(File file) {
setFile(file);
setImage(loadImage2(file));
}
public void setImage(MakesBufferedImage image) {
swing(() -> {
setImage_thisThread(image);
});
}
public void setImage(BufferedImage img) {
swing(() -> {
setImage_thisThread(img);
});
}
public void setImage_thisThread(MakesBufferedImage img) {
setImage_thisThread(toBufferedImage(img));
}
public void setImage_thisThread(BufferedImage img) {
BufferedImage newImage = img != null ? img : dummyImage();
BufferedImage oldImage = image;
image = newImage;
if (verbose)
print("Old image size:" + imageSize(oldImage) + ", new image size: " + imageSize(newImage));
boolean sameSize = imagesHaveSameSize(oldImage, newImage);
if (!sameSize) {
if (verbose)
_print("New image size");
revalidateMe();
}
quickRepaint();
pcallF(onNewImage);
if (!sameSize && autoZoomToDisplay)
zoomToDisplaySize();
imageChanged();
}
public void setImageAndZoomToDisplay(BufferedImage img) {
setImage(img);
zoomToDisplaySize();
}
public BufferedImage getImage() {
return image;
}
public double getZoomX() {
return zoomX;
}
public double getZoomY() {
return zoomY;
}
public Dimension getPreferredSize() {
if (metaGet("scaffolding") != null)
scaffoldCalled(this, "getPreferredSize");
return printIfScaffoldingEnabled(this, new Dimension(getZoomedWidth(), getZoomedHeight()));
}
public JScrollPane makeScrollPane() {
JScrollPane scrollPane = new JScrollPane(this);
scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
return scrollPane;
}
public void zoomToWindow() {
zoomToDisplaySize();
}
public void zoomToDisplaySize() {
swing(() -> {
if (!hasImage())
return;
Dimension display = getDisplaySize();
if (display.width == 0 || display.height == 0)
return;
int w = w(), h = h();
double xRatio = (display.width - 5) / (double) w;
double yRatio = (display.height - 5) / (double) h;
if (scaffoldingEnabled(this))
printVars("zoomToDisplaySize", "display", display, "w", w, "h", h, "xRatio", xRatio, "yRatio", yRatio);
setZoom_dontChangeAutoZoom(min(xRatio, yRatio));
revalidateMe();
});
}
private Dimension getDisplaySize() {
if (metaGet("scaffolding") != null)
scaffoldCalled(this, "getDisplaySize");
Container c = getParent();
while (c != null) {
if (c instanceof JScrollPane)
return c.getSize();
c = c.getParent();
}
return getSize();
}
public void setSelection(Rect r) {
setSelection(toRectangle(r));
}
public void setSelection(Rectangle r) {
if (neq(selection, r)) {
selection = r;
pcallF(onSelectionChange);
quickRepaint();
}
}
public Rectangle getSelection() {
return selection;
}
public RGBImage getRGBImage() {
return new RGBImage(getImage());
}
public void centerPoint(Point p) {
JScrollPane sp = enclosingScrollPane(this);
if (sp == null)
return;
p = new Point((int) (p.x * getZoomX()), (int) (p.y * getZoomY()));
final JViewport viewport = sp.getViewport();
Dimension viewSize = viewport.getExtentSize();
int x = max(0, p.x - viewSize.width / 2);
int y = max(0, p.y - viewSize.height / 2);
p = new Point(x, y);
final Point _p = p;
awtLater(new Runnable() {
public void run() {
try {
viewport.setViewPosition(_p);
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "viewport.setViewPosition(_p);";
}
});
}
public Pt pointFromEvent(MouseEvent e) {
return pointFromComponentCoordinates(new Pt(e.getX(), e.getY()));
}
public Pt pointFromComponentCoordinates(Pt p) {
return new Pt((int) (p.x / zoomX), (int) (p.y / zoomY));
}
public Pt pointToComponentCoordinates(double x, double y) {
return new Pt((int) (x * zoomX), (int) (y * zoomY));
}
public void uploadTheImage() {
}
public void showFullScreen() {
showFullScreenImageSurface(getImage());
}
public void zoomIn(double f) {
setZoom(getZoomX() * f, getZoomY() * f);
}
public void zoomOut(double f) {
setZoom(getZoomX() / f, getZoomY() / f);
}
public ImageSurface setFile(File f) {
file = f;
return this;
}
public void setOverlay(IVF1 overlay) {
this.overlay = overlay;
}
public boolean hasImage() {
return image != null;
}
public int w() {
return image.getWidth();
}
public int h() {
return image.getHeight();
}
final public void pixelate(boolean b) {
setPixelated(b);
}
public void setPixelated(boolean b) {
assertTrue(b);
imageSurface_pixelated(this);
}
final public ImageSurface autoZoomToDisplay(boolean b) {
return setAutoZoomToDisplay(b);
}
public ImageSurface setAutoZoomToDisplay(boolean b) {
if (autoZoomToDisplay = b)
zoomToDisplaySize();
return this;
}
public void quickRepaint() {
if (repaintInThread)
paintImmediately(0, 0, getWidth(), getHeight());
else
repaint();
}
public void setTool(ImageSurfaceMouseHandler tool) {
swing(() -> {
removeAllTools();
addTool(tool);
});
}
public boolean hasTool(AutoCloseable tool) {
return swing(() -> tools.contains(tool));
}
public void addTool(ImageSurfaceMouseHandler tool) {
swing(() -> {
if (!tools.contains(tool))
tool.register(this);
});
}
public void removeTool(AutoCloseable tool) {
swing(() -> {
if (tools.contains(tool)) {
close(tool);
tools.remove(tool);
}
});
}
final public void clearTools() {
removeAllTools();
}
public void removeAllTools() {
closeAllAndClear(tools);
}
public void performAutoZoom() {
if (autoZoomToDisplay)
zoomToDisplaySize();
}
public void revalidateMe() {
revalidateIncludingFullCenterContainer(this);
}
public void addOverlay(G2Drawable overlay) {
overlays.add(overlay);
repaint();
}
public void clearOverlays() {
if (nempty(overlays)) {
overlays.clear();
repaint();
}
}
public void setOverlay(G2Drawable overlay) {
clearOverlays();
if (overlay != null)
addOverlay(overlay);
}
public void loadImage(File f) {
setImage(loadImage2(f));
}
public JComponent visualize() {
return jscroll_center_borderless(this);
}
public void standardZoom() {
setZoom(1.0);
}
public A print(A a) {
return print("", a);
}
public A print(String msg, A a) {
return _print(msg, a);
}
}
static public VF2 ImageSurface_popupMenuMaker() {
return new VF2() {
public void get(ImageSurface is, JPopupMenu menu) {
try {
Point p = is.pointFromEvent(componentPopupMenu_mouseEvent.get()).getPoint();
is.fillPopupMenu(menu, p);
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "Point p = is.pointFromEvent(componentPopupMenu_mouseEvent.get()).getPoint();\r...";
}
};
}
static public class CombinedStringifier implements IStringifier {
public CopyOnWriteArrayList> stringifiers = new CopyOnWriteArrayList();
public IStringifier defaultStringifier = new Stringifier_ToString();
public CombinedStringifier(IPartialStringifier... stringifiers) {
addAll(this.stringifiers, stringifiers);
}
public String toString(A o) {
for (var stringifier : stringifiers) {
String s = stringifier.toStringOpt(o);
if (s != null)
return s;
}
return defaultStringifier.toString(o);
}
public String toString() {
return formatFunctionCall("CombinedStringifier", listPlus((List) stringifiers, defaultStringifier));
}
}
static final public class BWImage extends Meta implements MakesBufferedImage, IBWImage {
public int width, height;
public byte[] pixels;
public float borderColor = 0.0f;
public BWImage() {
}
public BWImage(int width, int height) {
this.height = height;
this.width = width;
pixels = new byte[width * height];
}
public BWImage(int width, int height, float brightness) {
this.height = height;
this.width = width;
pixels = new byte[width * height];
fillArrayUnlessZero(pixels, _toByte(brightness));
}
public BWImage(int width, int height, float[] pixels) {
this.pixels = new byte[pixels.length];
this.height = height;
this.width = width;
for (int i = 0; i < pixels.length; i++) this.pixels[i] = _toByte(pixels[i]);
}
public BWImage(int width, int height, byte[] pixels) {
this.height = height;
this.width = width;
this.pixels = pixels;
}
public BWImage(BWImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] pixels = this.pixels = new byte[width * height];
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) pixels[y * width + x] = image.getByte(x, y);
}
public BWImage(RGBImage image) {
width = image.getWidth();
height = image.getHeight();
byte[] pixels = this.pixels = new byte[height * width];
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) {
RGB rgb = image.getRGB(x, y);
pixels[y * width + x] = BWImage._toByte(rgb.getBrightness());
}
}
public BWImage(BufferedImage image) {
try {
width = image.getWidth();
height = image.getHeight();
int[] pixels = new int[width * height];
byte[] bytePixels = this.pixels = new byte[width * height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
if (!pixelGrabber.grabPixels())
throw fail("Could not grab pixels");
int n = width * height;
for (int i = 0; i < n; i++) {
int packed = pixels[i];
int r = ((packed >> 16) & 0xFF);
int g = ((packed >> 8) & 0xFF);
int b = (packed & 0xFF);
bytePixels[i] = (byte) ((r + g + b + 1) / 3);
}
} catch (Exception __e) {
throw rethrow(__e);
}
}
static public byte pixelToByte(int packed) {
float r = ((packed >> 16) & 0xFF) / 255f;
float g = ((packed >> 8) & 0xFF) / 255f;
float b = (packed & 0xFF) / 255f;
return (byte) ((r + g + b) / 3.0f * 255f);
}
public byte getByte(int x, int y) {
return inRange(x, y) ? getByte_noRangeCheck(x, y) : _toByte(borderColor);
}
public int getInt(int x, int y) {
return ubyteToInt(getByte(x, y));
}
public int getInt_noRangeCheck(int idx) {
return ubyteToInt(pixels[idx]);
}
public int getInt(int x, int y, int defaultValue) {
return inRange(x, y) ? getInt(x, y) : defaultValue;
}
public double averageBrightness() {
double sum = 0;
int n = width * height;
for (int i = 0; i < n; i++) sum += getInt_noRangeCheck(i);
return sum / n;
}
public float minimumBrightness() {
float min = 1;
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) min = Math.min(min, getPixel(x, y));
return min;
}
public float maximumBrightness() {
float max = 0;
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) max = Math.max(max, getPixel(x, y));
return max;
}
public float getPixel(int x, int y) {
return inRange(x, y) ? _toFloat(getByte(x, y)) : borderColor;
}
public float getFloatPixel(int x, int y) {
return getPixel(x, y);
}
public float getPixel(Pt p) {
return getPixel(p.x, p.y);
}
static public byte _toByte(float pixel) {
return (byte) (pixel * 255f);
}
static public float _toFloat(byte pixel) {
return (((int) pixel) & 255) / 255f;
}
private boolean inRange(int x, int y) {
return x >= 0 && x < width && y >= 0 && y < height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public RGBImage toRGB() {
int[] rgbs = new int[width * height];
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) {
int b = getByte(x, y) & 0xFF;
rgbs[y * width + x] = 0xFF000000 | b * 0x010101;
}
return new RGBImage(width, height, rgbs);
}
public RGBImage toRGB_slow() {
RGB[] rgbs = new RGB[width * height];
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) {
float p = getPixel(x, y);
rgbs[y * width + x] = new RGB(p, p, p);
}
return new RGBImage(width, height, rgbs);
}
public BWImage clip(int x, int y, int w, int h) {
return clip(new Rectangle(x, y, w, h));
}
private Rectangle fixClipRect(Rectangle r) {
return r.intersection(new Rectangle(0, 0, width, height));
}
public BWImage clip(Rect r) {
return clip(r.getRectangle());
}
public BWImage clip(Rectangle r) {
r = fixClipRect(r);
byte[] newPixels = new byte[r.height * r.width];
for (int y = 0; y < r.height; y++) for (int x = 0; x < r.width; x++) newPixels[y * r.width + x] = getByte(r.x + x, r.y + y);
return new BWImage(r.width, r.height, newPixels);
}
public void setPixel(int x, int y, float brightness) {
setByte(x, y, _toByte(fixPixel(brightness)));
}
public void setInt(int x, int y, int i) {
setByte(x, y, (byte) limitToUByte(i));
}
public void setInt(Pt p, int i) {
setInt(p.x, p.y, i);
}
public void setByte(int x, int y, byte b) {
if (x >= 0 && x < width && y >= 0 && y < height)
pixels[y * width + x] = b;
}
public byte getByte_noRangeCheck(int x, int y) {
return pixels[y * width + x];
}
public void setByte(int x, int y, int brightness) {
setByte(x, y, (byte) brightness);
}
private float fixPixel(float pixel) {
return Math.max(0, Math.min(1, pixel));
}
public float getBorderColor() {
return borderColor;
}
public void setBorderColor(float borderColor) {
this.borderColor = borderColor;
}
public boolean anyPixelBrighterThan(double threshold) {
for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) if (getPixel(x, y) > threshold)
return true;
return false;
}
public int[] getRGBPixels() {
int n = width * height;
int[] out = new int[n];
for (int i = 0; i < n; i++) {
var b = ubyteToInt(pixels[i]);
b |= (b << 8) | (b << 16);
out[i] = b | 0xFF000000;
}
return out;
}
public BufferedImage getBufferedImage() {
return bufferedImage(getRGBPixels(), width, height);
}
public byte[] getBytes() {
return pixels;
}
}
static public class Best {
public A best;
public double score;
public boolean verboseNewBest, replaceIfSameScore;
final public Best setLowerIsBetter(boolean lowerIsBetter) {
return lowerIsBetter(lowerIsBetter);
}
public Best lowerIsBetter(boolean lowerIsBetter) {
this.lowerIsBetter = lowerIsBetter;
return this;
}
final public boolean getLowerIsBetter() {
return lowerIsBetter();
}
public boolean lowerIsBetter() {
return lowerIsBetter;
}
public boolean lowerIsBetter = false;
transient public Object onChange;
transient public Object stringifier;
synchronized public boolean isNewBest(double score) {
return best == null || !isNaN(score) && (replaceIfSameScore ? compareScores(score, this.score) >= 0 : compareScores(score, this.score) > 0);
}
public double worstScore() {
return lowerIsBetter ? infinity() : minusInfinity();
}
public int compareScores(double a, double b) {
return lowerIsBetter ? -cmp(a, b) : cmp(a, b);
}
synchronized public double bestScore() {
return best == null ? worstScore() : score;
}
public double score() {
return bestScore();
}
public double getScore() {
return bestScore();
}
synchronized public float floatScoreOr(float defaultValue) {
return best == null ? defaultValue : (float) score;
}
public boolean put(Pair extends A, Double> p) {
return p != null && put(p.a, p.b);
}
public boolean put(Best extends A> b) {
return b != null && put(b.get(), b.score);
}
public boolean put(A a, double score) {
ping();
boolean change = false;
if (a != null)
synchronized (this) {
if (isNewBest(score)) {
best = a;
this.score = score;
change = true;
}
}
if (change) {
if (verboseNewBest)
print("New best! " + this);
pcallF(onChange);
}
return change;
}
synchronized public A get() {
return best;
}
synchronized public boolean has() {
return best != null;
}
synchronized public Pair pair() {
return main.pair(best, bestScore());
}
synchronized public Scored scored() {
return best == null ? null : new Scored(best, bestScore());
}
synchronized public A getIfScoreAbove(double x) {
return compareScores(score(), x) >= 0 ? best : null;
}
public String toString() {
return "Score " + formatDouble_significant2(score, 4) + ": " + callStringifier(stringifier, best);
}
public boolean putAndPrintIfNewBest(A a, double score) {
if (!put(a, score))
return false;
{
print(this);
return true;
}
}
synchronized public void clear() {
best = null;
score = 0;
}
}
static public class Rect implements WidthAndHeight, IFieldsToList {
static final public String _fieldOrder = "x y w h";
public int x;
public int y;
public int w;
public int h;
public Rect() {
}
public 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 };
}
public Rect(Rectangle r) {
x = r.x;
y = r.y;
w = r.width;
h = r.height;
}
public Rect(Pt p, int w, int h) {
this.h = h;
this.w = w;
x = p.x;
y = p.y;
}
public Rect(Rect r) {
x = r.x;
y = r.y;
w = r.w;
h = r.h;
}
final public Rectangle getRectangle() {
return new Rectangle(x, y, w, h);
}
public String toString() {
return x + "," + y + " / " + w + "," + h;
}
final public int x1() {
return x;
}
final public int y1() {
return y;
}
final public int x2() {
return x + w;
}
final public int y2() {
return y + h;
}
final public boolean contains(Pt p) {
return contains(p.x, p.y);
}
final public boolean contains(int _x, int _y) {
return _x >= x && _y >= y && _x < x + w && _y < y + h;
}
final public boolean contains(Rectangle r) {
return rectContains(this, r);
}
final public boolean empty() {
return w <= 0 || h <= 0;
}
final public int getWidth() {
return w;
}
final public int getHeight() {
return h;
}
final public int area() {
return w * h;
}
final public int x() {
return x;
}
final public int y() {
return y;
}
public WidthAndHeight widthAndHeight() {
return main.widthAndHeight(w, h);
}
}
static public class FunctionTimings {
public Map data = syncMap();
final public void timeCtex(A function, RunnableWithExceptions r) {
doCtex(function, r);
}
public void doCtex(A function, RunnableWithExceptions r) {
try {
if (r == null)
return;
long time = nanoTime();
try {
r.run();
} finally {
time = nanoTime() - time;
saveTiming(function, time);
}
} catch (Exception __e) {
throw rethrow(__e);
}
}
public B get(A function, IF0 f) {
if (f == null)
return null;
Var var = new Var();
time(function, () -> var.set(f.get()));
return var.get();
}
final public void time(A function, Runnable r) {
dO(function, r);
}
public void dO(A function, Runnable r) {
if (r == null)
return;
long time = nanoTime();
try {
r.run();
} finally {
time = nanoTime() - time;
saveTiming(function, time);
}
}
public void saveTiming(A function, long time) {
Average avg = syncMapGetOrCreate(data, function, () -> new Average());
avg.add(time);
}
public Map get() {
return cloneMap(data);
}
final public void clear() {
reset();
}
public void reset() {
data.clear();
}
final public String toString() {
return render();
}
public String render() {
return lines(renderedEntries());
}
public List renderedEntries() {
return ciSorted(map(get(), (f, avg) -> functionToString(f) + ": " + n2(iround(nsToMicroseconds(avg.get()))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")"));
}
public String toStringSingleLine() {
return joinWithComma(renderedEntries());
}
public String functionToString(A f) {
return firstToUpper(str(f));
}
}
static public class PatchworkImage extends AbstractWAndH implements MakesBufferedImage {
public List patches = new ArrayList();
final public PatchworkImage setBackgroundColor(Color backgroundColor) {
return backgroundColor(backgroundColor);
}
public PatchworkImage backgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
return this;
}
final public Color getBackgroundColor() {
return backgroundColor();
}
public Color backgroundColor() {
return backgroundColor;
}
public Color backgroundColor = grayToColor(0.9);
public class Patch {
public Rect bounds;
public BufferedImage image;
final public Patch setUserValue(A userValue) {
return userValue(userValue);
}
public Patch userValue(A userValue) {
this.userValue = userValue;
return this;
}
final public A getUserValue() {
return userValue();
}
public A userValue() {
return userValue;
}
public A userValue;
public Patch(Rect bounds, BufferedImage image) {
this.image = image;
this.bounds = bounds;
}
}
public PatchworkImage() {
}
public PatchworkImage(int w, int h) {
super(w, h);
}
public void addPatch(BufferedImage image, int p_x, int p_y, A userValue) {
addPatch(image, pt(p_x, p_y), userValue);
}
public void addPatch(BufferedImage image, Pt p, A userValue) {
addPatch(p, image, userValue);
}
public void addPatch(int p_x, int p_y, BufferedImage image, A userValue) {
addPatch(pt(p_x, p_y), image, userValue);
}
public void addPatch(Pt p, BufferedImage image, A userValue) {
patches.add(new Patch(rect(p.x, p.y, image.getWidth(), image.getHeight()), image).userValue(userValue));
}
public BufferedImage getBufferedImage() {
BufferedImage out = newBufferedImage(w(), h(), backgroundColor);
for (var patch : patches) copyBufferedImage(patch.image, out, topLeft(patch.bounds));
return out;
}
}
static public class WeightlessShuffledIterator extends IterableIterator implements IndexIterator {
final public List list;
final public int n;
final public int bits, cycleLength, a, b, c;
public int i;
public int value;
public WeightlessShuffledIterator(int n) {
this((List) virtualNullList(n));
}
public WeightlessShuffledIterator(List list) {
this.list = list;
n = l(list);
if (n == 0) {
a = b = c = bits = cycleLength = 0;
return;
}
bits = numberOfBitsNeededToRepresentNOptions(n + 1);
var lsfr = new TripletLSFR(bits);
a = lsfr.a;
b = lsfr.b;
c = lsfr.c;
value = lsfr.value;
cycleLength = lsfr.cycleLength;
}
public boolean hasNext() {
return i < n;
}
public A next() {
return list.get(nextIndex());
}
public int nextIndex() {
if (i >= n)
return -1;
++i;
int raw;
do {
int x = value;
x ^= (x << a) & cycleLength;
x ^= x >>> b;
x ^= (x << c) & cycleLength;
value = x;
raw = postProcessLSFRValue(x - 1);
} while (raw >= n);
return raw;
}
public int bits() {
return bits;
}
public int postProcessLSFRValue(int i) {
return i;
}
}
static public class Pt implements Comparable, IDoublePt {
public int x, y;
public Pt() {
}
public Pt(Point p) {
x = p.x;
y = p.y;
}
public Pt(int x, int y) {
this.y = y;
this.x = x;
}
public 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);
}
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;
}
public double length() {
return sqrt(x * x + y * y);
}
public Pt minus(Pt p) {
return ptMinus(this, p);
}
public double x_double() {
return x;
}
public double y_double() {
return y;
}
}
static public class G22GhostImage implements IBWImage {
public G22GhostImage() {
}
public int w, h;
public int getWidth() {
return w;
}
public int getHeight() {
return h;
}
public int imageCount;
public int[] pixels;
public G22GhostImage(List maskImages) {
imageCount = l(maskImages);
if (imageCount == 0)
return;
var img = first(maskImages);
w = img.w();
h = img.h();
pixels = sumOfBinaryImages(maskImages);
}
public float getFloatPixel(int x, int y) {
return imageCount == 0 ? 0.5f : floatRatio(pixels[y * w + x], imageCount);
}
public FloatBWImage toFloatBWImage() {
float[] floatPixels = new float[pixels.length];
if (imageCount == 0)
fillArray(floatPixels, 0.5f);
else
for (int i = 0; i < l(pixels); i++) floatPixels[i] = floatRatio(pixels[i], imageCount);
return new FloatBWImage(w, h, floatPixels);
}
public BufferedImage getBufferedImage() {
return toFloatBWImage().getBufferedImage();
}
public FloatBWImage certaintyImage() {
return preciseCertaintyImage(this);
}
public Double certainty_cache;
public double certainty() {
if (certainty_cache == null)
certainty_cache = certainty_load();
return certainty_cache;
}
public double certainty_load() {
if (imageCount == 0)
return 0;
double sum = 0;
int n = pixels.length;
for (int i = 0; i < n; i++) sum += g22pixelCertainty(doubleRatio(pixels[i], imageCount));
return sum / (w * h);
}
public G22GhostImage minus(G22GhostImage img) {
G22GhostImage ghost = new G22GhostImage();
ghost.w = w;
ghost.h = h;
ghost.imageCount = imageCount - img.imageCount;
ghost.pixels = intArray_minus(pixels, img.pixels);
return ghost;
}
}
public interface IG22Mask extends MakesBufferedImage {
public Image2B image();
public A label();
default public BufferedImage getBufferedImage() {
return toBufferedImage(image());
}
}
static public interface MakesBufferedImage extends WidthAndHeight {
public BufferedImage getBufferedImage();
public default void drawAt(Graphics2D g, int x, int y) {
g.drawImage(getBufferedImage(), x, y, null);
}
default public int getWidth() {
return getBufferedImage().getWidth();
}
default public int getHeight() {
return getBufferedImage().getHeight();
}
}
static public class G22AutoStarter extends MetaWithChangeListeners implements AutoCloseable, IFieldsToList {
public G22Utils g22utils;
public G22AutoStarter() {
}
public G22AutoStarter(G22Utils g22utils) {
this.g22utils = g22utils;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + g22utils + ")";
}
public Object[] _fieldsToList() {
return new Object[] { g22utils };
}
public transient FieldVar varEnabled_cache;
public FieldVar varEnabled() {
if (varEnabled_cache == null)
varEnabled_cache = varEnabled_load();
return varEnabled_cache;
}
public FieldVar varEnabled_load() {
return new FieldVar(this, "enabled", () -> enabled(), enabled -> enabled(enabled));
}
final public G22AutoStarter setEnabled(boolean enabled) {
return enabled(enabled);
}
public G22AutoStarter enabled(boolean enabled) {
if (!eq(this.enabled, enabled)) {
this.enabled = enabled;
change();
}
return this;
}
final public boolean getEnabled() {
return enabled();
}
public boolean enabled() {
return enabled;
}
volatile public boolean enabled = true;
public transient FieldVar varInitialDelay_cache;
public FieldVar varInitialDelay() {
if (varInitialDelay_cache == null)
varInitialDelay_cache = varInitialDelay_load();
return varInitialDelay_cache;
}
public FieldVar varInitialDelay_load() {
return new FieldVar(this, "initialDelay", () -> initialDelay(), initialDelay -> initialDelay(initialDelay));
}
final public G22AutoStarter setInitialDelay(int initialDelay) {
return initialDelay(initialDelay);
}
public G22AutoStarter initialDelay(int initialDelay) {
if (!eq(this.initialDelay, initialDelay)) {
this.initialDelay = initialDelay;
change();
}
return this;
}
final public int getInitialDelay() {
return initialDelay();
}
public int initialDelay() {
return initialDelay;
}
volatile public int initialDelay = 3;
public transient FieldVar varNScriptsRun_cache;
public FieldVar varNScriptsRun() {
if (varNScriptsRun_cache == null)
varNScriptsRun_cache = varNScriptsRun_load();
return varNScriptsRun_cache;
}
public FieldVar varNScriptsRun_load() {
return new FieldVar(this, "nScriptsRun", () -> nScriptsRun(), nScriptsRun -> nScriptsRun(nScriptsRun));
}
final public G22AutoStarter setNScriptsRun(int nScriptsRun) {
return nScriptsRun(nScriptsRun);
}
public G22AutoStarter nScriptsRun(int nScriptsRun) {
if (!eq(this.nScriptsRun, nScriptsRun)) {
this.nScriptsRun = nScriptsRun;
change();
}
return this;
}
final public int getNScriptsRun() {
return nScriptsRun();
}
public int nScriptsRun() {
return nScriptsRun;
}
volatile public int nScriptsRun;
public transient FieldVar varCurrentScript_cache;
public FieldVar varCurrentScript() {
if (varCurrentScript_cache == null)
varCurrentScript_cache = varCurrentScript_load();
return varCurrentScript_cache;
}
public FieldVar varCurrentScript_load() {
return new FieldVar(this, "currentScript", () -> currentScript(), currentScript -> currentScript(currentScript));
}
final public G22AutoStarter setCurrentScript(AutoStartScript currentScript) {
return currentScript(currentScript);
}
public G22AutoStarter currentScript(AutoStartScript currentScript) {
if (!eq(this.currentScript, currentScript)) {
this.currentScript = currentScript;
change();
}
return this;
}
final public AutoStartScript getCurrentScript() {
return currentScript();
}
public AutoStartScript currentScript() {
return currentScript;
}
volatile public AutoStartScript currentScript;
transient public Set onDone;
public G22AutoStarter onDone(Runnable r) {
onDone = createOrAddToSyncLinkedHashSet(onDone, r);
return this;
}
public G22AutoStarter removeDoneListener(Runnable r) {
main.remove(onDone, r);
return this;
}
public void fireDone() {
if (onDone != null)
for (var listener : onDone) pcallF_typed(listener);
}
public Flag started = new Flag();
public Flag waited = new Flag();
public Flag ctrlPressed = new Flag();
public List scripts = syncL();
public AutoCloseable ctrlListener;
public ReliableSingleThread rst = rst(() -> _run());
public class AutoStartScript extends RunResultWithTimestamps implements IFieldsToList {
public G22LeftArrowScript script;
public AutoStartScript() {
}
public AutoStartScript(G22LeftArrowScript script) {
this.script = script;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + script + ")";
}
public Object[] _fieldsToList() {
return new Object[] { script };
}
public void run() {
try {
LASCompileResult cr = script.compileForAutoRun();
if (cr == null)
cr = script.compileSaved();
var _cr_2 = cr;
run(() -> {
G22AutoStarter.this.change();
if (_cr_2 == null)
throw fail("Script is not saved: " + script);
var parsed = _cr_2.parsedScriptMandatory();
return parsed.get();
});
} catch (Exception __e) {
throw rethrow(__e);
}
}
}
public void init() {
if (ctrlListener != null)
return;
scripts.clear();
var scripts = conceptsWhere(g22utils.concepts, G22LeftArrowScript.class, "runOnProjectOpen", true);
var sorted = sortByCalculatedFieldAlphaNumIC(scripts, s -> s.runOrder);
for (var script : sorted) this.scripts.add(new AutoStartScript(script));
change();
ctrlListener = tempAddGlobalCtrlKeyListener(b -> {
if (b) {
ctrlPressed.raise();
cancel();
}
});
}
public void start() {
print("G22AutoStarter: Start");
if (enabled)
rst.get();
}
public void _run() {
if (!enabled)
return;
AutoCloseable __1 = g22utils.backgroundProcessesUI.tempAdd("Auto-Start Scripts");
try {
if (started.raise())
change();
if (!waited.get()) {
print("G22AutoStarter: Sleeping");
while (initialDelay > 0) {
sleepSeconds(1);
initialDelay(initialDelay - 1);
}
waited.raise();
change();
print("G22AutoStarter: Slept");
}
while (enabled && !done()) {
var script = scripts.get(nScriptsRun);
currentScript(script);
change();
script.run();
nScriptsRun(nScriptsRun + 1);
currentScript(null);
change();
}
fireDone();
change();
close();
} finally {
_close(__1);
}
}
public boolean done() {
return nScriptsRun >= l(scripts);
}
public boolean waitedAndDone() {
return waited.get() && done();
}
public void cancel() {
setEnabled(false);
}
public boolean canResume() {
return !done() && !enabled;
}
public void resume() {
if (done()) {
infoBox("Nothing to resume - auto-start is done");
return;
}
if (enabled) {
infoBox("Already running");
return;
}
infoBox("Resuming auto-start");
setEnabled(true);
rst.get();
}
public String status() {
return !enabled ? ctrlPressed.get() ? "Cancelled due to ctrl key" : "Cancelled" : done() ? "Done" : waited.get() ? "Started" : started.get() ? "Pre-start wait (" + formatDouble1(initialDelay) + "s)" : "Not started";
}
public String stats() {
return status() + ". " + scriptsRunStats();
}
public String scriptsRunStats() {
return "Scripts run: " + nScriptsRun() + "/" + l(scripts);
}
public String currentScriptStats() {
var s = currentScript;
if (s == null)
return "";
return "Running: " + s.script;
}
public void close() {
try {
if (ctrlListener != null) {
{
cleanUp(ctrlListener);
ctrlListener = null;
}
change();
}
} catch (Exception __e) {
throw rethrow(__e);
}
}
public void waitUntilDone() {
waitForVarPredicate(varNScriptsRun(), () -> done());
}
public boolean ctrlEnabled() {
return ctrlListener != null;
}
public boolean cancelled() {
return !enabled;
}
}
static public class JLeftArrowScriptIDE extends MetaWithChangeListeners implements Swingable {
final public JLeftArrowScriptIDE setLvScript(IVarWithNotify lvScript) {
return lvScript(lvScript);
}
public JLeftArrowScriptIDE lvScript(IVarWithNotify lvScript) {
this.lvScript = lvScript;
return this;
}
final public IVarWithNotify getLvScript() {
return lvScript();
}
public IVarWithNotify lvScript() {
return lvScript;
}
public IVarWithNotify lvScript = stringLiveValue();
final public JLeftArrowScriptIDE setSectionTitle(String sectionTitle) {
return sectionTitle(sectionTitle);
}
public JLeftArrowScriptIDE sectionTitle(String sectionTitle) {
this.sectionTitle = sectionTitle;
return this;
}
final public String getSectionTitle() {
return sectionTitle();
}
public String sectionTitle() {
return sectionTitle;
}
public String sectionTitle = "Left arrow script";
final public JLeftArrowScriptIDE setWithResultPanel(boolean withResultPanel) {
return withResultPanel(withResultPanel);
}
public JLeftArrowScriptIDE withResultPanel(boolean withResultPanel) {
this.withResultPanel = withResultPanel;
return this;
}
final public boolean getWithResultPanel() {
return withResultPanel();
}
public boolean withResultPanel() {
return withResultPanel;
}
public boolean withResultPanel = true;
final public JLeftArrowScriptIDE setCompileDelay(double compileDelay) {
return compileDelay(compileDelay);
}
public JLeftArrowScriptIDE compileDelay(double compileDelay) {
this.compileDelay = compileDelay;
return this;
}
final public double getCompileDelay() {
return compileDelay();
}
public double compileDelay() {
return compileDelay;
}
public double compileDelay = 0.1;
static public String helpText = "Gazelle 22 \"Left Arrow Script\"\r\n------------------------------\r\n\r\n\"Left arrow script\" is one of Gazelle 22's two scripting languages. It is the powerful one of the two. It can do anything Java can do except for defining classes or lambdas.\r\n\r\n-Usually, you write one command per line\r\n-Each command contains at most one action and at most one assignment\r\n-The language is case-sensitive\r\n-You can add comments like in Java with /* */ or //\r\n-You can write multiple commands in one line by separating them with a semicolon\r\n-Arguments to functions are separated by spaces\r\n-You can use integer and string literals like in Java\r\n-You can use true, false and null\r\n\r\nIt's called \"left arrow script\" because the left arrow (variable assignment) is its only actual operator (not counting ; and {}).\r\n\r\n\r\nOperations\r\n----------\r\n\r\nYou can call any global function defined in Gazelle. Example:\r\n\r\n infoBox \"hello\" // show a popup with the text \"hello\"\r\n \r\nYou can assign the result of a function call to a variable:\r\n\r\n time <- tsNow // get current time as a Timestamp object\r\n infoBox time // show as popup\r\n \r\nNote that this script requires 2 lines because only one operation is allowed per command.\r\n \r\nVariables can be overwritten and don't have to be declared.\r\n\r\n\r\nCreating objects\r\n----------------\r\n\r\nYou can create an instance of any Java class and call methods on the object:\r\n\r\n list <- new ArrayList\r\n list add \"hello\"\r\n list add \"world\"\r\n infoBox list // shows [hello, world]\r\n \r\n(Currently you can also say \"list <- ArrayList\", but this is ambiguous and may be removed in a future version.)\r\n \r\nYou can pass parameters to the constructor:\r\n\r\n pair <- new Pair \"hello\" \"world\"\r\n infoBox pair // shows \r\n \r\n\r\nJava operators (+, * etc)\r\n-------------------------\r\n \r\nJava operators can't be used directly but we have functions that do the same thing (if we don't, we'll add them):\r\n\r\n x <- plus 1 2\r\n infoBox x\r\n\r\n\r\nFunction definitions\r\n--------------------\r\n\r\nYou can define functions in your script, with arguments. The function can return a value (which is the result of the last command in the function).\r\n\r\n def doubleMe x { mul x 2 }\r\n\r\n x <- doubleMe 5\r\n infoBox x // shows 10\r\n";
public transient FieldVar varCompileResult_cache;
public FieldVar varCompileResult() {
if (varCompileResult_cache == null)
varCompileResult_cache = varCompileResult_load();
return varCompileResult_cache;
}
public FieldVar varCompileResult_load() {
return new FieldVar(this, "compileResult", () -> compileResult(), compileResult -> compileResult(compileResult));
}
final public JLeftArrowScriptIDE setCompileResult(LASCompileResult compileResult) {
return compileResult(compileResult);
}
public JLeftArrowScriptIDE compileResult(LASCompileResult compileResult) {
if (!eq(this.compileResult, compileResult)) {
this.compileResult = compileResult;
change();
}
return this;
}
final public LASCompileResult getCompileResult() {
return compileResult();
}
public LASCompileResult compileResult() {
return compileResult;
}
transient public LASCompileResult compileResult;
transient public RSyntaxTextAreaWithSearch taScript;
transient public RSTADummyParser dummyParser = new RSTADummyParser();
transient public Q compileQ = new Q();
final public JPanel getButtons() {
return buttons();
}
public JPanel buttons() {
return buttons;
}
transient public JPanel buttons = jline();
transient public JButton btnRun;
transient public CollapsibleLeftPanel collapsibleResultPanel;
transient public G22ScriptResultPanel resultPanel;
transient public JPopDownButton popDownButton;
transient public LeftArrowCompletionProvider completionProvider;
final public JLeftArrowScriptIDE setG22utils(G22Utils g22utils) {
return g22utils(g22utils);
}
public JLeftArrowScriptIDE g22utils(G22Utils g22utils) {
this.g22utils = g22utils;
return this;
}
final public G22Utils getG22utils() {
return g22utils();
}
public G22Utils g22utils() {
return g22utils;
}
transient public G22Utils g22utils;
final public JLeftArrowScriptIDE setScriptTimeout(double scriptTimeout) {
return scriptTimeout(scriptTimeout);
}
public JLeftArrowScriptIDE scriptTimeout(double scriptTimeout) {
this.scriptTimeout = scriptTimeout;
return this;
}
final public double getScriptTimeout() {
return scriptTimeout();
}
public double scriptTimeout() {
return scriptTimeout;
}
public double scriptTimeout = 10.0;
final public JLeftArrowScriptIDE setShowTitle(boolean showTitle) {
return showTitle(showTitle);
}
public JLeftArrowScriptIDE showTitle(boolean showTitle) {
this.showTitle = showTitle;
return this;
}
final public boolean getShowTitle() {
return showTitle();
}
public boolean showTitle() {
return showTitle;
}
transient public boolean showTitle = true;
transient public IF0 makeParser;
public GazelleV_LeftArrowScriptParser makeParser() {
return makeParser != null ? makeParser.get() : makeParser_base();
}
final public GazelleV_LeftArrowScriptParser makeParser_fallback(IF0 _f) {
return _f != null ? _f.get() : makeParser_base();
}
public GazelleV_LeftArrowScriptParser makeParser_base() {
return g22utils.leftArrowParser();
}
public class LeftArrowCompletionProvider extends DefaultCompletionProvider {
@Override
public List getCompletionsImpl(JTextComponent comp) {
try {
String text = getText(comp);
GazelleV_LeftArrowScriptParser parser = makeParser2();
LeftArrowScriptAutoCompleter completer = new LeftArrowScriptAutoCompleter(g22utils, parser);
enableScaffolding(completer);
completer.seek(text, getCaretPosition(comp));
return map(completer.searcher().withScores(), completion -> {
BasicCompletion c = new BasicCompletion(this, completion.get());
c.setRelevance((int) completion.score());
return c;
});
} catch (Throwable e) {
printStackTrace(e);
return ll();
}
}
}
public JComponent wrapStatusLabel(JComponent lbl) {
onLeftClick(lbl, () -> {
LineAndColumn lineAndCol = compileResult == null ? null : compileResult.errorLineAndCol();
if (lineAndCol != null) {
moveCaretToLineAndCol(textArea(), lineAndCol);
focus(textArea());
}
});
popDownButton = swing(() -> new JPopDownButton("Help"));
popDownButton.onFillingMenu(menu -> addMenuItems(menu, "Show Scripting Help", runnableThread(new Runnable() {
public void run() {
try {
showTextWordWrapped("Gazelle 'Left arrow script' Help", helpText);
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "showTextWordWrapped(\"Gazelle 'Left arrow script' Help\", helpText)";
}
}), "Show Global Class Names", runnableThread(new Runnable() {
public void run() {
try {
showGlobalClassNames();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "showGlobalClassNames();";
}
}), "Convert to Java", runnableThread(new Runnable() {
public void run() {
try {
convertToJava();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "convertToJava();";
}
})));
return centerAndEastWithMargin(jBorderlessHigherScrollPane(lbl), jfullcenter(buttons));
}
public transient JComponent visualize_cache;
public JComponent visualize() {
if (visualize_cache == null)
visualize_cache = visualize_load();
return visualize_cache;
}
public JComponent visualize_load() {
return markVisualizer(this, visualize_impl());
}
public JComponent visualize_impl() {
return swing(() -> {
taScript = g22utils.newSyntaxTextArea(__2 -> wrapStatusLabel(__2));
bindTextComponentToVarWithNotify_noInitialUndo(textArea(), lvScript);
dummyParser.install(textArea());
addKeyListener(textArea(), functionKeyListener(5, runnableThread(new Runnable() {
public void run() {
try {
runScript();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "runScript();";
}
})));
addKeyListener(textArea(), ctrlLetterKeyListener('b', runnableThread(new Runnable() {
public void run() {
try {
goToDefinition();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "goToDefinition();";
}
})));
awtCalcEvery(textArea(), compileDelay, () -> compileQ.add(new Runnable() {
public void run() {
try {
compile();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "compile();";
}
}));
installCompletionProvider(completionProvider = new LeftArrowCompletionProvider(), textArea());
JComponent vis = taScript.visualize();
if (showTitle)
vis = jCenteredSection(sectionTitle, vis);
vis = wrapSection(vis);
addAll(buttons, btnRun = toolTip("Run script (F5)", jbutton("Run", runnableThread(new Runnable() {
public void run() {
try {
runScript();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "runScript();";
}
}))), popDownButton);
if (withResultPanel) {
resultPanel = new G22ScriptResultPanel();
collapsibleResultPanel = new CollapsibleLeftPanel(false, "Output", resultPanel.visualize(), vis);
collapsibleResultPanel.sidePanelMargins = c -> withTopAndLeftMargin(c);
return collapsibleResultPanel.visualize();
} else
return vis;
});
}
transient public IF1 wrapSection;
public JComponent wrapSection(JComponent c) {
return wrapSection != null ? wrapSection.get(c) : wrapSection_base(c);
}
final public JComponent wrapSection_fallback(IF1 _f, JComponent c) {
return _f != null ? _f.get(c) : wrapSection_base(c);
}
public JComponent wrapSection_base(JComponent c) {
return c;
}
public RSyntaxTextArea textArea() {
if (taScript == null)
visualize();
return taScript.textArea();
}
public void setText(String text) {
main.setText(textArea(), text);
}
public boolean visible() {
return isShowing(textArea());
}
public void compile() {
var script = lvScript.get();
var result = compileResult;
if (result == null || !eq(result.script, script)) {
result = newCompileResult();
result.script = script;
result.makeParser = () -> makeParser();
result.compile();
compileResult(result);
showStatus(str(compileResult));
updateRunButtonState();
List errors = new ArrayList();
if (result.compileError != null) {
LineAndColumn lineAndCol = result.errorLineAndCol();
if (lineAndCol != null)
errors.add(new RSTADummyParser.Error().msg(result.errorToString()).start(lineAndCol).end(new LineAndColumn(lineAndCol.line + 1, 1)));
}
dummyParser.setErrors(result.script, errors, textArea());
}
}
public void updateRunButtonState() {
setEnabled(btnRun, runButtonShouldBeEnabled());
}
transient public IF0 runButtonShouldBeEnabled;
public boolean runButtonShouldBeEnabled() {
return runButtonShouldBeEnabled != null ? runButtonShouldBeEnabled.get() : runButtonShouldBeEnabled_base();
}
final public boolean runButtonShouldBeEnabled_fallback(IF0 _f) {
return _f != null ? _f.get() : runButtonShouldBeEnabled_base();
}
public boolean runButtonShouldBeEnabled_base() {
return compileResult != null && compileResult.runnable();
}
public LASCompileResult freshCompileResult() {
runInQAndWait(compileQ, new Runnable() {
public void run() {
try {
compile();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "compile();";
}
});
return compileResult;
}
public GazelleV_LeftArrowScript.Script parsedScript() {
return freshCompileResult().parsedScript;
}
transient public Runnable runScript;
public void runScript() {
if (runScript != null)
runScript.run();
else
runScript_base();
}
final public void runScript_fallback(Runnable _f) {
if (_f != null)
_f.run();
else
runScript_base();
}
public void runScript_base() {
var result = freshCompileResult();
if (result.parsedScript != null) {
var value = runResultWithTimestamps(() -> callCompiledObjectWithTimeout(result.parsedScript));
showScriptResult(value);
}
}
public void showScriptResult(OKOrError result) {
if (result instanceof RunResultWithTimestamps) {
if (resultPanel != null)
resultPanel.logView.setText(str(((RunResultWithTimestamps) result).printOutput()));
}
if (result.isOK()) {
setStatus(shorten(g22utils.stringify(result.get())));
var objVisualizer = new G22JavaObjectVisualizer(g22utils, result.get());
if (result instanceof RunResultWithTimestamps) {
var duration = ((RunResultWithTimestamps) result).duration();
print("duration", duration);
if (duration != null) {
long nanos = ((RunResultWithTimestamps) result).duration().toNanos();
printVars("nanos", nanos, "objVisualizer", objVisualizer);
objVisualizer.nanos(nanos);
}
}
if (collapsibleResultPanel != null)
objVisualizer.withTypeAndTime(false);
{
if (resultPanel != null)
resultPanel.scpResult.set(objVisualizer);
}
if (collapsibleResultPanel != null)
collapsibleResultPanel.sidePanelName("Output" + appendBracketed(objVisualizer.objectInfos()));
} else {
setStatus(exceptionToStringShorter_dontDropOuterExceptions(result.error()));
{
if (resultPanel != null)
resultPanel.scpResult.set(jErrorView(result.getError()));
}
}
{
if (collapsibleResultPanel != null)
collapsibleResultPanel.expand();
}
}
final public void showStatus(String status) {
setStatus(status);
}
public void setStatus(String status) {
{
if (taScript != null)
taScript.setStatus(" " + unnull(status));
}
}
public void showRuntimeError(Throwable e) {
showStatus(exceptionToStringShorter(e));
}
transient public IF0 makeVarContextForExecution;
public VarContext makeVarContextForExecution() {
return makeVarContextForExecution != null ? makeVarContextForExecution.get() : makeVarContextForExecution_base();
}
final public VarContext makeVarContextForExecution_fallback(IF0 _f) {
return _f != null ? _f.get() : makeVarContextForExecution_base();
}
public VarContext makeVarContextForExecution_base() {
return new FlexibleVarContext();
}
public Object callCompiledObjectWithTimeout(GazelleV_LeftArrowScript.Script script) {
return callCompiledObjectWithTimeout(scriptTimeout, script);
}
public Object callCompiledObjectWithTimeout(double timeoutSeconds, GazelleV_LeftArrowScript.Script script) {
return callCompiledObjectWithTimeout(timeoutSeconds, script, makeVarContextForExecution());
}
public Object callCompiledObjectWithTimeout(GazelleV_LeftArrowScript.Script script, VarContext ctx) {
return callCompiledObjectWithTimeout(scriptTimeout, script, ctx);
}
public Object callCompiledObjectWithTimeout(double timeoutSeconds, GazelleV_LeftArrowScript.Script script, VarContext ctx) {
return g22utils.evalRegisteredCode(timeoutSeconds, str(script), () -> script.get(ctx));
}
public GazelleV_LeftArrowScriptParser makeParser2() {
var parser = makeParser();
print("Function containers: " + parser.functionContainers);
return parser;
}
public void showGlobalClassNames() {
showText("Global Class Names", pnlToString(toCIMap(makeParser().globalClassNames())));
}
public void setEditable(boolean b) {
main.setEditable(textArea(), b);
}
transient public IF0 newCompileResult;
public LASCompileResult newCompileResult() {
return newCompileResult != null ? newCompileResult.get() : newCompileResult_base();
}
final public LASCompileResult newCompileResult_fallback(IF0 _f) {
return _f != null ? _f.get() : newCompileResult_base();
}
public LASCompileResult newCompileResult_base() {
return new LASCompileResult();
}
public void convertToJava() {
try {
ConvertLASToJava converter = new ConvertLASToJava();
enableScaffolding(converter);
showText("Java conversion - " + sectionTitle(), strOrNull(converter.get(parsedScript(), true)));
} catch (Throwable __e) {
infoBox(__e);
}
}
public void goToDefinition() {
String text;
int iChar;
Pair __1 = textAndCaretPosition(textArea());
text = __1.a;
iChar = __1.b;
List tok = lasTok(text);
int iTok = charToTokenIndex_left(tok, iChar);
String token = lastIdentifier(subList(tok, iTok - 2, iTok + 1));
printVars("goToDefinition", "iTok", iTok, "token", quote(token));
if (token != null) {
String name = lookupStandardFunctionOrClassNameIC(token);
if (name != null) {
String snippetID = sfOrSCSnippet(token);
if (snippetID != null) {
infoBox("Opening " + quote(name));
g22utils.openInBrowser(snippetURL(snippetID));
return;
}
}
flatInfoBox("No information found for " + token);
}
}
}
static public int concepts_internStringsLongerThan = 10;
static public ThreadLocal concepts_unlisted = new ThreadLocal();
static public boolean concepts_unlistedByDefault = true;
public interface IConceptIndex {
public void update(Concept c);
public void remove(Concept c);
}
public interface IFieldIndex {
public Collection getAll(Val val);
public List allValues();
public MultiSet allValues_multiSet();
public IterableIterator objectIterator();
}
static public class ConceptsChange {
}
static public class ConceptCreate extends ConceptsChange implements IFieldsToList {
public Concept c;
public ConceptCreate() {
}
public ConceptCreate(Concept c) {
this.c = c;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + c + ")";
}
public boolean equals(Object o) {
if (!(o instanceof ConceptCreate))
return false;
ConceptCreate __3 = (ConceptCreate) o;
return eq(c, __3.c);
}
public int hashCode() {
int h = -1751266972;
h = boostHashCombine(h, _hashCode(c));
return h;
}
public Object[] _fieldsToList() {
return new Object[] { c };
}
}
static public class ConceptChange extends ConceptsChange implements IFieldsToList {
public Concept c;
public ConceptChange() {
}
public ConceptChange(Concept c) {
this.c = c;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + c + ")";
}
public boolean equals(Object o) {
if (!(o instanceof ConceptChange))
return false;
ConceptChange __4 = (ConceptChange) o;
return eq(c, __4.c);
}
public int hashCode() {
int h = -1760609256;
h = boostHashCombine(h, _hashCode(c));
return h;
}
public Object[] _fieldsToList() {
return new Object[] { c };
}
}
static public class ConceptDelete extends ConceptsChange implements IFieldsToList {
static final public String _fieldOrder = "id c";
public long id;
public Concept c;
public ConceptDelete() {
}
public ConceptDelete(long id, Concept c) {
this.c = c;
this.id = id;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + id + ", " + c + ")";
}
public boolean equals(Object o) {
if (!(o instanceof ConceptDelete))
return false;
ConceptDelete __5 = (ConceptDelete) o;
return id == __5.id && eq(c, __5.c);
}
public int hashCode() {
int h = -1734431213;
h = boostHashCombine(h, _hashCode(id));
h = boostHashCombine(h, _hashCode(c));
return h;
}
public Object[] _fieldsToList() {
return new Object[] { id, c };
}
}
static public class FullChange extends ConceptsChange implements IFieldsToList {
public FullChange() {
}
public String toString() {
return shortClassName_dropNumberPrefix(this);
}
public boolean equals(Object o) {
return o instanceof FullChange;
}
public int hashCode() {
int h = 733452095;
return h;
}
public Object[] _fieldsToList() {
return null;
}
}
static public class Concepts implements AutoCloseable {
public SortedMap concepts = synchroTreeMap();
final public long getIdCounter() {
return idCounter();
}
public long idCounter() {
return idCounter;
}
public long idCounter;
transient public HashMap perClassData;
transient public Map miscMap;
transient public String programID;
transient public File conceptsFile;
transient public Concepts parent;
transient volatile public long changes, changesWritten, lastChange;
transient volatile public java.util.Timer autoSaver;
transient volatile public boolean dontSave = false;
transient volatile public boolean savingConcepts, noXFullGrab;
transient public boolean vmBusSend = true;
transient public boolean initialSave = false;
transient public int autoSaveInterval = -1000;
transient public boolean useGZIP = true, quietSave;
transient public ReentrantLock lock = new ReentrantLock(true);
transient public ReentrantLock saverLock = new ReentrantLock(true);
transient public long lastSaveTook = -1, lastSaveWas, loadTook, uncompressedSize;
transient public float maxAutoSavePercentage = 10;
transient public List conceptIndices;
transient public Map, Map> fieldIndices;
transient public Map, Map> ciFieldIndices;
transient public List preSave;
transient public Object classFinder = _defaultClassFinder();
transient public List onAllChanged = synchroList();
transient public Set onChange = new HashSet();
transient public Object saveWrapper;
final public Concepts setModifyOnCreate(boolean modifyOnCreate) {
return modifyOnCreate(modifyOnCreate);
}
public Concepts modifyOnCreate(boolean modifyOnCreate) {
this.modifyOnCreate = modifyOnCreate;
return this;
}
final public boolean getModifyOnCreate() {
return modifyOnCreate();
}
public boolean modifyOnCreate() {
return modifyOnCreate;
}
transient public boolean modifyOnCreate = false;
transient public boolean modifyOnBackRef = false;
transient public boolean useFileLock = true;
final public Concepts setGrabThroughSocket(boolean grabThroughSocket) {
return grabThroughSocket(grabThroughSocket);
}
public Concepts grabThroughSocket(boolean grabThroughSocket) {
this.grabThroughSocket = grabThroughSocket;
return this;
}
final public boolean getGrabThroughSocket() {
return grabThroughSocket();
}
public boolean grabThroughSocket() {
return grabThroughSocket;
}
transient public boolean grabThroughSocket = true;
transient public FileBasedLock fileLock;
transient public boolean storeBaseClassesInStructure = false;
transient public boolean useBackRefsForSearches = false;
transient public boolean defunct = false;
transient public int newBackupEveryXMinutes = 60;
final public Concepts setCloseConceptsOnExit(boolean closeConceptsOnExit) {
return closeConceptsOnExit(closeConceptsOnExit);
}
public Concepts closeConceptsOnExit(boolean closeConceptsOnExit) {
this.closeConceptsOnExit = closeConceptsOnExit;
return this;
}
final public boolean getCloseConceptsOnExit() {
return closeConceptsOnExit();
}
public boolean closeConceptsOnExit() {
return closeConceptsOnExit;
}
transient public boolean closeConceptsOnExit = false;
public Concepts() {
}
public Concepts(String programID) {
this.programID = programID;
}
public Concepts(File conceptsFile) {
this.conceptsFile = conceptsFile;
}
synchronized public long internalID() {
do {
++idCounter;
} while (hasConcept(idCounter));
return idCounter;
}
synchronized public HashMap perClassData() {
if (perClassData == null)
perClassData = new HashMap();
return perClassData;
}
public void initProgramID() {
if (programID == null)
programID = getDBProgramID();
}
public Concepts load(String structure) {
return load(structure, false);
}
public Concepts load(String structure, boolean allDynamic) {
clearConcepts();
Map map = unstructureMap(structure, allDynamic, classFinder);
concepts.putAll(map);
assignConceptsToUs();
calcIdCounter();
return this;
}
public Concepts load() {
initProgramID();
Object dbGrabber = miscMapGet("dbGrabber");
if (dbGrabber != null && !isFalse(callF(dbGrabber)))
return this;
try {
if (grabThroughSocket && tryToGrab())
return this;
} catch (Throwable e) {
if (!exceptionMessageContains(e, "no xfullgrab"))
printShortException(e);
print("xfullgrab failed - loading DB of " + programID + " from disk");
}
return loadFromDisk();
}
public Concepts loadFromDisk() {
if (nempty(concepts))
clearConcepts();
long time = now();
Map _concepts = (Map) (unstructureGZFile(conceptsFile(), toIF1(classFinder)));
putAll(concepts, _concepts);
assignConceptsToUs();
loadTook = now() - time;
done("Loaded " + n2(l(concepts), "concept"), time);
calcIdCounter();
return this;
}
public Concepts loadConcepts() {
return load();
}
public boolean tryToGrab() {
if (sameSnippetID(programID, getDBProgramID()))
return false;
RemoteDB db = connectToDBOpt(programID);
try {
if (db != null) {
loadGrab(db.fullgrab());
return true;
}
return false;
} finally {
_close(db);
}
}
public Concepts loadGrab(String grab) {
clearConcepts();
DynamicObject_loading.set(true);
try {
Map map = (Map) unstructure(grab, false, classFinder);
concepts.putAll(map);
assignConceptsToUs();
for (long l : map.keySet()) idCounter = max(idCounter, l);
} finally {
DynamicObject_loading.set(null);
}
return this;
}
public void assignConceptsToUs() {
for (Pair p : mapToPairs((Map) (Map) concepts)) if (!(p.b instanceof Concept)) {
print("DROPPING non-existant concept " + p.a + ": " + dynShortName(p.b));
concepts.remove(p.a);
}
for (Concept c : values(concepts)) c._concepts = this;
for (Concept c : values(concepts)) c._doneLoading2();
}
public String progID() {
return programID == null ? getDBProgramID() : programID;
}
public Concept getConcept(String id) {
return empty(id) ? null : getConcept(parseLong(id));
}
public Concept getConcept(long id) {
return (Concept) concepts.get((long) id);
}
public Concept getConcept(RC ref) {
return ref == null ? null : getConcept(ref.longID());
}
public boolean hasConcept(long id) {
return concepts.containsKey((long) id);
}
public void deleteConcept(long id) {
Concept c = getConcept(id);
if (c == null)
print("Concept " + id + " not found");
else
c.delete();
}
public void calcIdCounter() {
Long lastID = lastKey(concepts);
idCounter = lastID == null ? 1 : lastID + 1;
}
public File conceptsDir() {
return dirOfFile(conceptsFile());
}
public Concepts conceptsFile(File conceptsFile) {
this.conceptsFile = conceptsFile;
return this;
}
public File conceptsFile() {
if (conceptsFile != null)
return conceptsFile;
return getProgramFile(programID, useGZIP ? "concepts.structure.gz" : "concepts.structure");
}
public File lockFile() {
return newFile(conceptsDir(), "concepts.lock");
}
public FileBasedLock fileLock() {
if (fileLock == null)
fileLock = new FileBasedLock(lockFile());
return fileLock;
}
public void saveConceptsIfDirty() {
saveConcepts();
}
public void save() {
saveConcepts();
}
public void saveConcepts() {
vmBus_send("saveConceptsCalled", Concepts.this);
if (dontSave)
return;
initProgramID();
saverLock.lock();
savingConcepts = true;
long start = now(), time;
try {
String s = null;
long _changes = changes;
if (_changes == changesWritten)
return;
File f = conceptsFile();
lock.lock();
long fullTime = now();
try {
if (useGZIP) {
vmBus_send("callingSaveWrapper", Concepts.this, saveWrapper);
callRunnableWithWrapper(saveWrapper, new Runnable() {
public void run() {
try {
vmBus_send("callingPreSave", Concepts.this, preSave);
callFAll(preSave);
vmBus_send("writingFile", Concepts.this, f);
uncompressedSize = saveGZStructureToFile(f, cloneMap(concepts), makeStructureData());
vmBus_send("gzFileSaved", Concepts.this, f, uncompressedSize);
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "vmBus_send callingPreSave(Concepts.this, preSave);\r\n callFAll(preS...";
}
});
newFile(conceptsDir(), "concepts.structure").delete();
} else
s = fullStructure();
} finally {
lock.unlock();
}
changesWritten = _changes;
if (!useGZIP) {
time = now() - start;
if (!quietSave)
print("Saving " + toM(l(s)) + "M chars (" + time + " ms)");
start = now();
saveTextFile(f, javaTokWordWrap(s));
newFile(conceptsDir(), "concepts.structure.gz").delete();
}
File conceptsFile = conceptsFile();
File backupFile = newFile(conceptsDir(), "backups/" + fileName(conceptsFile) + ".backup" + ymd() + "-" + formatInt(hours(), 2) + (newBackupEveryXMinutes >= 60 ? "" : formatInt(roundDownTo_rev(minutes(), newBackupEveryXMinutes), 2)));
copyFile(f, backupFile);
time = now() - start;
if (!quietSave)
print("Saved " + toK(f.length()) + " K, " + n(concepts, "concepts") + " (" + time + " ms)");
lastSaveWas = fullTime;
lastSaveTook = now() - fullTime;
} finally {
savingConcepts = false;
saverLock.unlock();
}
}
public void _autoSaveConcepts() {
if (autoSaveInterval < 0 && maxAutoSavePercentage != 0) {
long pivotTime = Math.round(lastSaveWas + lastSaveTook * 100.0 / maxAutoSavePercentage);
if (now() < pivotTime) {
return;
}
}
try {
saveConcepts();
} catch (Throwable e) {
print("Concept save failed, will try again");
printStackTrace(e);
}
}
public String fullStructure() {
return structure(cloneMap(concepts), makeStructureData());
}
transient public IF0 makeStructureData;
public structure_Data makeStructureData() {
return makeStructureData != null ? makeStructureData.get() : makeStructureData_base();
}
final public structure_Data makeStructureData_fallback(IF0 _f) {
return _f != null ? _f.get() : makeStructureData_base();
}
public structure_Data makeStructureData_base() {
return finishStructureData(new structure_Data());
}
public structure_Data finishStructureData(structure_Data data) {
if (storeBaseClassesInStructure)
data.storeBaseClasses = true;
return data;
}
public void clearConcepts() {
for (Concept c : allConcepts()) c.delete();
}
public void fireLegacyChangeEvent() {
synchronized (this) {
++changes;
lastChange = sysNow();
}
if (vmBusSend)
vmBus_send("conceptsChanged", this);
pcallFAll(onAllChanged);
}
synchronized public void autoSaveConcepts() {
if (autoSaver == null) {
if (isTransient())
throw fail("Can't persist transient database");
autoSaver = doEvery_daemon("Concepts Saver for " + conceptsDir(), abs(autoSaveInterval), new Runnable() {
public void run() {
try {
_autoSaveConcepts();
} catch (Exception __e) {
throw rethrow(__e);
}
}
public String toString() {
return "_autoSaveConcepts()";
}
});
}
}
public void close() {
cleanMeUp();
}
public void cleanMeUp() {
try {
if (closeConceptsOnExit)
closeAllOpt(allConcepts());
defunct = true;
boolean shouldSave = autoSaver != null;
if (autoSaver != null) {
autoSaver.cancel();
autoSaver = null;
}
while (savingConcepts) sleepInCleanUp(10);
if (shouldSave)
saveConceptsIfDirty();
} catch (Throwable __e) {
printStackTrace(__e);
}
{
cleanUp(fileLock);
fileLock = null;
}
}
public Map getIDsAndNames() {
Map map = new HashMap();
Map cloned = cloneMap(concepts);
for (long id : keys(cloned)) map.put(id, cloned.get(id).className);
return map;
}
public void deleteConcepts(List l) {
ping();
if (l != null)
for (Object o : cloneList(l)) if (o instanceof Long) {
Concept c = concepts.get(o);
if (c != null)
c.delete();
} else if (o instanceof Concept)
((Concept) o).delete();
else
warn("Can't delete " + getClassName(o));
}
public A conceptOfType(Class type) {
IConceptCounter counter = conceptCounterForClass(type);
if (counter != null)
return (A) first(counter.allConcepts());
return firstOfType(allConcepts(), type);
}
public List conceptsOfType(Class type) {
List l = conceptsOfType_noParent(type);
if (parent == null)
return l;
return concatLists_conservative(l, parent.conceptsOfType(type));
}
public List conceptsOfType_noParent(Class type) {
ping();
IConceptCounter counter = conceptCounterForClass(type);
if (counter != null)
return (List) cloneList(counter.allConcepts());
return filterByType(allConcepts(), type);
}
public List listConcepts(Class type) {
return conceptsOfType(type);
}
public List list(Class type) {
return conceptsOfType(type);
}
public List list_noParent(Class type) {
return conceptsOfType_noParent(type);
}
public List list(String type) {
return conceptsOfType(type);
}
public List conceptsOfType(String type) {
return filterByDynamicType(allConcepts(), "main$" + type);
}
public boolean hasConceptOfType(Class extends Concept> type) {
return hasType(allConcepts(), type);
}
public void persistConcepts() {
loadConcepts();
autoSaveConcepts();
}
public void conceptPersistence() {
persistConcepts();
}
public Concepts persist() {
persistConcepts();
return this;
}
public void persist(Integer interval) {
if (interval != null)
autoSaveInterval = interval;
persist();
}
public A ensureHas(Class c, Runnable r) {
A a = conceptOfType(c);
if (a == null) {
r.run();
a = conceptOfType(c);
if (a == null)
throw fail("Concept not made by " + r + ": " + shortClassName(c));
}
return a;
}
public void ensureHas(Class extends Concept> c1, Class extends Concept> c2, Object func) {
for (Concept a : conceptsOfType(c1)) {
Concept b = findBackRef(a, c2);
if (b == null) {
callF(func, a);
b = findBackRef(a, c2);
if (b == null)
throw fail("Concept not made by " + func + ": " + shortClassName(c2));
}
}
}
public void forEvery(Class extends Concept> type, Object func) {
for (Concept c : conceptsOfType(type)) callF(func, c);
}
public int deleteAll(Class extends Concept> type) {
List l = (List) conceptsOfType(type);
for (Concept c : l) c.delete();
return l(l);
}
public Collection allConcepts() {
synchronized (concepts) {
return new ArrayList(values(concepts));
}
}
public IConceptCounter conceptCounterForClass(Class extends Concept> c) {
for (IFieldIndex idx : values(mapGet(fieldIndices, c))) if (idx instanceof IConceptCounter)
return ((IConceptCounter) idx);
for (IFieldIndex idx : values(mapGet(ciFieldIndices, c))) if (idx instanceof IConceptCounter)
return ((IConceptCounter) idx);
return null;
}
public int countConcepts(Class c, Object... params) {
int n = countConcepts_noParent(c, params);
if (parent == null)
return n;
return n + parent.countConcepts(c, params);
}
public int countConcepts_noParent(Class c, Object... params) {
ping();
if (empty(params)) {
IConceptCounter counter = conceptCounterForClass(c);
if (counter != null)
return counter.countConcepts();
return l(list_noParent(c));
}
int n = 0;
for (A x : list_noParent(c)) if (checkConceptFields(x, params))
++n;
return n;
}
public int countConcepts(String c, Object... params) {
ping();
if (empty(params))
return l(list(c));
int n = 0;
for (Concept x : list(c)) if (checkConceptFields(x, params))
++n;
return n;
}
public int countConcepts() {
return l(concepts);
}
synchronized public List clonedConceptIndices() {
return cloneList(conceptIndices);
}
synchronized public void addConceptIndex(IConceptIndex index) {
if (conceptIndices == null)
conceptIndices = new ArrayList();
conceptIndices.add(index);
}
synchronized public void removeConceptIndex(IConceptIndex index) {
if (conceptIndices == null)
return;
conceptIndices.remove(index);
if (empty(conceptIndices))
conceptIndices = null;
}
synchronized public void addFieldIndex(Class extends Concept> c, String field, IFieldIndex index) {
if (fieldIndices == null)
fieldIndices = new HashMap();
Map map = fieldIndices.get(c);
if (map == null)
fieldIndices.put(c, map = new HashMap());
map.put(field, index);
}
synchronized public void removeFieldIndex(Class extends Concept> c, String field, IFieldIndex index) {
Map map = mapGet(fieldIndices, c);
mapRemove(map, field);
}
synchronized public IFieldIndex getFieldIndex(Class extends Concept> c, String field) {
if (fieldIndices == null)
return null;
Map map = fieldIndices.get(c);
return map == null ? null : map.get(field);
}
synchronized public IFieldIndex getAnyIndexForClass(Class extends Concept> c) {
return first(allIndicesForClass(c));
}
synchronized public Collection allIndicesForClass(Class extends Concept> c) {
return concatLists(values(fieldIndices == null ? null : fieldIndices.get(c)), values(ciFieldIndices == null ? null : ciFieldIndices.get(c)));
}
synchronized public void addCIFieldIndex(Class extends Concept> c, String field, IFieldIndex index) {
if (ciFieldIndices == null)
ciFieldIndices = new HashMap();
Map map = ciFieldIndices.get(c);
if (map == null)
ciFieldIndices.put(c, map = new HashMap());
map.put(field, index);
}
synchronized public void removeCIFieldIndex(Class extends Concept> c, String field) {
Map map = mapGet(ciFieldIndices, c);
mapRemove(map, field);
}
synchronized public IFieldIndex getCIFieldIndex(Class extends Concept> c, String field) {
if (ciFieldIndices == null)
return null;
Map map = ciFieldIndices.get(c);
return map == null ? null : map.get(field);
}
public RC xnew(String name, Object... values) {
return new RC(cnew(name, values));
}
public void xset(long id, String field, Object value) {
xset(new RC(id), field, value);
}
public void xset(RC c, String field, Object value) {
if (value instanceof RC)
value = getConcept((RC) value);
cset(getConcept(c), field, value);
}
public Object xget(long id, String field) {
return xget(new RC(id), field);
}
public Object xget(RC c, String field) {
return xgetPost(cget(getConcept(c), field));
}
public Object xgetPost(Object o) {
o = deref(o);
if (o instanceof Concept)
return new RC((Concept) o);
return o;
}
public void xdelete(long id) {
xdelete(new RC(id));
}
public void xdelete(RC c) {
getConcept(c).delete();
}
public void xdelete(List l) {
for (RC c : l) xdelete(c);
}
public List xlist() {
return map("toPassRef", allConcepts());
}
public List xlist(String className) {
return map("toPassRef", conceptsOfType(className));
}
public boolean isTransient() {
return eq(programID, "-");
}
public String xfullgrab() {
if (noXFullGrab)
throw fail("no xfullgrab (DB too large)");
Lock __1 = lock();
lock(__1);
try {
if (changes == changesWritten && !isTransient())
return loadConceptsStructure(programID);
return fullStructure();
} finally {
unlock(__1);
}
}
public void xshutdown() {
cleanKillVM();
}
public long xchangeCount() {
return changes;
}
public int xcount() {
return countConcepts();
}
public void register(Concept c) {
ping();
if (c._concepts == this)
return;
if (c._concepts != null)
throw fail("Can't re-register");
c.id = internalID();
c.created = now();
if (modifyOnCreate)
c._setModified(c.created);
register_phase2(c);
vmBus_send("conceptCreated", c);
fireChange(new ConceptCreate(c));
}
public void register_phase2(Concept c) {
c._concepts = this;
concepts.put((long) c.id, c);
for (Concept.Ref r : c._refs()) r.index();
c.change();
c._onRegistered();
}
public void registerKeepingID(Concept c) {
if (c._concepts == this)
return;
if (c._concepts != null)
throw fail("Can't re-register");
c._concepts = this;
concepts.put((long) c.id, c);
c.change();
}
public void conceptChanged(Concept c) {
fireChange(new ConceptChange(c));
if (conceptIndices != null)
for (IConceptIndex index : clonedConceptIndices()) index.update(c);
}
public boolean hasUnsavedData() {
return changes != changesWritten || savingConcepts;
}
synchronized public Object miscMapGet(Object key) {
return mapGet(miscMap, key);
}
synchronized public Object miscMapPut(Object key, Object value) {
if (miscMap == null)
miscMap = new HashMap();
return miscMap.put(key, value);
}
synchronized public void miscMapRemove(Object key) {
mapRemove(miscMap, key);
}
synchronized public A miscMapGetOrCreate(Object key, IF0 create) {
if (containsKey(miscMap, key))
return (A) miscMap.get(key);
A value = create.get();
miscMapPut(key, value);
return value;
}
public void setParent(Concepts parent) {
this.parent = parent;
}
public void fireChange(ConceptsChange change) {
if (change == null)
return;
pcallFAll(onChange, change);
fireLegacyChangeEvent();
}
final public void onChange(IVF1 l) {
addChangeListener(l);
}
public void addChangeListener(IVF1 l) {
syncAdd(onChange, l);
}
public void removeChangeListener(IVF1 l) {
syncRemove(onChange, l);
}
public void addPreSave(Runnable r) {
preSave = syncAddOrCreate(preSave, r);
}
public String toString() {
return nConcepts(concepts) + " (" + conceptsDir() + ", hash: " + identityHashCode(this) + ")";
}
}
public interface IConcept {
public long _conceptID();
public Concepts concepts();
}
static public class Concept extends DynamicObject implements IConcept, ChangeTriggerable {
transient public Concepts _concepts;
public long id;
public long created, _modified;
public List[ backRefs;
public Concept(String className) {
super(className);
_created();
}
public Concept() {
if (!_loading()) {
_created();
}
}
public Concept(boolean unlisted) {
if (!unlisted)
_created();
}
public boolean includeZeroIDInToString() {
return false;
}
public String toString() {
String s = shortDynamicClassName(this);
long id = this.id;
if (id != 0 || includeZeroIDInToString())
s += " " + id;
return s;
}
static public boolean loading() {
return _loading();
}
static public boolean _loading() {
return dynamicObjectIsLoading();
}
public void _created() {
if (!concepts_unlistedByDefault && !eq(concepts_unlisted.get(), true))
db_mainConcepts().register(this);
}
public class TypedRef extends Ref {
public TypedRef() {
}
public Class bType;
public TypedRef(Class bType) {
this.bType = bType;
}
public TypedRef(Class bType, B value) {
this.bType = bType;
set((A) value);
}
public TypedRef(B value) {
set((A) value);
}
public boolean set(A a) {
return super.set(checkValue(a));
}
public void check() {
checkValue(get());
}
public C checkValue(C a) {
if (bType != null && a != null)
assertIsInstance(a, bType);
return a;
}
public B b() {
return (B) value;
}
}
public class Ref implements IRef {
public A value;
public Ref() {
if (!dynamicObjectIsLoading())
registerRef();
}
public void registerRef() {
vmBus_send("registeringConceptRef", this);
}
public Ref(A value) {
this.value = value;
registerRef();
index();
}
public Concept concept() {
return Concept.this;
}
public A get() {
return value;
}
public boolean has() {
return value != null;
}
public boolean set(A a) {
if (a == value)
return false;
unindex();
value = a;
index();
change();
return true;
}
public void setIfEmpty(A a) {
if (!has())
set(a);
}
public void set(Ref ref) {
set(ref.get());
}
public void clear() {
set((A) null);
}
public boolean validRef() {
return value != null && _concepts != null && _concepts == value._concepts;
}
public void index() {
if (validRef()) {
value._addBackRef(this);
change();
}
}
public Ref unindex() {
if (validRef()) {
value._removeBackRef(this);
change();
}
return this;
}
public void unindexAndDrop() {
unindex();
_removeRef(this);
}
public void change() {
Concept.this.change();
}
public String toString() {
return str(value);
}
}
public class RefL extends AbstractList {
public List][> l = new ArrayList();
public RefL() {
}
public RefL(List l) {
replaceWithList(l);
}
public void clear() {
while (!isEmpty()) removeLast(this);
}
public void replaceWithList(List l) {
clear();
for (A a : unnullForIteration(l)) add(a);
}
public A set(int i, A o) {
Ref ref = syncGet(l, i);
A prev = ref.get();
ref.set(o);
return prev;
}
public void add(int i, A o) {
syncAdd(l, i, new Ref(o));
}
public A get(int i) {
return syncGet(l, i).get();
}
public A remove(int i) {
return syncRemove(l, i).get();
}
public int size() {
return syncL(l);
}
public boolean contains(Object o) {
if (o instanceof Concept)
for (Ref r : l) if (eq(r.get(), o))
return true;
return super.contains(o);
}
}
public void delete() {
for (Ref r : unnullForIteration(_refs())) r.unindex();
for (Ref r : cloneList(backRefs)) r.set((Concept) null);
backRefs = null;
var _concepts = this._concepts;
if (_concepts != null) {
_concepts.concepts.remove(id);
_concepts.fireChange(new ConceptDelete(id, this));
if (_concepts.conceptIndices != null)
for (IConceptIndex index : _concepts.conceptIndices) index.remove(this);
this._concepts = null;
}
id = 0;
}
public BaseXRef export() {
return new BaseXRef(_concepts.progID(), id);
}
final public void _change() {
change();
}
public void change() {
_setModified(now());
_change_withoutUpdatingModifiedField();
}
public void _setModified(long modified) {
_modified = modified;
}
final public void _change_withoutUpdatingModifiedField() {
_onChange();
if (_concepts != null)
_concepts.conceptChanged(this);
}
public void _onChange() {
}
public String _programID() {
return _concepts == null ? getDBProgramID() : _concepts.progID();
}
public void _addBackRef(Concept.Ref ref) {
backRefs = addDyn_quickSync(backRefs, ref);
_backRefsModified();
}
public void _backRefsModified() {
if (_concepts != null && _concepts.modifyOnBackRef)
change();
}
public void _removeBackRef(Concept.Ref ref) {
backRefs = removeDyn_quickSync(backRefs, ref);
_backRefsModified();
}
public void _removeRef(Concept.Ref ref) {
}
public int _backRefCount() {
return syncL(backRefs);
}
final public void setField(String field, Object value) {
_setField(field, value);
}
public void _setField(String field, Object value) {
cset(this, field, value);
}
public boolean setField_trueIfChanged(String field, Object value) {
return cset(this, field, value) != 0;
}
public A setFieldAndReturn(String field, A value) {
setField(field, value);
return value;
}
final public void setFields(Object... values) {
_setFields(values);
}
public void _setFields(Object... values) {
cset(this, values);
}
public Concepts concepts() {
return _concepts;
}
public boolean isDeleted() {
return id == 0;
}
public void _doneLoading() {
}
public void _doneLoading2() {
Map map = _fieldMigrations();
if (map != null)
for (Map.Entry extends String, ? extends FieldMigration> __0 : _entrySet(map)) {
String oldField = __0.getKey();
FieldMigration m = __0.getValue();
crenameField_noOverwrite(this, oldField, m.newField);
}
}
static public class FieldMigration implements IFieldsToList {
public String newField;
public FieldMigration() {
}
public FieldMigration(String newField) {
this.newField = newField;
}
public String toString() {
return shortClassName_dropNumberPrefix(this) + "(" + newField + ")";
}
public boolean equals(Object o) {
if (!(o instanceof FieldMigration))
return false;
FieldMigration __6 = (FieldMigration) o;
return eq(newField, __6.newField);
}
public int hashCode() {
int h = 558692372;
h = boostHashCombine(h, _hashCode(newField));
return h;
}
public Object[] _fieldsToList() {
return new Object[] { newField };
}
}
public Map _fieldMigrations() {
return null;
}
public Collection][ _refs() {
return scanConceptForRefs(this);
}
public Concepts _concepts() {
return _concepts;
}
public boolean _conceptsDefunct() {
return _concepts != null && _concepts.defunct;
}
public boolean _conceptsDefunctOrUnregistered() {
return _concepts == null || _concepts.defunct;
}
public void _onRegistered() {
}
public boolean addAndChange(Collection cl, A a) {
if (cl == null || !cl.add(a))
return false;
change();
return true;
}
public void clearAndChange(Collection cl) {
if (cl == null)
return;
cl.clear();
change();
}
public void addAndChange(LongBuffer buf, long a) {
if (buf == null)
return;
buf.add(a);
change();
}
public void clearAndChange(LongBuffer buf) {
if (buf == null)
return;
buf.clear();
change();
}
public File conceptsDir() {
var concepts = concepts();
return concepts == null ? null : concepts.conceptsDir();
}
public File fileInConceptsDir(String name) {
var dir = conceptsDir();
return dir == null ? null : newFile(dir, name);
}
public long _conceptID() {
return id;
}
}
static public class RC {
transient public Object owner;
public String id;
public RC() {
}
public RC(long id) {
this.id = str(id);
}
public RC(Object owner, long id) {
this.id = str(id);
this.owner = owner;
}
public RC(Concept c) {
this(c.id);
}
public long longID() {
return parseLong(id);
}
public String toString() {
return id;
}
transient public RemoteDB db;
public String getString(String field) {
return db.xS(this, field);
}
public Object get(String field) {
return db.xget(this, field);
}
public void set(String field, Object value) {
db.xset(this, field, value);
}
}
static public class BaseXRef {
public String programID;
public long id;
public BaseXRef() {
}
public BaseXRef(String programID, long id) {
this.id = id;
this.programID = programID;
}
public boolean equals(Object o) {
if (!(o instanceof BaseXRef))
return false;
BaseXRef r = (BaseXRef) o;
return eq(programID, r.programID) && eq(id, r.id);
}
public int hashCode() {
return programID.hashCode() + (int) id;
}
}
static public class XRef extends Concept {
public BaseXRef ref;
public XRef() {
}
public XRef(BaseXRef ref) {
this.ref = ref;
_doneLoading2();
}
public void _doneLoading2() {
getIndex().put(ref, this);
}
public HashMap getIndex() {
return getXRefIndex(_concepts);
}
}
static synchronized public HashMap getXRefIndex(Concepts concepts) {
HashMap cache = (HashMap) concepts.perClassData().get(XRef.class);
if (cache == null)
concepts.perClassData.put(XRef.class, cache = new HashMap());
return cache;
}
static public XRef lookupOrCreateXRef(BaseXRef ref) {
XRef xref = getXRefIndex(db_mainConcepts()).get(ref);
if (xref == null)
xref = new XRef(ref);
return xref;
}
static public void loadAndAutoSaveConcepts() {
db_mainConcepts().persist();
}
static public void loadAndAutoSaveConcepts(int interval) {
db_mainConcepts().persist(interval);
}
static public RC toPassRef(Concept c) {
return new RC(c);
}
static public void concepts_setUnlistedByDefault(boolean b) {
concepts_unlistedByDefault = b;
}
public static interface IF0 {
public A get();
}
static public interface IF1 {
public B get(A a);
}
static public interface IVF1 {
public void get(A a);
}
public interface G22MasterStuff {
public RunnablesReferenceQueue runnablesReferenceQueue();
public EphemeralObjectIDs ephemeralObjectIDs();
public File databasesMotherDir();
default public IG22LoadedDB openDatabase(File dir) {
return openDatabase(dir, false);
}
public IG22LoadedDB openDatabase(File dir, boolean hidden);
default public IG22LoadedDB openDB(String dbName) {
return openDB(dbName, false);
}
public IG22LoadedDB openDB(String dbName, boolean hidden);
public void closeDatabase(File dir);
public void switchToDatabase(File dir);
public Collection openConceptDirs();
public IG22LoadedDB getLoadedDB(Concepts concepts);
public IG22LoadedDB getLoadedDBForConceptDir(File dir);
default public Collection extends IG22LoadedDB> openProjects() {
return getLoadedDBs();
}
public Collection extends IG22LoadedDB> getLoadedDBs();
public G22MasterStuff onLoadedDBsChange(Runnable r);
public G22MasterStuff removeLoadedDBsChangeListener(Runnable r);
public IF1 makeClassFinder();
public IF0WithChangeListeners]