diff --git a/doric-android/doric/src/main/java/pub/doric/DoricRegistry.java b/doric-android/doric/src/main/java/pub/doric/DoricRegistry.java index b95669ed..db60f006 100644 --- a/doric-android/doric/src/main/java/pub/doric/DoricRegistry.java +++ b/doric-android/doric/src/main/java/pub/doric/DoricRegistry.java @@ -28,6 +28,7 @@ import pub.doric.plugin.PopoverPlugin; import pub.doric.plugin.ShaderPlugin; import pub.doric.plugin.StoragePlugin; import pub.doric.refresh.RefreshableNode; +import pub.doric.shader.DraggableNode; import pub.doric.shader.HLayoutNode; import pub.doric.shader.ImageNode; import pub.doric.shader.InputNode; @@ -110,6 +111,7 @@ public class DoricRegistry { this.registerViewNode(FlowLayoutItemNode.class); this.registerViewNode(InputNode.class); this.registerViewNode(NestedSliderNode.class); + this.registerViewNode(DraggableNode.class); initRegistry(this); } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/DraggableNode.java b/doric-android/doric/src/main/java/pub/doric/shader/DraggableNode.java new file mode 100644 index 00000000..835a18d4 --- /dev/null +++ b/doric-android/doric/src/main/java/pub/doric/shader/DraggableNode.java @@ -0,0 +1,76 @@ +package pub.doric.shader; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +import com.github.pengfeizhou.jscore.JSValue; + +import pub.doric.DoricContext; +import pub.doric.extension.bridge.DoricPlugin; + +@DoricPlugin(name = "Draggable") +public class DraggableNode extends StackNode { + + private String onDrag; + + public DraggableNode(DoricContext doricContext) { + super(doricContext); + } + + @Override + protected FrameLayout build() { + return new DraggableView(getContext()); + } + + @Override + protected void blend(FrameLayout view, String name, JSValue prop) { + if ("onDrag".equals(name)) { + if (prop.isString()) { + onDrag = prop.asString().value(); + } else { + onDrag = null; + } + } else { + super.blend(view, name, prop); + } + } + + private class DraggableView extends FrameLayout { + private int lastX; + + private int lastY; + + public DraggableView(Context context) { + super(context); + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent event) { + int x = (int) event.getX(); + int y = (int) event.getY(); + + int rawX = (int) event.getRawX(); + int rawY = (int) event.getRawY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + lastX = x; + lastY = y; + break; + case MotionEvent.ACTION_MOVE: + int offsetX = x - lastX; + int offsetY = y - lastY; + layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); + break; + case MotionEvent.ACTION_UP: + break; + } + + callJSResponse(onDrag, rawX - x, rawY - y); + return true; + } + } +} diff --git a/doric-demo/src/DraggableDemo.ts b/doric-demo/src/DraggableDemo.ts new file mode 100644 index 00000000..545336f3 --- /dev/null +++ b/doric-demo/src/DraggableDemo.ts @@ -0,0 +1,30 @@ +import { Panel, Group, vlayout, layoutConfig, draggable, Color, Text} from "doric"; +import { title } from "./utils"; +@Entry +class DraggableDemo extends Panel { + build(root: Group) { + let text = (new Text).also(it => { + it.layoutConfig = layoutConfig().most() + it.textColor = Color.parse('#ff0000') + }) + vlayout([ + title("Draggable Demo"), + draggable({ + onDrag: (x: number, y: number) => { + text.text = "x: " + x + " y: " + y + } + }, [ text ]).apply({ + layoutConfig: layoutConfig().just(), + width: 100, + height: 100, + backgroundColor: Color.WHITE + }) + ]) + .apply({ + layoutConfig: layoutConfig().most(), + backgroundColor: Color.BLACK + }) + .in(root) + } + +} \ No newline at end of file diff --git a/doric-js/bundle/doric-lib.js b/doric-js/bundle/doric-lib.js index e5d1c7a3..5a05abe9 100644 --- a/doric-js/bundle/doric-lib.js +++ b/doric-js/bundle/doric-lib.js @@ -1694,6 +1694,33 @@ __decorate$a([ __metadata$a("design:type", Function) ], NestedSlider.prototype, "onPageSlided", void 0); +var __decorate$b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata$b = (undefined && undefined.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +class Draggable extends Stack { +} +__decorate$b([ + Property, + __metadata$b("design:type", Function) +], Draggable.prototype, "onDrag", void 0); +function draggable(config, views) { + const ret = new Draggable; + ret.layoutConfig = layoutConfig().fit(); + for (let key in config) { + Reflect.set(ret, key, Reflect.get(config, key, config), ret); + } + for (let v of views) { + ret.addChild(v); + } + return ret; +} + function modal(context) { return { toast: (msg, gravity = Gravity.Bottom) => { @@ -2079,6 +2106,7 @@ exports.CENTER = CENTER; exports.CENTER_X = CENTER_X; exports.CENTER_Y = CENTER_Y; exports.Color = Color; +exports.Draggable = Draggable; exports.FlowLayout = FlowLayout; exports.FlowLayoutItem = FlowLayoutItem; exports.Gravity = Gravity; @@ -2116,6 +2144,7 @@ exports.View = View; exports.ViewHolder = ViewHolder; exports.ViewModel = ViewModel; exports.animate = animate; +exports.draggable = draggable; exports.flowItem = flowItem; exports.flowlayout = flowlayout; exports.gravity = gravity; diff --git a/doric-js/bundle/doric-vm.js b/doric-js/bundle/doric-vm.js index cf5440e4..f2c0d1b4 100644 --- a/doric-js/bundle/doric-vm.js +++ b/doric-js/bundle/doric-vm.js @@ -3142,6 +3142,33 @@ __decorate$a([ __metadata$a("design:type", Function) ], NestedSlider.prototype, "onPageSlided", void 0); +var __decorate$b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata$b = (undefined && undefined.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +class Draggable extends Stack { +} +__decorate$b([ + Property, + __metadata$b("design:type", Function) +], Draggable.prototype, "onDrag", void 0); +function draggable(config, views) { + const ret = new Draggable; + ret.layoutConfig = layoutConfig().fit(); + for (let key in config) { + Reflect.set(ret, key, Reflect.get(config, key, config), ret); + } + for (let v of views) { + ret.addChild(v); + } + return ret; +} + function modal(context) { return { toast: (msg, gravity = Gravity.Bottom) => { @@ -3633,6 +3660,7 @@ exports.CENTER = CENTER; exports.CENTER_X = CENTER_X; exports.CENTER_Y = CENTER_Y; exports.Color = Color; +exports.Draggable = Draggable; exports.FlowLayout = FlowLayout; exports.FlowLayoutItem = FlowLayoutItem; exports.Gravity = Gravity; @@ -3670,6 +3698,7 @@ exports.View = View; exports.ViewHolder = ViewHolder; exports.ViewModel = ViewModel; exports.animate = animate; +exports.draggable = draggable; exports.flowItem = flowItem; exports.flowlayout = flowlayout; exports.gravity = gravity; diff --git a/doric-js/src/widget/draggable.ts b/doric-js/src/widget/draggable.ts new file mode 100644 index 00000000..dabe40ab --- /dev/null +++ b/doric-js/src/widget/draggable.ts @@ -0,0 +1,39 @@ +/* + * Copyright [2019] [Doric.Pub] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Property, View } from "../ui/view" +import { IStack, Stack } from "../widget/layouts" +import { layoutConfig } from "../util/layoutconfig" + +export interface IDraggable extends IStack { + onDrag?: (x: number, y: number) => void +} + +export class Draggable extends Stack implements IDraggable { + @Property + onDrag?: (x: number, y: number) => void +} + +export function draggable(config: IDraggable, views: View[]) { + const ret = new Draggable + ret.layoutConfig = layoutConfig().fit() + for (let key in config) { + Reflect.set(ret, key, Reflect.get(config, key, config), ret) + } + for (let v of views) { + ret.addChild(v) + } + return ret +} \ No newline at end of file diff --git a/doric-js/src/widget/index.widget.ts b/doric-js/src/widget/index.widget.ts index 11f5bd97..2f8d724e 100644 --- a/doric-js/src/widget/index.widget.ts +++ b/doric-js/src/widget/index.widget.ts @@ -22,4 +22,5 @@ export * from './scroller' export * from './refreshable' export * from './flowlayout' export * from './input' -export * from './nestedSlider' \ No newline at end of file +export * from './nestedSlider' +export * from './draggable' \ No newline at end of file