abstract sclass DynImageSurface extends DynModule { transient ImageSurface imageSurface; transient BufferedImage image; transient S imageID; transient bool useUpdateHack; transient O onNewImage; visualize { imageSurface = imageSurface(image); imageSurface.onNewImage = r newImageFromSurface; ret jscroll_center(imageSurface); } // call after visualize void enableDoubleBuffering { if (imageSurface != null) imageSurface.setDoubleBuffered(true); } // hold image during reload (not during reboot yet) O _getReloadData() { ret image; } void _setReloadData(BufferedImage image) { this.image = image; } // API void setImage(MakesBufferedImage image) { imageID = null; setImage(image == null ? null : image.getBufferedImage()); } void newImageFromSurface { setImage(imageSurface.getImage()); } void setImage(BufferedImage image) { this.image = image; imageID = null; if (imageSurface != null) { temp tempSetField(imageSurface, onNewImage := null); // avoid recursion imageSurface.setImage(image); } vmBus_send('newImage, this); pcallF(onNewImage, image); } void setImage(S imageID) { if (sameSnippetID(this.imageID, imageID)) ret; setImage(loadImage2(imageID)); this.imageID = imageID; } BufferedImage getImage() { if (useUpdateHack) { // HACKY: to get changes in ImageSurface (e.g. images drag&dropped in there directly) ImageSurface is = imageSurface; if (is != null && is.getImage() != image) setImage(is.getImage()); } ret image; } bool hasImage() { ret image != null; } void setZoom(double zoom) { if (imageSurface != null) imageSurface.setZoom(zoom); } Rect getSelection() { ret imageSurface == null ? null : toRect(imageSurface.getSelection()); } void setSelection(Rect r) { if (imageSurface != null) imageSurface.setSelection(toRectangle(r)); } int imageWidth() { ret imageSurface.getImage().getWidth(); } int imageHeight() { ret imageSurface.getImage().getHeight(); } }