Warning: session_start(): open(/var/lib/php/sessions/sess_okj3r1uveqssefnlkl650t5osa, 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 JPaintTool > MetaWithChangeListeners is Swingable, AutoCloseable {
settableWithVar File autoPersistFile;
settableWithVar double autoPersistInterval = 10.0;
settableWithVar Color brushColor = Color.black;
event imageChanged(BufferedImage image);
transient settableWithChange volatile bool dirty;
transient gettable BufferedImage image;
transient ImageSurface imageSurface;
transient bool autoPersistInstalled;
transient ReliableSingleThread rstPersist = new(r _persist);
transient JPanel buttons;
transient ImageSurfaceScribbleTool scribbler;
transient JComboBox cbImageSize;
transient settableWithVar S status;
transient new ButtonGroup colorButtonGroup;
transient simplyCached void init() {
imageSurface = makeImageSurface();
cbImageSize = jTypedComboBox(imageSizes());
main onChange(cbImageSize, l1 setImageSize);
printVars("JPaintTool.init", +image, +autoPersistFile);
if (image == null) {
setImage(makeNewImage());
if (autoPersistFile != null) {
pcall {
var img = loadImage2(autoPersistFile);
if (img != null) {
setImage(img);
print("Image loaded");
}
}
if (!autoPersistInstalled) {
set autoPersistInstalled;
awtEvery(imageSurface, autoPersistInterval, rstPersist);
bindToComponent(imageSurface, null, rstPersist);
}
}
}
}
BufferedImage makeNewImage() {
ret main newImage(defaultImageSize());
}
WidthAndHeight defaultImageSize() { ret getSelected(cbImageSize); }
public transient simplyCached JComponent visualize() {
init();
var filePathLabel = new JFilePathLabel(autoPersistFile).nameOnly();
varAutoPersistFile().onChange(file -> filePathLabel.setFile(file));
ret withTopMargin(northCenterAndSouthWithMargin(
buttons = jcenteredline(flattenToList(
jbutton("New image", rThread newImage),
withLabel("Size:", cbImageSize),
map colorSelectButton(colors())
)),
jscroll_center_borderless(imageSurface),
centerAndEast(
jVarLabel(varStatus()),
autoPersistFile == null ? jpanel()
: withLeftMargin(withLabel("File", filePathLabel.visualize()))
)
));
}
void setImage(BufferedImage image) {
this.image = image;
imageSurface.setImage(image);
imageChanged(image);
}
transient swappable ImageSurface makeImageSurface() {
var is = pixelatedImageSurface();
//is.setAutoZoomToDisplay(true);
//is.specialPurposed = true;
is.zoomable(false);
is.removeAllTools();
scribbler = new ImageSurfaceScribbleTool(is);
scribbler.onPainted(-> { set dirty; imageChanged(is.getImage()); });
varBrushColor().onChangeAndNow(color -> scribbler.setColor(color));
ret is;
}
void _persist {
if (autoPersistFile != null && dirty) {
dirty = false;
savePNGVerbose(autoPersistFile, image);
}
}
void newImage() ctex {
close(); // persist
//if (dirty && !swingConfirm(imageSurface, "Discard image")) ret;
var file = createAutoPersistFile();
print("Created auto persist file: " + f2s(file));
autoPersistFile(file);
setImage(makeNewImage());
dirty = false;
}
// swap to make a new file every time user clicks "New image"
swappable File createAutoPersistFile() { ret autoPersistFile(); }
JToggleButton colorSelectButton(Color color) {
var btn = jImageToggleButton(main newImage(16, color),
"Select color to draw with", -> setBrushColor(color),
eq(brushColor(), color));
ret addToButtonGroup(colorButtonGroup, btn);
}
L colors() {
ret colorPaletteByBits(1); // 8 primary colors
}
L imageSizes() {
ret mapLL sixteenToNine_p(
240, 360, 480, 720
);
}
void setImageSize(WidthAndHeight size) {
if (!sameSize(getImage(), size))
newImage();
}
close {
rstPersist.triggerAndWait();
}
BufferedImage getImage() { ret is?.getImage(); }
}