fun setStyle(node, name, value) {ignore(domSetStyleAttrFromRef(node, name, value))} fun dragging(offsetLeft, offsetTop, left, top, width, height, mdownX, mdownY) client { receive { case MouseMove(x, y) -> { var frame = getNodeById("cropping-frame"); setStyle(frame, "left", intToString(x - mdownX + left)); setStyle(frame, "top", intToString(y - mdownY + top)); var pictureFrame = getNodeById("picture-frame"); # FIXME: should actually be a method that sums up the offsetXxxxs # of all ancestor nodes. var offsetLeft = stringToInt(domGetAttributeFromRef(pictureFrame, "offsetLeft")); var offsetTop = stringToInt(domGetAttributeFromRef(pictureFrame, "offsetTop")); var preview = getNodeById("crop-preview"); setStyle(preview, "marginTop", intToString(-(y - mdownY + top - offsetTop))); setStyle(preview, "marginLeft", intToString(-(x - mdownX + left - offsetLeft))); dragging(offsetLeft, offsetTop, left, top, width, height, mdownX, mdownY) } case MouseUp(x, y) -> frameMgr(offsetLeft, offsetTop, left + x - mdownX, top + y - mdownY, width, height) case _ -> dragging(offsetLeft, offsetTop, left, top, width, height, mdownX, mdownY) } } fun resizing(offsetLeft, offsetTop, left, top, width, height, corner) client { receive { case MouseMove(x, y) -> { var pictureFrame = getNodeById("picture-frame"); var offsetLeft = stringToInt(domGetAttributeFromRef(pictureFrame, "offsetLeft")); var offsetTop = stringToInt(domGetAttributeFromRef(pictureFrame, "offsetTop")); var frame = getNodeById("cropping-frame"); var frameSizer = getNodeById("white-border"); var (l, t, w, h) = switch (corner) { case NW -> (x, y, width - (x - left), height - y + top) case NE -> (left, y, x - left, height - y + top) case SW -> (x, top, width - (x - left), y-top) case SE -> (left, top, x-left, y-top) }; setStyle(frame, "left", intToString(l-offsetLeft)); setStyle(frame, "top", intToString(t)); setStyle(frameSizer, "width", intToString(w)); setStyle(frameSizer, "height", intToString(h)); var previewFrame = getNodeById("crop-preview-frame"); setStyle(previewFrame, "width", intToString(w)); setStyle(previewFrame, "height", intToString(h)); var preview = getNodeById("crop-preview"); setStyle(preview, "marginTop", intToString(-t+offsetTop)); setStyle(preview, "marginLeft", intToString(-l+offsetLeft)); resizing(offsetLeft, offsetTop, l, t, w, h, corner) } case MouseUp(x, y) -> { frameMgr(offsetLeft, offsetTop, left, top, width, height); } case _ -> { resizing(offsetLeft, offsetTop, left, top, width, height, corner) } } } fun frameMgr(offsetLeft, offsetTop, left, top, width, height) client { receive { case MouseDown(x, y) -> dragging(offsetLeft, offsetTop, left, top, width, height, x, y) case StartResize(corner) -> resizing(offsetLeft, offsetTop, left, top, width, height, corner) case _ -> frameMgr(offsetLeft, offsetTop, left, top, width, height) } } fun makeCroppingFrame(left, top, width, height) { var frameMgr = spawnClient {frameMgr(left, top, left, top, width, height)};
} fun main() { page

Home of Robert Louis Stevenson

{ makeCroppingFrame(16, 112, 32, 32) }
Drag the cropping frame around the image; drag the wee handles in the corners to resize it.
} main()