浏览代码

prototype_1

ssaket 6 年之前
父节点
当前提交
bd661ed840

+ 1 - 0
Tools/Gulp/config.json

@@ -158,6 +158,7 @@
                 "../../src/babylon.types.js",
                 "../../src/Events/babylon.keyboardEvents.js",
                 "../../src/Events/babylon.pointerEvents.js",
+                "../../src/Events/babylon.clipboardEvents.js",
                 "../../src/Tools/babylon.tools.js",
                 "../../src/Math/babylon.math.js",
                 "../../src/Math/babylon.math.scalar.js",

+ 9 - 48
gui/src/2D/advancedDynamicTexture.ts

@@ -1,4 +1,4 @@
-import { DynamicTexture, Nullable, Observer, Camera, Engine, KeyboardInfoPre, ClipboardEventTypes, ClipboardInfo, PointerInfoPre, PointerInfo, Layer, Viewport, Scene, Texture, KeyboardEventTypes, Vector3, Matrix, Vector2, Tools, PointerEventTypes, AbstractMesh, StandardMaterial, Color3 } from "babylonjs";
+import { DynamicTexture, Nullable, Observer, Camera, Engine, KeyboardInfoPre, ClipboardEventTypes, ClipboardInfo, PointerInfoPre, PointerInfo, Layer, Viewport, Scene, Texture, KeyboardEventTypes, Vector3, Matrix, Vector2, Tools, PointerEventTypes, AbstractMesh, StandardMaterial, Color3 } from 'babylonjs';
 import { Container } from "./controls/container";
 import { Control } from "./controls/control";
 import { Style } from "./style";
