Warning: session_start(): open(/var/lib/php/sessions/sess_rdusv3fbmes8ql4hs1kvsdmn79, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
sclass BaseBase {
S text;
S textForRender() { ret text; }
}
sclass Base extends BaseBase {
}
sclass CirclesAndLines {
new L circles;
new L lines;
Class extends Arrow> arrowClass = Arrow;
Class extends Circle> circleClass = Circle;
transient Lock lock = fairLock();
transient S defaultImageID = #1007372;
double imgZoom = 1;
Pt translate;
Circle hoverCircle; // which one we are hovering over
O onUserMadeArrow, onUserMadeCircle, onLayoutChange;
O onFullLayoutChange, onDeleteCircle, onDeleteLine;
BufferedImage imageForUserMadeNodes;
// auto-visualize
Circle circle_autoVis(S text, S visualizationText, double x, double y) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(quickVisualizeOr(visualizationText, defaultImageID))));
}
S makeVisualizationText(S text) {
ret possibleGlobalID(text) ? "" : text;
}
Circle circle_autoVis(S text, double x, double y) {
ret circle_autoVis(text, makeVisualizationText(text), x, y);
}
Circle circle(BufferedImage img, double x, double y, S text) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(img));
}
Circle circle(S text, BufferedImage img, double x, double y) {
ret circle(img, x, y, text);
}
Circle circle(S text, double x, double y) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(loadImage2(#1007452))); // white
}
Circle addCircle(S imageID, double x, double y) {
ret addCircle(imageID, x, y, "");
}
Circle addCircle(S imageID, double x, double y, S text) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(loadImage2(imageID))));
}
Arrow findArrow(Circle a, Circle b) {
for (Line l : getWhere(lines, +a, +b))
if (l instanceof Arrow)
ret (Arrow) l;
null;
}
Line addLine(Circle a, Circle b) {
Line line = findWhere(lines, +a, +b);
if (line == null)
lines.add(line = nu(Line, +a, +b));
ret line;
}
Arrow arrow(Circle a, S text, Circle b) {
ret addArrow(a, b, text);
}
Arrow addArrow(Circle a, Circle b) {
ret addArrow(a, b, "");
}
Arrow addArrow(Circle a, Circle b, S text) {
ret addAndReturn(lines, nu(arrowClass, +a, +b, +text));
}
BufferedImage makeImage(int w, int h) {
BufferedImage bg = renderTiledBackground(#1007195, w, h, ptX(translate), ptY(translate));
if (!lock.tryLock()) null;
try {
// Lines
for (Line l : lines) {
Pt a = translatePt(translate, l.a.pt(w, h));
Pt b = translatePt(translate, l.b.pt(w, h));
if (l << Arrow)
drawThoughtArrow(bg, l.a.img(), a.x, a.y, l.b.img(), b.x, b.y, l.color);
else
drawThoughtLine(bg, l.a.img(), a.x, a.y, l.b.img(), b.x, b.y, l.color);
S text = l.textForRender();
if (nempty(text))
drawThoughtLineText(bg, l.a.img(), a.x, a.y, l.b.img(), b.x, b.y, text, l.color);
}
// Circles
for (Circle c : circles) {
Pt p = translatePt(translate, c.pt(w, h));
drawThoughtCircle(bg, c.img(), p.x, p.y);
S text = c.textForRender();
if (nempty(text))
drawThoughtCircleText(bg, c.img(), p, text);
if (c == hoverCircle)
drawThoughtCirclePlus(bg, c.img(), p.x, p.y);
}
} finally {
lock.unlock();
}
ret bg;
}
Canvas showAsFrame(int w, int h) {
Canvas canvas = showAsFrame();
frameInnerSize(canvas, w, h);
centerFrame(getFrame(canvas));
ret canvas;
}
Canvas showAsFrame() {
ret (Canvas) swing(func {
Canvas canvas = makeCanvas();
showCenterFrame(canvas);
ret canvas;
});
}
Canvas makeCanvas() {
fO makeImg = func(int w, int h) { makeImage(w, h) };
final Canvas canvas = jcanvas(makeImg);
disableImageSurfaceSelector(canvas);
new CircleDragger(this, canvas, r { updateCanvas(canvas, makeImg) });
componentPopupMenu(canvas, voidfunc(JPopupMenu menu) {
Pt p = canvas.pointFromEvent(componentPopupMenu_mouseEvent.get());
final Line l = findLine(canvas, p);
if (l != null)
addMenuItem(menu, "Delete Relation", r {
deleteLine(l);
canvas.update();
});
final Circle c = findCircle(canvas, p);
if (c != null)
addMenuItem(menu, "Delete Circle", r {
deleteCircle(c);
canvas.update();
});
});
ret canvas;
}
Canvas show() { ret showAsFrame(); }
Canvas show(int w, int h) { ret showAsFrame(w, h); }
Circle findCircle(S text) {
for (Circle c : circles)
if (eqic(c.text, text))
ret c;
null;
}
void clear {
clearAll(circles, lines);
}
Circle findNearestCircle(Canvas canvas, Pt p) {
new Lowest best;
for (Circle c : circles)
if (c.contains(canvas, p))
best.put(c, pointDistance(p, c.pt(canvas)));
ret best.get();
}
BufferedImage processImage(BufferedImage img) {
ret scaleImage(img, imgZoom);
}
void deleteCircle(Circle c) {
for (Line l : cloneList(lines))
if (l.a == c || l.b == c) lines.remove(l);
circles.remove(c);
pcallF(onDeleteCircle, c);
}
void deleteLine(Line l) {
lines.remove(l);
pcallF(onDeleteLine, l);
}
void openPlusDialog(Circle c) {
if (c == null) ret;
final JTextField tfFrom = jtextfield(c.text);
final JTextField tfRel = jtextfield(web_defaultRelationName());
final JTextField tfTo = jtextfield();
showFormTitled("Add connection",
"From node", tfFrom,
"Conection name", tfRel,
"To node", tfTo,
func {
Circle a = findOrMakeCircle(getTextTrim(tfFrom));
if (a == null) { messageBox("Not found: " + getTextTrim(tfFrom)); false; }
Circle b = findOrMakeCircle(getTextTrim(tfTo));
if (b == null) { messageBox("Not found: " + getTextTrim(tfTo)); false; }
pcallF(onUserMadeArrow, arrow(a, getTextTrim(tfRel), b));
null;
});
awtLater(tfRel, 100, r { requestFocus(tfRel) });
}
Circle findOrMakeCircle(S text) {
Circle c = findCircle(text);
if (c == null) {
if (imageForUserMadeNodes == null)
imageForUserMadeNodes = whiteImage(20, 20);
c = circle(imageForUserMadeNodes, random(), random(), text);
pcallF(onUserMadeCircle, c);
}
ret c;
}
Line findLine(Canvas is, Pt p) {
p = untranslatePt(translate, p);
new Lowest best;
for (Line line : lines) {
double d = distancePointToLineSegment(line.a.pt(is), line.b.pt(is), p);
if (d <= maxDistanceToLine)
best.put(line, d);
}
ret best!;
}
} // end of class CirclesAndLines
sclass Circle extends Base {
transient BufferedImage img;
double x, y;
static BufferedImage defaultImage;
BufferedImage img() {
if (img != null) ret img;
if (defaultImage == null) defaultImage = loadImage2(#1007372);
ret defaultImage;
}
Pt pt(ImageSurface is) {
ret pt(is.getWidth(), is.getHeight());
}
Pt pt(int w, int h) {
ret new Pt(iround(x*w), iround(y*h));
}
bool contains(ImageSurface is, Pt p) {
ret pointDistance(p, pt(is)) <= thoughtCircleSize(img())/2+1;
}
}
sclass Line extends Base {
Circle a, b;
Color color = Color.white;
Line setColor(Color color) {
this.color = color;
this;
}
}
Line > Arrow {}
sclass CircleDragger extends MouseAdapter {
CirclesAndLines cal;
ImageSurface is;
O update;
int dx, dy;
Circle circle;
Pt startPoint;
static int maxDistanceToLine = 20;
*(CirclesAndLines *cal, ImageSurface *is, O *update) {
if (containsInstance(is.tools, CircleDragger)) ret;
is.tools.add(this);
is.addMouseListener(this);
is.addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e) {
Pt p = is.pointFromEvent(e);
Circle c = findCircle(p);
if (c != cal.hoverCircle) {
cal.hoverCircle = c;
callF(update);
}
}
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Pt p = is.pointFromEvent(e);
startPoint = p;
circle = findCircle(p);
if (circle != null) {
dx = p.x-iround(circle.x*is.getWidth());
dy = p.y-iround(circle.y*is.getHeight());
} else {
Pt t = unnull(cal.translate);
dx = p.x-t.x;
dy = p.y-t.y;
}
}
}
public void mouseDragged(MouseEvent e) {
Pt p = is.pointFromEvent(e);
if (circle != null) {
circle.x = (p.x-dx)/(double) is.getWidth();
circle.y = (p.y-dy)/(double) is.getHeight();
pcallF(cal.onLayoutChange, circle);
callF(update);
} else {
cal.translate = new Pt(p.x-dx, p.y-dy);
callF(update);
}
}
public void mouseReleased(MouseEvent e) {
mouseDragged(e);
if (eq(is.pointFromEvent(e), startPoint))
cal.openPlusDialog(circle);
circle = null;
}
// only finds actually containing circles
Circle findCircle(Pt p) {
p = untranslatePt(cal.translate, p);
new Lowest best;
for (Circle c : cal.circles)
if (c.contains(is, p))
best.put(c, pointDistance(p, c.pt(is)));
ret best!;
}
}