diff --git a/.idea/artifacts/k2js_jar.xml b/.idea/artifacts/k2js_jar.xml index eb3b4c0e9ab..a4f2e6c0057 100644 --- a/.idea/artifacts/k2js_jar.xml +++ b/.idea/artifacts/k2js_jar.xml @@ -6,14 +6,11 @@ - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index d9a95e51532..07c88da7dbd 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -5,6 +5,7 @@ + diff --git a/examplesForWebDemo/src/html5/demo/demo.html b/examplesForWebDemo/src/html5/demo/demo.html new file mode 100644 index 00000000000..2f0dcf75fb5 --- /dev/null +++ b/examplesForWebDemo/src/html5/demo/demo.html @@ -0,0 +1,44 @@ + + + + + + \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/demo/demo_template.html b/examplesForWebDemo/src/html5/demo/demo_template.html new file mode 100644 index 00000000000..cd8c8e5d6d3 --- /dev/null +++ b/examplesForWebDemo/src/html5/demo/demo_template.html @@ -0,0 +1,51 @@ + + + + Canvas demo + + + + + + + + \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/demo/template.html b/examplesForWebDemo/src/html5/demo/template.html new file mode 100644 index 00000000000..861e4d81eec --- /dev/null +++ b/examplesForWebDemo/src/html5/demo/template.html @@ -0,0 +1,13 @@ + + + + Canvas demo + + + + + + + + \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/interactive2/interactive2.js b/examplesForWebDemo/src/html5/interactive2/interactive2.js new file mode 100644 index 00000000000..442796dfb27 --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive2/interactive2.js @@ -0,0 +1,459 @@ +{ + var classes = function () { + var Vector = Kotlin.Class.create({initialize:function (x, y) { + this.$x = x; + this.$y = y; + }, get_x:function () { + return this.$x; + }, get_y:function () { + return this.$y; + }, plus:function (v) { + { + return interactive2.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y()); + } + }, minus:function () { + { + return interactive2.v_0(-this.get_x(), -this.get_y()); + } + }, minus$0:function (v) { + { + return interactive2.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y()); + } + }, times:function (coef) { + { + return interactive2.v_0(this.get_x() * coef, this.get_y() * coef); + } + }, distanceTo:function (v) { + { + return Math.sqrt(this.minus$0(v).get_sqr()); + } + }, rotatedBy:function (theta) { + { + var sin = Math.sin(theta); + var cos = Math.cos(theta); + return interactive2.v_0(this.get_x() * cos - this.get_y() * sin, this.get_x() * sin + this.get_y() * cos); + } + }, isInRect:function (topLeft, size) { + { + return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y(); + } + }, get_sqr:function () { + { + return this.get_x() * this.get_x() + this.get_y() * this.get_y(); + } + }, get_normalized:function () { + { + return this.times(1 / Math.sqrt(this.get_sqr())); + } + } + }); + var RadialGradientGenerator = Kotlin.Class.create({initialize:function (context) { + this.$context = context; + this.$gradients = new Kotlin.ArrayList; + this.$current = 0; + { + this.newColorStops([ + [0, '#F59898'], + [0.5, '#F57373'], + [1, '#DB6B6B'] + ]); + this.newColorStops([ + [0.39, 'rgb(140,167,209)'], + [0.7, 'rgb(104,139,209)'], + [0.85, 'rgb(67,122,217)'] + ]); + this.newColorStops([ + [0, 'rgb(255,222,255)'], + [0.5, 'rgb(255,185,222)'], + [1, 'rgb(230,154,185)'] + ]); + this.newColorStops([ + [0, 'rgb(255,209,114)'], + [0.5, 'rgb(255,174,81)'], + [1, 'rgb(241,145,54)'] + ]); + this.newColorStops([ + [0, 'rgb(132,240,135)'], + [0.5, 'rgb(91,240,96)'], + [1, 'rgb(27,245,41)'] + ]); + this.newColorStops([ + [0, 'rgb(250,147,250)'], + [0.5, 'rgb(255,80,255)'], + [1, 'rgb(250,0,217)'] + ]); + } + }, get_context:function () { + return this.$context; + }, get_gradients:function () { + return this.$gradients; + }, get_current:function () { + return this.$current; + }, set_current:function (tmp$0) { + this.$current = tmp$0; + }, newColorStops:function (colorStops) { + { + this.get_gradients().add(colorStops); + } + }, getNext:function () { + { + var result = this.get_gradients().get(this.get_current()); + this.set_current((this.get_current() + 1) % this.get_gradients().size()); + return result; + } + } + }); + var CanvasState = Kotlin.Class.create({initialize:function (canvas) { + this.$canvas = canvas; + this.$width = this.get_canvas().width; + this.$height = this.get_canvas().height; + this.$context = getContext(); + this.$valid = false; + this.$shapes = new Kotlin.ArrayList; + this.$selection = null; + this.$dragOff = new interactive2.Vector_0(0, 0); + this.$interval = 1000 / 30; + { + var tmp$4; + var tmp$3; + var tmp$2; + var tmp$1; + var tmp$0_0; + $(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) { + { + var tmp$0; + tmp$0_0.set_valid(false); + tmp$0_0.set_selection(null); + var mousePos = tmp$0_0.mousePos_0(it); + { + tmp$0 = tmp$0_0.get_shapes().iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + if (shape.contains(mousePos)) { + tmp$0_0.set_dragOff(mousePos.minus$0(shape.get_pos())); + shape.set_selected(true); + tmp$0_0.set_selection(shape); + break; + } + } + } + } + } + } + )); + $(this.get_canvas()).mousemove((tmp$1 = this , function (it) { + { + if (tmp$1.get_selection() != null) { + Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus$0(tmp$1.get_dragOff())); + tmp$1.set_valid(false); + } + } + } + )); + $(this.get_canvas()).mouseup((tmp$2 = this , function (it) { + { + if (tmp$2.get_selection() != null) { + Kotlin.sure(tmp$2.get_selection()).set_selected(false); + } + tmp$2.set_selection(null); + tmp$2.set_valid(false); + } + } + )); + $(this.get_canvas()).dblclick((tmp$3 = this , function (it) { + { + var redTransparentCircle = new interactive2.Creature_0(tmp$3.mousePos_0(it), tmp$3); + tmp$3.addShape(redTransparentCircle); + tmp$3.set_valid(false); + } + } + )); + interactive2.doWithPeriod(this.get_interval(), (tmp$4 = this , function () { + { + tmp$4.draw(); + } + } + )); + } + }, get_canvas:function () { + return this.$canvas; + }, get_width:function () { + return this.$width; + }, get_height:function () { + return this.$height; + }, get_context:function () { + return this.$context; + }, get_valid:function () { + return this.$valid; + }, set_valid:function (tmp$0) { + this.$valid = tmp$0; + }, get_shapes:function () { + return this.$shapes; + }, set_shapes:function (tmp$0) { + this.$shapes = tmp$0; + }, get_selection:function () { + return this.$selection; + }, set_selection:function (tmp$0) { + this.$selection = tmp$0; + }, get_dragOff:function () { + return this.$dragOff; + }, set_dragOff:function (tmp$0) { + this.$dragOff = tmp$0; + }, get_interval:function () { + return this.$interval; + }, mousePos_0:function (e) { + { + var offset = new interactive2.Vector_0(0, 0); + var element = this.get_canvas(); + while (element != null) { + var el = Kotlin.sure(element); + offset = offset.plus(new interactive2.Vector_0(el.offsetLeft, el.offsetTop)); + element = el.offsetParent; + } + return (new interactive2.Vector_0(e.pageX, e.pageY)).minus$0(offset); + } + }, addShape:function (shape) { + { + this.get_shapes().add(shape); + this.set_valid(false); + } + }, clear:function () { + { + this.get_context().fillStyle = '#FFFFFF'; + this.get_context().fillRect(0, 0, this.get_width(), this.get_height()); + this.get_context().strokeStyle = '#000000'; + this.get_context().lineWidth = 4; + this.get_context().strokeRect(0, 0, this.get_width(), this.get_height()); + } + }, draw:function () { + { + var tmp$0; + if (this.get_valid()) + return; + this.clear(); + { + tmp$0 = this.get_shapes().iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + shape.draw(this); + } + } + } + this.set_valid(true); + } + } + }); + var Shape = Kotlin.Class.create({initialize:function () { + this.$selected = false; + }, draw:function (state) { + }, contains:function (mousePos) { + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_selected:function () { + return this.$selected; + }, set_selected:function (tmp$0) { + this.$selected = tmp$0; + } + }); + var Creature = Kotlin.Class.create(Shape, {initialize:function (pos, state) { + this.$pos = pos; + this.$state = state; + this.super_init(); + this.$shadowOffset = interactive2.v_0(-5, 5); + this.$colorStops = interactive2.get_gradientGenerator().getNext(); + this.$relSize = 0.05; + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_state:function () { + return this.$state; + }, set_state:function (tmp$0) { + this.$state = tmp$0; + }, get_shadowOffset:function () { + return this.$shadowOffset; + }, get_colorStops:function () { + return this.$colorStops; + }, get_relSize:function () { + return this.$relSize; + }, get_radius:function () { + { + return this.get_state().get_width() * this.get_relSize(); + } + }, get_position:function () { + var tmp$0; + if (this.get_selected()) + tmp$0 = this.get_pos().minus$0(this.get_shadowOffset()); + else + tmp$0 = this.get_pos(); + { + return tmp$0; + } + }, get_directionToLogo:function () { + { + return interactive2.get_JB().get_centre().minus$0(this.get_position()).get_normalized(); + } + }, contains:function (mousePos) { + { + return this.get_pos().distanceTo(mousePos) < this.get_radius(); + } + }, fillCircle:function (receiver, position, rad) { + { + receiver.beginPath(); + receiver.arc(position.get_x(), position.get_y(), rad, 0, 2 * Math.PI, false); + receiver.closePath(); + receiver.fill(); + } + }, draw:function (state) { + { + var context = state.get_context(); + if (!this.get_selected()) { + this.drawCreature(context); + } + else { + this.drawCreatureWithShadow(context); + } + } + }, drawCreature:function (context) { + { + context.fillStyle = this.getGradient(context); + this.fillCircle(context, this.get_position(), this.get_radius()); + this.drawEye(context); + this.drawTail(context); + } + }, getGradient:function (context) { + { + var tmp$0; + var gradientCentre = this.get_position().plus(this.get_directionToLogo().times(this.get_radius() / 4)); + var gradient = context.createRadialGradient(gradientCentre.get_x(), gradientCentre.get_y(), 1, gradientCentre.get_x(), gradientCentre.get_y(), 2 * this.get_radius()); + { + tmp$0 = Kotlin.arrayIterator(this.get_colorStops()); + while (tmp$0.hasNext()) { + var colorStop = tmp$0.next(); + { + gradient.addColorStop(colorStop[0], colorStop[1]); + } + } + } + return gradient; + } + }, drawTail:function (context) { + { + var tailDirection = this.get_directionToLogo().minus(); + var tailPos = this.get_position().plus(tailDirection.times(this.get_radius()).times(0.7)); + var tailSize = this.get_radius() * 1.6; + var angle = Math.PI / 6; + var p1 = tailPos.plus(tailDirection.rotatedBy(angle).times(tailSize)); + var p2 = tailPos.plus(tailDirection.rotatedBy(-angle).times(tailSize)); + context.fillStyle = this.getGradient(context); + context.beginPath(); + context.moveTo(tailPos.get_x(), tailPos.get_y()); + context.lineTo(p1.get_x(), p1.get_y()); + var middlePoint = this.get_position().plus(tailDirection.times(this.get_radius()).times(1)); + context.quadraticCurveTo(middlePoint.get_x(), middlePoint.get_y(), p2.get_x(), p2.get_y()); + context.lineTo(tailPos.get_x(), tailPos.get_y()); + context.closePath(); + context.fill(); + } + }, drawEye:function (context) { + { + var eyePos = this.get_directionToLogo().times(this.get_radius()).times(0.6).plus(this.get_position()); + var eyeRadius = this.get_radius() / 3; + var eyeLidRadius = eyeRadius / 2; + context.fillStyle = '#FFFFFF'; + this.fillCircle(context, eyePos, eyeRadius); + context.fillStyle = '#000000'; + this.fillCircle(context, eyePos, eyeLidRadius); + } + }, drawCreatureWithShadow:function (context) { + { + context.save(); + this.setShadow(context); + context.fillStyle = this.getGradient(context); + this.fillCircle(context, this.get_position(), this.get_radius()); + context.restore(); + this.drawEye(context); + this.drawTail(context); + } + }, setShadow:function (context) { + { + context.shadowColor = 'rgba(100, 100, 100, 0.7)'; + context.shadowBlur = 5; + context.shadowOffsetX = this.get_shadowOffset().get_x(); + context.shadowOffsetY = this.get_shadowOffset().get_y(); + } + } + }); + var Logo = Kotlin.Class.create(Shape, {initialize:function (pos, relSize) { + this.$pos = pos; + this.$relSize = relSize; + this.super_init(); + this.$imageSize = interactive2.v_0(704, 254); + this.$canvasSize = this.get_imageSize().times(this.get_relSize()); + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_relSize:function () { + return this.$relSize; + }, set_relSize:function (tmp$0) { + this.$relSize = tmp$0; + }, get_imageSize:function () { + return this.$imageSize; + }, get_canvasSize:function () { + return this.$canvasSize; + }, draw:function (state) { + { + var context = state.get_context(); + context.drawImage(getJBLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_pos().get_x(), this.get_pos().get_y(), this.get_canvasSize().get_x(), this.get_canvasSize().get_y()); + } + }, contains:function (mousePos) { + { + return mousePos.isInRect(this.get_pos(), this.get_canvasSize()); + } + }, get_centre:function () { + { + return this.get_pos().plus(this.get_canvasSize().times(0.5)); + } + } + }); + return {Shape_0:Shape, Logo_0:Logo, Creature_0:Creature, RadialGradientGenerator_0:RadialGradientGenerator, CanvasState_0:CanvasState, Vector_0:Vector}; + } + (); + var interactive2 = Kotlin.Namespace.create({initialize:function () { + interactive2.$gradientGenerator = new interactive2.RadialGradientGenerator_0(getContext()); + interactive2.$JB = new interactive2.Logo_0(interactive2.v_0(20, 20), 0.3); + }, get_gradientGenerator:function () { + return interactive2.$gradientGenerator; + }, get_JB:function () { + return interactive2.$JB; + }, doWithPeriod:function (period, f) { + { + setInterval(f, period); + } + }, v_0:function (x, y) { + { + return new interactive2.Vector_0(x, y); + } + }, main:function () { + { + var state = new interactive2.CanvasState_0(getCanvas()); + state.addShape(interactive2.get_JB()); + setTimeout(function () { + { + state.set_valid(false); + } + } + ); + } + } + }, classes); + interactive2.initialize(); +} + +var args = []; +interactive2.main(args); diff --git a/examplesForWebDemo/src/html5/interactive2/jbLogo.png b/examplesForWebDemo/src/html5/interactive2/jbLogo.png new file mode 100644 index 00000000000..759aa8ae05a Binary files /dev/null and b/examplesForWebDemo/src/html5/interactive2/jbLogo.png differ diff --git a/examplesForWebDemo/src/html5/interactive2/main.kt b/examplesForWebDemo/src/html5/interactive2/main.kt new file mode 100644 index 00000000000..4f21e9eb66b --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive2/main.kt @@ -0,0 +1,280 @@ +package interactive2; + +import jquery.*; +import html5.*; +import java.util.ArrayList; +import js.*; +import js.Math; +import js.setInterval +import html5.getCanvas +import html5.getJBLogo +import jquery.jq +import js.setTimeout + +val gradientGenerator = RadialGradientGenerator(getContext()) +val JB = Logo(v(20.0, 20.0)) + +fun doWithPeriod(period : Int, f : ()->Unit) { + setInterval(f, period); +} + +abstract class Shape() { + abstract fun draw(state : CanvasState); + abstract fun contains(mousePos : Vector) : Boolean; + abstract var pos : Vector; + var selected : Boolean = false; +} + +class Logo(override var pos : Vector, + var relSize : Double = 0.3) + : Shape() +{ + val imageSize = v(704.0, 254.0) + val canvasSize = imageSize * relSize + + override fun draw(state : CanvasState) { + val context = state.context; + context.drawImage(getJBLogo(), 0.0, 0.0, imageSize.x, imageSize.y, pos.x, pos.y, canvasSize.x, canvasSize.y) + } + + override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, canvasSize) + + val centre : Vector + get() = pos + canvasSize * 0.5 +} + +class Creature(override var pos : Vector, + var state : CanvasState) : Shape() { + + val shadowOffset = v(-5.0, 5.0) + val colorStops = gradientGenerator.getNext() + val relSize = 0.05; + val radius : Double + get() = state.width * relSize; + + val position : Vector + get() = if (selected) pos - shadowOffset else pos + + val directionToLogo : Vector + get() = (JB.centre - position).normalized + + override fun contains(mousePos : Vector) = pos.distanceTo(mousePos) < radius; + + fun Context.fillCircle(position : Vector, rad : Double) { + beginPath(); + arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false); + closePath(); + fill() + } + + override fun draw(state : CanvasState) { + val context = state.context; + if (!selected) { + drawCreature(context) + } else { + drawCreatureWithShadow(context) + } + } + + fun drawCreature(context : Context) { + context.fillStyle = getGradient(context); + context.fillCircle(position, radius) + drawEye(context) + drawTail(context) + } + + fun getGradient(context : Context) : CanvasGradient { + val gradientCentre = position + directionToLogo * (radius / 4) + val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius) + for (colorStop in colorStops) { + gradient.addColorStop(colorStop._1, colorStop._2) + } + return gradient; + } + + fun drawTail(context : Context) { + val tailDirection = -directionToLogo; + val tailPos = position + tailDirection * radius * 0.7 + val tailSize = radius * 1.6 + val angle = Math.PI / 6.0; + val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize + val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize + context.fillStyle = getGradient(context) + context.beginPath() + context.moveTo(tailPos.x, tailPos.y) + context.lineTo(p1.x, p1.y) + val middlePoint = position + tailDirection * radius * 1.0 + context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y) + context.lineTo(tailPos.x, tailPos.y) + context.closePath() + context.fill() + } + + fun drawEye(context : Context) {; + val eyePos = directionToLogo * radius * 0.6 + position; + val eyeRadius = radius / 3; + val eyeLidRadius = eyeRadius / 2; + context.fillStyle = "#FFFFFF"; + context.fillCircle(eyePos, eyeRadius) + context.fillStyle = "#000000" + context.fillCircle(eyePos, eyeLidRadius) + } + + fun drawCreatureWithShadow(context : Context) { + context.save() + setShadow(context) + context.fillStyle = getGradient(context) + context.fillCircle(position, radius) + context.restore(); + drawEye(context) + drawTail(context) + } + + fun setShadow(context : Context) { + context.shadowColor = "rgba(100, 100, 100, 0.7)"; + context.shadowBlur = 5.0; + context.shadowOffsetX = shadowOffset.x; + context.shadowOffsetY = shadowOffset.y; + } +} + +class CanvasState(val canvas : Canvas) { + val width = canvas.width; + val height = canvas.height; + val context = getContext(); + var valid = false; + var shapes = ArrayList(); + var selection : Shape? = null; + var dragOff = Vector(); + val interval = 1000 / 30; + + { + jq(canvas).mousedown { + valid = false; + selection = null; + val mousePos = mousePos(it); + for (shape in shapes) { + if (mousePos in shape) { + dragOff = mousePos - shape.pos; + shape.selected = true; + selection = shape; + break; + } + } + } + + jq(canvas).mousemove { + if (selection != null) { + selection.sure().pos = mousePos(it) - dragOff; + valid = false; + } + } + + jq(canvas).mouseup { + if (selection != null) { + selection.sure().selected = false; + } + selection = null; + valid = false; + } + + jq(canvas).dblclick { + val redTransparentCircle = Creature(mousePos(it), this @CanvasState); + addShape(redTransparentCircle); + valid = false; + } + + doWithPeriod(interval) { + draw(); + } + } + + fun mousePos(e : MouseEvent) : Vector { + var offset = Vector(); + var element : DomElement? = canvas; + while (element != null) { + val el : DomElement = element.sure(); + offset += Vector(el.offsetLeft, el.offsetTop); + element = el.offsetParent; + } + return Vector(e.pageX, e.pageY) - offset; + } + + fun addShape(shape : Shape) { + shapes.add(shape); + valid = false; + } + + fun clear() { + context.fillStyle = "#FFFFFF" + context.fillRect(0.0, 0.0, width, height) + context.strokeStyle = "#000000" + context.lineWidth = 4.0; + context.strokeRect(0.0, 0.0, width, height) + } + + fun draw() { + if (valid) return + + clear(); + for (shape in shapes) { + shape.draw(this); + } + valid = true; + } +} + +class RadialGradientGenerator(val context : Context) { + val gradients = ArrayList>(); + var current = 0 + + fun newColorStops(vararg colorStops : #(Double, String)) { + gradients.add(colorStops) + } + + { + newColorStops(#(0.0, "#F59898"), #(0.5, "#F57373"), #(1.0, "#DB6B6B")) + newColorStops(#(0.39, "rgb(140,167,209)"), #(0.7, "rgb(104,139,209)"), #(0.85, "rgb(67,122,217)")) + newColorStops(#(0.0, "rgb(255,222,255)"), #(0.5, "rgb(255,185,222)"), #(1.0, "rgb(230,154,185)")) + newColorStops(#(0.0, "rgb(255,209,114)"), #(0.5, "rgb(255,174,81)"), #(1.0, "rgb(241,145,54)")) + newColorStops(#(0.0, "rgb(132,240,135)"), #(0.5, "rgb(91,240,96)"), #(1.0, "rgb(27,245,41)")) + newColorStops(#(0.0, "rgb(250,147,250)"), #(0.5, "rgb(255,80,255)"), #(1.0, "rgb(250,0,217)")) +} + + fun getNext() : Array<#(Double, String)> { + val result = gradients.get(current) + current = (current + 1) % gradients.size() + return result + } +} + +fun v(x : Double, y : Double) = Vector(x, y); + +class Vector(val x : Double = 0.0, val y : Double = 0.0) { + fun plus(v : Vector) = v(x + v.x, y + v.y); + fun minus() = v(-x, -y) + fun minus(v : Vector) = v(x - v.x, y - v.y) + fun times(coef : Double) = v(x * coef, y * coef) + fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr) + fun rotatedBy(theta : Double) : Vector { + val sin = Math.sin(theta) + val cos = Math.cos(theta) + return v(x * cos - y * sin, x * sin + y * cos) + } + + fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) && + (y >= topLeft.y) && (y <= topLeft.y + size.y) + + val sqr : Double + get() = x * x + y * y + val normalized : Vector + get() = this * (1.0 / Math.sqrt(sqr)) +} + +fun main() { + val state = CanvasState(getCanvas()); + state.addShape(JB); + setTimeout({ + state.valid = false + }) +} \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/interactive2/template.html b/examplesForWebDemo/src/html5/interactive2/template.html new file mode 100644 index 00000000000..c1619f21c8a --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive2/template.html @@ -0,0 +1,15 @@ + + + + Canvas demo + + + + + + + + + + \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/interactive3/interactive2.js b/examplesForWebDemo/src/html5/interactive3/interactive2.js new file mode 100644 index 00000000000..442796dfb27 --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive3/interactive2.js @@ -0,0 +1,459 @@ +{ + var classes = function () { + var Vector = Kotlin.Class.create({initialize:function (x, y) { + this.$x = x; + this.$y = y; + }, get_x:function () { + return this.$x; + }, get_y:function () { + return this.$y; + }, plus:function (v) { + { + return interactive2.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y()); + } + }, minus:function () { + { + return interactive2.v_0(-this.get_x(), -this.get_y()); + } + }, minus$0:function (v) { + { + return interactive2.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y()); + } + }, times:function (coef) { + { + return interactive2.v_0(this.get_x() * coef, this.get_y() * coef); + } + }, distanceTo:function (v) { + { + return Math.sqrt(this.minus$0(v).get_sqr()); + } + }, rotatedBy:function (theta) { + { + var sin = Math.sin(theta); + var cos = Math.cos(theta); + return interactive2.v_0(this.get_x() * cos - this.get_y() * sin, this.get_x() * sin + this.get_y() * cos); + } + }, isInRect:function (topLeft, size) { + { + return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y(); + } + }, get_sqr:function () { + { + return this.get_x() * this.get_x() + this.get_y() * this.get_y(); + } + }, get_normalized:function () { + { + return this.times(1 / Math.sqrt(this.get_sqr())); + } + } + }); + var RadialGradientGenerator = Kotlin.Class.create({initialize:function (context) { + this.$context = context; + this.$gradients = new Kotlin.ArrayList; + this.$current = 0; + { + this.newColorStops([ + [0, '#F59898'], + [0.5, '#F57373'], + [1, '#DB6B6B'] + ]); + this.newColorStops([ + [0.39, 'rgb(140,167,209)'], + [0.7, 'rgb(104,139,209)'], + [0.85, 'rgb(67,122,217)'] + ]); + this.newColorStops([ + [0, 'rgb(255,222,255)'], + [0.5, 'rgb(255,185,222)'], + [1, 'rgb(230,154,185)'] + ]); + this.newColorStops([ + [0, 'rgb(255,209,114)'], + [0.5, 'rgb(255,174,81)'], + [1, 'rgb(241,145,54)'] + ]); + this.newColorStops([ + [0, 'rgb(132,240,135)'], + [0.5, 'rgb(91,240,96)'], + [1, 'rgb(27,245,41)'] + ]); + this.newColorStops([ + [0, 'rgb(250,147,250)'], + [0.5, 'rgb(255,80,255)'], + [1, 'rgb(250,0,217)'] + ]); + } + }, get_context:function () { + return this.$context; + }, get_gradients:function () { + return this.$gradients; + }, get_current:function () { + return this.$current; + }, set_current:function (tmp$0) { + this.$current = tmp$0; + }, newColorStops:function (colorStops) { + { + this.get_gradients().add(colorStops); + } + }, getNext:function () { + { + var result = this.get_gradients().get(this.get_current()); + this.set_current((this.get_current() + 1) % this.get_gradients().size()); + return result; + } + } + }); + var CanvasState = Kotlin.Class.create({initialize:function (canvas) { + this.$canvas = canvas; + this.$width = this.get_canvas().width; + this.$height = this.get_canvas().height; + this.$context = getContext(); + this.$valid = false; + this.$shapes = new Kotlin.ArrayList; + this.$selection = null; + this.$dragOff = new interactive2.Vector_0(0, 0); + this.$interval = 1000 / 30; + { + var tmp$4; + var tmp$3; + var tmp$2; + var tmp$1; + var tmp$0_0; + $(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) { + { + var tmp$0; + tmp$0_0.set_valid(false); + tmp$0_0.set_selection(null); + var mousePos = tmp$0_0.mousePos_0(it); + { + tmp$0 = tmp$0_0.get_shapes().iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + if (shape.contains(mousePos)) { + tmp$0_0.set_dragOff(mousePos.minus$0(shape.get_pos())); + shape.set_selected(true); + tmp$0_0.set_selection(shape); + break; + } + } + } + } + } + } + )); + $(this.get_canvas()).mousemove((tmp$1 = this , function (it) { + { + if (tmp$1.get_selection() != null) { + Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus$0(tmp$1.get_dragOff())); + tmp$1.set_valid(false); + } + } + } + )); + $(this.get_canvas()).mouseup((tmp$2 = this , function (it) { + { + if (tmp$2.get_selection() != null) { + Kotlin.sure(tmp$2.get_selection()).set_selected(false); + } + tmp$2.set_selection(null); + tmp$2.set_valid(false); + } + } + )); + $(this.get_canvas()).dblclick((tmp$3 = this , function (it) { + { + var redTransparentCircle = new interactive2.Creature_0(tmp$3.mousePos_0(it), tmp$3); + tmp$3.addShape(redTransparentCircle); + tmp$3.set_valid(false); + } + } + )); + interactive2.doWithPeriod(this.get_interval(), (tmp$4 = this , function () { + { + tmp$4.draw(); + } + } + )); + } + }, get_canvas:function () { + return this.$canvas; + }, get_width:function () { + return this.$width; + }, get_height:function () { + return this.$height; + }, get_context:function () { + return this.$context; + }, get_valid:function () { + return this.$valid; + }, set_valid:function (tmp$0) { + this.$valid = tmp$0; + }, get_shapes:function () { + return this.$shapes; + }, set_shapes:function (tmp$0) { + this.$shapes = tmp$0; + }, get_selection:function () { + return this.$selection; + }, set_selection:function (tmp$0) { + this.$selection = tmp$0; + }, get_dragOff:function () { + return this.$dragOff; + }, set_dragOff:function (tmp$0) { + this.$dragOff = tmp$0; + }, get_interval:function () { + return this.$interval; + }, mousePos_0:function (e) { + { + var offset = new interactive2.Vector_0(0, 0); + var element = this.get_canvas(); + while (element != null) { + var el = Kotlin.sure(element); + offset = offset.plus(new interactive2.Vector_0(el.offsetLeft, el.offsetTop)); + element = el.offsetParent; + } + return (new interactive2.Vector_0(e.pageX, e.pageY)).minus$0(offset); + } + }, addShape:function (shape) { + { + this.get_shapes().add(shape); + this.set_valid(false); + } + }, clear:function () { + { + this.get_context().fillStyle = '#FFFFFF'; + this.get_context().fillRect(0, 0, this.get_width(), this.get_height()); + this.get_context().strokeStyle = '#000000'; + this.get_context().lineWidth = 4; + this.get_context().strokeRect(0, 0, this.get_width(), this.get_height()); + } + }, draw:function () { + { + var tmp$0; + if (this.get_valid()) + return; + this.clear(); + { + tmp$0 = this.get_shapes().iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + shape.draw(this); + } + } + } + this.set_valid(true); + } + } + }); + var Shape = Kotlin.Class.create({initialize:function () { + this.$selected = false; + }, draw:function (state) { + }, contains:function (mousePos) { + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_selected:function () { + return this.$selected; + }, set_selected:function (tmp$0) { + this.$selected = tmp$0; + } + }); + var Creature = Kotlin.Class.create(Shape, {initialize:function (pos, state) { + this.$pos = pos; + this.$state = state; + this.super_init(); + this.$shadowOffset = interactive2.v_0(-5, 5); + this.$colorStops = interactive2.get_gradientGenerator().getNext(); + this.$relSize = 0.05; + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_state:function () { + return this.$state; + }, set_state:function (tmp$0) { + this.$state = tmp$0; + }, get_shadowOffset:function () { + return this.$shadowOffset; + }, get_colorStops:function () { + return this.$colorStops; + }, get_relSize:function () { + return this.$relSize; + }, get_radius:function () { + { + return this.get_state().get_width() * this.get_relSize(); + } + }, get_position:function () { + var tmp$0; + if (this.get_selected()) + tmp$0 = this.get_pos().minus$0(this.get_shadowOffset()); + else + tmp$0 = this.get_pos(); + { + return tmp$0; + } + }, get_directionToLogo:function () { + { + return interactive2.get_JB().get_centre().minus$0(this.get_position()).get_normalized(); + } + }, contains:function (mousePos) { + { + return this.get_pos().distanceTo(mousePos) < this.get_radius(); + } + }, fillCircle:function (receiver, position, rad) { + { + receiver.beginPath(); + receiver.arc(position.get_x(), position.get_y(), rad, 0, 2 * Math.PI, false); + receiver.closePath(); + receiver.fill(); + } + }, draw:function (state) { + { + var context = state.get_context(); + if (!this.get_selected()) { + this.drawCreature(context); + } + else { + this.drawCreatureWithShadow(context); + } + } + }, drawCreature:function (context) { + { + context.fillStyle = this.getGradient(context); + this.fillCircle(context, this.get_position(), this.get_radius()); + this.drawEye(context); + this.drawTail(context); + } + }, getGradient:function (context) { + { + var tmp$0; + var gradientCentre = this.get_position().plus(this.get_directionToLogo().times(this.get_radius() / 4)); + var gradient = context.createRadialGradient(gradientCentre.get_x(), gradientCentre.get_y(), 1, gradientCentre.get_x(), gradientCentre.get_y(), 2 * this.get_radius()); + { + tmp$0 = Kotlin.arrayIterator(this.get_colorStops()); + while (tmp$0.hasNext()) { + var colorStop = tmp$0.next(); + { + gradient.addColorStop(colorStop[0], colorStop[1]); + } + } + } + return gradient; + } + }, drawTail:function (context) { + { + var tailDirection = this.get_directionToLogo().minus(); + var tailPos = this.get_position().plus(tailDirection.times(this.get_radius()).times(0.7)); + var tailSize = this.get_radius() * 1.6; + var angle = Math.PI / 6; + var p1 = tailPos.plus(tailDirection.rotatedBy(angle).times(tailSize)); + var p2 = tailPos.plus(tailDirection.rotatedBy(-angle).times(tailSize)); + context.fillStyle = this.getGradient(context); + context.beginPath(); + context.moveTo(tailPos.get_x(), tailPos.get_y()); + context.lineTo(p1.get_x(), p1.get_y()); + var middlePoint = this.get_position().plus(tailDirection.times(this.get_radius()).times(1)); + context.quadraticCurveTo(middlePoint.get_x(), middlePoint.get_y(), p2.get_x(), p2.get_y()); + context.lineTo(tailPos.get_x(), tailPos.get_y()); + context.closePath(); + context.fill(); + } + }, drawEye:function (context) { + { + var eyePos = this.get_directionToLogo().times(this.get_radius()).times(0.6).plus(this.get_position()); + var eyeRadius = this.get_radius() / 3; + var eyeLidRadius = eyeRadius / 2; + context.fillStyle = '#FFFFFF'; + this.fillCircle(context, eyePos, eyeRadius); + context.fillStyle = '#000000'; + this.fillCircle(context, eyePos, eyeLidRadius); + } + }, drawCreatureWithShadow:function (context) { + { + context.save(); + this.setShadow(context); + context.fillStyle = this.getGradient(context); + this.fillCircle(context, this.get_position(), this.get_radius()); + context.restore(); + this.drawEye(context); + this.drawTail(context); + } + }, setShadow:function (context) { + { + context.shadowColor = 'rgba(100, 100, 100, 0.7)'; + context.shadowBlur = 5; + context.shadowOffsetX = this.get_shadowOffset().get_x(); + context.shadowOffsetY = this.get_shadowOffset().get_y(); + } + } + }); + var Logo = Kotlin.Class.create(Shape, {initialize:function (pos, relSize) { + this.$pos = pos; + this.$relSize = relSize; + this.super_init(); + this.$imageSize = interactive2.v_0(704, 254); + this.$canvasSize = this.get_imageSize().times(this.get_relSize()); + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_relSize:function () { + return this.$relSize; + }, set_relSize:function (tmp$0) { + this.$relSize = tmp$0; + }, get_imageSize:function () { + return this.$imageSize; + }, get_canvasSize:function () { + return this.$canvasSize; + }, draw:function (state) { + { + var context = state.get_context(); + context.drawImage(getJBLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_pos().get_x(), this.get_pos().get_y(), this.get_canvasSize().get_x(), this.get_canvasSize().get_y()); + } + }, contains:function (mousePos) { + { + return mousePos.isInRect(this.get_pos(), this.get_canvasSize()); + } + }, get_centre:function () { + { + return this.get_pos().plus(this.get_canvasSize().times(0.5)); + } + } + }); + return {Shape_0:Shape, Logo_0:Logo, Creature_0:Creature, RadialGradientGenerator_0:RadialGradientGenerator, CanvasState_0:CanvasState, Vector_0:Vector}; + } + (); + var interactive2 = Kotlin.Namespace.create({initialize:function () { + interactive2.$gradientGenerator = new interactive2.RadialGradientGenerator_0(getContext()); + interactive2.$JB = new interactive2.Logo_0(interactive2.v_0(20, 20), 0.3); + }, get_gradientGenerator:function () { + return interactive2.$gradientGenerator; + }, get_JB:function () { + return interactive2.$JB; + }, doWithPeriod:function (period, f) { + { + setInterval(f, period); + } + }, v_0:function (x, y) { + { + return new interactive2.Vector_0(x, y); + } + }, main:function () { + { + var state = new interactive2.CanvasState_0(getCanvas()); + state.addShape(interactive2.get_JB()); + setTimeout(function () { + { + state.set_valid(false); + } + } + ); + } + } + }, classes); + interactive2.initialize(); +} + +var args = []; +interactive2.main(args); diff --git a/examplesForWebDemo/src/html5/interactive3/interactive3.js b/examplesForWebDemo/src/html5/interactive3/interactive3.js new file mode 100644 index 00000000000..0fd6120c796 --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive3/interactive3.js @@ -0,0 +1,529 @@ +{ + var classes = function () { + var Vector = Kotlin.Class.create({initialize:function (x, y) { + this.$x = x; + this.$y = y; + }, get_x:function () { + return this.$x; + }, get_y:function () { + return this.$y; + }, plus:function (v) { + { + return interactive3.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y()); + } + }, minus:function () { + { + return interactive3.v_0(-this.get_x(), -this.get_y()); + } + }, minus$0:function (v) { + { + return interactive3.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y()); + } + }, times:function (koef) { + { + return interactive3.v_0(this.get_x() * koef, this.get_y() * koef); + } + }, distanceTo:function (v) { + { + return Math.sqrt(this.minus$0(v).get_sqr()); + } + }, rotatedBy:function (theta) { + { + var sin = Math.sin(theta); + var cos = Math.cos(theta); + return interactive3.v_0(this.get_x() * cos - this.get_y() * sin, this.get_x() * sin + this.get_y() * cos); + } + }, isInRect:function (topLeft, size) { + { + return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y(); + } + }, get_sqr:function () { + { + return this.get_x() * this.get_x() + this.get_y() * this.get_y(); + } + }, get_normalized:function () { + { + return this.times(1 / Math.sqrt(this.get_sqr())); + } + } + }); + var RadialGradientGenerator = Kotlin.Class.create({initialize:function (context) { + this.$context = context; + this.$gradients = new Kotlin.ArrayList; + this.$current = 0; + { + this.newColorStops([ + [0, '#F59898'], + [0.5, '#F57373'], + [1, '#DB6B6B'] + ]); + this.newColorStops([ + [0.39, 'rgb(140,167,209)'], + [0.7, 'rgb(104,139,209)'], + [0.85, 'rgb(67,122,217)'] + ]); + this.newColorStops([ + [0, 'rgb(255,222,255)'], + [0.5, 'rgb(255,185,222)'], + [1, 'rgb(230,154,185)'] + ]); + this.newColorStops([ + [0, 'rgb(255,209,114)'], + [0.5, 'rgb(255,174,81)'], + [1, 'rgb(241,145,54)'] + ]); + this.newColorStops([ + [0, 'rgb(132,240,135)'], + [0.5, 'rgb(91,240,96)'], + [1, 'rgb(27,245,41)'] + ]); + this.newColorStops([ + [0, 'rgb(250,147,250)'], + [0.5, 'rgb(255,80,255)'], + [1, 'rgb(250,0,217)'] + ]); + } + }, get_context:function () { + return this.$context; + }, get_gradients:function () { + return this.$gradients; + }, get_current:function () { + return this.$current; + }, set_current:function (tmp$0) { + this.$current = tmp$0; + }, newColorStops:function (colorStops) { + { + this.get_gradients().add(colorStops); + } + }, getNext:function () { + { + var result = this.get_gradients().get(this.get_current()); + this.set_current((this.get_current() + 1) % this.get_gradients().size()); + return result; + } + } + }); + var CanvasState = Kotlin.Class.create({initialize:function (canvas) { + this.$canvas = canvas; + this.$width = this.get_canvas().width; + this.$height = this.get_canvas().height; + this.$context = getContext(); + this.$valid = false; + this.$shapes = new Kotlin.ArrayList; + this.$selection = null; + this.$dragOff = new interactive3.Vector_0(0, 0); + this.$interval = 1000 / 30; + { + var tmp$4; + var tmp$3; + var tmp$2; + var tmp$1; + var tmp$0_0; + $(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) { + { + var tmp$0; + tmp$0_0.set_valid(false); + tmp$0_0.set_selection(null); + var mousePos = tmp$0_0.mousePos_0(it); + { + tmp$0 = tmp$0_0.get_shapes().iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + if (shape.contains(mousePos)) { + tmp$0_0.set_dragOff(mousePos.minus$0(shape.get_pos())); + shape.set_selected(true); + tmp$0_0.set_selection(shape); + break; + } + } + } + } + } + } + )); + $(this.get_canvas()).mousemove((tmp$1 = this , function (it) { + { + if (tmp$1.get_selection() != null) { + Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus$0(tmp$1.get_dragOff())); + tmp$1.set_valid(false); + } + } + } + )); + $(this.get_canvas()).mouseup((tmp$2 = this , function (it) { + { + if (tmp$2.get_selection() != null) { + Kotlin.sure(tmp$2.get_selection()).set_selected(false); + } + tmp$2.set_selection(null); + tmp$2.set_valid(false); + } + } + )); + $(this.get_canvas()).dblclick((tmp$3 = this , function (it) { + { + var newCreature = new interactive3.Creature_0(tmp$3.mousePos_0(it), tmp$3); + tmp$3.addShape(newCreature); + tmp$3.set_valid(false); + } + } + )); + setInterval((tmp$4 = this , function () { + { + tmp$4.draw(); + } + } + ), this.get_interval()); + } + }, get_canvas:function () { + return this.$canvas; + }, get_width:function () { + return this.$width; + }, get_height:function () { + return this.$height; + }, get_size:function () { + { + return interactive3.v_0(this.get_width(), this.get_height()); + } + }, get_context:function () { + return this.$context; + }, get_valid:function () { + return this.$valid; + }, set_valid:function (tmp$0) { + this.$valid = tmp$0; + }, get_shapes:function () { + return this.$shapes; + }, set_shapes:function (tmp$0) { + this.$shapes = tmp$0; + }, get_selection:function () { + return this.$selection; + }, set_selection:function (tmp$0) { + this.$selection = tmp$0; + }, get_dragOff:function () { + return this.$dragOff; + }, set_dragOff:function (tmp$0) { + this.$dragOff = tmp$0; + }, get_interval:function () { + return this.$interval; + }, mousePos_0:function (e) { + { + var offset = new interactive3.Vector_0(0, 0); + var element = this.get_canvas(); + while (element != null) { + var el = Kotlin.sure(element); + offset = offset.plus(new interactive3.Vector_0(el.offsetLeft, el.offsetTop)); + element = el.offsetParent; + } + return (new interactive3.Vector_0(e.pageX, e.pageY)).minus$0(offset); + } + }, addShape:function (shape) { + { + this.get_shapes().add(shape); + this.set_valid(false); + } + }, clear:function () { + { + this.get_context().fillStyle = '#FFFFFF'; + this.get_context().fillRect(0, 0, this.get_width(), this.get_height()); + this.get_context().strokeStyle = '#000000'; + this.get_context().lineWidth = 4; + this.get_context().strokeRect(0, 0, this.get_width(), this.get_height()); + } + }, draw:function () { + { + var tmp$0; + if (this.get_valid()) + return; + this.clear(); + { + tmp$0 = interactive3.reversed(this.get_shapes()).iterator(); + while (tmp$0.hasNext()) { + var shape = tmp$0.next(); + { + shape.draw(this); + } + } + } + interactive3.get_Kotlin().draw(this); + this.set_valid(true); + } + } + }); + var Shape = Kotlin.Class.create({initialize:function () { + this.$selected = false; + }, draw:function (state) { + }, contains:function (mousePos) { + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_selected:function () { + return this.$selected; + }, set_selected:function (tmp$0) { + this.$selected = tmp$0; + }, shadowed:function (receiver, shadowOffset, alpha, render) { + { + receiver.save(); + receiver.shadowColor = 'rgba(100, 100, 100, ' + alpha + ')'; + receiver.shadowBlur = 5; + receiver.shadowOffsetX = shadowOffset.get_x(); + receiver.shadowOffsetY = shadowOffset.get_y(); + render.call(receiver); + receiver.restore(); + } + }, fillPath:function (receiver, constructPath) { + { + receiver.beginPath(); + constructPath.call(receiver); + receiver.closePath(); + receiver.fill(); + } + } + }); + var Creature = Kotlin.Class.create(Shape, {initialize:function (pos, state) { + this.$pos = pos; + this.$state = state; + this.super_init(); + this.$shadowOffset = interactive3.v_0(-5, 5); + this.$colorStops = interactive3.get_gradientGenerator().getNext(); + this.$relSize = 0.05; + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_state:function () { + return this.$state; + }, set_state:function (tmp$0) { + this.$state = tmp$0; + }, get_shadowOffset:function () { + return this.$shadowOffset; + }, get_colorStops:function () { + return this.$colorStops; + }, get_relSize:function () { + return this.$relSize; + }, get_radius:function () { + { + return this.get_state().get_width() * this.get_relSize(); + } + }, get_position:function () { + var tmp$0; + if (this.get_selected()) + tmp$0 = this.get_pos().minus$0(this.get_shadowOffset()); + else + tmp$0 = this.get_pos(); + { + return tmp$0; + } + }, get_directionToLogo:function () { + { + return interactive3.get_Kotlin().get_centre().minus$0(this.get_position()).get_normalized(); + } + }, contains:function (mousePos) { + { + return this.get_pos().distanceTo(mousePos) < this.get_radius(); + } + }, circlePath:function (receiver, position, rad) { + { + receiver.arc(position.get_x(), position.get_y(), rad, 0, 2 * Math.PI, false); + } + }, fillCircle:function (receiver, position, rad) { + { + var tmp$0; + this.fillPath(receiver, (tmp$0 = this , function () { + { + tmp$0.circlePath(receiver, position, rad); + } + } + )); + } + }, draw:function (state) { + { + var context = state.get_context(); + if (!this.get_selected()) { + this.drawCreature(context); + } + else { + this.drawCreatureWithShadow(context); + } + } + }, drawCreature:function (context) { + { + var tmp$0; + context.fillStyle = this.getGradient(context); + this.fillPath(context, (tmp$0 = this , function () { + { + tmp$0.tailPath(context); + tmp$0.circlePath(this, tmp$0.get_position(), tmp$0.get_radius()); + } + } + )); + this.drawEye(context); + } + }, getGradient:function (context) { + { + var tmp$0; + var gradientCentre = this.get_position().plus(this.get_directionToLogo().times(this.get_radius() / 4)); + var gradient = context.createRadialGradient(gradientCentre.get_x(), gradientCentre.get_y(), 1, gradientCentre.get_x(), gradientCentre.get_y(), 2 * this.get_radius()); + { + tmp$0 = Kotlin.arrayIterator(this.get_colorStops()); + while (tmp$0.hasNext()) { + var colorStop = tmp$0.next(); + { + gradient.addColorStop(colorStop[0], colorStop[1]); + } + } + } + return gradient; + } + }, tailPath:function (context) { + { + var tailDirection = this.get_directionToLogo().minus(); + var tailPos = this.get_position().plus(tailDirection.times(this.get_radius()).times(1)); + var tailSize = this.get_radius() * 1.6; + var angle = Math.PI / 6; + var p1 = tailPos.plus(tailDirection.rotatedBy(angle).times(tailSize)); + var p2 = tailPos.plus(tailDirection.rotatedBy(-angle).times(tailSize)); + var middlePoint = this.get_position().plus(tailDirection.times(this.get_radius()).times(1)); + context.moveTo(tailPos.get_x(), tailPos.get_y()); + context.lineTo(p1.get_x(), p1.get_y()); + context.quadraticCurveTo(middlePoint.get_x(), middlePoint.get_y(), p2.get_x(), p2.get_y()); + context.lineTo(tailPos.get_x(), tailPos.get_y()); + } + }, drawEye:function (context) { + { + var eyePos = this.get_directionToLogo().times(this.get_radius()).times(0.6).plus(this.get_position()); + var eyeRadius = this.get_radius() / 3; + var eyeLidRadius = eyeRadius / 2; + context.fillStyle = '#FFFFFF'; + this.fillCircle(context, eyePos, eyeRadius); + context.fillStyle = '#000000'; + this.fillCircle(context, eyePos, eyeLidRadius); + } + }, drawCreatureWithShadow:function (context) { + { + var tmp$0_0; + this.shadowed(context, this.get_shadowOffset(), 0.7, (tmp$0_0 = this , function () { + { + var tmp$0; + context.fillStyle = tmp$0_0.getGradient(context); + tmp$0_0.fillPath(this, (tmp$0 = tmp$0_0 , function () { + { + tmp$0.tailPath(context); + tmp$0.circlePath(context, tmp$0.get_position(), tmp$0.get_radius()); + } + } + )); + } + } + )); + this.drawEye(context); + } + } + }); + var Logo = Kotlin.Class.create(Shape, {initialize:function (pos, relSize) { + this.$pos = pos; + this.$relSize = relSize; + this.super_init(); + this.$shadowOffset = interactive3.v_0(-3, 3); + this.$imageSize = interactive3.v_0(377, 393); + this.$size = this.get_imageSize().times(this.get_relSize()); + }, get_pos:function () { + return this.$pos; + }, set_pos:function (tmp$0) { + this.$pos = tmp$0; + }, get_relSize:function () { + return this.$relSize; + }, set_relSize:function (tmp$0) { + this.$relSize = tmp$0; + }, get_shadowOffset:function () { + return this.$shadowOffset; + }, get_imageSize:function () { + return this.$imageSize; + }, get_size:function () { + return this.$size; + }, set_size:function (tmp$0) { + this.$size = tmp$0; + }, get_position:function () { + var tmp$0; + if (this.get_selected()) + tmp$0 = this.get_pos().minus$0(this.get_shadowOffset()); + else + tmp$0 = this.get_pos(); + { + return tmp$0; + } + }, drawLogo:function (state) { + { + this.set_size(this.get_imageSize().times(state.get_size().get_x() / this.get_imageSize().get_x()).times(this.get_relSize())); + state.get_context().drawImage(getJBLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_position().get_x(), this.get_position().get_y(), this.get_size().get_x(), this.get_size().get_y()); + } + }, draw:function (state) { + { + var context = state.get_context(); + if (this.get_selected()) { + var tmp$0; + this.shadowed(context, this.get_shadowOffset(), 0.2, (tmp$0 = this , function () { + { + tmp$0.drawLogo(state); + } + } + )); + } + else { + this.drawLogo(state); + } + } + }, contains:function (mousePos) { + { + return mousePos.isInRect(this.get_pos(), this.get_size()); + } + }, get_centre:function () { + { + return this.get_pos().plus(this.get_size().times(0.5)); + } + } + }); + return {Shape_0:Shape, Logo_0:Logo, Creature_0:Creature, RadialGradientGenerator_0:RadialGradientGenerator, CanvasState_0:CanvasState, Vector_0:Vector}; + } + (); + var interactive3 = Kotlin.Namespace.create({initialize:function () { + interactive3.$gradientGenerator = new interactive3.RadialGradientGenerator_0(getContext()); + interactive3.$Kotlin = new interactive3.Logo_0(interactive3.v_0(20, 20), 0.25); + }, get_gradientGenerator:function () { + return interactive3.$gradientGenerator; + }, get_Kotlin:function () { + return interactive3.$Kotlin; + }, v_0:function (x, y) { + { + return new interactive3.Vector_0(x, y); + } + }, main:function () { + { + var state = new interactive3.CanvasState_0(getCanvas()); + state.addShape(interactive3.get_Kotlin()); + state.addShape(new interactive3.Creature_0(state.get_size().times(0.25), state)); + state.addShape(new interactive3.Creature_0(state.get_size().times(0.75), state)); + setTimeout(function () { + { + state.set_valid(false); + } + } + ); + } + }, reversed:function (receiver) { + { + var result = new Kotlin.ArrayList; + var i = receiver.size(); + while (i > 0) { + result.add(receiver.get(--i)); + } + return result; + } + } + }, classes); + interactive3.initialize(); +} + +var args = []; +interactive3.main(args); diff --git a/examplesForWebDemo/src/html5/interactive3/kotlinlogo.png b/examplesForWebDemo/src/html5/interactive3/kotlinlogo.png new file mode 100644 index 00000000000..5394223b3d6 Binary files /dev/null and b/examplesForWebDemo/src/html5/interactive3/kotlinlogo.png differ diff --git a/examplesForWebDemo/src/html5/interactive3/main.kt b/examplesForWebDemo/src/html5/interactive3/main.kt new file mode 100644 index 00000000000..af53cfbe1d6 --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive3/main.kt @@ -0,0 +1,318 @@ +package interactive3 + +import jquery.* +import html5.* +import java.util.ArrayList +import js.* +import js.Math +import js.setInterval +import html5.getCanvas +import html5.getJBLogo +import jquery.jq +import js.setTimeout +import java.util.List + +val gradientGenerator = RadialGradientGenerator(getContext()) +val Kotlin = Logo(v(20.0, 20.0)) + +abstract class Shape() { + + abstract fun draw(state : CanvasState) + abstract fun contains(mousePos : Vector) : Boolean + abstract var pos : Vector + + var selected : Boolean = false + + fun Context.shadowed(shadowOffset : Vector, alpha : Double, render : Context.() -> Unit) { + save() + shadowColor = "rgba(100, 100, 100, $alpha)" + shadowBlur = 5.0 + shadowOffsetX = shadowOffset.x + shadowOffsetY = shadowOffset.y + render() + restore() + } + + fun Context.fillPath(constructPath : Context.() -> Unit) { + beginPath() + constructPath() + closePath() + fill() + } +} + +class Logo(override var pos : Vector, +var relSize : Double = 0.25) +: Shape() +{ + val shadowOffset = v(-3.0, 3.0) + val imageSize = v(377.0, 393.0) + var size : Vector = imageSize * relSize + val position : Vector + get() = if (selected) pos - shadowOffset else pos + + fun drawLogo(state : CanvasState) { + size = imageSize * (state.size.x / imageSize.x) * relSize + state.context.drawImage(getJBLogo(), 0.0, 0.0, imageSize.x, imageSize.y, position.x, position.y, size.x, size.y) + } + + override fun draw(state : CanvasState) { + val context = state.context + if (selected) { + context.shadowed(shadowOffset, 0.2) { + drawLogo(state) + } + } else { + drawLogo(state) + } + } + + override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, size) + + val centre : Vector + get() = pos + size * 0.5 +} + +class Creature(override var pos : Vector, +var state : CanvasState) : Shape() { + + val shadowOffset = v(-5.0, 5.0) + val colorStops = gradientGenerator.getNext() + val relSize = 0.05 + val radius : Double + get() = state.width * relSize + val position : Vector + get() = if (selected) pos - shadowOffset else pos + val directionToLogo : Vector + get() = (Kotlin.centre - position).normalized + + override fun contains(mousePos : Vector) = pos distanceTo mousePos < radius + + fun Context.circlePath(position : Vector, rad : Double) { + arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false) + } + + fun Context.fillCircle(position : Vector, rad : Double) { + fillPath { + circlePath(position, rad) + } + } + + override fun draw(state : CanvasState) { + val context = state.context + if (!selected) { + drawCreature(context) + } else { + drawCreatureWithShadow(context) + } + } + + fun drawCreature(context : Context) { + context.fillStyle = getGradient(context) + context.fillPath { + tailPath(context) + circlePath(position, radius) + } + drawEye(context) + } + + fun getGradient(context : Context) : CanvasGradient { + val gradientCentre = position + directionToLogo * (radius / 4) + val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius) + for (colorStop in colorStops) { + gradient.addColorStop(colorStop._1, colorStop._2) + } + return gradient + } + + fun tailPath(context : Context) { + val tailDirection = -directionToLogo + val tailPos = position + tailDirection * radius * 1.0 + val tailSize = radius * 1.6 + val angle = Math.PI / 6.0 + val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize + val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize + val middlePoint = position + tailDirection * radius * 1.0 + context.moveTo(tailPos.x, tailPos.y) + context.lineTo(p1.x, p1.y) + context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y) + context.lineTo(tailPos.x, tailPos.y) + } + + fun drawEye(context : Context) { + val eyePos = directionToLogo * radius * 0.6 + position + val eyeRadius = radius / 3 + val eyeLidRadius = eyeRadius / 2 + context.fillStyle = "#FFFFFF" + context.fillCircle(eyePos, eyeRadius) + context.fillStyle = "#000000" + context.fillCircle(eyePos, eyeLidRadius) + } + + fun drawCreatureWithShadow(context : Context) { + context.shadowed(shadowOffset, 0.7) { + context.fillStyle = getGradient(context) + fillPath { + tailPath(context) + context.circlePath(position, radius) + } + } + drawEye(context) + } +} + +class CanvasState(val canvas : Canvas) { + val width = canvas.width + val height = canvas.height + val size : Vector + get() = v(width, height) + val context = getContext() + var valid = false + var shapes = ArrayList() + var selection : Shape? = null + var dragOff = Vector() + val interval = 1000 / 30 + + + { + jq(canvas).mousedown { + valid = false + selection = null + val mousePos = mousePos(it) + for (shape in shapes) { + if (mousePos in shape) { + dragOff = mousePos - shape.pos + shape.selected = true + selection = shape + break + } + } + } + + jq(canvas).mousemove { + if (selection != null) { + selection.sure().pos = mousePos(it) - dragOff + valid = false + } + } + + jq(canvas).mouseup { + if (selection != null) { + selection.sure().selected = false + } + selection = null + valid = false + } + + jq(canvas).dblclick { + val newCreature = Creature(mousePos(it), this @CanvasState) + addShape(newCreature) + valid = false + } + + setInterval({ + draw() + }, interval) + } + + fun mousePos(e : MouseEvent) : Vector { + var offset = Vector() + var element : DomElement? = canvas + while (element != null) { + val el : DomElement = element.sure() + offset += Vector(el.offsetLeft, el.offsetTop) + element = el.offsetParent + } + return Vector(e.pageX, e.pageY) - offset + } + + fun addShape(shape : Shape) { + shapes.add(shape) + valid = false + } + + fun clear() { + context.fillStyle = "#FFFFFF" + context.fillRect(0.0, 0.0, width, height) + context.strokeStyle = "#000000" + context.lineWidth = 4.0 + context.strokeRect(0.0, 0.0, width, height) + } + + fun draw() { + if (valid) return + + clear() + for (shape in shapes.reversed()) { + shape.draw(this) + } + Kotlin.draw(this) + valid = true + } +} + +class RadialGradientGenerator(val context : Context) { + val gradients = ArrayList>() + var current = 0 + + fun newColorStops(vararg colorStops : #(Double, String)) { + gradients.add(colorStops) + } + + { + newColorStops(#(0.0, "#F59898"), #(0.5, "#F57373"), #(1.0, "#DB6B6B")) + newColorStops(#(0.39, "rgb(140,167,209)"), #(0.7, "rgb(104,139,209)"), #(0.85, "rgb(67,122,217)")) + newColorStops(#(0.0, "rgb(255,222,255)"), #(0.5, "rgb(255,185,222)"), #(1.0, "rgb(230,154,185)")) + newColorStops(#(0.0, "rgb(255,209,114)"), #(0.5, "rgb(255,174,81)"), #(1.0, "rgb(241,145,54)")) + newColorStops(#(0.0, "rgb(132,240,135)"), #(0.5, "rgb(91,240,96)"), #(1.0, "rgb(27,245,41)")) + newColorStops(#(0.0, "rgb(250,147,250)"), #(0.5, "rgb(255,80,255)"), #(1.0, "rgb(250,0,217)")) + } + + fun getNext() : Array<#(Double, String)> { + val result = gradients.get(current) + current = (current + 1) % gradients.size() + return result + } +} + +fun v(x : Double, y : Double) = Vector(x, y) + +class Vector(val x : Double = 0.0, val y : Double = 0.0) { + fun plus(v : Vector) = v(x + v.x, y + v.y) + fun minus() = v(-x, -y) + fun minus(v : Vector) = v(x - v.x, y - v.y) + fun times(koef : Double) = v(x * koef, y * koef) + fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr) + fun rotatedBy(theta : Double) : Vector { + val sin = Math.sin(theta) + val cos = Math.cos(theta) + return v(x * cos - y * sin, x * sin + y * cos) + } + + fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) && + (y >= topLeft.y) && (y <= topLeft.y + size.y) + + val sqr : Double + get() = x * x + y * y + val normalized : Vector + get() = this * (1.0 / Math.sqrt(sqr)) +} + +fun main() { + val state = CanvasState(getCanvas()) + state.addShape(Kotlin) + state.addShape(Creature(state.size * 0.25, state)) + state.addShape(Creature(state.size * 0.75, state)) + setTimeout({ + state.valid = false + }) +} + +fun List.reversed() : List { + val result = ArrayList() + var i = size() + while (i > 0) { + result.add(get(--i)) + } + return result +} \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/interactive3/template.html b/examplesForWebDemo/src/html5/interactive3/template.html new file mode 100644 index 00000000000..6daacd29669 --- /dev/null +++ b/examplesForWebDemo/src/html5/interactive3/template.html @@ -0,0 +1,15 @@ + + + + Canvas demo + + + + + + + + + + \ No newline at end of file diff --git a/examplesForWebDemo/src/html5/test/test.kt b/examplesForWebDemo/src/html5/test/test.kt index e4fdcae638d..47f5754e507 100644 --- a/examplesForWebDemo/src/html5/test/test.kt +++ b/examplesForWebDemo/src/html5/test/test.kt @@ -7,7 +7,7 @@ import jquery.*; fun main() { jq { Test().run(); - HelloKotlin().run(); + // HelloKotlin().run(); } } diff --git a/examplesForWebDemo/src/html5/test/testhtml.js b/examplesForWebDemo/src/html5/test/testhtml.js index 8312453d084..876a7228c17 100644 --- a/examplesForWebDemo/src/html5/test/testhtml.js +++ b/examplesForWebDemo/src/html5/test/testhtml.js @@ -106,7 +106,6 @@ $(function () { { (new testhtml.Test_0).run(); - (new testhtml.HelloKotlin_0).run(); } } ); diff --git a/jslib/src/html5/core.kt b/jslib/src/html5/core.kt index ac64a472188..01b34c33150 100644 --- a/jslib/src/html5/core.kt +++ b/jslib/src/html5/core.kt @@ -5,20 +5,28 @@ import js.DomElement native class Context() { - fun save() {} - fun restore() {} + fun save() { + } + fun restore() { + } - fun scale(x : Double, y : Double) {} - fun rotate(angle : Double) {} - fun translate(x : Double, y : Double) {} + fun scale(x : Double, y : Double) { + } + fun rotate(angle : Double) { + } + fun translate(x : Double, y : Double) { + } - fun clearRect(x : Double, y : Double, w : Double, h : Double) {} - fun fillRect(x : Double, y : Double, w : Double, h : Double) {} - fun strokeRect(x : Double, y : Double, w : Double, h : Double) {} + fun clearRect(x : Double, y : Double, w : Double, h : Double) { + } + fun fillRect(x : Double, y : Double, w : Double, h : Double) { + } + fun strokeRect(x : Double, y : Double, w : Double, h : Double) { + } var globalAlpha : Double = 1.0; - var strokeStyle : String = "" - var fillStyle : String = "" + var strokeStyle : Any = "" + var fillStyle : Any = "" var lineWidth : Double = 1.0 var shadowOffsetX : Double = 0.0 var shadowOffsetY : Double = 0.0 @@ -26,35 +34,64 @@ class Context() { var shadowColor : String = "" var font : String = "" - fun beginPath() {} - fun moveTo(x : Double, y : Double) {} - fun closePath() {} + fun beginPath() { + } + fun moveTo(x : Double, y : Double) { + } + fun closePath() { + } - fun lineTo(x : Double, y : Double) {} - fun quadraticCurveTo(cpx : Double, cpy : Double, x : Double, y : Double) {} - fun bezierCurveTo(cp1x : Double, cp1y : Double, cp2x : Double, cp2y : Double, x : Double, y : Double) {} - fun arcTo(x1 : Double, y1 : Double, x2 : Double, y2 : Double, radius : Double) {} - fun arc(x : Double, y : Double, radius : Double, startAngle : Double, endAngle : Double, anticlockwise : Boolean) {} + fun lineTo(x : Double, y : Double) { + } + fun quadraticCurveTo(cpx : Double, cpy : Double, x : Double, y : Double) { + } + fun bezierCurveTo(cp1x : Double, cp1y : Double, cp2x : Double, cp2y : Double, x : Double, y : Double) { + } + fun arcTo(x1 : Double, y1 : Double, x2 : Double, y2 : Double, radius : Double) { + } + fun arc(x : Double, y : Double, radius : Double, startAngle : Double, endAngle : Double, anticlockwise : Boolean) { + } - fun rect(x : Double, y : Double, w : Double, h : Double) {} - fun fill() {} - fun stroke() {} + fun rect(x : Double, y : Double, w : Double, h : Double) { + } + fun fill() { + } + fun stroke() { + } - fun fillText(text : String, x : Double, y : Double) {} - fun fillText(text : String, x : Double, y : Double, maxWidth : Double) {} - fun strokeText(text : String, x : Double, y : Double) {} - fun strokeText(text : String, x : Double, y : Double, maxWidth : Double) {} + fun fillText(text : String, x : Double, y : Double) { + } + fun fillText(text : String, x : Double, y : Double, maxWidth : Double) { + } + fun strokeText(text : String, x : Double, y : Double) { + } + fun strokeText(text : String, x : Double, y : Double, maxWidth : Double) { + } fun measureText(text : String) : TextMetrics = TextMetrics(); - fun drawImage(image : HTMLImageElement, dx : Double, dy : Double) {} - fun drawImage(image : HTMLImageElement, dx: Double, dy: Double, dw: Double, dh: Double) {} + fun drawImage(image : HTMLImageElement, dx : Double, dy : Double) { + } + fun drawImage(image : HTMLImageElement, dx: Double, dy: Double, dw: Double, dh: Double) { + } fun drawImage(image : HTMLImageElement, sx: Double, sy: Double, - sw: Double, sh: Double, dx: Double, dy: Double, dw: Double, dh: Double) {} + sw: Double, sh: Double, dx: Double, dy: Double, dw: Double, dh: Double) { + } + + fun createLinearGradient(x0 : Double, y0 : Double, x1 : Double, y1 : Double) : CanvasGradient = CanvasGradient() + fun createRadialGradient(x0 : Double, y0 : Double, r0 : Double, x1 : Double, y1 : Double, r1 : Double) : CanvasGradient = CanvasGradient(); + } native -class HTMLImageElement() : DomElement() {} +class HTMLImageElement() : DomElement() { +} + +native +class CanvasGradient() { + fun addColorStop(offset : Double, color : String) {} +} + native class Canvas() : DomElement() {