From 2cdf5f913a12e6aa97723fa44ced88824cd100fb Mon Sep 17 00:00:00 2001 From: jonathan Date: Sat, 21 Nov 2020 09:50:22 +0200 Subject: [PATCH 1/4] Implemented image cropper --- src/cave.ui/BoxIconWidget.sling | 199 ++++++++++++++++++++ src/cave.ui/CropImageWidget.sling | 289 ++++++++++++++++++++++++++++++ src/cave.ui/CropRangeWidget.sling | 167 +++++++++++++++++ 3 files changed, 655 insertions(+) create mode 100644 src/cave.ui/BoxIconWidget.sling create mode 100644 src/cave.ui/CropImageWidget.sling create mode 100644 src/cave.ui/CropRangeWidget.sling diff --git a/src/cave.ui/BoxIconWidget.sling b/src/cave.ui/BoxIconWidget.sling new file mode 100644 index 00000000..25dcbbb9 --- /dev/null +++ b/src/cave.ui/BoxIconWidget.sling @@ -0,0 +1,199 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016-2018 Job and Esther Technologies Oy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +class is LayerWidget #widget: + +IFDEF "target_html" +{ + var sdkIncluded static = false + + func createElement override as object: + return HTMLDOM.createElement("i") + + func prepareElement(element as object) override + { + base.prepareElement(element) + HTMLDOM.setStyle(element, "font-size", "20px") + HTMLDOM.setStyle(element, "text-align", "center") + HTMLDOM.addToClassList(element, "bx") + } + + func initializeHtmlWidget + { + if sdkIncluded { + PRINT "Boxicons CSS included" + return + } + if HTMLDOM.getElementById(VALUE "__THIS__"): + return + var link = HTMLDOM.createElement("link") + HTMLDOM.setAttribute(link, "id", VALUE "__THIS__") + HTMLDOM.setAttribute(link, "rel", "stylesheet") + HTMLDOM.setAttribute(link, "href", "https://unpkg.com/boxicons@2.0.5/css/boxicons.min.css") + HTMLDOM.appendChild(HTMLDOM.getDocumentHead(), link) + } +} + +const SPIN_ANIMATION = 0 +const TADA_ANIMATION = 1 +const FLASHING_ANIMATION = 2 +const BURST_ANIMATION = 3 +const FADE_LEFT_ANIMATION = 4 +const FADE_RIGHT_ANIMATION = 5 +const FADE_UP_ANIMATION = 6 +const FADE_DOWN_ANIMATION = 7 + +var widgetContext as GuiApplicationContext +var widgetColor as Color +var widgetFontSize as double +var lastResourceString as string +var lastAnimationAdded as string +var lastRotateString as string + +ctor(ctx as cave.GuiApplicationContext) +{ + base(ctx) + widgetColor = Color.black() +} + +func setWidgetColor(color as Color) +{ + widgetColor = color + IFDEF "target_html" { + if not widgetColor { + HTMLDOM.removeStyle(element, "color") + } + else { + HTMLDOM.setStyle(element, "color", HTMLDOM.colorToRGBA(widgetColor)) + } + } +} + +func setWidgetFontSize(fontSize as double #notLiteral) as this +{ + widgetFontSize = fontSize + updateWidgetFont(true) + return this +} + +func updateWidgetFont(changesLayout as bool) private +{ + IFDEF "target_html" { + HTMLDOM.setStyle(this.element, "font-size", String.forDouble(widgetFontSize) .. "px") + } + if changesLayout: + Widget.onLayoutChanged(this) +} + +func setWidgetIcon(resource as string) as this +{ + assert String.isNotEmpty(resource) + IFDEF "target_html" { + if String.isNotEmpty(lastResourceString): + HTMLDOM.removeFromClassList(this.element, "bx-" .. lastResourceString) + HTMLDOM.addToClassList(this.element, "bx-" .. resource) + } + lastResourceString = resource + Widget.onLayoutChanged(this) + return this +} + +func setWidgetLogo(resource as string) as this +{ + assert String.isNotEmpty(resource) + IFDEF "target_html" { + HTMLDOM.addToClassList(this.element, "bxl-" .. resource) + } + Widget.onLayoutChanged(this) + return this +} + +func setWidgetHoverAnimation(type as int) as this +{ + setWidgetAnimation(type, true) + return this +} + +func setWidgetAnimation(animation as int, hover as bool = false) as this +{ + if animation < 0 { + IFDEF "target_html" { + if lastAnimationAdded: + HTMLDOM.removeFromClassList(this.element, lastAnimationAdded) + lastAnimationAdded = null + } + return this + } + var sb = StringBuilder.forString("bx-") + if animation == SPIN_ANIMATION { + sb.append("spin") + } + else if animation == TADA_ANIMATION { + sb.append("tada") + } + else if animation == FLASHING_ANIMATION { + sb.append("flashing") + } + else if animation == BURST_ANIMATION { + sb.append("burst") + } + else if animation == FADE_LEFT_ANIMATION { + sb.append("fade-left") + } + else if animation == FADE_RIGHT_ANIMATION { + sb.append("fade-right") + } + else if animation == FADE_UP_ANIMATION { + sb.append("fade-up") + } + else if animation == FADE_DOWN_ANIMATION { + sb.append("fade-down") + } + if hover: + sb.append("-hover") + IFDEF "target_html" { + lastAnimationAdded = sb.toString() + HTMLDOM.addToClassList(this.element, lastAnimationAdded) + } + return this +} + +func setWidgetRotate(rotate as int) as this +{ + var rotateString = "bx-rotate-" .. String.forInteger(rotate) + IFDEF "target_html" { + if String.isNotEmpty(lastRotateString): + HTMLDOM.removeFromClassList(this.element, lastRotateString) + HTMLDOM.addToClassList(this.element, rotateString) + } + lastRotateString = rotateString + return this +} + +func onWidgetAddedToParent override +{ + base.onWidgetAddedToParent() + IFDEF "target_browser" { + initializeHtmlWidget() + } +} diff --git a/src/cave.ui/CropImageWidget.sling b/src/cave.ui/CropImageWidget.sling new file mode 100644 index 00000000..15164f2f --- /dev/null +++ b/src/cave.ui/CropImageWidget.sling @@ -0,0 +1,289 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016-2018 Job and Esther Technologies Oy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +class #widget: + +ui LayerWidget +{ + CanvasWidget { + color = Color.instance("#373a40") + } + VerticalBoxWidget { + LabelWidget title { + text = "Update Profile Picture" + textAlign = LabelWidget.ALIGN_CENTER + fontBold = true + padding = context.getStylePixels("jkop-kit", "padding", "2mm") + textColor = Color.instance("#FFFFFF") + } + LayerWidget layer : 1.0 { + ImageWidget img { + imageScaleMethod = ImageWidget.FILL + } + CropperLayerWidget canvas { + } + AlignWidget reposition { + LayerWithBackgroundColorWidget { + color = Color.forRGBADouble(0, 0, 0, 0.5) + roundingRadius = context.getHeightValue("800um") + outlineColor = Color.white() + HorizontalBoxWidget { + spacing = context.getStylePixels("jkop-kit", "spacing", "1mm") + margin = context.getStylePixels("jkop-kit", "spacing", "1mm") + AlignWidget { + BoxIconWidget { + icon = "move" + fontSize = context.getHeightValue("3mm") + color = Color.white() + } + } + AlignWidget { + LabelWidget { + text = "Drag to Reposition" + textColor = Color.white() + fontBold = true + fontSize = context.getHeightValue("3mm") + } + } + } + } + } + } + LayerWithBackgroundColorWidget { + color = Color.instance("#373a40") + VerticalBoxWidget { + CropRangeWidget control { + roundingRadius = context.getHeightValue("2000um") + rangeColor = Color.instance("#0278ae") + } + LayerWithBackgroundColorWidget { + heightRequest = context.getStylePixels("jkop-kit", "separatorSize", "1px") + color = context.getStyleColor("jkop-kit", "separatorColor", "#000000") + } + HorizontalBoxWidget { + margin = context.getStylePixels("jkop-kit", "margin", "2mm") + spacing = context.getStylePixels("jkop-kit", "spacing", "2mm") + ButtonWidget : 1.0 { + text = "CANCEL" + clickHandler = func { + onCancelClicked() + } + } + ButtonWidget button : 1.0 { + text = "SAVE" + clickHandler = func { + onCropImage() + } + } + } + } + } + } +} + +pvar image as Image +pvar doneCroppedHandler as function +pvar widgetNegativeClickHandler as function +var originalHeight as int +var originalWidth as int +var refX as double +var refY as double + +ctor(ctx as GuiApplicationContext) +{ + base(ctx) + forceCreateWidget() +} + +func initializeWidget override +{ + base.initializeWidget() + img.setWidgetImage(image) + Widget.setWidgetPointerHandlers(reposition, onStartHandler, onTouchHandler, onEndHandler) + Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) + control.setWidgetControlChangeListener(func(val as double) { + if originalWidth <= 0: + originalWidth = Widget.getWidth(img) + if originalHeight <= 0: + originalHeight = Widget.getHeight(img) + var sw = (originalWidth + val) as int + var sh = (originalHeight + val) as int + Widget.setLayoutSize(img, sw, sh) + }) +} + +func onCancelClicked +{ + new PopupDialogManager(context, this).showConfirmDialog("Confirm", "Are you sure you want to discard your edits?", func { + assert widgetNegativeClickHandler + widgetNegativeClickHandler() + }, null) +} + +func onStartHandler(x as double, y as double) +{ + refX = x + refY = y +} + +func onTouchHandler(x as double, y as double) +{ + var iy = Widget.getY(img) + var ix = Widget.getX(img) + var endRight as bool + var endLeft as bool + var endDown as bool + var endUp as bool + if refX < x && ix >= 0 { + ix = 0 + endRight = true + } + var maxX = Widget.getWidth(img) - Widget.getWidth(canvas) + if refX > x && Math.abs(ix) >= maxX { + ix = -maxX + endLeft = true + } + if refY < y && iy >= 0 { + iy = 0 + endDown = true + } + var maxY = Widget.getHeight(img) - Widget.getHeight(canvas) + if refY > y && Math.abs(iy) >= maxY { + iy = -maxY + endUp = true + } + var mx as int + var my as int + if not endRight && not endLeft { + mx = ix + (x - refX) as int + } + else if endLeft { + mx = -maxX + } + if not endUp && not endDown { + my = iy + (y - refY) as int + } + else if endUp { + my = -maxY + } + Widget.move(img, mx, my) +} + +func onEndHandler(x as double, y as double): + nop + +func onCropImage private +{ + var cheight = Widget.getHeight(canvas) + var cwidth = Widget.getWidth(canvas) + var radius = ((cwidth + cheight) / 2) / 2 + var x = (cwidth / 2) - (radius / 2) + var y = (cheight / 2) - (radius / 2) + image.scaleToSize(Widget.getWidth(img), Widget.getHeight(img), func(newimage as Image) { + var xx = Math.abs(Widget.getX(img)) + x + var yy = Math.abs(Widget.getY(img)) + y + newimage.crop(xx as int, yy as int, radius, radius, func(cimage as Image) { + if doneCroppedHandler: + doneCroppedHandler(cimage) + }) + }) +} + +class CropperLayerWidget is CanvasWidget is ResizeAwareWidget #widget +{ + + IFDEF "target_android" { + lang "java" {{{ + @Override + protected void onDraw(android.graphics.Canvas canvas) { + super.onDraw(canvas); + android.graphics.Paint mTransparentPaint = new android.graphics.Paint(); + mTransparentPaint.setColor(android.graphics.Color.TRANSPARENT); + mTransparentPaint.setStrokeWidth(10); + android.graphics.Paint mSemiBlackPaint = new android.graphics.Paint(); + mSemiBlackPaint.setColor(android.graphics.Color.TRANSPARENT); + mSemiBlackPaint.setStrokeWidth(10); + android.graphics.Path mPath = new android.graphics.Path(); + mPath.reset(); + float cw = canvas.getWidth() / 2; + float ch = canvas.getHeight() / 2; + float rr = ((cw + ch) / 2) / 2; + mPath.addCircle(cw, ch, rr, android.graphics.Path.Direction.CW); + mPath.setFillType(android.graphics.Path.FillType.INVERSE_EVEN_ODD); + canvas.drawCircle(cw, ch, rr, mTransparentPaint); + canvas.drawPath(mPath, mSemiBlackPaint); + canvas.clipPath(mPath); + canvas.drawColor(android.graphics.Color.parseColor("#555555")); + } + }}} + } + + func onWidgetResized + { + IFDEF "target_html" { + var cheight = Widget.getHeight(canvas) + var cwidth = Widget.getWidth(canvas) + var ee = this.element + var parent = assert HTMLDOM.getParentElement(ee) + var ecanvas = HTMLDOM.createElement("canvas") + HTMLDOM.setStyle(ecanvas, "height", String.asString(cheight)) + HTMLDOM.setStyle(ecanvas, "width", String.asString(cwidth)) + HTMLDOM.setStyle(ecanvas, "position", "absolute") + HTMLDOM.appendChild(parent, ecanvas) + lang "js" {{{ + var ctx = ecanvas.getContext('2d'); + var xc = ecanvas.width / 2; + var yc = ecanvas.height / 2; + var rr = ((xc + yc) / 2) / 2; + + ctx.fillStyle = "#555555"; + ctx.globalAlpha = 0.8; + ctx.fillRect(0, 0, ecanvas.width, ecanvas.height); + ctx.translate(xc, yc); + + ctx.beginPath(); + ctx.arc(0, 0, rr, 0, Math.PI * 2, true); + ctx.clip(); + ctx.clearRect(-xc, -yc, ecanvas.width, ecanvas.height); + }}} + } + ELSE IFDEF "target_ios" { + IFDEF "target_objc" { + setWidgetColor(Color.instance("#555555")) + lang "objc" {{{ + int radius = self.bounds.size.width / 3; + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) cornerRadius:0]; + [path addArcWithCenter:self.center radius:radius startAngle:0.0 endAngle:2*M_PI clockwise: TRUE]; + + CAShapeLayer *fillLayer = [CAShapeLayer layer]; + fillLayer.path = path.CGPath; + fillLayer.fillRule = kCAFillRuleEvenOdd; + self.layer.mask = fillLayer; + self.clipsToBounds = true; + }}} + } + } + Widget.setAlpha(this, 0.5) + } +} diff --git a/src/cave.ui/CropRangeWidget.sling b/src/cave.ui/CropRangeWidget.sling new file mode 100644 index 00000000..7112f686 --- /dev/null +++ b/src/cave.ui/CropRangeWidget.sling @@ -0,0 +1,167 @@ + +/* + * This file is part of Jkop + * Copyright (c) 2016-2018 Job and Esther Technologies Oy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +class #widget: + +class RangeControlWidget #widget +{ + ui LayerWidget + { + widthRequest = context.getHeightValue("4mm") + heightRequest = context.getHeightValue("4mm") + CanvasWidget outline { + color = Color.instance("#000000") + roundingRadius = context.getHeightValue("800um") + } + LayerWidget { + margin = context.getHeightValue("10um") + CanvasWidget cirle { + color = Color.instance("#ffffff") + roundingRadius = context.getHeightValue("800um") + } + } + } + + func setWidgetColor(color as Color): + cirle.setWidgetColor(color) + + func setWidgetRoundingRadius(radius as int #notLiteral) + { + outline.setWidgetRoundingRadius(radius) + cirle.setWidgetRoundingRadius(radius) + } +} + +ui HorizontalBoxWidget +{ + margin = context.getStylePixels("jkop-kit", "spacing", "3mm") + AlignWidget : 0.0 { + BoxIconWidget minusIcon : 0.0, 0.5 { + icon = "minus" + fontSize = context.getHeightValue("6mm") + } + } + LayerWidget con : 1.0 { + AlignWidget { + LayerWidget : 0.5, 0.5, true { + marginLeft = context.getHeightValue("2mm") + marginRight = context.getHeightValue("2mm") + heightRequest = context.getHeightValue("500um") + CanvasWidget prange { + color = Color.instance("#000000") + } + CanvasWidget range { + color = Color.instance("#000000") + } + } + RangeControlWidget control : 0.0, 0.5 { + } + } + } + AlignWidget { + BoxIconWidget plusIcon : 1.0, 0.5 { + icon = "plus" + fontSize = context.getHeightValue("6mm") + } + } +} + +pvar widgetControlChangeListener as function +pvar widgetRangeColor as Color +var currentLength as double +var widget as Widget + +ctor(ctx as GuiApplicationContext) +{ + base(ctx) + forceCreateWidget() +} + +func initializeWidget override +{ + base.initializeWidget() + Widget.setWidgetPointerHandlers(con, onStartHandler, onTouchHandler, onEndHandler) + Widget.setWidgetClickHandler(plusIcon, func { + onChangedControlValuehandler(currentLength+=3) + }) + Widget.setWidgetClickHandler(minusIcon, func { + onChangedControlValuehandler(currentLength-=3) + }) +} + +func isInside(x as double, y as double, w as Widget) private as bool +{ + var wx = Widget.getX(w) + var wy = Widget.getY(w) + return x >= wx && y >= wy && x <= wx + Widget.getWidth(w) && y <= wy + Widget.getHeight(w) +} + +func onStartHandler(x as double, y as double) private +{ + resetControlWidget() + if isInside(x, y, control) { + widget = control + currentLength = x + } +} + +func onTouchHandler(x as double, y as double) private +{ + var dx = Widget.getX(control) + (x - currentLength) as int + onChangedControlValuehandler(dx) +} + +func onChangedControlValuehandler(val as double) private +{ + moveControl(val) + currentLength = val + if widgetControlChangeListener: + widgetControlChangeListener(val) +} + +func onEndHandler(x as double, y as double) private: + resetControlWidget() + +func resetControlWidget: + widget = null + +func moveControl(value as double) +{ + resetControlWidget() + var x = value + Widget.move(control, x as! int, Widget.getY(control)) + updateInsideOfRangeCanvas() +} + +func updateInsideOfRangeCanvas private +{ + var x = Widget.getWidth(control) + range.setWidgetColor(widgetRangeColor) + var width = (Widget.getX(control) + Widget.getWidth(control) / 2) - x + Widget.setLayoutSize(range, width, Widget.getHeight(range)) + Widget.move(range, Widget.getX(prange), Widget.getY(range)) +} + +func setWidgetRoundingRadius(radius as int #notLiteral): + control.setWidgetRoundingRadius(radius) From 39c8f490843b02aa528b0ab1bbb7f0b2408482d0 Mon Sep 17 00:00:00 2001 From: Jonathan Liso-an Date: Wed, 2 Dec 2020 12:35:11 +0200 Subject: [PATCH 2/4] updates --- src/cave.ui/CropImageWidget.sling | 65 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/cave.ui/CropImageWidget.sling b/src/cave.ui/CropImageWidget.sling index 15164f2f..2479e557 100644 --- a/src/cave.ui/CropImageWidget.sling +++ b/src/cave.ui/CropImageWidget.sling @@ -31,7 +31,6 @@ ui LayerWidget } VerticalBoxWidget { LabelWidget title { - text = "Update Profile Picture" textAlign = LabelWidget.ALIGN_CENTER fontBold = true padding = context.getStylePixels("jkop-kit", "padding", "2mm") @@ -81,30 +80,13 @@ ui LayerWidget heightRequest = context.getStylePixels("jkop-kit", "separatorSize", "1px") color = context.getStyleColor("jkop-kit", "separatorColor", "#000000") } - HorizontalBoxWidget { - margin = context.getStylePixels("jkop-kit", "margin", "2mm") - spacing = context.getStylePixels("jkop-kit", "spacing", "2mm") - ButtonWidget : 1.0 { - text = "CANCEL" - clickHandler = func { - onCancelClicked() - } - } - ButtonWidget button : 1.0 { - text = "SAVE" - clickHandler = func { - onCropImage() - } - } + LayerWidget blayer { } - } } } } pvar image as Image -pvar doneCroppedHandler as function -pvar widgetNegativeClickHandler as function var originalHeight as int var originalWidth as int var refX as double @@ -120,8 +102,12 @@ func initializeWidget override { base.initializeWidget() img.setWidgetImage(image) - Widget.setWidgetPointerHandlers(reposition, onStartHandler, onTouchHandler, onEndHandler) - Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) + IFDEF "target_html" { + Widget.setWidgetPointerHandlers(reposition, onStartHandler, onTouchHandler, onEndHandler) + } + ELSE { + Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) + } control.setWidgetControlChangeListener(func(val as double) { if originalWidth <= 0: originalWidth = Widget.getWidth(img) @@ -133,12 +119,18 @@ func initializeWidget override }) } -func onCancelClicked +func setWidgetTitle(str as string) as this { - new PopupDialogManager(context, this).showConfirmDialog("Confirm", "Are you sure you want to discard your edits?", func { - assert widgetNegativeClickHandler - widgetNegativeClickHandler() - }, null) + assert title + title.setWidgetText(str) + return this +} + +func setWidgetButton(widget as Widget) as this +{ + assert blayer + blayer.addWidget(widget) + return this } func onStartHandler(x as double, y as double) @@ -191,9 +183,9 @@ func onTouchHandler(x as double, y as double) } func onEndHandler(x as double, y as double): - nop + ; -func onCropImage private +func doneCrop(callback as function) { var cheight = Widget.getHeight(canvas) var cwidth = Widget.getWidth(canvas) @@ -204,8 +196,8 @@ func onCropImage private var xx = Math.abs(Widget.getX(img)) + x var yy = Math.abs(Widget.getY(img)) + y newimage.crop(xx as int, yy as int, radius, radius, func(cimage as Image) { - if doneCroppedHandler: - doneCroppedHandler(cimage) + if callback: + callback(cimage) }) }) } @@ -242,15 +234,22 @@ class CropperLayerWidget is CanvasWidget is ResizeAwareWidget #widget func onWidgetResized { IFDEF "target_html" { - var cheight = Widget.getHeight(canvas) - var cwidth = Widget.getWidth(canvas) + var cheight = Widget.getHeight(this) + var cwidth = Widget.getWidth(this) var ee = this.element var parent = assert HTMLDOM.getParentElement(ee) var ecanvas = HTMLDOM.createElement("canvas") HTMLDOM.setStyle(ecanvas, "height", String.asString(cheight)) HTMLDOM.setStyle(ecanvas, "width", String.asString(cwidth)) HTMLDOM.setStyle(ecanvas, "position", "absolute") - HTMLDOM.appendChild(parent, ecanvas) + lang "js" {{{ + console.log(ee.hasChildNodes()); + var children = ee.children; + for (var i = 0; i < children.length; i++) { + ee.removeChild(children[i]); + } + }}} + HTMLDOM.appendChild(ee, ecanvas) lang "js" {{{ var ctx = ecanvas.getContext('2d'); var xc = ecanvas.width / 2; From 71bd4d8ea3a236860a28c802531d68824900651f Mon Sep 17 00:00:00 2001 From: Jonathan Liso-an Date: Tue, 8 Dec 2020 04:28:43 +0200 Subject: [PATCH 3/4] updates --- src/cave.ui/CropImageWidget.sling | 73 +++++++++++++++++-------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/src/cave.ui/CropImageWidget.sling b/src/cave.ui/CropImageWidget.sling index 2479e557..ec818e81 100644 --- a/src/cave.ui/CropImageWidget.sling +++ b/src/cave.ui/CropImageWidget.sling @@ -26,43 +26,36 @@ class #widget: ui LayerWidget { - CanvasWidget { - color = Color.instance("#373a40") - } VerticalBoxWidget { - LabelWidget title { - textAlign = LabelWidget.ALIGN_CENTER - fontBold = true - padding = context.getStylePixels("jkop-kit", "padding", "2mm") - textColor = Color.instance("#FFFFFF") - } LayerWidget layer : 1.0 { ImageWidget img { imageScaleMethod = ImageWidget.FILL } CropperLayerWidget canvas { } - AlignWidget reposition { - LayerWithBackgroundColorWidget { - color = Color.forRGBADouble(0, 0, 0, 0.5) - roundingRadius = context.getHeightValue("800um") - outlineColor = Color.white() - HorizontalBoxWidget { - spacing = context.getStylePixels("jkop-kit", "spacing", "1mm") - margin = context.getStylePixels("jkop-kit", "spacing", "1mm") - AlignWidget { - BoxIconWidget { - icon = "move" - fontSize = context.getHeightValue("3mm") - color = Color.white() + LayerWidget ll { + AlignWidget reposition { + LayerWithBackgroundColorWidget { + color = Color.forRGBADouble(0, 0, 0, 0.5) + roundingRadius = context.getHeightValue("800um") + outlineColor = Color.white() + HorizontalBoxWidget { + spacing = context.getStylePixels("jkop-kit", "spacing", "1mm") + margin = context.getStylePixels("jkop-kit", "spacing", "1mm") + AlignWidget { + BoxIconWidget { + icon = "move" + fontSize = context.getHeightValue("3mm") + color = Color.white() + } } - } - AlignWidget { - LabelWidget { - text = "Drag to Reposition" - textColor = Color.white() - fontBold = true - fontSize = context.getHeightValue("3mm") + AlignWidget { + LabelWidget { + text = "Drag to Reposition" + textColor = Color.white() + fontBold = true + fontSize = context.getHeightValue("3mm") + } } } } @@ -82,6 +75,18 @@ ui LayerWidget } LayerWidget blayer { } + } + } + } + AlignWidget { + LayerWithBackgroundColorWidget : 0.5, 0.0, true { + color = Color.instance("#373a40") + LabelWidget title { + textAlign = LabelWidget.ALIGN_CENTER + fontBold = true + padding = context.getStylePixels("jkop-kit", "padding", "2mm") + textColor = Color.instance("#FFFFFF") + } } } } @@ -102,11 +107,11 @@ func initializeWidget override { base.initializeWidget() img.setWidgetImage(image) - IFDEF "target_html" { - Widget.setWidgetPointerHandlers(reposition, onStartHandler, onTouchHandler, onEndHandler) + IFDEF "target_android" { + Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) } ELSE { - Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) + Widget.setWidgetPointerHandlers(ll, onStartHandler, onTouchHandler, onEndHandler) } control.setWidgetControlChangeListener(func(val as double) { if originalWidth <= 0: @@ -151,7 +156,7 @@ func onTouchHandler(x as double, y as double) ix = 0 endRight = true } - var maxX = Widget.getWidth(img) - Widget.getWidth(canvas) + var maxX = Widget.getWidth(img) - Widget.getWidth(layer) if refX > x && Math.abs(ix) >= maxX { ix = -maxX endLeft = true @@ -160,7 +165,7 @@ func onTouchHandler(x as double, y as double) iy = 0 endDown = true } - var maxY = Widget.getHeight(img) - Widget.getHeight(canvas) + var maxY = Widget.getHeight(img) - Widget.getHeight(layer) if refY > y && Math.abs(iy) >= maxY { iy = -maxY endUp = true From e531840680e622f833cc4c4b2801d85477aac63d Mon Sep 17 00:00:00 2001 From: Jonathan Liso-an Date: Tue, 9 Mar 2021 08:41:15 +0200 Subject: [PATCH 4/4] updates --- src/cave.ui/CropImageWidget.sling | 70 ++++++++++++------------------- src/cave.ui/CropRangeWidget.sling | 9 +++- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/cave.ui/CropImageWidget.sling b/src/cave.ui/CropImageWidget.sling index ec818e81..4412ba3c 100644 --- a/src/cave.ui/CropImageWidget.sling +++ b/src/cave.ui/CropImageWidget.sling @@ -92,10 +92,13 @@ ui LayerWidget } pvar image as Image +pvar moveSpeed as int var originalHeight as int var originalWidth as int var refX as double var refY as double +var afterX as double +var afterY as double ctor(ctx as GuiApplicationContext) { @@ -107,12 +110,9 @@ func initializeWidget override { base.initializeWidget() img.setWidgetImage(image) - IFDEF "target_android" { - Widget.setWidgetPointerHandlers(img, onStartHandler, onTouchHandler, onEndHandler) - } - ELSE { - Widget.setWidgetPointerHandlers(ll, onStartHandler, onTouchHandler, onEndHandler) - } + if moveSpeed <= 0: + moveSpeed = 3 + Widget.setWidgetPointerHandlers(ll, onStartHandler, onTouchHandler, onEndHandler) control.setWidgetControlChangeListener(func(val as double) { if originalWidth <= 0: originalWidth = Widget.getWidth(img) @@ -146,45 +146,29 @@ func onStartHandler(x as double, y as double) func onTouchHandler(x as double, y as double) { - var iy = Widget.getY(img) - var ix = Widget.getX(img) - var endRight as bool - var endLeft as bool - var endDown as bool - var endUp as bool - if refX < x && ix >= 0 { - ix = 0 - endRight = true - } + var iy2 = Widget.getY(img) + var ix2 = Widget.getX(img) + if refX > x && afterX > x: + ix2 = ix2 - moveSpeed + if refX < x && afterX < x: + ix2 = ix2 + moveSpeed + if refY > y && afterY > y: + iy2 = iy2 - moveSpeed + if refY < y && afterY < y: + iy2 = iy2 + moveSpeed + if refX < x && ix2 >= 0: + ix2 = 0 var maxX = Widget.getWidth(img) - Widget.getWidth(layer) - if refX > x && Math.abs(ix) >= maxX { - ix = -maxX - endLeft = true - } - if refY < y && iy >= 0 { - iy = 0 - endDown = true - } + if refX > x && Math.abs(ix2) >= maxX: + ix2 = -maxX + if refY < y && iy2 >= 0: + iy2 = 0 var maxY = Widget.getHeight(img) - Widget.getHeight(layer) - if refY > y && Math.abs(iy) >= maxY { - iy = -maxY - endUp = true - } - var mx as int - var my as int - if not endRight && not endLeft { - mx = ix + (x - refX) as int - } - else if endLeft { - mx = -maxX - } - if not endUp && not endDown { - my = iy + (y - refY) as int - } - else if endUp { - my = -maxY - } - Widget.move(img, mx, my) + if refY > y && Math.abs(iy2) >= maxY: + iy2 = -maxY + Widget.move(img, ix2, iy2) + afterX = x + afterY = y } func onEndHandler(x as double, y as double): diff --git a/src/cave.ui/CropRangeWidget.sling b/src/cave.ui/CropRangeWidget.sling index 7112f686..650b96c4 100644 --- a/src/cave.ui/CropRangeWidget.sling +++ b/src/cave.ui/CropRangeWidget.sling @@ -128,6 +128,12 @@ func onStartHandler(x as double, y as double) private func onTouchHandler(x as double, y as double) private { + var rightX = Widget.getWidth(prange) as! double + var leftX = Widget.getX(prange) as! double + if x > rightX: + x = rightX + if x < leftX: + x = leftX var dx = Widget.getX(control) + (x - currentLength) as int onChangedControlValuehandler(dx) } @@ -149,8 +155,7 @@ func resetControlWidget: func moveControl(value as double) { resetControlWidget() - var x = value - Widget.move(control, x as! int, Widget.getY(control)) + Widget.move(control, value as! int, Widget.getY(control)) updateInsideOfRangeCanvas() }