@@ -21,13 +21,13 @@ export interface IFocusableControl {
      * @param evt defines the current keyboard event
      */
     processKeyboard(evt: KeyboardEvent): void;
-
     /**
-     * Function called to let the control handle clipboard events
-     * @param {boolean} show determines whether to show the highlighted text
+     * Defines clipboard events
+     * @param {ClipboardEventsTypes} evt
      */
-    processClipboard(showHighlightedText: boolean, clipboardData?: DataTransfer): void;
+    onClipboardKeyBoardEvent(type: ClipboardEventTypes): void;
 
+    onClipboardPointerEvents(showHighlightedText: boolean): void;
     /**
      * Function called to get the list of controls that should not steal the focus from this control
      * @returns an array of controls
@@ -271,8 +271,9 @@ export class AdvancedDynamicTexture extends DynamicTexture {
             }
 
             if (info.type === KeyboardEventTypes.KEYDOWN) {
+                //get the event type
                 let type = ClipboardInfo.GetTypeFromCharacter(info.event);
-                (this._ctrKeyOn && type !== -1) ? this._executeClipboardEvent(type) : this._focusedControl.processKeyboard(info.event);
+                (this._ctrKeyOn && type !== -1) ? this._focusedControl.onClipboardKeyBoardEvent(type) : this._focusedControl.processKeyboard(info.event);
             }
 
             info.skipOnPointerObservable = true;
@@ -428,47 +429,6 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         }
     }
 
-   /**
-     * @hidden
-     */
-    public registerClipboardEvents(): void {
-        this._rootCanvas!.addEventListener(ClipboardEventTypes.COPY + "_clipboard", this.onClipboardCopy, false);
-        this._rootCanvas!.addEventListener(ClipboardEventTypes.CUT + "_clipboard", this.onClipboardCut, false);
-        this._rootCanvas!.addEventListener(ClipboardEventTypes.PASTE + "_clipboard", this.onClipboardPaste, false);
-    }
-    /**
-     * @hidden
-     */
-    public unRegisterClipboardEvents(): void {
-        this._rootCanvas!.removeEventListener(ClipboardEventTypes.COPY + "_clipboard", this.onClipboardCopy, false);
-        this._rootCanvas!.removeEventListener(ClipboardEventTypes.CUT + "_clipboard", this.onClipboardCut, false);
-        this._rootCanvas!.removeEventListener(ClipboardEventTypes.PASTE + "_clipboard", this.onClipboardPaste, false);
-    }
-
-    /** @hidden */
-    private _executeClipboardEvent(type: ClipboardEventTypes): void {
-       this._simulateClipboardEvent(type);
-    }
-
-    /** @hidden */
-    private _simulateClipboardEvent(type: ClipboardEventTypes): void {
-        let ev;
-        if (type === ClipboardEventTypes.COPY) {
-            ev = new ClipboardInfo(ClipboardEventTypes.COPY, new ClipboardEvent("copy")); //new ClipboardEvent("copy");
-            this._focusedControl!.processClipboard(false, ev.clipboardData);
-        }
-        else if (type === ClipboardEventTypes.CUT) {
-            ev = new ClipboardInfo(ClipboardEventTypes.CUT, new ClipboardEvent("cut"));
-            this._focusedControl!.processClipboard(false, ev.clipboardData);
-        }
-        else if (type === ClipboardEventTypes.PASTE) {
-            ev = new ClipboardInfo(ClipboardEventTypes.PASTE, new ClipboardEvent("paste"));
-        }
-        if (typeof ev !== "undefined") {
-            this.dispatchClipboardEvents(ev);
-        }
-    }
-
     /** @hidden */
     public _getGlobalViewport(scene: Scene): Viewport {
         var engine = scene.getEngine();
@@ -644,7 +604,8 @@ export class AdvancedDynamicTexture extends DynamicTexture {
             if (scene!.isPointerCaptured((<PointerEvent>(pi.event)).pointerId)) {
                 return;
             }
-            (this._focusedControl) ? ((pi.type === PointerEventTypes.POINTERDOUBLETAP) ? this._focusedControl.processClipboard(true) : null) : null;
+            //check for focused control and call the onClipboardPointerEvents
+            (this._focusedControl) ? ((pi.type === PointerEventTypes.POINTERDOUBLETAP) ? this._focusedControl.onClipboardPointerEvents(true) : null) : null;
 
             if (pi.type !== PointerEventTypes.POINTERMOVE
                 && pi.type !== PointerEventTypes.POINTERUP

+ 62 - 1
gui/src/2D/controls/control.ts

@@ -1,7 +1,7 @@
 import { Container } from "./container";
 import { AdvancedDynamicTexture } from "../advancedDynamicTexture";
 import { ValueAndUnit } from "../valueAndUnit";
-import { Nullable, Observer, Vector2, AbstractMesh, Observable, Vector3, Scene, Tools, Matrix, PointerEventTypes } from "babylonjs";
+import { Nullable, Observer, Vector2, AbstractMesh, Observable, Vector3, Scene, Tools, Matrix, PointerEventTypes, ClipboardInfo } from "babylonjs";
 import { Measure } from "../measure";
 import { Style } from "../style";
 import { Matrix2D, Vector2WithInfo } from "../math2D";
@@ -80,6 +80,8 @@ export class Control {
     protected _disabledColor = "#9a9a9a";
     /** @hidden */
     public _tag: any;
+    /** @hidden */
+    private _clipboardData: DataTransfer;
 
     /** Gets or sets a boolean indicating if the control can be hit with pointer events */
     public isHitTestVisible = true;
@@ -164,6 +166,15 @@ export class Control {
         this._fontOffset = offset;
     }
 
+     /** Gets or set information about font offsets (used to render and align text) */
+     public get clipboardData(): DataTransfer {
+        return this._clipboardData;
+    }
+
+    public set clipboardData(data: DataTransfer) {
+        this._clipboardData = data;
+    }
+
     /** Gets or sets alpha value for the control (1 means opaque and 0 means entirely transparent) */
     public get alpha(): number {
         return this._alpha;
@@ -1369,6 +1380,56 @@ export class Control {
         return false;
     }
 
+     /** @hidden */
+    public onClipboardCopy(evt: ClipboardEvent): void {
+        console.log(this._clipboardData!, "copy");
+        evt.preventDefault();
+    }
+     /** @hidden */
+    public onClipboardCut(evt: ClipboardEvent): void {
+        console.log("Cut ! " + this._clipboardData.getData("text/plain"));
+        evt.preventDefault();
+    }
+     /** @hidden */
+    public onClipboardPaste(evt: ClipboardEvent): void {
+        if (evt.clipboardData.types.indexOf('text/plain') > -1) {
+            var text = evt.clipboardData.getData('text/plain');
+            console.log(text);
+            evt.preventDefault();
+          }
+    }
+
+   /**
+     * @hidden
+     */
+    protected registerClipboardEvents(): void {
+        //binds the current focusedControl item to actions
+        this.onClipboardCopy = this.onClipboardCopy.bind(this);
+        this.onClipboardCut = this.onClipboardCut.bind(this);
+        this.onClipboardPaste = this.onClipboardPaste.bind(this);
+
+        document.addEventListener("copy", this.onClipboardCopy, false);
+        document.addEventListener("cut", this.onClipboardCut, false);
+        document.addEventListener("paste", this.onClipboardPaste, false);
+    }
+    /**
+     * @hidden
+     */
+    protected unRegisterClipboardEvents(): void {
+        document.removeEventListener("copy", this.onClipboardCopy);
+        document.removeEventListener("cut", this.onClipboardCut);
+        document.removeEventListener("paste", this.onClipboardPaste);
+    }
+
+    /**
+     * @hidden dispatchClipboardEvent
+    */
+    protected dispatchClipboardEvent(event: ClipboardInfo): void {
+            // custom copy as navigator.clipboard as well as clipboardData in ClipboardInit not supported!
+            this._clipboardData = event.clipboardData;
+            document.dispatchEvent(event.event);
+    }
+
     private _prepareFont() {
         if (!this._font && !this._fontSet) {
             return;

+ 73 - 15
gui/src/2D/controls/inputText.ts

@@ -1,9 +1,10 @@
 import { Control } from "./control";
 import { IFocusableControl } from "../advancedDynamicTexture";
 import { ValueAndUnit } from "../valueAndUnit";
-import { Nullable, Observable, Vector2 } from "babylonjs";
+import { Nullable, Observable, Vector2, ClipboardEventTypes, ClipboardInfo } from "babylonjs";
 import { Measure } from "../measure";
 import { VirtualKeyboard } from "./virtualKeyboard";
+import { TextBlock } from './textBlock';
 
 /**
  * Class used to create input text control
@@ -31,6 +32,8 @@ export class InputText extends Control implements IFocusableControl {
     private _isTextHighlightOn = false;
     private _textHighlightColor = "#d5e0ff";
     private _highlightedText = "";
+    private _startHighlightIndex = 0;
+    private _endHighlightIndex = 0;
 
     /** @hidden */
     public _connectedVirtualKeyboard: Nullable<VirtualKeyboard>;
@@ -265,7 +268,7 @@ export class InputText extends Control implements IFocusableControl {
 
         this.onBlurObservable.notifyObservers(this);
 
-        this._host.unRegisterClipboardEvents.call(this);
+        this.unRegisterClipboardEvents();
     }
 
     /** @hidden */
@@ -291,7 +294,7 @@ export class InputText extends Control implements IFocusableControl {
             return;
         }
 
-        this._host.registerClipboardEvents.call(this);
+        this.registerClipboardEvents();
 
     }
 
@@ -411,12 +414,61 @@ export class InputText extends Control implements IFocusableControl {
     }
 
     /** @hidden */
-    public processClipboard(show: boolean, clipboardData?: DataTransfer): void {
-        if (!show && clipboardData) {
-            clipboardData.setData("text/plain", this._highlightedText);
+    public onClipboardPointerEvents(showHighlightedText: boolean): void {
+        if (!showHighlightedText) {
             return;
         }
-        this._isTextHighlightOn = show;
+        this._isTextHighlightOn = true;
+    }
+     /** @hidden */
+    public onClipboardKeyBoardEvent(type: number) {
+        this.executeClipboardEvent(type, this._highlightedText);
+    }
+    /** @hidden */
+    private _processDataTransfer(data: DataTransfer, text: string = ""): void {
+        //FOR TESTING: TODO: remove this in final version
+        let textbl = new TextBlock();
+        textbl.text = "text copied : " + text;
+        textbl.color = "white";
+        textbl.fontSize = 24;
+        textbl.top = this.topInPixels - 23;
+        this._host.addControl(textbl);
+        setTimeout(() => {textbl.dispose(); }, 2000);
+
+        //copy data to the custom DataTransfer object
+        data.setData("text/plain", text);
+    }
+
+     /** @hidden */
+    private executeClipboardEvent(type: ClipboardEventTypes, text: string): void {
+        this._simulateClipboardEvent(type, text);
+    }
+
+     /** @hidden */
+    private _simulateClipboardEvent(type: ClipboardEventTypes, text: string): void {
+         let ev;
+         switch (type){
+             case ClipboardEventTypes.COPY:
+                    ev = new ClipboardInfo(ClipboardEventTypes.COPY, new ClipboardEvent("copy")); //new ClipboardEvent("copy");
+                    this._processDataTransfer(ev.clipboardData, text);
+                    super.dispatchClipboardEvent(ev);
+                    break;
+              case ClipboardEventTypes.CUT:
+                    ev = new ClipboardInfo(ClipboardEventTypes.CUT, new ClipboardEvent("cut", {dataType: 'text/plain', data: text }));
+                    this.text = this._text.replace(text, "");
+                    this._isTextHighlightOn = false;
+                    this._processDataTransfer(ev.clipboardData, text);
+                    super.dispatchClipboardEvent(ev);
+                    break;
+               case ClipboardEventTypes.PASTE:
+                    if (this.clipboardData.items.length > 0) {
+                        let data = this.clipboardData.getData("text/plain");
+                        let insertPosition = this._text.length - this._cursorOffset;
+                        this.text = this._text.slice(0, insertPosition) + data + this._text.slice(insertPosition);
+                    }
+                    break;
+                default: return;
+         }
     }
 
     public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
@@ -547,20 +599,18 @@ export class InputText extends Control implements IFocusableControl {
                     this._markAsDirty();
                 }, 500);
 
+                 //show the highlighted text
                 if (this._isTextHighlightOn) {
                     clearTimeout(this._blinkTimeout);
                     this._blinkIsEven = true;
-                    let startIndex = this._text.length - this._cursorOffset , endIndex = startIndex;
-                    for (let rWord = /\w+/, check = 1; startIndex >= 0 && endIndex < this.text.length && check + 1;) {
-                        check = rWord.test(this.text.charAt(endIndex)) ? ++endIndex : (rWord.test(this.text.charAt(startIndex)) ? --startIndex : -1);
-                    }
-                    let highlightCursorOffsetWidth = context.measureText(this.text.substring(startIndex + 1)).width;
+
+                    let highlightCursorOffsetWidth = context.measureText(this.text.substring(this._startHighlightIndex + 1)).width;
                     let highlightCursorLeft = this._scrollLeft + this._textWidth - highlightCursorOffsetWidth;
-                    this._highlightedText = this.text.substring(startIndex + 1, endIndex);
+                    this._highlightedText = this.text.substring(this._startHighlightIndex + 1, this._endHighlightIndex);
                     //for transparancy
-                    context.globalAlpha = 0.2;
+                    context.globalAlpha = 0.4;
                     context.fillStyle = this._textHighlightColor;
-                    context.fillRect(highlightCursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, (context.measureText(this.text.substring(startIndex + 1, endIndex)).width), this._fontOffset.height);
+                    context.fillRect(highlightCursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, context.measureText(this.text.substring(this._startHighlightIndex + 1, this._endHighlightIndex)).width, this._fontOffset.height);
                     context.globalAlpha = 1.0;
                 }
             }
@@ -605,6 +655,13 @@ export class InputText extends Control implements IFocusableControl {
 
     public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
         super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
+
+        //pre-find the start and end index of the word under cursor, speeds up the rendering
+        this._startHighlightIndex = this._text.length - this._cursorOffset;
+        this._endHighlightIndex = this._startHighlightIndex;
+        for (let rWord = /\w+/, check = 1; this._startHighlightIndex >= 0 && this._endHighlightIndex < this.text.length && check + 1;) {
+            check = rWord.test(this.text.charAt(this._endHighlightIndex)) ? ++this._endHighlightIndex : (rWord.test(this.text.charAt(this._startHighlightIndex)) ? --this._startHighlightIndex : -1);
+        }
     }
 
     protected _beforeRenderText(text: string): string {
@@ -617,5 +674,6 @@ export class InputText extends Control implements IFocusableControl {
         this.onBlurObservable.clear();
         this.onFocusObservable.clear();
         this.onTextChangedObservable.clear();
+        this.onClipboardObservable.clear();
     }
 }

+ 68 - 23
src/Events/babylon.clipboardEvents.ts

@@ -1,40 +1,85 @@
 
 module BABYLON {
-    //
+    /**
+     * Gather the list of clipboard event types as constants.
+     */
     export class ClipboardEventTypes {
+        /**
+         * T he clipboard event is fired when a copy command is active (pressed).
+         */
         public static readonly COPY = 0x01; //
-
+        /**
+         *  The clipboard event is fired when a cut command is active (pressed).
+         */
         public static readonly CUT = 0x02;
 
+        /**
+         * The clipboard event is fired when a paste command is active (pressed).
+         */
         public static readonly PASTE = 0x03;
     }
-
+    /**
+     * This class is used to store clipboard related info for the onClipboardObservable event.
+     */
     export class ClipboardInfo {
+        /**
+         * Instantiates a new ClipboardInfo info.
+         * @param {number} type Defines the type of event (BABYLON.ClipboardEventTypes)
+         * @param {ClipboardEvent} event Defines the related dom event
+        /**
+         *Creates an instance of ClipboardInfo.
+         * @param {number} type
+         * @param {ClipboardEvent} event
+         * @memberof ClipboardInfo
+         */
         constructor(
+            /**
+             * Defines the type of event (BABYLON.ClipboardEventTypes)
+             */
             public type: number,
+            /**
+             * Defines the related dom event
+             */
             public event: ClipboardEvent) {
-
+                /**
+                 *  initialize the clipboard data
+                */
+                this._clipboardData = new DataTransfer();
+        }
+        /**
+         * Stores the clipboard data
+         * @type {DataTransfer}
+         */
+        private _clipboardData: DataTransfer;
+        /**
+         * Getter clipboardData
+         * @return {DataTransfer}
+         */
+        public get clipboardData(): DataTransfer {
+            return this._clipboardData;
+        }
+        /**
+         * Setter clipboardData
+         * @param {DataTransfer} value
+         */
+        public set clipboardData(value: DataTransfer) {
+            this._clipboardData = value;
         }
-    }
-
-    export class ClipboardInfoPre extends ClipboardInfo {
-
-        public skipOnPointerObservables: boolean;
 
-        constructor(
-            public type: number,
-            public event: ClipboardEvent) {
-                super(type, event);
-                this.skipOnPointerObservables = true;
+        /**
+         * This method is used to get the clipboard event type from the event.key
+         * @param {KeyboardEvent} e  triggered keyboard event
+         * @returns {number} clipboard event type (BABYLON.ClipboardEventTypes)
+         */
+        public static GetTypeFromCharacter(e: KeyboardEvent): number {
+            let charCode = (typeof e.which == "number") ? e.which : e.keyCode;
+            //TODO: add codes for extended ASCII
+            switch (charCode){
+                case 67: return ClipboardEventTypes.COPY;
+                case 86: return ClipboardEventTypes.PASTE;
+                case 88: return ClipboardEventTypes.CUT;
+                default: return -1;
             }
-            public static getTypeFromCharacter(char: string): number {
-                switch (char.charCodeAt(0)){
-                    case 63: return ClipboardEventTypes.COPY;
-                    case 76: return ClipboardEventTypes.PASTE;
-                    case 78: return ClipboardEventTypes.CUT;
-                    default: return -1;
-                }
-            }
-
+        }
     }
 }